Merge pull request #149 from lexa/master
xkb: implementation of keyboard layout switcher
This commit is contained in:
commit
2f24ec69e1
|
@ -56,6 +56,7 @@ set(AWE_SRCS
|
||||||
${SOURCE_DIR}/strut.c
|
${SOURCE_DIR}/strut.c
|
||||||
${SOURCE_DIR}/systray.c
|
${SOURCE_DIR}/systray.c
|
||||||
${SOURCE_DIR}/xwindow.c
|
${SOURCE_DIR}/xwindow.c
|
||||||
|
${SOURCE_DIR}/xkb.c
|
||||||
${SOURCE_DIR}/common/atoms.c
|
${SOURCE_DIR}/common/atoms.c
|
||||||
${SOURCE_DIR}/common/backtrace.c
|
${SOURCE_DIR}/common/backtrace.c
|
||||||
${SOURCE_DIR}/common/buffer.c
|
${SOURCE_DIR}/common/buffer.c
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "common/backtrace.h"
|
#include "common/backtrace.h"
|
||||||
#include "common/version.h"
|
#include "common/version.h"
|
||||||
#include "common/xutil.h"
|
#include "common/xutil.h"
|
||||||
|
#include "xkb.h"
|
||||||
#include "dbus.h"
|
#include "dbus.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
#include "ewmh.h"
|
#include "ewmh.h"
|
||||||
|
@ -499,6 +500,9 @@ main(int argc, char **argv)
|
||||||
/* init spawn (sn) */
|
/* init spawn (sn) */
|
||||||
spawn_init();
|
spawn_init();
|
||||||
|
|
||||||
|
/* init xkb */
|
||||||
|
xkb_init();
|
||||||
|
|
||||||
/* The default GC is just a newly created associated with a window with
|
/* The default GC is just a newly created associated with a window with
|
||||||
* depth globalconf.default_depth */
|
* depth globalconf.default_depth */
|
||||||
xcb_window_t tmp_win = xcb_generate_id(globalconf.connection);
|
xcb_window_t tmp_win = xcb_generate_id(globalconf.connection);
|
||||||
|
|
|
@ -140,6 +140,7 @@ pkg_check_modules(AWESOME_REQUIRED REQUIRED
|
||||||
xcb-util>=0.3.8
|
xcb-util>=0.3.8
|
||||||
xcb-keysyms>=0.3.4
|
xcb-keysyms>=0.3.4
|
||||||
xcb-icccm>=0.3.8
|
xcb-icccm>=0.3.8
|
||||||
|
xcb-xkb>=1.11
|
||||||
cairo-xcb
|
cairo-xcb
|
||||||
libstartup-notification-1.0>=0.10
|
libstartup-notification-1.0>=0.10
|
||||||
xproto>=7.0.15
|
xproto>=7.0.15
|
||||||
|
|
|
@ -107,6 +107,10 @@ mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
|
||||||
menubar.utils.terminal = terminal -- Set the terminal for applications that require it
|
menubar.utils.terminal = terminal -- Set the terminal for applications that require it
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
|
-- Keyboard map indicator and switcher
|
||||||
|
mykeyboardlayout = awful.widget.keyboardlayout()
|
||||||
|
-- }}}
|
||||||
|
|
||||||
-- {{{ Wibox
|
-- {{{ Wibox
|
||||||
-- Create a textclock widget
|
-- Create a textclock widget
|
||||||
mytextclock = awful.widget.textclock()
|
mytextclock = awful.widget.textclock()
|
||||||
|
@ -189,6 +193,8 @@ for s = 1, screen.count() do
|
||||||
|
|
||||||
-- Widgets that are aligned to the right
|
-- Widgets that are aligned to the right
|
||||||
local right_layout = wibox.layout.fixed.horizontal()
|
local right_layout = wibox.layout.fixed.horizontal()
|
||||||
|
right_layout:add(mykeyboardlayout)
|
||||||
|
|
||||||
if s == 1 then right_layout:add(wibox.widget.systray()) end
|
if s == 1 then right_layout:add(wibox.widget.systray()) end
|
||||||
right_layout:add(mytextclock)
|
right_layout:add(mytextclock)
|
||||||
right_layout:add(mylayoutbox[s])
|
right_layout:add(mylayoutbox[s])
|
||||||
|
|
|
@ -75,3 +75,16 @@
|
||||||
-- @param name A string with the event name.
|
-- @param name A string with the event name.
|
||||||
-- @param ... Signal arguments.
|
-- @param ... Signal arguments.
|
||||||
-- @function emit_signal
|
-- @function emit_signal
|
||||||
|
|
||||||
|
--- Switch keyboard layout group.
|
||||||
|
-- @param num keyboard layout number, integer from 0 to 3
|
||||||
|
-- @function xkb_set_layout_group
|
||||||
|
|
||||||
|
--- Get current keyboard layout group.
|
||||||
|
-- @return current keyboard layout number
|
||||||
|
-- @function xkb_get_layout_group
|
||||||
|
|
||||||
|
|
||||||
|
--- Get description of configured layouts
|
||||||
|
-- @return String with description of configured layouts
|
||||||
|
-- @function xkb_get_group_names
|
||||||
|
|
14
event.c
14
event.c
|
@ -32,6 +32,7 @@
|
||||||
#include "mousegrabber.h"
|
#include "mousegrabber.h"
|
||||||
#include "luaa.h"
|
#include "luaa.h"
|
||||||
#include "systray.h"
|
#include "systray.h"
|
||||||
|
#include "xkb.h"
|
||||||
#include "objects/screen.h"
|
#include "objects/screen.h"
|
||||||
#include "common/atoms.h"
|
#include "common/atoms.h"
|
||||||
#include "common/xutil.h"
|
#include "common/xutil.h"
|
||||||
|
@ -42,6 +43,7 @@
|
||||||
#include <xcb/xcb_atom.h>
|
#include <xcb/xcb_atom.h>
|
||||||
#include <xcb/xcb_icccm.h>
|
#include <xcb/xcb_icccm.h>
|
||||||
#include <xcb/xcb_event.h>
|
#include <xcb/xcb_event.h>
|
||||||
|
#include <xcb/xkb.h>
|
||||||
|
|
||||||
#define DO_EVENT_HOOK_CALLBACK(type, xcbtype, xcbeventprefix, arraytype, match) \
|
#define DO_EVENT_HOOK_CALLBACK(type, xcbtype, xcbeventprefix, arraytype, match) \
|
||||||
static void \
|
static void \
|
||||||
|
@ -880,6 +882,7 @@ void event_handle(xcb_generic_event_t *event)
|
||||||
|
|
||||||
static uint8_t randr_screen_change_notify = 0;
|
static uint8_t randr_screen_change_notify = 0;
|
||||||
static uint8_t shape_notify = 0;
|
static uint8_t shape_notify = 0;
|
||||||
|
static uint8_t xkb_notify = 0;
|
||||||
|
|
||||||
if(randr_screen_change_notify == 0)
|
if(randr_screen_change_notify == 0)
|
||||||
{
|
{
|
||||||
|
@ -898,10 +901,21 @@ void event_handle(xcb_generic_event_t *event)
|
||||||
shape_notify = shape_query->first_event + XCB_SHAPE_NOTIFY;
|
shape_notify = shape_query->first_event + XCB_SHAPE_NOTIFY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(xkb_notify == 0)
|
||||||
|
{
|
||||||
|
/* check for xkb extension */
|
||||||
|
const xcb_query_extension_reply_t *xkb_query;
|
||||||
|
xkb_query = xcb_get_extension_data(globalconf.connection, &xcb_xkb_id);
|
||||||
|
if(xkb_query->present)
|
||||||
|
xkb_notify = xkb_query->first_event;
|
||||||
|
}
|
||||||
|
|
||||||
if (response_type == randr_screen_change_notify)
|
if (response_type == randr_screen_change_notify)
|
||||||
event_handle_randr_screen_change_notify((void *) event);
|
event_handle_randr_screen_change_notify((void *) event);
|
||||||
if (response_type == shape_notify)
|
if (response_type == shape_notify)
|
||||||
event_handle_shape_notify((void *) event);
|
event_handle_shape_notify((void *) event);
|
||||||
|
if (response_type == xkb_notify)
|
||||||
|
event_handle_xkb_notify((void *) event);
|
||||||
}
|
}
|
||||||
|
|
||||||
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||||
|
|
|
@ -18,6 +18,7 @@ return
|
||||||
graph = require("awful.widget.graph");
|
graph = require("awful.widget.graph");
|
||||||
layoutbox = require("awful.widget.layoutbox");
|
layoutbox = require("awful.widget.layoutbox");
|
||||||
textclock = require("awful.widget.textclock");
|
textclock = require("awful.widget.textclock");
|
||||||
|
keyboardlayout = require("awful.widget.keyboardlayout");
|
||||||
}
|
}
|
||||||
|
|
||||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
-- @author Aleksey Fedotov <lexa@cfotr.com>
|
||||||
|
-- @copyright 2015 Aleksey Fedotov
|
||||||
|
-- @release @AWESOME_VERSION@
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local capi = {awesome = awesome,
|
||||||
|
awful = awful}
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local os = os
|
||||||
|
local textbox = require("wibox.widget.textbox")
|
||||||
|
local button = require("awful.button")
|
||||||
|
local util = require("awful.util")
|
||||||
|
local widget_base = require("wibox.widget.base")
|
||||||
|
|
||||||
|
--- Keyboard Layout widget.
|
||||||
|
-- awful.widget.keyboardlayout
|
||||||
|
local keyboardlayout = { mt = {} }
|
||||||
|
|
||||||
|
-- Callback for updaing current layout
|
||||||
|
local function update_status (keyboardlayout)
|
||||||
|
keyboardlayout.current = awesome.xkb_get_layout_group();
|
||||||
|
local text = ""
|
||||||
|
if (#keyboardlayout.layout > 0) then
|
||||||
|
text = (" " .. keyboardlayout.layout[keyboardlayout.current] .. " ")
|
||||||
|
end
|
||||||
|
keyboardlayout.widget:set_text(text)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Callback for updating list of layouts
|
||||||
|
local function update_layout(keyboardlayout)
|
||||||
|
keyboardlayout.layout = {};
|
||||||
|
local group_names = awesome.xkb_get_group_names();
|
||||||
|
|
||||||
|
-- typical layout string looks like "pc+us+ru:2+de:3+ba:4+inet"
|
||||||
|
-- and we want to get only three mathes: "us", "ru:2", "de:3" "ba:4"
|
||||||
|
-- also please note, that numbers of groups reported by xkb_get_group_names
|
||||||
|
-- is greater by one of the real group number
|
||||||
|
|
||||||
|
|
||||||
|
local first_group = string.match(group_names, "+(%a+)");
|
||||||
|
if (not first_group) then
|
||||||
|
error ("Failed to get list of keyboard groups");
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
keyboardlayout.layout[0] = first_group;
|
||||||
|
|
||||||
|
for name, number_str in string.gmatch(group_names, "+(%a+):(%d)") do
|
||||||
|
group = tonumber(number_str);
|
||||||
|
keyboardlayout.layout[group - 1] = name;
|
||||||
|
end
|
||||||
|
update_status(keyboardlayout)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a keyboard layout widget. It shows current keyboard layout name in a textbox.
|
||||||
|
-- @return A keyboard layout widget.
|
||||||
|
function keyboardlayout.new()
|
||||||
|
local widget = textbox()
|
||||||
|
local keyboardlayout = widget_base.make_widget(widget)
|
||||||
|
|
||||||
|
keyboardlayout.widget = widget
|
||||||
|
|
||||||
|
update_layout(keyboardlayout);
|
||||||
|
|
||||||
|
keyboardlayout.next_layout = function()
|
||||||
|
new_layout = (keyboardlayout.current + 1) % (#keyboardlayout.layout + 1)
|
||||||
|
keyboardlayout.set_layout(new_layout)
|
||||||
|
end
|
||||||
|
|
||||||
|
keyboardlayout.set_layout = function(group_number)
|
||||||
|
if (0 > group_number) or (group_number > #keyboardlayout.layout) then
|
||||||
|
error("Invalid group number: " .. group_number ..
|
||||||
|
"expected number from 0 to " .. #keyboardlayout.layout)
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
awesome.xkb_set_layout_group(group_number);
|
||||||
|
end
|
||||||
|
|
||||||
|
-- callback for processing layout changes
|
||||||
|
capi.awesome.connect_signal("xkb::map_changed",
|
||||||
|
function () update_layout(keyboardlayout) end)
|
||||||
|
capi.awesome.connect_signal("xkb::group_changed",
|
||||||
|
function () update_status(keyboardlayout) end);
|
||||||
|
|
||||||
|
-- Mouse bindings
|
||||||
|
keyboardlayout:buttons(
|
||||||
|
util.table.join(button({ }, 1, keyboardlayout.next_layout))
|
||||||
|
)
|
||||||
|
|
||||||
|
return keyboardlayout
|
||||||
|
end
|
||||||
|
|
||||||
|
local _instance = nil;
|
||||||
|
|
||||||
|
function keyboardlayout.mt:__call(...)
|
||||||
|
if _instance == nil then
|
||||||
|
_instance = keyboardlayout.new(...)
|
||||||
|
end
|
||||||
|
return _instance
|
||||||
|
end
|
||||||
|
|
||||||
|
return setmetatable(keyboardlayout, keyboardlayout.mt)
|
||||||
|
|
||||||
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
6
luaa.c
6
luaa.c
|
@ -37,6 +37,7 @@
|
||||||
#include "selection.h"
|
#include "selection.h"
|
||||||
#include "spawn.h"
|
#include "spawn.h"
|
||||||
#include "systray.h"
|
#include "systray.h"
|
||||||
|
#include "xkb.h"
|
||||||
|
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
#include <lauxlib.h>
|
#include <lauxlib.h>
|
||||||
|
@ -359,6 +360,9 @@ luaA_init(xdgHandle* xdg)
|
||||||
{ "get_xproperty", luaA_get_xproperty },
|
{ "get_xproperty", luaA_get_xproperty },
|
||||||
{ "__index", luaA_awesome_index },
|
{ "__index", luaA_awesome_index },
|
||||||
{ "__newindex", luaA_default_newindex },
|
{ "__newindex", luaA_default_newindex },
|
||||||
|
{ "xkb_set_layout_group", luaA_xkb_set_layout_group},
|
||||||
|
{ "xkb_get_layout_group", luaA_xkb_get_layout_group},
|
||||||
|
{ "xkb_get_group_names", luaA_xkb_get_group_names},
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -473,6 +477,8 @@ luaA_init(xdgHandle* xdg)
|
||||||
signal_add(&global_signals, "debug::newindex::miss");
|
signal_add(&global_signals, "debug::newindex::miss");
|
||||||
signal_add(&global_signals, "systray::update");
|
signal_add(&global_signals, "systray::update");
|
||||||
signal_add(&global_signals, "wallpaper_changed");
|
signal_add(&global_signals, "wallpaper_changed");
|
||||||
|
signal_add(&global_signals, "xkb::map_changed");
|
||||||
|
signal_add(&global_signals, "xkb::group_changed");
|
||||||
signal_add(&global_signals, "refresh");
|
signal_add(&global_signals, "refresh");
|
||||||
signal_add(&global_signals, "startup");
|
signal_add(&global_signals, "startup");
|
||||||
signal_add(&global_signals, "exit");
|
signal_add(&global_signals, "exit");
|
||||||
|
|
|
@ -0,0 +1,185 @@
|
||||||
|
/*
|
||||||
|
* xkb.c - keyboard layout control functions
|
||||||
|
*
|
||||||
|
* Copyright © 2015 Aleksey Fedotov <lexa@cfotr.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xkb.h"
|
||||||
|
#include "globalconf.h"
|
||||||
|
#include <xcb/xkb.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* \brief switch keyboard layout
|
||||||
|
* \param L The Lua VM state.
|
||||||
|
* \return The number of elements pushed on stack.
|
||||||
|
* \luastack
|
||||||
|
* \lparam layout number, integer from 0 to 3
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
luaA_xkb_set_layout_group(lua_State *L)
|
||||||
|
{
|
||||||
|
unsigned group = luaL_checkinteger(L, 1);
|
||||||
|
xcb_xkb_latch_lock_state (globalconf.connection, XCB_XKB_ID_USE_CORE_KBD,
|
||||||
|
0, 0, true, group, 0, 0, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* \brief get current layout number
|
||||||
|
* \param L The Lua VM state.
|
||||||
|
* \return The number of elements pushed on stack.
|
||||||
|
* \luastack
|
||||||
|
* \lreturn current layout number, integer from 0 to 3
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
luaA_xkb_get_layout_group(lua_State *L)
|
||||||
|
{
|
||||||
|
xcb_xkb_get_state_cookie_t state_c;
|
||||||
|
state_c = xcb_xkb_get_state_unchecked (globalconf.connection,
|
||||||
|
XCB_XKB_ID_USE_CORE_KBD);
|
||||||
|
xcb_xkb_get_state_reply_t* state_r;
|
||||||
|
state_r = xcb_xkb_get_state_reply (globalconf.connection,
|
||||||
|
state_c, NULL);
|
||||||
|
if (!state_r)
|
||||||
|
{
|
||||||
|
free(state_r);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
lua_pushinteger(L, state_r->group);
|
||||||
|
free(state_r);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* \brief get layout short names
|
||||||
|
* \param L The Lua VM state.
|
||||||
|
* \return The number of elements pushed on stack.
|
||||||
|
* \luastack
|
||||||
|
* \lreturn string describing current layout settings, \
|
||||||
|
* example: 'pc+us+de:2+inet(evdev)+group(alt_shift_toggle)+ctrl(nocaps)'
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
luaA_xkb_get_group_names(lua_State *L)
|
||||||
|
{
|
||||||
|
xcb_xkb_get_names_cookie_t name_c;
|
||||||
|
name_c = xcb_xkb_get_names_unchecked (globalconf.connection,
|
||||||
|
XCB_XKB_ID_USE_CORE_KBD,
|
||||||
|
XCB_XKB_NAME_DETAIL_SYMBOLS);
|
||||||
|
xcb_xkb_get_names_reply_t* name_r;
|
||||||
|
name_r = xcb_xkb_get_names_reply (globalconf.connection, name_c, NULL);
|
||||||
|
|
||||||
|
if (!name_r)
|
||||||
|
{
|
||||||
|
luaA_warn(L, "Failed to get xkb symbols name");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_xkb_get_names_value_list_t name_list;
|
||||||
|
void *buffer = xcb_xkb_get_names_value_list(name_r);
|
||||||
|
xcb_xkb_get_names_value_list_unpack (
|
||||||
|
buffer, name_r->nTypes, name_r->indicators,
|
||||||
|
name_r->virtualMods, name_r->groupNames, name_r->nKeys,
|
||||||
|
name_r->nKeyAliases, name_r->nRadioGroups, name_r->which,
|
||||||
|
&name_list);
|
||||||
|
|
||||||
|
xcb_get_atom_name_cookie_t atom_name_c;
|
||||||
|
atom_name_c = xcb_get_atom_name_unchecked(globalconf.connection, name_list.symbolsName);
|
||||||
|
xcb_get_atom_name_reply_t *atom_name_r;
|
||||||
|
atom_name_r = xcb_get_atom_name_reply(globalconf.connection, atom_name_c, NULL);
|
||||||
|
if (!atom_name_r) {
|
||||||
|
luaA_warn(L, "Failed to get atom symbols name");
|
||||||
|
free(name_r);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *name = xcb_get_atom_name_name(atom_name_r);
|
||||||
|
size_t name_len = xcb_get_atom_name_name_length(atom_name_r);
|
||||||
|
lua_pushlstring(L, name, name_len);
|
||||||
|
|
||||||
|
free(atom_name_r);
|
||||||
|
free(name_r);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 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();
|
||||||
|
/* The pad0 field of xcb_generic_event_t contains the event sub-type,
|
||||||
|
* unfortunately xkb doesn't provide a usable struct for getting this in a
|
||||||
|
* nicer way*/
|
||||||
|
switch (event->pad0)
|
||||||
|
{
|
||||||
|
case XCB_XKB_NEW_KEYBOARD_NOTIFY:
|
||||||
|
{
|
||||||
|
xcb_xkb_new_keyboard_notify_event_t *new_keyboard_event = (void*)event;
|
||||||
|
if (new_keyboard_event->changed & XCB_XKB_NKN_DETAIL_KEYCODES)
|
||||||
|
{
|
||||||
|
signal_object_emit(L, &global_signals, "xkb::map_changed", 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XCB_XKB_NAMES_NOTIFY:
|
||||||
|
{
|
||||||
|
signal_object_emit(L, &global_signals, "xkb::map_changed", 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XCB_XKB_STATE_NOTIFY:
|
||||||
|
{
|
||||||
|
xcb_xkb_state_notify_event_t *state_notify_event = (void*)event;
|
||||||
|
if (state_notify_event->changed & XCB_XKB_STATE_PART_GROUP_STATE)
|
||||||
|
{
|
||||||
|
lua_pushnumber(L, state_notify_event->group);
|
||||||
|
signal_object_emit(L, &global_signals, "xkb::group_changed", 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Initialize XKB support
|
||||||
|
*/
|
||||||
|
|
||||||
|
void xkb_init(void)
|
||||||
|
{
|
||||||
|
/* check that XKB extension present in this X server */
|
||||||
|
const xcb_query_extension_reply_t *xkb_r;
|
||||||
|
xkb_r = xcb_get_extension_data(globalconf.connection, &xcb_xkb_id);
|
||||||
|
if (!xkb_r || !xkb_r->present)
|
||||||
|
{
|
||||||
|
fatal("Xkb extension not present");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check xkb version */
|
||||||
|
xcb_xkb_use_extension_cookie_t ext_cookie = xcb_xkb_use_extension(globalconf.connection, 1, 0);
|
||||||
|
xcb_xkb_use_extension_reply_t *ext_reply = xcb_xkb_use_extension_reply (globalconf.connection, ext_cookie, NULL);
|
||||||
|
if (!ext_reply || !ext_reply->supported)
|
||||||
|
{
|
||||||
|
fatal("Required xkb extension is not supported");
|
||||||
|
}
|
||||||
|
unsigned int map = XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY;
|
||||||
|
xcb_xkb_select_events_checked(globalconf.connection,
|
||||||
|
XCB_XKB_ID_USE_CORE_KBD,
|
||||||
|
map,
|
||||||
|
0,
|
||||||
|
map,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* xkb.h - Keyboard layout manager header
|
||||||
|
*
|
||||||
|
* Copyright © 2015 Aleksey Fedotov <lexa@cfotr.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AWESOME_XKB_H
|
||||||
|
#define AWESOME_XKB_H
|
||||||
|
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#include <lua.h>
|
||||||
|
|
||||||
|
void event_handle_xkb_notify(xcb_generic_event_t* event);
|
||||||
|
void xkb_init(void);
|
||||||
|
|
||||||
|
int luaA_xkb_set_layout_group(lua_State *L);
|
||||||
|
int luaA_xkb_get_layout_group(lua_State *L);
|
||||||
|
int luaA_xkb_get_group_names(lua_State *L);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue