diff options
-rw-r--r-- | gtk/Makefile.am | 1 | ||||
-rw-r--r-- | gtk/gtkplug.c | 813 | ||||
-rw-r--r-- | gtk/gtksocket.c | 486 | ||||
-rw-r--r-- | gtk/gtksocket.h | 3 | ||||
-rw-r--r-- | gtk/gtkwindow.c | 52 | ||||
-rw-r--r-- | gtk/gtkwindow.h | 1 | ||||
-rw-r--r-- | gtk/xembed.h | 19 |
7 files changed, 939 insertions, 436 deletions
diff --git a/gtk/Makefile.am b/gtk/Makefile.am index cbb5ef42b3..509b8ecd5f 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -359,6 +359,7 @@ gtk_c_sources = @STRIP_BEGIN@ \ gtkwindow-decorate.c \ fnmatch.c \ fnmatch.h \ + xembed.h \ @STRIP_END@ # we use our own built_sources variable rules to avoid automake's diff --git a/gtk/gtkplug.c b/gtk/gtkplug.c index 420b53a8c6..78d9d5128f 100644 --- a/gtk/gtkplug.c +++ b/gtk/gtkplug.c @@ -25,34 +25,39 @@ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ -#include "gdkconfig.h" -#include "gdkprivate.h" - -#if defined (GDK_WINDOWING_X11) -#include "x11/gdkx.h" -#elif defined (GDK_WINDOWING_WIN32) -#include "win32/gdkwin32.h" -#elif defined (GDK_WINDOWING_NANOX) -#include "nanox/gdkprivate-nanox.h" -#elif defined (GDK_WINDOWING_FB) -#include "linux-fb/gdkfb.h" -#endif - -#include "gdk/gdkkeysyms.h" +#include "gtkmain.h" #include "gtkplug.h" -static void gtk_plug_class_init (GtkPlugClass *klass); -static void gtk_plug_init (GtkPlug *plug); +#include "gdk/gdkkeysyms.h" +#include "x11/gdkx.h" -static void gtk_plug_realize (GtkWidget *widget); -static void gtk_plug_unrealize (GtkWidget *widget); -static gint gtk_plug_key_press_event (GtkWidget *widget, - GdkEventKey *event); -static void gtk_plug_forward_key_press (GtkPlug *plug, GdkEventKey *event); -static gint gtk_plug_focus_in_event (GtkWidget *widget, GdkEventFocus *event); -static gint gtk_plug_focus_out_event (GtkWidget *widget, GdkEventFocus *event); -static void gtk_plug_set_focus (GtkWindow *window, - GtkWidget *focus); +#include "xembed.h" + +static void gtk_plug_class_init (GtkPlugClass *klass); +static void gtk_plug_init (GtkPlug *plug); +static void gtk_plug_realize (GtkWidget *widget); +static void gtk_plug_unrealize (GtkWidget *widget); +static gboolean gtk_plug_key_press_event (GtkWidget *widget, + GdkEventKey *event); +static void gtk_plug_forward_key_press (GtkPlug *plug, + GdkEventKey *event); +static void gtk_plug_set_focus (GtkWindow *window, + GtkWidget *focus); +static gboolean gtk_plug_focus (GtkContainer *container, + GtkDirectionType direction); +static void gtk_plug_accel_entries_changed (GtkWindow *window); +static GdkFilterReturn gtk_plug_filter_func (GdkXEvent *gdk_xevent, + GdkEvent *event, + gpointer data); + +static void gtk_plug_free_grabbed_keys (GHashTable *key_table); +static void handle_modality_off (GtkPlug *plug); +static void send_xembed_message (GtkPlug *plug, + glong message, + glong detail, + glong data1, + glong data2, + guint32 time); /* From Tk */ #define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20 @@ -88,21 +93,22 @@ gtk_plug_get_type () static void gtk_plug_class_init (GtkPlugClass *class) { - GtkWidgetClass *widget_class; - GtkWindowClass *window_class; - - widget_class = (GtkWidgetClass *)class; - window_class = (GtkWindowClass *)class; + GtkWidgetClass *widget_class = (GtkWidgetClass *)class; + GtkContainerClass *container_class = (GtkContainerClass *)class; + GtkWindowClass *window_class = (GtkWindowClass *)class; parent_class = gtk_type_class (GTK_TYPE_WINDOW); widget_class->realize = gtk_plug_realize; widget_class->unrealize = gtk_plug_unrealize; widget_class->key_press_event = gtk_plug_key_press_event; - widget_class->focus_in_event = gtk_plug_focus_in_event; - widget_class->focus_out_event = gtk_plug_focus_out_event; + + container_class->focus = gtk_plug_focus; window_class->set_focus = gtk_plug_set_focus; +#if 0 + window_class->accel_entries_changed = gtk_plug_accel_entries_changed; +#endif } static void @@ -114,18 +120,25 @@ gtk_plug_init (GtkPlug *plug) window->type = GTK_WINDOW_TOPLEVEL; window->auto_shrink = TRUE; + +#if 0 + gtk_window_set_grab_group (window, window); +#endif } void gtk_plug_construct (GtkPlug *plug, GdkNativeWindow socket_id) { - plug->socket_window = gdk_window_lookup (socket_id); - plug->same_app = TRUE; - - if (plug->socket_window == NULL) + if (socket_id) { - plug->socket_window = gdk_window_foreign_new (socket_id); - plug->same_app = FALSE; + plug->socket_window = gdk_window_lookup (socket_id); + plug->same_app = TRUE; + + if (plug->socket_window == NULL) + { + plug->socket_window = gdk_window_foreign_new (socket_id); + plug->same_app = FALSE; + } } } @@ -156,6 +169,11 @@ gtk_plug_unrealize (GtkWidget *widget) plug->socket_window = NULL; } +#if 0 + if (plug->modality_window) + handle_modality_off (plug); +#endif + if (GTK_WIDGET_CLASS (parent_class)->unrealize) (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); } @@ -212,132 +230,31 @@ gtk_plug_realize (GtkWidget *widget) widget->window = gdk_window_new (NULL, &attributes, attributes_mask); } - GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL; + GDK_WINDOW_TYPE (widget->window) = GDK_WINDOW_TOPLEVEL; gdk_window_set_user_data (widget->window, window); widget->style = gtk_style_attach (widget->style, widget->window); gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); + + gdk_window_add_filter (widget->window, gtk_plug_filter_func, widget); } -static gint +static gboolean gtk_plug_key_press_event (GtkWidget *widget, GdkEventKey *event) { - GtkWindow *window; - GtkPlug *plug; - GtkDirectionType direction = 0; - gint return_val; - - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_PLUG (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - - window = GTK_WINDOW (widget); - plug = GTK_PLUG (widget); - - if (!GTK_WIDGET_HAS_FOCUS(widget)) + if (!GTK_WINDOW (widget)->has_focus) { - gtk_plug_forward_key_press (plug, event); + gtk_plug_forward_key_press (GTK_PLUG (widget), event); return TRUE; } - - return_val = FALSE; - if (window->focus_widget) - return_val = gtk_widget_event (window->focus_widget, (GdkEvent*) event); - -#if 0 - if (!return_val && gtk_window_check_accelerator (window, event->keyval, event->state)) - return_val = TRUE; -#endif - - if (!return_val) - { - switch (event->keyval) - { - case GDK_space: - if (window->focus_widget) - { - gtk_widget_activate (window->focus_widget); - return_val = TRUE; - } - break; - case GDK_Return: - case GDK_KP_Enter: - if (window->default_widget && - (!window->focus_widget || - !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))) - { - gtk_widget_activate (window->default_widget); - return_val = TRUE; - } - else if (window->focus_widget) - { - gtk_widget_activate (window->focus_widget); - return_val = TRUE; - } - break; - case GDK_Up: - case GDK_Down: - case GDK_Left: - case GDK_Right: - case GDK_Tab: - switch (event->keyval) - { - case GDK_Up: - direction = GTK_DIR_UP; - break; - case GDK_Down: - direction = GTK_DIR_DOWN; - break; - case GDK_Left: - direction = GTK_DIR_LEFT; - break; - case GDK_Right: - direction = GTK_DIR_RIGHT; - break; - case GDK_Tab: - if (event->state & GDK_SHIFT_MASK) - direction = GTK_DIR_TAB_BACKWARD; - else - direction = GTK_DIR_TAB_FORWARD; - break; - default : - direction = GTK_DIR_UP; /* never reached, but makes compiler happy */ - } - - gtk_container_focus (GTK_CONTAINER (widget), direction); - - if (!GTK_CONTAINER (window)->focus_child) - { - gtk_window_set_focus (GTK_WINDOW (widget), NULL); - - gdk_error_trap_push (); -#ifdef GDK_WINDOWING_X11 - XSetInputFocus (GDK_DISPLAY (), - GDK_WINDOW_XWINDOW (plug->socket_window), - RevertToParent, event->time); -#elif defined (GDK_WINDOWING_WIN32) - SetFocus (GDK_WINDOW_HWND (plug->socket_window)); -#endif - gdk_flush (); - gdk_error_trap_pop (); - - gtk_plug_forward_key_press (plug, event); - } - - return_val = TRUE; - - break; - } - } - - return return_val; + else + return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); } static void gtk_plug_forward_key_press (GtkPlug *plug, GdkEventKey *event) { -#ifdef GDK_WINDOWING_X11 XEvent xevent; xevent.xkey.type = KeyPress; @@ -362,261 +279,280 @@ gtk_plug_forward_key_press (GtkPlug *plug, GdkEventKey *event) False, NoEventMask, &xevent); gdk_flush (); gdk_error_trap_pop (); -#elif defined (GDK_WINDOWING_WIN32) - /* This is pretty bogus, and not tested at all. */ - WPARAM wParam; - LPARAM lParam; - gboolean no_WM_CHAR = TRUE; - - lParam = 0; - switch (event->keyval) - { - case GDK_Cancel: - wParam = VK_CANCEL; break; - case GDK_BackSpace: - wParam = VK_BACK; break; - case GDK_Tab: - wParam = VK_TAB; break; - case GDK_Clear: - wParam = VK_CLEAR; break; - case GDK_Return: - wParam = VK_RETURN; break; - case GDK_Shift_L: - wParam = VK_SHIFT; break; - case GDK_Control_L: - wParam = VK_CONTROL; break; - case GDK_Control_R: - wParam = VK_CONTROL; lParam |= 0x01000000; break; - case GDK_Alt_L: - wParam = VK_MENU; break; - case GDK_Alt_R: - wParam = VK_MENU; lParam |= 0x01000000; break; - case GDK_Pause: - wParam = VK_PAUSE; break; - case GDK_Caps_Lock: - wParam = VK_CAPITAL; break; - case GDK_Escape: - wParam = VK_ESCAPE; break; - case GDK_Prior: - wParam = VK_PRIOR; break; - case GDK_Next: - wParam = VK_NEXT; break; - case GDK_End: - wParam = VK_END; break; - case GDK_Home: - wParam = VK_HOME; break; - case GDK_Left: - wParam = VK_LEFT; break; - case GDK_Up: - wParam = VK_UP; break; - case GDK_Right: - wParam = VK_RIGHT; break; - case GDK_Down: - wParam = VK_DOWN; break; - case GDK_Select: - wParam = VK_SELECT; break; - case GDK_Print: - wParam = VK_PRINT; break; - case GDK_Execute: - wParam = VK_EXECUTE; break; - case GDK_Insert: - wParam = VK_INSERT; break; - case GDK_Delete: - wParam = VK_DELETE; break; - case GDK_Help: - wParam = VK_HELP; break; - case GDK_KP_0: - wParam = VK_NUMPAD0; break; - case GDK_KP_1: - wParam = VK_NUMPAD1; break; - case GDK_KP_2: - wParam = VK_NUMPAD2; break; - case GDK_KP_3: - wParam = VK_NUMPAD3; break; - case GDK_KP_4: - wParam = VK_NUMPAD4; break; - case GDK_KP_5: - wParam = VK_NUMPAD5; break; - case GDK_KP_6: - wParam = VK_NUMPAD6; break; - case GDK_KP_7: - wParam = VK_NUMPAD7; break; - case GDK_KP_8: - wParam = VK_NUMPAD8; break; - case GDK_KP_9: - wParam = VK_NUMPAD9; break; - case GDK_KP_Multiply: - wParam = VK_MULTIPLY; break; - case GDK_KP_Add: - wParam = VK_ADD; break; - case GDK_KP_Separator: - wParam = VK_SEPARATOR; break; - case GDK_KP_Subtract: - wParam = VK_SUBTRACT; break; - case GDK_KP_Decimal: - wParam = VK_DECIMAL; break; - case GDK_KP_Divide: - wParam = VK_DIVIDE; break; - case GDK_F1: - wParam = VK_F1; break; - case GDK_F2: - wParam = VK_F2; break; - case GDK_F3: - wParam = VK_F3; break; - case GDK_F4: - wParam = VK_F4; break; - case GDK_F5: - wParam = VK_F5; break; - case GDK_F6: - wParam = VK_F6; break; - case GDK_F7: - wParam = VK_F7; break; - case GDK_F8: - wParam = VK_F8; break; - case GDK_F9: - wParam = VK_F9; break; - case GDK_F10: - wParam = VK_F10; break; - case GDK_F11: - wParam = VK_F11; break; - case GDK_F12: - wParam = VK_F12; break; - case GDK_F13: - wParam = VK_F13; break; - case GDK_F14: - wParam = VK_F14; break; - case GDK_F15: - wParam = VK_F15; break; - case GDK_F16: - wParam = VK_F16; break; - default: - wParam = event->keyval; - no_WM_CHAR = FALSE; - break; - } - - PostMessage (GDK_WINDOW_HWND (plug->socket_window), - WM_KEYDOWN, wParam, lParam); - if (!no_WM_CHAR) - PostMessage (GDK_WINDOW_HWND (plug->socket_window), - WM_CHAR, wParam, lParam); - PostMessage (GDK_WINDOW_HWND (plug->socket_window), - WM_KEYUP, wParam, lParam); -#endif } -/* Copied from Window, Ughh */ - -static gint -gtk_plug_focus_in_event (GtkWidget *widget, - GdkEventFocus *event) +static void +gtk_plug_set_focus (GtkWindow *window, + GtkWidget *focus) { - GtkWindow *window; - GdkEventFocus fevent; - - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_PLUG (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); + GtkPlug *plug = GTK_PLUG (window); - /* It appears spurious focus in events can occur when - * the window is hidden. So we'll just check to see if - * the window is visible before actually handling the - * event + GTK_WINDOW_CLASS (parent_class)->set_focus (window, focus); + + /* Ask for focus from embedder */ - if (GTK_WIDGET_VISIBLE (widget)) + + if (focus && !window->has_focus) { - GTK_OBJECT_SET_FLAGS (widget, GTK_HAS_FOCUS); - window = GTK_WINDOW (widget); - if (window->focus_widget && !GTK_WIDGET_HAS_FOCUS (window->focus_widget)) - { - fevent.type = GDK_FOCUS_CHANGE; - fevent.window = window->focus_widget->window; - fevent.in = TRUE; +#if 0 + XEvent xevent; - gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent); - } - } + xevent.xfocus.type = FocusIn; + xevent.xfocus.display = GDK_WINDOW_XDISPLAY (GTK_WIDGET(plug)->window); + xevent.xfocus.window = GDK_WINDOW_XWINDOW (plug->socket_window); + xevent.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS; + xevent.xfocus.detail = FALSE; /* Don't force */ - return FALSE; + gdk_error_trap_push (); + XSendEvent (gdk_display, + GDK_WINDOW_XWINDOW (plug->socket_window), + False, NoEventMask, &xevent); + gdk_flush (); + gdk_error_trap_pop (); +#endif + + send_xembed_message (plug, XEMBED_REQUEST_FOCUS, 0, 0, 0, + gtk_get_current_event_time ()); + } } -static gint -gtk_plug_focus_out_event (GtkWidget *widget, - GdkEventFocus *event) +#if 0 + +typedef struct { - GtkWindow *window; - GdkEventFocus fevent; + guint accelerator_key; + GdkModifierType accelerator_mods; +} GrabbedKey; - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_PLUG (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); +static guint +grabbed_key_hash (gconstpointer a) +{ + const GrabbedKey *key = a; + guint h; + + h = key->accelerator_key << 16; + h ^= key->accelerator_key >> 16; + h ^= key->accelerator_mods; - GTK_OBJECT_UNSET_FLAGS (widget, GTK_HAS_FOCUS); + return h; +} - window = GTK_WINDOW (widget); +static gboolean +grabbed_key_equal (gconstpointer a, gconstpointer b) +{ + const GrabbedKey *keya = a; + const GrabbedKey *keyb = b; - if (window->focus_widget && GTK_WIDGET_HAS_FOCUS (window->focus_widget)) - { - fevent.type = GDK_FOCUS_CHANGE; - fevent.window = window->focus_widget->window; - fevent.in = FALSE; + return (keya->accelerator_key == keyb->accelerator_key && + keya->accelerator_mods == keyb->accelerator_mods); +} - gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent); +static void +add_grabbed_keys (gpointer key, gpointer val, gpointer data) +{ + GrabbedKey *grabbed_key = key; + GtkPlug *plug = data; + + if (!plug->grabbed_keys || + !g_hash_table_lookup (plug->grabbed_keys, grabbed_key)) + { + send_xembed_message (plug, XEMBED_GRAB_KEY, 0, + grabbed_key->accelerator_key, grabbed_key->accelerator_mods, + gtk_get_current_event_time ()); } +} - return FALSE; +static void +remove_grabbed_keys (gpointer key, gpointer val, gpointer data) +{ + GrabbedKey *grabbed_key = key; + GtkPlug *plug = data; + + if (!plug->grabbed_keys || + !g_hash_table_lookup (plug->grabbed_keys, grabbed_key)) + { + send_xembed_message (plug, XEMBED_UNGRAB_KEY, 0, + grabbed_key->accelerator_key, grabbed_key->accelerator_mods, + gtk_get_current_event_time ()); + } } static void -gtk_plug_set_focus (GtkWindow *window, - GtkWidget *focus) +gtk_plug_free_grabbed_keys (GHashTable *key_table) { - GtkPlug *plug; - GdkEventFocus event; + g_hash_table_foreach (key_table, (GHFunc)g_free, NULL); + g_hash_table_destroy (key_table); +} - g_return_if_fail (window != NULL); - g_return_if_fail (GTK_IS_PLUG (window)); +static void +gtk_plug_accel_entries_changed (GtkWindow *window) +{ + GHashTable *new_grabbed_keys, *old_grabbed_keys; + GSList *accel_groups, *tmp_list; + GtkPlug *plug = GTK_PLUG (window); - plug = GTK_PLUG (window); + new_grabbed_keys = g_hash_table_new (grabbed_key_hash, grabbed_key_equal); - if (focus && !GTK_WIDGET_CAN_FOCUS (focus)) - return; + accel_groups = gtk_accel_groups_from_object (GTK_OBJECT (window)); + + tmp_list = accel_groups; - if (window->focus_widget != focus) + while (tmp_list) { - if (window->focus_widget) - { - event.type = GDK_FOCUS_CHANGE; - event.window = window->focus_widget->window; - event.in = FALSE; + GtkAccelGroup *accel_group = tmp_list->data; + gint i, n_entries; + GtkAccelEntry *entries; + + gtk_accel_group_get_entries (accel_group, &entries, &n_entries); - gtk_widget_event (window->focus_widget, (GdkEvent*) &event); + for (i = 0; i < n_entries; i++) + { + GdkKeymapKey *keys; + gint n_keys; + + if (gdk_keymap_get_entries_for_keyval (NULL, entries[i].accelerator_key, &keys, &n_keys)) + { + GrabbedKey *key = g_new (GrabbedKey, 1); + + key->accelerator_key = keys[0].keycode; + key->accelerator_mods = entries[i].accelerator_mods; + + g_hash_table_insert (new_grabbed_keys, key, key); + + g_free (keys); + } } + + tmp_list = tmp_list->next; + } + + g_hash_table_foreach (new_grabbed_keys, add_grabbed_keys, plug); - window->focus_widget = focus; + old_grabbed_keys = plug->grabbed_keys; + plug->grabbed_keys = new_grabbed_keys; + + if (old_grabbed_keys) + { + g_hash_table_foreach (old_grabbed_keys, remove_grabbed_keys, plug); + gtk_plug_free_grabbed_keys (old_grabbed_keys); + } + +} +#endif + +static gboolean +gtk_plug_focus (GtkContainer *container, + GtkDirectionType direction) +{ + GtkBin *bin = GTK_BIN (container); + GtkPlug *plug = GTK_PLUG (container); + GtkWindow *window = GTK_WINDOW (container); + GtkWidget *old_focus_child = container->focus_child; + GtkWidget *parent; + + /* We override GtkWindow's behavior, since we don't want wrapping here. + */ + if (old_focus_child) + { + if (GTK_IS_CONTAINER (old_focus_child) && + GTK_WIDGET_DRAWABLE (old_focus_child) && + GTK_WIDGET_IS_SENSITIVE (old_focus_child) && + gtk_container_focus (GTK_CONTAINER (old_focus_child), direction)) + return TRUE; if (window->focus_widget) { - event.type = GDK_FOCUS_CHANGE; - event.window = window->focus_widget->window; - event.in = TRUE; + /* Wrapped off the end, clear the focus setting for the toplevel */ + parent = window->focus_widget->parent; + while (parent) + { + gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL); + parent = GTK_WIDGET (parent)->parent; + } + + gtk_window_set_focus (GTK_WINDOW (container), NULL); - gtk_widget_event (window->focus_widget, (GdkEvent*) &event); + 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 ()); + +#if 0 + gtk_window_set_focus (GTK_WINDOW (widget), NULL); + + gdk_error_trap_push (); + XSetInputFocus (GDK_DISPLAY (), + GDK_WINDOW_XWINDOW (plug->socket_window), + RevertToParent, event->time); + gdk_flush (); + gdk_error_trap_pop (); + + gtk_plug_forward_key_press (plug, event); +#endif + } + } + + return FALSE; + } + else + { + /* Try to focus the first widget in the window */ + if (GTK_WIDGET_DRAWABLE (bin->child) && + GTK_WIDGET_IS_SENSITIVE (bin->child)) + { + if (GTK_IS_CONTAINER (bin->child)) + { + if (gtk_container_focus (GTK_CONTAINER (bin->child), direction)) + return TRUE; + } + else if (GTK_WIDGET_CAN_FOCUS (bin->child)) + { + gtk_widget_grab_focus (bin->child); + return TRUE; + } } } - /* Ask for focus from parent */ + return FALSE; +} - if (focus && !GTK_WIDGET_HAS_FOCUS(window)) +static void +send_xembed_message (GtkPlug *plug, + glong message, + glong detail, + glong data1, + glong data2, + guint32 time) +{ + if (plug->socket_window) { -#ifdef GDK_WINDOWING_X11 XEvent xevent; - xevent.xfocus.type = FocusIn; - xevent.xfocus.display = GDK_WINDOW_XDISPLAY (GTK_WIDGET(plug)->window); - xevent.xfocus.window = GDK_WINDOW_XWINDOW (plug->socket_window); - xevent.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS; - xevent.xfocus.detail = FALSE; /* Don't force */ + xevent.xclient.window = GDK_WINDOW_XWINDOW (plug->socket_window); + xevent.xclient.type = ClientMessage; + xevent.xclient.message_type = gdk_atom_intern ("_XEMBED", FALSE); + 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_display, @@ -624,8 +560,157 @@ gtk_plug_set_focus (GtkWindow *window, False, NoEventMask, &xevent); gdk_flush (); gdk_error_trap_pop (); -#elif defined (GDK_WINDOWING_WIN32) - /* XXX Not implemented */ -#endif } } + +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; + while (parent) + { + gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL); + parent = GTK_WIDGET (parent)->parent; + } + + gtk_window_set_focus (GTK_WINDOW (plug), NULL); + } + + gtk_container_focus (GTK_CONTAINER (plug), direction); +} + +static void +handle_modality_on (GtkPlug *plug) +{ +#if 0 + if (!plug->modality_window) + { + plug->modality_window = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_grab_group (GTK_WINDOW (plug->modality_window), GTK_WINDOW (plug)); + gtk_grab_add (plug->modality_window); + } +#endif +} + +static void +handle_modality_off (GtkPlug *plug) +{ +#if 0 + if (plug->modality_window) + { + gtk_grab_remove (plug->modality_window); + gtk_widget_destroy (plug->modality_window); + plug->modality_window = NULL; + } +#endif +} + +static void +handle_xembed_message (GtkPlug *plug, + glong message, + glong detail, + glong data1, + glong data2, + guint32 time) +{ + GTK_NOTE (PLUGSOCKET, + g_message ("Message of type %ld received", message)); + + switch (message) + { + case XEMBED_EMBEDDED_NOTIFY: + break; + case XEMBED_WINDOW_ACTIVATE: + GTK_NOTE(PLUGSOCKET, + g_message ("GtkPlug: ACTIVATE received")); + break; + case XEMBED_WINDOW_DEACTIVATE: + GTK_NOTE(PLUGSOCKET, + g_message ("GtkPlug: DEACTIVATE received")); + break; + + case XEMBED_MODALITY_ON: + handle_modality_on (plug); + break; + case XEMBED_MODALITY_OFF: + handle_modality_off (plug); + break; + + case XEMBED_FOCUS_IN: + switch (detail) + { + case XEMBED_FOCUS_FIRST: + focus_first_last (plug, GTK_DIR_TAB_FORWARD); + break; + case XEMBED_FOCUS_LAST: + focus_first_last (plug, GTK_DIR_TAB_BACKWARD); + break; + case XEMBED_FOCUS_CURRENT: + /* fall through */; + } + + case XEMBED_FOCUS_OUT: + { + GdkEvent event; + + event.focus_change.type = GDK_FOCUS_CHANGE; + event.focus_change.window = GTK_WIDGET (plug)->window; + event.focus_change.send_event = TRUE; + event.focus_change.in = (message == XEMBED_FOCUS_IN); + + gtk_widget_event (GTK_WIDGET (plug), &event); + + break; + } + + case XEMBED_REQUEST_FOCUS: + case XEMBED_FOCUS_NEXT: + case XEMBED_FOCUS_PREV: + case XEMBED_GRAB_KEY: + case XEMBED_UNGRAB_KEY: + g_warning ("GtkPlug: Invalid _XEMBED message of type %ld received", message); + break; + + default: + GTK_NOTE(PLUGSOCKET, + g_message ("GtkPlug: Ignoring unknown _XEMBED message of type %ld", message)); + break; + } +} + +static GdkFilterReturn +gtk_plug_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) +{ + GtkPlug *plug = GTK_PLUG (data); + XEvent *xevent = (XEvent *)gdk_xevent; + + GdkFilterReturn return_val; + + return_val = GDK_FILTER_CONTINUE; + + switch (xevent->type) + { + case ClientMessage: + if (xevent->xclient.message_type == gdk_atom_intern ("_XEMBED", FALSE)) + { + 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]); + + + return GDK_FILTER_REMOVE; + } + break; + } + + return GDK_FILTER_CONTINUE; +} diff --git a/gtk/gtksocket.c b/gtk/gtksocket.c index 648cedc481..1f905b796c 100644 --- a/gtk/gtksocket.c +++ b/gtk/gtksocket.c @@ -36,34 +36,49 @@ #endif #include "gdk/gdkkeysyms.h" +#include "gtkmain.h" #include "gtkwindow.h" #include "gtksignal.h" #include "gtksocket.h" #include "gtkdnd.h" +#include "xembed.h" + #ifdef GDK_WINDOWING_X11 /* Forward declararations */ -static void gtk_socket_class_init (GtkSocketClass *klass); -static void gtk_socket_init (GtkSocket *socket); -static void gtk_socket_realize (GtkWidget *widget); -static void gtk_socket_unrealize (GtkWidget *widget); -static void gtk_socket_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void gtk_socket_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); -static gint gtk_socket_focus_in_event (GtkWidget *widget, - GdkEventFocus *event); -static void gtk_socket_claim_focus (GtkSocket *socket); -static gint gtk_socket_focus_out_event (GtkWidget *widget, - GdkEventFocus *event); -static void gtk_socket_send_configure_event (GtkSocket *socket); -static gint gtk_socket_focus (GtkContainer *container, - GtkDirectionType direction); -static GdkFilterReturn gtk_socket_filter_func (GdkXEvent *gdk_xevent, - GdkEvent *event, - gpointer data); +static void gtk_socket_class_init (GtkSocketClass *klass); +static void gtk_socket_init (GtkSocket *socket); +static void gtk_socket_realize (GtkWidget *widget); +static void gtk_socket_unrealize (GtkWidget *widget); +static void gtk_socket_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void gtk_socket_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static void gtk_socket_hierarchy_changed (GtkWidget *widget); +static void gtk_socket_grab_notify (GtkWidget *widget, + gboolean was_grabbed); +static gboolean gtk_socket_key_press_event (GtkWidget *widget, + GdkEventKey *event); +static gboolean gtk_socket_focus_in_event (GtkWidget *widget, + GdkEventFocus *event); +static void gtk_socket_claim_focus (GtkSocket *socket); +static gboolean gtk_socket_focus_out_event (GtkWidget *widget, + GdkEventFocus *event); +static void gtk_socket_send_configure_event (GtkSocket *socket); +static gboolean gtk_socket_focus (GtkContainer *container, + GtkDirectionType direction); +static GdkFilterReturn gtk_socket_filter_func (GdkXEvent *gdk_xevent, + GdkEvent *event, + gpointer data); + +static void send_xembed_message (GtkSocket *socket, + glong message, + glong detail, + glong data1, + glong data2, + guint32 time); /* From Tk */ #define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20 @@ -101,11 +116,9 @@ gtk_socket_get_type (void) static void gtk_socket_class_init (GtkSocketClass *class) { - GtkObjectClass *object_class; GtkWidgetClass *widget_class; GtkContainerClass *container_class; - object_class = (GtkObjectClass*) class; widget_class = (GtkWidgetClass*) class; container_class = (GtkContainerClass*) class; @@ -115,6 +128,11 @@ gtk_socket_class_init (GtkSocketClass *class) widget_class->unrealize = gtk_socket_unrealize; widget_class->size_request = gtk_socket_size_request; widget_class->size_allocate = gtk_socket_size_allocate; + widget_class->hierarchy_changed = gtk_socket_hierarchy_changed; +#if 0 + widget_class->grab_notify = gtk_socket_grab_notify; +#endif + widget_class->key_press_event = gtk_socket_key_press_event; widget_class->focus_in_event = gtk_socket_focus_in_event; widget_class->focus_out_event = gtk_socket_focus_out_event; @@ -141,7 +159,7 @@ gtk_socket_new (void) { GtkSocket *socket; - socket = gtk_type_new (GTK_TYPE_SOCKET); + socket = g_object_new (GTK_TYPE_SOCKET, NULL); return GTK_WIDGET (socket); } @@ -271,8 +289,19 @@ gtk_socket_unrealize (GtkWidget *widget) if (toplevel && GTK_IS_WINDOW (toplevel)) gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), GDK_WINDOW_XWINDOW (socket->plug_window)); + + socket->plug_window = NULL; } +#if 0 + if (socket->grabbed_keys) + { + g_hash_table_foreach (socket->grabbed_keys, (GHFunc)g_free, NULL); + g_hash_table_destroy (socket->grabbed_keys); + socket->grabbed_keys = NULL; + } +#endif + if (GTK_WIDGET_CLASS (parent_class)->unrealize) (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); } @@ -383,35 +412,256 @@ gtk_socket_size_allocate (GtkWidget *widget, } } -static gint -gtk_socket_focus_in_event (GtkWidget *widget, GdkEventFocus *event) +#if 0 + +typedef struct { - GtkSocket *socket; - g_return_val_if_fail (GTK_IS_SOCKET (widget), FALSE); - socket = GTK_SOCKET (widget); + guint accelerator_key; + GdkModifierType accelerator_mods; +} GrabbedKey; + +static guint +grabbed_key_hash (gconstpointer a) +{ + const GrabbedKey *key = a; + guint h; + + h = key->accelerator_key << 16; + h ^= key->accelerator_key >> 16; + h ^= key->accelerator_mods; - if (socket->focus_in && socket->plug_window) + return h; +} + +static gboolean +grabbed_key_equal (gconstpointer a, gconstpointer b) +{ + const GrabbedKey *keya = a; + const GrabbedKey *keyb = b; + + return (keya->accelerator_key == keyb->accelerator_key && + keya->accelerator_mods == keyb->accelerator_mods); +} + +static void +add_grabbed_key (GtkSocket *socket, + guint hardware_keycode, + GdkModifierType mods) +{ + GrabbedKey key; + GrabbedKey *new_key; + GrabbedKey *found_key; + + if (socket->grabbed_keys) { + key.accelerator_key = hardware_keycode; + key.accelerator_mods = mods; + + found_key = g_hash_table_lookup (socket->grabbed_keys, &key); + + if (found_key) + { + g_warning ("GtkSocket: request to add already present grabbed key %u,%#x\n", + hardware_keycode, mods); + return; + } + } + + if (!socket->grabbed_keys) + socket->grabbed_keys = g_hash_table_new (grabbed_key_hash, grabbed_key_equal); + + new_key = g_new (GrabbedKey, 1); + + new_key->accelerator_key = hardware_keycode; + new_key->accelerator_mods = mods; + + g_hash_table_insert (socket->grabbed_keys, new_key, new_key); +} + +static void +remove_grabbed_key (GtkSocket *socket, + guint hardware_keycode, + GdkModifierType mods) +{ + GrabbedKey key; + GrabbedKey *found_key = NULL; + + if (socket->grabbed_keys) + { + key.accelerator_key = hardware_keycode; + key.accelerator_mods = mods; + + found_key = g_hash_table_lookup (socket->grabbed_keys, &key); + } + + if (found_key) + { + g_hash_table_remove (socket->grabbed_keys, &key); + g_free (found_key); + } + else + g_warning ("GtkSocket: request to remove non-present grabbed key %u,%#x\n", + hardware_keycode, mods); +} + +static gboolean +toplevel_key_press_handler (GtkWidget *toplevel, + GdkEventKey *event, + GtkSocket *socket) +{ + GrabbedKey search_key; + + search_key.accelerator_key = event->hardware_keycode; + search_key.accelerator_mods = event->state; + + if (socket->grabbed_keys && + g_hash_table_lookup (socket->grabbed_keys, &search_key)) + { + gtk_socket_key_press_event (GTK_WIDGET (socket), event); + gtk_signal_emit_stop_by_name (GTK_OBJECT (toplevel), "key_press_event"); + + return TRUE; + } + else + return FALSE; +} + +#endif + +static void +toplevel_focus_in_handler (GtkWidget *toplevel, + GdkEventFocus *event, + GtkSocket *socket) +{ + /* It appears spurious focus in events can occur when + * the window is hidden. So we'll just check to see if + * the window is visible before actually handling the + * event. (Comment from gtkwindow.c) + */ + if (GTK_WIDGET_VISIBLE (toplevel)) + send_xembed_message (socket, XEMBED_WINDOW_ACTIVATE, 0, 0, 0, + gtk_get_current_event_time ()); /* Will be GDK_CURRENT_TIME */ +} + +static void +toplevel_focus_out_handler (GtkWidget *toplevel, + GdkEventFocus *event, + GtkSocket *socket) +{ + send_xembed_message (socket, XEMBED_WINDOW_DEACTIVATE, 0, 0, 0, + gtk_get_current_event_time ()); /* Will be GDK_CURRENT_TIME */ +} + +static void +gtk_socket_hierarchy_changed (GtkWidget *widget) +{ + GtkSocket *socket = GTK_SOCKET (widget); + GtkWidget *toplevel = gtk_widget_get_toplevel (widget); + + if (toplevel && !GTK_IS_WINDOW (toplevel)) + toplevel = NULL; + + if (toplevel != socket->toplevel) + { + if (socket->toplevel) + { +#if 0 + gtk_signal_disconnect_by_func (GTK_OBJECT (socket->toplevel), GTK_SIGNAL_FUNC (toplevel_key_press_handler), socket); +#endif + gtk_signal_disconnect_by_func (GTK_OBJECT (socket->toplevel), GTK_SIGNAL_FUNC (toplevel_focus_in_handler), socket); + gtk_signal_disconnect_by_func (GTK_OBJECT (socket->toplevel), GTK_SIGNAL_FUNC (toplevel_focus_out_handler), socket); + } + + socket->toplevel = toplevel; + + if (toplevel) + { +#if 0 + gtk_signal_connect (GTK_OBJECT (socket->toplevel), "key_press_event", + GTK_SIGNAL_FUNC (toplevel_key_press_handler), socket); +#endif + gtk_signal_connect (GTK_OBJECT (socket->toplevel), "focus_in_event", + GTK_SIGNAL_FUNC (toplevel_focus_in_handler), socket); + gtk_signal_connect (GTK_OBJECT (socket->toplevel), "focus_out_event", + GTK_SIGNAL_FUNC (toplevel_focus_out_handler), socket); + } + } +} + +static void +gtk_socket_grab_notify (GtkWidget *widget, + gboolean was_grabbed) +{ + send_xembed_message (GTK_SOCKET (widget), + was_grabbed ? XEMBED_MODALITY_OFF : XEMBED_MODALITY_ON, + 0, 0, 0, gtk_get_current_event_time ()); +} + +static gboolean +gtk_socket_key_press_event (GtkWidget *widget, + GdkEventKey *event) +{ + GtkSocket *socket = GTK_SOCKET (widget); + + if (socket->plug_window) + { + XEvent xevent; + + xevent.xkey.type = KeyPress; + xevent.xkey.display = GDK_WINDOW_XDISPLAY (event->window); + xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window); + xevent.xkey.root = GDK_ROOT_WINDOW (); + xevent.xkey.time = event->time; + /* FIXME, the following might cause problems for non-GTK apps */ + xevent.xkey.x = 0; + xevent.xkey.y = 0; + xevent.xkey.x_root = 0; + xevent.xkey.y_root = 0; + xevent.xkey.state = event->state; + xevent.xkey.keycode = event->hardware_keycode; + xevent.xkey.same_screen = TRUE; /* FIXME ? */ + gdk_error_trap_push (); - XSetInputFocus (GDK_DISPLAY (), - GDK_WINDOW_XWINDOW (socket->plug_window), - RevertToParent, GDK_CURRENT_TIME); - gdk_flush(); + XSendEvent (gdk_display, + GDK_WINDOW_XWINDOW (socket->plug_window), + False, NoEventMask, &xevent); + gdk_flush (); gdk_error_trap_pop (); + + return TRUE; + } + else + return FALSE; +} + +static gboolean +gtk_socket_focus_in_event (GtkWidget *widget, GdkEventFocus *event) +{ + GtkSocket *socket = GTK_SOCKET (widget); + + if (!GTK_WIDGET_HAS_FOCUS (widget)) + { + GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS); + + if (socket->plug_window) + { + send_xembed_message (socket, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0, + gtk_get_current_event_time ()); + } } return TRUE; } -static gint +static gboolean gtk_socket_focus_out_event (GtkWidget *widget, GdkEventFocus *event) { - GtkWidget *toplevel; - GtkSocket *socket; + GtkSocket *socket = GTK_SOCKET (widget); - g_return_val_if_fail (GTK_IS_SOCKET (widget), FALSE); - socket = GTK_SOCKET (widget); + GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS); +#if 0 + GtkWidget *toplevel; toplevel = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW); if (toplevel) @@ -421,8 +671,16 @@ gtk_socket_focus_out_event (GtkWidget *widget, GdkEventFocus *event) RevertToParent, CurrentTime); /* FIXME? */ } - socket->focus_in = FALSE; +#endif + + if (socket->plug_window) + { + send_xembed_message (socket, XEMBED_FOCUS_OUT, 0, 0, 0, + gtk_get_current_event_time ()); + } + socket->focus_in = FALSE; + return TRUE; } @@ -442,24 +700,55 @@ gtk_socket_claim_focus (GtkSocket *socket) * it as an app... (and see _focus_in ()) */ if (socket->plug_window) { +#if 0 gdk_error_trap_push (); XSetInputFocus (GDK_DISPLAY (), GDK_WINDOW_XWINDOW (socket->plug_window), RevertToParent, GDK_CURRENT_TIME); gdk_flush (); gdk_error_trap_pop (); +#endif } } -static gint +static gboolean gtk_socket_focus (GtkContainer *container, GtkDirectionType direction) { GtkSocket *socket; + gint detail = -1; g_return_val_if_fail (GTK_IS_SOCKET (container), FALSE); socket = GTK_SOCKET (container); + if (!GTK_WIDGET_HAS_FOCUS (container)) + { + switch (direction) + { + case GTK_DIR_UP: + case GTK_DIR_LEFT: + case GTK_DIR_TAB_BACKWARD: + detail = XEMBED_FOCUS_LAST; + break; + case GTK_DIR_DOWN: + case GTK_DIR_RIGHT: + case GTK_DIR_TAB_FORWARD: + detail = XEMBED_FOCUS_FIRST; + break; + } + + send_xembed_message (socket, XEMBED_FOCUS_IN, detail, 0, 0, + gtk_get_current_event_time ()); + + GTK_WIDGET_SET_FLAGS (container, GTK_HAS_FOCUS); + gtk_widget_grab_focus (GTK_WIDGET (container)); + + return TRUE; + } + else + return FALSE; + +#if 0 if (!socket->focus_in && socket->plug_window) { XEvent xevent; @@ -517,6 +806,7 @@ gtk_socket_focus (GtkContainer *container, GtkDirectionType direction) { return FALSE; } +#endif } static void @@ -587,6 +877,98 @@ gtk_socket_add_window (GtkSocket *socket, GdkNativeWindow xid) { gtk_window_add_embedded_xid (GTK_WINDOW (toplevel), xid); } + + gtk_widget_queue_resize (GTK_WIDGET (socket)); + } +} + + +static void +send_xembed_message (GtkSocket *socket, + glong message, + glong detail, + glong data1, + glong data2, + guint32 time) +{ + GTK_NOTE(PLUGSOCKET, + g_message ("GtkSocket: Sending XEMBED message of type %d", message)); + + if (socket->plug_window) + { + XEvent xevent; + + xevent.xclient.window = GDK_WINDOW_XWINDOW (socket->plug_window); + xevent.xclient.type = ClientMessage; + xevent.xclient.message_type = gdk_atom_intern ("_XEMBED", FALSE); + 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_display, + GDK_WINDOW_XWINDOW (socket->plug_window), + False, NoEventMask, &xevent); + gdk_flush (); + gdk_error_trap_pop (); + } +} + +static void +handle_xembed_message (GtkSocket *socket, + glong message, + glong detail, + glong data1, + glong data2, + guint32 time) +{ + switch (message) + { + case XEMBED_EMBEDDED_NOTIFY: + case XEMBED_WINDOW_ACTIVATE: + case XEMBED_WINDOW_DEACTIVATE: + case XEMBED_MODALITY_ON: + case XEMBED_MODALITY_OFF: + case XEMBED_FOCUS_IN: + case XEMBED_FOCUS_OUT: + g_warning ("GtkSocket: Invalid _XEMBED message of type %ld received", message); + break; + + case XEMBED_REQUEST_FOCUS: + gtk_socket_claim_focus (socket); + break; + + case XEMBED_FOCUS_NEXT: + case XEMBED_FOCUS_PREV: + { + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket)); + if (toplevel && GTK_IS_CONTAINER (toplevel)) + { + gtk_container_focus (GTK_CONTAINER (toplevel), + (message == XEMBED_FOCUS_NEXT ? + GTK_DIR_TAB_FORWARD : GTK_DIR_TAB_BACKWARD)); + } + break; + } + + case XEMBED_GRAB_KEY: +#if 0 + add_grabbed_key (socket, data1, data2); +#endif + break; + case XEMBED_UNGRAB_KEY: +#if 0 + remove_grabbed_key (socket, data1, data2); +#endif + break; + + default: + GTK_NOTE(PLUGSOCKET, + g_message ("GtkSocket: Ignoring unknown _XEMBED message of type %ld", message)); + break; } } @@ -631,8 +1013,6 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) g_message ("GtkSocket - window created with size: %d %d", socket->request_width, socket->request_height)); - - gtk_widget_queue_resize (widget); } return_val = GDK_FILTER_REMOVE; @@ -688,6 +1068,7 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket)); if (toplevel && GTK_IS_WINDOW (toplevel)) gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), xdwe->window); + gdk_window_destroy_notify (socket->plug_window); gtk_widget_destroy (widget); @@ -696,8 +1077,8 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) return_val = GDK_FILTER_REMOVE; } break; - } - + } + case FocusIn: if (xevent->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS) { @@ -731,7 +1112,7 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) { GTK_NOTE(PLUGSOCKET, g_message ("GtkSocket - Map Request")); - + gdk_error_trap_push (); gdk_window_show (socket->plug_window); gdk_flush (); @@ -759,8 +1140,23 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) } return_val = GDK_FILTER_REMOVE; } + break; + case ClientMessage: + if (xevent->xclient.message_type == gdk_atom_intern ("_XEMBED", FALSE)) + { + handle_xembed_message (socket, + 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]); + + + return_val = GDK_FILTER_REMOVE; + } + break; } - + return return_val; } diff --git a/gtk/gtksocket.h b/gtk/gtksocket.h index 4d354a0969..d6dc92d710 100644 --- a/gtk/gtksocket.h +++ b/gtk/gtksocket.h @@ -58,6 +58,9 @@ struct _GtkSocket guint focus_in : 1; guint have_size : 1; guint need_map : 1; + + GHashTable *grabbed_keys; + GtkWidget *toplevel; }; struct _GtkSocketClass diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index e03cc71fd3..52654dab08 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -2248,13 +2248,9 @@ static gint gtk_window_focus_in_event (GtkWidget *widget, GdkEventFocus *event) { - GtkWindow *window; + GtkWindow *window = GTK_WINDOW (widget); GdkEventFocus fevent; - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - /* It appears spurious focus in events can occur when * the window is hidden. So we'll just check to see if * the window is visible before actually handling the @@ -2262,7 +2258,8 @@ gtk_window_focus_in_event (GtkWidget *widget, */ if (GTK_WIDGET_VISIBLE (widget)) { - window = GTK_WINDOW (widget); + window->has_focus = TRUE; + if (window->focus_widget && window->focus_widget != widget && !GTK_WIDGET_HAS_FOCUS (window->focus_widget)) @@ -2282,14 +2279,11 @@ static gint gtk_window_focus_out_event (GtkWidget *widget, GdkEventFocus *event) { - GtkWindow *window; + GtkWindow *window = GTK_WINDOW (widget); GdkEventFocus fevent; - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - - window = GTK_WINDOW (widget); + window->has_focus = FALSE; + if (window->focus_widget && window->focus_widget != widget && GTK_WIDGET_HAS_FOCUS (window->focus_widget)) @@ -2456,32 +2450,29 @@ gtk_window_real_set_focus (GtkWindow *window, if (window->focus_widget) { - event.type = GDK_FOCUS_CHANGE; - event.window = window->focus_widget->window; - event.in = FALSE; - if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) && (window->focus_widget != window->default_widget)) { GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT); - /* if any widget had the default set there should be - a default_widget, but might not so this is a sanity - check */ + if (window->default_widget) GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT); } - - gtk_widget_event (window->focus_widget, (GdkEvent*) &event); + + if (window->has_focus) + { + event.type = GDK_FOCUS_CHANGE; + event.window = window->focus_widget->window; + event.in = FALSE; + + gtk_widget_event (window->focus_widget, (GdkEvent*) &event); + } } window->focus_widget = focus; if (window->focus_widget) { - event.type = GDK_FOCUS_CHANGE; - event.window = window->focus_widget->window; - event.in = TRUE; - if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) && (window->focus_widget != window->default_widget)) { @@ -2491,8 +2482,15 @@ gtk_window_real_set_focus (GtkWindow *window, if (window->default_widget) GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT); } - - gtk_widget_event (window->focus_widget, (GdkEvent*) &event); + + if (window->has_focus) + { + event.type = GDK_FOCUS_CHANGE; + event.window = window->focus_widget->window; + event.in = TRUE; + + gtk_widget_event (window->focus_widget, (GdkEvent*) &event); + } } if (window->default_widget && diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h index 8688917297..76584d80de 100644 --- a/gtk/gtkwindow.h +++ b/gtk/gtkwindow.h @@ -70,6 +70,7 @@ struct _GtkWindow GtkWindowType type : 4; guint has_user_ref_count : 1; + guint has_focus : 1; guint allow_shrink : 1; guint allow_grow : 1; guint auto_shrink : 1; diff --git a/gtk/xembed.h b/gtk/xembed.h new file mode 100644 index 0000000000..5c4e35d774 --- /dev/null +++ b/gtk/xembed.h @@ -0,0 +1,19 @@ +/* XEMBED messages */ +#define XEMBED_EMBEDDED_NOTIFY 0 +#define XEMBED_WINDOW_ACTIVATE 1 +#define XEMBED_WINDOW_DEACTIVATE 2 +#define XEMBED_REQUEST_FOCUS 3 +#define XEMBED_FOCUS_IN 4 +#define XEMBED_FOCUS_OUT 5 +#define XEMBED_FOCUS_NEXT 6 +#define XEMBED_FOCUS_PREV 7 +#define XEMBED_GRAB_KEY 8 +#define XEMBED_UNGRAB_KEY 9 +#define XEMBED_MODALITY_ON 10 +#define XEMBED_MODALITY_OFF 11 + +/* Details for XEMBED_FOCUS_IN: */ +#define XEMBED_FOCUS_CURRENT 0 +#define XEMBED_FOCUS_FIRST 1 +#define XEMBED_FOCUS_LAST 2 + |