comparison gtk3/dw.c @ 1510:218c85939040

Ported fixes in previous commit from GTK2 to GTK3... Also dw_main_sleep() and dW_main_iteration() needed more complicated locking code on Linux... Due to Linux's use of fast mutexes double locking will deadlock, and calling dw_main_*() from a DW API function or callback before starting dw_main() might cause a double lock... We need to only lock the mutex if it isn't already locked by this thread.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Wed, 28 Dec 2011 14:46:57 +0000
parents 308bfa8426db
children 010e1d916ee7
comparison
equal deleted inserted replaced
1509:02bfae9fd3e7 1510:218c85939040
1884 1884
1885 gettimeofday(&tv, NULL); 1885 gettimeofday(&tv, NULL);
1886 1886
1887 while(((tv.tv_sec - start.tv_sec)*1000) + ((tv.tv_usec - start.tv_usec)/1000) <= milliseconds) 1887 while(((tv.tv_sec - start.tv_sec)*1000) + ((tv.tv_usec - start.tv_usec)/1000) <= milliseconds)
1888 { 1888 {
1889 int _locked_by_me = FALSE;
1890
1889 if(orig == (pthread_t)-1) 1891 if(orig == (pthread_t)-1)
1890 { 1892 {
1891 gdk_threads_enter(); 1893 if(!pthread_getspecific(_dw_mutex_key))
1894 {
1895 gdk_threads_enter();
1896 pthread_setspecific(_dw_mutex_key, (void *)1);
1897 _locked_by_me = TRUE;
1898 }
1892 _dw_thread = curr; 1899 _dw_thread = curr;
1893 } 1900 }
1894 if(gtk_events_pending()) 1901 if(curr == _dw_thread && gtk_events_pending())
1895 gtk_main_iteration(); 1902 gtk_main_iteration();
1896 else 1903 else
1897 _dw_msleep(1); 1904 _dw_msleep(1);
1898 if(orig == (pthread_t)-1) 1905 if(orig == (pthread_t)-1)
1899 { 1906 {
1900 _dw_thread = orig; 1907 _dw_thread = orig;
1901 gdk_threads_leave(); 1908 if(_locked_by_me)
1909 {
1910 pthread_setspecific(_dw_mutex_key, NULL);
1911 gdk_threads_leave();
1912 }
1902 } 1913 }
1903 gettimeofday(&tv, NULL); 1914 gettimeofday(&tv, NULL);
1904 } 1915 }
1905 } 1916 }
1906 else 1917 else
1910 /* 1921 /*
1911 * Processes a single message iteration and returns. 1922 * Processes a single message iteration and returns.
1912 */ 1923 */
1913 void dw_main_iteration(void) 1924 void dw_main_iteration(void)
1914 { 1925 {
1915 gdk_threads_enter(); 1926 pthread_t orig = _dw_thread;
1916 _dw_thread = pthread_self(); 1927 pthread_t curr = pthread_self();
1917 gtk_main_iteration(); 1928 int _locked_by_me = FALSE;
1918 _dw_thread = (pthread_t)-1; 1929
1919 gdk_threads_leave(); 1930 if(_dw_thread == (pthread_t)-1)
1931 {
1932 if(!pthread_getspecific(_dw_mutex_key))
1933 {
1934 gdk_threads_enter();
1935 pthread_setspecific(_dw_mutex_key, (void *)1);
1936 _locked_by_me = TRUE;
1937 }
1938 _dw_thread = curr;
1939 }
1940 if(curr == _dw_thread && gtk_events_pending())
1941 gtk_main_iteration();
1942 else
1943 sched_yield();
1944 if(orig == (pthread_t)-1)
1945 {
1946 _dw_thread = orig;
1947 if(_locked_by_me)
1948 {
1949 pthread_setspecific(_dw_mutex_key, NULL);
1950 gdk_threads_leave();
1951 }
1952 }
1920 } 1953 }
1921 1954
1922 /* 1955 /*
1923 * Free's memory allocated by dynamic windows. 1956 * Free's memory allocated by dynamic windows.
1924 * Parameters: 1957 * Parameters:
2942 2975
2943 gtk_grid_attach(GTK_GRID(grid), box, 0, 1, 1, 1); 2976 gtk_grid_attach(GTK_GRID(grid), box, 0, 1, 1, 1);
2944 gtk_container_add(GTK_CONTAINER(tmp), grid); 2977 gtk_container_add(GTK_CONTAINER(tmp), grid);
2945 g_object_set_data(G_OBJECT(tmp), "_dw_boxhandle", (gpointer)box); 2978 g_object_set_data(G_OBJECT(tmp), "_dw_boxhandle", (gpointer)box);
2946 g_object_set_data(G_OBJECT(tmp), "_dw_grid", (gpointer)grid); 2979 g_object_set_data(G_OBJECT(tmp), "_dw_grid", (gpointer)grid);
2980 gtk_widget_add_events(GTK_WIDGET(tmp), GDK_PROPERTY_CHANGE_MASK);
2947 } 2981 }
2948 g_object_set_data(G_OBJECT(tmp), "_dw_style", GINT_TO_POINTER(flStyle)); 2982 g_object_set_data(G_OBJECT(tmp), "_dw_style", GINT_TO_POINTER(flStyle));
2949 DW_MUTEX_UNLOCK; 2983 DW_MUTEX_UNLOCK;
2950 return tmp; 2984 return tmp;
2951 } 2985 }
8509 _dw_box_pack(box, item, 0, width, height, hsize, vsize, pad, "dw_box_pack_end()"); 8543 _dw_box_pack(box, item, 0, width, height, hsize, vsize, pad, "dw_box_pack_end()");
8510 } 8544 }
8511 8545
8512 8546
8513 union extents_union { guchar **gu_extents; unsigned long **extents; }; 8547 union extents_union { guchar **gu_extents; unsigned long **extents; };
8514 static Atom extents_atom = 0; 8548 static GdkAtom extents_atom = 0;
8515 static time_t extents_time = 0; 8549 static time_t extents_time = 0;
8516 8550
8517 static Bool property_notify_predicate(Display *xdisplay, XEvent *event, XPointer window_id) 8551 static gboolean _dw_property_notify(GtkWidget *window, GdkEventProperty* event, GdkWindow *gdkwindow)
8518 { 8552 {
8519 unsigned long *window = (unsigned long *)window_id; 8553 /* Check to see if we got a property change */
8520 time_t currtime = time(NULL); 8554 if(event->state == GDK_PROPERTY_NEW_VALUE && event->atom == extents_atom && event->window == gdkwindow)
8521 8555 extents_time = 0;
8522 /* If it is the event we are looking for... or if the timeout has expired */ 8556 return FALSE;
8523 if((event->xany.type == PropertyNotify && event->xany.window == *window && event->xproperty.atom == extents_atom) ||
8524 (currtime - extents_time) > 1)
8525 return True;
8526 return False;
8527 } 8557 }
8528 8558
8529 /* Internal function to figure out the frame extents of an unmapped window */ 8559 /* Internal function to figure out the frame extents of an unmapped window */
8530 void _dw_get_frame_extents(GtkWidget *window, int *vert, int *horz) 8560 void _dw_get_frame_extents(GtkWidget *window, int *vert, int *horz)
8531 { 8561 {
8536 union extents_union eu; 8566 union extents_union eu;
8537 GdkAtom request_extents = gdk_atom_intern(request, FALSE); 8567 GdkAtom request_extents = gdk_atom_intern(request, FALSE);
8538 GdkWindow *gdkwindow = gtk_widget_get_window(window); 8568 GdkWindow *gdkwindow = gtk_widget_get_window(window);
8539 GdkDisplay *display = gtk_widget_get_display(window); 8569 GdkDisplay *display = gtk_widget_get_display(window);
8540 8570
8571 if(!extents_atom)
8572 extents_atom = gdk_atom_intern("_NET_FRAME_EXTENTS", FALSE);
8573
8541 /* Set some rational defaults.. just in case */ 8574 /* Set some rational defaults.. just in case */
8542 *vert = 28; 8575 *vert = 28;
8543 *horz = 12; 8576 *horz = 12;
8544 8577
8545 /* See if the current window manager supports _NET_REQUEST_FRAME_EXTENTS */ 8578 /* See if the current window manager supports _NET_REQUEST_FRAME_EXTENTS */
8548 Display *xdisplay = GDK_DISPLAY_XDISPLAY(display); 8581 Display *xdisplay = GDK_DISPLAY_XDISPLAY(display);
8549 GdkWindow *root_window = gdk_get_default_root_window(); 8582 GdkWindow *root_window = gdk_get_default_root_window();
8550 Window xroot_window = GDK_WINDOW_XID(root_window); 8583 Window xroot_window = GDK_WINDOW_XID(root_window);
8551 Atom extents_request_atom = gdk_x11_get_xatom_by_name_for_display(display, request); 8584 Atom extents_request_atom = gdk_x11_get_xatom_by_name_for_display(display, request);
8552 unsigned long window_id = GDK_WINDOW_XID(gdkwindow); 8585 unsigned long window_id = GDK_WINDOW_XID(gdkwindow);
8553 XEvent notify_xevent, xevent = {0}; 8586 XEvent xevent = {0};
8554 8587 time_t currtime;
8555 if(!extents_atom) 8588 gulong connid;
8556 {
8557 const char *extents_name = "_NET_FRAME_EXTENTS";
8558 extents_atom = gdk_x11_get_xatom_by_name_for_display(display, extents_name);
8559 }
8560 8589
8561 xevent.xclient.type = ClientMessage; 8590 xevent.xclient.type = ClientMessage;
8562 xevent.xclient.message_type = extents_request_atom; 8591 xevent.xclient.message_type = extents_request_atom;
8563 xevent.xclient.display = xdisplay; 8592 xevent.xclient.display = xdisplay;
8564 xevent.xclient.window = window_id; 8593 xevent.xclient.window = window_id;
8567 /* Send the property request */ 8596 /* Send the property request */
8568 XSendEvent(xdisplay, xroot_window, False, 8597 XSendEvent(xdisplay, xroot_window, False,
8569 (SubstructureRedirectMask | SubstructureNotifyMask), 8598 (SubstructureRedirectMask | SubstructureNotifyMask),
8570 &xevent); 8599 &xevent);
8571 8600
8601 /* Connect a signal to look for the property change */
8602 connid = g_signal_connect(G_OBJECT(window), "property_notify_event", G_CALLBACK(_dw_property_notify), gdkwindow);
8603
8572 /* Record the request time */ 8604 /* Record the request time */
8573 time(&extents_time); 8605 time(&extents_time);
8606
8607 /* Look for the property notify event */
8608 do
8609 {
8610 dw_main_iteration();
8611 time(&currtime);
8612 }
8613 while(currtime - extents_time < 2);
8574 8614
8575 /* Look for the property notify event */ 8615 /* Remove the signal handler now that we are done */
8576 XIfEvent(xdisplay, &notify_xevent, property_notify_predicate, (XPointer)&window_id); 8616 g_signal_handler_disconnect(G_OBJECT(window), connid);
8577
8578 /* If we didn't get the notification... put the event back onto the stack */
8579 if(notify_xevent.xany.type != PropertyNotify || notify_xevent.xany.window != window_id
8580 || notify_xevent.xproperty.atom != extents_atom)
8581 XPutBackEvent(xdisplay, &notify_xevent);
8582 } 8617 }
8583 8618
8584 /* Attempt to retrieve window's frame extents. */ 8619 /* Attempt to retrieve window's frame extents. */
8585 eu.extents = &extents; 8620 eu.extents = &extents;
8586 if(gdk_property_get(gdkwindow, 8621 if(gdk_property_get(gdkwindow,
8587 gdk_atom_intern("_NET_FRAME_EXTENTS", FALSE), 8622 extents_atom,
8588 gdk_atom_intern("CARDINAL", FALSE), 8623 gdk_atom_intern("CARDINAL", FALSE),
8589 0, sizeof(unsigned long)*4, FALSE, 8624 0, sizeof(unsigned long)*4, FALSE,
8590 NULL, NULL, NULL, eu.gu_extents)) 8625 NULL, NULL, NULL, eu.gu_extents))
8591 { 8626 {
8592 *horz = extents[0] + extents[1]; 8627 *horz = extents[0] + extents[1];