diff --git a/include/xcb-internal.h b/include/xcb-internal.h index 75fd4b89..fcbbc1ba 100644 --- a/include/xcb-internal.h +++ b/include/xcb-internal.h @@ -61,6 +61,7 @@ struct _xcb_stuff xcb_timestamp_t last_timestamp; NkBindingsSeat *bindings_seat; gboolean mouse_seen; + xcb_window_t focus_revert; }; #endif diff --git a/include/xcb.h b/include/xcb.h index d811a2c7..a88d8d92 100644 --- a/include/xcb.h +++ b/include/xcb.h @@ -127,6 +127,9 @@ typedef struct _workarea */ int monitor_active ( workarea *mon ); +void rofi_xcb_set_input_focus(xcb_window_t w); +void rofi_xcb_revert_input_focus(void); + /** * Depth of visual */ diff --git a/source/view.c b/source/view.c index 0ebcd4bd..5e266405 100644 --- a/source/view.c +++ b/source/view.c @@ -1894,6 +1894,12 @@ RofiViewState *rofi_view_create ( Mode *sw, xcb_map_window ( xcb->connection, CacheState.main_window ); widget_queue_redraw ( WIDGET ( state->main_window ) ); xcb_flush ( xcb->connection ); + + /* When Override Redirect, the WM will not let us know we can take focus, so just steal it */ + if ( ( ( menu_flags & MENU_NORMAL_WINDOW ) == 0 ) ) { + rofi_xcb_set_input_focus(CacheState.main_window); + } + if ( xcb->sncontext != NULL ) { sn_launchee_context_complete ( xcb->sncontext ); } @@ -1946,6 +1952,7 @@ int rofi_view_error_dialog ( const char *msg, int markup ) void rofi_view_hide ( void ) { if ( CacheState.main_window != XCB_WINDOW_NONE ) { + rofi_xcb_revert_input_focus(); xcb_unmap_window ( xcb->connection, CacheState.main_window ); display_early_cleanup (); } diff --git a/source/xcb.c b/source/xcb.c index 3ad31a92..2067a106 100644 --- a/source/xcb.c +++ b/source/xcb.c @@ -1047,6 +1047,32 @@ static gboolean main_loop_x11_event_handler ( xcb_generic_event_t *ev, G_GNUC_UN return G_SOURCE_CONTINUE; } +void rofi_xcb_set_input_focus ( xcb_window_t w ) +{ + xcb_generic_error_t *error; + xcb_get_input_focus_reply_t *freply; + xcb_get_input_focus_cookie_t fcookie = xcb_get_input_focus ( xcb->connection ); + freply = xcb_get_input_focus_reply ( xcb->connection, fcookie, &error ); + if ( error != NULL ) { + g_warning ( "Could not get input focus (error %d), will revert focus to best effort", error->error_code ); + free ( error ); + xcb->focus_revert = 0; + } else { + xcb->focus_revert = freply->focus; + } + xcb_set_input_focus ( xcb->connection, XCB_INPUT_FOCUS_POINTER_ROOT, w, XCB_CURRENT_TIME ); + xcb_flush ( xcb->connection ); +} + +void rofi_xcb_revert_input_focus (void) +{ + if ( xcb->focus_revert == 0 ) + return; + + xcb_set_input_focus ( xcb->connection, XCB_INPUT_FOCUS_POINTER_ROOT, xcb->focus_revert, XCB_CURRENT_TIME ); + xcb_flush ( xcb->connection ); +} + static int take_pointer ( xcb_window_t w, int iters ) { int i = 0;