WIP: xinput support

related to #112
xinput
Michael Stapelberg 2020-02-23 19:43:43 +01:00
parent f3b061233e
commit 482f5b0a26
6 changed files with 164 additions and 3 deletions

View File

@ -48,7 +48,9 @@ i3lock_SOURCES = \
unlock_indicator.c \
unlock_indicator.h \
xcb.c \
xcb.h
xcb.h \
xinput.h \
xinput.c
EXTRA_DIST = \
$(pamd_files) \

View File

@ -90,7 +90,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])
PKG_CHECK_MODULES([XCB], [xcb xcb-xkb xcb-xinerama xcb-randr xcb-xinput])
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])

View File

@ -47,6 +47,7 @@
#include "unlock_indicator.h"
#include "randr.h"
#include "dpi.h"
#include "xinput.h"
#define TSTAMP_N_SECS(n) (n * 1.0)
#define TSTAMP_N_MINS(n) (60 * TSTAMP_N_SECS(n))
@ -1196,6 +1197,8 @@ int main(int argc, char *argv[]) {
randr_init(&randr_base, screen->root);
randr_query(screen->root);
xinput_init();
last_resolution[0] = screen->width_in_pixels;
last_resolution[1] = screen->height_in_pixels;
@ -1310,6 +1313,7 @@ int main(int argc, char *argv[]) {
DEBUG("restoring focus to X11 window 0x%08x\n", stolen_focus);
xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
xcb_ungrab_keyboard(conn, XCB_CURRENT_TIME);
xinput_ungrab();
xcb_destroy_window(conn, win);
set_focused_window(conn, screen->root, stolen_focus);
xcb_aux_sync(conn);

7
xcb.c
View File

@ -23,6 +23,7 @@
#include "cursors.h"
#include "unlock_indicator.h"
#include "xinput.h"
extern auth_state_t auth_state;
@ -303,7 +304,11 @@ bool grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb
}
}
return (tries > 0);
if (tries == 0) {
return false;
}
return xinput_grab(screen->root);
}
xcb_cursor_t create_cursor(xcb_connection_t *conn, xcb_screen_t *screen, xcb_window_t win, int choice) {

139
xinput.c Normal file
View File

@ -0,0 +1,139 @@
/*
* vim:ts=4:sw=4:expandtab
*
* © 2010 Michael Stapelberg
*
* See LICENSE for licensing information
*
*/
#include "xinput.h"
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <xcb/xcb.h>
#include <xcb/xinput.h>
#include "i3lock.h"
#include "xcb.h"
extern bool debug_mode;
static bool xinput_available = false;
void xinput_init(void) {
const xcb_query_extension_reply_t *extreply;
extreply = xcb_get_extension_data(conn, &xcb_input_id);
if (!extreply->present) {
DEBUG("xinput is not present\n");
return;
}
DEBUG("xinput: querying version\n");
xcb_generic_error_t *err = NULL;
xcb_input_xi_query_version_reply_t *xinput_version =
xcb_input_xi_query_version_reply(
conn, xcb_input_xi_query_version(conn, XCB_INPUT_MAJOR_VERSION, XCB_INPUT_MINOR_VERSION), &err);
if (err != NULL) {
DEBUG("Could not query xinput version: X11 error code %d\n", err->error_code);
return;
}
DEBUG("xinput %d.%d found\n",
xinput_version->major_version,
xinput_version->minor_version);
free(xinput_version);
xinput_available = true;
}
bool xinput_grab(xcb_window_t root_window) {
if (!xinput_available) {
return true;
}
xcb_generic_error_t *err = NULL;
xcb_input_xi_query_device_reply_t *devices =
xcb_input_xi_query_device_reply(
conn, xcb_input_xi_query_device(conn, XCB_INPUT_DEVICE_ALL_MASTER), &err);
if (err != NULL) {
DEBUG("xinput: querying devices: X11 error code %d\n", err->error_code);
return false;
}
xcb_input_xi_device_info_iterator_t device_iter;
for (device_iter = xcb_input_xi_query_device_infos_iterator(devices);
device_iter.rem;
xcb_input_xi_device_info_next(&device_iter)) {
xcb_input_xi_device_info_t *device_info = device_iter.data;
DEBUG("device %s\n",
xcb_input_xi_device_info_name(device_info));
// TODO: skip virtual core pointer/keyboard
const uint32_t mask =
XCB_INPUT_XI_EVENT_MASK_BUTTON_PRESS |
XCB_INPUT_XI_EVENT_MASK_BUTTON_RELEASE |
XCB_INPUT_XI_EVENT_MASK_MOTION |
XCB_INPUT_XI_EVENT_MASK_ENTER |
XCB_INPUT_XI_EVENT_MASK_LEAVE;
xcb_input_xi_grab_device_reply_t *reply =
xcb_input_xi_grab_device_reply(
conn,
xcb_input_xi_grab_device(conn,
root_window,
XCB_TIME_CURRENT_TIME,
XCB_CURSOR_NONE,
device_info->deviceid,
XCB_INPUT_GRAB_MODE_22_ASYNC,
XCB_INPUT_GRAB_MODE_22_ASYNC,
true /* owner_events */,
1,
&mask),
&err);
if (err != NULL) {
DEBUG("xinput: grabbing device %s: X11 error code %d\n",
xcb_input_xi_device_info_name(device_info),
err->error_code);
free(devices);
return false;
}
if (reply->status != 0 /* XiGrabSuccess */) {
free(reply);
free(devices);
return false;
}
free(reply);
}
free(devices);
return true;
}
void xinput_ungrab(void) {
if (!xinput_available) {
return;
}
xcb_generic_error_t *err = NULL;
xcb_input_xi_query_device_reply_t *devices =
xcb_input_xi_query_device_reply(
conn, xcb_input_xi_query_device(conn, XCB_INPUT_DEVICE_ALL_MASTER), &err);
if (err != NULL) {
DEBUG("xinput: querying devices: X11 error code %d\n", err->error_code);
return;
}
xcb_input_xi_device_info_iterator_t device_iter;
for (device_iter = xcb_input_xi_query_device_infos_iterator(devices);
device_iter.rem;
xcb_input_xi_device_info_next(&device_iter)) {
xcb_input_xi_device_info_t *device_info = device_iter.data;
// TODO: skip virtual core pointer/keyboard
xcb_input_xi_ungrab_device(conn, XCB_TIME_CURRENT_TIME, device_info->deviceid);
}
free(devices);
}

11
xinput.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef _XINPUT_H
#define _XINPUT_H
#include <stdbool.h>
#include <xcb.h>
void xinput_init(void);
bool xinput_grab(xcb_window_t root_window);
void xinput_ungrab(void);
#endif