Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add customisable shortcut keybinds #1705

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
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
43 changes: 10 additions & 33 deletions src/Backends/SDLBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "SDL_events.h"
#include "gamescope_shared.h"
#include "main.hpp"
#include "shortcut.h"
#include "wlserver.hpp"
#include <SDL.h>
#include <SDL_vulkan.h>
Expand Down Expand Up @@ -730,9 +731,7 @@ namespace gamescope
if ( event.key.keysym.mod & KMOD_LGUI )
{
uint32_t key = SDLScancodeToLinuxKey( event.key.keysym.scancode );
const uint32_t shortcutKeys[] = {KEY_F, KEY_N, KEY_B, KEY_U, KEY_Y, KEY_I, KEY_O, KEY_S, KEY_G};
const bool isShortcutKey = std::find(std::begin(shortcutKeys), std::end(shortcutKeys), key) != std::end(shortcutKeys);
if ( isShortcutKey )
if ( g_shortcutHandler.GetShortcut( key ) != GAMESCOPE_SHORTCUT_NONE )
{
break;
}
Expand All @@ -745,48 +744,26 @@ namespace gamescope

if ( event.type == SDL_KEYUP && ( event.key.keysym.mod & KMOD_LGUI ) )
{
bool handled = true;
switch ( key )
auto shortcut = g_shortcutHandler.GetShortcut( key );
g_shortcutHandler.HandleShortcut( shortcut );

switch ( shortcut )
{
case KEY_F:
case GAMESCOPE_SHORTCUT_FULLSCREEN:
g_bFullscreen = !g_bFullscreen;
SDL_SetWindowFullscreen( m_Connector.GetSDLWindow(), g_bFullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0 );
break;
case KEY_N:
g_wantedUpscaleFilter = GamescopeUpscaleFilter::PIXEL;
break;
case KEY_B:
g_wantedUpscaleFilter = GamescopeUpscaleFilter::LINEAR;
break;
case KEY_U:
g_wantedUpscaleFilter = (g_wantedUpscaleFilter == GamescopeUpscaleFilter::FSR) ?
GamescopeUpscaleFilter::LINEAR : GamescopeUpscaleFilter::FSR;
break;
case KEY_Y:
g_wantedUpscaleFilter = (g_wantedUpscaleFilter == GamescopeUpscaleFilter::NIS) ?
GamescopeUpscaleFilter::LINEAR : GamescopeUpscaleFilter::NIS;
break;
case KEY_I:
g_upscaleFilterSharpness = std::min(20, g_upscaleFilterSharpness + 1);
break;
case KEY_O:
g_upscaleFilterSharpness = std::max(0, g_upscaleFilterSharpness - 1);
break;
case KEY_S:
gamescope::CScreenshotManager::Get().TakeScreenshot( true );
break;
case KEY_G:
g_bGrabbed = !g_bGrabbed;
case GAMESCOPE_SHORTCUT_KEYBOARD_GRAB:
SDL_SetWindowKeyboardGrab( m_Connector.GetSDLWindow(), g_bGrabbed ? SDL_TRUE : SDL_FALSE );

SDL_Event event;
event.type = GetUserEventIndex( GAMESCOPE_SDL_EVENT_TITLE );
SDL_PushEvent( &event );
break;
default:
handled = false;
break;
}
if ( handled )
if ( shortcut != GAMESCOPE_SHORTCUT_NONE )
{
break;
}
Expand Down
79 changes: 7 additions & 72 deletions src/Backends/WaylandBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2544,81 +2544,16 @@ namespace gamescope

void CWaylandInputThread::HandleKey( uint32_t uKey, bool bPressed )
{
if ( m_uKeyModifiers & m_uModMask[ GAMESCOPE_WAYLAND_MOD_META ] )
if ( !bPressed && m_uKeyModifiers & m_uModMask[ GAMESCOPE_WAYLAND_MOD_META ] )
{
switch ( uKey )
{
case KEY_F:
{
if ( !bPressed )
{
static_cast< CWaylandConnector * >( m_pBackend->GetCurrentConnector() )->SetFullscreen( !g_bFullscreen );
}
return;
}

case KEY_N:
{
if ( !bPressed )
{
g_wantedUpscaleFilter = GamescopeUpscaleFilter::PIXEL;
}
return;
}
auto shortcut = g_shortcutHandler.GetShortcut( uKey );
g_shortcutHandler.HandleShortcut( shortcut );

case KEY_B:
{
if ( !bPressed )
{
g_wantedUpscaleFilter = GamescopeUpscaleFilter::LINEAR;
}
return;
}

case KEY_U:
{
if ( !bPressed )
{
g_wantedUpscaleFilter = ( g_wantedUpscaleFilter == GamescopeUpscaleFilter::FSR ) ?
GamescopeUpscaleFilter::LINEAR : GamescopeUpscaleFilter::FSR;
}
return;
}

case KEY_Y:
{
if ( !bPressed )
{
g_wantedUpscaleFilter = ( g_wantedUpscaleFilter == GamescopeUpscaleFilter::NIS ) ?
GamescopeUpscaleFilter::LINEAR : GamescopeUpscaleFilter::NIS;
}
return;
}

case KEY_I:
{
if ( !bPressed )
{
g_upscaleFilterSharpness = std::min( 20, g_upscaleFilterSharpness + 1 );
}
return;
}

case KEY_O:
{
if ( !bPressed )
{
g_upscaleFilterSharpness = std::max( 0, g_upscaleFilterSharpness - 1 );
}
return;
}

case KEY_S:
switch ( shortcut )
{
case GAMESCOPE_SHORTCUT_FULLSCREEN:
{
if ( !bPressed )
{
gamescope::CScreenshotManager::Get().TakeScreenshot( true );
}
static_cast< CWaylandConnector * >( m_pBackend->GetCurrentConnector() )->SetFullscreen( !g_bFullscreen );
return;
}

Expand Down
2 changes: 2 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,8 @@ float g_flMaxWindowScale = FLT_MAX;
uint32_t g_preferVendorID = 0;
uint32_t g_preferDeviceID = 0;

gamescope::ShortcutHandler g_shortcutHandler = {};

pthread_t g_mainThread;

static void steamCompMgrThreadRun(int argc, char **argv);
Expand Down
3 changes: 3 additions & 0 deletions src/main.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include <atomic>

#include "shortcut.h"

extern const char *gamescope_optstring;
extern const struct option *gamescope_options;

Expand Down Expand Up @@ -73,3 +75,4 @@ extern int g_nXWaylandCount;
extern uint32_t g_preferVendorID;
extern uint32_t g_preferDeviceID;

extern gamescope::ShortcutHandler g_shortcutHandler;
1 change: 1 addition & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ src = [
'mangoapp.cpp',
'Timeline.cpp',
'reshade_effect_manager.cpp',
'shortcut.cpp',
'backend.cpp',
'x11cursor.cpp',
'InputEmulation.cpp',
Expand Down
183 changes: 183 additions & 0 deletions src/shortcut.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
#include <linux/input-event-codes.h>

#include "shortcut.h"
#include "convar.h"
#include "steamcompmgr_shared.hpp"
#include "main.hpp"

namespace gamescope
{
ShortcutHandler::ShortcutHandler()
{
// default mappings
m_binds = {
{ KEY_F, GAMESCOPE_SHORTCUT_FULLSCREEN },
{ KEY_N, GAMESCOPE_SHORTCUT_FILTER_NEAREST },
{ KEY_B, GAMESCOPE_SHORTCUT_FILTER_LINEAR },
{ KEY_U, GAMESCOPE_SHORTCUT_UPSCALE_FSR },
{ KEY_Y, GAMESCOPE_SHORTCUT_UPSCALE_NIS },
{ KEY_I, GAMESCOPE_SHORTCUT_UPSCALE_SHARPNESS_UP },
{ KEY_O, GAMESCOPE_SHORTCUT_UPSCALE_SHARPNESS_DOWN },
{ KEY_S, GAMESCOPE_SHORTCUT_SCREENSHOT },
{ KEY_G, GAMESCOPE_SHORTCUT_KEYBOARD_GRAB }
};
}

ShortcutHandler::~ShortcutHandler() {}

void ShortcutHandler::Bind( uint32_t key, GamescopeShortcut shortcut )
{
Unbind( key );
m_binds.insert( { key, shortcut } );
}

void ShortcutHandler::Unbind( uint32_t key )
{
m_binds.erase( key );
}

void ShortcutHandler::Unbind( GamescopeShortcut shortcut )
{
m_binds.erase( shortcut );
}

GamescopeShortcut ShortcutHandler::GetShortcut( uint32_t key )
{
if (auto it = m_binds.find( key ); it != m_binds.end())
{
return it->second;
}

return GAMESCOPE_SHORTCUT_NONE;
}

void ShortcutHandler::HandleShortcut( GamescopeShortcut shortcut )
{
switch ( shortcut )
{
case GAMESCOPE_SHORTCUT_FILTER_NEAREST:
g_wantedUpscaleFilter = GamescopeUpscaleFilter::PIXEL;
break;
case GAMESCOPE_SHORTCUT_FILTER_LINEAR:
g_wantedUpscaleFilter = GamescopeUpscaleFilter::LINEAR;
break;
case GAMESCOPE_SHORTCUT_UPSCALE_FSR:
g_wantedUpscaleFilter = (g_wantedUpscaleFilter == GamescopeUpscaleFilter::FSR) ?
GamescopeUpscaleFilter::LINEAR : GamescopeUpscaleFilter::FSR;
break;
case GAMESCOPE_SHORTCUT_UPSCALE_NIS:
g_wantedUpscaleFilter = (g_wantedUpscaleFilter == GamescopeUpscaleFilter::NIS) ?
GamescopeUpscaleFilter::LINEAR : GamescopeUpscaleFilter::NIS;
break;
case GAMESCOPE_SHORTCUT_UPSCALE_SHARPNESS_UP:
g_upscaleFilterSharpness = std::min( 20, g_upscaleFilterSharpness + 1 );
break;
case GAMESCOPE_SHORTCUT_UPSCALE_SHARPNESS_DOWN:
g_upscaleFilterSharpness = std::max( 0, g_upscaleFilterSharpness - 1 );
break;
case GAMESCOPE_SHORTCUT_SCREENSHOT:
gamescope::CScreenshotManager::Get().TakeScreenshot( true );
break;
case GAMESCOPE_SHORTCUT_KEYBOARD_GRAB:
g_bGrabbed = !g_bGrabbed;
break;
default:
break;
}
}

static const char* ShortcutNames[GAMESCOPE_SHORTCUT_COUNT] = {
"",
"fullscreen",
"filter_nearest",
"filter_linear",
"upscale_fsr",
"upscale_nis",
"upscale_sharpness_up",
"upscale_sharpness_down",
"screenshot",
"keyboard_grab",
};

static GamescopeShortcut ParseShortcut( std::string_view sv )
{
if ( sv.length() > 0 )
{
for ( auto i = 0; i < GAMESCOPE_SHORTCUT_COUNT; i++ )
{
if ( sv == ShortcutNames[i] )
{
return static_cast<GamescopeShortcut>( i );
}
}
}

return GAMESCOPE_SHORTCUT_NONE;
}

static ConCommand cc_bind( "bind",
"Bind a shortcut to SUPER-<key> combination. e.g. 'bind 33,fullscreen'",
[](std::span<std::string_view> svArgs )
{
if ( svArgs.size() < 2 )
{
console_log.errorf( "Invalid number of arguments." );
return;
}

// Space delimited args would be nice but requires
// changes to gamescopectl / gamescope_private_execute.
auto svBinds = gamescope::Split( svArgs[1], "," );
if ( svBinds.size() < 2 )
{
console_log.errorf( "Invalid number of arguments." );
return;
}

// TODO: key names
std::optional<uint32_t> ouKey = Parse<uint32_t>( svBinds[0] );
if ( !ouKey )
{
console_log.errorf( "Failed to parse key." );
return;
}

uint32_t uKey = *ouKey;
auto shortcut = ParseShortcut( svBinds[1] );

if ( shortcut != GAMESCOPE_SHORTCUT_NONE )
{
g_shortcutHandler.Bind( uKey, shortcut );
}
});

static ConCommand cc_unbind( "unbind", "Unbind a shortcut from SUPER-<key> combination.",
[](std::span<std::string_view> svArgs )
{
if ( svArgs.size() < 2 )
{
console_log.errorf( "Invalid number of arguments." );
return;
}

// TODO: key names
std::optional<uint32_t> ouKey = Parse<uint32_t>( svArgs[1] );
if ( !ouKey )
{
console_log.errorf( "Failed to parse key." );
return;
}

g_shortcutHandler.Unbind( *ouKey );
});

static ConCommand cc_shortcuts( "shortcuts", "List shortcut names for use with 'bind'",
[](std::span<std::string_view> svArgs )
{
console_log.infof( "Shortcut names:" );
for ( auto i = 0; i < GAMESCOPE_SHORTCUT_COUNT; i++ )
{
console_log.infof( " %s", ShortcutNames[i] );
}
});
}
Loading
Loading