mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-25 23:07:18 +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/renderers.h"
|
||||||
#include "dynamic/clipboards.h"
|
#include "dynamic/clipboards.h"
|
||||||
|
|
||||||
|
#include "interface/app.h"
|
||||||
|
|
||||||
struct AppState
|
struct AppState
|
||||||
{
|
{
|
||||||
bool running;
|
bool running;
|
||||||
|
bool escapeActive;
|
||||||
|
SDL_Scancode escapeAction;
|
||||||
|
KeybindHandle bindings[SDL_NUM_SCANCODES];
|
||||||
bool keyDown[SDL_NUM_SCANCODES];
|
bool keyDown[SDL_NUM_SCANCODES];
|
||||||
|
|
||||||
bool haveSrcSize;
|
bool haveSrcSize;
|
||||||
@ -114,7 +119,7 @@ struct AppParams
|
|||||||
bool ignoreQuit;
|
bool ignoreQuit;
|
||||||
bool allowScreensaver;
|
bool allowScreensaver;
|
||||||
bool grabKeyboard;
|
bool grabKeyboard;
|
||||||
SDL_Scancode captureKey;
|
SDL_Scancode escapeKey;
|
||||||
bool disableAlerts;
|
bool disableAlerts;
|
||||||
|
|
||||||
bool forceRenderer;
|
bool forceRenderer;
|
||||||
@ -153,7 +158,7 @@ struct AppParams params =
|
|||||||
.ignoreQuit = false,
|
.ignoreQuit = false,
|
||||||
.allowScreensaver = true,
|
.allowScreensaver = true,
|
||||||
.grabKeyboard = true,
|
.grabKeyboard = true,
|
||||||
.captureKey = SDL_SCANCODE_SCROLLLOCK,
|
.escapeKey = SDL_SCANCODE_SCROLLLOCK,
|
||||||
.disableAlerts = false,
|
.disableAlerts = false,
|
||||||
.forceRenderer = false,
|
.forceRenderer = false,
|
||||||
.windowTitle = "Looking Glass (Client)"
|
.windowTitle = "Looking Glass (Client)"
|
||||||
@ -166,6 +171,13 @@ struct CBRequest
|
|||||||
void * opaque;
|
void * opaque;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct KeybindHandle
|
||||||
|
{
|
||||||
|
SDL_Scancode key;
|
||||||
|
SuperEventFn callback;
|
||||||
|
void * opaque;
|
||||||
|
};
|
||||||
|
|
||||||
// forwards
|
// forwards
|
||||||
static int cursorThread(void * unused);
|
static int cursorThread(void * unused);
|
||||||
static int renderThread(void * unused);
|
static int renderThread(void * unused);
|
||||||
@ -792,27 +804,16 @@ int eventFilter(void * userdata, SDL_Event * event)
|
|||||||
case SDL_KEYDOWN:
|
case SDL_KEYDOWN:
|
||||||
{
|
{
|
||||||
SDL_Scancode sc = event->key.keysym.scancode;
|
SDL_Scancode sc = event->key.keysym.scancode;
|
||||||
if (sc == params.captureKey)
|
if (sc == params.escapeKey)
|
||||||
{
|
{
|
||||||
if (event->key.repeat)
|
state.escapeActive = true;
|
||||||
|
state.escapeAction = sc;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
serverMode = !serverMode;
|
if (state.escapeActive)
|
||||||
spice_mouse_mode(serverMode);
|
{
|
||||||
SDL_SetRelativeMouseMode(serverMode);
|
state.escapeAction = sc;
|
||||||
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;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -836,8 +837,36 @@ int eventFilter(void * userdata, SDL_Event * event)
|
|||||||
case SDL_KEYUP:
|
case SDL_KEYUP:
|
||||||
{
|
{
|
||||||
SDL_Scancode sc = event->key.keysym.scancode;
|
SDL_Scancode sc = event->key.keysym.scancode;
|
||||||
if (sc == params.captureKey)
|
if (state.escapeActive)
|
||||||
break;
|
{
|
||||||
|
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
|
// avoid sending key up events when we didn't send a down
|
||||||
if (!state.keyDown[sc])
|
if (!state.keyDown[sc])
|
||||||
@ -1370,7 +1399,7 @@ void doHelp(char * app)
|
|||||||
" -Q Ignore requests to quit (ie: Alt+F4)\n"
|
" -Q Ignore requests to quit (ie: Alt+F4)\n"
|
||||||
" -S Disable the screensaver\n"
|
" -S Disable the screensaver\n"
|
||||||
" -G Don't capture the keyboard in capture mode\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"
|
" See https://wiki.libsdl.org/SDLScancodeLookup for valid values\n"
|
||||||
" -q Disable alert messages [current: %s]\n"
|
" -q Disable alert messages [current: %s]\n"
|
||||||
" -t TITLE Use a custom title for the main window\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.center ? "center" : y,
|
||||||
params.w,
|
params.w,
|
||||||
params.h,
|
params.h,
|
||||||
params.captureKey,
|
params.escapeKey,
|
||||||
params.disableAlerts ? "disabled" : "enabled",
|
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;
|
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)
|
if (itmp <= SDL_SCANCODE_UNKNOWN || itmp > SDL_SCANCODE_APP2)
|
||||||
{
|
{
|
||||||
@ -1523,7 +1552,7 @@ static bool load_config(const char * configFile)
|
|||||||
config_destroy(&cfg);
|
config_destroy(&cfg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
params.captureKey = (SDL_Scancode)itmp;
|
params.escapeKey = (SDL_Scancode)itmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config_setting_lookup_string(global, "windowTitle", &stmp))
|
if (config_setting_lookup_string(global, "windowTitle", &stmp))
|
||||||
@ -1882,7 +1911,7 @@ int main(int argc, char * argv[])
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
params.captureKey = atoi(optarg);
|
params.escapeKey = atoi(optarg);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 'q':
|
case 'q':
|
||||||
@ -1927,3 +1956,31 @@ int main(int argc, char * argv[])
|
|||||||
|
|
||||||
return ret;
|
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