# HG changeset patch # User bsmith@81767d24-ef19-dc11-ae90-00e081727c95 # Date 1325077932 0 # Node ID 02bfae9fd3e7106df3d5ecb1c75e400faee475d6 # Parent 9b26000344739e57f9d75406884143587cfff963 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. diff -r 9b2600034473 -r 02bfae9fd3e7 gtk/dw.c --- 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, ¬ify_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, ¬ify_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))