diff options
author | Gary Wong <gtw@gnu.org> | 2009-08-28 22:13:39 -0600 |
---|---|---|
committer | Gary Wong <gtw@gnu.org> | 2009-08-28 22:13:39 -0600 |
commit | ae6d0a2457caaff50aeacafd6a336a15bf70db90 (patch) | |
tree | 79a1768a3bc2b57fffcb2337cc50f01613db9939 | |
parent | 589adb7718321cda673c70a115d105a6e181a8d1 (diff) |
Properly handle events of Withdrawn clients, even if still reparented.
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | frame.c | 41 | ||||
-rw-r--r-- | frame.h | 2 | ||||
-rw-r--r-- | gwm.c | 40 | ||||
-rw-r--r-- | gwm.h | 2 | ||||
-rw-r--r-- | managed.c | 31 | ||||
-rw-r--r-- | managed.h | 5 | ||||
-rw-r--r-- | root.c | 35 |
8 files changed, 127 insertions, 39 deletions
@@ -1,5 +1,15 @@ 2009-08-28 Gary Wong <gtw@gnu.org> + * gwm.c (unmanage_window): Put the parent of the unmanaged child + into a childless state, so that lingering events can be handled + correctly. + (handle_destroy_window): New function. + (show_window): Annotate childless windows. + * managed.c (withdrawn_map_request, withdrawn_configure_request): New + functions. + +2009-08-28 Gary Wong <gtw@gnu.org> + * decorate-render.c (decorate_render_init): Cast FONT_NAME to (FcChar8 *). @@ -30,6 +30,7 @@ #include "gwm.h" #include "frame.h" +#include "managed.h" #include "window-table.h" #define EDGE_RESIST 8 @@ -750,3 +751,43 @@ event_handler frame_handlers[] = { NULL, /* (synthetic) */ NULL /* ShapeNotify */ }; + +event_handler childless_handlers[] = { + NULL, /* Error */ + NULL, /* Reply */ + NULL, /* KeyPress */ + NULL, /* KeyRelease */ + NULL, /* ButtonPress */ + NULL, /* ButtonRelease */ + NULL, /* MotionNotify */ + NULL, /* EnterNotify */ + NULL, /* LeaveNotify */ + NULL, /* FocusIn */ + NULL, /* FocusOut */ + NULL, /* KeymapNotify */ + NULL, /* Expose */ + NULL, /* GraphicsExpose */ + NULL, /* NoExposure */ + NULL, /* VisibilityNotify */ + NULL, /* CreateNotify */ + NULL, /* DestroyNotify */ + NULL, /* UnmapNotify */ + NULL, /* MapNotify */ + (event_handler) withdrawn_map_request, + NULL, /* ReparentNotify */ + NULL, /* ConfigureNotify */ + (event_handler) withdrawn_configure_request, + NULL, /* GravityNotify */ + NULL, /* ResizeRequest */ + NULL, /* CirculateNotify */ + NULL, /* CirculateRequest */ + NULL, /* PropertyNotify */ + NULL, /* SelectionClear */ + NULL, /* SelectionRequest */ + NULL, /* SelectionNotify */ + NULL, /* ColormapNotify */ + NULL, /* ClientMessage */ + NULL, /* MappingNotify */ + NULL, /* (synthetic) */ + NULL /* ShapeNotify */ +}; @@ -3,6 +3,6 @@ extern void synthetic_configure_notify( struct gwm_window *window ); -extern event_handler frame_handlers[]; +extern event_handler frame_handlers[], childless_handlers[]; #endif @@ -334,6 +334,11 @@ static void show_window( char *label, xcb_window_t w ) { fputs( "incomplete", stdout ); client = NULL; break; + + case WINDOW_CHILDLESS: + fputs( "childless", stdout ); + client = NULL; + break; } if( client ) @@ -1532,13 +1537,30 @@ extern void manage_window( xcb_window_t w, int map_request ) { nw->window->u.incomplete.sequence = seq; } +static void handle_destroy_window( unsigned int sequence, void *reply, + xcb_generic_error_t *error, + union callback_param cp ) { + + if( reply ) + free( reply ); + + if( error ) { + show_error( error ); + + free( error ); + } + + forget_window( cp.p ); +} + extern void unmanage_window( struct gwm_window *window ) { xcb_window_t w = window->w; struct gwm_window *frame = window->u.managed.frame; uint32_t border_width = window->u.managed.border_width; int x, y; - + union callback_param cp; + if( focus_frame == frame ) focus_frame = NULL; @@ -1567,15 +1589,23 @@ extern void unmanage_window( struct gwm_window *window ) { if( window->u.managed.state == STATE_ICONIC ) handle_error_reply( xcb_map_window_checked( c, w ), ERR_MASK_WINDOW ); - - xcb_destroy_window( c, frame->w ); + + cp.p = frame; + handle_async_reply( xcb_destroy_window_checked( c, frame->w ).sequence, + handle_destroy_window, cp ); if( window->u.managed.name ) free( window->u.managed.name ); forget_window( window ); forget_window( frame->u.frame.button ); - forget_window( frame ); + + /* We can't completely dismiss the frame window yet. Until our + DestroyWindow is handled, other events might still arrive for + it: in particular, we might see a MapRequest indicating a + transition back to the Normal state before the adoption by the + root has occurred. */ + frame->type = WINDOW_CHILDLESS; } extern void iconic_to_normal( struct gwm_window *window ) { @@ -1747,7 +1777,7 @@ static event_handler feedback_handlers[] = { static const event_handler *handlers[] = { root_handlers, managed_handlers, frame_handlers, button_handlers, - fake_handlers, feedback_handlers, NULL + fake_handlers, feedback_handlers, NULL, childless_handlers }; static void setup_display( void ) { @@ -189,7 +189,7 @@ struct gwm_window { int screen; enum _gwm_window_type { WINDOW_ROOT, WINDOW_MANAGED, WINDOW_FRAME, WINDOW_BUTTON, WINDOW_FAKE, - WINDOW_FEEDBACK, WINDOW_INCOMPLETE + WINDOW_FEEDBACK, WINDOW_INCOMPLETE, WINDOW_CHILDLESS } type; xcb_rectangle_t update; /* the area which needs updating */ int cleared; /* TRUE if the update area has already been cleared */ @@ -497,3 +497,34 @@ event_handler managed_handlers[] = { NULL /* ShapeNotify */ #endif }; + +extern void withdrawn_map_request( struct gwm_window *window, + xcb_map_request_event_t *ev ) { + + manage_window( ev->window, TRUE ); +} + +extern void withdrawn_configure_request( struct gwm_window *window, + xcb_configure_request_event_t *ev ) { + + int i = 0; + uint32_t values[ 7 ]; + + /* Configuring an unmanaged window -- just honour the request as is. */ + if( ev->value_mask & XCB_CONFIG_WINDOW_X ) + values[ i++ ] = ev->x; + if( ev->value_mask & XCB_CONFIG_WINDOW_Y ) + values[ i++ ] = ev->y; + if( ev->value_mask & XCB_CONFIG_WINDOW_WIDTH ) + values[ i++ ] = ev->width; + if( ev->value_mask & XCB_CONFIG_WINDOW_HEIGHT ) + values[ i++ ] = ev->height; + if( ev->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH ) + values[ i++ ] = ev->border_width; + if( ev->value_mask & XCB_CONFIG_WINDOW_SIBLING ) + values[ i++ ] = ev->sibling; + if( ev->value_mask & XCB_CONFIG_WINDOW_STACK_MODE ) + values[ i++ ] = ev->stack_mode; + + xcb_configure_window( c, ev->window, ev->value_mask, values ); +} @@ -10,4 +10,9 @@ extern void managed_property_change( struct gwm_window *window, int prop, extern event_handler managed_handlers[]; +extern void withdrawn_map_request( struct gwm_window *window, + xcb_map_request_event_t *ev ); +extern void withdrawn_configure_request( struct gwm_window *window, + xcb_configure_request_event_t *ev ); + #endif @@ -29,6 +29,7 @@ #include "actions.h" #include "keyboard.h" +#include "managed.h" #include "root.h" #include "window-table.h" @@ -93,36 +94,6 @@ static void root_enter_notify( struct gwm_window *window, install_window_colormap( window->screen, NULL, ev->time ); } -static void root_map_request( struct gwm_window *window, - xcb_map_request_event_t *ev ) { - - manage_window( ev->window, TRUE ); -} - -static void root_configure_request( struct gwm_window *window, - xcb_configure_request_event_t *ev ) { - int i = 0; - uint32_t values[ 7 ]; - - /* Configuring an unmanaged window -- just honour the request as is. */ - if( ev->value_mask & XCB_CONFIG_WINDOW_X ) - values[ i++ ] = ev->x; - if( ev->value_mask & XCB_CONFIG_WINDOW_Y ) - values[ i++ ] = ev->y; - if( ev->value_mask & XCB_CONFIG_WINDOW_WIDTH ) - values[ i++ ] = ev->width; - if( ev->value_mask & XCB_CONFIG_WINDOW_HEIGHT ) - values[ i++ ] = ev->height; - if( ev->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH ) - values[ i++ ] = ev->border_width; - if( ev->value_mask & XCB_CONFIG_WINDOW_SIBLING ) - values[ i++ ] = ev->sibling; - if( ev->value_mask & XCB_CONFIG_WINDOW_STACK_MODE ) - values[ i++ ] = ev->stack_mode; - - xcb_configure_window( c, ev->window, ev->value_mask, values ); -} - static void root_circulate_request( struct gwm_window *window, xcb_circulate_request_event_t *ev ) { @@ -203,10 +174,10 @@ event_handler root_handlers[] = { NULL, /* DestroyNotify */ NULL, /* UnmapNotify */ NULL, /* MapNotify */ - (event_handler) root_map_request, + (event_handler) withdrawn_map_request, NULL, /* ReparentNotify */ NULL, /* ConfigureNotify */ - (event_handler) root_configure_request, + (event_handler) withdrawn_configure_request, NULL, /* GravityNotify */ NULL, /* ResizeRequest */ NULL, /* CirculateNotify */ |