diff options
author | Owen Taylor <otaylor@redhat.com> | 2003-08-25 21:46:57 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2003-08-25 21:46:57 +0000 |
commit | eb41026147d0966a366420bb93f7e0fcefb73536 (patch) | |
tree | 18b29a08a3e5fe61d3e5e3f0c767ee2aecc79839 /gtk/gtkplug.c | |
parent | 9eb2d7c261dbbfaa3f7248efb88970eb02aa210a (diff) | |
download | gtk+-eb41026147d0966a366420bb93f7e0fcefb73536.tar.gz |
Send the focus on to the parent when there was no focus widget before and
Wed Aug 20 21:26:49 2003 Owen Taylor <otaylor@redhat.com>
* gtk/gtkplug.c (gtk_plug_focus): Send the focus on
to the parent when there was no focus widget before
and no focus widget after - that is, when there are
no focusable widgets. (#108678, help tracking it
down from Padraig O'Briain, Federico Mena Quintero, )
* gtk/gtkxembed.[ch]: Move various shared utilities
for the XEMBED protocol eused by GtkPlug and GtkSocket
here.
* gtk/gtkxembed.[ch] gtkplug.c gtksocket.c: Implement
a flag bit that is sent with focus mesages to indicate
that the focus has wrapped around on the toplevel;
use this bit to catch infinite loops when there is no
focusable widget at ll in the entire toplevel.
* tests/testsocket.c (child_read_watch): Remove an
extraneous unref.
* gtk/gtkplug.c gtk/gtksocket.c gtk/gtkxembed.h:
Up XEMBED protocol version to 1, add logic for
sending the right version in XEMBED_EMBEDDED_NOTIFY.
* gtk/gtksocket.c (gtk_socket_add_window): Send
the embedder window in the XEMBED_EMBEDDED_NOTIFY
as the spec requires.
Diffstat (limited to 'gtk/gtkplug.c')
-rw-r--r-- | gtk/gtkplug.c | 140 |
1 files changed, 49 insertions, 91 deletions
diff --git a/gtk/gtkplug.c b/gtk/gtkplug.c index 17345563ed..d0c3496a64 100644 --- a/gtk/gtkplug.c +++ b/gtk/gtkplug.c @@ -33,7 +33,7 @@ #include "gdk/gdkkeysyms.h" #include "x11/gdkx.h" -#include "xembed.h" +#include "gtkxembed.h" static void gtk_plug_class_init (GtkPlugClass *klass); static void gtk_plug_init (GtkPlug *plug); @@ -61,12 +61,6 @@ static GdkFilterReturn gtk_plug_filter_func (GdkXEvent *gdk_xev gpointer data); static void handle_modality_off (GtkPlug *plug); -static void send_xembed_message (GtkPlug *plug, - glong message, - glong detail, - glong data1, - glong data2, - guint32 time); static void xembed_set_info (GdkWindow *window, unsigned long flags); @@ -698,8 +692,8 @@ gtk_plug_set_focus (GtkWindow *window, if (focus && !window->has_toplevel_focus) { - send_xembed_message (plug, XEMBED_REQUEST_FOCUS, 0, 0, 0, - gtk_get_current_event_time ()); + _gtk_xembed_send_message (plug->socket_window, + XEMBED_REQUEST_FOCUS, 0, 0, 0); } } @@ -741,9 +735,8 @@ add_grabbed_key (gpointer key, gpointer val, gpointer data) if (!plug->grabbed_keys || !g_hash_table_lookup (plug->grabbed_keys, grabbed_key)) { - send_xembed_message (plug, XEMBED_GTK_GRAB_KEY, 0, - grabbed_key->accelerator_key, grabbed_key->accelerator_mods, - gtk_get_current_event_time ()); + _gtk_xembed_send_message (plug->socket_window, XEMBED_GTK_GRAB_KEY, 0, + grabbed_key->accelerator_key, grabbed_key->accelerator_mods); } } @@ -753,9 +746,8 @@ add_grabbed_key_always (gpointer key, gpointer val, gpointer data) GrabbedKey *grabbed_key = key; GtkPlug *plug = data; - send_xembed_message (plug, XEMBED_GTK_GRAB_KEY, 0, - grabbed_key->accelerator_key, grabbed_key->accelerator_mods, - gtk_get_current_event_time ()); + _gtk_xembed_send_message (plug->socket_window, XEMBED_GTK_GRAB_KEY, 0, + grabbed_key->accelerator_key, grabbed_key->accelerator_mods); } static void @@ -767,9 +759,8 @@ remove_grabbed_key (gpointer key, gpointer val, gpointer data) if (!plug->grabbed_keys || !g_hash_table_lookup (plug->grabbed_keys, grabbed_key)) { - send_xembed_message (plug, XEMBED_GTK_UNGRAB_KEY, 0, - grabbed_key->accelerator_key, grabbed_key->accelerator_mods, - gtk_get_current_event_time ()); + _gtk_xembed_send_message (plug->socket_window, XEMBED_GTK_UNGRAB_KEY, 0, + grabbed_key->accelerator_key, grabbed_key->accelerator_mods); } } @@ -812,6 +803,29 @@ gtk_plug_keys_changed (GtkWindow *window) } } +static void +focus_to_parent (GtkPlug *plug, + GtkDirectionType direction) +{ + XEmbedMessageType message = XEMBED_FOCUS_PREV; /* Quiet GCC */ + + switch (direction) + { + case GTK_DIR_UP: + case GTK_DIR_LEFT: + case GTK_DIR_TAB_BACKWARD: + message = XEMBED_FOCUS_PREV; + break; + case GTK_DIR_DOWN: + case GTK_DIR_RIGHT: + case GTK_DIR_TAB_FORWARD: + message = XEMBED_FOCUS_NEXT; + break; + } + + _gtk_xembed_send_focus_message (plug->socket_window, message, 0); +} + static gboolean gtk_plug_focus (GtkWidget *widget, GtkDirectionType direction) @@ -841,40 +855,18 @@ gtk_plug_focus (GtkWidget *widget, } gtk_window_set_focus (GTK_WINDOW (container), NULL); - - if (!GTK_CONTAINER (window)->focus_child) - { - gint message = -1; - - switch (direction) - { - case GTK_DIR_UP: - case GTK_DIR_LEFT: - case GTK_DIR_TAB_BACKWARD: - message = XEMBED_FOCUS_PREV; - break; - case GTK_DIR_DOWN: - case GTK_DIR_RIGHT: - case GTK_DIR_TAB_FORWARD: - message = XEMBED_FOCUS_NEXT; - break; - } - - send_xembed_message (plug, message, 0, 0, 0, - gtk_get_current_event_time ()); - } } - - return FALSE; } else { /* Try to focus the first widget in the window */ - if (bin->child && gtk_widget_child_focus (bin->child, direction)) return TRUE; } + if (!GTK_CONTAINER (window)->focus_child) + focus_to_parent (plug, direction); + return FALSE; } @@ -888,47 +880,12 @@ gtk_plug_check_resize (GtkContainer *container) } static void -send_xembed_message (GtkPlug *plug, - glong message, - glong detail, - glong data1, - glong data2, - guint32 time) -{ - if (plug->socket_window) - { - GdkDisplay *display = gdk_drawable_get_display (plug->socket_window); - XEvent xevent; - - GTK_NOTE(PLUGSOCKET, - g_message ("GtkPlug: Sending XEMBED message of type %ld", message)); - - xevent.xclient.window = GDK_WINDOW_XWINDOW (plug->socket_window); - xevent.xclient.type = ClientMessage; - xevent.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED"); - xevent.xclient.format = 32; - xevent.xclient.data.l[0] = time; - xevent.xclient.data.l[1] = message; - xevent.xclient.data.l[2] = detail; - xevent.xclient.data.l[3] = data1; - xevent.xclient.data.l[4] = data2; - - gdk_error_trap_push (); - XSendEvent (GDK_WINDOW_XDISPLAY(plug->socket_window), - GDK_WINDOW_XWINDOW (plug->socket_window), - False, NoEventMask, &xevent); - gdk_display_sync (display); - gdk_error_trap_pop (); - } -} - -static void focus_first_last (GtkPlug *plug, GtkDirectionType direction) { GtkWindow *window = GTK_WINDOW (plug); GtkWidget *parent; - + if (window->focus_widget) { parent = window->focus_widget->parent; @@ -977,7 +934,7 @@ xembed_set_info (GdkWindow *window, Atom xembed_info_atom = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO"); - buffer[1] = 0; /* Protocol version */ + buffer[1] = GTK_XEMBED_PROTOCOL_VERSION; buffer[1] = flags; XChangeProperty (GDK_DISPLAY_XDISPLAY (display), @@ -988,17 +945,17 @@ xembed_set_info (GdkWindow *window, } static void -handle_xembed_message (GtkPlug *plug, - glong message, - glong detail, - glong data1, - glong data2, - guint32 time) +handle_xembed_message (GtkPlug *plug, + XEmbedMessageType message, + glong detail, + glong data1, + glong data2, + guint32 time) { GtkWindow *window = GTK_WINDOW (plug); - + GTK_NOTE (PLUGSOCKET, - g_message ("GtkPlug: Message of type %ld received", message)); + g_message ("GtkPlug: Message of type %d received", message)); switch (message) { @@ -1044,12 +1001,12 @@ handle_xembed_message (GtkPlug *plug, case XEMBED_REQUEST_FOCUS: case XEMBED_FOCUS_NEXT: case XEMBED_FOCUS_PREV: - g_warning ("GtkPlug: Invalid _XEMBED message of type %ld received", message); + g_warning ("GtkPlug: Invalid _XEMBED message of type %d received", message); break; default: GTK_NOTE(PLUGSOCKET, - g_message ("GtkPlug: Ignoring unknown _XEMBED message of type %ld", message)); + g_message ("GtkPlug: Ignoring unknown _XEMBED message of type %d", message)); break; } } @@ -1071,14 +1028,15 @@ gtk_plug_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) case ClientMessage: if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED")) { + _gtk_xembed_push_message (xevent); handle_xembed_message (plug, xevent->xclient.data.l[1], xevent->xclient.data.l[2], xevent->xclient.data.l[3], xevent->xclient.data.l[4], xevent->xclient.data.l[0]); + _gtk_xembed_pop_message (); - return GDK_FILTER_REMOVE; } else if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW")) |