summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary Wong <gtw@gnu.org>2009-08-28 22:13:39 -0600
committerGary Wong <gtw@gnu.org>2009-08-28 22:13:39 -0600
commitae6d0a2457caaff50aeacafd6a336a15bf70db90 (patch)
tree79a1768a3bc2b57fffcb2337cc50f01613db9939
parent589adb7718321cda673c70a115d105a6e181a8d1 (diff)
Properly handle events of Withdrawn clients, even if still reparented.
-rw-r--r--ChangeLog10
-rw-r--r--frame.c41
-rw-r--r--frame.h2
-rw-r--r--gwm.c40
-rw-r--r--gwm.h2
-rw-r--r--managed.c31
-rw-r--r--managed.h5
-rw-r--r--root.c35
8 files changed, 127 insertions, 39 deletions
diff --git a/ChangeLog b/ChangeLog
index 4a0ba54..35f463f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 *).
diff --git a/frame.c b/frame.c
index 5e92d58..e73b68f 100644
--- a/frame.c
+++ b/frame.c
@@ -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 */
+};
diff --git a/frame.h b/frame.h
index a46bb79..72c67a6 100644
--- a/frame.h
+++ b/frame.h
@@ -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
diff --git a/gwm.c b/gwm.c
index cb3a70e..ccd40d8 100644
--- a/gwm.c
+++ b/gwm.c
@@ -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 ) {
diff --git a/gwm.h b/gwm.h
index 4758c9b..5f02ade 100644
--- a/gwm.h
+++ b/gwm.h
@@ -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 */
diff --git a/managed.c b/managed.c
index 501ed62..43d6ea9 100644
--- a/managed.c
+++ b/managed.c
@@ -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 );
+}
diff --git a/managed.h b/managed.h
index a9f0911..d366ac8 100644
--- a/managed.h
+++ b/managed.h
@@ -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
diff --git a/root.c b/root.c
index a3d865d..39a09a9 100644
--- a/root.c
+++ b/root.c
@@ -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 */