[client] evdev: add new exclusive evdev while captured option
Some checks are pending
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Waiting to run
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Waiting to run
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Waiting to run
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Waiting to run
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Waiting to run
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Waiting to run
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Waiting to run
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Waiting to run
build / module (push) Waiting to run
build / host-linux (push) Waiting to run
build / host-windows-cross (push) Waiting to run
build / host-windows-native (push) Waiting to run
build / obs (clang) (push) Waiting to run
build / obs (gcc) (push) Waiting to run
build / docs (push) Waiting to run

This commit is contained in:
Geoffrey McRae 2025-03-07 13:47:01 +11:00
parent 7c285a45fb
commit afbd844be8
6 changed files with 115 additions and 14 deletions

View File

@ -44,3 +44,8 @@ void evdev_grabKeyboard(void);
* ungrab the keyboard
*/
void evdev_ungrabKeyboard(void);
/**
* returns true if input should only be processed by evdev
*/
bool evdev_isExclusive(void);

View File

@ -18,13 +18,14 @@
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "app.h"
#include "app_internal.h"
#include "main.h"
#include "core.h"
#include "util.h"
#include "clipboard.h"
#include "render_queue.h"
#include "evdev.h"
#include "kb.h"
@ -119,7 +120,7 @@ void app_handleFocusEvent(bool focused)
if (g_params.releaseKeysOnFocusLoss)
for (int key = 0; key < KEY_MAX; key++)
if (g_state.keyDown[key])
app_handleKeyRelease(key);
app_handleKeyReleaseInternal(key);
g_state.escapeActive = false;
@ -311,7 +312,7 @@ void app_handleWheelMotion(double motion)
g_state.io->MouseWheel -= motion;
}
void app_handleKeyPress(int sc)
void app_handleKeyPressInternal(int sc)
{
if (!app_isOverlayMode() || !g_state.io->WantCaptureKeyboard)
{
@ -375,7 +376,7 @@ void app_handleKeyPress(int sc)
}
}
void app_handleKeyRelease(int sc)
void app_handleKeyReleaseInternal(int sc)
{
if (g_state.escapeActive)
{
@ -420,6 +421,18 @@ void app_handleKeyRelease(int sc)
}
}
void app_handleKeyPress(int sc)
{
if (!evdev_isExclusive())
app_handleKeyPressInternal(sc);
}
void app_handleKeyRelease(int sc)
{
if (!evdev_isExclusive())
app_handleKeyReleaseInternal(sc);
}
void app_handleKeyboardTyped(const char * typed)
{
ImGuiIO_AddInputCharactersUTF8(g_state.io, typed);

View File

@ -21,6 +21,8 @@
#ifndef _H_LG_APP_INTERNAL_
#define _H_LG_APP_INTERNAL_
#include "app.h"
void app_handleKeyPressInternal(int scancode);
void app_handleKeyReleaseInternal(int scancode);

View File

@ -27,7 +27,8 @@
#include <string.h>
#include <sys/epoll.h>
#include "app.h"
#include "app_internal.h"
#include "main.h"
#include "common/debug.h"
#include "common/option.h"
@ -47,9 +48,23 @@ struct EvdevState
char * deviceList;
EvdevDevice * devices;
int deviceCount;
bool exclusive;
int keys[KEY_MAX];
void (*dsGrabKeyboard)(void);
void (*dsUngrabKeyboard)(void);
int epoll;
LGThread * thread;
bool grabbed;
enum
{
PENDING_NONE,
PENDING_GRAB,
PENDING_UNGRAB
}
pending;
};
static struct EvdevState state = {};
@ -64,6 +79,14 @@ static struct Option options[] =
.type = OPTION_TYPE_STRING,
.value.x_string = NULL,
},
{
.module = "input",
.name = "evdevExclusive",
.description = "Only use evdev devices for keyboard input when in capture "
"mode",
.type = OPTION_TYPE_BOOL,
.value.x_bool = true
},
{0}
};
@ -89,13 +112,35 @@ static int evdev_thread(void * opaque)
continue;
}
if (!state.grabbed || ev.type != EV_KEY)
if (ev.type != EV_KEY)
continue;
bool grabbed = state.grabbed;
if (ev.value == 1)
app_handleKeyPress(ev.code);
else if (ev.value == 0)
app_handleKeyRelease(ev.code);
{
++state.keys[ev.code];
if (grabbed && state.keys[ev.code] == 1)
app_handleKeyPressInternal(ev.code);
}
else if (ev.value == 0 && --state.keys[ev.code] <= 0)
{
state.keys[ev.code] = 0;
if (state.pending == PENDING_GRAB)
{
state.pending = PENDING_NONE;
evdev_grabKeyboard();
}
else if (state.pending == PENDING_UNGRAB)
{
state.pending = PENDING_NONE;
evdev_ungrabKeyboard();
}
if (grabbed)
app_handleKeyReleaseInternal(ev.code);
}
}
}
DEBUG_INFO("evdev_thread Stopped");
@ -128,6 +173,8 @@ bool evdev_start(void)
if (state.deviceCount == 0)
return false;
state.exclusive = option_get("input", "evdevExclusive");
state.epoll = epoll_create1(0);
if (state.epoll < 0)
{
@ -166,6 +213,12 @@ bool evdev_start(void)
return false;
}
//hook the display server's grab methods
state.dsGrabKeyboard = g_state.ds->grabKeyboard;
state.dsUngrabKeyboard = g_state.ds->ungrabKeyboard;
g_state.ds->grabKeyboard = &evdev_grabKeyboard;
g_state.ds->ungrabKeyboard = &evdev_ungrabKeyboard;
return true;
}
@ -201,6 +254,19 @@ void evdev_stop(void)
void evdev_grabKeyboard(void)
{
if (state.grabbed)
return;
// we must be in a neutral state
for(int i = 0; i < KEY_MAX; ++i)
if (state.keys[i] > 0)
{
state.pending = PENDING_GRAB;
return;
}
// state.dsGrabKeyboard();
for(EvdevDevice * device = state.devices; device->path; ++device)
{
if (device->fd <= 0 || device->grabbed)
@ -220,6 +286,17 @@ void evdev_grabKeyboard(void)
void evdev_ungrabKeyboard(void)
{
if (!state.grabbed)
return;
// we must be in a neutral state
for(int i = 0; i < KEY_MAX; ++i)
if (state.keys[i] > 0)
{
state.pending = PENDING_UNGRAB;
return;
}
for(EvdevDevice * device = state.devices; device->path; ++device)
{
if (device->fd <= 0 || !device->grabbed)
@ -234,5 +311,13 @@ void evdev_ungrabKeyboard(void)
DEBUG_INFO("Ungrabbed %s", device->path);
device->grabbed = false;
}
// state.dsUngrabKeyboard();
state.grabbed = false;
}
bool evdev_isExclusive(void)
{
return state.exclusive && state.grabbed && !app_isOverlayMode();
}

View File

@ -1242,12 +1242,7 @@ static int lg_run(void)
}
if (evdev_start())
{
DEBUG_INFO("Using evdev for keyboard capture");
//override the display server's grab methods if we are using evdev
g_state.ds->grabKeyboard = &evdev_grabKeyboard;
g_state.ds->ungrabKeyboard = &evdev_ungrabKeyboard;
}
// override the SIGINIT handler so that we can tell the difference between
// SIGINT and the user sending a close event, such as ALT+F4

View File

@ -72,6 +72,7 @@ struct AppState
bool modSuper;
uint64_t lastImGuiFrame;
bool renderImGuiTwice;
bool exclusiveEvdev;
struct LG_DisplayServerOps * ds;
bool dsInitialized;