mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-25 14:57:20 +00:00
[client] main: add interface for modules to register key binds
This commit is contained in:
parent
03cb61f746
commit
fd4cfc2ff3
41
client/include/interface/app.h
Normal file
41
client/include/interface/app.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
||||
https://looking-glass.hostfission.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
typedef struct KeybindHandle * KeybindHandle;
|
||||
typedef void (*SuperEventFn)(SDL_Scancode key, void * opaque);
|
||||
|
||||
/**
|
||||
* Register a handler for the <super>+<key> combination
|
||||
* @param key The scancode to register
|
||||
* @param callback The function to be called when the combination is pressed
|
||||
* @param opaque A pointer to be passed to the callback, may be NULL
|
||||
* @retval A handle for the binding or NULL on failure.
|
||||
* The caller is required to release the handle via `app_release_keybind` when it is no longer required
|
||||
*/
|
||||
KeybindHandle app_register_keybind(SDL_Scancode key, SuperEventFn callback, void * opaque);
|
||||
|
||||
/**
|
||||
* Release an existing key binding
|
||||
* @param handle A pointer to the keybind handle to release, may be NULL
|
||||
*/
|
||||
void app_release_keybind(KeybindHandle * handle);
|
@ -45,9 +45,14 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "dynamic/renderers.h"
|
||||
#include "dynamic/clipboards.h"
|
||||
|
||||
#include "interface/app.h"
|
||||
|
||||
struct AppState
|
||||
{
|
||||
bool running;
|
||||
bool escapeActive;
|
||||
SDL_Scancode escapeAction;
|
||||
KeybindHandle bindings[SDL_NUM_SCANCODES];
|
||||
bool keyDown[SDL_NUM_SCANCODES];
|
||||
|
||||
bool haveSrcSize;
|
||||
@ -114,7 +119,7 @@ struct AppParams
|
||||
bool ignoreQuit;
|
||||
bool allowScreensaver;
|
||||
bool grabKeyboard;
|
||||
SDL_Scancode captureKey;
|
||||
SDL_Scancode escapeKey;
|
||||
bool disableAlerts;
|
||||
|
||||
bool forceRenderer;
|
||||
@ -153,7 +158,7 @@ struct AppParams params =
|
||||
.ignoreQuit = false,
|
||||
.allowScreensaver = true,
|
||||
.grabKeyboard = true,
|
||||
.captureKey = SDL_SCANCODE_SCROLLLOCK,
|
||||
.escapeKey = SDL_SCANCODE_SCROLLLOCK,
|
||||
.disableAlerts = false,
|
||||
.forceRenderer = false,
|
||||
.windowTitle = "Looking Glass (Client)"
|
||||
@ -166,6 +171,13 @@ struct CBRequest
|
||||
void * opaque;
|
||||
};
|
||||
|
||||
struct KeybindHandle
|
||||
{
|
||||
SDL_Scancode key;
|
||||
SuperEventFn callback;
|
||||
void * opaque;
|
||||
};
|
||||
|
||||
// forwards
|
||||
static int cursorThread(void * unused);
|
||||
static int renderThread(void * unused);
|
||||
@ -792,27 +804,16 @@ int eventFilter(void * userdata, SDL_Event * event)
|
||||
case SDL_KEYDOWN:
|
||||
{
|
||||
SDL_Scancode sc = event->key.keysym.scancode;
|
||||
if (sc == params.captureKey)
|
||||
if (sc == params.escapeKey)
|
||||
{
|
||||
if (event->key.repeat)
|
||||
break;
|
||||
state.escapeActive = true;
|
||||
state.escapeAction = sc;
|
||||
break;
|
||||
}
|
||||
|
||||
serverMode = !serverMode;
|
||||
spice_mouse_mode(serverMode);
|
||||
SDL_SetRelativeMouseMode(serverMode);
|
||||
SDL_SetWindowGrab(state.window, serverMode);
|
||||
DEBUG_INFO("Server Mode: %s", serverMode ? "on" : "off");
|
||||
|
||||
if (state.lgr && !params.disableAlerts)
|
||||
state.lgr->on_alert(
|
||||
state.lgrData,
|
||||
serverMode ? LG_ALERT_SUCCESS : LG_ALERT_WARNING,
|
||||
serverMode ? "Capture Enabled" : "Capture Disabled",
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!serverMode)
|
||||
realignGuest = true;
|
||||
if (state.escapeActive)
|
||||
{
|
||||
state.escapeAction = sc;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -836,8 +837,36 @@ int eventFilter(void * userdata, SDL_Event * event)
|
||||
case SDL_KEYUP:
|
||||
{
|
||||
SDL_Scancode sc = event->key.keysym.scancode;
|
||||
if (sc == params.captureKey)
|
||||
break;
|
||||
if (state.escapeActive)
|
||||
{
|
||||
if (state.escapeAction == params.escapeKey)
|
||||
{
|
||||
serverMode = !serverMode;
|
||||
spice_mouse_mode(serverMode);
|
||||
SDL_SetRelativeMouseMode(serverMode);
|
||||
SDL_SetWindowGrab(state.window, serverMode);
|
||||
DEBUG_INFO("Server Mode: %s", serverMode ? "on" : "off");
|
||||
|
||||
if (state.lgr && !params.disableAlerts)
|
||||
state.lgr->on_alert(
|
||||
state.lgrData,
|
||||
serverMode ? LG_ALERT_SUCCESS : LG_ALERT_WARNING,
|
||||
serverMode ? "Capture Enabled" : "Capture Disabled",
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!serverMode)
|
||||
realignGuest = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
KeybindHandle handle = state.bindings[sc];
|
||||
if (handle)
|
||||
handle->callback(sc, handle->opaque);
|
||||
}
|
||||
|
||||
state.escapeActive = false;
|
||||
}
|
||||
|
||||
// avoid sending key up events when we didn't send a down
|
||||
if (!state.keyDown[sc])
|
||||
@ -1370,7 +1399,7 @@ void doHelp(char * app)
|
||||
" -Q Ignore requests to quit (ie: Alt+F4)\n"
|
||||
" -S Disable the screensaver\n"
|
||||
" -G Don't capture the keyboard in capture mode\n"
|
||||
" -m CODE Specify the capture key [current: %u (%s)]\n"
|
||||
" -m CODE Specify the escape key [current: %u (%s)]\n"
|
||||
" See https://wiki.libsdl.org/SDLScancodeLookup for valid values\n"
|
||||
" -q Disable alert messages [current: %s]\n"
|
||||
" -t TITLE Use a custom title for the main window\n"
|
||||
@ -1388,9 +1417,9 @@ void doHelp(char * app)
|
||||
params.center ? "center" : y,
|
||||
params.w,
|
||||
params.h,
|
||||
params.captureKey,
|
||||
params.escapeKey,
|
||||
params.disableAlerts ? "disabled" : "enabled",
|
||||
SDL_GetScancodeName(params.captureKey)
|
||||
SDL_GetScancodeName(params.escapeKey)
|
||||
);
|
||||
}
|
||||
|
||||
@ -1515,7 +1544,7 @@ static bool load_config(const char * configFile)
|
||||
params.fpsLimit = (unsigned int)itmp;
|
||||
}
|
||||
|
||||
if (config_setting_lookup_int(global, "captureKey", &itmp))
|
||||
if (config_setting_lookup_int(global, "escapeKey", &itmp))
|
||||
{
|
||||
if (itmp <= SDL_SCANCODE_UNKNOWN || itmp > SDL_SCANCODE_APP2)
|
||||
{
|
||||
@ -1523,7 +1552,7 @@ static bool load_config(const char * configFile)
|
||||
config_destroy(&cfg);
|
||||
return false;
|
||||
}
|
||||
params.captureKey = (SDL_Scancode)itmp;
|
||||
params.escapeKey = (SDL_Scancode)itmp;
|
||||
}
|
||||
|
||||
if (config_setting_lookup_string(global, "windowTitle", &stmp))
|
||||
@ -1882,7 +1911,7 @@ int main(int argc, char * argv[])
|
||||
continue;
|
||||
|
||||
case 'm':
|
||||
params.captureKey = atoi(optarg);
|
||||
params.escapeKey = atoi(optarg);
|
||||
continue;
|
||||
|
||||
case 'q':
|
||||
@ -1926,4 +1955,32 @@ int main(int argc, char * argv[])
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
KeybindHandle app_register_keybind(SDL_Scancode key, SuperEventFn callback, void * opaque)
|
||||
{
|
||||
// don't allow duplicate binds
|
||||
if (state.bindings[key])
|
||||
{
|
||||
DEBUG_INFO("Key already bound");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
KeybindHandle handle = (KeybindHandle)malloc(sizeof(struct KeybindHandle));
|
||||
handle->key = key;
|
||||
handle->callback = callback;
|
||||
handle->opaque = opaque;
|
||||
|
||||
state.bindings[key] = handle;
|
||||
return handle;
|
||||
}
|
||||
|
||||
void app_release_keybind(KeybindHandle * handle)
|
||||
{
|
||||
if (!handle)
|
||||
return;
|
||||
|
||||
state.bindings[(*handle)->key] = NULL;
|
||||
free(*handle);
|
||||
*handle = NULL;
|
||||
}
|
Loading…
Reference in New Issue
Block a user