Compare commits

...

5 Commits

Author SHA1 Message Date
chrysante
825409841e
Merge f07c466a20 into 7ef6efeb66 2025-08-19 11:14:09 +08:00
Camilla Löwy
7ef6efeb66 Wayland: Fix cursor position after a modal
If a modal surface like the window menu was active, clicking on the GLFW
window content area to close it would correctly emit the cursor enter
event but would not propagate the cursor position from the event.
2025-08-18 20:58:12 +02:00
Camilla Löwy
3cf9f6726d Wayland: Fix fallback decoration cursor updating
When a click through to the fallback decorations caused the end of
a modal like the window menu, the cursor shape would not be updated
until the next time the cursor moved.

This commit adds an update of the cursor for the pointer enter event for
fallback decoration surfaces, in addition to the updates at pointer
motion events.
2025-08-18 18:06:46 +02:00
Camilla Löwy
bfa1c424e5 Wayland: Fix fallback decoration menu placement
The fallback decorations would place the menu at the wrong position, by
not translating the last decoration surface position into toplevel
surface coordinates.

This also limits the menu to the caption area of the top decoration
surface, similar to how other toolkits work.
2025-08-18 18:06:46 +02:00
chrysante
f07c466a20 Added ability to override canBecomeKeyWindow and canBecomeMainWindow in Cocoa backend 2024-04-20 22:46:00 +02:00
6 changed files with 69 additions and 10 deletions

View File

@ -139,6 +139,11 @@ information on what to include when reporting a bug.
fallback decorations fallback decorations
- [Wayland] Bugfix: Fallback decorations would report scroll events - [Wayland] Bugfix: Fallback decorations would report scroll events
- [Wayland] Bugfix: Keyboard repeat events halted when any key is released (#2568) - [Wayland] Bugfix: Keyboard repeat events halted when any key is released (#2568)
- [Wayland] Bugfix: Fallback decorations would show menu at wrong position
- [Wayland] Bugfix: The cursor was not updated when clicking through from
a modal to a fallback decoration
- [Wayland] Bugfix: The cursor position was not updated when clicking through
from a modal to the content area
- [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631) - [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631)
- [Null] Added Vulkan 'window' surface creation via `VK_EXT_headless_surface` - [Null] Added Vulkan 'window' surface creation via `VK_EXT_headless_surface`
- [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless` - [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless`

View File

@ -929,6 +929,18 @@ extern "C" {
*/ */
#define GLFW_MOUSE_PASSTHROUGH 0x0002000D #define GLFW_MOUSE_PASSTHROUGH 0x0002000D
/*! @brief Window can become the main window
*
* Only honored with Cocoa backend
*/
#define GLFW_CAN_BECOME_MAIN 0x00020010
/*! @brief Window can receive key inputs
*
* Only honored with Cocoa backend
*/
#define GLFW_CAN_BECOME_KEY 0x00020011
/*! @brief Initial position x-coordinate window hint. /*! @brief Initial position x-coordinate window hint.
* *
* Initial position x-coordinate [window hint](@ref GLFW_POSITION_X). * Initial position x-coordinate [window hint](@ref GLFW_POSITION_X).

View File

@ -752,19 +752,19 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
//------------------------------------------------------------------------ //------------------------------------------------------------------------
@interface GLFWWindow : NSWindow {} @interface GLFWWindow : NSWindow {}
@property _GLFWwindow* glfwWindow;
@end @end
@implementation GLFWWindow @implementation GLFWWindow
- (BOOL)canBecomeKeyWindow - (BOOL)canBecomeKeyWindow
{ {
// Required for NSWindowStyleMaskBorderless windows return self.glfwWindow->canBecomeKey;
return YES;
} }
- (BOOL)canBecomeMainWindow - (BOOL)canBecomeMainWindow
{ {
return YES; return self.glfwWindow->canBecomeMain;
} }
@end @end
@ -835,6 +835,8 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
((GLFWWindow*)window->ns.object).glfwWindow = window;
if (window->monitor) if (window->monitor)
[window->ns.object setLevel:NSMainMenuWindowLevel + 1]; [window->ns.object setLevel:NSMainMenuWindowLevel + 1];
else else

View File

@ -413,6 +413,8 @@ struct _GLFWwndconfig
GLFWbool centerCursor; GLFWbool centerCursor;
GLFWbool focusOnShow; GLFWbool focusOnShow;
GLFWbool mousePassthrough; GLFWbool mousePassthrough;
GLFWbool canBecomeMain;
GLFWbool canBecomeKey;
GLFWbool scaleToMonitor; GLFWbool scaleToMonitor;
GLFWbool scaleFramebuffer; GLFWbool scaleFramebuffer;
struct { struct {
@ -538,6 +540,8 @@ struct _GLFWwindow
GLFWbool floating; GLFWbool floating;
GLFWbool focusOnShow; GLFWbool focusOnShow;
GLFWbool mousePassthrough; GLFWbool mousePassthrough;
GLFWbool canBecomeMain;
GLFWbool canBecomeKey;
GLFWbool shouldClose; GLFWbool shouldClose;
void* userPointer; void* userPointer;
GLFWbool doublebuffer; GLFWbool doublebuffer;

View File

@ -232,6 +232,8 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
window->floating = wndconfig.floating; window->floating = wndconfig.floating;
window->focusOnShow = wndconfig.focusOnShow; window->focusOnShow = wndconfig.focusOnShow;
window->mousePassthrough = wndconfig.mousePassthrough; window->mousePassthrough = wndconfig.mousePassthrough;
window->canBecomeMain = wndconfig.canBecomeMain;
window->canBecomeKey = wndconfig.canBecomeKey;
window->cursorMode = GLFW_CURSOR_NORMAL; window->cursorMode = GLFW_CURSOR_NORMAL;
window->doublebuffer = fbconfig.doublebuffer; window->doublebuffer = fbconfig.doublebuffer;
@ -398,6 +400,12 @@ GLFWAPI void glfwWindowHint(int hint, int value)
case GLFW_MOUSE_PASSTHROUGH: case GLFW_MOUSE_PASSTHROUGH:
_glfw.hints.window.mousePassthrough = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.mousePassthrough = value ? GLFW_TRUE : GLFW_FALSE;
return; return;
case GLFW_CAN_BECOME_MAIN:
_glfw.hints.window.canBecomeMain = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_CAN_BECOME_KEY:
_glfw.hints.window.canBecomeKey = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_CLIENT_API: case GLFW_CLIENT_API:
_glfw.hints.context.client = value; _glfw.hints.context.client = value;
return; return;
@ -900,6 +908,10 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
return window->focusOnShow; return window->focusOnShow;
case GLFW_MOUSE_PASSTHROUGH: case GLFW_MOUSE_PASSTHROUGH:
return window->mousePassthrough; return window->mousePassthrough;
case GLFW_CAN_BECOME_MAIN:
return window->canBecomeMain;
case GLFW_CAN_BECOME_KEY:
return window->canBecomeKey;
case GLFW_TRANSPARENT_FRAMEBUFFER: case GLFW_TRANSPARENT_FRAMEBUFFER:
return _glfw.platform.framebufferTransparent(window); return _glfw.platform.framebufferTransparent(window);
case GLFW_RESIZABLE: case GLFW_RESIZABLE:
@ -981,6 +993,14 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
window->mousePassthrough = value; window->mousePassthrough = value;
_glfw.platform.setWindowMousePassthrough(window, value); _glfw.platform.setWindowMousePassthrough(window, value);
return; return;
case GLFW_CAN_BECOME_MAIN:
window->canBecomeMain = value;
return;
case GLFW_CAN_BECOME_KEY:
window->canBecomeKey = value;
return;
} }
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib); _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);

View File

@ -405,13 +405,19 @@ static void handleFallbackDecorationButton(_GLFWwindow* window,
} }
else if (button == BTN_RIGHT) else if (button == BTN_RIGHT)
{ {
if (window->wl.xdg.toplevel) if (!window->wl.xdg.toplevel)
{ return;
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
_glfw.wl.seat, serial, if (window->wl.fallback.focus != window->wl.fallback.top.surface)
window->wl.cursorPosX, return;
window->wl.cursorPosY);
} if (ypos < GLFW_BORDER_SIZE)
return;
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
_glfw.wl.seat, serial,
xpos,
ypos - GLFW_CAPTION_HEIGHT - GLFW_BORDER_SIZE);
} }
} }
@ -1532,11 +1538,21 @@ static void pointerHandleEnter(void* userData,
window->wl.hovered = GLFW_TRUE; window->wl.hovered = GLFW_TRUE;
_glfwSetCursorWayland(window, window->wl.currentCursor); _glfwSetCursorWayland(window, window->wl.currentCursor);
_glfwInputCursorEnter(window, GLFW_TRUE); _glfwInputCursorEnter(window, GLFW_TRUE);
if (window->cursorMode != GLFW_CURSOR_DISABLED)
{
window->wl.cursorPosX = wl_fixed_to_double(sx);
window->wl.cursorPosY = wl_fixed_to_double(sy);
_glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY);
}
} }
else else
{ {
if (window->wl.fallback.decorations) if (window->wl.fallback.decorations)
{
window->wl.fallback.focus = surface; window->wl.fallback.focus = surface;
updateFallbackDecorationCursor(window, sx, sy);
}
} }
} }