summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary Wong <gtw@gnu.org>2009-09-10 11:05:23 -0600
committerGary Wong <gtw@gnu.org>2009-09-10 11:05:23 -0600
commitd4d66325598a872099c946de60855f991c588142 (patch)
tree2fb00b50050fcdcdbeeee65cb31057674891184e
parent354413b0f7026c11f9e70b14f7e828d06a1f4772 (diff)
Be careful to catch all events when starting up and shutting down.
-rw-r--r--ChangeLog7
-rw-r--r--gwm.c58
-rw-r--r--root.c2
-rw-r--r--root.h3
4 files changed, 61 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 7f02d73..50ee58c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2009-09-10 Gary Wong <gtw@gnu.org>
+
+ * gwm.c (setup_display): Make sure the root event mask change is
+ atomic with the query of its children.
+ (shutdown_display): Process any remaining MapRequest,
+ ConfigureRequest or CirculateRequest events before closing.
+
2009-09-09 Gary Wong <gtw@gnu.org>
* actions.c (action_window_list_menu): Insert windows into the
diff --git a/gwm.c b/gwm.c
index cc1c69d..e744520 100644
--- a/gwm.c
+++ b/gwm.c
@@ -2016,15 +2016,22 @@ static void setup_display( void ) {
/* Send StructureNotify ClientMessage (ICCCM 2.0, section 2.8). */
msg.window = screens[ i ]->root;
msg.data.data32[ 1 ] = gwm_screens[ i ].wm_atom;
- /* FIXME Make the SubstructureNotify/SubstructureRedirect atomic
- with respect to the QueryTree below. */
xcb_send_event( c, FALSE, screens[ i ]->root,
XCB_EVENT_MASK_STRUCTURE_NOTIFY, (char *) &msg );
+ /* Querying the list of children of the root must be atomic with
+ respect to both our SubstructureNotify and SubstructureRedirect
+ event masks taking effect, so grab the server for a moment. */
+ xcb_grab_server( c );
+
cookies[ i ] =
xcb_change_window_attributes_checked( c, screens[ i ]->root,
XCB_CW_EVENT_MASK, &n );
+ tree_cookies[ i ] = xcb_query_tree( c, screens[ i ]->root );
+
+ xcb_ungrab_server( c );
+
values[ 0 ] = 0;
xcb_change_property( c, XCB_PROP_MODE_REPLACE, screens[ i ]->root,
atoms[ ATOM__NET_CURRENT_DESKTOP ], CARDINAL, 32,
@@ -2065,8 +2072,6 @@ static void setup_display( void ) {
xcb_change_property( c, XCB_PROP_MODE_REPLACE, screens[ i ]->root,
atoms[ ATOM__NET_WORKAREA ], CARDINAL, 32,
4, values );
-
- tree_cookies[ i ] = xcb_query_tree( c, screens[ i ]->root );
}
xcb_set_input_focus( c, XCB_INPUT_FOCUS_NONE, XCB_INPUT_FOCUS_POINTER_ROOT,
@@ -2405,7 +2410,8 @@ static void shutdown_display( void ) {
uint32_t n;
xcb_intern_atom_cookie_t cookie;
union callback_param cp;
-
+ xcb_generic_event_t *ev;
+
for( i = 0; i < num_screens; i++ ) {
xcb_window_t w = screens[ i ]->root | STACK_END;
@@ -2465,9 +2471,45 @@ static void shutdown_display( void ) {
sync_with_callback( cookie.sequence );
- /* FIXME We must handle any MapRequest (and perhaps ConfigureRequest
- and CirculateRequest) the server might have sent us before it
- changed our root event masks. */
+ /* We have now received all events that preceded our change to the
+ root event masks, and we won't be getting any more redirected
+ requests. Run through the event queue one last time, and handle
+ any that are still waiting. */
+ while( ( ev = xcb_poll_for_event( c ) ) ) {
+#if DEBUG
+ if( flag_debug && ev )
+ show_event( ev );
+#endif
+
+ switch( ev->response_type ) {
+ case 0: /* Error */
+ show_error( (xcb_generic_error_t *) ev );
+ break;
+
+ case XCB_MAP_REQUEST:
+ xcb_map_window( c, ( ( xcb_map_request_event_t *) ev )->window );
+ break;
+
+ case XCB_CONFIGURE_REQUEST:
+ withdrawn_configure_request( NULL,
+ (xcb_configure_request_event_t *) ev );
+ break;
+
+ case XCB_CIRCULATE_REQUEST:
+ root_circulate_request( NULL,
+ (xcb_circulate_request_event_t *) ev );
+ break;
+
+ default:
+ /* Do nothing. We're about to go away. Even client messages
+ such as WM_CHANGE_STATE should be ignored; all windows have
+ been forced into the Normal state whether they like it or
+ not. */
+ break;
+ }
+
+ free( ev );
+ }
xcb_disconnect( c );
#if DEBUG
diff --git a/root.c b/root.c
index 8043678..6f468c3 100644
--- a/root.c
+++ b/root.c
@@ -144,7 +144,7 @@ static void root_configure_notify( struct gwm_window *window,
ev->above_sibling : window->w | STACK_END );
}
-static void root_circulate_request( struct gwm_window *window,
+extern void root_circulate_request( struct gwm_window *window,
xcb_circulate_request_event_t *ev ) {
uint32_t value = ev->place == XCB_PLACE_ON_TOP ? XCB_STACK_MODE_ABOVE :
diff --git a/root.h b/root.h
index 6be2272..3102804 100644
--- a/root.h
+++ b/root.h
@@ -1,6 +1,9 @@
#ifndef ROOT_H
#define ROOT_H
+extern void root_circulate_request( struct gwm_window *window,
+ xcb_circulate_request_event_t *ev );
+
extern const event_handler root_handlers[];
#endif