diff options
author | Tiago Vignatti <tiago.vignatti@intel.com> | 2012-06-06 14:29:02 +0300 |
---|---|---|
committer | Tiago Vignatti <tiago.vignatti@intel.com> | 2012-06-11 20:33:36 +0300 |
commit | eb1804fb5afb85fa345310283070e6ae167e1caf (patch) | |
tree | 0520799c7524ddcb7cda18e6a1d499370dc32c12 | |
parent | 9ee1403b44fe72e261e8cd16cc53656308ba0676 (diff) |
xwm: fix implementation of focus assistance
ICCCM 4.1.7 and 4.2.7.
Signed-off-by: Tiago Vignatti <tiago.vignatti@intel.com>
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/xwayland/window-manager.c | 55 |
2 files changed, 54 insertions, 3 deletions
diff --git a/configure.ac b/configure.ac index 7dbd9f9..9e7bed3 100644 --- a/configure.ac +++ b/configure.ac @@ -42,7 +42,7 @@ AC_ARG_ENABLE(xwayland, [ --enable-xwayland],, enable_xwayland=yes) AM_CONDITIONAL(ENABLE_XWAYLAND, test x$enable_xwayland = xyes) if test x$enable_xwayland = xyes; then - PKG_CHECK_MODULES([XWAYLAND], xcb xcb-xfixes cairo-xcb) + PKG_CHECK_MODULES([XWAYLAND], xcb xcb-icccm xcb-xfixes cairo-xcb) AC_DEFINE([BUILD_XWAYLAND], [1], [Build the X server launcher]) AC_ARG_WITH(xserver-path, AS_HELP_STRING([--with-xserver-path=PATH], diff --git a/src/xwayland/window-manager.c b/src/xwayland/window-manager.c index 0831bef..04d0c30 100644 --- a/src/xwayland/window-manager.c +++ b/src/xwayland/window-manager.c @@ -33,6 +33,7 @@ #include <signal.h> #include "xwayland.h" +#include <xcb/xcb_icccm.h> #include "../../shared/cairo-util.h" #include "../compositor.h" @@ -89,7 +90,10 @@ struct motif_wm_hints { #define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */ #define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */ - +/* WM_PROTOCOLS property, ICCCM 4.1.2.7 */ +#define ICCCM_WM_TAKE_FOCUS (1L << 1) +#define ICCCM_WM_SAVE_YOURSELF (1L << 2) +#define ICCCM_WM_DELETE_WINDOW (1L << 3) struct weston_wm_window { struct weston_wm *wm; @@ -209,6 +213,20 @@ read_and_dump_property(struct weston_wm *wm, free(reply); } +static void +handle_wm_protocols(struct weston_wm_window *window, + xcb_get_property_reply_t *reply) +{ + xcb_icccm_get_wm_protocols_reply_t protocols; + struct weston_wm *wm = window->wm; + uint32_t i; + + xcb_icccm_get_wm_protocols_from_reply(reply, &protocols); + for (i = 0; i < protocols.atoms_len; i++) + if (protocols.atoms[i] == wm->atom.wm_take_focus) + window->protocols = ICCCM_WM_TAKE_FOCUS; +} + /* We reuse some predefined, but otherwise useles atoms */ #define TYPE_WM_PROTOCOLS XCB_ATOM_CUT_BUFFER0 #define TYPE_MOTIF_WM_HINTS XCB_ATOM_CUT_BUFFER1 @@ -227,7 +245,7 @@ weston_wm_window_read_properties(struct weston_wm_window *window) { XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, F(class) }, { XCB_ATOM_WM_NAME, XCB_ATOM_STRING, F(name) }, { XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, F(transient_for) }, - { wm->atom.wm_protocols, TYPE_WM_PROTOCOLS, F(protocols) }, + { wm->atom.wm_protocols, TYPE_WM_PROTOCOLS, 0 }, { wm->atom.net_wm_window_type, XCB_ATOM_ATOM, F(type) }, { wm->atom.net_wm_name, XCB_ATOM_STRING, F(name) }, { wm->atom.motif_wm_hints, TYPE_MOTIF_WM_HINTS, 0 }, @@ -287,6 +305,7 @@ weston_wm_window_read_properties(struct weston_wm_window *window) *(xcb_atom_t *) p = *atom; break; case TYPE_WM_PROTOCOLS: + handle_wm_protocols(window, reply); break; case TYPE_MOTIF_WM_HINTS: hints = xcb_get_property_value(reply); @@ -406,6 +425,34 @@ weston_wm_handle_configure_notify(struct weston_wm *wm, xcb_generic_event_t *eve window->y = configure_notify->y - y; } +/* + * Follows up ICCCM 4.1.7. The function returns 1 when WM assistance is needed + * and 0 otherwise. + */ +static int +weston_wm_focus_assistance(struct weston_wm_window *window) +{ + struct weston_wm *wm = window->wm; + int is_needed = 0; + + /* the order here is important */ + if (window->type == wm->atom.net_wm_window_type_normal || + window->type == wm->atom.net_wm_window_type_dialog) + is_needed = 1; + + /* special rule for google-chrome "utility" window that in + * fact has not the type "utility" but "normal" */ + if (window->type == wm->atom.net_wm_window_type_normal && + window->override_redirect) + is_needed = 0; + + /* if WM_TAKE_FOCUS is absent, we assume WM help is needed. */ + if (!(window->protocols & ICCCM_WM_TAKE_FOCUS)) + is_needed = 1; + + return is_needed; +} + static void weston_wm_window_activate(struct wl_listener *listener, void *data) { @@ -416,6 +463,9 @@ weston_wm_window_activate(struct wl_listener *listener, void *data) xcb_client_message_event_t client_message; if (window) { + if (!weston_wm_focus_assistance(window)) + return; + client_message.response_type = XCB_CLIENT_MESSAGE; client_message.format = 32; client_message.window = window->id; @@ -761,6 +811,7 @@ weston_wm_window_create(struct weston_wm *wm, window->decorate = !window->override_redirect; window->width = width; window->height = height; + window->type = XCB_ATOM_NONE; hash_table_insert(wm->window_hash, id, window); } |