changeset 1509:02bfae9fd3e7

Rewrote part of _dw_get_frame_extents() on GTK2 to not use XIfEvent() since it will block if it never gets an event... even with our timeout code. Instead use a property notify GTK signal handler and wait up to a second for the notification using dw_main_iteration(). Also fixed a problem with dw_main_iteration() not updating the _dw_thread properly.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Wed, 28 Dec 2011 13:12:12 +0000
parents 9b2600034473
children 218c85939040
files gtk/dw.c
diffstat 1 files changed, 50 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/gtk/dw.c	Tue Dec 27 10:47:38 2011 +0000
+++ b/gtk/dw.c	Wed Dec 28 13:12:12 2011 +0000
@@ -2253,11 +2253,27 @@
  */
 void dw_main_iteration(void)
 {
-   gdk_threads_enter();
-   _dw_thread = pthread_self();
-   gtk_main_iteration();
-   _dw_thread = (pthread_t)-1;
-   gdk_threads_leave();
+   pthread_t orig = _dw_thread;
+   pthread_t curr = pthread_self();
+   
+   if(_dw_thread == (pthread_t)-1)
+   {
+      _dw_thread = curr;
+      gdk_threads_enter();
+   }
+   if(curr == _dw_thread && gtk_events_pending())
+      gtk_main_iteration();
+   else
+#ifdef __sun__
+      sched_yield();
+#else   
+      pthread_yield();
+#endif
+   if(orig == (pthread_t)-1)
+   {
+      _dw_thread = (pthread_t)-1;
+      gdk_threads_leave();
+   }
 }
 
 /*
@@ -3480,6 +3496,7 @@
       gtk_container_add(GTK_CONTAINER(tmp), table);
       gtk_object_set_data(GTK_OBJECT(tmp), "_dw_boxhandle", (gpointer)box);
       gtk_object_set_data(GTK_OBJECT(tmp), "_dw_table", (gpointer)table);
+      gtk_widget_add_events(GTK_WIDGET(tmp), GDK_PROPERTY_CHANGE_MASK);
    }
    gtk_object_set_data(GTK_OBJECT(tmp), "_dw_style", GINT_TO_POINTER(flStyle));
    DW_MUTEX_UNLOCK;
@@ -10136,19 +10153,15 @@
 }
 
 union extents_union { guchar **gu_extents; unsigned long **extents; };
-static Atom extents_atom = 0;
-static time_t extents_time = 0;
-
-static Bool property_notify_predicate(Display *xdisplay, XEvent *event, XPointer window_id)
-{
-   unsigned long *window = (unsigned long *)window_id;
-   time_t currtime = time(NULL);
-
-   /* If it is the event we are looking for... or if the timeout has expired */
-   if((event->xany.type == PropertyNotify && event->xany.window == *window && event->xproperty.atom == extents_atom) ||
-      (currtime - extents_time) > 1)
-      return True;
-   return False;
+static GdkAtom extents_atom = 0;
+static time_t extents_time;
+
+static gboolean _dw_property_notify(GtkWidget *window, GdkEventProperty* event, GdkWindow *gdkwindow)
+{
+   /* Check to see if we got a property change */
+   if(event->state == GDK_PROPERTY_NEW_VALUE && event->atom == extents_atom && event->window == gdkwindow)
+      extents_time = 0;
+   return FALSE;
 }
 
 /* Internal function to figure out the frame extents of an unmapped window */
@@ -10161,6 +10174,9 @@
       union extents_union eu;
       GdkAtom request_extents = gdk_atom_intern(request, FALSE);
 
+      if(!extents_atom)
+         extents_atom = gdk_atom_intern("_NET_FRAME_EXTENTS", FALSE);
+
       /* Set some rational defaults.. just in case */
       *vert = 28;
       *horz = 12;
@@ -10174,13 +10190,9 @@
          Window xroot_window = GDK_WINDOW_XID(root_window);
          Atom extents_request_atom = gdk_x11_get_xatom_by_name_for_display(display, request);
          unsigned long window_id = GDK_WINDOW_XID(GDK_DRAWABLE(window->window));
-         XEvent notify_xevent, xevent = {0};
-
-         if(!extents_atom)
-         {
-            const char *extents_name = "_NET_FRAME_EXTENTS";
-            extents_atom = gdk_x11_get_xatom_by_name_for_display(display, extents_name);
-         }
+         XEvent xevent = {0};
+         time_t currtime;
+         gulong connid;
 
          xevent.xclient.type = ClientMessage;
          xevent.xclient.message_type = extents_request_atom;
@@ -10193,22 +10205,28 @@
                    (SubstructureRedirectMask | SubstructureNotifyMask),
                    &xevent);
 
+         /* Connect a signal to look for the property change */
+         connid = gtk_signal_connect(GTK_OBJECT(window), "property_notify_event", GTK_SIGNAL_FUNC(_dw_property_notify), window->window);
+         
          /* Record the request time */
          time(&extents_time);
 
          /* Look for the property notify event */
-         XIfEvent(xdisplay, &notify_xevent, property_notify_predicate, (XPointer)&window_id);
-
-         /* If we didn't get the notification... put the event back onto the stack */
-         if(notify_xevent.xany.type != PropertyNotify || notify_xevent.xany.window != window_id
-            || notify_xevent.xproperty.atom != extents_atom)
-               XPutBackEvent(xdisplay, &notify_xevent);
+         do
+         {
+            dw_main_iteration();
+            time(&currtime);
+         }
+         while(currtime - extents_time < 2);
+         
+         /* Remove the signal handler now that we are done */
+         gtk_signal_disconnect(GTK_OBJECT(window), connid);
       }
 
       /* Attempt to retrieve window's frame extents. */
       eu.extents = &extents;
       if(gdk_property_get(window->window,
-                          gdk_atom_intern("_NET_FRAME_EXTENTS", FALSE),
+                          extents_atom,
                           gdk_atom_intern("CARDINAL", FALSE),
                           0, sizeof(unsigned long)*4, FALSE,
                           NULL, NULL, NULL, eu.gu_extents))