Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions src/Backends/WaylandBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "waitable.h"
#include "Utils/TempFiles.h"

#include <condition_variable>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
Expand Down Expand Up @@ -521,6 +522,8 @@ namespace gamescope

void SetRelativePointer( bool bRelative );

::xkb_keymap *Wayland_GetParentKeymap() const;

private:

void HandleKey( uint32_t uKey, bool bPressed );
Expand Down Expand Up @@ -548,7 +551,7 @@ namespace gamescope
uint32_t m_uFakeTimestamp = 0;

xkb_context *m_pXkbContext = nullptr;
xkb_keymap *m_pXkbKeymap = nullptr;
::xkb_keymap *m_pXkbKeymap = nullptr;

uint32_t m_uKeyModifiers = 0;
uint32_t m_uModMask[ GAMESCOPE_WAYLAND_MOD_COUNT ];
Expand Down Expand Up @@ -626,6 +629,7 @@ namespace gamescope
.modifiers = WAYLAND_USERDATA_TO_THIS( CWaylandInputThread, Wayland_Keyboard_Modifiers ),
.repeat_info = WAYLAND_USERDATA_TO_THIS( CWaylandInputThread, Wayland_Keyboard_RepeatInfo ),
};

const zwp_relative_pointer_v1_listener CWaylandInputThread::s_RelativePointerListener =
{
.relative_motion = WAYLAND_USERDATA_TO_THIS( CWaylandInputThread, Wayland_RelativePointer_RelativeMotion ),
Expand Down Expand Up @@ -676,6 +680,8 @@ namespace gamescope

virtual bool UsesVirtualConnectors() override;
virtual std::shared_ptr<IBackendConnector> CreateVirtualConnector( uint64_t ulVirtualConnectorKey ) override;

::xkb_keymap *GetParentKeymap() const override;
protected:
virtual void OnBackendBlobDestroyed( BackendBlob *pBlob ) override;

Expand Down Expand Up @@ -2349,6 +2355,11 @@ namespace gamescope
return pConnector;
}

::xkb_keymap *CWaylandBackend::GetParentKeymap() const
{
return m_InputThread.Wayland_GetParentKeymap();
}

///////////////////
// INestedHints
///////////////////
Expand Down Expand Up @@ -2891,6 +2902,10 @@ namespace gamescope
}
}

::xkb_keymap *CWaylandInputThread::Wayland_GetParentKeymap() const{
return m_pXkbKeymap;
}

void CWaylandInputThread::HandleKey( uint32_t uKey, bool bPressed )
{
if ( m_uKeyModifiers & m_uModMask[ GAMESCOPE_WAYLAND_MOD_META ] )
Expand Down Expand Up @@ -3148,9 +3163,6 @@ namespace gamescope

void CWaylandInputThread::Wayland_Keyboard_Keymap( wl_keyboard *pKeyboard, uint32_t uFormat, int32_t nFd, uint32_t uSize )
{
// We are not doing much with the keymap, we pass keycodes thru.
// Ideally we'd use this to influence our keymap to clients, eg. x server.

defer( close( nFd ) );
if ( uFormat != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 )
return;
Expand All @@ -3163,7 +3175,12 @@ namespace gamescope
}
defer( munmap( pMap, uSize ) );

xkb_keymap *pKeymap = xkb_keymap_new_from_string( m_pXkbContext, pMap, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS );
::xkb_keymap *pKeymap = xkb_keymap_new_from_string(
m_pXkbContext,
pMap,
XKB_KEYMAP_FORMAT_TEXT_V1,
XKB_KEYMAP_COMPILE_NO_FLAGS
);
if ( !pKeymap )
{
xdg_log.errorf( "Failed to create xkb_keymap" );
Expand Down
4 changes: 4 additions & 0 deletions src/backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include <variant>
#include <any>

#include <xkbcommon/xkbcommon.h>

struct wlr_buffer;
struct wlr_dmabuf_attributes;

Expand Down Expand Up @@ -404,6 +406,8 @@ namespace gamescope

virtual void OnEndFrame() = 0;

virtual ::xkb_keymap *GetParentKeymap() const { return nullptr; }

static IBackend *Get();
template <typename T>
static bool Set();
Expand Down
6 changes: 4 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1033,9 +1033,11 @@ int main(int argc, char **argv)
if ( g_nNestedWidth == 0 )
g_nNestedWidth = g_nNestedHeight * 16 / 9;

if ( !wlserver_init() )
::xkb_keymap *parent_keymap = GetBackend()->GetParentKeymap();

if (!wlserver_init(parent_keymap))
{
fprintf( stderr, "Failed to initialize wlserver\n" );
fprintf(stderr, "Failed to initialize wlserver\n");
return 1;
}

Expand Down
2 changes: 2 additions & 0 deletions src/steamcompmgr.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#pragma once

#include <stdint.h>

#include "wlr_begin.hpp"
Expand Down
97 changes: 82 additions & 15 deletions src/wlserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ struct wlserver_content_override {
std::mutex g_wlserver_xdg_shell_windows_lock;

static struct wl_list pending_surfaces = {0};

static std::atomic<bool> g_bShutdownWLServer{ false };

static void wlserver_x11_surface_info_set_wlr( struct wlserver_x11_surface_info *surf, struct wlr_surface *wlr_surf, bool override );
Expand Down Expand Up @@ -484,7 +483,7 @@ static void wlserver_new_input(struct wl_listener *listener, void *data)
case WLR_INPUT_DEVICE_KEYBOARD:
{
struct wlr_keyboard *keyboard = wlr_keyboard_from_input_device(device);
wlr_keyboard_set_keymap(keyboard, wlserver.keyboard_group->keyboard.keymap);

if (!wlr_keyboard_group_add_keyboard(wlserver.keyboard_group, keyboard)) {
wl_log.errorf("failed to add physical keyboard %s", device->name);
break;
Expand Down Expand Up @@ -1936,7 +1935,7 @@ static gamescope::CAsyncWaiter g_LibEisWaiter( "gamescope-eis" );
static std::unique_ptr<gamescope::GamescopeInputServer> g_InputServer;
#endif

bool wlserver_init( void ) {
bool wlserver_init( ::xkb_keymap *p_keymap ) {
assert( wlserver.display != nullptr );

wl_list_init(&pending_surfaces);
Expand Down Expand Up @@ -1967,21 +1966,15 @@ bool wlserver_init( void ) {
wlserver.wlr.virtual_keyboard_device = kbd;

// Create a keyboard group to keep all externally connected keyboards
// in sync (one single layout and a shared state)
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
struct xkb_rule_names rules = { 0 };
rules.rules = getenv("XKB_DEFAULT_RULES");
rules.model = getenv("XKB_DEFAULT_MODEL");
rules.layout = getenv("XKB_DEFAULT_LAYOUT");
rules.variant = getenv("XKB_DEFAULT_VARIANT");
rules.options = getenv("XKB_DEFAULT_OPTIONS");
struct xkb_keymap *keymap = xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
wlserver.keyboard_group = wlr_keyboard_group_create();
// in sync (one single layout and a shared state) - defer keymap to later
wlserver.keyboard_group = wlr_keyboard_group_create();
struct wlr_keyboard *keyboard = &wlserver.keyboard_group->keyboard;
wlr_keyboard_set_repeat_info(keyboard, 25, 600);
wlr_keyboard_set_keymap(keyboard, keymap);
wlserver.keyboard_group_modifiers.notify = wlserver_handle_modifiers;
wl_signal_add(&keyboard->events.modifiers, &wlserver.keyboard_group_modifiers);
wl_signal_add(
&keyboard->events.modifiers,
&wlserver.keyboard_group_modifiers
);
wlserver.keyboard_group_key.notify = wlserver_handle_key;
wl_signal_add(&keyboard->events.key, &wlserver.keyboard_group_key);

Expand Down Expand Up @@ -2088,6 +2081,80 @@ bool wlserver_init( void ) {
return false;
}

// Backend initialized, input_devices populated. Now we can extract keymap
// from parent, then override with any set env vars
Comment thread
ninetailedtori marked this conversation as resolved.
::xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
::xkb_rule_names rules = { 0 };
::xkb_keymap *keymap = nullptr;

// Fetch xkb env vars from session
const char *env_rules = getenv("XKB_DEFAULT_RULES");
const char *env_model = getenv("XKB_DEFAULT_MODEL");
const char *env_layout = getenv("XKB_DEFAULT_LAYOUT");
const char *env_variant = getenv("XKB_DEFAULT_VARIANT");
const char *env_options = getenv("XKB_DEFAULT_OPTIONS");

// priority: env overrides parent keymap overrides default
if (
env_rules
|| env_model
|| env_layout
|| env_options
)
{
// Build keymap from env
rules.rules = env_rules ? : "evdev";
rules.model = env_model ? : "pc105";
rules.layout = env_layout ? : "us";
rules.variant = (env_layout && env_variant) ? env_variant : NULL;
rules.options = env_options;
keymap = xkb_keymap_new_from_names(
context,
&rules,
XKB_KEYMAP_COMPILE_NO_FLAGS
);
}

// Note: xkb_keymap_new_from_names can fail and leave keymap UB. This is
// why we check.
if (keymap)
{
wl_log.infof("Using xkb_keymap from environment variables");
}
else if (p_keymap)
{
// Ref parent session's keymap
keymap = xkb_keymap_ref(p_keymap);
wl_log.infof("Using parent session xkb_keymap");
}

// Build default keymap as fallback
if (!keymap)
{
rules.rules = "evdev";
rules.model = "pc105";
rules.layout = "us";
rules.variant = NULL;
rules.options = NULL;
keymap = xkb_keymap_new_from_names(
context,
&rules,
XKB_KEYMAP_COMPILE_NO_FLAGS
);

if (keymap)
{
wl_log.infof("Using default xkb_keymap.");
}
else
{
wl_log.errorf("Failed to create any xkb_keymap.");
return false;
}
}

wlr_keyboard_set_keymap(kbd, keymap);

wl_signal_emit( &wlserver.wlr.multi_backend->events.new_input, kbd );

#if HAVE_LIBEIS
Expand Down
2 changes: 1 addition & 1 deletion src/wlserver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ bool wlsession_init( void );
int wlsession_open_kms( const char *device_name );
void wlsession_close_kms();

bool wlserver_init( void );
bool wlserver_init(::xkb_keymap *p_keymap = nullptr);

void wlserver_run(void);

Expand Down