mirror of
https://github.com/davatorium/rofi.git
synced 2025-01-27 15:25:24 -05:00
Grab keyboard from X mainloop.
Should fix small 'jerk' when starting from keybinding and having to wait for keyboard grab.
This commit is contained in:
parent
de9e78bb57
commit
f40e072802
1 changed files with 223 additions and 194 deletions
|
@ -469,17 +469,38 @@ static int pointer_get ( Display *display, Window root, int *x, int *y )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int take_keyboard ( Window w )
|
typedef enum _MainLoopEvent
|
||||||
{
|
{
|
||||||
int i;
|
ML_XEVENT,
|
||||||
|
ML_TIMEOUT
|
||||||
|
} MainLoopEvent;
|
||||||
|
static inline MainLoopEvent wait_for_xevent_or_timeout ( Display *display, int x11_fd )
|
||||||
|
{
|
||||||
|
// Check if events are pending.
|
||||||
|
if ( XPending ( display ) ) {
|
||||||
|
return ML_XEVENT;
|
||||||
|
}
|
||||||
|
// If not, wait for timeout.
|
||||||
|
struct timeval tv;
|
||||||
|
fd_set in_fds;
|
||||||
|
// Create a File Description Set containing x11_fd
|
||||||
|
FD_ZERO ( &in_fds );
|
||||||
|
FD_SET ( x11_fd, &in_fds );
|
||||||
|
|
||||||
for ( i = 0; i < 1000; i++ ) {
|
// Set our timer. 200ms is a decent delay
|
||||||
if ( XGrabKeyboard ( display, w, True, GrabModeAsync, GrabModeAsync, CurrentTime ) == GrabSuccess ) {
|
tv.tv_usec = 200000;
|
||||||
return 1;
|
tv.tv_sec = 0;
|
||||||
|
// Wait for X Event or a Timer
|
||||||
|
if ( select ( x11_fd + 1, &in_fds, 0, 0, &tv ) == 0 ) {
|
||||||
|
return ML_TIMEOUT;
|
||||||
|
}
|
||||||
|
return ML_XEVENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct timespec rsl = { 0, 100000L };
|
static int take_keyboard ( Display *display, Window w )
|
||||||
nanosleep ( &rsl, NULL );
|
{
|
||||||
|
if ( XGrabKeyboard ( display, w, True, GrabModeAsync, GrabModeAsync, CurrentTime ) == GrabSuccess ) {
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1724,7 +1745,6 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
|
||||||
XMapRaised ( display, main_window );
|
XMapRaised ( display, main_window );
|
||||||
|
|
||||||
// if grabbing keyboard failed, fall through
|
// if grabbing keyboard failed, fall through
|
||||||
if ( take_keyboard ( main_window ) ) {
|
|
||||||
state.selected = 0;
|
state.selected = 0;
|
||||||
// The cast to unsigned in here is valid, we checked if selected_line > 0.
|
// The cast to unsigned in here is valid, we checked if selected_line > 0.
|
||||||
// So its maximum range is 0-2³¹, well within the num_lines range.
|
// So its maximum range is 0-2³¹, well within the num_lines range.
|
||||||
|
@ -1736,6 +1756,7 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
|
||||||
menu_refilter ( &state, lines, mmc, mmc_data, sorting, config.case_sensitive );
|
menu_refilter ( &state, lines, mmc, mmc_data, sorting, config.case_sensitive );
|
||||||
|
|
||||||
int x11_fd = ConnectionNumber ( display );
|
int x11_fd = ConnectionNumber ( display );
|
||||||
|
int has_keyboard = take_keyboard ( display, main_window );
|
||||||
while ( !state.quit ) {
|
while ( !state.quit ) {
|
||||||
// Update if requested.
|
// Update if requested.
|
||||||
if ( state.update ) {
|
if ( state.update ) {
|
||||||
|
@ -1745,33 +1766,33 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
|
||||||
// Wait for event.
|
// Wait for event.
|
||||||
XEvent ev;
|
XEvent ev;
|
||||||
// Only use lazy mode above 5000 lines.
|
// Only use lazy mode above 5000 lines.
|
||||||
if ( state.num_lines > config.lazy_filter_limit ) {
|
// Or if we still need to get window.
|
||||||
// No message waiting, update been set, do timeout trick.
|
MainLoopEvent mle = ML_XEVENT;
|
||||||
if ( state.refilter && !XPending ( display ) ) {
|
// If we are in lazy mode, or trying to grab keyboard, go into timeout.
|
||||||
// This implements a lazy re-filtering.
|
// Otherwise continue like we had an XEvent (and we will block on fetching this event).
|
||||||
struct timeval tv;
|
if ( !has_keyboard || ( state.refilter && state.num_lines > config.lazy_filter_limit ) ) {
|
||||||
fd_set in_fds;
|
mle = wait_for_xevent_or_timeout ( display, x11_fd );
|
||||||
// Create a File Description Set containing x11_fd
|
// Whatever happened, try to get keyboard.
|
||||||
FD_ZERO ( &in_fds );
|
has_keyboard = take_keyboard ( display, main_window );
|
||||||
FD_SET ( x11_fd, &in_fds );
|
|
||||||
|
|
||||||
// Set our timer. 200ms is a decent delay
|
|
||||||
tv.tv_usec = 200000;
|
|
||||||
tv.tv_sec = 0;
|
|
||||||
// Wait for X Event or a Timer
|
|
||||||
if ( select ( x11_fd + 1, &in_fds, 0, 0, &tv ) == 0 ) {
|
|
||||||
// Timer expired, update.
|
|
||||||
menu_refilter ( &state, lines, mmc, mmc_data, sorting, config.case_sensitive );
|
|
||||||
menu_update ( &state );
|
|
||||||
}
|
}
|
||||||
}
|
// If not in lazy mode, refilter.
|
||||||
}
|
if ( state.num_lines <= config.lazy_filter_limit ) {
|
||||||
else {
|
|
||||||
if ( state.refilter ) {
|
if ( state.refilter ) {
|
||||||
menu_refilter ( &state, lines, mmc, mmc_data, sorting, config.case_sensitive );
|
menu_refilter ( &state, lines, mmc, mmc_data, sorting, config.case_sensitive );
|
||||||
menu_update ( &state );
|
menu_update ( &state );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if ( mle == ML_TIMEOUT ) {
|
||||||
|
// When timeout (and in lazy filter mode)
|
||||||
|
// We refilter then loop back and wait for Xevent.
|
||||||
|
if ( state.refilter ) {
|
||||||
|
menu_refilter ( &state, lines, mmc, mmc_data, sorting, config.case_sensitive );
|
||||||
|
menu_update ( &state );
|
||||||
|
}
|
||||||
|
// Return like normal.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Get next event. (might block)
|
||||||
XNextEvent ( display, &ev );
|
XNextEvent ( display, &ev );
|
||||||
|
|
||||||
// Handle event.
|
// Handle event.
|
||||||
|
@ -1905,7 +1926,6 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
|
||||||
}
|
}
|
||||||
|
|
||||||
release_keyboard ();
|
release_keyboard ();
|
||||||
}
|
|
||||||
// Update input string.
|
// Update input string.
|
||||||
g_free ( *input );
|
g_free ( *input );
|
||||||
*input = g_strdup ( state.text->text );
|
*input = g_strdup ( state.text->text );
|
||||||
|
@ -1974,7 +1994,8 @@ void error_dialog ( char *msg )
|
||||||
// Display it.
|
// Display it.
|
||||||
XMapRaised ( display, main_window );
|
XMapRaised ( display, main_window );
|
||||||
|
|
||||||
if ( take_keyboard ( main_window ) ) {
|
int x11_fd = ConnectionNumber ( display );
|
||||||
|
int has_keyboard = take_keyboard ( display, main_window );
|
||||||
while ( !state.quit ) {
|
while ( !state.quit ) {
|
||||||
// Update if requested.
|
// Update if requested.
|
||||||
if ( state.update ) {
|
if ( state.update ) {
|
||||||
|
@ -1983,6 +2004,15 @@ void error_dialog ( char *msg )
|
||||||
}
|
}
|
||||||
// Wait for event.
|
// Wait for event.
|
||||||
XEvent ev;
|
XEvent ev;
|
||||||
|
MainLoopEvent mle = ML_XEVENT;
|
||||||
|
if ( !has_keyboard ) {
|
||||||
|
mle = wait_for_xevent_or_timeout ( display, x11_fd );
|
||||||
|
has_keyboard = take_keyboard ( display, main_window );
|
||||||
|
}
|
||||||
|
if ( mle == ML_TIMEOUT ) {
|
||||||
|
// Loop.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
XNextEvent ( display, &ev );
|
XNextEvent ( display, &ev );
|
||||||
|
|
||||||
|
|
||||||
|
@ -2003,7 +2033,6 @@ void error_dialog ( char *msg )
|
||||||
}
|
}
|
||||||
release_keyboard ();
|
release_keyboard ();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SwitcherMode run_switcher_window ( char **input, G_GNUC_UNUSED void *data )
|
SwitcherMode run_switcher_window ( char **input, G_GNUC_UNUSED void *data )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue