]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtksocket-x11.c
Fix a tag mismatch in the docs
[~andy/gtk] / gtk / gtksocket-x11.c
index 0470a7c8960d16021d257e5d328afd11fa033c37..692e08345f41ca68cd490af06fee94d67799fea4 100644 (file)
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
-#include <config.h>
+#include "config.h"
 #include <string.h>
 
 #include "gdk/gdkkeysyms.h"
-#include "gtkalias.h"
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
-#include "gtkwindow.h"
+#include "gtkwindowprivate.h"
 #include "gtkplug.h"
 #include "gtkprivate.h"
 #include "gtksocket.h"
 #include "gtksocketprivate.h"
 #include "gtkdnd.h"
+#include "gtkdebug.h"
 
-#include "x11/gdkx.h"
+#include "gdk/x11/gdkx.h"
+#include "gdk/gdkprivate.h"
 
 #ifdef HAVE_XFIXES
 #include <X11/extensions/Xfixes.h>
 #endif
 
 #include "gtkxembed.h"
-#include "gtkalias.h"
 
 static gboolean xembed_get_info     (GdkWindow     *gdk_window,
                                     unsigned long *version,
@@ -58,22 +58,32 @@ static gboolean xembed_get_info     (GdkWindow     *gdk_window,
 GdkNativeWindow
 _gtk_socket_windowing_get_id (GtkSocket *socket)
 {
-  return GDK_WINDOW_XWINDOW (GTK_WIDGET (socket)->window);
+  return GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (socket)));
 }
 
 void
 _gtk_socket_windowing_realize_window (GtkSocket *socket)
 {
-  GdkWindow *window = GTK_WIDGET (socket)->window;
+  GdkWindow *window;
   XWindowAttributes xattrs;
 
+  window = gtk_widget_get_window (GTK_WIDGET (socket));
+
   XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
-                       GDK_WINDOW_XWINDOW (window),
+                       GDK_WINDOW_XID (window),
                        &xattrs);
 
+  /* Sooooo, it turns out that mozilla, as per the gtk2xt code selects
+     for input on the socket with a mask of 0x0fffff (for god knows why)
+     which includes ButtonPressMask causing a BadAccess if someone else
+     also selects for this. As per the client-side windows merge we always
+     normally selects for button press so we can emulate it on client
+     side children that selects for button press. However, we don't need
+     this for GtkSocket, so we unselect it here, fixing the crashes in
+     firefox. */
   XSelectInput (GDK_WINDOW_XDISPLAY (window),
-               GDK_WINDOW_XWINDOW (window), 
-               xattrs.your_event_mask | 
+               GDK_WINDOW_XID (window), 
+               (xattrs.your_event_mask & ~ButtonPressMask) |
                SubstructureNotifyMask | SubstructureRedirectMask);
 }
 
@@ -81,38 +91,39 @@ void
 _gtk_socket_windowing_end_embedding_toplevel (GtkSocket *socket)
 {
   gtk_window_remove_embedded_xid (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (socket))),
-                                 GDK_WINDOW_XWINDOW (socket->plug_window));
+                                 GDK_WINDOW_XID (socket->priv->plug_window));
 }
 
 void
 _gtk_socket_windowing_size_request (GtkSocket *socket)
 {
+  GtkSocketPrivate *private = socket->priv;
   XSizeHints hints;
   long supplied;
          
   gdk_error_trap_push ();
 
-  socket->request_width = 1;
-  socket->request_height = 1;
+  private->request_width = 1;
+  private->request_height = 1;
          
-  if (XGetWMNormalHints (GDK_WINDOW_XDISPLAY (socket->plug_window),
-                        GDK_WINDOW_XWINDOW (socket->plug_window),
+  if (XGetWMNormalHints (GDK_WINDOW_XDISPLAY (private->plug_window),
+                        GDK_WINDOW_XID (private->plug_window),
                         &hints, &supplied))
     {
       if (hints.flags & PMinSize)
        {
-         socket->request_width = hints.min_width;
-         socket->request_height = hints.min_height;
+         private->request_width = MAX (hints.min_width, 1);
+         private->request_height = MAX (hints.min_height, 1);
        }
       else if (hints.flags & PBaseSize)
        {
-         socket->request_width = hints.base_width;
-         socket->request_height = hints.base_height;
+         private->request_width = MAX (hints.base_width, 1);
+         private->request_height = MAX (hints.base_height, 1);
        }
     }
-  socket->have_size = TRUE;
+  private->have_size = TRUE;
   
-  gdk_error_trap_pop ();
+  gdk_error_trap_pop_ignored ();
 }
 
 void
@@ -120,30 +131,30 @@ _gtk_socket_windowing_send_key_event (GtkSocket *socket,
                                      GdkEvent  *gdk_event,
                                      gboolean   mask_key_presses)
 {
-  XEvent xevent;
-  GdkScreen *screen = gdk_drawable_get_screen (socket->plug_window);
-
-  xevent.xkey.type = (gdk_event->type == GDK_KEY_PRESS) ? KeyPress : KeyRelease;
-  xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window);
-  xevent.xkey.root = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
-  xevent.xkey.subwindow = None;
-  xevent.xkey.time = gdk_event->key.time;
-  xevent.xkey.x = 0;
-  xevent.xkey.y = 0;
-  xevent.xkey.x_root = 0;
-  xevent.xkey.y_root = 0;
-  xevent.xkey.state = gdk_event->key.state;
-  xevent.xkey.keycode = gdk_event->key.hardware_keycode;
-  xevent.xkey.same_screen = True;/* FIXME ? */
+  XKeyEvent xkey;
+  GdkScreen *screen = gdk_window_get_screen (socket->priv->plug_window);
+
+  memset (&xkey, 0, sizeof (xkey));
+  xkey.type = (gdk_event->type == GDK_KEY_PRESS) ? KeyPress : KeyRelease;
+  xkey.window = GDK_WINDOW_XID (socket->priv->plug_window);
+  xkey.root = GDK_WINDOW_XID (gdk_screen_get_root_window (screen));
+  xkey.subwindow = None;
+  xkey.time = gdk_event->key.time;
+  xkey.x = 0;
+  xkey.y = 0;
+  xkey.x_root = 0;
+  xkey.y_root = 0;
+  xkey.state = gdk_event->key.state;
+  xkey.keycode = gdk_event->key.hardware_keycode;
+  xkey.same_screen = True;/* FIXME ? */
 
   gdk_error_trap_push ();
-  XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
-             GDK_WINDOW_XWINDOW (socket->plug_window),
+  XSendEvent (GDK_WINDOW_XDISPLAY (socket->priv->plug_window),
+             GDK_WINDOW_XID (socket->priv->plug_window),
              False,
              (mask_key_presses ? KeyPressMask : NoEventMask),
-             &xevent);
-  gdk_display_sync (gdk_screen_get_display (screen));
-  gdk_error_trap_pop ();
+             (XEvent *)&xkey);
+  gdk_error_trap_pop_ignored ();
 }
 
 void
@@ -151,10 +162,10 @@ _gtk_socket_windowing_focus_change (GtkSocket *socket,
                                    gboolean   focus_in)
 {
   if (focus_in)
-    _gtk_xembed_send_focus_message (socket->plug_window,
+    _gtk_xembed_send_focus_message (socket->priv->plug_window,
                                    XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT);
   else
-    _gtk_xembed_send_message (socket->plug_window,
+    _gtk_xembed_send_message (socket->priv->plug_window,
                              XEMBED_FOCUS_OUT, 0, 0, 0);
 }
 
@@ -162,7 +173,7 @@ void
 _gtk_socket_windowing_update_active (GtkSocket *socket,
                                     gboolean   active)
 {
-  _gtk_xembed_send_message (socket->plug_window,
+  _gtk_xembed_send_message (socket->priv->plug_window,
                            active ? XEMBED_WINDOW_ACTIVATE : XEMBED_WINDOW_DEACTIVATE,
                            0, 0, 0);
 }
@@ -171,7 +182,7 @@ void
 _gtk_socket_windowing_update_modality (GtkSocket *socket,
                                       gboolean   modality)
 {
-  _gtk_xembed_send_message (socket->plug_window,
+  _gtk_xembed_send_message (socket->priv->plug_window,
                            modality ? XEMBED_MODALITY_ON : XEMBED_MODALITY_OFF,
                            0, 0, 0);
 }
@@ -196,52 +207,54 @@ _gtk_socket_windowing_focus (GtkSocket       *socket,
       break;
     }
   
-  _gtk_xembed_send_focus_message (socket->plug_window, XEMBED_FOCUS_IN, detail);
+  _gtk_xembed_send_focus_message (socket->priv->plug_window, XEMBED_FOCUS_IN, detail);
 }
 
 void
 _gtk_socket_windowing_send_configure_event (GtkSocket *socket)
 {
-  XEvent event;
+  GtkAllocation allocation;
+  XConfigureEvent xconfigure;
   gint x, y;
 
-  g_return_if_fail (socket->plug_window != NULL);
+  g_return_if_fail (socket->priv->plug_window != NULL);
 
-  event.xconfigure.type = ConfigureNotify;
+  memset (&xconfigure, 0, sizeof (xconfigure));
+  xconfigure.type = ConfigureNotify;
 
-  event.xconfigure.event = GDK_WINDOW_XWINDOW (socket->plug_window);
-  event.xconfigure.window = GDK_WINDOW_XWINDOW (socket->plug_window);
+  xconfigure.event = GDK_WINDOW_XID (socket->priv->plug_window);
+  xconfigure.window = GDK_WINDOW_XID (socket->priv->plug_window);
 
   /* The ICCCM says that synthetic events should have root relative
    * coordinates. We still aren't really ICCCM compliant, since
    * we don't send events when the real toplevel is moved.
    */
   gdk_error_trap_push ();
-  gdk_window_get_origin (socket->plug_window, &x, &y);
-  gdk_error_trap_pop ();
-                        
-  event.xconfigure.x = x;
-  event.xconfigure.y = y;
-  event.xconfigure.width = GTK_WIDGET(socket)->allocation.width;
-  event.xconfigure.height = GTK_WIDGET(socket)->allocation.height;
-
-  event.xconfigure.border_width = 0;
-  event.xconfigure.above = None;
-  event.xconfigure.override_redirect = False;
+  gdk_window_get_origin (socket->priv->plug_window, &x, &y);
+  gdk_error_trap_pop_ignored ();
+
+  gtk_widget_get_allocation (GTK_WIDGET(socket), &allocation);
+  xconfigure.x = x;
+  xconfigure.y = y;
+  xconfigure.width = allocation.width;
+  xconfigure.height = allocation.height;
+
+  xconfigure.border_width = 0;
+  xconfigure.above = None;
+  xconfigure.override_redirect = False;
 
   gdk_error_trap_push ();
-  XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
-             GDK_WINDOW_XWINDOW (socket->plug_window),
-             False, NoEventMask, &event);
-  gdk_display_sync (gtk_widget_get_display (GTK_WIDGET (socket)));
-  gdk_error_trap_pop ();
+  XSendEvent (GDK_WINDOW_XDISPLAY (socket->priv->plug_window),
+             GDK_WINDOW_XID (socket->priv->plug_window),
+             False, NoEventMask, (XEvent *)&xconfigure);
+  gdk_error_trap_pop_ignored ();
 }
 
 void
 _gtk_socket_windowing_select_plug_window_input (GtkSocket *socket)
 {
   XSelectInput (GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (socket))),
-               GDK_WINDOW_XWINDOW (socket->plug_window),
+               GDK_WINDOW_XID (socket->priv->plug_window),
                StructureNotifyMask | PropertyChangeMask);
 }
 
@@ -250,34 +263,38 @@ _gtk_socket_windowing_embed_get_info (GtkSocket *socket)
 {
   unsigned long version;
   unsigned long flags;
+  GtkSocketPrivate *private = socket->priv;
 
-  socket->xembed_version = -1;
-  if (xembed_get_info (socket->plug_window, &version, &flags))
+  private->xembed_version = -1;
+  if (xembed_get_info (private->plug_window, &version, &flags))
     {
-      socket->xembed_version = MIN (GTK_XEMBED_PROTOCOL_VERSION, version);
-      socket->is_mapped = (flags & XEMBED_MAPPED) != 0;
+      private->xembed_version = MIN (GTK_XEMBED_PROTOCOL_VERSION, version);
+      private->is_mapped = (flags & XEMBED_MAPPED) != 0;
     }
   else
     {
       /* FIXME, we should probably actually check the state before we started */
-      socket->is_mapped = TRUE;
+      private->is_mapped = TRUE;
     }
 }
 
 void
 _gtk_socket_windowing_embed_notify (GtkSocket *socket)
 {
+  GtkSocketPrivate *private = socket->priv;
 #ifdef HAVE_XFIXES
   GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (socket));
 
+  gdk_error_trap_push ();
   XFixesChangeSaveSet (GDK_DISPLAY_XDISPLAY (display),
-                      GDK_WINDOW_XWINDOW (socket->plug_window),
+                      GDK_WINDOW_XID (private->plug_window),
                       SetModeInsert, SaveSetRoot, SaveSetUnmap);
+  gdk_error_trap_pop_ignored ();
 #endif
-  _gtk_xembed_send_message (socket->plug_window,
+  _gtk_xembed_send_message (private->plug_window,
                            XEMBED_EMBEDDED_NOTIFY, 0,
-                           GDK_WINDOW_XWINDOW (GTK_WIDGET (socket)->window),
-                           socket->xembed_version);
+                           GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (socket))),
+                           private->xembed_version);
 }
 
 static gboolean
@@ -285,7 +302,7 @@ xembed_get_info (GdkWindow     *window,
                 unsigned long *version,
                 unsigned long *flags)
 {
-  GdkDisplay *display = gdk_drawable_get_display (window);
+  GdkDisplay *display = gdk_window_get_display (window);
   Atom xembed_info_atom = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO");
   Atom type;
   int format;
@@ -294,14 +311,14 @@ xembed_get_info (GdkWindow     *window,
   unsigned long *data_long;
   int status;
   
-  gdk_error_trap_push();
+  gdk_error_trap_push ();
   status = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
-                              GDK_WINDOW_XWINDOW (window),
+                              GDK_WINDOW_XID (window),
                               xembed_info_atom,
                               0, 2, False,
                               xembed_info_atom, &type, &format,
                               &nitems, &bytes_after, &data);
-  gdk_error_trap_pop();
+  gdk_error_trap_pop_ignored ();
 
   if (status != Success)
     return FALSE;              /* Window vanished? */
@@ -405,14 +422,16 @@ _gtk_socket_windowing_filter_func (GdkXEvent *gdk_xevent,
   GtkWidget *widget;
   GdkDisplay *display;
   XEvent *xevent;
+  GtkSocketPrivate *private;
 
   GdkFilterReturn return_val;
-  
+
   socket = GTK_SOCKET (data);
+  private = socket->priv;
 
   return_val = GDK_FILTER_CONTINUE;
 
-  if (socket->plug_widget)
+  if (private->plug_widget)
     return return_val;
 
   widget = GTK_WIDGET (socket);
@@ -441,11 +460,11 @@ _gtk_socket_windowing_filter_func (GdkXEvent *gdk_xevent,
       {
        XCreateWindowEvent *xcwe = &xevent->xcreatewindow;
 
-       if (!socket->plug_window)
+       if (!private->plug_window)
          {
            _gtk_socket_add_window (socket, xcwe->window, FALSE);
 
-           if (socket->plug_window)
+           if (private->plug_window)
              {
                GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - window created"));
              }
@@ -460,19 +479,17 @@ _gtk_socket_windowing_filter_func (GdkXEvent *gdk_xevent,
       {
        XConfigureRequestEvent *xcre = &xevent->xconfigurerequest;
        
-       if (!socket->plug_window)
+       if (!private->plug_window)
          _gtk_socket_add_window (socket, xcre->window, FALSE);
        
-       if (socket->plug_window)
+       if (private->plug_window)
          {
-           GtkSocketPrivate *private = _gtk_socket_get_private (socket);
-           
            if (xcre->value_mask & (CWWidth | CWHeight))
              {
                GTK_NOTE (PLUGSOCKET,
                          g_message ("GtkSocket - configure request: %d %d",
-                                    socket->request_width,
-                                    socket->request_height));
+                                    private->request_width,
+                                    private->request_height));
 
                private->resize_count++;
                gtk_widget_queue_resize (widget);
@@ -495,17 +512,17 @@ _gtk_socket_windowing_filter_func (GdkXEvent *gdk_xevent,
        /* Note that we get destroy notifies both from SubstructureNotify on
         * our window and StructureNotify on socket->plug_window
         */
-       if (socket->plug_window && (xdwe->window == GDK_WINDOW_XWINDOW (socket->plug_window)))
+       if (private->plug_window && (xdwe->window == GDK_WINDOW_XID (private->plug_window)))
          {
            gboolean result;
            
            GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - destroy notify"));
            
-           gdk_window_destroy_notify (socket->plug_window);
+           gdk_window_destroy_notify (private->plug_window);
            _gtk_socket_end_embedding (socket);
 
            g_object_ref (widget);
-           g_signal_emit_by_name (widget, "plug_removed", &result);
+           g_signal_emit_by_name (widget, "plug-removed", &result);
            if (!result)
              gtk_widget_destroy (widget);
            g_object_unref (widget);
@@ -526,12 +543,12 @@ _gtk_socket_windowing_filter_func (GdkXEvent *gdk_xevent,
       return_val = GDK_FILTER_REMOVE;
       break;
     case MapRequest:
-      if (!socket->plug_window)
+      if (!private->plug_window)
        {
          _gtk_socket_add_window (socket, xevent->xmaprequest.window, FALSE);
        }
        
-      if (socket->plug_window)
+      if (private->plug_window)
        {
          GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - Map Request"));
 
@@ -540,15 +557,15 @@ _gtk_socket_windowing_filter_func (GdkXEvent *gdk_xevent,
        }
       break;
     case PropertyNotify:
-      if (socket->plug_window &&
-         xevent->xproperty.window == GDK_WINDOW_XWINDOW (socket->plug_window))
+      if (private->plug_window &&
+         xevent->xproperty.window == GDK_WINDOW_XID (private->plug_window))
        {
          GdkDragProtocol protocol;
 
          if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_NORMAL_HINTS"))
            {
              GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - received PropertyNotify for plug's WM_NORMAL_HINTS"));
-             socket->have_size = FALSE;
+             private->have_size = FALSE;
              gtk_widget_queue_resize (widget);
              return_val = GDK_FILTER_REMOVE;
            }
@@ -560,20 +577,19 @@ _gtk_socket_windowing_filter_func (GdkXEvent *gdk_xevent,
                                                     xevent->xproperty.window,
                                                     &protocol))
                gtk_drag_dest_set_proxy (GTK_WIDGET (socket),
-                                        socket->plug_window,
+                                        private->plug_window,
                                         protocol, TRUE);
 
-             gdk_display_sync (display);
-             gdk_error_trap_pop ();
+             gdk_error_trap_pop_ignored ();
              return_val = GDK_FILTER_REMOVE;
            }
          else if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO"))
            {
              unsigned long flags;
              
-             if (xembed_get_info (socket->plug_window, NULL, &flags))
+             if (xembed_get_info (private->plug_window, NULL, &flags))
                {
-                 gboolean was_mapped = socket->is_mapped;
+                 gboolean was_mapped = private->is_mapped;
                  gboolean is_mapped = (flags & XEMBED_MAPPED) != 0;
 
                  if (was_mapped != is_mapped)
@@ -583,9 +599,8 @@ _gtk_socket_windowing_filter_func (GdkXEvent *gdk_xevent,
                      else
                        {
                          gdk_error_trap_push ();
-                         gdk_window_show (socket->plug_window);
-                         gdk_flush ();
-                         gdk_error_trap_pop ();
+                         gdk_window_show (private->plug_window);
+                         gdk_error_trap_pop_ignored ();
                          
                          _gtk_socket_unmap_notify (socket);
                        }
@@ -597,26 +612,49 @@ _gtk_socket_windowing_filter_func (GdkXEvent *gdk_xevent,
       break;
     case ReparentNotify:
       {
+        GdkWindow *window;
        XReparentEvent *xre = &xevent->xreparent;
 
-       GTK_NOTE (PLUGSOCKET, g_message ("GtkPlug: ReparentNotify received\n"));
-       if (!socket->plug_window && xre->parent == GDK_WINDOW_XWINDOW (widget->window))
+        window = gtk_widget_get_window (widget);
+
+       GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - ReparentNotify received"));
+       if (!private->plug_window &&
+            xre->parent == GDK_WINDOW_XID (window))
          {
            _gtk_socket_add_window (socket, xre->window, FALSE);
            
-           if (socket->plug_window)
+           if (private->plug_window)
              {
                GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - window reparented"));
              }
            
            return_val = GDK_FILTER_REMOVE;
          }
-       
+        else
+          {
+            if (private->plug_window &&
+                xre->window == GDK_WINDOW_XID (private->plug_window) &&
+                xre->parent != GDK_WINDOW_XID (window))
+              {
+                gboolean result;
+
+                _gtk_socket_end_embedding (socket);
+
+                g_object_ref (widget);
+                g_signal_emit_by_name (widget, "plug-removed", &result);
+                if (!result)
+                  gtk_widget_destroy (widget);
+                g_object_unref (widget);
+
+                return_val = GDK_FILTER_REMOVE;
+              }
+          }
+
        break;
       }
     case UnmapNotify:
-      if (socket->plug_window &&
-         xevent->xunmap.window == GDK_WINDOW_XWINDOW (socket->plug_window))
+      if (private->plug_window &&
+         xevent->xunmap.window == GDK_WINDOW_XID (private->plug_window))
        {
          GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - Unmap notify"));