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/.
28 #include "gdkconfig.h"
29 #include "gdkprivate.h"
31 #if defined (GDK_WINDOWING_X11)
33 #elif defined (GDK_WINDOWING_WIN32)
34 #include "win32/gdkwin32.h"
35 #elif defined (GDK_WINDOWING_NANOX)
36 #include "nanox/gdkprivate-nanox.h"
37 #elif defined (GDK_WINDOWING_FB)
38 #include "linux-fb/gdkfb.h"
41 #include "gdk/gdkkeysyms.h"
44 static void gtk_plug_class_init (GtkPlugClass *klass);
45 static void gtk_plug_init (GtkPlug *plug);
47 static void gtk_plug_realize (GtkWidget *widget);
48 static void gtk_plug_unrealize (GtkWidget *widget);
49 static gint gtk_plug_key_press_event (GtkWidget *widget,
51 static void gtk_plug_forward_key_press (GtkPlug *plug, GdkEventKey *event);
52 static gint gtk_plug_focus_in_event (GtkWidget *widget, GdkEventFocus *event);
53 static gint gtk_plug_focus_out_event (GtkWidget *widget, GdkEventFocus *event);
54 static void gtk_plug_set_focus (GtkWindow *window,
58 #define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20
60 static GtkWindowClass *parent_class = NULL;
65 static GtkType plug_type = 0;
69 static const GTypeInfo plug_info =
71 sizeof (GtkPlugClass),
73 NULL, /* base_finalize */
74 (GClassInitFunc) gtk_plug_class_init,
75 NULL, /* class_finalize */
76 NULL, /* class_data */
79 (GInstanceInitFunc) gtk_plug_init,
82 plug_type = g_type_register_static (GTK_TYPE_WINDOW, "GtkPlug", &plug_info);
89 gtk_plug_class_init (GtkPlugClass *class)
91 GtkWidgetClass *widget_class;
92 GtkWindowClass *window_class;
94 widget_class = (GtkWidgetClass *)class;
95 window_class = (GtkWindowClass *)class;
97 parent_class = gtk_type_class (GTK_TYPE_WINDOW);
99 widget_class->realize = gtk_plug_realize;
100 widget_class->unrealize = gtk_plug_unrealize;
101 widget_class->key_press_event = gtk_plug_key_press_event;
102 widget_class->focus_in_event = gtk_plug_focus_in_event;
103 widget_class->focus_out_event = gtk_plug_focus_out_event;
105 window_class->set_focus = gtk_plug_set_focus;
109 gtk_plug_init (GtkPlug *plug)
113 window = GTK_WINDOW (plug);
115 window->type = GTK_WINDOW_TOPLEVEL;
116 window->auto_shrink = TRUE;
120 gtk_plug_construct (GtkPlug *plug, GdkNativeWindow socket_id)
122 plug->socket_window = gdk_window_lookup (socket_id);
123 plug->same_app = TRUE;
125 if (plug->socket_window == NULL)
127 plug->socket_window = gdk_window_foreign_new (socket_id);
128 plug->same_app = FALSE;
133 gtk_plug_new (GdkNativeWindow socket_id)
137 plug = GTK_PLUG (gtk_type_new (GTK_TYPE_PLUG));
138 gtk_plug_construct (plug, socket_id);
139 return GTK_WIDGET (plug);
143 gtk_plug_unrealize (GtkWidget *widget)
147 g_return_if_fail (widget != NULL);
148 g_return_if_fail (GTK_IS_PLUG (widget));
150 plug = GTK_PLUG (widget);
152 if (plug->socket_window != NULL)
154 gdk_window_set_user_data (plug->socket_window, NULL);
155 gdk_window_unref (plug->socket_window);
156 plug->socket_window = NULL;
159 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
160 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
164 gtk_plug_realize (GtkWidget *widget)
168 GdkWindowAttr attributes;
169 gint attributes_mask;
171 g_return_if_fail (widget != NULL);
172 g_return_if_fail (GTK_IS_PLUG (widget));
174 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
175 window = GTK_WINDOW (widget);
176 plug = GTK_PLUG (widget);
178 attributes.window_type = GDK_WINDOW_CHILD; /* XXX GDK_WINDOW_PLUG ? */
179 attributes.title = window->title;
180 attributes.wmclass_name = window->wmclass_name;
181 attributes.wmclass_class = window->wmclass_class;
182 attributes.width = widget->allocation.width;
183 attributes.height = widget->allocation.height;
184 attributes.wclass = GDK_INPUT_OUTPUT;
186 /* this isn't right - we should match our parent's visual/colormap.
187 * though that will require handling "foreign" colormaps */
188 attributes.visual = gtk_widget_get_visual (widget);
189 attributes.colormap = gtk_widget_get_colormap (widget);
190 attributes.event_mask = gtk_widget_get_events (widget);
191 attributes.event_mask |= (GDK_EXPOSURE_MASK |
193 GDK_ENTER_NOTIFY_MASK |
194 GDK_LEAVE_NOTIFY_MASK |
195 GDK_FOCUS_CHANGE_MASK |
198 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
199 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
200 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
202 gdk_error_trap_push ();
203 widget->window = gdk_window_new (plug->socket_window,
204 &attributes, attributes_mask);
206 if (gdk_error_trap_pop ()) /* Uh-oh */
208 gdk_error_trap_push ();
209 gdk_window_destroy (widget->window);
211 gdk_error_trap_pop ();
212 widget->window = gdk_window_new (NULL, &attributes, attributes_mask);
215 GDK_DRAWABLE_TYPE (window) = GDK_WINDOW_TOPLEVEL;
216 gdk_window_set_user_data (widget->window, window);
218 widget->style = gtk_style_attach (widget->style, widget->window);
219 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
223 gtk_plug_key_press_event (GtkWidget *widget,
228 GtkDirectionType direction = 0;
231 g_return_val_if_fail (widget != NULL, FALSE);
232 g_return_val_if_fail (GTK_IS_PLUG (widget), FALSE);
233 g_return_val_if_fail (event != NULL, FALSE);
235 window = GTK_WINDOW (widget);
236 plug = GTK_PLUG (widget);
238 if (!GTK_WIDGET_HAS_FOCUS(widget))
240 gtk_plug_forward_key_press (plug, event);
245 if (window->focus_widget)
246 return_val = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
249 if (!return_val && gtk_window_check_accelerator (window, event->keyval, event->state))
255 switch (event->keyval)
258 if (window->focus_widget)
260 gtk_widget_activate (window->focus_widget);
266 if (window->default_widget &&
267 (!window->focus_widget ||
268 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
270 gtk_widget_activate (window->default_widget);
273 else if (window->focus_widget)
275 gtk_widget_activate (window->focus_widget);
284 switch (event->keyval)
287 direction = GTK_DIR_UP;
290 direction = GTK_DIR_DOWN;
293 direction = GTK_DIR_LEFT;
296 direction = GTK_DIR_RIGHT;
299 if (event->state & GDK_SHIFT_MASK)
300 direction = GTK_DIR_TAB_BACKWARD;
302 direction = GTK_DIR_TAB_FORWARD;
305 direction = GTK_DIR_UP; /* never reached, but makes compiler happy */
308 gtk_container_focus (GTK_CONTAINER (widget), direction);
310 if (!GTK_CONTAINER (window)->focus_child)
312 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
314 gdk_error_trap_push ();
315 #ifdef GDK_WINDOWING_X11
316 XSetInputFocus (GDK_DISPLAY (),
317 GDK_WINDOW_XWINDOW (plug->socket_window),
318 RevertToParent, event->time);
319 #elif defined (GDK_WINDOWING_WIN32)
320 SetFocus (GDK_WINDOW_XWINDOW (plug->socket_window));
323 gdk_error_trap_pop ();
325 gtk_plug_forward_key_press (plug, event);
338 gtk_plug_forward_key_press (GtkPlug *plug, GdkEventKey *event)
340 #ifdef GDK_WINDOWING_X11
343 xevent.xkey.type = KeyPress;
344 xevent.xkey.display = GDK_WINDOW_XDISPLAY (GTK_WIDGET(plug)->window);
345 xevent.xkey.window = GDK_WINDOW_XWINDOW (plug->socket_window);
346 xevent.xkey.root = GDK_ROOT_WINDOW (); /* FIXME */
347 xevent.xkey.time = event->time;
348 /* FIXME, the following might cause big problems for
352 xevent.xkey.x_root = 0;
353 xevent.xkey.y_root = 0;
354 xevent.xkey.state = event->state;
355 xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(),
357 xevent.xkey.same_screen = TRUE; /* FIXME ? */
359 gdk_error_trap_push ();
360 XSendEvent (gdk_display,
361 GDK_WINDOW_XWINDOW (plug->socket_window),
362 False, NoEventMask, &xevent);
364 gdk_error_trap_pop ();
365 #elif defined (GDK_WINDOWING_WIN32)
366 /* This is pretty bogus, and not tested at all. */
369 gboolean no_WM_CHAR = TRUE;
372 switch (event->keyval)
375 wParam = VK_CANCEL; break;
377 wParam = VK_BACK; break;
379 wParam = VK_TAB; break;
381 wParam = VK_CLEAR; break;
383 wParam = VK_RETURN; break;
385 wParam = VK_SHIFT; break;
387 wParam = VK_CONTROL; break;
389 wParam = VK_CONTROL; lParam |= 0x01000000; break;
391 wParam = VK_MENU; break;
393 wParam = VK_MENU; lParam |= 0x01000000; break;
395 wParam = VK_PAUSE; break;
397 wParam = VK_CAPITAL; break;
399 wParam = VK_ESCAPE; break;
401 wParam = VK_PRIOR; break;
403 wParam = VK_NEXT; break;
405 wParam = VK_END; break;
407 wParam = VK_HOME; break;
409 wParam = VK_LEFT; break;
411 wParam = VK_UP; break;
413 wParam = VK_RIGHT; break;
415 wParam = VK_DOWN; break;
417 wParam = VK_SELECT; break;
419 wParam = VK_PRINT; break;
421 wParam = VK_EXECUTE; break;
423 wParam = VK_INSERT; break;
425 wParam = VK_DELETE; break;
427 wParam = VK_HELP; break;
429 wParam = VK_NUMPAD0; break;
431 wParam = VK_NUMPAD1; break;
433 wParam = VK_NUMPAD2; break;
435 wParam = VK_NUMPAD3; break;
437 wParam = VK_NUMPAD4; break;
439 wParam = VK_NUMPAD5; break;
441 wParam = VK_NUMPAD6; break;
443 wParam = VK_NUMPAD7; break;
445 wParam = VK_NUMPAD8; break;
447 wParam = VK_NUMPAD9; break;
448 case GDK_KP_Multiply:
449 wParam = VK_MULTIPLY; break;
451 wParam = VK_ADD; break;
452 case GDK_KP_Separator:
453 wParam = VK_SEPARATOR; break;
454 case GDK_KP_Subtract:
455 wParam = VK_SUBTRACT; break;
457 wParam = VK_DECIMAL; break;
459 wParam = VK_DIVIDE; break;
461 wParam = VK_F1; break;
463 wParam = VK_F2; break;
465 wParam = VK_F3; break;
467 wParam = VK_F4; break;
469 wParam = VK_F5; break;
471 wParam = VK_F6; break;
473 wParam = VK_F7; break;
475 wParam = VK_F8; break;
477 wParam = VK_F9; break;
479 wParam = VK_F10; break;
481 wParam = VK_F11; break;
483 wParam = VK_F12; break;
485 wParam = VK_F13; break;
487 wParam = VK_F14; break;
489 wParam = VK_F15; break;
491 wParam = VK_F16; break;
493 wParam = event->keyval;
498 PostMessage (GDK_WINDOW_XWINDOW (plug->socket_window),
499 WM_KEYDOWN, wParam, lParam);
501 PostMessage (GDK_WINDOW_XWINDOW (plug->socket_window),
502 WM_CHAR, wParam, lParam);
503 PostMessage (GDK_WINDOW_XWINDOW (plug->socket_window),
504 WM_KEYUP, wParam, lParam);
508 /* Copied from Window, Ughh */
511 gtk_plug_focus_in_event (GtkWidget *widget,
512 GdkEventFocus *event)
515 GdkEventFocus fevent;
517 g_return_val_if_fail (widget != NULL, FALSE);
518 g_return_val_if_fail (GTK_IS_PLUG (widget), FALSE);
519 g_return_val_if_fail (event != NULL, FALSE);
521 /* It appears spurious focus in events can occur when
522 * the window is hidden. So we'll just check to see if
523 * the window is visible before actually handling the
526 if (GTK_WIDGET_VISIBLE (widget))
528 GTK_OBJECT_SET_FLAGS (widget, GTK_HAS_FOCUS);
529 window = GTK_WINDOW (widget);
530 if (window->focus_widget && !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
532 fevent.type = GDK_FOCUS_CHANGE;
533 fevent.window = window->focus_widget->window;
536 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
544 gtk_plug_focus_out_event (GtkWidget *widget,
545 GdkEventFocus *event)
548 GdkEventFocus fevent;
550 g_return_val_if_fail (widget != NULL, FALSE);
551 g_return_val_if_fail (GTK_IS_PLUG (widget), FALSE);
552 g_return_val_if_fail (event != NULL, FALSE);
554 GTK_OBJECT_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
556 window = GTK_WINDOW (widget);
558 if (window->focus_widget && GTK_WIDGET_HAS_FOCUS (window->focus_widget))
560 fevent.type = GDK_FOCUS_CHANGE;
561 fevent.window = window->focus_widget->window;
564 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
571 gtk_plug_set_focus (GtkWindow *window,
577 g_return_if_fail (window != NULL);
578 g_return_if_fail (GTK_IS_PLUG (window));
580 plug = GTK_PLUG (window);
582 if (focus && !GTK_WIDGET_CAN_FOCUS (focus))
585 if (window->focus_widget != focus)
587 if (window->focus_widget)
589 event.type = GDK_FOCUS_CHANGE;
590 event.window = window->focus_widget->window;
593 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
596 window->focus_widget = focus;
598 if (window->focus_widget)
600 event.type = GDK_FOCUS_CHANGE;
601 event.window = window->focus_widget->window;
604 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
608 /* Ask for focus from parent */
610 if (focus && !GTK_WIDGET_HAS_FOCUS(window))
612 #ifdef GDK_WINDOWING_X11
615 xevent.xfocus.type = FocusIn;
616 xevent.xfocus.display = GDK_WINDOW_XDISPLAY (GTK_WIDGET(plug)->window);
617 xevent.xfocus.window = GDK_WINDOW_XWINDOW (plug->socket_window);
618 xevent.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS;
619 xevent.xfocus.detail = FALSE; /* Don't force */
621 gdk_error_trap_push ();
622 XSendEvent (gdk_display,
623 GDK_WINDOW_XWINDOW (plug->socket_window),
624 False, NoEventMask, &xevent);
626 gdk_error_trap_pop ();
627 #elif defined (GDK_WINDOWING_WIN32)
628 /* XXX Not implemented */