]> git.mdlowis.com Git - proto/labwc.git/commitdiff
view: add view_wants_focus enum (NEVER/ALWAYS/OFFER) and function
authorJohn Lindgren <john@jlindgren.net>
Sun, 15 Oct 2023 05:11:12 +0000 (01:11 -0400)
committerJohan Malm <johanmalm@users.noreply.github.com>
Mon, 16 Oct 2023 19:28:18 +0000 (20:28 +0100)
This allows identifying XWayland views using the ICCCM "Globally Active"
input model. Later commits will improve handling of these views.

No functional change in this commit.

include/view.h
src/view.c
src/xwayland.c

index 0fb10a229985a507dbff0fbf458540d6225b327b..12b5d1093d7a62f57ac569aac3e758fac9618f01 100644 (file)
@@ -36,6 +36,21 @@ enum view_edge {
        VIEW_EDGE_CENTER,
 };
 
+enum view_wants_focus {
+       /* View does not want focus */
+       VIEW_WANTS_FOCUS_NEVER = 0,
+       /* View wants focus */
+       VIEW_WANTS_FOCUS_ALWAYS,
+       /*
+        * View should be offered focus and may accept or decline
+        * (a.k.a. ICCCM Globally Active input model). Labwc generally
+        * avoids focusing these views automatically (e.g. when another
+        * view on top is closed) but they may be focused by user action
+        * (e.g. mouse click).
+        */
+       VIEW_WANTS_FOCUS_OFFER,
+};
+
 struct view;
 struct wlr_surface;
 
@@ -72,8 +87,8 @@ struct view_impl {
        /* determines if view and surface are owned by the same process */
        bool (*is_related)(struct view *self, struct wlr_surface *surface);
        struct view_size_hints (*get_size_hints)(struct view *self);
-       /* if not implemented, view is assumed to want focus */
-       bool (*wants_focus)(struct view *self);
+       /* if not implemented, VIEW_WANTS_FOCUS_ALWAYS is assumed */
+       enum view_wants_focus (*wants_focus)(struct view *self);
 };
 
 struct view {
@@ -273,6 +288,8 @@ struct view *view_next(struct wl_list *head, struct view *view,
 void view_array_append(struct server *server, struct wl_array *views,
        enum lab_view_criteria criteria);
 
+enum view_wants_focus view_wants_focus(struct view *view);
+
 /**
  * view_is_focusable() - Check whether or not a view can be focused
  * @view: view to be checked
index 7a390d1148c1ec6759c2220374961eaba7978cee..dcca4bcdc08bde9e1e5f876c634531f10c4460e2 100644 (file)
@@ -143,6 +143,16 @@ view_array_append(struct server *server, struct wl_array *views,
        }
 }
 
+enum view_wants_focus
+view_wants_focus(struct view *view)
+{
+       assert(view);
+       if (view->impl->wants_focus) {
+               return view->impl->wants_focus(view);
+       }
+       return VIEW_WANTS_FOCUS_ALWAYS;
+}
+
 bool
 view_is_focusable(struct view *view)
 {
@@ -150,7 +160,7 @@ view_is_focusable(struct view *view)
        if (!view->surface) {
                return false;
        }
-       if (view->impl->wants_focus && !view->impl->wants_focus(view)) {
+       if (view_wants_focus(view) != VIEW_WANTS_FOCUS_ALWAYS) {
                return false;
        }
        return (view->mapped || view->minimized);
index e2c74fb135498bdef079c81c2917e032200f91f9..a8109bfec528f8e546522331495fcf99ce86a312 100644 (file)
@@ -30,29 +30,61 @@ xwayland_view_get_size_hints(struct view *view)
        };
 }
 
-static bool
+static enum view_wants_focus
 xwayland_view_wants_focus(struct view *view)
 {
-       xcb_icccm_wm_hints_t *hints = xwayland_surface_from_view(view)->hints;
-       if (!hints) {
-               return true;
-       }
+       struct wlr_xwayland_surface *xsurface =
+               xwayland_surface_from_view(view);
+
+       switch (wlr_xwayland_icccm_input_model(xsurface)) {
        /*
-        * Paraphrased from ICCCM section 4.1.7 (Input Focus):
+        * Abbreviated from ICCCM section 4.1.7 (Input Focus):
         *
-        * Clients set the input field of WM_HINTS to True to indicate
-        * that they require window manager assistance in acquiring the
-        * input focus. Clients set the input field to False to request
-        * that the window manager not set the input focus to their
-        * top-level window.
+        * Passive Input - The client expects keyboard input but never
+        * explicitly sets the input focus.
+        * Locally Active Input - The client expects keyboard input and
+        * explicitly sets the input focus, but it only does so when one
+        * of its windows already has the focus.
         *
-        * Clients that use XSetInputFocus() to explicitly set the input
-        * focus should set the WM_TAKE_FOCUS atom in WM_PROTOCOLS.
-        * Currently, labwc does not support this method of taking focus
-        * and thus ignores WM_TAKE_FOCUS. These views can still be
-        * focused by explicit user action (e.g. clicking in them).
+        * Passive and Locally Active clients set the input field of
+        * WM_HINTS to True, which indicates that they require window
+        * manager assistance in acquiring the input focus.
         */
-       return (bool)hints->input;
+       case WLR_ICCCM_INPUT_MODEL_PASSIVE:
+       case WLR_ICCCM_INPUT_MODEL_LOCAL:
+               return VIEW_WANTS_FOCUS_ALWAYS;
+
+       /*
+        * Globally Active Input - The client expects keyboard input and
+        * explicitly sets the input focus, even when it is in windows
+        * the client does not own. ... It wants to prevent the window
+        * manager from setting the input focus to any of its windows
+        * [because it may or may not want focus].
+        *
+        * Globally Active client windows may receive a WM_TAKE_FOCUS
+        * message from the window manager. If they want the focus, they
+        * should respond with a SetInputFocus request.
+        *
+        * [Currently, labwc does not fully support clients voluntarily
+        * taking focus via the WM_TAKE_FOCUS + SetInputFocus mechanism
+        * and avoids automatically focusing Globally Active windows.
+        * This may change in future.]
+        */
+       case WLR_ICCCM_INPUT_MODEL_GLOBAL:
+               return VIEW_WANTS_FOCUS_OFFER;
+
+       /*
+        * No Input - The client never expects keyboard input.
+        *
+        * No Input and Globally Active clients set the input field to
+        * False, which requests that the window manager not set the
+        * input focus to their top-level window.
+        */
+       case WLR_ICCCM_INPUT_MODEL_NONE:
+               break;
+       }
+
+       return VIEW_WANTS_FOCUS_NEVER;
 }
 
 static struct wlr_xwayland_surface *