1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* By Owen Taylor <otaylor@gtk.org> 98/4/4 */
22 #include "gdk/gdkkeysyms.h"
25 static void gtk_plug_class_init (GtkPlugClass *klass);
26 static void gtk_plug_init (GtkPlug *plug);
28 static void gtk_plug_realize (GtkWidget *widget);
29 static gint gtk_plug_key_press_event (GtkWidget *widget,
31 static void gtk_plug_forward_key_press (GtkPlug *plug, GdkEventKey *event);
32 static gint gtk_plug_focus_in_event (GtkWidget *widget, GdkEventFocus *event);
33 static gint gtk_plug_focus_out_event (GtkWidget *widget, GdkEventFocus *event);
34 static void gtk_plug_set_focus (GtkWindow *window,
38 #define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20
43 static guint plug_type = 0;
47 static const GtkTypeInfo plug_info =
51 sizeof (GtkPlugClass),
52 (GtkClassInitFunc) gtk_plug_class_init,
53 (GtkObjectInitFunc) gtk_plug_init,
58 plug_type = gtk_type_unique (gtk_window_get_type (), &plug_info);
65 gtk_plug_class_init (GtkPlugClass *class)
67 GtkWidgetClass *widget_class;
68 GtkWindowClass *window_class;
70 widget_class = (GtkWidgetClass *)class;
71 window_class = (GtkWindowClass *)class;
73 widget_class->realize = gtk_plug_realize;
74 widget_class->key_press_event = gtk_plug_key_press_event;
75 widget_class->focus_in_event = gtk_plug_focus_in_event;
76 widget_class->focus_out_event = gtk_plug_focus_out_event;
78 window_class->set_focus = gtk_plug_set_focus;
82 gtk_plug_init (GtkPlug *plug)
86 window = GTK_WINDOW (plug);
88 window->type = GTK_WINDOW_TOPLEVEL;
89 window->auto_shrink = TRUE;
93 gtk_plug_construct (GtkPlug *plug, guint32 socket_id)
95 plug->socket_window = gdk_window_lookup (socket_id);
96 plug->same_app = TRUE;
98 if (plug->socket_window == NULL)
100 plug->socket_window = gdk_window_foreign_new (socket_id);
101 plug->same_app = FALSE;
106 gtk_plug_new (guint32 socket_id)
110 plug = GTK_PLUG (gtk_type_new (gtk_plug_get_type ()));
111 gtk_plug_construct (plug, socket_id);
112 return GTK_WIDGET (plug);
116 gtk_plug_realize (GtkWidget *widget)
120 GdkWindowAttr attributes;
121 gint attributes_mask;
123 g_return_if_fail (widget != NULL);
124 g_return_if_fail (GTK_IS_PLUG (widget));
126 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
127 window = GTK_WINDOW (widget);
128 plug = GTK_PLUG (widget);
130 attributes.window_type = GDK_WINDOW_CHILD; /* XXX GDK_WINDOW_PLUG ? */
131 attributes.title = window->title;
132 attributes.wmclass_name = window->wmclass_name;
133 attributes.wmclass_class = window->wmclass_class;
134 attributes.width = widget->allocation.width;
135 attributes.height = widget->allocation.height;
136 attributes.wclass = GDK_INPUT_OUTPUT;
138 /* this isn't right - we should match our parent's visual/colormap.
139 * though that will require handling "foreign" colormaps */
140 attributes.visual = gtk_widget_get_visual (widget);
141 attributes.colormap = gtk_widget_get_colormap (widget);
142 attributes.event_mask = gtk_widget_get_events (widget);
143 attributes.event_mask |= (GDK_EXPOSURE_MASK |
145 GDK_ENTER_NOTIFY_MASK |
146 GDK_LEAVE_NOTIFY_MASK |
147 GDK_FOCUS_CHANGE_MASK |
150 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
151 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
152 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
154 widget->window = gdk_window_new (plug->socket_window,
155 &attributes, attributes_mask);
156 ((GdkWindowPrivate *)widget->window)->window_type = GDK_WINDOW_TOPLEVEL;
157 gdk_window_set_user_data (widget->window, window);
159 widget->style = gtk_style_attach (widget->style, widget->window);
160 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
164 gtk_plug_key_press_event (GtkWidget *widget,
169 GtkDirectionType direction = 0;
172 g_return_val_if_fail (widget != NULL, FALSE);
173 g_return_val_if_fail (GTK_IS_PLUG (widget), FALSE);
174 g_return_val_if_fail (event != NULL, FALSE);
176 window = GTK_WINDOW (widget);
177 plug = GTK_PLUG (widget);
179 if (!GTK_WIDGET_HAS_FOCUS(widget))
181 gtk_plug_forward_key_press (plug, event);
186 if (window->focus_widget)
187 return_val = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
190 if (!return_val && gtk_window_check_accelerator (window, event->keyval, event->state))
196 switch (event->keyval)
199 if (window->focus_widget)
201 gtk_widget_activate (window->focus_widget);
207 if (window->default_widget &&
208 (!window->focus_widget ||
209 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
211 gtk_widget_activate (window->default_widget);
214 else if (window->focus_widget)
216 gtk_widget_activate (window->focus_widget);
225 switch (event->keyval)
228 direction = GTK_DIR_UP;
231 direction = GTK_DIR_DOWN;
234 direction = GTK_DIR_LEFT;
237 direction = GTK_DIR_RIGHT;
240 if (event->state & GDK_SHIFT_MASK)
241 direction = GTK_DIR_TAB_BACKWARD;
243 direction = GTK_DIR_TAB_FORWARD;
246 direction = GTK_DIR_UP; /* never reached, but makes compiler happy */
249 gtk_container_focus (GTK_CONTAINER (widget), direction);
251 if (!GTK_CONTAINER (window)->focus_child)
253 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
255 XSetInputFocus (GDK_DISPLAY (),
256 GDK_WINDOW_XWINDOW (plug->socket_window),
257 RevertToParent, event->time);
259 gtk_plug_forward_key_press (plug, event);
272 gtk_plug_forward_key_press (GtkPlug *plug, GdkEventKey *event)
276 xevent.xkey.type = KeyPress;
277 xevent.xkey.display = GDK_WINDOW_XDISPLAY (GTK_WIDGET(plug)->window);
278 xevent.xkey.window = GDK_WINDOW_XWINDOW (plug->socket_window);
279 xevent.xkey.root = GDK_ROOT_WINDOW (); /* FIXME */
280 xevent.xkey.time = event->time;
281 /* FIXME, the following might cause big problems for
285 xevent.xkey.x_root = 0;
286 xevent.xkey.y_root = 0;
287 xevent.xkey.state = event->state;
288 xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(),
290 xevent.xkey.same_screen = TRUE; /* FIXME ? */
292 XSendEvent (gdk_display,
293 GDK_WINDOW_XWINDOW (plug->socket_window),
294 False, NoEventMask, &xevent);
297 /* Copied from Window, Ughh */
300 gtk_plug_focus_in_event (GtkWidget *widget,
301 GdkEventFocus *event)
304 GdkEventFocus fevent;
306 g_return_val_if_fail (widget != NULL, FALSE);
307 g_return_val_if_fail (GTK_IS_PLUG (widget), FALSE);
308 g_return_val_if_fail (event != NULL, FALSE);
310 /* It appears spurious focus in events can occur when
311 * the window is hidden. So we'll just check to see if
312 * the window is visible before actually handling the
315 if (GTK_WIDGET_VISIBLE (widget))
317 GTK_OBJECT_SET_FLAGS (widget, GTK_HAS_FOCUS);
318 window = GTK_WINDOW (widget);
319 if (window->focus_widget && !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
321 fevent.type = GDK_FOCUS_CHANGE;
322 fevent.window = window->focus_widget->window;
325 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
333 gtk_plug_focus_out_event (GtkWidget *widget,
334 GdkEventFocus *event)
337 GdkEventFocus fevent;
339 g_return_val_if_fail (widget != NULL, FALSE);
340 g_return_val_if_fail (GTK_IS_PLUG (widget), FALSE);
341 g_return_val_if_fail (event != NULL, FALSE);
343 GTK_OBJECT_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
345 window = GTK_WINDOW (widget);
347 if (window->focus_widget && GTK_WIDGET_HAS_FOCUS (window->focus_widget))
349 fevent.type = GDK_FOCUS_CHANGE;
350 fevent.window = window->focus_widget->window;
353 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
360 gtk_plug_set_focus (GtkWindow *window,
366 g_return_if_fail (window != NULL);
367 g_return_if_fail (GTK_IS_PLUG (window));
369 plug = GTK_PLUG (window);
371 if (focus && !GTK_WIDGET_CAN_FOCUS (focus))
374 if (window->focus_widget != focus)
376 if (window->focus_widget)
378 event.type = GDK_FOCUS_CHANGE;
379 event.window = window->focus_widget->window;
382 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
385 window->focus_widget = focus;
387 if (window->focus_widget)
389 event.type = GDK_FOCUS_CHANGE;
390 event.window = window->focus_widget->window;
393 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
397 /* Ask for focus from parent */
399 if (focus && !GTK_WIDGET_HAS_FOCUS(window))
403 xevent.xfocus.type = FocusIn;
404 xevent.xfocus.display = GDK_WINDOW_XDISPLAY (GTK_WIDGET(plug)->window);
405 xevent.xfocus.window = GDK_WINDOW_XWINDOW (plug->socket_window);
406 xevent.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS;
407 xevent.xfocus.detail = FALSE; /* Don't force */
409 XSendEvent (gdk_display,
410 GDK_WINDOW_XWINDOW (plug->socket_window),
411 False, NoEventMask, &xevent);