forked from AuroraMiddleware/gtk
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:
parent
e13ec2098a
commit
bf660df987
@ -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
|
||||
|
831
gtk/gtkplug.c
831
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 "gtkmain.h"
|
||||
#include "gtkplug.h"
|
||||
|
||||
#include "gdk/gdkkeysyms.h"
|
||||
#include "gtkplug.h"
|
||||
#include "x11/gdkx.h"
|
||||
|
||||
#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 gint gtk_plug_key_press_event (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_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);
|
||||
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,11 +120,17 @@ 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)
|
||||
{
|
||||
if (socket_id)
|
||||
{
|
||||
plug->socket_window = gdk_window_lookup (socket_id);
|
||||
plug->same_app = TRUE;
|
||||
|
||||
@ -127,6 +139,7 @@ gtk_plug_construct (GtkPlug *plug, GdkNativeWindow socket_id)
|
||||
plug->socket_window = gdk_window_foreign_new (socket_id);
|
||||
plug->same_app = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
@ -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;
|
||||
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);
|
||||
|
||||
plug = GTK_PLUG (window);
|
||||
/* Ask for focus from embedder
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
448
gtk/gtksocket.c
448
gtk/gtksocket.c
@ -36,11 +36,14 @@
|
||||
#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 */
|
||||
@ -53,18 +56,30 @@ 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,
|
||||
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 gint gtk_socket_focus_out_event (GtkWidget *widget,
|
||||
static gboolean 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,
|
||||
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,6 +671,14 @@ gtk_socket_focus_out_event (GtkWidget *widget, GdkEventFocus *event)
|
||||
RevertToParent, CurrentTime); /* FIXME? */
|
||||
}
|
||||
|
||||
#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);
|
||||
|
||||
@ -759,6 +1140,21 @@ 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;
|
||||
|
@ -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
|
||||
|
@ -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->has_focus = FALSE;
|
||||
|
||||
window = GTK_WINDOW (widget);
|
||||
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);
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
@ -2492,8 +2483,15 @@ gtk_window_real_set_focus (GtkWindow *window,
|
||||
GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
|
||||
}
|
||||
|
||||
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 &&
|
||||
(def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
|
||||
|
@ -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
19
gtk/xembed.h
Normal 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
|
||||
|
Loading…
Reference in New Issue
Block a user