commit 4ff79c0e8f8ee119c7533641ecc85d2a9693563b
parent 8da502a4a20b691f8bd616b965322b0f15c03fb8
Author: Raymond Li <hi@raymond.li>
Date: Mon, 9 Aug 2021 17:55:48 -0400
Merge pull request #231 from JezerM/passKeys
--pass-*-keys options (#136)
Diffstat:
6 files changed, 54 insertions(+), 9 deletions(-)
diff --git a/.github/workflows/Build Test.yml b/.github/workflows/Build Test.yml
@@ -9,7 +9,7 @@ jobs:
- name: Install deps
run: |
sudo apt update
- sudo apt install pkg-config libpam0g-dev libcairo2-dev libfontconfig1-dev libxcb-composite0-dev libev-dev libx11-xcb-dev libxcb-xkb-dev libxcb-xinerama0-dev libxcb-randr0-dev libxcb-image0-dev libxcb-util-dev libxcb-xrm-dev libxkbcommon-dev libxkbcommon-x11-dev libjpeg-dev
+ sudo apt install pkg-config libpam0g-dev libcairo2-dev libfontconfig1-dev libxcb-composite0-dev libev-dev libx11-xcb-dev libxcb-xkb-dev libxcb-xinerama0-dev libxcb-randr0-dev libxcb-image0-dev libxcb-util-dev libxcb-xrm-dev libxcb-xtest0-dev libxkbcommon-dev libxkbcommon-x11-dev libjpeg-dev
- name: Build
run: ./build.sh
- name: Check and distcheck
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
@@ -66,7 +66,7 @@ jobs:
- run: |
sudo apt-get update
- sudo apt install autoconf gcc make pkg-config libpam0g-dev libcairo2-dev libfontconfig1-dev libxcb-composite0-dev libev-dev libx11-xcb-dev libxcb-xkb-dev libxcb-xinerama0-dev libxcb-randr0-dev libxcb-image0-dev libxcb-util-dev libxcb-xrm-dev libxkbcommon-dev libxkbcommon-x11-dev libjpeg-dev
+ sudo apt install autoconf gcc make pkg-config libpam0g-dev libcairo2-dev libfontconfig1-dev libxcb-composite0-dev libev-dev libx11-xcb-dev libxcb-xkb-dev libxcb-xinerama0-dev libxcb-randr0-dev libxcb-image0-dev libxcb-util-dev libxcb-xrm-dev libxcb-xtest0-dev libxkbcommon-dev libxkbcommon-x11-dev libjpeg-dev
./build.sh
- name: Perform CodeQL Analysis
diff --git a/README.md b/README.md
@@ -81,7 +81,7 @@ The following dependencies will need to be installed for a successful build, dep
### Debian
Run this command to install all dependencies:
```
-sudo apt install autoconf gcc make pkg-config libpam0g-dev libcairo2-dev libfontconfig1-dev libxcb-composite0-dev libev-dev libx11-xcb-dev libxcb-xkb-dev libxcb-xinerama0-dev libxcb-randr0-dev libxcb-image0-dev libxcb-util0-dev libxcb-xrm-dev libxkbcommon-dev libxkbcommon-x11-dev libjpeg-dev
+sudo apt install autoconf gcc make pkg-config libpam0g-dev libcairo2-dev libfontconfig1-dev libxcb-composite0-dev libev-dev libx11-xcb-dev libxcb-xkb-dev libxcb-xinerama0-dev libxcb-randr0-dev libxcb-image0-dev libxcb-util0-dev libxcb-xrm-dev libxcb-xtest0-dev libxkbcommon-dev libxkbcommon-x11-dev libjpeg-dev
```
If you still see missing packages during build after installing all of these dependencies, try following the steps [here](https://github.com/Raymo111/i3lock-color/issues/211#issuecomment-809891727).
@@ -95,7 +95,7 @@ sudo dnf install -y autoconf automake cairo-devel fontconfig gcc libev-devel lib
### Ubuntu 18/20.04 LTS
Run this command to install all dependencies:
```
-sudo apt install autoconf gcc make pkg-config libpam0g-dev libcairo2-dev libfontconfig1-dev libxcb-composite0-dev libev-dev libx11-xcb-dev libxcb-xkb-dev libxcb-xinerama0-dev libxcb-randr0-dev libxcb-image0-dev libxcb-util-dev libxcb-xrm-dev libxkbcommon-dev libxkbcommon-x11-dev libjpeg-dev
+sudo apt install autoconf gcc make pkg-config libpam0g-dev libcairo2-dev libfontconfig1-dev libxcb-composite0-dev libev-dev libx11-xcb-dev libxcb-xkb-dev libxcb-xinerama0-dev libxcb-randr0-dev libxcb-image0-dev libxcb-util-dev libxcb-xrm-dev libxcb-xtest0-dev libxkbcommon-dev libxkbcommon-x11-dev libjpeg-dev
```
## Building i3lock-color
diff --git a/configure.ac b/configure.ac
@@ -97,7 +97,7 @@ AC_SEARCH_LIBS([iconv_open], [iconv], , [AC_MSG_FAILURE([cannot find the require
dnl Each prefix corresponds to a source tarball which users might have
dnl downloaded in a newer version and would like to overwrite.
-PKG_CHECK_MODULES([XCB], [xcb xcb-xkb xcb-xinerama xcb-randr xcb-composite])
+PKG_CHECK_MODULES([XCB], [xcb xcb-xkb xcb-xinerama xcb-randr xcb-composite xcb-xtest])
PKG_CHECK_MODULES([XCB_IMAGE], [xcb-image])
PKG_CHECK_MODULES([XCB_UTIL], [xcb-event xcb-util xcb-atom])
PKG_CHECK_MODULES([XCB_UTIL_XRM], [xcb-xrm])
diff --git a/i3lock.1 b/i3lock.1
@@ -389,6 +389,18 @@ volume - XF86AudioMute, XF86AudioLowerVolume, XF86AudioRaiseVolume
.RE
.TP
+.B \-\-special\-passthrough
+Allows special keys to pass through the locked screen, with \-\-pass\-{media, screen,
+power, volume}\-keys. Keystrokes are forcibly sent to the window manager or desktop
+environment in three steps: un-grab keyboard, send key, and re-grab the keyboard.
+No other keys will be sent to the WM/DE.
+
+Note: ONLY use this option if the special keys are NOT passed through without it.
+This could be less safe than the default behavior since the keyboard is ungrabbed for
+the keys to be passed through. This HAS been tested though, so there SHOULDN'T be any
+security issues.
+
+.TP
.B \-\-bar\-indicator
Replaces the usual ring indicator with a bar indicator. Comes with perks.
diff --git a/i3lock.c b/i3lock.c
@@ -49,6 +49,8 @@
#endif
#include <xcb/xcb_aux.h>
#include <xcb/randr.h>
+#include <xcb/xtest.h>
+#include <time.h>
#include "i3lock.h"
#include "xcb.h"
@@ -257,6 +259,7 @@ bool pass_media_keys = false;
bool pass_screen_keys = false;
bool pass_power_keys = false;
bool pass_volume_keys = false;
+bool special_passthrough = false;
// for the rendering thread, so we can clean it up
pthread_t draw_thread;
@@ -651,6 +654,32 @@ static bool skip_without_validation(void) {
}
/*
+ * Sends key press event to root/wm
+ * Releases the keyboard, sends the event, and
+ * grabs the keyboard again
+ * */
+static void send_key_to_root(xcb_key_press_event_t *event, bool twice) {
+ if (!special_passthrough) {
+ xcb_send_event(conn, true, screen->root, XCB_EVENT_MASK_BUTTON_PRESS, (char *)event);
+ return;
+ }
+
+ xcb_ungrab_keyboard(conn, XCB_CURRENT_TIME);
+ DEBUG("Received: %d at %ld\n", event->detail, time(0));
+
+ xcb_test_fake_input(conn, XCB_KEY_PRESS, event->detail, XCB_CURRENT_TIME, screen->root, 0, 0, 0);
+ xcb_test_fake_input(conn, XCB_KEY_RELEASE, event->detail, XCB_CURRENT_TIME, screen->root, 0, 0, 0);
+
+ if (twice) {
+ xcb_test_fake_input(conn, XCB_KEY_PRESS, event->detail, XCB_CURRENT_TIME, screen->root, 0, 0, 0);
+ xcb_test_fake_input(conn, XCB_KEY_RELEASE, event->detail, XCB_CURRENT_TIME, screen->root, 0, 0, 0);
+ }
+
+ xcb_grab_keyboard(conn, true, screen->root, XCB_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
+ xcb_set_input_focus(conn, XCB_INPUT_FOCUS_PARENT, win, XCB_CURRENT_TIME);
+}
+
+/*
* Handle key presses. Fixes state, then looks up the key symbol for the
* given keycode, then looks up the key symbol (as UCS-2), converts it to
* UTF-8 and stores it in the password array.
@@ -709,7 +738,7 @@ static void handle_key_press(xcb_key_press_event_t *event) {
case XKB_KEY_XF86AudioMute:
case XKB_KEY_XF86AudioLowerVolume:
case XKB_KEY_XF86AudioRaiseVolume:
- xcb_send_event(conn, true, screen->root, XCB_EVENT_MASK_BUTTON_PRESS, (char *)event);
+ send_key_to_root(event, true);
return;
}
}
@@ -719,7 +748,7 @@ static void handle_key_press(xcb_key_press_event_t *event) {
switch(ksym) {
case XKB_KEY_XF86MonBrightnessUp:
case XKB_KEY_XF86MonBrightnessDown:
- xcb_send_event(conn, true, screen->root, XCB_EVENT_MASK_BUTTON_PRESS, (char *)event);
+ send_key_to_root(event, false);
return;
}
}
@@ -730,7 +759,7 @@ static void handle_key_press(xcb_key_press_event_t *event) {
case XKB_KEY_XF86PowerDown:
case XKB_KEY_XF86PowerOff:
case XKB_KEY_XF86Sleep:
- xcb_send_event(conn, true, screen->root, XCB_EVENT_MASK_BUTTON_PRESS, (char *)event);
+ send_key_to_root(event, false);
return;
}
}
@@ -741,7 +770,7 @@ static void handle_key_press(xcb_key_press_event_t *event) {
case XKB_KEY_XF86AudioMute:
case XKB_KEY_XF86AudioLowerVolume:
case XKB_KEY_XF86AudioRaiseVolume:
- xcb_send_event(conn, true, screen->root, XCB_EVENT_MASK_BUTTON_PRESS, (char *)event);
+ send_key_to_root(event, true);
return;
}
}
@@ -1543,6 +1572,7 @@ int main(int argc, char *argv[]) {
{"pass-screen-keys", no_argument, NULL, 602},
{"pass-power-keys", no_argument, NULL, 603},
{"pass-volume-keys", no_argument, NULL, 604},
+ {"special-passthrough", no_argument, NULL, 605},
// bar indicator stuff
{"bar-indicator", no_argument, NULL, 700},
@@ -2104,6 +2134,9 @@ int main(int argc, char *argv[]) {
case 604:
pass_volume_keys = true;
break;
+ case 605:
+ special_passthrough = true;
+ break;
// Bar indicator
case 700: