File containing #defines for XEMBED protocol.

Thu Apr 19 16:11:07 2001  Owen Taylor  <otaylor@redhat.com>

	* gtk/Makefile.am xembed.h: File containing #defines
	for XEMBED protocol.

	* gtk/gtkplug.[ch] gtk/gtksocket.[ch]:

	- Change protocol from old plug/socket specific protocol
	  to XEMBED draft
	- Various fixes to work with GTK+-2.0

	Still quite a bit of work to do here to handle initiation
	from the socket side (as specified by XEMBED), to handle
	the more advanced features of XEMBED, and to figure out
	a good way to handle same-app embedding with less overhead
	than using full XEMBED.
This commit is contained in:
Owen Taylor 2001-04-19 20:36:46 +00:00 committed by Owen Taylor
parent e13ec2098a
commit bf660df987
7 changed files with 965 additions and 462 deletions

View File

@ -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

View File

@ -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,254 +279,22 @@ 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)
{
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);
/* 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
*/
if (GTK_WIDGET_VISIBLE (widget))
{
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;
gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
}
}
return FALSE;
}
static gint
gtk_plug_focus_out_event (GtkWidget *widget,
GdkEventFocus *event)
{
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);
GTK_OBJECT_UNSET_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 = FALSE;
gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
}
return FALSE;
}
static void
gtk_plug_set_focus (GtkWindow *window,
GtkWidget *focus)
{
GtkPlug *plug;
GdkEventFocus event;
GtkPlug *plug = GTK_PLUG (window);
g_return_if_fail (window != NULL);
g_return_if_fail (GTK_IS_PLUG (window));
GTK_WINDOW_CLASS (parent_class)->set_focus (window, focus);
/* Ask for focus from embedder
*/
plug = GTK_PLUG (window);
if (focus && !GTK_WIDGET_CAN_FOCUS (focus))
return;
if (window->focus_widget != focus)
if (focus && !window->has_focus)
{
if (window->focus_widget)
{
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;
gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
}
}
/* Ask for focus from parent */
if (focus && !GTK_WIDGET_HAS_FOCUS(window))
{
#ifdef GDK_WINDOWING_X11
#if 0
XEvent xevent;
xevent.xfocus.type = FocusIn;
@ -624,8 +309,408 @@ gtk_plug_set_focus (GtkWindow *window,
False, NoEventMask, &xevent);
gdk_flush ();
gdk_error_trap_pop ();
#elif defined (GDK_WINDOWING_WIN32)
/* XXX Not implemented */
#endif
send_xembed_message (plug, XEMBED_REQUEST_FOCUS, 0, 0, 0,
gtk_get_current_event_time ());
}
}
#if 0
typedef struct
{
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;
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_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 ());
}
}
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_free_grabbed_keys (GHashTable *key_table)
{
g_hash_table_foreach (key_table, (GHFunc)g_free, NULL);
g_hash_table_destroy (key_table);
}
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);
new_grabbed_keys = g_hash_table_new (grabbed_key_hash, grabbed_key_equal);
accel_groups = gtk_accel_groups_from_object (GTK_OBJECT (window));
tmp_list = accel_groups;
while (tmp_list)
{
GtkAccelGroup *accel_group = tmp_list->data;
gint i, n_entries;
GtkAccelEntry *entries;
gtk_accel_group_get_entries (accel_group, &entries, &n_entries);
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);
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)
{
/* 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);
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;
}
}
}
return FALSE;
}
static void
send_xembed_message (GtkPlug *plug,
glong message,
glong detail,
glong data1,
glong data2,
guint32 time)
{
if (plug->socket_window)
{
XEvent xevent;
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,
GDK_WINDOW_XWINDOW (plug->socket_window),
False, NoEventMask, &xevent);
gdk_flush ();
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;
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;
}

View File

@ -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
#if 0
typedef struct
{
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;
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 ();
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;
g_return_val_if_fail (GTK_IS_SOCKET (widget), FALSE);
socket = GTK_SOCKET (widget);
GtkSocket *socket = GTK_SOCKET (widget);
if (socket->focus_in && socket->plug_window)
if (!GTK_WIDGET_HAS_FOCUS (widget))
{
gdk_error_trap_push ();
XSetInputFocus (GDK_DISPLAY (),
GDK_WINDOW_XWINDOW (socket->plug_window),
RevertToParent, GDK_CURRENT_TIME);
gdk_flush();
gdk_error_trap_pop ();
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)
{
GtkSocket *socket = GTK_SOCKET (widget);
GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
#if 0
GtkWidget *toplevel;
GtkSocket *socket;
g_return_val_if_fail (GTK_IS_SOCKET (widget), FALSE);
socket = GTK_SOCKET (widget);
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;
}

View File

@ -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

View File

@ -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 &&

View File

@ -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;

19
gtk/xembed.h Normal file
View File

@ -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