Mercurial > dwindows
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, ¬ify_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, ¬ify_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]; |