comparison gtk/dw.c @ 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 308bfa8426db
children 218c85939040
comparison
equal deleted inserted replaced
1508:9b2600034473 1509:02bfae9fd3e7
2251 /* 2251 /*
2252 * Processes a single message iteration and returns. 2252 * Processes a single message iteration and returns.
2253 */ 2253 */
2254 void dw_main_iteration(void) 2254 void dw_main_iteration(void)
2255 { 2255 {
2256 gdk_threads_enter(); 2256 pthread_t orig = _dw_thread;
2257 _dw_thread = pthread_self(); 2257 pthread_t curr = pthread_self();
2258 gtk_main_iteration(); 2258
2259 _dw_thread = (pthread_t)-1; 2259 if(_dw_thread == (pthread_t)-1)
2260 gdk_threads_leave(); 2260 {
2261 _dw_thread = curr;
2262 gdk_threads_enter();
2263 }
2264 if(curr == _dw_thread && gtk_events_pending())
2265 gtk_main_iteration();
2266 else
2267 #ifdef __sun__
2268 sched_yield();
2269 #else
2270 pthread_yield();
2271 #endif
2272 if(orig == (pthread_t)-1)
2273 {
2274 _dw_thread = (pthread_t)-1;
2275 gdk_threads_leave();
2276 }
2261 } 2277 }
2262 2278
2263 /* 2279 /*
2264 * Free's memory allocated by dynamic windows. 2280 * Free's memory allocated by dynamic windows.
2265 * Parameters: 2281 * Parameters:
3478 3494
3479 gtk_table_attach(GTK_TABLE(table), box, 0, 1, 1, 2, GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0); 3495 gtk_table_attach(GTK_TABLE(table), box, 0, 1, 1, 2, GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
3480 gtk_container_add(GTK_CONTAINER(tmp), table); 3496 gtk_container_add(GTK_CONTAINER(tmp), table);
3481 gtk_object_set_data(GTK_OBJECT(tmp), "_dw_boxhandle", (gpointer)box); 3497 gtk_object_set_data(GTK_OBJECT(tmp), "_dw_boxhandle", (gpointer)box);
3482 gtk_object_set_data(GTK_OBJECT(tmp), "_dw_table", (gpointer)table); 3498 gtk_object_set_data(GTK_OBJECT(tmp), "_dw_table", (gpointer)table);
3499 gtk_widget_add_events(GTK_WIDGET(tmp), GDK_PROPERTY_CHANGE_MASK);
3483 } 3500 }
3484 gtk_object_set_data(GTK_OBJECT(tmp), "_dw_style", GINT_TO_POINTER(flStyle)); 3501 gtk_object_set_data(GTK_OBJECT(tmp), "_dw_style", GINT_TO_POINTER(flStyle));
3485 DW_MUTEX_UNLOCK; 3502 DW_MUTEX_UNLOCK;
3486 return tmp; 3503 return tmp;
3487 } 3504 }
10134 { 10151 {
10135 _dw_box_pack(box, item, 0, width, height, hsize, vsize, pad, "dw_box_pack_end()"); 10152 _dw_box_pack(box, item, 0, width, height, hsize, vsize, pad, "dw_box_pack_end()");
10136 } 10153 }
10137 10154
10138 union extents_union { guchar **gu_extents; unsigned long **extents; }; 10155 union extents_union { guchar **gu_extents; unsigned long **extents; };
10139 static Atom extents_atom = 0; 10156 static GdkAtom extents_atom = 0;
10140 static time_t extents_time = 0; 10157 static time_t extents_time;
10141 10158
10142 static Bool property_notify_predicate(Display *xdisplay, XEvent *event, XPointer window_id) 10159 static gboolean _dw_property_notify(GtkWidget *window, GdkEventProperty* event, GdkWindow *gdkwindow)
10143 { 10160 {
10144 unsigned long *window = (unsigned long *)window_id; 10161 /* Check to see if we got a property change */
10145 time_t currtime = time(NULL); 10162 if(event->state == GDK_PROPERTY_NEW_VALUE && event->atom == extents_atom && event->window == gdkwindow)
10146 10163 extents_time = 0;
10147 /* If it is the event we are looking for... or if the timeout has expired */ 10164 return FALSE;
10148 if((event->xany.type == PropertyNotify && event->xany.window == *window && event->xproperty.atom == extents_atom) ||
10149 (currtime - extents_time) > 1)
10150 return True;
10151 return False;
10152 } 10165 }
10153 10166
10154 /* Internal function to figure out the frame extents of an unmapped window */ 10167 /* Internal function to figure out the frame extents of an unmapped window */
10155 void _dw_get_frame_extents(GtkWidget *window, int *vert, int *horz) 10168 void _dw_get_frame_extents(GtkWidget *window, int *vert, int *horz)
10156 { 10169 {
10158 { 10171 {
10159 const char *request = "_NET_REQUEST_FRAME_EXTENTS"; 10172 const char *request = "_NET_REQUEST_FRAME_EXTENTS";
10160 unsigned long *extents = NULL; 10173 unsigned long *extents = NULL;
10161 union extents_union eu; 10174 union extents_union eu;
10162 GdkAtom request_extents = gdk_atom_intern(request, FALSE); 10175 GdkAtom request_extents = gdk_atom_intern(request, FALSE);
10176
10177 if(!extents_atom)
10178 extents_atom = gdk_atom_intern("_NET_FRAME_EXTENTS", FALSE);
10163 10179
10164 /* Set some rational defaults.. just in case */ 10180 /* Set some rational defaults.. just in case */
10165 *vert = 28; 10181 *vert = 28;
10166 *horz = 12; 10182 *horz = 12;
10167 10183
10172 Display *xdisplay = GDK_DISPLAY_XDISPLAY(display); 10188 Display *xdisplay = GDK_DISPLAY_XDISPLAY(display);
10173 GdkWindow *root_window = gdk_get_default_root_window(); 10189 GdkWindow *root_window = gdk_get_default_root_window();
10174 Window xroot_window = GDK_WINDOW_XID(root_window); 10190 Window xroot_window = GDK_WINDOW_XID(root_window);
10175 Atom extents_request_atom = gdk_x11_get_xatom_by_name_for_display(display, request); 10191 Atom extents_request_atom = gdk_x11_get_xatom_by_name_for_display(display, request);
10176 unsigned long window_id = GDK_WINDOW_XID(GDK_DRAWABLE(window->window)); 10192 unsigned long window_id = GDK_WINDOW_XID(GDK_DRAWABLE(window->window));
10177 XEvent notify_xevent, xevent = {0}; 10193 XEvent xevent = {0};
10178 10194 time_t currtime;
10179 if(!extents_atom) 10195 gulong connid;
10180 {
10181 const char *extents_name = "_NET_FRAME_EXTENTS";
10182 extents_atom = gdk_x11_get_xatom_by_name_for_display(display, extents_name);
10183 }
10184 10196
10185 xevent.xclient.type = ClientMessage; 10197 xevent.xclient.type = ClientMessage;
10186 xevent.xclient.message_type = extents_request_atom; 10198 xevent.xclient.message_type = extents_request_atom;
10187 xevent.xclient.display = xdisplay; 10199 xevent.xclient.display = xdisplay;
10188 xevent.xclient.window = window_id; 10200 xevent.xclient.window = window_id;
10191 /* Send the property request */ 10203 /* Send the property request */
10192 XSendEvent(xdisplay, xroot_window, False, 10204 XSendEvent(xdisplay, xroot_window, False,
10193 (SubstructureRedirectMask | SubstructureNotifyMask), 10205 (SubstructureRedirectMask | SubstructureNotifyMask),
10194 &xevent); 10206 &xevent);
10195 10207
10208 /* Connect a signal to look for the property change */
10209 connid = gtk_signal_connect(GTK_OBJECT(window), "property_notify_event", GTK_SIGNAL_FUNC(_dw_property_notify), window->window);
10210
10196 /* Record the request time */ 10211 /* Record the request time */
10197 time(&extents_time); 10212 time(&extents_time);
10198 10213
10199 /* Look for the property notify event */ 10214 /* Look for the property notify event */
10200 XIfEvent(xdisplay, &notify_xevent, property_notify_predicate, (XPointer)&window_id); 10215 do
10201 10216 {
10202 /* If we didn't get the notification... put the event back onto the stack */ 10217 dw_main_iteration();
10203 if(notify_xevent.xany.type != PropertyNotify || notify_xevent.xany.window != window_id 10218 time(&currtime);
10204 || notify_xevent.xproperty.atom != extents_atom) 10219 }
10205 XPutBackEvent(xdisplay, &notify_xevent); 10220 while(currtime - extents_time < 2);
10221
10222 /* Remove the signal handler now that we are done */
10223 gtk_signal_disconnect(GTK_OBJECT(window), connid);
10206 } 10224 }
10207 10225
10208 /* Attempt to retrieve window's frame extents. */ 10226 /* Attempt to retrieve window's frame extents. */
10209 eu.extents = &extents; 10227 eu.extents = &extents;
10210 if(gdk_property_get(window->window, 10228 if(gdk_property_get(window->window,
10211 gdk_atom_intern("_NET_FRAME_EXTENTS", FALSE), 10229 extents_atom,
10212 gdk_atom_intern("CARDINAL", FALSE), 10230 gdk_atom_intern("CARDINAL", FALSE),
10213 0, sizeof(unsigned long)*4, FALSE, 10231 0, sizeof(unsigned long)*4, FALSE,
10214 NULL, NULL, NULL, eu.gu_extents)) 10232 NULL, NULL, NULL, eu.gu_extents))
10215 { 10233 {
10216 *horz = extents[0] + extents[1]; 10234 *horz = extents[0] + extents[1];