Added GLFW_WAYLAND_ZWLR_KEYBOARD_ON_FOCUS

This commit is contained in:
anon3989 2025-09-11 18:41:26 +00:00
parent e5ce6c1be0
commit b8b08ed2f9
7 changed files with 167 additions and 81 deletions

View File

@ -527,6 +527,12 @@ If success, you can control layer behavior with
[<GLFW/glfw3native.h>](@ref glfwWaylandZwlrSetLayer) api. [<GLFW/glfw3native.h>](@ref glfwWaylandZwlrSetLayer) api.
Example available [here](https://github.com/glfw/glfw/blob/master/examples/wayland-widget.c). Example available [here](https://github.com/glfw/glfw/blob/master/examples/wayland-widget.c).
@anchor GLFW_WAYLAND_ZWLR_KEYBOARD_ON_FOCUS_hint
__GLFW_WAYLAND_ZWLR_KEYBOARD_ON_FOCUS__ By default, layer shell surfaces do not receive keyboard
events. Set this flag to automatically redirect focus to app on hover, and release it when mouse
leave surface. This is set by @ref glfwWindowHint. Otherwise, you may control keyboard focus
with [<GLFW/glfw3native.h>](@ref glfwWaylandZwlrSetKeyboardFocus) api.
#### X11 specific window hints {#window_hints_x11} #### X11 specific window hints {#window_hints_x11}
@anchor GLFW_X11_CLASS_NAME_hint @anchor GLFW_X11_CLASS_NAME_hint
@ -540,7 +546,7 @@ These are set with @ref glfwWindowHintString.
#### Supported and default values {#window_hints_values} #### Supported and default values {#window_hints_values}
Window hint | Default value | Supported values Window hint | Default value | Supported values
----------------------------- | --------------------------- | ---------------- ---------------------------------- | --------------------------- | ----------------
GLFW_RESIZABLE | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` GLFW_RESIZABLE | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_VISIBLE | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` GLFW_VISIBLE | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_DECORATED | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` GLFW_DECORATED | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ -589,6 +595,7 @@ GLFW_X11_CLASS_NAME | `""` | An ASCII encoded `
GLFW_X11_INSTANCE_NAME | `""` | An ASCII encoded `WM_CLASS` instance name GLFW_X11_INSTANCE_NAME | `""` | An ASCII encoded `WM_CLASS` instance name
GLFW_WAYLAND_APP_ID | `""` | An ASCII encoded Wayland `app_id` name GLFW_WAYLAND_APP_ID | `""` | An ASCII encoded Wayland `app_id` name
GLFW_WAYLAND_USE_ZWLR | 0 | `GLFW_WAYLAND_ZWLR_LAYER_BACKGROUD`, `GLFW_WAYLAND_ZWLR_LAYER_BOTTOM`, `GLFW_WAYLAND_ZWLR_LAYER_TOP` or `GLFW_WAYLAND_ZWLR_LAYER_OVERLAY` GLFW_WAYLAND_USE_ZWLR | 0 | `GLFW_WAYLAND_ZWLR_LAYER_BACKGROUD`, `GLFW_WAYLAND_ZWLR_LAYER_BOTTOM`, `GLFW_WAYLAND_ZWLR_LAYER_TOP` or `GLFW_WAYLAND_ZWLR_LAYER_OVERLAY`
GLFW_WAYLAND_ZWLR_KEYBOARD_ON_FOCUS| `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
## Window event processing {#window_events} ## Window event processing {#window_events}

View File

@ -26,7 +26,7 @@
#define WIN_HEIGHT 150 static unsigned char LastCharPressed = 0;
void nk_process(GLFWwindow*, struct nk_context*, float, float); void nk_process(GLFWwindow*, struct nk_context*, float, float);
@ -38,7 +38,7 @@ static void GLFW_DebugCallback(int err_code, const char* description)
} }
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{ printf("Captured %i\n", key); } { if (action == GLFW_PRESS) LastCharPressed = key; }
@ -48,14 +48,12 @@ int main(int argc, char** argv)
if (!glfwInit()) return 1; if (!glfwInit()) return 1;
//glfwWindowHint(GLFW_WAYLAND_ZWLR_KEYBOARD_ON_FOCUS, GLFW_TRUE); // no need to call glfwWaylandSetKeyboardFocus manually
glfwWindowHint(GLFW_WAYLAND_USE_ZWLR, GLFW_WAYLAND_ZWLR_LAYER_TOP); glfwWindowHint(GLFW_WAYLAND_USE_ZWLR, GLFW_WAYLAND_ZWLR_LAYER_TOP);
GLFWwindow* window = glfwCreateWindow(600, 400, "Don't Care", NULL, NULL); GLFWwindow* window = glfwCreateWindow(600, 400, "Don't Care", NULL, NULL);
if (!window) return 1; if (!window) return 1;
//glfwWaylandZwlrSetExclusiveZone(window, WIN_HEIGHT + 50); // try to play with
//glfwWaylandZwlrSetMargin(window, 10, 10, 10, 10);
glfwMakeContextCurrent(window); glfwMakeContextCurrent(window);
glfwSetKeyCallback (window, key_callback); glfwSetKeyCallback (window, key_callback);
gladLoadGL (glfwGetProcAddress); gladLoadGL (glfwGetProcAddress);
@ -111,9 +109,17 @@ void nk_process(GLFWwindow* window, struct nk_context* ctx, float width, float h
glfwSetWindowShouldClose(window, GLFW_TRUE); glfwSetWindowShouldClose(window, GLFW_TRUE);
} }
nk_layout_row_dynamic(ctx, (height / 3), 1); nk_layout_row_dynamic(ctx, (height / 4), 1);
nk_layout_row_dynamic(ctx, 30, 2); nk_layout_row_dynamic(ctx, 30, 1);
{
static char inputBuff[64];
sprintf(inputBuff, "Mouse focus: %b | Char received: %i",
glfwGetWindowAttrib(window, GLFW_FOCUSED), LastCharPressed);
nk_label(ctx, inputBuff, NK_TEXT_CENTERED);
}
nk_layout_row_dynamic(ctx, 30, 2);
{ {
static char exclusiveBuff[12]; static char exclusiveBuff[12];
@ -192,6 +198,16 @@ void nk_process(GLFWwindow* window, struct nk_context* ctx, float width, float h
nk_combo_end(ctx); nk_combo_end(ctx);
} }
} }
nk_layout_row_dynamic(ctx, 30, 2);
{
if (nk_button_label(ctx, "Request keybord focus"))
glfwWaylandZwlrSetKeyboardFocus(window, GLFW_TRUE);
if (nk_button_label(ctx, "Release keybord focus"))
glfwWaylandZwlrSetKeyboardFocus(window, GLFW_FALSE);
}
} }

View File

@ -1136,15 +1136,6 @@ extern "C" {
*/ */
#define GLFW_WAYLAND_APP_ID 0x00026001 #define GLFW_WAYLAND_APP_ID 0x00026001
#define GLFW_WAYLAND_ZWLR_LAYER_BACKGROUND 0x00026002
#define GLFW_WAYLAND_ZWLR_LAYER_BOTTOM 0x00026003
#define GLFW_WAYLAND_ZWLR_LAYER_TOP 0x00026004
#define GLFW_WAYLAND_ZWLR_LAYER_OVERLAY 0x00026005
#define GLFW_WAYLAND_ZWLR_ANCHOR_TOP 0x1
#define GLFW_WAYLAND_ZWLR_ANCHOR_BOTTOM 0x2
#define GLFW_WAYLAND_ZWLR_ANCHOR_LEFT 0x4
#define GLFW_WAYLAND_ZWLR_ANCHOR_RIGHT 0x8
/*! @brief Wayland specific /*! @brief Wayland specific
* [window hint](@ref GLFW_WAYLAND_USE_ZWLR_hint). * [window hint](@ref GLFW_WAYLAND_USE_ZWLR_hint).
* *
@ -1156,7 +1147,25 @@ extern "C" {
*/ */
#define GLFW_WAYLAND_USE_ZWLR 0x00026010 #define GLFW_WAYLAND_USE_ZWLR 0x00026010
/*! @} */ #define GLFW_WAYLAND_ZWLR_LAYER_BACKGROUND 0x00026011
#define GLFW_WAYLAND_ZWLR_LAYER_BOTTOM 0x00026012
#define GLFW_WAYLAND_ZWLR_LAYER_TOP 0x00026013
#define GLFW_WAYLAND_ZWLR_LAYER_OVERLAY 0x00026014
#define GLFW_WAYLAND_ZWLR_ANCHOR_TOP 0x1
#define GLFW_WAYLAND_ZWLR_ANCHOR_BOTTOM 0x2
#define GLFW_WAYLAND_ZWLR_ANCHOR_LEFT 0x4
#define GLFW_WAYLAND_ZWLR_ANCHOR_RIGHT 0x8
/*! @brief Wayland specific
* [window hint](@ref GLFW_WAYLAND_ZWLR_KEYBOARD_ON_FOCUS).
*
* By default, layer shell surfaces do not receive keyboard events.
* Set this flag to automatically redirect focus to app on hover,
* and release it when mouse leave surface.
*/
#define GLFW_WAYLAND_ZWLR_KEYBOARD_ON_FOCUS 0x00026015
#define GLFW_NO_API 0 #define GLFW_NO_API 0
#define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_API 0x00030001

View File

@ -629,6 +629,23 @@ GLFWAPI void glfwWaylandZwlrSetExclusiveZone(GLFWwindow* window, int zone);
* @ingroup native * @ingroup native
*/ */
GLFWAPI void glfwWaylandZwlrSetMargin(GLFWwindow* window, int top, int right, int bottom, int left); GLFWAPI void glfwWaylandZwlrSetMargin(GLFWwindow* window, int top, int right, int bottom, int left);
/*! @brief Request or release keyboard focus from compositor.
*
* @warning Create fallback mechanism to release focus before request one.
* Standart window events are not processed by GLFW in ZWLR mode,
* you will not be able to interact with your compositor after focus granted.
*
* @errors Possible errors include @ref GLFW_FEATURE_UNAVAILABLE and @ref
* GLFW_PLATFORM_UNAVAILABLE.
*
* @thread_safety This function should be called from main thread.
*
* @since Added in version 3.5.
*
* @ingroup native
*/
GLFWAPI void glfwWaylandZwlrSetKeyboardFocus(GLFWwindow* window, int focus);
#endif #endif
#if defined(GLFW_EXPOSE_NATIVE_EGL) #if defined(GLFW_EXPOSE_NATIVE_EGL)

View File

@ -428,6 +428,7 @@ struct _GLFWwndconfig
struct { struct {
char appId[256]; char appId[256];
GLFWbool useZWLR; GLFWbool useZWLR;
GLFWbool zwlrKeyboardGrabOnFocus;
} wl; } wl;
}; };

View File

@ -384,6 +384,9 @@ GLFWAPI void glfwWindowHint(int hint, int value)
case GLFW_WAYLAND_USE_ZWLR: case GLFW_WAYLAND_USE_ZWLR:
_glfw.hints.window.wl.useZWLR = value; _glfw.hints.window.wl.useZWLR = value;
return; return;
case GLFW_WAYLAND_ZWLR_KEYBOARD_ON_FOCUS:
_glfw.hints.window.wl.zwlrKeyboardGrabOnFocus = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_SCALE_TO_MONITOR: case GLFW_SCALE_TO_MONITOR:
_glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE;
return; return;

View File

@ -1167,7 +1167,7 @@ static bool createZwlrShellObjects(_GLFWwindow* window)
if (!_glfw.wl.zwlrLayerShell) if (!_glfw.wl.zwlrLayerShell)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: zwlr protocol not supported on this system"); "Wayland: ZWLR protocol not supported on this system");
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -1618,6 +1618,8 @@ static void pointerHandleEnter(void* userData,
_glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY); _glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY);
} }
if (_glfw.hints.window.wl.zwlrKeyboardGrabOnFocus)
{
if (window->wl.zwlr.surface) if (window->wl.zwlr.surface)
{ {
// mf don't receive keyboard events by default // mf don't receive keyboard events by default
@ -1625,6 +1627,7 @@ static void pointerHandleEnter(void* userData,
ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND); ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND);
} }
} }
}
else else
{ {
if (window->wl.fallback.decorations) if (window->wl.fallback.decorations)
@ -1653,11 +1656,14 @@ static void pointerHandleLeave(void* userData,
_glfw.wl.serial = serial; _glfw.wl.serial = serial;
_glfw.wl.pointerFocus = NULL; _glfw.wl.pointerFocus = NULL;
if (_glfw.hints.window.wl.zwlrKeyboardGrabOnFocus)
{
if (window->wl.zwlr.surface) // TODO: find out why wl.hovered not fired if (window->wl.zwlr.surface) // TODO: find out why wl.hovered not fired
{ {
zwlr_layer_surface_v1_set_keyboard_interactivity(window->wl.zwlr.surface, zwlr_layer_surface_v1_set_keyboard_interactivity(window->wl.zwlr.surface,
ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE); ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE);
} }
}
if (window->wl.hovered) if (window->wl.hovered)
{ {
@ -3460,7 +3466,7 @@ GLFWAPI void glfwWaylandZwlrSetLayer(GLFWwindow* handle, int layer)
if (!(window->wl.zwlr.surface)) if (!(window->wl.zwlr.surface))
{ {
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
"Wayland: zwlr not supported or wasn't requested"); "Wayland: ZWLR not supported or wasn't requested");
return; return;
} }
@ -3474,7 +3480,7 @@ GLFWAPI void glfwWaylandZwlrSetLayer(GLFWwindow* handle, int layer)
default: default:
{ {
_glfwInputError(GLFW_INVALID_ENUM, _glfwInputError(GLFW_INVALID_ENUM,
"Wayland: invalid zwlr layer received"); "Wayland: invalid ZWLR layer received");
return; return;
} }
} }
@ -3500,7 +3506,7 @@ GLFWAPI void glfwWaylandZwlrSetAnchor(GLFWwindow* handle, int anchor)
if (!(window->wl.zwlr.surface)) if (!(window->wl.zwlr.surface))
{ {
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
"Wayland: zwlr not supported or wasn't requested"); "Wayland: ZWLR not supported or wasn't requested");
return; return;
} }
@ -3522,7 +3528,7 @@ GLFWAPI void glfwWaylandZwlrSetExclusiveZone(GLFWwindow* handle, int zone)
if (!(window->wl.zwlr.surface)) if (!(window->wl.zwlr.surface))
{ {
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
"Wayland: zwlr not supported or wasn't requested"); "Wayland: ZWLR not supported or wasn't requested");
return; return;
} }
@ -3544,12 +3550,39 @@ GLFWAPI void glfwWaylandZwlrSetMargin(GLFWwindow* handle, int top, int right, in
if (!(window->wl.zwlr.surface)) if (!(window->wl.zwlr.surface))
{ {
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
"Wayland: zwlr not supported or wasn't requested"); "Wayland: ZWLR not supported or wasn't requested");
return; return;
} }
zwlr_layer_surface_v1_set_margin(window->wl.zwlr.surface, top, right, bottom, left); zwlr_layer_surface_v1_set_margin(window->wl.zwlr.surface, top, right, bottom, left);
} }
GLFWAPI void glfwWaylandZwlrSetKeyboardFocus(GLFWwindow* handle, int focus)
{
_GLFW_REQUIRE_INIT();
if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND)
{
_glfwInputError(GLFW_PLATFORM_UNAVAILABLE,
"Wayland: Platform not initialized");
return;
}
_GLFWwindow* window = (_GLFWwindow*) handle;
if (!(window->wl.zwlr.surface))
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
"Wayland: ZWLR not supported or wasn't requested");
return;
}
int flag;
if (focus) flag = ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE;
else flag = ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE;
zwlr_layer_surface_v1_set_keyboard_interactivity(window->wl.zwlr.surface, flag);
}
#endif // _GLFW_WAYLAND #endif // _GLFW_WAYLAND