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 * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
23 * file for a list of people on the GTK+ Team. See the ChangeLog
24 * files for a list of changes. These files are distributed with
25 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
29 #include "gdk/gdkkeysyms.h"
32 static void gtk_plug_class_init (GtkPlugClass *klass);
33 static void gtk_plug_init (GtkPlug *plug);
35 static void gtk_plug_realize (GtkWidget *widget);
36 static gint gtk_plug_key_press_event (GtkWidget *widget,
38 static void gtk_plug_forward_key_press (GtkPlug *plug, GdkEventKey *event);
39 static gint gtk_plug_focus_in_event (GtkWidget *widget, GdkEventFocus *event);
40 static gint gtk_plug_focus_out_event (GtkWidget *widget, GdkEventFocus *event);
41 static void gtk_plug_set_focus (GtkWindow *window,
45 #define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20
50 static guint plug_type = 0;
54 static const GtkTypeInfo plug_info =
58 sizeof (GtkPlugClass),
59 (GtkClassInitFunc) gtk_plug_class_init,
60 (GtkObjectInitFunc) gtk_plug_init,
65 plug_type = gtk_type_unique (gtk_window_get_type (), &plug_info);
72 gtk_plug_class_init (GtkPlugClass *class)
74 GtkWidgetClass *widget_class;
75 GtkWindowClass *window_class;
77 widget_class = (GtkWidgetClass *)class;
78 window_class = (GtkWindowClass *)class;
80 widget_class->realize = gtk_plug_realize;
81 widget_class->key_press_event = gtk_plug_key_press_event;
82 widget_class->focus_in_event = gtk_plug_focus_in_event;
83 widget_class->focus_out_event = gtk_plug_focus_out_event;
85 window_class->set_focus = gtk_plug_set_focus;
89 gtk_plug_init (GtkPlug *plug)
93 window = GTK_WINDOW (plug);
95 window->type = GTK_WINDOW_TOPLEVEL;
96 window->auto_shrink = TRUE;
100 gtk_plug_construct (GtkPlug *plug, guint32 socket_id)
102 plug->socket_window = gdk_window_lookup (socket_id);
103 plug->same_app = TRUE;
105 if (plug->socket_window == NULL)
107 plug->socket_window = gdk_window_foreign_new (socket_id);
108 plug->same_app = FALSE;
113 gtk_plug_new (guint32 socket_id)
117 plug = GTK_PLUG (gtk_type_new (gtk_plug_get_type ()));
118 gtk_plug_construct (plug, socket_id);
119 return GTK_WIDGET (plug);
123 gtk_plug_realize (GtkWidget *widget)
127 GdkWindowAttr attributes;
128 gint attributes_mask;
130 g_return_if_fail (widget != NULL);
131 g_return_if_fail (GTK_IS_PLUG (widget));
133 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
134 window = GTK_WINDOW (widget);
135 plug = GTK_PLUG (widget);
137 attributes.window_type = GDK_WINDOW_CHILD; /* XXX GDK_WINDOW_PLUG ? */
138 attributes.title = window->title;
139 attributes.wmclass_name = window->wmclass_name;
140 attributes.wmclass_class = window->wmclass_class;
141 attributes.width = widget->allocation.width;
142 attributes.height = widget->allocation.height;
143 attributes.wclass = GDK_INPUT_OUTPUT;
145 /* this isn't right - we should match our parent's visual/colormap.
146 * though that will require handling "foreign" colormaps */
147 attributes.visual = gtk_widget_get_visual (widget);
148 attributes.colormap = gtk_widget_get_colormap (widget);
149 attributes.event_mask = gtk_widget_get_events (widget);
150 attributes.event_mask |= (GDK_EXPOSURE_MASK |
152 GDK_ENTER_NOTIFY_MASK |
153 GDK_LEAVE_NOTIFY_MASK |
154 GDK_FOCUS_CHANGE_MASK |
157 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
158 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
159 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
161 gdk_error_trap_push ();
162 widget->window = gdk_window_new (plug->socket_window,
163 &attributes, attributes_mask);
165 if (gdk_error_trap_pop ()) /* Uh-oh */
167 gdk_error_trap_push ();
168 gdk_window_destroy (widget->window);
170 gdk_error_trap_pop ();
171 widget->window = gdk_window_new (NULL, &attributes, attributes_mask);
174 ((GdkWindowPrivate *)widget->window)->window_type = GDK_WINDOW_TOPLEVEL;
175 gdk_window_set_user_data (widget->window, window);
177 widget->style = gtk_style_attach (widget->style, widget->window);
178 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
182 gtk_plug_key_press_event (GtkWidget *widget,
187 GtkDirectionType direction = 0;
190 g_return_val_if_fail (widget != NULL, FALSE);
191 g_return_val_if_fail (GTK_IS_PLUG (widget), FALSE);
192 g_return_val_if_fail (event != NULL, FALSE);
194 window = GTK_WINDOW (widget);
195 plug = GTK_PLUG (widget);
197 if (!GTK_WIDGET_HAS_FOCUS(widget))
199 gtk_plug_forward_key_press (plug, event);
204 if (window->focus_widget)
205 return_val = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
208 if (!return_val && gtk_window_check_accelerator (window, event->keyval, event->state))
214 switch (event->keyval)
217 if (window->focus_widget)
219 gtk_widget_activate (window->focus_widget);
225 if (window->default_widget &&
226 (!window->focus_widget ||
227 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
229 gtk_widget_activate (window->default_widget);
232 else if (window->focus_widget)
234 gtk_widget_activate (window->focus_widget);
243 switch (event->keyval)
246 direction = GTK_DIR_UP;
249 direction = GTK_DIR_DOWN;
252 direction = GTK_DIR_LEFT;
255 direction = GTK_DIR_RIGHT;
258 if (event->state & GDK_SHIFT_MASK)
259 direction = GTK_DIR_TAB_BACKWARD;
261 direction = GTK_DIR_TAB_FORWARD;
264 direction = GTK_DIR_UP; /* never reached, but makes compiler happy */
267 gtk_container_focus (GTK_CONTAINER (widget), direction);
269 if (!GTK_CONTAINER (window)->focus_child)
271 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
273 gdk_error_trap_push ();
274 #if GDK_WINDOWING == GDK_WINDOWING_X11
275 XSetInputFocus (GDK_DISPLAY (),
276 GDK_WINDOW_XWINDOW (plug->socket_window),
277 RevertToParent, event->time);
278 #elif GDK_WINDOWING == GDK_WINDOWING_WIN32
279 SetFocus (GDK_WINDOW_XWINDOW (plug->socket_window));
282 gdk_error_trap_pop ();
284 gtk_plug_forward_key_press (plug, event);
297 gtk_plug_forward_key_press (GtkPlug *plug, GdkEventKey *event)
299 #if GDK_WINDOWING == GDK_WINDOWING_X11
302 xevent.xkey.type = KeyPress;
303 xevent.xkey.display = GDK_WINDOW_XDISPLAY (GTK_WIDGET(plug)->window);
304 xevent.xkey.window = GDK_WINDOW_XWINDOW (plug->socket_window);
305 xevent.xkey.root = GDK_ROOT_WINDOW (); /* FIXME */
306 xevent.xkey.time = event->time;
307 /* FIXME, the following might cause big problems for
311 xevent.xkey.x_root = 0;
312 xevent.xkey.y_root = 0;
313 xevent.xkey.state = event->state;
314 xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(),
316 xevent.xkey.same_screen = TRUE; /* FIXME ? */
318 gdk_error_trap_push ();
319 XSendEvent (gdk_display,
320 GDK_WINDOW_XWINDOW (plug->socket_window),
321 False, NoEventMask, &xevent);
323 gdk_error_trap_pop ();
324 #elif GDK_WINDOWING == GDK_WINDOWING_WIN32
325 /* This is pretty bogus, and not tested at all. */
328 gboolean no_WM_CHAR = TRUE;
331 switch (event->keyval)
334 wParam = VK_CANCEL; break;
336 wParam = VK_BACK; break;
338 wParam = VK_TAB; break;
340 wParam = VK_CLEAR; break;
342 wParam = VK_RETURN; break;
344 wParam = VK_SHIFT; break;
346 wParam = VK_CONTROL; break;
348 wParam = VK_CONTROL; lParam |= 0x01000000; break;
350 wParam = VK_MENU; break;
352 wParam = VK_MENU; lParam |= 0x01000000; break;
354 wParam = VK_PAUSE; break;
356 wParam = VK_CAPITAL; break;
358 wParam = VK_ESCAPE; break;
360 wParam = VK_PRIOR; break;
362 wParam = VK_NEXT; break;
364 wParam = VK_END; break;
366 wParam = VK_HOME; break;
368 wParam = VK_LEFT; break;
370 wParam = VK_UP; break;
372 wParam = VK_RIGHT; break;
374 wParam = VK_DOWN; break;
376 wParam = VK_SELECT; break;
378 wParam = VK_PRINT; break;
380 wParam = VK_EXECUTE; break;
382 wParam = VK_INSERT; break;
384 wParam = VK_DELETE; break;
386 wParam = VK_HELP; break;
388 wParam = VK_NUMPAD0; break;
390 wParam = VK_NUMPAD1; break;
392 wParam = VK_NUMPAD2; break;
394 wParam = VK_NUMPAD3; break;
396 wParam = VK_NUMPAD4; break;
398 wParam = VK_NUMPAD5; break;
400 wParam = VK_NUMPAD6; break;
402 wParam = VK_NUMPAD7; break;
404 wParam = VK_NUMPAD8; break;
406 wParam = VK_NUMPAD9; break;
407 case GDK_KP_Multiply:
408 wParam = VK_MULTIPLY; break;
410 wParam = VK_ADD; break;
411 case GDK_KP_Separator:
412 wParam = VK_SEPARATOR; break;
413 case GDK_KP_Subtract:
414 wParam = VK_SUBTRACT; break;
416 wParam = VK_DECIMAL; break;
418 wParam = VK_DIVIDE; break;
420 wParam = VK_F1; break;
422 wParam = VK_F2; break;
424 wParam = VK_F3; break;
426 wParam = VK_F4; break;
428 wParam = VK_F5; break;
430 wParam = VK_F6; break;
432 wParam = VK_F7; break;
434 wParam = VK_F8; break;
436 wParam = VK_F9; break;
438 wParam = VK_F10; break;
440 wParam = VK_F11; break;
442 wParam = VK_F12; break;
444 wParam = VK_F13; break;
446 wParam = VK_F14; break;
448 wParam = VK_F15; break;
450 wParam = VK_F16; break;
452 wParam = event->keyval;
457 PostMessage (GDK_WINDOW_XWINDOW (plug->socket_window),
458 WM_KEYDOWN, wParam, lParam);
460 PostMessage (GDK_WINDOW_XWINDOW (plug->socket_window),
461 WM_CHAR, wParam, lParam);
462 PostMessage (GDK_WINDOW_XWINDOW (plug->socket_window),
463 WM_KEYUP, wParam, lParam);
467 /* Copied from Window, Ughh */
470 gtk_plug_focus_in_event (GtkWidget *widget,
471 GdkEventFocus *event)
474 GdkEventFocus fevent;
476 g_return_val_if_fail (widget != NULL, FALSE);
477 g_return_val_if_fail (GTK_IS_PLUG (widget), FALSE);
478 g_return_val_if_fail (event != NULL, FALSE);
480 /* It appears spurious focus in events can occur when
481 * the window is hidden. So we'll just check to see if
482 * the window is visible before actually handling the
485 if (GTK_WIDGET_VISIBLE (widget))
487 GTK_OBJECT_SET_FLAGS (widget, GTK_HAS_FOCUS);
488 window = GTK_WINDOW (widget);
489 if (window->focus_widget && !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
491 fevent.type = GDK_FOCUS_CHANGE;
492 fevent.window = window->focus_widget->window;
495 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
503 gtk_plug_focus_out_event (GtkWidget *widget,
504 GdkEventFocus *event)
507 GdkEventFocus fevent;
509 g_return_val_if_fail (widget != NULL, FALSE);
510 g_return_val_if_fail (GTK_IS_PLUG (widget), FALSE);
511 g_return_val_if_fail (event != NULL, FALSE);
513 GTK_OBJECT_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
515 window = GTK_WINDOW (widget);
517 if (window->focus_widget && GTK_WIDGET_HAS_FOCUS (window->focus_widget))
519 fevent.type = GDK_FOCUS_CHANGE;
520 fevent.window = window->focus_widget->window;
523 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
530 gtk_plug_set_focus (GtkWindow *window,
536 g_return_if_fail (window != NULL);
537 g_return_if_fail (GTK_IS_PLUG (window));
539 plug = GTK_PLUG (window);
541 if (focus && !GTK_WIDGET_CAN_FOCUS (focus))
544 if (window->focus_widget != focus)
546 if (window->focus_widget)
548 event.type = GDK_FOCUS_CHANGE;
549 event.window = window->focus_widget->window;
552 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
555 window->focus_widget = focus;
557 if (window->focus_widget)
559 event.type = GDK_FOCUS_CHANGE;
560 event.window = window->focus_widget->window;
563 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
567 /* Ask for focus from parent */
569 if (focus && !GTK_WIDGET_HAS_FOCUS(window))
571 #if GDK_WINDOWING == GDK_WINDOWING_X11
574 xevent.xfocus.type = FocusIn;
575 xevent.xfocus.display = GDK_WINDOW_XDISPLAY (GTK_WIDGET(plug)->window);
576 xevent.xfocus.window = GDK_WINDOW_XWINDOW (plug->socket_window);
577 xevent.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS;
578 xevent.xfocus.detail = FALSE; /* Don't force */
580 gdk_error_trap_push ();
581 XSendEvent (gdk_display,
582 GDK_WINDOW_XWINDOW (plug->socket_window),
583 False, NoEventMask, &xevent);
585 gdk_error_trap_pop ();
586 #elif GDK_WINDOWING == GDK_WINDOWING_WIN32
587 /* XXX Not implemented */