Asynchronously update the keyboard state
When the keyboard layout is modified via xmodmap, each single "change" (line of input to xmodmap) causes an "the keyboard configuration changed"-event to be sent. Awesome reacted to each of these events by reloading the keyboard layout. Thus, awesome reloaded the keyboard layout a lot and appeared to freeze. Fix this by asynchronously update the keyboard state: When such an event comes in, instead of reloading things immediately, we set a flag which makes us update the state at the end of the main loop iteration. This means that many events still cause only a single (or at least few) re-quering of the layout. Thus, a lot of time is saved. This commit removes the argument to the (undocumented!) signal xkb::group_changed. Previously, the argument was the active group number. Since this argument was unused and I'm lazy, I just removed it. The alternative would be that it might be visible to Lua that some "the active group changed"-events are dropped. Fixes: https://github.com/awesomeWM/awesome/issues/1494 Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
686abd174f
commit
9f3a6757e9
4
event.h
4
event.h
|
@ -42,9 +42,13 @@ void client_destroy_later(void);
|
|||
/* objects/screen.c */
|
||||
void screen_refresh(void);
|
||||
|
||||
/* xkb.c */
|
||||
void xkb_refresh(void);
|
||||
|
||||
static inline int
|
||||
awesome_refresh(void)
|
||||
{
|
||||
xkb_refresh();
|
||||
screen_refresh();
|
||||
luaA_emit_refresh();
|
||||
drawin_refresh();
|
||||
|
|
|
@ -186,6 +186,12 @@ typedef struct
|
|||
struct xkb_context *xkb_ctx;
|
||||
/* xkb state of dead keys on keyboard */
|
||||
struct xkb_state *xkb_state;
|
||||
/* Do we have a pending reload? */
|
||||
bool xkb_reload_keymap;
|
||||
/* Do we have a pending map change? */
|
||||
bool xkb_map_changed;
|
||||
/* Do we have a pending group change? */
|
||||
bool xkb_group_changed;
|
||||
/** The preferred size of client icons for this screen */
|
||||
uint32_t preferred_icon_size;
|
||||
/** Cached wallpaper information */
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
-- Test for bug #1494: Using xmodmap freezes awesome since it re-queries the
|
||||
-- keyboard layout many, many times. (xmodmap applies each change on its own)
|
||||
|
||||
local runner = require("_runner")
|
||||
local spawn = require("awful.spawn")
|
||||
local GLib = require("lgi").GLib
|
||||
|
||||
local done
|
||||
local timer = GLib.Timer()
|
||||
|
||||
local steps = {
|
||||
function(count)
|
||||
if count == 1 then
|
||||
-- POSIX allows us to use awk
|
||||
local cmd = "awk 'BEGIN { for(i=1; i<=1000;i++) print \"keycode 107 = parenleft\" }' | xmodmap -"
|
||||
spawn.easy_async({"sh", "-c", cmd}, function()
|
||||
awesome.sync()
|
||||
done = true
|
||||
end)
|
||||
end
|
||||
if done then
|
||||
-- Apply some limit on how long awesome may need to process 'things'
|
||||
return timer:elapsed() < 5
|
||||
end
|
||||
end
|
||||
}
|
||||
runner.run_steps(steps)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
36
xkb.c
36
xkb.c
|
@ -297,13 +297,29 @@ xkb_reload_keymap(void)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
xkb_refresh(void)
|
||||
{
|
||||
lua_State *L = globalconf_get_lua_State();
|
||||
|
||||
if (globalconf.xkb_reload_keymap)
|
||||
xkb_reload_keymap();
|
||||
if (globalconf.xkb_map_changed)
|
||||
signal_object_emit(L, &global_signals, "xkb::map_changed", 0);
|
||||
if (globalconf.xkb_group_changed)
|
||||
signal_object_emit(L, &global_signals, "xkb::group_changed", 0);
|
||||
|
||||
globalconf.xkb_reload_keymap = false;
|
||||
globalconf.xkb_map_changed = false;
|
||||
globalconf.xkb_group_changed = false;
|
||||
}
|
||||
|
||||
/** The xkb notify event handler.
|
||||
* \param event The event.
|
||||
*/
|
||||
void
|
||||
event_handle_xkb_notify(xcb_generic_event_t* event)
|
||||
{
|
||||
lua_State *L = globalconf_get_lua_State();
|
||||
assert(globalconf.have_xkb);
|
||||
|
||||
/* The pad0 field of xcb_generic_event_t contains the event sub-type,
|
||||
|
@ -315,18 +331,16 @@ event_handle_xkb_notify(xcb_generic_event_t* event)
|
|||
{
|
||||
xcb_xkb_new_keyboard_notify_event_t *new_keyboard_event = (void*)event;
|
||||
|
||||
xkb_reload_keymap();
|
||||
globalconf.xkb_reload_keymap = true;
|
||||
|
||||
if (new_keyboard_event->changed & XCB_XKB_NKN_DETAIL_KEYCODES)
|
||||
{
|
||||
signal_object_emit(L, &global_signals, "xkb::map_changed", 0);
|
||||
}
|
||||
globalconf.xkb_map_changed = true;
|
||||
break;
|
||||
}
|
||||
case XCB_XKB_MAP_NOTIFY:
|
||||
{
|
||||
xkb_reload_keymap();
|
||||
signal_object_emit(L, &global_signals, "xkb::map_changed", 0);
|
||||
globalconf.xkb_reload_keymap = true;
|
||||
globalconf.xkb_map_changed = true;
|
||||
break;
|
||||
}
|
||||
case XCB_XKB_STATE_NOTIFY:
|
||||
|
@ -342,10 +356,7 @@ event_handle_xkb_notify(xcb_generic_event_t* event)
|
|||
state_notify_event->lockedGroup);
|
||||
|
||||
if (state_notify_event->changed & XCB_XKB_STATE_PART_GROUP_STATE)
|
||||
{
|
||||
lua_pushinteger(L, state_notify_event->group);
|
||||
signal_object_emit(L, &global_signals, "xkb::group_changed", 1);
|
||||
}
|
||||
globalconf.xkb_group_changed = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -358,6 +369,9 @@ event_handle_xkb_notify(xcb_generic_event_t* event)
|
|||
void
|
||||
xkb_init(void)
|
||||
{
|
||||
globalconf.xkb_reload_keymap = false;
|
||||
globalconf.xkb_map_changed = false;
|
||||
globalconf.xkb_group_changed = false;
|
||||
|
||||
int success_xkb = xkb_x11_setup_xkb_extension(globalconf.connection,
|
||||
XKB_X11_MIN_MAJOR_XKB_VERSION,
|
||||
|
|
Loading…
Reference in New Issue