Hi Jonas,
> > [...]
> > For that last point, I'd rather use:
> >
> > * does not guarantee that events sent to this client are continuous,
> > a compositor may change and reroute keyboard events while the grab
> > is nominally active.
> >
> > > hmm, and thinking about the last point: do we need to specify what the
> > > focus
> > > behaviour is if a grab is active? I'm assuming 'no' because there is no
> > > notification whatsoever whether it ever activates anyway, but...
> >
> > No, indeed, that's precisely the main difference with the shortcuts
> > inhibitor logic for the wayland native apps.
> >
> > Here, keyboards events are routed to the surface regardless of the focus,
> > just like an X11 grab.
>
> Should this part really be respected though? In what circumstances does
> it make sense to route input events to Xwayland when a Wayland client is
> the one focused?
Yes, that's precisely the whole point of this protocol (and grabs in general) :)
Take the attached sample code for example, it maps a single override redirect
window (one that no X11 window manager would focus, because it's an O-R) and
issues an active keyboard grab to get all keyboard events.
While that works fine in X11 native, that won't work in Wayland/Xwayland
without this protocol and the ability to route keyboard events even when the
surface is not focused.
> > > Last question: how will you deal with XGrabKeyboard() requests on already
> > > grabbed keyboards? I can send that request twice with different grab
> > > windows
> > > and it'll change the grab over (iirc). Xwayland will destroy the current
> > > grab and request a new one?
> >
> > Yeap, good point, "XGrabKeyboard overrides any active keyboard grab by the
> > client" so Xwayland needs to destroy any current grab before setting a new
> > one in this case.
> >
>
> FWIW, this will create a minor race, where any key presses between the
> .destroy and .grab requests will be ungrabbed.
Yeah, you're right, but I reckon it's acceptable.
Cheers,
Olivier
/*
* Compile with :
*
* gcc -Wall -g grab.c -o grab `pkg-config --cflags gtk+-2.0` `pkg-config --libs gtk+-2.0`
*
*/
#include <gtk/gtk.h>
static gboolean
on_map_event_cb (GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
{
GdkWindow *gdk_window = gtk_widget_get_window (widget);
gdk_keyboard_grab (gdk_window, TRUE, GDK_CURRENT_TIME);
g_message ("Widget %p is mapped!", widget);
return FALSE;
}
static void
destroy (GtkWidget *widget, gpointer data)
{
gtk_main_quit ();
}
static gboolean
on_key_press_event (GtkWidget *widget, GdkEventKey *event, gpointer data)
{
g_message ("Key 0x%x pressed, widget %p", event->keyval, widget);
return FALSE;
}
static gboolean
on_key_release_event (GtkWidget *widget, GdkEventKey *event, gpointer data)
{
g_message ("Key 0x%x released, widget %p", event->keyval, widget);
return FALSE;
}
int
main (int argc, char *argv[])
{
GtkWidget *window1;
GtkWidget *button;
GtkWidget *vbox;
GtkWidget *label;
GtkWidget *entry;
gchar* str;
gtk_init (&argc, &argv);
/* Popup window (override redirect on X11) */
window1 = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_keep_above (GTK_WINDOW (window1), TRUE);
gtk_window_set_position (GTK_WINDOW (window1), GTK_WIN_POS_CENTER_ALWAYS);
gtk_container_set_border_width (GTK_CONTAINER (window1), 25);
g_signal_connect (G_OBJECT (window1), "destroy", G_CALLBACK (destroy), NULL);
g_signal_connect_after (G_OBJECT (window1), "map-event", G_CALLBACK (on_map_event_cb), NULL);
vbox = gtk_vbox_new (FALSE, 10);
gtk_container_add (GTK_CONTAINER (window1), vbox);
label = gtk_label_new (NULL);
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
str = g_markup_printf_escaped ("<big>This is widget <b><tt>%p</tt></b></big>", window1);
gtk_label_set_markup (GTK_LABEL (label), str);
g_free (str);
gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
entry = gtk_entry_new ();
gtk_entry_set_text (GTK_ENTRY (entry), "Enter some text here...");
gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
button = gtk_toggle_button_new_with_label ("Done");
gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (gtk_main_quit), NULL);
g_signal_connect (G_OBJECT (window1), "key-press-event", G_CALLBACK(on_key_press_event), NULL);
g_signal_connect (G_OBJECT (window1), "key-release-event", G_CALLBACK(on_key_release_event), NULL);
gtk_widget_show_all (window1);
gtk_main ();
return 0;
}
_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel