How should I investigate it?
The current workaround is to close the second window and launch the third
window by the program but not XI shortcut key.
Thanks,
Fujiwara
---------
// gcc -o a a.c `pkg-config --cflags --libs gtk+-3.0 x11 xi`
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <X11/extensions/XInput2.h>
#include <string.h>
guint shortcut_keysym = 0;
guint shortcut_modifiers = 0;
static void
loop_quit (GtkWindow *window,
gpointer data)
{
GMainLoop *loop = data;
g_return_if_fail (loop != NULL);
gtk_widget_hide (GTK_WIDGET (window));
while (gtk_events_pending ()) {
gtk_main_iteration ();
}
g_main_loop_quit (loop);
}
GtkWidget *
my_window_new (GMainLoop *loop) {
GtkWidget *window=gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window), 200, 200);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
g_signal_connect(window, "destroy", G_CALLBACK(loop_quit), loop);
GtkWidget *entry = gtk_entry_new ();
GtkWidget *grid=gtk_grid_new();
gtk_grid_attach(GTK_GRID(grid), entry, 0, 0, 1, 1);
gtk_container_add(GTK_CONTAINER(window), grid);
return window;
}
static XIGrabModifiers *
get_grab_modifiers (guint modifiers,
int *result_length)
{
XIGrabModifiers *ximodifiers = g_new0 (XIGrabModifiers, 1);
XIGrabModifiers ximodifier = { 0, };
memset (&ximodifier, 0, sizeof (XIGrabModifiers));
ximodifier.modifiers = modifiers;
ximodifier.status = 0;
ximodifiers[0] = ximodifier;
if (result_length)
*result_length = 1;
return ximodifiers;
}
static void
grab_keycode (guint keysym,
guint modifiers)
{
GdkDisplay *display = gdk_display_get_default ();
Display *xdisplay = gdk_x11_display_get_xdisplay (display);
guint keycode = 0;
XIEventMask evmask = { 0, };
int length = 0;
XIGrabModifiers *ximodifiers;
keycode = XKeysymToKeycode (xdisplay, keysym);
memset (&evmask, 0, sizeof (XIEventMask));
evmask.deviceid = XIAllMasterDevices;
evmask.mask = g_new0 (guchar, (XI_LASTEVENT + 7) / 8);
evmask.mask_len = (XI_LASTEVENT + 7) / 8;
XISetMask (evmask.mask, XI_KeyPress);
XISetMask (evmask.mask, XI_KeyRelease);
ximodifiers = get_grab_modifiers (modifiers, &length);
XIGrabKeycode (xdisplay,
XIAllMasterDevices,
keycode,
DefaultRootWindow (xdisplay),
GrabModeAsync,
GrabModeAsync,
TRUE,
&evmask,
length,
ximodifiers);
g_free (ximodifiers);
}
static void
ungrab_keycode (guint keysym,
guint modifiers)
{
GdkDisplay *display = gdk_display_get_default ();
Display *xdisplay = gdk_x11_display_get_xdisplay (display);
guint keycode = 0;
int length = 0;
XIGrabModifiers *ximodifiers;
keycode = XKeysymToKeycode (xdisplay, keysym);
ximodifiers = get_grab_modifiers (modifiers, &length);
XIUngrabKeycode (xdisplay,
XIAllMasterDevices,
keycode,
DefaultRootWindow (xdisplay),
length,
ximodifiers);
g_free (ximodifiers);
}
static void
run_window ()
{
GtkWidget *window;
GMainLoop *loop;
loop = g_main_loop_new (NULL, FALSE);
window = my_window_new (loop);
gtk_widget_show_all(window);
g_main_loop_run (loop);
}
static void
event_handler (GdkEvent *event,
gpointer data)
{
static int times = 0;
if (((GdkEventAny*)event)->window == gdk_get_default_root_window() &&
event->type == GDK_KEY_PRESS) {
guint keyval = ((GdkEventKey*)event)->keyval;
guint modifiers = ((GdkEventKey*)event)->state;
if (keyval >= GDK_KEY_A && keyval <= GDK_KEY_Z &&
(modifiers & GDK_SHIFT_MASK) != 0) {
keyval = keyval - GDK_KEY_A + GDK_KEY_a;
}
if (keyval == shortcut_keysym &&
modifiers == shortcut_modifiers) {
run_window ();
times++;
if (times > 1) {
ungrab_keycode (keyval, modifiers);
gtk_main_quit();
}
}
}
gtk_main_do_event (event);
}
int
main (int argc, char *argv[])
{
GtkWidget *window;
GMainLoop *loop;
gtk_init (&argc, &argv);
gdk_event_handler_set (event_handler, NULL, NULL);
gtk_accelerator_parse ("<Control><Alt>v",
&shortcut_keysym,
&shortcut_modifiers);
grab_keycode (shortcut_keysym, shortcut_modifiers);
gtk_main();
return 0;
}