commit f39e4fa
Michael Forney
·
2014-08-05 06:54:47 +0000 UTC
parent 892ffcb
window: Add an unfocus method instead of using focus(NULL) This makes it easier for the xwm to keep track of the X11 focus, and allows us to deactivate the window in an xdg_shell_surface implementation.
3 files changed,
+33,
-12
+7,
-9
1@@ -74,18 +74,16 @@ void swc_window_focus(struct swc_window * base)
2 struct compositor_view * new_focus = window ? window->view : NULL,
3 * old_focus = swc.seat->keyboard->focus.view;
4
5- /* If the keyboard already has a focused window, and we are changing the
6- * focus to either NULL, or a window with a different implementation, set
7- * the focus of the previous focus window's implementation to NULL. */
8- if (old_focus && old_focus->window
9- && !(window && window->impl == INTERNAL(old_focus->window)->impl)
10- && old_focus->window->impl->focus)
11- {
12- old_focus->window->impl->focus(NULL);
13- }
14+ if (new_focus == old_focus)
15+ return;
16
17+ /* Focus the new window before unfocusing the old one in case both are X11
18+ * windows so the xwl_window implementation can handle this transition
19+ * correctly. */
20 if (window && window->impl->focus)
21 window->impl->focus(window);
22+ if (old_focus && old_focus->window && old_focus->window->impl->unfocus)
23+ old_focus->window->impl->unfocus(old_focus->window);
24
25 keyboard_set_focus(swc.seat->keyboard, new_focus);
26 }
+1,
-0
1@@ -60,6 +60,7 @@ struct window_impl
2 void (* configure)(struct window * window,
3 const struct swc_rectangle * geometry);
4 void (* focus)(struct window * window);
5+ void (* unfocus)(struct window * window);
6 };
7
8 extern struct wl_listener window_enter_listener;
+25,
-3
1@@ -62,6 +62,7 @@ static struct
2 xcb_ewmh_connection_t ewmh;
3 xcb_screen_t * screen;
4 xcb_window_t window;
5+ struct xwl_window * focus;
6 struct wl_event_source * source;
7 struct wl_list windows, unpaired_windows;
8 union
9@@ -145,16 +146,34 @@ static void focus(struct window * window)
10 {
11 struct xwl_window * xwl_window
12 = wl_container_of(window, xwl_window, window);
13- xcb_window_t id = window ? xwl_window->id : XCB_NONE;
14
15 xcb_set_input_focus(xwm.connection, XCB_INPUT_FOCUS_NONE,
16- id, XCB_CURRENT_TIME);
17+ xwl_window->id, XCB_CURRENT_TIME);
18 xcb_flush(xwm.connection);
19+ xwm.focus = xwl_window;
20+}
21+
22+static void unfocus(struct window * window)
23+{
24+ struct xwl_window * xwl_window
25+ = wl_container_of(window, xwl_window, window);
26+
27+ /* If the window we are unfocusing is the latest xwl_window to be focused,
28+ * we know we have transitioned to some other window type, so the X11 focus
29+ * can be set to XCB_NONE. Otherwise, we have transitioned to another X11
30+ * window, and the X11 focus has already been updated. */
31+ if (xwl_window == xwm.focus)
32+ {
33+ xcb_set_input_focus(xwm.connection, XCB_INPUT_FOCUS_NONE, XCB_NONE,
34+ XCB_CURRENT_TIME);
35+ xcb_flush(xwm.connection);
36+ }
37 }
38
39 static const struct window_impl xwl_window_handler = {
40 .configure = &configure,
41- .focus = &focus
42+ .focus = &focus,
43+ .unfocus = &unfocus,
44 };
45
46 static void handle_surface_destroy(struct wl_listener * listener, void * data)
47@@ -162,6 +181,9 @@ static void handle_surface_destroy(struct wl_listener * listener, void * data)
48 struct xwl_window * xwl_window
49 = wl_container_of(listener, xwl_window, surface_destroy_listener);
50
51+ if (xwm.focus == xwl_window)
52+ xwm.focus = NULL;
53+
54 window_finalize(&xwl_window->window);
55 wl_list_remove(&xwl_window->link);
56 wl_list_insert(&xwm.unpaired_windows, &xwl_window->link);