diff options
author | Samuel Thibault <[email protected]> | 2018-08-30 18:11:29 +0200 |
---|---|---|
committer | lukefromdc <[email protected]> | 2018-09-26 00:18:03 -0400 |
commit | f0f4c5e1217eefd46edf9f98633fb32967c67461 (patch) | |
tree | cf66d12ba747544370762d077417409a2064a01d /mate-panel/panel-util.c | |
parent | 4c30c52e4857da9d23e284aa75b12c8ab62e2ee4 (diff) | |
download | mate-panel-f0f4c5e1217eefd46edf9f98633fb32967c67461.tar.bz2 mate-panel-f0f4c5e1217eefd46edf9f98633fb32967c67461.tar.xz |
menu-bar: transfer focus correctly on alt-F1
The background is in https://gitlab.gnome.org/GNOME/gtk/issues/85 . One of
the conclusions, in https://gitlab.gnome.org/GNOME/gtk/issues/85#note_264804
, is that mate-panel needs to properly transfer focus on alt-F1 keyboard
shortcut.
It used to work only by luck before, only because gtk used to
deactivate itself during a keyboard grab. But as discussed in
https://gitlab.gnome.org/GNOME/gtk/issues/85 that behavior poses
accessibility feedback issues, is not coherent, and keyboard grab
feedback will not be available in wayland anyway. Thus @ebassi saying
in https://gitlab.gnome.org/GNOME/gtk/issues/85#note_264804 that not
transferring focus properly is the actual bug.
This change explictly switches to the menu bar after saving which X Window
had the focus, and on menu bar deactivation restores focus to that X Window.
Fixes #851
Diffstat (limited to 'mate-panel/panel-util.c')
-rw-r--r-- | mate-panel/panel-util.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/mate-panel/panel-util.c b/mate-panel/panel-util.c index 1106f034..6183cca8 100644 --- a/mate-panel/panel-util.c +++ b/mate-panel/panel-util.c @@ -23,11 +23,15 @@ #include <unistd.h> #include <sys/types.h> +#include <X11/Xlib.h> +#include <X11/Xatom.h> + #include <glib.h> #include <glib/gi18n.h> #include <glib/gstdio.h> #include <gio/gio.h> #include <gdk-pixbuf/gdk-pixbuf.h> +#include <gdk/gdkx.h> #define MATE_DESKTOP_USE_UNSTABLE_API #include <libmate-desktop/mate-desktop-utils.h> @@ -47,6 +51,8 @@ #include "panel-icon-names.h" #include "panel-lockdown.h" +static Atom _net_active_window = None; + char * panel_util_make_exec_uri_for_desktop (const char *exec) { @@ -1241,3 +1247,89 @@ panel_util_get_file_optional_homedir (const char *location) return file; } + +static void panel_menu_bar_get_net_active_window(Display *xdisplay) +{ + if (_net_active_window == None) + _net_active_window = XInternAtom (xdisplay, + "_NET_ACTIVE_WINDOW", + False); +} + +Window panel_util_get_current_active_window (GtkWidget *toplevel) +{ + GdkScreen *screen; + GdkDisplay *display; + GdkWindow *root; + Display *xdisplay; + Window xroot; + + Window res = None; + + Atom return_type; + int return_format; + unsigned long n; + unsigned long bytes; + unsigned char *prop = NULL; + + screen = gtk_window_get_screen (GTK_WINDOW(toplevel)); + display = gdk_screen_get_display (screen); + root = gdk_screen_get_root_window (screen); + + xdisplay = GDK_DISPLAY_XDISPLAY (display); + xroot = GDK_WINDOW_XID (root); + + panel_menu_bar_get_net_active_window (xdisplay); + if (_net_active_window != None + && XGetWindowProperty (xdisplay, xroot, _net_active_window, 0, 1, + False, XA_WINDOW, &return_type, &return_format, + &n, &bytes, &prop) == Success) + { + if ((return_type == XA_WINDOW) && (return_format == 32) && + (n == 1) && (prop)) { + res = *(Window *)prop; + } + + if (prop) + XFree (prop); + + } + return res; +} + +void panel_util_set_current_active_window (GtkWidget *toplevel, Window window) +{ + GdkScreen *screen; + GdkDisplay *display; + GdkWindow *root; + Display *xdisplay; + Window xroot; + XEvent xev; + + screen = gtk_window_get_screen (GTK_WINDOW(toplevel)); + display = gdk_screen_get_display (screen); + root = gdk_screen_get_root_window (screen); + + xdisplay = GDK_DISPLAY_XDISPLAY (display); + xroot = GDK_WINDOW_XID (root); + + panel_menu_bar_get_net_active_window (xdisplay); + if (_net_active_window == None) + return; + + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.window = window; + xev.xclient.message_type = _net_active_window; + xev.xclient.format = 32; + xev.xclient.data.l[0] = 2; /* requestor type; we're not an app */ + xev.xclient.data.l[1] = CurrentTime; + xev.xclient.data.l[2] = None; /* our currently active window */ + xev.xclient.data.l[3] = 0; + xev.xclient.data.l[4] = 0; + + XSendEvent (xdisplay, xroot, False, + SubstructureRedirectMask | SubstructureNotifyMask, + &xev); +} |