Горячие клавиши ctrl+shift+[key] и переключение языков по ctrl+shift (xorg-server 1.12.*)
Ожидает приглашения
Здравствуйте.
Данная статья является продолжением http://habrahabr.ru/post/87408/. Напомню, что проблема заключается в следующем: комбинация клавиш для переключения раскладки срабатывает на нажатие, а не на отпускание (как, например, в Windows). Это приводит к тому, что комбинации ctrl+shift+[key] уже не срабатывают. В Ubuntu, начиная с версии 11.04, проблема с горячими клавишами решена, но в большинстве дистрибутивов проблема осталась. С выходом xorg-server версии 1.12.1, патч по указанной выше ссылке не актуален.
Итак, инструкция для решения проблемы в ArchLinux.
Сначала необходимо получить файлы для сборки xorg-server, например с помощью abs. После синхронизации дерева abs, файлы будут доступны в /var/abs/extra/xorg-server. Далее нам необходимо подготовить эти файлы для сборки пакета с нашем патчем:
Создаем файл hotkeys.patch и записываем в него следующее:
Меняем PKGBUILD следующим образом:
Сохраняем, собираем (makepkg), устанавливаем (pacman -U xorg-server xorg-server-common) и перезапускам иксы.
Для того, чтобы в будущем xorg-server сам не обновился, рекомендую в файле /etc/pacman.conf добавить настройку (на свой страх и риск, разумеется):
Вот и все. Всем спасибо за внимание.
Данная статья является продолжением http://habrahabr.ru/post/87408/. Напомню, что проблема заключается в следующем: комбинация клавиш для переключения раскладки срабатывает на нажатие, а не на отпускание (как, например, в Windows). Это приводит к тому, что комбинации ctrl+shift+[key] уже не срабатывают. В Ubuntu, начиная с версии 11.04, проблема с горячими клавишами решена, но в большинстве дистрибутивов проблема осталась. С выходом xorg-server версии 1.12.1, патч по указанной выше ссылке не актуален.
Итак, инструкция для решения проблемы в ArchLinux.
Сначала необходимо получить файлы для сборки xorg-server, например с помощью abs. После синхронизации дерева abs, файлы будут доступны в /var/abs/extra/xorg-server. Далее нам необходимо подготовить эти файлы для сборки пакета с нашем патчем:
$ cp -R /var/abs/extra/xorg-server /var/abs/local/ && cd /var/abs/local/xorg-server
Создаем файл hotkeys.patch и записываем в него следующее:
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index c473df1..fff66f7 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -340,23 +340,83 @@ _XkbFilterLatchState(XkbSrvInfoPtr xkbi,
return 1;
}
+static int xkbSwitchGroupOnRelease(void)
+{
+ /* TODO: user configuring */
+ return TRUE;
+}
+
+static void xkbUpdateLockedGroup(XkbSrvInfoPtr xkbi, XkbAction* pAction)
+{
+ XkbGroupAction ga = pAction->group;
+ if (ga.flags&XkbSA_GroupAbsolute)
+ xkbi->state.locked_group= XkbSAGroup(&ga);
+ else xkbi->state.locked_group+= XkbSAGroup(&ga);
+}
+
+static XkbFilterPtr _XkbNextFreeFilter(XkbSrvInfoPtr xkbi);
+
static int
-_XkbFilterLockState(XkbSrvInfoPtr xkbi,
+_XkbFilterLockGroup(XkbSrvInfoPtr xkbi,
XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
{
- if (pAction && (pAction->type == XkbSA_LockGroup)) {
- if (pAction->group.flags & XkbSA_GroupAbsolute)
- xkbi->state.locked_group = XkbSAGroup(&pAction->group);
- else
- xkbi->state.locked_group += XkbSAGroup(&pAction->group);
- return 1;
+
+ int sendEvent = 1;
+
+ if (!xkbSwitchGroupOnRelease()) {
+ xkbUpdateLockedGroup(xkbi, pAction);
+ return sendEvent;
+ }
+
+ /* Delay switch till button release */
+ if (filter->keycode==0) { /* initial press */
+ filter->keycode = keycode;
+ filter->active = 1;
+ filter->filterOthers = 0; /* for what? */
+ filter->filter = _XkbFilterLockGroup;
+
+ /* filter->priv = 0; */
+ filter->upAction = *pAction;
+
+ /* Ok, now we need to simulate the action which would go if this action didn't block it.
+ XkbSA_SetMods is the one: it is to set modifier' flag up. */
+ {
+ XkbStateRec fake_state = xkbi->state;
+ XkbAction act;
+
+ fake_state.mods = 0;
+ act = XkbGetKeyAction(xkbi, &fake_state, keycode);
+
+ /* KLUDGE: XkbSA_SetMods only? */
+ if (act.type == XkbSA_SetMods) {
+ XkbFilterPtr filter = _XkbNextFreeFilter(xkbi);
+ sendEvent = _XkbFilterSetState(xkbi,filter,keycode,&act);
+ }
+ }
}
+ else {
+ /* do nothing if some button else is pressed */
+ if (!pAction)
+ xkbUpdateLockedGroup(xkbi, &filter->upAction);
+ filter->active = 0;
+ }
+
+ return sendEvent;
+}
+
+static int
+_XkbFilterLockMods( XkbSrvInfoPtr xkbi,
+ XkbFilterPtr filter,
+ unsigned keycode,
+ XkbAction * pAction)
+{
+
if (filter->keycode == 0) { /* initial press */
filter->keycode = keycode;
filter->active = 1;
filter->filterOthers = 0;
filter->priv = xkbi->state.locked_mods & pAction->mods.mask;
- filter->filter = _XkbFilterLockState;
+ filter->filter = _XkbFilterLockMods;
filter->upAction = *pAction;
if (!(filter->upAction.mods.flags & XkbSA_LockNoLock))
xkbi->state.locked_mods |= pAction->mods.mask;
@@ -1129,10 +1189,13 @@ XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event)
sendEvent = _XkbFilterLatchState(xkbi, filter, key, &act);
break;
case XkbSA_LockMods:
- case XkbSA_LockGroup:
filter = _XkbNextFreeFilter(xkbi);
- sendEvent = _XkbFilterLockState(xkbi, filter, key, &act);
+ sendEvent=_XkbFilterLockMods(xkbi,filter,key,&act);
break;
+ case XkbSA_LockGroup:
+ filter = _XkbNextFreeFilter(xkbi);
+ sendEvent = _XkbFilterLockGroup(xkbi,filter,key,&act);
+ break;
case XkbSA_ISOLock:
filter = _XkbNextFreeFilter(xkbi);
sendEvent = _XkbFilterISOLock(xkbi, filter, key, &act);
Меняем PKGBUILD следующим образом:
...
source=(
...
10-quirks.conf
hotkeys.patch) # Добавляем в списке наш патч
...
sha1sums=('922b963901f4711449b53fb32ce3e14f5b642766'
...
'993798f3d22ad672d769dae5f48d1fa068d5578f'
'd908acf9fe169a7479b4cedeffc5ab3f08d958fc') #Добавляем sha1 сумму от файла hotkeys.patch
...
build() {
...
# После применения всех патчей и перед началом сборки применяем наш патч
#HotKeys
patch -Np1 -i "${srcdir}/hotkeys.patch"
autoreconf -fi
./configure --prefix=/usr \
...
Сохраняем, собираем (makepkg), устанавливаем (pacman -U xorg-server xorg-server-common) и перезапускам иксы.
Для того, чтобы в будущем xorg-server сам не обновился, рекомендую в файле /etc/pacman.conf добавить настройку (на свой страх и риск, разумеется):
IgnorePkg = xorg-server xorg-server-common
Вот и все. Всем спасибо за внимание.