diff options
author | Gary Wong <gtw@gnu.org> | 2009-09-01 14:48:01 -0600 |
---|---|---|
committer | Gary Wong <gtw@gnu.org> | 2009-09-01 14:48:01 -0600 |
commit | 86c8dfa5b8017f7a940ed2e7333ee27a4af199a8 (patch) | |
tree | ba4a17ca0804df2c89eab84dd21508158cfad531 | |
parent | cf1b6f1e83b798ad54bdf6147dc3557220d7312a (diff) |
Replace passive_grab with pointer_demux (redirecting events on client side).
-rw-r--r-- | ChangeLog | 19 | ||||
-rw-r--r-- | button.c | 31 | ||||
-rw-r--r-- | frame.c | 18 | ||||
-rw-r--r-- | gwm.c | 39 | ||||
-rw-r--r-- | gwm.h | 10 | ||||
-rw-r--r-- | window-table.c | 3 |
6 files changed, 70 insertions, 50 deletions
@@ -1,10 +1,27 @@ +Tue Sep 1 14:40:15 2009 Gary Wong <gtw@gnu.org> + + * gwm.c (handle_events): Replace passive_grab with pointer_demux, + which redirects events on the client side. + (start_managing_window): Set initial event mask for + the frame button window, instead of an explicit GrabButton. + * button.c (button_button_press, button_button_release): Use + pointer_demux instead of GrabButton. + (button_enter_notify, button_leave_notify): Inspect event parameters + to determine which window is entered/left. + * frame.c (frame_button_press, frame_button_release): Use + pointer_demux instead of passive_grab. + (frame_motion_notify, frame_destroy_notify): Likewise. + (frame_enter_notify): Ignore events when pointer_demux is set. + * window-table.c (forget_window): Remove pointer_demux from + forgotten windows. + 2009-08-31 Gary Wong <gtw@gnu.org> * gwm.c (show_atom): Declare predefined_names[] as const. (show_error): Declare render_strings[] as const. (show_event): Declare event_names[] as const. (setup_display): Use auto storage class for wm_atom_str. - + 2009-08-31 Gary Wong <gtw@gnu.org> * gwm.c (start_managing_window): Create "border region" input-only @@ -69,12 +69,16 @@ static void set_button_active( struct gwm_window *window, int new ) { static void button_button_press( struct gwm_window *window, xcb_button_press_event_t *ev ) { - if( initial_press( ev ) ) - /* No buttons were pressed; grab initiates. */ - set_button_active( window, TRUE ); + if( !pointer_demux ) { + /* Initiate grab. */ + pointer_demux = window->w; - if( ev->detail == 3 && ( window->u.button.frame->u.frame.child-> - u.managed.protocols & PROTOCOL_DELETE_WINDOW ) ) + set_button_active( window, TRUE ); + } + + if( ( window->u.button.frame->u.frame.child->u.managed.protocols & + PROTOCOL_DELETE_WINDOW ) && ( ev->detail == 3 || + ( ev->state & XCB_BUTTON_MASK_3 ) ) ) /* Button 3 will kill the client, even if it supports WM_DELETE_WINDOW. Change to CURSOR_DESTROY to indicate the distinction. */ xcb_change_active_pointer_grab( c, cursors[ CURSOR_DESTROY ], @@ -87,6 +91,9 @@ static void button_button_press( struct gwm_window *window, static void button_button_release( struct gwm_window *window, xcb_button_release_event_t *ev ) { + if( !pointer_demux ) + return; + if( final_release( ev ) ) { /* Final button released; grab terminates. */ if( button_active ) { @@ -115,6 +122,8 @@ static void button_button_release( struct gwm_window *window, set_button_active( window, FALSE ); } + + pointer_demux = XCB_NONE; } else if( ev->detail == 3 && ( window->u.button.frame->u.frame.child-> u.managed.protocols & PROTOCOL_DELETE_WINDOW ) ) @@ -130,13 +139,21 @@ static void button_button_release( struct gwm_window *window, static void button_enter_notify( struct gwm_window *window, xcb_enter_notify_event_t *ev ) { - set_button_active( window, TRUE ); + if( !pointer_demux ) + return; + + if( ev->event == window->w ) + set_button_active( window, TRUE ); } static void button_leave_notify( struct gwm_window *window, xcb_leave_notify_event_t *ev ) { - set_button_active( window, FALSE ); + if( !pointer_demux ) + return; + + if( ev->event == window->w ) + set_button_active( window, FALSE ); } const event_handler button_handlers[] = { @@ -731,14 +731,10 @@ static void recalc_size( struct gwm_window *window, int x, int y, static void frame_button_press( struct gwm_window *window, xcb_button_press_event_t *ev ) { - if( !initial_press( ev ) ) + if( pointer_demux || ev->child == window->u.frame.child->w ) return; - if( ev->child == window->u.frame.child->w ) { - passive_grab = XCB_NONE; - - return; - } + pointer_demux = window->w; window_op = ( ev->detail > 1 ) == ( ( window->u.frame.decoration & DEC_TITLE ) && @@ -768,7 +764,7 @@ static void frame_motion_notify( struct gwm_window *window, uint32_t values[ 2 ]; - if( window->w != passive_grab ) + if( !pointer_demux ) return; /* Hint to the server that we're ready for further motion events. */ @@ -841,7 +837,7 @@ static void frame_motion_notify( struct gwm_window *window, static void frame_button_release( struct gwm_window *window, xcb_button_release_event_t *ev ) { - if( !final_release( ev ) || window->w != passive_grab ) + if( !final_release( ev ) || !pointer_demux ) return; if( moved ) @@ -859,13 +855,15 @@ static void frame_button_release( struct gwm_window *window, forget_window( feedback ); feedback = NULL; } + + pointer_demux = XCB_NONE; } static void frame_enter_notify( struct gwm_window *window, xcb_enter_notify_event_t *ev ) { uint32_t n; - if( focus_frame == window ) + if( pointer_demux || focus_frame == window ) /* We have the focus already -- probably an inferior change or ungrab. */ return; @@ -929,7 +927,7 @@ static void frame_enter_notify( struct gwm_window *window, static void frame_destroy_notify( struct gwm_window *window, xcb_destroy_notify_event_t *ev ) { - if( window->w != passive_grab ) + if( window->w != pointer_demux ) return; if( moved ) @@ -1141,7 +1141,9 @@ static void start_managing_window( struct gwm_window *window, values[ 1 ] = gwm_screens[ frame->screen ].pixels[ COL_BORDER ]; /* border pixel */ values[ 2 ] = TRUE; /* override redirect */ - values[ 3 ] = XCB_EVENT_MASK_EXPOSURE; + values[ 3 ] = XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | + XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_OWNER_GRAB_BUTTON; xcb_create_window( c, XCB_COPY_FROM_PARENT, button->w, frame->w, 2, 1, button_size( button, FALSE ), button_size( button, FALSE ), button_xb( button ), @@ -1149,12 +1151,6 @@ static void start_managing_window( struct gwm_window *window, XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK, values ); - xcb_grab_button( c, FALSE, button->w, XCB_EVENT_MASK_BUTTON_PRESS | - XCB_EVENT_MASK_BUTTON_RELEASE | - XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW, - XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, - XCB_NONE, XCB_BUTTON_INDEX_ANY, 0x8000 ); - if( frame->u.frame.decoration & DEC_TITLE ) xcb_map_window( c, button->w ); @@ -1441,8 +1437,7 @@ extern void generic_expose( struct gwm_window *window, queue_window_update( window, ev->x, ev->y, ev->width, ev->height, TRUE ); } -xcb_window_t passive_grab; /* the window which has the pointer automatically - grabbed via a button press, or XCB_NONE */ +xcb_window_t pointer_demux; static void handle_fake_change_property( unsigned int sequence, void *reply, xcb_generic_error_t *error, @@ -2219,23 +2214,27 @@ static void handle_events( void ) { break; case XCB_BUTTON_PRESS: - w = ( (xcb_button_press_event_t *) ev )->event; + w = pointer_demux ? + pointer_demux : ( (xcb_button_press_event_t *) ev )->event; latest_timestamp = ( (xcb_button_press_event_t *) ev )->time; break; case XCB_BUTTON_RELEASE: - w = ( (xcb_button_release_event_t *) ev )->event; + w = pointer_demux ? + pointer_demux : ( (xcb_button_release_event_t *) ev )->event; latest_timestamp = ( (xcb_button_release_event_t *) ev )->time; break; case XCB_MOTION_NOTIFY: - w = ( (xcb_motion_notify_event_t *) ev )->event; + w = pointer_demux ? + pointer_demux : ( (xcb_motion_notify_event_t *) ev )->event; latest_timestamp = ( (xcb_motion_notify_event_t *) ev )->time; break; case XCB_ENTER_NOTIFY: case XCB_LEAVE_NOTIFY: - w = ( (xcb_enter_notify_event_t *) ev )->event; + w = pointer_demux ? + pointer_demux : ( (xcb_enter_notify_event_t *) ev )->event; latest_timestamp = ( (xcb_enter_notify_event_t *) ev )->time; break; @@ -2358,12 +2357,6 @@ static void handle_events( void ) { warning( "handle_events: received reply message" ); break; - case XCB_BUTTON_PRESS: - if( initial_press( (xcb_button_press_event_t *) ev ) - && !passive_grab ) - passive_grab = w; - break; - case XCB_KEYMAP_NOTIFY: break; @@ -2393,14 +2386,6 @@ static void handle_events( void ) { handler( window, ev ); } - /* Global handling for events (after specific window handler). */ - switch( event_type ) { - case XCB_BUTTON_RELEASE: - if( final_release( (xcb_button_release_event_t *) ev ) ) - passive_grab = XCB_NONE; - break; - } - /* FIXME other features: - make override-redirect windows translucent - desktop menu & other key/pointer bindings @@ -306,17 +306,17 @@ extern void show_error( xcb_generic_error_t *error ); typedef void ( *event_handler )( struct gwm_window *window, xcb_generic_event_t *ev ); -/* Return TRUE iff an event is the only button pressed (and so would - initiate a passive grab). */ +/* Return TRUE iff an event is the only button pressed. */ extern CONST int initial_press( xcb_button_press_event_t *ev ); /* Return TRUE iff an event is the release of the last button (and so would terminate a passive grab). */ extern CONST int final_release( xcb_button_release_event_t *ev ); -/* The window which has the pointer automatically grabbed via a button - press, or XCB_NONE. */ -extern xcb_window_t passive_grab; +/* The window whose event handler(s) should be invoked for pointer events. + Unlike pointer grabs, this mechanism is implemented entirely on the + client side, and has no effect on the contents of events. */ +extern xcb_window_t pointer_demux; /* Install a window's colormap on a screen, or the default colormap if unspecified. */ diff --git a/window-table.c b/window-table.c index 1ab65f7..6970171 100644 --- a/window-table.c +++ b/window-table.c @@ -317,6 +317,9 @@ extern MALLOC struct gwm_window *add_window( xcb_window_t w ) { extern void forget_window( struct gwm_window *window ) { + if( pointer_demux == window->w ) + pointer_demux = XCB_NONE; + table_delete( &windows, window->w ); table_delete( &update_windows, window->w ); free( window ); |