source: trunk/third/bonobo/bonobo/bonobo-socket.c @ 16855

Revision 16855, 20.9 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r16854, which included commits to RCS files with non-trunk default branches.
Line 
1/* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
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.
8 *
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.
13 *
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.
17 */
18
19/* By Owen Taylor <otaylor@gtk.org>              98/4/4 */
20
21/*
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/.
26 */
27
28#undef SOCKET_DEBUG
29
30#include <stdio.h>
31#include <gdk/gdkx.h>
32#include <gdk/gdkkeysyms.h>
33#include <gtk/gtkwindow.h>
34#include <gtk/gtksignal.h>
35#include <gtk/gtkdnd.h>
36#include <bonobo/bonobo-socket.h>
37#include <bonobo/bonobo-control-frame.h>
38
39
40
41struct _BonoboSocketPrivate {
42        /* The control on the other side which we use to gdk_flush() */
43        BonoboControlFrame *frame;
44
45        guint16 request_width;
46        guint16 request_height;
47        guint16 current_width;
48        guint16 current_height;
49
50        GdkWindow *plug_window;
51        guint same_app : 1;
52        guint have_size : 1;
53        guint need_map : 1;
54
55        /* Whether we gave the focus to the child through our own ::focus() */
56        guint gave_focus : 1;
57};
58
59/* Last timestamp we got from the X server, for use with XSetInputFocus() */
60static guint32 last_x_time_stamp = CurrentTime;
61
62/* Forward declararations */
63
64static void bonobo_socket_class_init               (BonoboSocketClass    *klass);
65static void bonobo_socket_init                     (BonoboSocket         *socket);
66static void bonobo_socket_finalize                 (GtkObject            *object);
67static void bonobo_socket_realize                  (GtkWidget        *widget);
68static void bonobo_socket_unrealize                (GtkWidget        *widget);
69static void bonobo_socket_size_request             (GtkWidget      *widget,
70                                                    GtkRequisition *requisition);
71static void bonobo_socket_size_allocate            (GtkWidget     *widget,
72                                                    GtkAllocation *allocation);
73static gint bonobo_socket_focus_in_event           (GtkWidget *widget,
74                                                    GdkEventFocus *event);
75static gint bonobo_socket_focus_out_event          (GtkWidget *widget,
76                                                    GdkEventFocus *event);
77static gint bonobo_socket_focus                    (GtkContainer *container,
78                                                    GtkDirectionType direction);
79
80static GdkFilterReturn bonobo_socket_filter_func   (GdkXEvent *gdk_xevent,
81                                                    GdkEvent *event,
82                                                    gpointer data);
83
84/* From Tk */
85#define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20
86
87/* Local data */
88
89static GtkContainerClass *parent_class = NULL;
90
91
92
93guint
94bonobo_socket_get_type ()
95{
96        static guint socket_type = 0;
97
98        if (!socket_type)
99        {
100                static const GtkTypeInfo socket_info =
101                {
102                        "BonoboSocket",
103                        sizeof (BonoboSocket),
104                        sizeof (BonoboSocketClass),
105                        (GtkClassInitFunc) bonobo_socket_class_init,
106                        (GtkObjectInitFunc) bonobo_socket_init,
107                        (GtkArgSetFunc) NULL,
108                        (GtkArgGetFunc) NULL
109                };
110
111                socket_type = gtk_type_unique (gtk_container_get_type (), &socket_info);
112        }
113
114        return socket_type;
115}
116
117static void
118bonobo_socket_class_init (BonoboSocketClass *class)
119{
120        GtkObjectClass *object_class;
121        GtkWidgetClass *widget_class;
122        GtkContainerClass *container_class;
123
124        object_class = (GtkObjectClass*) class;
125        widget_class = (GtkWidgetClass*) class;
126        container_class = (GtkContainerClass*) class;
127
128        parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
129
130        object_class->finalize = bonobo_socket_finalize;
131
132        widget_class->realize = bonobo_socket_realize;
133        widget_class->unrealize = bonobo_socket_unrealize;
134        widget_class->size_request = bonobo_socket_size_request;
135        widget_class->size_allocate = bonobo_socket_size_allocate;
136        widget_class->focus_in_event = bonobo_socket_focus_in_event;
137        widget_class->focus_out_event = bonobo_socket_focus_out_event;
138
139        container_class->focus = bonobo_socket_focus;
140}
141
142static void
143bonobo_socket_init (BonoboSocket *socket)
144{
145        BonoboSocketPrivate *priv;
146
147        priv = g_new (BonoboSocketPrivate, 1);
148        socket->priv = priv;
149
150        priv->frame = NULL;
151
152        priv->request_width = 0;
153        priv->request_height = 0;
154        priv->current_width = 0;
155        priv->current_height = 0;
156
157        priv->plug_window = NULL;
158        priv->same_app = FALSE;
159        priv->have_size = FALSE;
160        priv->need_map = FALSE;
161        priv->gave_focus = FALSE;
162}
163
164/* Destroy handler for the socket */
165static void
166bonobo_socket_finalize (GtkObject *object)
167{
168        BonoboSocket *socket;
169        BonoboSocketPrivate *priv;
170
171        g_return_if_fail (object != NULL);
172        g_return_if_fail (BONOBO_IS_SOCKET (object));
173
174        socket = BONOBO_SOCKET (object);
175        priv = socket->priv;
176
177        g_free (priv);
178        socket->priv = NULL;
179
180        if (GTK_OBJECT_CLASS (parent_class)->finalize)
181                (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
182}
183
184/**
185 * bonobo_socket_new:
186 *
187 * Create a new empty #BonoboSocket.
188 * Returns: A new #BonoboSocket.
189 */
190GtkWidget*
191bonobo_socket_new (void)
192{
193        BonoboSocket *socket;
194
195        socket = gtk_type_new (bonobo_socket_get_type ());
196
197        return GTK_WIDGET (socket);
198}
199
200/**
201 * bonobo_socket_steal:
202 * @socket: the #BonoboSocket.
203 * @id: the XID of an existing toplevel window.
204 *
205 * Reparents a pre-existing toplevel window into a
206 * #BonoboSocket.
207 */
208void
209bonobo_socket_steal (BonoboSocket *socket, guint32 id)
210{
211        BonoboSocketPrivate *priv;
212        GtkWidget *widget;
213
214        g_return_if_fail (socket != NULL);
215        g_return_if_fail (BONOBO_IS_SOCKET (socket));
216
217        priv = socket->priv;
218
219        widget = GTK_WIDGET (socket);
220
221        priv->plug_window = gdk_window_lookup (id);
222
223        gdk_error_trap_push ();
224
225        if (priv->plug_window && priv->plug_window->user_data) {
226                /*
227                  GtkWidget *child_widget;
228
229                  child_widget = GTK_WIDGET (priv->plug_window->user_data);
230                */
231
232                g_warning("Stealing from same app not yet implemented");
233
234                priv->same_app = TRUE;
235        } else {
236                priv->plug_window = gdk_window_foreign_new (id);
237                if (!priv->plug_window) {
238                        /* was deleted before we could get it */
239                        gdk_error_trap_pop ();
240                        return;
241                }
242
243                priv->same_app = FALSE;
244                priv->have_size = FALSE;
245
246                XSelectInput (GDK_DISPLAY (),
247                              GDK_WINDOW_XWINDOW (priv->plug_window),
248                              StructureNotifyMask | PropertyChangeMask);
249
250                gtk_widget_queue_resize (widget);
251        }
252
253        gdk_window_hide (priv->plug_window);
254        gdk_window_reparent (priv->plug_window, widget->window, 0, 0);
255
256        gdk_flush ();
257        gdk_error_trap_pop ();
258
259        priv->need_map = TRUE;
260}
261
262static void
263bonobo_socket_realize (GtkWidget *widget)
264{
265        BonoboSocket *socket;
266        GdkWindowAttr attributes;
267        gint attributes_mask;
268        XWindowAttributes xattrs;
269
270        g_return_if_fail (widget != NULL);
271        g_return_if_fail (BONOBO_IS_SOCKET (widget));
272
273        socket = BONOBO_SOCKET (widget);
274        GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
275
276        attributes.window_type = GDK_WINDOW_CHILD;
277        attributes.x = widget->allocation.x;
278        attributes.y = widget->allocation.y;
279        attributes.width = widget->allocation.width;
280        attributes.height = widget->allocation.height;
281        attributes.wclass = GDK_INPUT_OUTPUT;
282        attributes.visual = gtk_widget_get_visual (widget);
283        attributes.colormap = gtk_widget_get_colormap (widget);
284        attributes.event_mask = GDK_FOCUS_CHANGE_MASK;
285
286        attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
287
288        widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
289                                         &attributes, attributes_mask);
290        gdk_window_set_user_data (widget->window, socket);
291
292        widget->style = gtk_style_attach (widget->style, widget->window);
293        gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
294
295        XGetWindowAttributes (GDK_DISPLAY (),
296                              GDK_WINDOW_XWINDOW (widget->window),
297                              &xattrs);
298
299        XSelectInput (GDK_DISPLAY (),
300                      GDK_WINDOW_XWINDOW(widget->window),
301                      xattrs.your_event_mask |
302                      SubstructureNotifyMask | SubstructureRedirectMask);
303
304        gdk_window_add_filter (widget->window, bonobo_socket_filter_func, widget);
305
306        GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
307
308        bonobo_control_frame_sync_realize (socket->priv->frame);
309}
310
311static void
312bonobo_socket_unrealize (GtkWidget *widget)
313{
314        BonoboSocket *socket;
315        BonoboSocketPrivate *priv;
316
317        g_return_if_fail (widget != NULL);
318        g_return_if_fail (BONOBO_IS_SOCKET (widget));
319
320        socket = BONOBO_SOCKET (widget);
321        priv = socket->priv;
322
323        if (priv->plug_window) {
324                GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
325
326                if (toplevel && GTK_IS_WINDOW (toplevel))
327                        gtk_window_remove_embedded_xid (
328                                GTK_WINDOW (toplevel),
329                                GDK_WINDOW_XWINDOW (priv->plug_window));
330        }
331
332        if (GTK_WIDGET_CLASS (parent_class)->unrealize)
333                (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
334
335        bonobo_control_frame_sync_unrealize (priv->frame);
336}
337
338void
339bonobo_socket_set_control_frame (BonoboSocket       *socket,
340                                 BonoboControlFrame *frame)
341{
342        g_return_if_fail (BONOBO_IS_SOCKET (socket));
343
344        if (socket->priv)
345                socket->priv->frame = frame;
346}
347
348static void
349bonobo_socket_size_request (GtkWidget      *widget,
350                            GtkRequisition *requisition)
351{
352        BonoboSocket *socket;
353        BonoboSocketPrivate *priv;
354
355        g_return_if_fail (widget != NULL);
356        g_return_if_fail (BONOBO_IS_SOCKET (widget));
357        g_return_if_fail (requisition != NULL);
358
359        socket = BONOBO_SOCKET (widget);
360        priv = socket->priv;
361
362        if (!priv->have_size && priv->plug_window) {
363                XSizeHints hints;
364                long supplied;
365
366                gdk_error_trap_push ();
367
368                if (XGetWMNormalHints (GDK_DISPLAY (),
369                                       GDK_WINDOW_XWINDOW (priv->plug_window),
370                                       &hints, &supplied)) {
371                        /*
372                         * This is obsolete, according the X docs, but many
373                         * programs still use it.
374                         */
375                        if (hints.flags & (PSize | USSize)) {
376                                priv->request_width = hints.width;
377                                priv->request_height = hints.height;
378                        } else if (hints.flags & PMinSize) {
379                                priv->request_width = hints.min_width;
380                                priv->request_height = hints.min_height;
381                        } else if (hints.flags & PBaseSize) {
382                                priv->request_width = hints.base_width;
383                                priv->request_height = hints.base_height;
384                        }
385                }
386
387                priv->have_size = TRUE; /* don't check again? */
388                gdk_error_trap_pop ();
389        }
390
391        requisition->width = MAX (priv->request_width, 1);
392        requisition->height = MAX (priv->request_height, 1);
393}
394
395static void
396send_configure_event (BonoboSocket *socket)
397{
398        BonoboSocketPrivate *priv;
399        XEvent event;
400
401        priv = socket->priv;
402
403        g_return_if_fail (priv->plug_window != NULL);
404
405        event.xconfigure.type = ConfigureNotify;
406        event.xconfigure.display = gdk_display;
407
408        event.xconfigure.event = GDK_WINDOW_XWINDOW (priv->plug_window);
409        event.xconfigure.window = GDK_WINDOW_XWINDOW (priv->plug_window);
410
411        event.xconfigure.x = 0;
412        event.xconfigure.y = 0;
413        event.xconfigure.width = GTK_WIDGET (socket)->allocation.width;
414        event.xconfigure.height = GTK_WIDGET (socket)->allocation.height;
415
416        event.xconfigure.border_width = 0;
417        event.xconfigure.above = None;
418        event.xconfigure.override_redirect = False;
419
420        gdk_error_trap_push ();
421        XSendEvent (gdk_display,
422                    GDK_WINDOW_XWINDOW (priv->plug_window),
423                    False, NoEventMask, &event);
424        gdk_flush ();
425        gdk_error_trap_pop ();
426}
427
428static void
429bonobo_socket_size_allocate (GtkWidget     *widget,
430                             GtkAllocation *allocation)
431{
432        BonoboSocket *socket;
433        BonoboSocketPrivate *priv;
434
435        g_return_if_fail (widget != NULL);
436        g_return_if_fail (BONOBO_IS_SOCKET (widget));
437        g_return_if_fail (allocation != NULL);
438
439        socket = BONOBO_SOCKET (widget);
440        priv = socket->priv;
441
442        widget->allocation = *allocation;
443        if (GTK_WIDGET_REALIZED (widget)) {
444                gdk_window_move_resize (widget->window,
445                                        allocation->x, allocation->y,
446                                        allocation->width, allocation->height);
447
448                if (priv->plug_window) {
449                        gdk_error_trap_push ();
450
451                        if (!priv->need_map &&
452                            (allocation->width == priv->current_width) &&
453                            (allocation->height == priv->current_height)) {
454                                send_configure_event (socket);
455                                GTK_NOTE(PLUGSOCKET,
456                                         g_message ("BonoboSocket - allocated no change: %d %d",
457                                                    allocation->width, allocation->height));
458                        } else {
459                                gdk_window_move_resize (priv->plug_window,
460                                                        0, 0,
461                                                        allocation->width, allocation->height);
462                                GTK_NOTE (PLUGSOCKET,
463                                          g_message ("BonoboSocket - allocated: %d %d",
464                                                     allocation->width, allocation->height));
465                                priv->current_width = allocation->width;
466                                priv->current_height = allocation->height;
467                        }
468
469                        if (priv->need_map) {
470                                gdk_window_show (priv->plug_window);
471                                priv->need_map = FALSE;
472                        }
473
474                        gdk_flush ();
475                        gdk_error_trap_pop ();
476                }
477        }
478}
479
480/*
481 * Focus_in_event handler for the socket widget.  If we had previously given the
482 * focus to the child window, we give it the focus again.  This is so that
483 * unfocusing the toplevel window and focusing it back again will restore the
484 * focus to our embedded window.
485 */
486static gint
487bonobo_socket_focus_in_event (GtkWidget *widget, GdkEventFocus *event)
488{
489        BonoboSocket *socket;
490        BonoboSocketPrivate *priv;
491
492        g_return_val_if_fail (BONOBO_IS_SOCKET (widget), TRUE);
493
494        socket = BONOBO_SOCKET (widget);
495        g_return_val_if_fail (socket->priv != NULL, TRUE);
496
497        priv = socket->priv;
498
499        if (priv->gave_focus && priv->plug_window) {
500                gdk_error_trap_push ();
501                XSetInputFocus (GDK_DISPLAY (),
502                                GDK_WINDOW_XWINDOW (priv->plug_window),
503                                RevertToParent, CurrentTime);
504                gdk_flush();
505                gdk_error_trap_pop ();
506        }
507
508        return TRUE;
509}
510
511/* Focus_out_event handler for the socket widget */
512static gint
513bonobo_socket_focus_out_event (GtkWidget *widget, GdkEventFocus *event)
514{
515        BonoboSocket *socket;
516        BonoboSocketPrivate *priv;
517        GtkWidget *toplevel;
518
519        socket = BONOBO_SOCKET (widget);
520        priv = socket->priv;
521
522        toplevel = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
523
524        if (toplevel && GTK_WIDGET_MAPPED (toplevel)) {
525                /*
526                 * XSetInputFocus() will BadMatch if the window is not viewable;
527                 * that is why we put the test for MAPPED above.  Still, any of
528                 * its ancestors, namely the window manager frame, may not be
529                 * mapped, so we push an error trap anyways.
530                 */
531                gdk_error_trap_push ();
532                XSetInputFocus (GDK_DISPLAY (),
533                                GDK_WINDOW_XWINDOW (toplevel->window),
534                                RevertToParent, CurrentTime);
535                gdk_flush();
536                gdk_error_trap_pop ();
537        }
538
539        priv->gave_focus = FALSE;
540
541        return TRUE;
542}
543
544static void
545claim_focus (BonoboSocket *socket)
546{
547        BonoboSocketPrivate *priv;
548
549        priv = socket->priv;
550
551        priv->gave_focus = TRUE;
552
553        /* Oh, the trickery... */
554
555        GTK_WIDGET_SET_FLAGS (socket, GTK_CAN_FOCUS);
556        gtk_widget_grab_focus (GTK_WIDGET (socket));
557        GTK_WIDGET_UNSET_FLAGS (socket, GTK_CAN_FOCUS);
558
559        /*
560         * FIXME: we might grab the focus even if we don't have it as an
561         * app... (and see _focus_in())
562         */
563        if (priv->plug_window) {
564                gdk_error_trap_push ();
565                XSetInputFocus (GDK_DISPLAY (),
566                                GDK_WINDOW_XWINDOW (priv->plug_window),
567                                RevertToParent, CurrentTime);
568                gdk_flush ();
569                gdk_error_trap_pop ();
570        }
571}
572
573/*
574 * Focus handler for the socket widget.  We proxy the focus request to the child
575 * Bonobo control and then give it the actual input focus or reclaim it as
576 * appropriate.
577 */
578static gint
579bonobo_socket_focus (GtkContainer *container, GtkDirectionType direction)
580{
581        BonoboSocket *socket;
582        BonoboSocketPrivate *priv;
583
584        socket = BONOBO_SOCKET (container);
585        priv = socket->priv;
586
587        if (!priv->gave_focus && priv->plug_window) {
588                claim_focus (socket);
589                return bonobo_control_frame_focus_child (priv->frame, direction);
590        } else
591                return FALSE;
592}
593
594static void
595bonobo_socket_add_window (BonoboSocket *socket, guint32 xid)
596{
597        BonoboSocketPrivate *priv;
598
599        priv = socket->priv;
600
601        priv->plug_window = gdk_window_lookup (xid);
602        priv->same_app = TRUE;
603
604        if (!priv->plug_window) {
605                GtkWidget *toplevel;
606                GdkDragProtocol protocol;
607
608                priv->plug_window = gdk_window_foreign_new (xid);
609                if (!priv->plug_window) /* Already gone */
610                        return;
611
612                priv->same_app = FALSE;
613
614                gdk_error_trap_push ();
615                XSelectInput (GDK_DISPLAY (),
616                              GDK_WINDOW_XWINDOW (priv->plug_window),
617                              StructureNotifyMask | PropertyChangeMask);
618
619                if (gdk_drag_get_protocol (xid, &protocol))
620                        gtk_drag_dest_set_proxy (GTK_WIDGET (socket), priv->plug_window,
621                                                 protocol, TRUE);
622                gdk_flush ();
623                gdk_error_trap_pop ();
624
625                gdk_window_add_filter (priv->plug_window,
626                                       bonobo_socket_filter_func, socket);
627
628                /* Add a pointer to the socket on our toplevel window */
629
630                toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
631                if (toplevel && GTK_IS_WINDOW (toplevel))
632                        gtk_window_add_embedded_xid (GTK_WINDOW (toplevel), xid);
633        }
634}
635
636static GdkFilterReturn
637bonobo_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
638{
639        BonoboSocket *socket;
640        BonoboSocketPrivate *priv;
641        GtkWidget *widget;
642        XEvent *xevent;
643        GdkFilterReturn return_val;
644
645        socket = BONOBO_SOCKET (data);
646        priv = socket->priv;
647
648        widget = GTK_WIDGET (socket);
649        xevent = (XEvent *) gdk_xevent;
650
651        return_val = GDK_FILTER_CONTINUE;
652
653        switch (xevent->type) {
654        case KeyPress:
655        case KeyRelease:
656                last_x_time_stamp = xevent->xkey.time;
657                break;
658
659        case ButtonPress:
660        case ButtonRelease:
661                last_x_time_stamp = xevent->xbutton.time;
662                break;
663
664        case MotionNotify:
665                last_x_time_stamp = xevent->xmotion.time;
666                break;
667
668        case EnterNotify:
669        case LeaveNotify:
670                last_x_time_stamp = xevent->xcrossing.time;
671                break;
672
673        case PropertyNotify:
674                last_x_time_stamp = xevent->xproperty.time;
675                break;
676
677        default:
678                break;
679        }
680
681        switch (xevent->type) {
682        case CreateNotify: {
683                XCreateWindowEvent *xcwe = &xevent->xcreatewindow;
684
685                if (!priv->plug_window) {
686                        bonobo_socket_add_window (socket, xcwe->window);
687                        if (!priv->plug_window)
688                                break;
689
690                        gdk_error_trap_push ();
691                        gdk_window_move_resize (priv->plug_window,
692                                                0, 0,
693                                                widget->allocation.width,
694                                                widget->allocation.height);
695                        gdk_flush ();
696                        gdk_error_trap_pop ();
697
698                        priv->request_width = xcwe->width;
699                        priv->request_height = xcwe->height;
700                        priv->have_size = TRUE;
701
702                        GTK_NOTE (PLUGSOCKET,
703                                  g_message ("BonoboSocket - window created with size: %d %d",
704                                             priv->request_width,
705                                             priv->request_height));
706
707                        gtk_widget_queue_resize (widget);
708                }
709
710                return_val = GDK_FILTER_REMOVE;
711                break;
712        }
713
714        case ConfigureRequest: {
715                XConfigureRequestEvent *xcre = &xevent->xconfigurerequest;
716
717                if (!priv->plug_window)
718                        bonobo_socket_add_window (socket, xcre->window);
719
720                if (!priv->plug_window)
721                        break;
722
723                if (xcre->window == GDK_WINDOW_XWINDOW (priv->plug_window)) {
724                        if (xcre->value_mask & (CWWidth | CWHeight)) {
725                                priv->request_width = xcre->width;
726                                priv->request_height = xcre->height;
727                                priv->have_size = TRUE;
728
729                                GTK_NOTE (PLUGSOCKET,
730                                          g_message ("BonoboSocket - configure request: %d %d",
731                                                     priv->request_width,
732                                                     priv->request_height));
733
734                                gtk_widget_queue_resize (widget);
735                        } else if (xcre->value_mask & (CWX | CWY))
736                                send_configure_event (socket);
737
738                        /* Ignore stacking requests. */
739                        return_val = GDK_FILTER_REMOVE;
740                }
741
742                break;
743        }
744
745        case DestroyNotify: {
746                XDestroyWindowEvent *xdwe = &xevent->xdestroywindow;
747
748                if (priv->plug_window && (xdwe->window == GDK_WINDOW_XWINDOW (priv->plug_window))) {
749                        GtkWidget *toplevel;
750
751                        GTK_NOTE (PLUGSOCKET, g_message ("BonoboSocket - destroy notify"));
752
753                        toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
754                        if (toplevel && GTK_IS_WINDOW (toplevel))
755                                gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), xdwe->window);
756
757                        gdk_window_destroy_notify (priv->plug_window);
758                        gtk_widget_destroy (widget);
759
760                        priv->plug_window = NULL;
761
762                        return_val = GDK_FILTER_REMOVE;
763                }
764                break;
765        }
766
767        case FocusIn:
768                if (xevent->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS)
769                        claim_focus (socket);
770                else if (xevent->xfocus.detail == NotifyInferior) {
771#if 0
772                        GtkWidget *toplevel;
773                        toplevel = gtk_widget_get_ancestor (widget, gtk_window_get_type());
774
775                        if (toplevel)
776                                XSetInputFocus (GDK_DISPLAY (),
777                                                GDK_WINDOW_XWINDOW (toplevel->window),
778                                                RevertToParent, CurrentTime);
779#endif
780                }
781
782                return_val = GDK_FILTER_REMOVE;
783                break;
784
785        case FocusOut:
786                return_val = GDK_FILTER_REMOVE;
787                break;
788
789        case MapRequest:
790                if (!priv->plug_window)
791                        bonobo_socket_add_window (socket, xevent->xmaprequest.window);
792
793                if (!priv->plug_window)
794                        break;
795
796                if (xevent->xmaprequest.window == GDK_WINDOW_XWINDOW (priv->plug_window)) {
797                        GTK_NOTE (PLUGSOCKET, g_message ("BonoboSocket - Map Request"));
798
799                        gdk_error_trap_push ();
800                        gdk_window_show (priv->plug_window);
801                        gdk_flush ();
802                        gdk_error_trap_pop ();
803
804                        return_val = GDK_FILTER_REMOVE;
805                }
806                break;
807
808        case PropertyNotify:
809                if (!priv->plug_window)
810                        break;
811
812                if (xevent->xproperty.window == GDK_WINDOW_XWINDOW (priv->plug_window)) {
813                        GdkDragProtocol protocol;
814
815                        if ((xevent->xproperty.atom == gdk_atom_intern ("XdndAware", FALSE)) ||
816                            (xevent->xproperty.atom == gdk_atom_intern ("_MOTIF_DRAG_RECEIVER_INFO",
817                                                                        FALSE))) {
818                                gdk_error_trap_push ();
819                                if (gdk_drag_get_protocol (xevent->xproperty.window, &protocol))
820                                        gtk_drag_dest_set_proxy (GTK_WIDGET (socket),
821                                                                 priv->plug_window,
822                                                                 protocol, TRUE);
823                                gdk_flush ();
824                                gdk_error_trap_pop ();
825                        }
826                        return_val = GDK_FILTER_REMOVE;
827                }
828        }
829
830        return return_val;
831}
Note: See TracBrowser for help on using the repository browser.