When we get a focus in event from an X window which is not the one
we last set as the active window, reset the focus.
---
 xwayland/window-manager.c | 44 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 11 deletions(-)

diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c
index 1e4abbb..e8f94f7 100644
--- a/xwayland/window-manager.c
+++ b/xwayland/window-manager.c
@@ -694,18 +694,11 @@ weston_wm_create_surface(struct wl_listener *listener, 
void *data)
 }
 
 static void
-weston_wm_window_activate(struct wl_listener *listener, void *data)
+weston_wm_send_focus_window(struct weston_wm *wm,
+                           struct weston_wm_window *window)
 {
-       struct weston_surface *surface = data;
-       struct weston_wm_window *window = NULL;
-       struct weston_wm *wm =
-               container_of(listener, struct weston_wm, activate_listener);
        xcb_client_message_event_t client_message;
 
-       if (surface) {
-               window = get_wm_window(surface);
-       }
-
        if (window) {
                if (window->override_redirect)
                        return;
@@ -717,7 +710,7 @@ weston_wm_window_activate(struct wl_listener *listener, 
void *data)
                client_message.data.data32[0] = wm->atom.wm_take_focus;
                client_message.data.data32[1] = XCB_TIME_CURRENT_TIME;
 
-               xcb_send_event(wm->conn, 0, window->id, 
+               xcb_send_event(wm->conn, 0, window->id,
                               XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
                               (char *) &client_message);
 
@@ -729,6 +722,21 @@ weston_wm_window_activate(struct wl_listener *listener, 
void *data)
                                     XCB_NONE,
                                     XCB_TIME_CURRENT_TIME);
        }
+}
+
+static void
+weston_wm_window_activate(struct wl_listener *listener, void *data)
+{
+       struct weston_surface *surface = data;
+       struct weston_wm_window *window = NULL;
+       struct weston_wm *wm =
+               container_of(listener, struct weston_wm, activate_listener);
+
+       if (surface) {
+               window = get_wm_window(surface);
+       }
+
+       weston_wm_send_focus_window(wm, window);
 
        if (wm->focus_window) {
                if (wm->focus_window->frame)
@@ -1139,7 +1147,8 @@ weston_wm_window_create(struct weston_wm *wm,
 
        geometry_cookie = xcb_get_geometry(wm->conn, id);
 
-       values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE;
+       values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE |
+                    XCB_EVENT_MASK_FOCUS_CHANGE;
        xcb_change_window_attributes(wm->conn, id, XCB_CW_EVENT_MASK, values);
 
        window->wm = wm;
@@ -1827,6 +1836,16 @@ weston_wm_handle_leave(struct weston_wm *wm, 
xcb_generic_event_t *event)
        weston_wm_window_set_cursor(wm, window->frame_id, XWM_CURSOR_LEFT_PTR);
 }
 
+static void
+weston_wm_handle_focus_in(struct weston_wm *wm, xcb_generic_event_t *event)
+{
+       xcb_focus_in_event_t *focus = (xcb_focus_in_event_t *) event;
+       /* Do not let X clients change the focus behind the compositor's
+        * back. Reset the focus to the old one if it changed. */
+       if (focus->event != (wm->focus_window ? wm->focus_window->id : 0))
+               weston_wm_send_focus_window(wm, wm->focus_window);
+}
+
 static int
 weston_wm_handle_event(int fd, uint32_t mask, void *data)
 {
@@ -1894,6 +1913,9 @@ weston_wm_handle_event(int fd, uint32_t mask, void *data)
                case XCB_CLIENT_MESSAGE:
                        weston_wm_handle_client_message(wm, event);
                        break;
+               case XCB_FOCUS_IN:
+                       weston_wm_handle_focus_in(wm, event);
+                       break;
                }
 
                free(event);
-- 
2.3.4

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to