mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-26 07:17:23 +00:00
[client/common] restructure project in prep for full SDL removal
This commit is contained in:
parent
6f1c19b3b0
commit
bf583290a4
@ -99,11 +99,14 @@ link_libraries(
|
|||||||
set(SOURCES
|
set(SOURCES
|
||||||
${CMAKE_BINARY_DIR}/version.c
|
${CMAKE_BINARY_DIR}/version.c
|
||||||
src/main.c
|
src/main.c
|
||||||
|
src/core.c
|
||||||
src/app.c
|
src/app.c
|
||||||
src/config.c
|
src/config.c
|
||||||
src/lg-renderer.c
|
src/lg-renderer.c
|
||||||
src/ll.c
|
src/ll.c
|
||||||
src/utils.c
|
src/util.c
|
||||||
|
src/clipboard.c
|
||||||
|
src/kb.c
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory("${PROJECT_TOP}/common" "${CMAKE_BINARY_DIR}/common" )
|
add_subdirectory("${PROJECT_TOP}/common" "${CMAKE_BINARY_DIR}/common" )
|
||||||
|
@ -128,12 +128,12 @@ static bool sdlEventFilter(SDL_Event * event)
|
|||||||
switch(event->window.event)
|
switch(event->window.event)
|
||||||
{
|
{
|
||||||
case SDL_WINDOWEVENT_ENTER:
|
case SDL_WINDOWEVENT_ENTER:
|
||||||
app_handleWindowEnter();
|
app_handleEnterEvent(true);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case SDL_WINDOWEVENT_LEAVE:
|
case SDL_WINDOWEVENT_LEAVE:
|
||||||
sdl.exiting = false;
|
sdl.exiting = false;
|
||||||
app_handleWindowLeave();
|
app_handleEnterEvent(false);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||||
|
@ -372,7 +372,7 @@ static bool x11EventFilter(SDL_Event * event)
|
|||||||
|
|
||||||
XIEnterEvent *xie = cookie->data;
|
XIEnterEvent *xie = cookie->data;
|
||||||
app_updateCursorPos(xie->event_x, xie->event_y);
|
app_updateCursorPos(xie->event_x, xie->event_y);
|
||||||
app_handleWindowEnter();
|
app_handleEnterEvent(true);
|
||||||
x11.entered = true;
|
x11.entered = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -384,7 +384,7 @@ static bool x11EventFilter(SDL_Event * event)
|
|||||||
|
|
||||||
XILeaveEvent *xie = cookie->data;
|
XILeaveEvent *xie = cookie->data;
|
||||||
app_updateCursorPos(xie->event_x, xie->event_y);
|
app_updateCursorPos(xie->event_x, xie->event_y);
|
||||||
app_handleWindowLeave();
|
app_handleEnterEvent(false);
|
||||||
x11.entered = false;
|
x11.entered = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#include "interface/displayserver.h"
|
#include "interface/displayserver.h"
|
||||||
|
|
||||||
|
|
||||||
SDL_Window * app_getWindow(void);
|
SDL_Window * app_getWindow(void);
|
||||||
|
|
||||||
bool app_getProp(LG_DSProperty prop, void * ret);
|
bool app_getProp(LG_DSProperty prop, void * ret);
|
||||||
@ -39,8 +38,7 @@ void app_handleButtonPress(int button);
|
|||||||
void app_handleButtonRelease(int button);
|
void app_handleButtonRelease(int button);
|
||||||
void app_handleKeyPress(int scancode);
|
void app_handleKeyPress(int scancode);
|
||||||
void app_handleKeyRelease(int scancode);
|
void app_handleKeyRelease(int scancode);
|
||||||
void app_handleWindowEnter(void);
|
void app_handleEnterEvent(bool entered);
|
||||||
void app_handleWindowLeave(void);
|
|
||||||
void app_handleFocusEvent(bool focused);
|
void app_handleFocusEvent(bool focused);
|
||||||
void app_handleCloseEvent(void);
|
void app_handleCloseEvent(void);
|
||||||
|
|
||||||
|
@ -105,10 +105,10 @@ struct LG_DisplayServerOps
|
|||||||
void (*uninhibitIdle)();
|
void (*uninhibitIdle)();
|
||||||
|
|
||||||
/* clipboard support */
|
/* clipboard support */
|
||||||
bool (* cbInit)(void);
|
bool (*cbInit)(void);
|
||||||
void (* cbNotice)(LG_ClipboardData type);
|
void (*cbNotice)(LG_ClipboardData type);
|
||||||
void (* cbRelease)(void);
|
void (*cbRelease)(void);
|
||||||
void (* cbRequest)(LG_ClipboardData type);
|
void (*cbRequest)(LG_ClipboardData type);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
37
client/include/util.h
Normal file
37
client/include/util.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _H_LG_UTIL_
|
||||||
|
#define _H_LG_UTIL_
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "common/types.h"
|
||||||
|
|
||||||
|
// reads the specified file into a new buffer
|
||||||
|
// the callee must free the buffer
|
||||||
|
bool util_fileGetContents(const char * filename, char ** buffer, size_t * length);
|
||||||
|
|
||||||
|
void util_cursorToInt(double ex, double ey, int *x, int *y);
|
||||||
|
bool util_guestCurToLocal(struct DoublePoint *local);
|
||||||
|
void util_localCurToGuest(struct DoublePoint *guest);
|
||||||
|
void util_rotatePoint(struct DoublePoint *point);
|
||||||
|
bool util_isValidCursorLocation(int x, int y);
|
||||||
|
|
||||||
|
#endif
|
@ -24,7 +24,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "common/sysinfo.h"
|
#include "common/sysinfo.h"
|
||||||
#include "common/time.h"
|
#include "common/time.h"
|
||||||
#include "common/locking.h"
|
#include "common/locking.h"
|
||||||
#include "utils.h"
|
#include "util.h"
|
||||||
#include "dynamic/fonts.h"
|
#include "dynamic/fonts.h"
|
||||||
|
|
||||||
#include <SDL2/SDL_syswm.h>
|
#include <SDL2/SDL_syswm.h>
|
||||||
|
@ -19,7 +19,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#include "fps.h"
|
#include "fps.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
|
@ -22,7 +22,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
|
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "utils.h"
|
|
||||||
#include "ll.h"
|
#include "ll.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -19,7 +19,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "utils.h"
|
#include "util.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -63,7 +63,7 @@ bool egl_shader_load(EGL_Shader * this, const char * vertex_file, const char * f
|
|||||||
char * vertex_code, * fragment_code;
|
char * vertex_code, * fragment_code;
|
||||||
size_t vertex_size, fragment_size;
|
size_t vertex_size, fragment_size;
|
||||||
|
|
||||||
if (!file_get_contents(vertex_file, &vertex_code, &vertex_size))
|
if (!util_fileGetContents(vertex_file, &vertex_code, &vertex_size))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to read vertex shader");
|
DEBUG_ERROR("Failed to read vertex shader");
|
||||||
return false;
|
return false;
|
||||||
@ -71,7 +71,7 @@ bool egl_shader_load(EGL_Shader * this, const char * vertex_file, const char * f
|
|||||||
|
|
||||||
DEBUG_INFO("Loaded vertex shader: %s", vertex_file);
|
DEBUG_INFO("Loaded vertex shader: %s", vertex_file);
|
||||||
|
|
||||||
if (!file_get_contents(fragment_file, &fragment_code, &fragment_size))
|
if (!util_fileGetContents(fragment_file, &fragment_code, &fragment_size))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to read fragment shader");
|
DEBUG_ERROR("Failed to read fragment shader");
|
||||||
free(vertex_code);
|
free(vertex_code);
|
||||||
|
@ -19,7 +19,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#include "splash.h"
|
#include "splash.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
|
@ -21,7 +21,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/framebuffer.h"
|
#include "common/framebuffer.h"
|
||||||
#include "dynprocs.h"
|
#include "dynprocs.h"
|
||||||
#include "utils.h"
|
|
||||||
#include "egldebug.h"
|
#include "egldebug.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
537
client/src/app.c
537
client/src/app.c
@ -17,13 +17,22 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "app.h"
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "core.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "clipboard.h"
|
||||||
|
|
||||||
|
#include "ll.h"
|
||||||
|
#include "kb.h"
|
||||||
|
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
void app_alert(LG_MsgAlert type, const char * fmt, ...)
|
void app_alert(LG_MsgAlert type, const char * fmt, ...)
|
||||||
{
|
{
|
||||||
if (!g_state.lgr || !params.showAlerts)
|
if (!g_state.lgr || !g_params.showAlerts)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
@ -73,3 +82,529 @@ void app_release_keybind(KeybindHandle * handle)
|
|||||||
free(*handle);
|
free(*handle);
|
||||||
*handle = NULL;
|
*handle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool app_getProp(LG_DSProperty prop, void * ret)
|
||||||
|
{
|
||||||
|
return g_state.ds->getProp(prop, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Window * app_getWindow(void)
|
||||||
|
{
|
||||||
|
return g_state.window;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool app_inputEnabled(void)
|
||||||
|
{
|
||||||
|
return g_params.useSpiceInput && !g_state.ignoreInput &&
|
||||||
|
((g_cursor.grab && g_params.captureInputOnly) || !g_params.captureInputOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool app_cursorInWindow(void)
|
||||||
|
{
|
||||||
|
return g_cursor.inWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool app_cursorIsGrabbed(void)
|
||||||
|
{
|
||||||
|
return g_cursor.grab;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool app_cursorWantsRaw(void)
|
||||||
|
{
|
||||||
|
return g_params.rawMouse;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_updateCursorPos(double x, double y)
|
||||||
|
{
|
||||||
|
g_cursor.pos.x = x;
|
||||||
|
g_cursor.pos.y = y;
|
||||||
|
g_cursor.valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_handleFocusEvent(bool focused)
|
||||||
|
{
|
||||||
|
g_state.focused = focused;
|
||||||
|
if (!app_inputEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!focused)
|
||||||
|
{
|
||||||
|
core_setGrabQuiet(false);
|
||||||
|
core_setCursorInView(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_cursor.realign = true;
|
||||||
|
g_state.ds->realignPointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_handleEnterEvent(bool entered)
|
||||||
|
{
|
||||||
|
if (entered)
|
||||||
|
{
|
||||||
|
g_cursor.inWindow = true;
|
||||||
|
if (!app_inputEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_cursor.realign = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_cursor.inWindow = false;
|
||||||
|
core_setCursorInView(false);
|
||||||
|
|
||||||
|
if (!app_inputEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!g_params.alwaysShowCursor)
|
||||||
|
g_cursor.draw = false;
|
||||||
|
g_cursor.redraw = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_clipboardRelease(void)
|
||||||
|
{
|
||||||
|
if (!g_params.clipboardToVM)
|
||||||
|
return;
|
||||||
|
|
||||||
|
spice_clipboard_release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_clipboardNotify(const LG_ClipboardData type, size_t size)
|
||||||
|
{
|
||||||
|
if (!g_params.clipboardToVM)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (type == LG_CLIPBOARD_DATA_NONE)
|
||||||
|
{
|
||||||
|
spice_clipboard_release();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_state.cbType = cb_lgTypeToSpiceType(type);
|
||||||
|
g_state.cbChunked = size > 0;
|
||||||
|
g_state.cbXfer = size;
|
||||||
|
|
||||||
|
spice_clipboard_grab(g_state.cbType);
|
||||||
|
|
||||||
|
if (size)
|
||||||
|
spice_clipboard_data_start(g_state.cbType, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_clipboardData(const LG_ClipboardData type, uint8_t * data, size_t size)
|
||||||
|
{
|
||||||
|
if (!g_params.clipboardToVM)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (g_state.cbChunked && size > g_state.cbXfer)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("refusing to send more then cbXfer bytes for chunked xfer");
|
||||||
|
size = g_state.cbXfer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_state.cbChunked)
|
||||||
|
spice_clipboard_data_start(g_state.cbType, size);
|
||||||
|
|
||||||
|
spice_clipboard_data(g_state.cbType, data, (uint32_t)size);
|
||||||
|
g_state.cbXfer -= size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_clipboardRequest(const LG_ClipboardReplyFn replyFn, void * opaque)
|
||||||
|
{
|
||||||
|
if (!g_params.clipboardToLocal)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct CBRequest * cbr = (struct CBRequest *)malloc(sizeof(struct CBRequest));
|
||||||
|
|
||||||
|
cbr->type = g_state.cbType;
|
||||||
|
cbr->replyFn = replyFn;
|
||||||
|
cbr->opaque = opaque;
|
||||||
|
ll_push(g_state.cbRequestList, cbr);
|
||||||
|
|
||||||
|
spice_clipboard_request(g_state.cbType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spiceClipboardNotice(const SpiceDataType type)
|
||||||
|
{
|
||||||
|
if (!g_params.clipboardToLocal)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!g_state.cbAvailable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_state.cbType = type;
|
||||||
|
g_state.ds->cbNotice(cb_spiceTypeToLGType(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_handleMouseGrabbed(double ex, double ey)
|
||||||
|
{
|
||||||
|
if (!app_inputEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
if (g_params.rawMouse && !g_cursor.useScale)
|
||||||
|
{
|
||||||
|
/* raw unscaled input are always round numbers */
|
||||||
|
x = floor(ex);
|
||||||
|
y = floor(ey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* apply sensitivity */
|
||||||
|
ex = (ex / 10.0) * (g_cursor.sens + 10);
|
||||||
|
ey = (ey / 10.0) * (g_cursor.sens + 10);
|
||||||
|
util_cursorToInt(ex, ey, &x, &y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x == 0 && y == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!spice_mouse_motion(x, y))
|
||||||
|
DEBUG_ERROR("failed to send mouse motion message");
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_handleButtonPress(int button)
|
||||||
|
{
|
||||||
|
if (!app_inputEnabled() || !g_cursor.inView)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_cursor.buttons |= (1U << button);
|
||||||
|
|
||||||
|
if (!spice_mouse_press(button))
|
||||||
|
DEBUG_ERROR("SDL_MOUSEBUTTONDOWN: failed to send message");
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_handleButtonRelease(int button)
|
||||||
|
{
|
||||||
|
if (!app_inputEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_cursor.buttons &= ~(1U << button);
|
||||||
|
|
||||||
|
if (!spice_mouse_release(button))
|
||||||
|
DEBUG_ERROR("SDL_MOUSEBUTTONUP: failed to send message");
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_handleKeyPress(int sc)
|
||||||
|
{
|
||||||
|
if (sc == g_params.escapeKey && !g_state.escapeActive)
|
||||||
|
{
|
||||||
|
g_state.escapeActive = true;
|
||||||
|
g_state.escapeAction = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_state.escapeActive)
|
||||||
|
{
|
||||||
|
g_state.escapeAction = sc;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!app_inputEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (g_params.ignoreWindowsKeys && (sc == KEY_LEFTMETA || sc == KEY_RIGHTMETA))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!g_state.keyDown[sc])
|
||||||
|
{
|
||||||
|
uint32_t ps2 = xfree86_to_ps2[sc];
|
||||||
|
if (!ps2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (spice_key_down(ps2))
|
||||||
|
g_state.keyDown[sc] = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("SDL_KEYDOWN: failed to send message");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_handleKeyRelease(int sc)
|
||||||
|
{
|
||||||
|
if (g_state.escapeActive)
|
||||||
|
{
|
||||||
|
if (g_state.escapeAction == -1)
|
||||||
|
{
|
||||||
|
if (g_params.useSpiceInput)
|
||||||
|
core_setGrab(!g_cursor.grab);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KeybindHandle handle = g_state.bindings[sc];
|
||||||
|
if (handle)
|
||||||
|
{
|
||||||
|
handle->callback(sc, handle->opaque);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sc == g_params.escapeKey)
|
||||||
|
g_state.escapeActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!app_inputEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// avoid sending key up events when we didn't send a down
|
||||||
|
if (!g_state.keyDown[sc])
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (g_params.ignoreWindowsKeys && (sc == KEY_LEFTMETA || sc == KEY_RIGHTMETA))
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32_t ps2 = xfree86_to_ps2[sc];
|
||||||
|
if (!ps2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (spice_key_up(ps2))
|
||||||
|
g_state.keyDown[sc] = false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("SDL_KEYUP: failed to send message");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_handleMouseNormal(double ex, double ey)
|
||||||
|
{
|
||||||
|
// prevent cursor handling outside of capture if the position is not known
|
||||||
|
if (!g_cursor.guest.valid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!app_inputEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* scale the movement to the guest */
|
||||||
|
if (g_cursor.useScale && g_params.scaleMouseInput)
|
||||||
|
{
|
||||||
|
ex *= g_cursor.scale.x / g_cursor.dpiScale;
|
||||||
|
ey *= g_cursor.scale.y / g_cursor.dpiScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool testExit = true;
|
||||||
|
if (!g_cursor.inView)
|
||||||
|
{
|
||||||
|
const bool inView =
|
||||||
|
g_cursor.pos.x >= g_state.dstRect.x &&
|
||||||
|
g_cursor.pos.x < g_state.dstRect.x + g_state.dstRect.w &&
|
||||||
|
g_cursor.pos.y >= g_state.dstRect.y &&
|
||||||
|
g_cursor.pos.y < g_state.dstRect.y + g_state.dstRect.h;
|
||||||
|
|
||||||
|
core_setCursorInView(inView);
|
||||||
|
if (inView)
|
||||||
|
g_cursor.realign = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* nothing to do if we are outside the viewport */
|
||||||
|
if (!g_cursor.inView)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do not pass mouse events to the guest if we do not have focus, this must be
|
||||||
|
* done after the inView test has been performed so that when focus is gained
|
||||||
|
* we know if we should be drawing the cursor.
|
||||||
|
*/
|
||||||
|
if (!g_state.focused)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* if we have been instructed to realign */
|
||||||
|
if (g_cursor.realign)
|
||||||
|
{
|
||||||
|
g_cursor.realign = false;
|
||||||
|
|
||||||
|
struct DoublePoint guest;
|
||||||
|
util_localCurToGuest(&guest);
|
||||||
|
|
||||||
|
/* add the difference to the offset */
|
||||||
|
ex += guest.x - (g_cursor.guest.x + g_cursor.guest.hx);
|
||||||
|
ey += guest.y - (g_cursor.guest.y + g_cursor.guest.hy);
|
||||||
|
|
||||||
|
/* don't test for an exit as we just entered, we can get into a enter/exit
|
||||||
|
* loop otherwise */
|
||||||
|
testExit = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we are in "autoCapture" and the delta was large don't test for exit */
|
||||||
|
if (g_params.autoCapture &&
|
||||||
|
(fabs(ex) > 100.0 / g_cursor.scale.x || fabs(ey) > 100.0 / g_cursor.scale.y))
|
||||||
|
testExit = false;
|
||||||
|
|
||||||
|
/* if any buttons are held we should not allow exit to happen */
|
||||||
|
if (g_cursor.buttons)
|
||||||
|
testExit = false;
|
||||||
|
|
||||||
|
if (testExit)
|
||||||
|
{
|
||||||
|
/* translate the move to the guests orientation */
|
||||||
|
struct DoublePoint move = {.x = ex, .y = ey};
|
||||||
|
util_rotatePoint(&move);
|
||||||
|
|
||||||
|
/* translate the guests position to our coordinate space */
|
||||||
|
struct DoublePoint local;
|
||||||
|
util_guestCurToLocal(&local);
|
||||||
|
|
||||||
|
/* check if the move would push the cursor outside the guest's viewport */
|
||||||
|
if (
|
||||||
|
local.x + move.x < g_state.dstRect.x ||
|
||||||
|
local.y + move.y < g_state.dstRect.y ||
|
||||||
|
local.x + move.x >= g_state.dstRect.x + g_state.dstRect.w ||
|
||||||
|
local.y + move.y >= g_state.dstRect.y + g_state.dstRect.h)
|
||||||
|
{
|
||||||
|
local.x += move.x;
|
||||||
|
local.y += move.y;
|
||||||
|
const int tx = (local.x <= 0.0) ? floor(local.x) : ceil(local.x);
|
||||||
|
const int ty = (local.y <= 0.0) ? floor(local.y) : ceil(local.y);
|
||||||
|
|
||||||
|
if (util_isValidCursorLocation(
|
||||||
|
g_state.windowPos.x + g_state.border.x + tx,
|
||||||
|
g_state.windowPos.y + g_state.border.y + ty))
|
||||||
|
{
|
||||||
|
core_setCursorInView(false);
|
||||||
|
|
||||||
|
/* preempt the window leave flag if the warp will leave our window */
|
||||||
|
if (tx < 0 || ty < 0 || tx > g_state.windowW || ty > g_state.windowH)
|
||||||
|
g_cursor.inWindow = false;
|
||||||
|
|
||||||
|
/* ungrab the pointer and move the local cursor to the exit point */
|
||||||
|
g_state.ds->ungrabPointer();
|
||||||
|
core_warpPointer(tx, ty, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
util_cursorToInt(ex, ey, &x, &y);
|
||||||
|
|
||||||
|
if (x == 0 && y == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (g_params.autoCapture)
|
||||||
|
{
|
||||||
|
g_cursor.delta.x += x;
|
||||||
|
g_cursor.delta.y += y;
|
||||||
|
|
||||||
|
if (fabs(g_cursor.delta.x) > 50.0 || fabs(g_cursor.delta.y) > 50.0)
|
||||||
|
{
|
||||||
|
g_cursor.delta.x = 0;
|
||||||
|
g_cursor.delta.y = 0;
|
||||||
|
core_warpPointer(g_state.windowCX, g_state.windowCY, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_cursor.guest.x = g_state.srcSize.x / 2;
|
||||||
|
g_cursor.guest.y = g_state.srcSize.y / 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* assume the mouse will move to the location we attempt to move it to so we
|
||||||
|
* avoid warp out of window issues. The cursorThread will correct this if
|
||||||
|
* wrong after the movement has ocurred on the guest */
|
||||||
|
g_cursor.guest.x += x;
|
||||||
|
g_cursor.guest.y += y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!spice_mouse_motion(x, y))
|
||||||
|
DEBUG_ERROR("failed to send mouse motion message");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// On some display servers normal cursor logic does not work due to the lack of
|
||||||
|
// cursor warp support. Instead, we attempt a best-effort emulation which works
|
||||||
|
// with a 1:1 mouse movement patch applied in the guest. For anything fancy, use
|
||||||
|
// capture mode.
|
||||||
|
void app_handleMouseBasic()
|
||||||
|
{
|
||||||
|
/* do not pass mouse events to the guest if we do not have focus */
|
||||||
|
if (!g_state.focused)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!app_inputEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const bool inView =
|
||||||
|
g_cursor.pos.x >= g_state.dstRect.x &&
|
||||||
|
g_cursor.pos.x < g_state.dstRect.x + g_state.dstRect.w &&
|
||||||
|
g_cursor.pos.y >= g_state.dstRect.y &&
|
||||||
|
g_cursor.pos.y < g_state.dstRect.y + g_state.dstRect.h;
|
||||||
|
|
||||||
|
core_setCursorInView(inView);
|
||||||
|
|
||||||
|
if (g_cursor.guest.dpiScale == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
double px = g_cursor.pos.x;
|
||||||
|
double py = g_cursor.pos.y;
|
||||||
|
|
||||||
|
if (px < g_state.dstRect.x)
|
||||||
|
px = g_state.dstRect.x;
|
||||||
|
else if (px > g_state.dstRect.x + g_state.dstRect.w)
|
||||||
|
px = g_state.dstRect.x + g_state.dstRect.w;
|
||||||
|
|
||||||
|
if (py < g_state.dstRect.y)
|
||||||
|
py = g_state.dstRect.y;
|
||||||
|
else if (py > g_state.dstRect.y + g_state.dstRect.h)
|
||||||
|
py = g_state.dstRect.y + g_state.dstRect.h;
|
||||||
|
|
||||||
|
/* translate the guests position to our coordinate space */
|
||||||
|
struct DoublePoint local;
|
||||||
|
util_guestCurToLocal(&local);
|
||||||
|
|
||||||
|
int x = (int) round((px - local.x) / g_cursor.dpiScale);
|
||||||
|
int y = (int) round((py - local.y) / g_cursor.dpiScale);
|
||||||
|
|
||||||
|
if (!x && !y)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_cursor.guest.x += x;
|
||||||
|
g_cursor.guest.y += y;
|
||||||
|
|
||||||
|
if (!spice_mouse_motion(x, y))
|
||||||
|
DEBUG_ERROR("failed to send mouse motion message");
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_updateWindowPos(int x, int y)
|
||||||
|
{
|
||||||
|
g_state.windowPos.x = x;
|
||||||
|
g_state.windowPos.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_handleResizeEvent(int w, int h)
|
||||||
|
{
|
||||||
|
SDL_GetWindowBordersSize(g_state.window,
|
||||||
|
&g_state.border.y,
|
||||||
|
&g_state.border.x,
|
||||||
|
&g_state.border.h,
|
||||||
|
&g_state.border.w
|
||||||
|
);
|
||||||
|
|
||||||
|
/* don't do anything else if the window dimensions have not changed */
|
||||||
|
if (g_state.windowW == w && g_state.windowH == h)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_state.windowW = w;
|
||||||
|
g_state.windowH = h;
|
||||||
|
g_state.windowCX = w / 2;
|
||||||
|
g_state.windowCY = h / 2;
|
||||||
|
core_updatePositionInfo();
|
||||||
|
|
||||||
|
if (app_inputEnabled())
|
||||||
|
{
|
||||||
|
/* if the window is moved/resized causing a loss of focus while grabbed, it
|
||||||
|
* makes it impossible to re-focus the window, so we quietly re-enter
|
||||||
|
* capture if we were already in it */
|
||||||
|
if (g_cursor.grab)
|
||||||
|
{
|
||||||
|
core_setGrabQuiet(false);
|
||||||
|
core_setGrabQuiet(true);
|
||||||
|
}
|
||||||
|
core_alignToGuest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_handleCloseEvent(void)
|
||||||
|
{
|
||||||
|
if (!g_params.ignoreQuit || !g_cursor.inView)
|
||||||
|
g_state.state = APP_STATE_SHUTDOWN;
|
||||||
|
}
|
||||||
|
116
client/src/clipboard.c
Normal file
116
client/src/clipboard.c
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
|
Copyright (C) 2017-2021 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "clipboard.h"
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "ll.h"
|
||||||
|
|
||||||
|
#include "common/debug.h"
|
||||||
|
|
||||||
|
LG_ClipboardData cb_spiceTypeToLGType(const SpiceDataType type)
|
||||||
|
{
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case SPICE_DATA_TEXT: return LG_CLIPBOARD_DATA_TEXT; break;
|
||||||
|
case SPICE_DATA_PNG : return LG_CLIPBOARD_DATA_PNG ; break;
|
||||||
|
case SPICE_DATA_BMP : return LG_CLIPBOARD_DATA_BMP ; break;
|
||||||
|
case SPICE_DATA_TIFF: return LG_CLIPBOARD_DATA_TIFF; break;
|
||||||
|
case SPICE_DATA_JPEG: return LG_CLIPBOARD_DATA_JPEG; break;
|
||||||
|
default:
|
||||||
|
DEBUG_ERROR("invalid spice data type");
|
||||||
|
return LG_CLIPBOARD_DATA_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SpiceDataType cb_lgTypeToSpiceType(const LG_ClipboardData type)
|
||||||
|
{
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case LG_CLIPBOARD_DATA_TEXT: return SPICE_DATA_TEXT; break;
|
||||||
|
case LG_CLIPBOARD_DATA_PNG : return SPICE_DATA_PNG ; break;
|
||||||
|
case LG_CLIPBOARD_DATA_BMP : return SPICE_DATA_BMP ; break;
|
||||||
|
case LG_CLIPBOARD_DATA_TIFF: return SPICE_DATA_TIFF; break;
|
||||||
|
case LG_CLIPBOARD_DATA_JPEG: return SPICE_DATA_JPEG; break;
|
||||||
|
default:
|
||||||
|
DEBUG_ERROR("invalid clipboard data type");
|
||||||
|
return SPICE_DATA_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cb_spiceNotice(const SpiceDataType type)
|
||||||
|
{
|
||||||
|
if (!g_params.clipboardToLocal)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!g_state.cbAvailable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_state.cbType = type;
|
||||||
|
g_state.ds->cbNotice(cb_spiceTypeToLGType(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
void cb_spiceData(const SpiceDataType type, uint8_t * buffer, uint32_t size)
|
||||||
|
{
|
||||||
|
if (!g_params.clipboardToLocal)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (type == SPICE_DATA_TEXT)
|
||||||
|
{
|
||||||
|
// dos2unix
|
||||||
|
uint8_t * p = buffer;
|
||||||
|
uint32_t newSize = size;
|
||||||
|
for(uint32_t i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
uint8_t c = buffer[i];
|
||||||
|
if (c == '\r')
|
||||||
|
{
|
||||||
|
--newSize;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*p++ = c;
|
||||||
|
}
|
||||||
|
size = newSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CBRequest * cbr;
|
||||||
|
if (ll_shift(g_state.cbRequestList, (void **)&cbr))
|
||||||
|
{
|
||||||
|
cbr->replyFn(cbr->opaque, cb_spiceTypeToLGType(type), buffer, size);
|
||||||
|
free(cbr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cb_spiceRelease(void)
|
||||||
|
{
|
||||||
|
if (!g_params.clipboardToLocal)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (g_state.cbAvailable)
|
||||||
|
g_state.ds->cbRelease();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cb_spiceRequest(const SpiceDataType type)
|
||||||
|
{
|
||||||
|
if (!g_params.clipboardToVM)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (g_state.cbAvailable)
|
||||||
|
g_state.ds->cbRequest(cb_spiceTypeToLGType(type));
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2021 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -17,17 +17,13 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#include "spice/spice.h"
|
||||||
#include "interface/decoder.h"
|
#include "interface/displayserver.h"
|
||||||
|
|
||||||
extern const LG_Decoder LGD_NULL;
|
LG_ClipboardData cb_spiceTypeToLGType(const SpiceDataType type);
|
||||||
extern const LG_Decoder LGD_YUV420;
|
SpiceDataType cb_lgTypeToSpiceType(const LG_ClipboardData type);
|
||||||
|
|
||||||
const LG_Decoder * LG_Decoders[] =
|
void cb_spiceNotice(const SpiceDataType type);
|
||||||
{
|
void cb_spiceData(const SpiceDataType type, uint8_t * buffer, uint32_t size);
|
||||||
&LGD_NULL,
|
void cb_spiceRelease(void);
|
||||||
&LGD_YUV420,
|
void cb_spiceRequest(const SpiceDataType type);
|
||||||
NULL // end of array sentinal
|
|
||||||
};
|
|
||||||
|
|
||||||
#define LG_DECODER_COUNT ((sizeof(LG_Decoders) / sizeof(LG_Decoder *)) - 1)
|
|
@ -411,9 +411,9 @@ static struct Option options[] =
|
|||||||
|
|
||||||
void config_init(void)
|
void config_init(void)
|
||||||
{
|
{
|
||||||
params.center = true;
|
g_params.center = true;
|
||||||
params.w = 1024;
|
g_params.w = 1024;
|
||||||
params.h = 768;
|
g_params.h = 768;
|
||||||
|
|
||||||
option_register(options);
|
option_register(options);
|
||||||
}
|
}
|
||||||
@ -468,72 +468,72 @@ bool config_load(int argc, char * argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setup the application params for the basic types
|
// setup the application params for the basic types
|
||||||
params.cursorPollInterval = option_get_int ("app", "cursorPollInterval");
|
g_params.cursorPollInterval = option_get_int ("app", "cursorPollInterval");
|
||||||
params.framePollInterval = option_get_int ("app", "framePollInterval" );
|
g_params.framePollInterval = option_get_int ("app", "framePollInterval" );
|
||||||
params.allowDMA = option_get_bool ("app", "allowDMA" );
|
g_params.allowDMA = option_get_bool ("app", "allowDMA" );
|
||||||
|
|
||||||
params.windowTitle = option_get_string("win", "title" );
|
g_params.windowTitle = option_get_string("win", "title" );
|
||||||
params.autoResize = option_get_bool ("win", "autoResize" );
|
g_params.autoResize = option_get_bool ("win", "autoResize" );
|
||||||
params.allowResize = option_get_bool ("win", "allowResize" );
|
g_params.allowResize = option_get_bool ("win", "allowResize" );
|
||||||
params.keepAspect = option_get_bool ("win", "keepAspect" );
|
g_params.keepAspect = option_get_bool ("win", "keepAspect" );
|
||||||
params.forceAspect = option_get_bool ("win", "forceAspect" );
|
g_params.forceAspect = option_get_bool ("win", "forceAspect" );
|
||||||
params.dontUpscale = option_get_bool ("win", "dontUpscale" );
|
g_params.dontUpscale = option_get_bool ("win", "dontUpscale" );
|
||||||
params.borderless = option_get_bool ("win", "borderless" );
|
g_params.borderless = option_get_bool ("win", "borderless" );
|
||||||
params.fullscreen = option_get_bool ("win", "fullScreen" );
|
g_params.fullscreen = option_get_bool ("win", "fullScreen" );
|
||||||
params.maximize = option_get_bool ("win", "maximize" );
|
g_params.maximize = option_get_bool ("win", "maximize" );
|
||||||
params.fpsMin = option_get_int ("win", "fpsMin" );
|
g_params.fpsMin = option_get_int ("win", "fpsMin" );
|
||||||
params.showFPS = option_get_bool ("win", "showFPS" );
|
g_params.showFPS = option_get_bool ("win", "showFPS" );
|
||||||
params.ignoreQuit = option_get_bool ("win", "ignoreQuit" );
|
g_params.ignoreQuit = option_get_bool ("win", "ignoreQuit" );
|
||||||
params.noScreensaver = option_get_bool ("win", "noScreensaver");
|
g_params.noScreensaver = option_get_bool ("win", "noScreensaver");
|
||||||
params.showAlerts = option_get_bool ("win", "alerts" );
|
g_params.showAlerts = option_get_bool ("win", "alerts" );
|
||||||
params.quickSplash = option_get_bool ("win", "quickSplash" );
|
g_params.quickSplash = option_get_bool ("win", "quickSplash" );
|
||||||
|
|
||||||
switch(option_get_int("win", "rotate"))
|
switch(option_get_int("win", "rotate"))
|
||||||
{
|
{
|
||||||
case 0 : params.winRotate = LG_ROTATE_0 ; break;
|
case 0 : g_params.winRotate = LG_ROTATE_0 ; break;
|
||||||
case 90 : params.winRotate = LG_ROTATE_90 ; break;
|
case 90 : g_params.winRotate = LG_ROTATE_90 ; break;
|
||||||
case 180: params.winRotate = LG_ROTATE_180; break;
|
case 180: g_params.winRotate = LG_ROTATE_180; break;
|
||||||
case 270: params.winRotate = LG_ROTATE_270; break;
|
case 270: g_params.winRotate = LG_ROTATE_270; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
params.grabKeyboard = option_get_bool("input", "grabKeyboard" );
|
g_params.grabKeyboard = option_get_bool("input", "grabKeyboard" );
|
||||||
params.grabKeyboardOnFocus = option_get_bool("input", "grabKeyboardOnFocus");
|
g_params.grabKeyboardOnFocus = option_get_bool("input", "grabKeyboardOnFocus");
|
||||||
params.escapeKey = option_get_int ("input", "escapeKey" );
|
g_params.escapeKey = option_get_int ("input", "escapeKey" );
|
||||||
params.ignoreWindowsKeys = option_get_bool("input", "ignoreWindowsKeys" );
|
g_params.ignoreWindowsKeys = option_get_bool("input", "ignoreWindowsKeys" );
|
||||||
params.hideMouse = option_get_bool("input", "hideCursor" );
|
g_params.hideMouse = option_get_bool("input", "hideCursor" );
|
||||||
params.mouseSens = option_get_int ("input", "mouseSens" );
|
g_params.mouseSens = option_get_int ("input", "mouseSens" );
|
||||||
params.mouseSmoothing = option_get_bool("input", "mouseSmoothing" );
|
g_params.mouseSmoothing = option_get_bool("input", "mouseSmoothing" );
|
||||||
params.rawMouse = option_get_bool("input", "rawMouse" );
|
g_params.rawMouse = option_get_bool("input", "rawMouse" );
|
||||||
params.mouseRedraw = option_get_bool("input", "mouseRedraw" );
|
g_params.mouseRedraw = option_get_bool("input", "mouseRedraw" );
|
||||||
params.autoCapture = option_get_bool("input", "autoCapture" );
|
g_params.autoCapture = option_get_bool("input", "autoCapture" );
|
||||||
params.captureInputOnly = option_get_bool("input", "captureOnly" );
|
g_params.captureInputOnly = option_get_bool("input", "captureOnly" );
|
||||||
|
|
||||||
params.minimizeOnFocusLoss = option_get_bool("win", "minimizeOnFocusLoss");
|
g_params.minimizeOnFocusLoss = option_get_bool("win", "minimizeOnFocusLoss");
|
||||||
|
|
||||||
if (option_get_bool("spice", "enable"))
|
if (option_get_bool("spice", "enable"))
|
||||||
{
|
{
|
||||||
params.spiceHost = option_get_string("spice", "host");
|
g_params.spiceHost = option_get_string("spice", "host");
|
||||||
params.spicePort = option_get_int ("spice", "port");
|
g_params.spicePort = option_get_int ("spice", "port");
|
||||||
|
|
||||||
params.useSpiceInput = option_get_bool("spice", "input" );
|
g_params.useSpiceInput = option_get_bool("spice", "input" );
|
||||||
params.useSpiceClipboard = option_get_bool("spice", "clipboard");
|
g_params.useSpiceClipboard = option_get_bool("spice", "clipboard");
|
||||||
|
|
||||||
if (params.useSpiceClipboard)
|
if (g_params.useSpiceClipboard)
|
||||||
{
|
{
|
||||||
params.clipboardToVM = option_get_bool("spice", "clipboardToVM" );
|
g_params.clipboardToVM = option_get_bool("spice", "clipboardToVM" );
|
||||||
params.clipboardToLocal = option_get_bool("spice", "clipboardToLocal");
|
g_params.clipboardToLocal = option_get_bool("spice", "clipboardToLocal");
|
||||||
|
|
||||||
if (!params.clipboardToVM && !params.clipboardToLocal)
|
if (!g_params.clipboardToVM && !g_params.clipboardToLocal)
|
||||||
params.useSpiceClipboard = false;
|
g_params.useSpiceClipboard = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
params.scaleMouseInput = option_get_bool("spice", "scaleCursor");
|
g_params.scaleMouseInput = option_get_bool("spice", "scaleCursor");
|
||||||
params.captureOnStart = option_get_bool("spice", "captureOnStart");
|
g_params.captureOnStart = option_get_bool("spice", "captureOnStart");
|
||||||
params.alwaysShowCursor = option_get_bool("spice", "alwaysShowCursor");
|
g_params.alwaysShowCursor = option_get_bool("spice", "alwaysShowCursor");
|
||||||
}
|
}
|
||||||
|
|
||||||
//FIXME, this should be using linux keycodes
|
//FIXME, this should be using linux keycodes
|
||||||
params.escapeKey = sdl_to_xfree86[params.escapeKey];
|
g_params.escapeKey = sdl_to_xfree86[g_params.escapeKey];
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -574,15 +574,15 @@ static bool optRendererParse(struct Option * opt, const char * str)
|
|||||||
|
|
||||||
if (strcasecmp(str, "auto") == 0)
|
if (strcasecmp(str, "auto") == 0)
|
||||||
{
|
{
|
||||||
params.forceRenderer = false;
|
g_params.forceRenderer = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned int i = 0; i < LG_RENDERER_COUNT; ++i)
|
for(unsigned int i = 0; i < LG_RENDERER_COUNT; ++i)
|
||||||
if (strcasecmp(str, LG_Renderers[i]->get_name()) == 0)
|
if (strcasecmp(str, LG_Renderers[i]->get_name()) == 0)
|
||||||
{
|
{
|
||||||
params.forceRenderer = true;
|
g_params.forceRenderer = true;
|
||||||
params.forceRendererIndex = i;
|
g_params.forceRendererIndex = i;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -602,13 +602,13 @@ static StringList optRendererValues(struct Option * opt)
|
|||||||
|
|
||||||
static char * optRendererToString(struct Option * opt)
|
static char * optRendererToString(struct Option * opt)
|
||||||
{
|
{
|
||||||
if (!params.forceRenderer)
|
if (!g_params.forceRenderer)
|
||||||
return strdup("auto");
|
return strdup("auto");
|
||||||
|
|
||||||
if (params.forceRendererIndex >= LG_RENDERER_COUNT)
|
if (g_params.forceRendererIndex >= LG_RENDERER_COUNT)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return strdup(LG_Renderers[params.forceRendererIndex]->get_name());
|
return strdup(LG_Renderers[g_params.forceRendererIndex]->get_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool optPosParse(struct Option * opt, const char * str)
|
static bool optPosParse(struct Option * opt, const char * str)
|
||||||
@ -618,13 +618,13 @@ static bool optPosParse(struct Option * opt, const char * str)
|
|||||||
|
|
||||||
if (strcmp(str, "center") == 0)
|
if (strcmp(str, "center") == 0)
|
||||||
{
|
{
|
||||||
params.center = true;
|
g_params.center = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sscanf(str, "%dx%d", ¶ms.x, ¶ms.y) == 2)
|
if (sscanf(str, "%dx%d", &g_params.x, &g_params.y) == 2)
|
||||||
{
|
{
|
||||||
params.center = false;
|
g_params.center = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -641,12 +641,12 @@ static StringList optPosValues(struct Option * opt)
|
|||||||
|
|
||||||
static char * optPosToString(struct Option * opt)
|
static char * optPosToString(struct Option * opt)
|
||||||
{
|
{
|
||||||
if (params.center)
|
if (g_params.center)
|
||||||
return strdup("center");
|
return strdup("center");
|
||||||
|
|
||||||
int len = snprintf(NULL, 0, "%dx%d", params.x, params.y);
|
int len = snprintf(NULL, 0, "%dx%d", g_params.x, g_params.y);
|
||||||
char * str = malloc(len + 1);
|
char * str = malloc(len + 1);
|
||||||
sprintf(str, "%dx%d", params.x, params.y);
|
sprintf(str, "%dx%d", g_params.x, g_params.y);
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
@ -656,9 +656,9 @@ static bool optSizeParse(struct Option * opt, const char * str)
|
|||||||
if (!str)
|
if (!str)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (sscanf(str, "%dx%d", ¶ms.w, ¶ms.h) == 2)
|
if (sscanf(str, "%dx%d", &g_params.w, &g_params.h) == 2)
|
||||||
{
|
{
|
||||||
if (params.w < 1 || params.h < 1)
|
if (g_params.w < 1 || g_params.h < 1)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -675,9 +675,9 @@ static StringList optSizeValues(struct Option * opt)
|
|||||||
|
|
||||||
static char * optSizeToString(struct Option * opt)
|
static char * optSizeToString(struct Option * opt)
|
||||||
{
|
{
|
||||||
int len = snprintf(NULL, 0, "%dx%d", params.w, params.h);
|
int len = snprintf(NULL, 0, "%dx%d", g_params.w, g_params.h);
|
||||||
char * str = malloc(len + 1);
|
char * str = malloc(len + 1);
|
||||||
sprintf(str, "%dx%d", params.w, params.h);
|
sprintf(str, "%dx%d", g_params.w, g_params.h);
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
262
client/src/core.c
Normal file
262
client/src/core.c
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
/*
|
||||||
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
|
Copyright (C) 2017-2021 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "app.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#include "common/time.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#define RESIZE_TIMEOUT (10 * 1000) // 10ms
|
||||||
|
|
||||||
|
void core_setCursorInView(bool enable)
|
||||||
|
{
|
||||||
|
// if the state has not changed, don't do anything else
|
||||||
|
if (g_cursor.inView == enable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (enable && !g_state.focused)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// do not allow the view to become active if any mouse buttons are being held,
|
||||||
|
// this fixes issues with meta window resizing.
|
||||||
|
if (enable && g_cursor.buttons)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_cursor.inView = enable;
|
||||||
|
g_cursor.draw = (g_params.alwaysShowCursor || g_params.captureInputOnly)
|
||||||
|
? true : enable;
|
||||||
|
g_cursor.redraw = true;
|
||||||
|
|
||||||
|
/* if the display server does not support warp, then we can not operate in
|
||||||
|
* always relative mode and we should not grab the pointer */
|
||||||
|
bool warpSupport = true;
|
||||||
|
app_getProp(LG_DS_WARP_SUPPORT, &warpSupport);
|
||||||
|
|
||||||
|
g_cursor.warpState = enable ? WARP_STATE_ON : WARP_STATE_OFF;
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
if (g_params.hideMouse)
|
||||||
|
SDL_ShowCursor(SDL_DISABLE);
|
||||||
|
|
||||||
|
if (warpSupport && !g_params.captureInputOnly)
|
||||||
|
g_state.ds->grabPointer();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (g_params.hideMouse)
|
||||||
|
SDL_ShowCursor(SDL_ENABLE);
|
||||||
|
|
||||||
|
if (warpSupport)
|
||||||
|
g_state.ds->ungrabPointer();
|
||||||
|
|
||||||
|
g_state.ds->ungrabKeyboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
g_cursor.warpState = WARP_STATE_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
void core_setGrab(bool enable)
|
||||||
|
{
|
||||||
|
core_setGrabQuiet(enable);
|
||||||
|
|
||||||
|
app_alert(
|
||||||
|
g_cursor.grab ? LG_ALERT_SUCCESS : LG_ALERT_WARNING,
|
||||||
|
g_cursor.grab ? "Capture Enabled" : "Capture Disabled"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void core_setGrabQuiet(bool enable)
|
||||||
|
{
|
||||||
|
/* we always do this so that at init the cursor is in the right state */
|
||||||
|
if (g_params.captureInputOnly && g_params.hideMouse)
|
||||||
|
SDL_ShowCursor(enable ? SDL_DISABLE : SDL_ENABLE);
|
||||||
|
|
||||||
|
if (g_cursor.grab == enable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_cursor.grab = enable;
|
||||||
|
g_cursor.acc.x = 0.0;
|
||||||
|
g_cursor.acc.y = 0.0;
|
||||||
|
|
||||||
|
/* if the display server does not support warp we need to ungrab the pointer
|
||||||
|
* here instead of in the move handler */
|
||||||
|
bool warpSupport = true;
|
||||||
|
app_getProp(LG_DS_WARP_SUPPORT, &warpSupport);
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
core_setCursorInView(true);
|
||||||
|
g_state.ignoreInput = false;
|
||||||
|
|
||||||
|
if (g_params.grabKeyboard)
|
||||||
|
g_state.ds->grabKeyboard();
|
||||||
|
|
||||||
|
g_state.ds->grabPointer();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (g_params.grabKeyboard)
|
||||||
|
{
|
||||||
|
if (!g_params.grabKeyboardOnFocus ||
|
||||||
|
!g_state.focused || g_params.captureInputOnly)
|
||||||
|
g_state.ds->ungrabKeyboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!warpSupport || g_params.captureInputOnly || !g_state.formatValid)
|
||||||
|
g_state.ds->ungrabPointer();
|
||||||
|
|
||||||
|
// if exiting capture when input on capture only, we want to show the cursor
|
||||||
|
if (g_params.captureInputOnly || !g_params.hideMouse)
|
||||||
|
core_alignToGuest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool core_warpPointer(int x, int y, bool exiting)
|
||||||
|
{
|
||||||
|
if (!g_cursor.inWindow && !exiting)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (g_cursor.warpState == WARP_STATE_OFF)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (exiting)
|
||||||
|
g_cursor.warpState = WARP_STATE_OFF;
|
||||||
|
|
||||||
|
if (g_cursor.pos.x == x && g_cursor.pos.y == y)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
g_state.ds->warpPointer(x, y, exiting);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void core_updatePositionInfo(void)
|
||||||
|
{
|
||||||
|
if (!g_state.haveSrcSize)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
float srcW;
|
||||||
|
float srcH;
|
||||||
|
switch(g_params.winRotate)
|
||||||
|
{
|
||||||
|
case LG_ROTATE_0:
|
||||||
|
case LG_ROTATE_180:
|
||||||
|
srcW = g_state.srcSize.x;
|
||||||
|
srcH = g_state.srcSize.y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LG_ROTATE_90:
|
||||||
|
case LG_ROTATE_270:
|
||||||
|
srcW = g_state.srcSize.y;
|
||||||
|
srcH = g_state.srcSize.x;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(!"unreachable");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_params.keepAspect)
|
||||||
|
{
|
||||||
|
const float srcAspect = srcH / srcW;
|
||||||
|
const float wndAspect = (float)g_state.windowH / (float)g_state.windowW;
|
||||||
|
bool force = true;
|
||||||
|
|
||||||
|
if (g_params.dontUpscale &&
|
||||||
|
srcW <= g_state.windowW &&
|
||||||
|
srcH <= g_state.windowH)
|
||||||
|
{
|
||||||
|
force = false;
|
||||||
|
g_state.dstRect.w = srcW;
|
||||||
|
g_state.dstRect.h = srcH;
|
||||||
|
g_state.dstRect.x = g_state.windowCX - srcW / 2;
|
||||||
|
g_state.dstRect.y = g_state.windowCY - srcH / 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if ((int)(wndAspect * 1000) == (int)(srcAspect * 1000))
|
||||||
|
{
|
||||||
|
force = false;
|
||||||
|
g_state.dstRect.w = g_state.windowW;
|
||||||
|
g_state.dstRect.h = g_state.windowH;
|
||||||
|
g_state.dstRect.x = 0;
|
||||||
|
g_state.dstRect.y = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (wndAspect < srcAspect)
|
||||||
|
{
|
||||||
|
g_state.dstRect.w = (float)g_state.windowH / srcAspect;
|
||||||
|
g_state.dstRect.h = g_state.windowH;
|
||||||
|
g_state.dstRect.x = (g_state.windowW >> 1) - (g_state.dstRect.w >> 1);
|
||||||
|
g_state.dstRect.y = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_state.dstRect.w = g_state.windowW;
|
||||||
|
g_state.dstRect.h = (float)g_state.windowW * srcAspect;
|
||||||
|
g_state.dstRect.x = 0;
|
||||||
|
g_state.dstRect.y = (g_state.windowH >> 1) - (g_state.dstRect.h >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force && g_params.forceAspect)
|
||||||
|
{
|
||||||
|
g_state.resizeTimeout = microtime() + RESIZE_TIMEOUT;
|
||||||
|
g_state.resizeDone = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_state.dstRect.x = 0;
|
||||||
|
g_state.dstRect.y = 0;
|
||||||
|
g_state.dstRect.w = g_state.windowW;
|
||||||
|
g_state.dstRect.h = g_state.windowH;
|
||||||
|
}
|
||||||
|
g_state.dstRect.valid = true;
|
||||||
|
|
||||||
|
g_cursor.useScale = (
|
||||||
|
srcH != g_state.dstRect.h ||
|
||||||
|
srcW != g_state.dstRect.w ||
|
||||||
|
g_cursor.guest.dpiScale != 100);
|
||||||
|
|
||||||
|
g_cursor.scale.x = (float)srcW / (float)g_state.dstRect.w;
|
||||||
|
g_cursor.scale.y = (float)srcH / (float)g_state.dstRect.h;
|
||||||
|
g_cursor.dpiScale = g_cursor.guest.dpiScale / 100.0f;
|
||||||
|
|
||||||
|
if (!g_state.posInfoValid)
|
||||||
|
{
|
||||||
|
g_state.posInfoValid = true;
|
||||||
|
g_state.ds->realignPointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
atomic_fetch_add(&g_state.lgrResize, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void core_alignToGuest(void)
|
||||||
|
{
|
||||||
|
if (!g_cursor.guest.valid || !g_state.focused)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct DoublePoint local;
|
||||||
|
if (util_guestCurToLocal(&local))
|
||||||
|
if (core_warpPointer(round(local.x), round(local.y), false))
|
||||||
|
core_setCursorInView(true);
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2021 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -17,11 +17,16 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#ifndef _H_LG_CORE_
|
||||||
|
#define _H_LG_CORE_
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
// reads the specified file into a new buffer
|
void core_setCursorInView(bool enable);
|
||||||
// the callee must free the buffer
|
void core_setGrab(bool enable);
|
||||||
bool file_get_contents(const char * filename, char ** buffer, size_t * length);
|
void core_setGrabQuiet(bool enable);
|
||||||
|
bool core_warpPointer(int x, int y, bool exiting);
|
||||||
|
void core_updatePositionInfo(void);
|
||||||
|
void core_alignToGuest(void);
|
||||||
|
|
||||||
|
#endif
|
148
client/src/kb.c
Normal file
148
client/src/kb.c
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
|
Copyright (C) 2017-2021 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _H_LG_KB_
|
||||||
|
#define _H_LG_KB_
|
||||||
|
|
||||||
|
#include "kb.h"
|
||||||
|
|
||||||
|
const uint32_t xfree86_to_ps2[KEY_MAX] =
|
||||||
|
{
|
||||||
|
[KEY_RESERVED] /* = USB 0 */ = 0x000000,
|
||||||
|
[KEY_ESC] /* = USB 41 */ = 0x000001,
|
||||||
|
[KEY_1] /* = USB 30 */ = 0x000002,
|
||||||
|
[KEY_2] /* = USB 31 */ = 0x000003,
|
||||||
|
[KEY_3] /* = USB 32 */ = 0x000004,
|
||||||
|
[KEY_4] /* = USB 33 */ = 0x000005,
|
||||||
|
[KEY_5] /* = USB 34 */ = 0x000006,
|
||||||
|
[KEY_6] /* = USB 35 */ = 0x000007,
|
||||||
|
[KEY_7] /* = USB 36 */ = 0x000008,
|
||||||
|
[KEY_8] /* = USB 37 */ = 0x000009,
|
||||||
|
[KEY_9] /* = USB 38 */ = 0x00000A,
|
||||||
|
[KEY_0] /* = USB 39 */ = 0x00000B,
|
||||||
|
[KEY_MINUS] /* = USB 45 */ = 0x00000C,
|
||||||
|
[KEY_EQUAL] /* = USB 46 */ = 0x00000D,
|
||||||
|
[KEY_BACKSPACE] /* = USB 42 */ = 0x00000E,
|
||||||
|
[KEY_TAB] /* = USB 43 */ = 0x00000F,
|
||||||
|
[KEY_Q] /* = USB 20 */ = 0x000010,
|
||||||
|
[KEY_W] /* = USB 26 */ = 0x000011,
|
||||||
|
[KEY_E] /* = USB 8 */ = 0x000012,
|
||||||
|
[KEY_R] /* = USB 21 */ = 0x000013,
|
||||||
|
[KEY_T] /* = USB 23 */ = 0x000014,
|
||||||
|
[KEY_Y] /* = USB 28 */ = 0x000015,
|
||||||
|
[KEY_U] /* = USB 24 */ = 0x000016,
|
||||||
|
[KEY_I] /* = USB 12 */ = 0x000017,
|
||||||
|
[KEY_O] /* = USB 18 */ = 0x000018,
|
||||||
|
[KEY_P] /* = USB 19 */ = 0x000019,
|
||||||
|
[KEY_LEFTBRACE] /* = USB 47 */ = 0x00001A,
|
||||||
|
[KEY_RIGHTBRACE] /* = USB 48 */ = 0x00001B,
|
||||||
|
[KEY_ENTER] /* = USB 40 */ = 0x00001C,
|
||||||
|
[KEY_LEFTCTRL] /* = USB 224 */ = 0x00001D,
|
||||||
|
[KEY_A] /* = USB 4 */ = 0x00001E,
|
||||||
|
[KEY_S] /* = USB 22 */ = 0x00001F,
|
||||||
|
[KEY_D] /* = USB 7 */ = 0x000020,
|
||||||
|
[KEY_F] /* = USB 9 */ = 0x000021,
|
||||||
|
[KEY_G] /* = USB 10 */ = 0x000022,
|
||||||
|
[KEY_H] /* = USB 11 */ = 0x000023,
|
||||||
|
[KEY_J] /* = USB 13 */ = 0x000024,
|
||||||
|
[KEY_K] /* = USB 14 */ = 0x000025,
|
||||||
|
[KEY_L] /* = USB 15 */ = 0x000026,
|
||||||
|
[KEY_SEMICOLON] /* = USB 51 */ = 0x000027,
|
||||||
|
[KEY_APOSTROPHE] /* = USB 52 */ = 0x000028,
|
||||||
|
[KEY_GRAVE] /* = USB 53 */ = 0x000029,
|
||||||
|
[KEY_LEFTSHIFT] /* = USB 225 */ = 0x00002A,
|
||||||
|
[KEY_BACKSLASH] /* = USB 49 */ = 0x00002B,
|
||||||
|
[KEY_Z] /* = USB 29 */ = 0x00002C,
|
||||||
|
[KEY_X] /* = USB 27 */ = 0x00002D,
|
||||||
|
[KEY_C] /* = USB 6 */ = 0x00002E,
|
||||||
|
[KEY_V] /* = USB 25 */ = 0x00002F,
|
||||||
|
[KEY_B] /* = USB 5 */ = 0x000030,
|
||||||
|
[KEY_N] /* = USB 17 */ = 0x000031,
|
||||||
|
[KEY_M] /* = USB 16 */ = 0x000032,
|
||||||
|
[KEY_COMMA] /* = USB 54 */ = 0x000033,
|
||||||
|
[KEY_DOT] /* = USB 55 */ = 0x000034,
|
||||||
|
[KEY_SLASH] /* = USB 56 */ = 0x000035,
|
||||||
|
[KEY_RIGHTSHIFT] /* = USB 229 */ = 0x000036,
|
||||||
|
[KEY_KPASTERISK] /* = USB 85 */ = 0x000037,
|
||||||
|
[KEY_LEFTALT] /* = USB 226 */ = 0x000038,
|
||||||
|
[KEY_SPACE] /* = USB 44 */ = 0x000039,
|
||||||
|
[KEY_CAPSLOCK] /* = USB 57 */ = 0x00003A,
|
||||||
|
[KEY_F1] /* = USB 58 */ = 0x00003B,
|
||||||
|
[KEY_F2] /* = USB 59 */ = 0x00003C,
|
||||||
|
[KEY_F3] /* = USB 60 */ = 0x00003D,
|
||||||
|
[KEY_F4] /* = USB 61 */ = 0x00003E,
|
||||||
|
[KEY_F5] /* = USB 62 */ = 0x00003F,
|
||||||
|
[KEY_F6] /* = USB 63 */ = 0x000040,
|
||||||
|
[KEY_F7] /* = USB 64 */ = 0x000041,
|
||||||
|
[KEY_F8] /* = USB 65 */ = 0x000042,
|
||||||
|
[KEY_F9] /* = USB 66 */ = 0x000043,
|
||||||
|
[KEY_F10] /* = USB 67 */ = 0x000044,
|
||||||
|
[KEY_NUMLOCK] /* = USB 83 */ = 0x000045,
|
||||||
|
[KEY_SCROLLLOCK] /* = USB 71 */ = 0x000046,
|
||||||
|
[KEY_KP7] /* = USB 95 */ = 0x000047,
|
||||||
|
[KEY_KP8] /* = USB 96 */ = 0x000048,
|
||||||
|
[KEY_KP9] /* = USB 97 */ = 0x000049,
|
||||||
|
[KEY_KPMINUS] /* = USB 86 */ = 0x00004A,
|
||||||
|
[KEY_KP4] /* = USB 92 */ = 0x00004B,
|
||||||
|
[KEY_KP5] /* = USB 93 */ = 0x00004C,
|
||||||
|
[KEY_KP6] /* = USB 94 */ = 0x00004D,
|
||||||
|
[KEY_KPPLUS] /* = USB 87 */ = 0x00004E,
|
||||||
|
[KEY_KP1] /* = USB 89 */ = 0x00004F,
|
||||||
|
[KEY_KP2] /* = USB 90 */ = 0x000050,
|
||||||
|
[KEY_KP3] /* = USB 91 */ = 0x000051,
|
||||||
|
[KEY_KP0] /* = USB 98 */ = 0x000052,
|
||||||
|
[KEY_KPDOT] /* = USB 99 */ = 0x000053,
|
||||||
|
[KEY_102ND] /* = USB 100 */ = 0x000056,
|
||||||
|
[KEY_F11] /* = USB 68 */ = 0x000057,
|
||||||
|
[KEY_F12] /* = USB 69 */ = 0x000058,
|
||||||
|
[KEY_RO] /* = USB 135 */ = 0x000073,
|
||||||
|
[KEY_HENKAN] /* = USB 138 */ = 0x000079,
|
||||||
|
[KEY_KATAKANAHIRAGANA] /* = USB 136 */ = 0x000070,
|
||||||
|
[KEY_MUHENKAN] /* = USB 139 */ = 0x00007B,
|
||||||
|
[KEY_KPENTER] /* = USB 88 */ = 0x00E01C,
|
||||||
|
[KEY_RIGHTCTRL] /* = USB 228 */ = 0x00E01D,
|
||||||
|
[KEY_KPSLASH] /* = USB 84 */ = 0x00E035,
|
||||||
|
[KEY_SYSRQ] /* = USB 70 */ = 0x00E037,
|
||||||
|
[KEY_RIGHTALT] /* = USB 230 */ = 0x00E038,
|
||||||
|
[KEY_HOME] /* = USB 74 */ = 0x00E047,
|
||||||
|
[KEY_UP] /* = USB 82 */ = 0x00E048,
|
||||||
|
[KEY_PAGEUP] /* = USB 75 */ = 0x00E049,
|
||||||
|
[KEY_LEFT] /* = USB 80 */ = 0x00E04B,
|
||||||
|
[KEY_RIGHT] /* = USB 79 */ = 0x00E04D,
|
||||||
|
[KEY_END] /* = USB 77 */ = 0x00E04F,
|
||||||
|
[KEY_DOWN] /* = USB 81 */ = 0x00E050,
|
||||||
|
[KEY_PAGEDOWN] /* = USB 78 */ = 0x00E051,
|
||||||
|
[KEY_INSERT] /* = USB 73 */ = 0x00E052,
|
||||||
|
[KEY_DELETE] /* = USB 76 */ = 0x00E053,
|
||||||
|
[KEY_KPEQUAL] /* = USB 103 */ = 0x000059,
|
||||||
|
[KEY_PAUSE] /* = USB 72 */ = 0x00E046,
|
||||||
|
[KEY_KPCOMMA] /* = USB 133 */ = 0x00007E,
|
||||||
|
[KEY_HANGEUL] /* = USB 144 */ = 0x0000F2,
|
||||||
|
[KEY_HANJA] /* = USB 145 */ = 0x0000F1,
|
||||||
|
[KEY_YEN] /* = USB 137 */ = 0x00007D,
|
||||||
|
[KEY_LEFTMETA] /* = USB 227 */ = 0x00E05B,
|
||||||
|
[KEY_RIGHTMETA] /* = USB 231 */ = 0x00E05C,
|
||||||
|
[KEY_COMPOSE] /* = USB 101 */ = 0x00E05D,
|
||||||
|
[KEY_F13] /* = USB 104 */ = 0x00005D,
|
||||||
|
[KEY_F14] /* = USB 105 */ = 0x00005E,
|
||||||
|
[KEY_F15] /* = USB 106 */ = 0x00005F,
|
||||||
|
[KEY_PRINT] /* = USB 70 */ = 0x00E037,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
126
client/src/kb.h
126
client/src/kb.h
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2021 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -18,126 +18,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
const uint32_t xfree86_to_ps2[KEY_MAX] =
|
extern const uint32_t xfree86_to_ps2[KEY_MAX];
|
||||||
{
|
|
||||||
[KEY_RESERVED] /* = USB 0 */ = 0x000000,
|
|
||||||
[KEY_ESC] /* = USB 41 */ = 0x000001,
|
|
||||||
[KEY_1] /* = USB 30 */ = 0x000002,
|
|
||||||
[KEY_2] /* = USB 31 */ = 0x000003,
|
|
||||||
[KEY_3] /* = USB 32 */ = 0x000004,
|
|
||||||
[KEY_4] /* = USB 33 */ = 0x000005,
|
|
||||||
[KEY_5] /* = USB 34 */ = 0x000006,
|
|
||||||
[KEY_6] /* = USB 35 */ = 0x000007,
|
|
||||||
[KEY_7] /* = USB 36 */ = 0x000008,
|
|
||||||
[KEY_8] /* = USB 37 */ = 0x000009,
|
|
||||||
[KEY_9] /* = USB 38 */ = 0x00000A,
|
|
||||||
[KEY_0] /* = USB 39 */ = 0x00000B,
|
|
||||||
[KEY_MINUS] /* = USB 45 */ = 0x00000C,
|
|
||||||
[KEY_EQUAL] /* = USB 46 */ = 0x00000D,
|
|
||||||
[KEY_BACKSPACE] /* = USB 42 */ = 0x00000E,
|
|
||||||
[KEY_TAB] /* = USB 43 */ = 0x00000F,
|
|
||||||
[KEY_Q] /* = USB 20 */ = 0x000010,
|
|
||||||
[KEY_W] /* = USB 26 */ = 0x000011,
|
|
||||||
[KEY_E] /* = USB 8 */ = 0x000012,
|
|
||||||
[KEY_R] /* = USB 21 */ = 0x000013,
|
|
||||||
[KEY_T] /* = USB 23 */ = 0x000014,
|
|
||||||
[KEY_Y] /* = USB 28 */ = 0x000015,
|
|
||||||
[KEY_U] /* = USB 24 */ = 0x000016,
|
|
||||||
[KEY_I] /* = USB 12 */ = 0x000017,
|
|
||||||
[KEY_O] /* = USB 18 */ = 0x000018,
|
|
||||||
[KEY_P] /* = USB 19 */ = 0x000019,
|
|
||||||
[KEY_LEFTBRACE] /* = USB 47 */ = 0x00001A,
|
|
||||||
[KEY_RIGHTBRACE] /* = USB 48 */ = 0x00001B,
|
|
||||||
[KEY_ENTER] /* = USB 40 */ = 0x00001C,
|
|
||||||
[KEY_LEFTCTRL] /* = USB 224 */ = 0x00001D,
|
|
||||||
[KEY_A] /* = USB 4 */ = 0x00001E,
|
|
||||||
[KEY_S] /* = USB 22 */ = 0x00001F,
|
|
||||||
[KEY_D] /* = USB 7 */ = 0x000020,
|
|
||||||
[KEY_F] /* = USB 9 */ = 0x000021,
|
|
||||||
[KEY_G] /* = USB 10 */ = 0x000022,
|
|
||||||
[KEY_H] /* = USB 11 */ = 0x000023,
|
|
||||||
[KEY_J] /* = USB 13 */ = 0x000024,
|
|
||||||
[KEY_K] /* = USB 14 */ = 0x000025,
|
|
||||||
[KEY_L] /* = USB 15 */ = 0x000026,
|
|
||||||
[KEY_SEMICOLON] /* = USB 51 */ = 0x000027,
|
|
||||||
[KEY_APOSTROPHE] /* = USB 52 */ = 0x000028,
|
|
||||||
[KEY_GRAVE] /* = USB 53 */ = 0x000029,
|
|
||||||
[KEY_LEFTSHIFT] /* = USB 225 */ = 0x00002A,
|
|
||||||
[KEY_BACKSLASH] /* = USB 49 */ = 0x00002B,
|
|
||||||
[KEY_Z] /* = USB 29 */ = 0x00002C,
|
|
||||||
[KEY_X] /* = USB 27 */ = 0x00002D,
|
|
||||||
[KEY_C] /* = USB 6 */ = 0x00002E,
|
|
||||||
[KEY_V] /* = USB 25 */ = 0x00002F,
|
|
||||||
[KEY_B] /* = USB 5 */ = 0x000030,
|
|
||||||
[KEY_N] /* = USB 17 */ = 0x000031,
|
|
||||||
[KEY_M] /* = USB 16 */ = 0x000032,
|
|
||||||
[KEY_COMMA] /* = USB 54 */ = 0x000033,
|
|
||||||
[KEY_DOT] /* = USB 55 */ = 0x000034,
|
|
||||||
[KEY_SLASH] /* = USB 56 */ = 0x000035,
|
|
||||||
[KEY_RIGHTSHIFT] /* = USB 229 */ = 0x000036,
|
|
||||||
[KEY_KPASTERISK] /* = USB 85 */ = 0x000037,
|
|
||||||
[KEY_LEFTALT] /* = USB 226 */ = 0x000038,
|
|
||||||
[KEY_SPACE] /* = USB 44 */ = 0x000039,
|
|
||||||
[KEY_CAPSLOCK] /* = USB 57 */ = 0x00003A,
|
|
||||||
[KEY_F1] /* = USB 58 */ = 0x00003B,
|
|
||||||
[KEY_F2] /* = USB 59 */ = 0x00003C,
|
|
||||||
[KEY_F3] /* = USB 60 */ = 0x00003D,
|
|
||||||
[KEY_F4] /* = USB 61 */ = 0x00003E,
|
|
||||||
[KEY_F5] /* = USB 62 */ = 0x00003F,
|
|
||||||
[KEY_F6] /* = USB 63 */ = 0x000040,
|
|
||||||
[KEY_F7] /* = USB 64 */ = 0x000041,
|
|
||||||
[KEY_F8] /* = USB 65 */ = 0x000042,
|
|
||||||
[KEY_F9] /* = USB 66 */ = 0x000043,
|
|
||||||
[KEY_F10] /* = USB 67 */ = 0x000044,
|
|
||||||
[KEY_NUMLOCK] /* = USB 83 */ = 0x000045,
|
|
||||||
[KEY_SCROLLLOCK] /* = USB 71 */ = 0x000046,
|
|
||||||
[KEY_KP7] /* = USB 95 */ = 0x000047,
|
|
||||||
[KEY_KP8] /* = USB 96 */ = 0x000048,
|
|
||||||
[KEY_KP9] /* = USB 97 */ = 0x000049,
|
|
||||||
[KEY_KPMINUS] /* = USB 86 */ = 0x00004A,
|
|
||||||
[KEY_KP4] /* = USB 92 */ = 0x00004B,
|
|
||||||
[KEY_KP5] /* = USB 93 */ = 0x00004C,
|
|
||||||
[KEY_KP6] /* = USB 94 */ = 0x00004D,
|
|
||||||
[KEY_KPPLUS] /* = USB 87 */ = 0x00004E,
|
|
||||||
[KEY_KP1] /* = USB 89 */ = 0x00004F,
|
|
||||||
[KEY_KP2] /* = USB 90 */ = 0x000050,
|
|
||||||
[KEY_KP3] /* = USB 91 */ = 0x000051,
|
|
||||||
[KEY_KP0] /* = USB 98 */ = 0x000052,
|
|
||||||
[KEY_KPDOT] /* = USB 99 */ = 0x000053,
|
|
||||||
[KEY_102ND] /* = USB 100 */ = 0x000056,
|
|
||||||
[KEY_F11] /* = USB 68 */ = 0x000057,
|
|
||||||
[KEY_F12] /* = USB 69 */ = 0x000058,
|
|
||||||
[KEY_RO] /* = USB 135 */ = 0x000073,
|
|
||||||
[KEY_HENKAN] /* = USB 138 */ = 0x000079,
|
|
||||||
[KEY_KATAKANAHIRAGANA] /* = USB 136 */ = 0x000070,
|
|
||||||
[KEY_MUHENKAN] /* = USB 139 */ = 0x00007B,
|
|
||||||
[KEY_KPENTER] /* = USB 88 */ = 0x00E01C,
|
|
||||||
[KEY_RIGHTCTRL] /* = USB 228 */ = 0x00E01D,
|
|
||||||
[KEY_KPSLASH] /* = USB 84 */ = 0x00E035,
|
|
||||||
[KEY_SYSRQ] /* = USB 70 */ = 0x00E037,
|
|
||||||
[KEY_RIGHTALT] /* = USB 230 */ = 0x00E038,
|
|
||||||
[KEY_HOME] /* = USB 74 */ = 0x00E047,
|
|
||||||
[KEY_UP] /* = USB 82 */ = 0x00E048,
|
|
||||||
[KEY_PAGEUP] /* = USB 75 */ = 0x00E049,
|
|
||||||
[KEY_LEFT] /* = USB 80 */ = 0x00E04B,
|
|
||||||
[KEY_RIGHT] /* = USB 79 */ = 0x00E04D,
|
|
||||||
[KEY_END] /* = USB 77 */ = 0x00E04F,
|
|
||||||
[KEY_DOWN] /* = USB 81 */ = 0x00E050,
|
|
||||||
[KEY_PAGEDOWN] /* = USB 78 */ = 0x00E051,
|
|
||||||
[KEY_INSERT] /* = USB 73 */ = 0x00E052,
|
|
||||||
[KEY_DELETE] /* = USB 76 */ = 0x00E053,
|
|
||||||
[KEY_KPEQUAL] /* = USB 103 */ = 0x000059,
|
|
||||||
[KEY_PAUSE] /* = USB 72 */ = 0x00E046,
|
|
||||||
[KEY_KPCOMMA] /* = USB 133 */ = 0x00007E,
|
|
||||||
[KEY_HANGEUL] /* = USB 144 */ = 0x0000F2,
|
|
||||||
[KEY_HANJA] /* = USB 145 */ = 0x0000F1,
|
|
||||||
[KEY_YEN] /* = USB 137 */ = 0x00007D,
|
|
||||||
[KEY_LEFTMETA] /* = USB 227 */ = 0x00E05B,
|
|
||||||
[KEY_RIGHTMETA] /* = USB 231 */ = 0x00E05C,
|
|
||||||
[KEY_COMPOSE] /* = USB 101 */ = 0x00E05D,
|
|
||||||
[KEY_F13] /* = USB 104 */ = 0x00005D,
|
|
||||||
[KEY_F14] /* = USB 105 */ = 0x00005E,
|
|
||||||
[KEY_F15] /* = USB 106 */ = 0x00005F,
|
|
||||||
[KEY_PRINT] /* = USB 70 */ = 0x00E037,
|
|
||||||
};
|
|
||||||
|
1145
client/src/main.c
1145
client/src/main.c
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2021 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -25,6 +25,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "interface/app.h"
|
#include "interface/app.h"
|
||||||
#include "dynamic/displayservers.h"
|
#include "dynamic/displayservers.h"
|
||||||
#include "dynamic/renderers.h"
|
#include "dynamic/renderers.h"
|
||||||
|
|
||||||
|
#include "common/types.h"
|
||||||
#include "common/ivshmem.h"
|
#include "common/ivshmem.h"
|
||||||
|
|
||||||
#include "spice/spice.h"
|
#include "spice/spice.h"
|
||||||
@ -192,11 +194,6 @@ struct CursorInfo
|
|||||||
uint32_t dpiScale;
|
uint32_t dpiScale;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DoublePoint
|
|
||||||
{
|
|
||||||
double x, y;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CursorState
|
struct CursorState
|
||||||
{
|
{
|
||||||
/* cursor is in grab mode */
|
/* cursor is in grab mode */
|
||||||
@ -253,4 +250,5 @@ struct CursorState
|
|||||||
|
|
||||||
// forwards
|
// forwards
|
||||||
extern struct AppState g_state;
|
extern struct AppState g_state;
|
||||||
extern struct AppParams params;
|
extern struct CursorState g_cursor;
|
||||||
|
extern struct AppParams g_params;
|
||||||
|
222
client/src/util.c
Normal file
222
client/src/util.c
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
/*
|
||||||
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
|
Copyright (C) 2017-2021 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
#include "common/debug.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
bool util_fileGetContents(const char * filename, char ** buffer, size_t * length)
|
||||||
|
{
|
||||||
|
FILE * fh = fopen(filename, "r");
|
||||||
|
if (!fh)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to open the file: %s", filename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fseek(fh, 0, SEEK_END) != 0)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to seek");
|
||||||
|
fclose(fh);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
long fsize = ftell(fh);
|
||||||
|
if (fseek(fh, 0, SEEK_SET) != 0)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to seek");
|
||||||
|
fclose(fh);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*buffer = malloc(fsize + 1);
|
||||||
|
if (!*buffer)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to allocate buffer of %lu bytes", fsize + 1);
|
||||||
|
fclose(fh);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fread(*buffer, 1, fsize, fh) != fsize)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to read the entire file");
|
||||||
|
fclose(fh);
|
||||||
|
free(*buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fh);
|
||||||
|
buffer[fsize] = 0;
|
||||||
|
*length = fsize;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void util_cursorToInt(double ex, double ey, int *x, int *y)
|
||||||
|
{
|
||||||
|
/* only smooth if enabled and not using raw mode */
|
||||||
|
if (g_params.mouseSmoothing && !(g_cursor.grab && g_params.rawMouse))
|
||||||
|
{
|
||||||
|
static struct DoublePoint last = { 0 };
|
||||||
|
|
||||||
|
/* only apply smoothing to small deltas */
|
||||||
|
if (fabs(ex - last.x) < 5.0 && fabs(ey - last.y) < 5.0)
|
||||||
|
{
|
||||||
|
ex = last.x = (last.x + ex) / 2.0;
|
||||||
|
ey = last.y = (last.y + ey) / 2.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
last.x = ex;
|
||||||
|
last.y = ey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert to int accumulating the fractional error */
|
||||||
|
ex += g_cursor.acc.x;
|
||||||
|
ey += g_cursor.acc.y;
|
||||||
|
g_cursor.acc.x = modf(ex, &ex);
|
||||||
|
g_cursor.acc.y = modf(ey, &ey);
|
||||||
|
|
||||||
|
*x = (int)ex;
|
||||||
|
*y = (int)ey;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool util_guestCurToLocal(struct DoublePoint *local)
|
||||||
|
{
|
||||||
|
if (!g_cursor.guest.valid || !g_state.posInfoValid)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const struct DoublePoint point =
|
||||||
|
{
|
||||||
|
.x = g_cursor.guest.x + g_cursor.guest.hx,
|
||||||
|
.y = g_cursor.guest.y + g_cursor.guest.hy
|
||||||
|
};
|
||||||
|
|
||||||
|
switch((g_state.rotate + g_params.winRotate) % LG_ROTATE_MAX)
|
||||||
|
{
|
||||||
|
case LG_ROTATE_0:
|
||||||
|
local->x = (point.x / g_cursor.scale.x) + g_state.dstRect.x;
|
||||||
|
local->y = (point.y / g_cursor.scale.y) + g_state.dstRect.y;;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LG_ROTATE_90:
|
||||||
|
local->x = (g_state.dstRect.x + g_state.dstRect.w) -
|
||||||
|
point.y / g_cursor.scale.y;
|
||||||
|
local->y = (point.x / g_cursor.scale.x) + g_state.dstRect.y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LG_ROTATE_180:
|
||||||
|
local->x = (g_state.dstRect.x + g_state.dstRect.w) -
|
||||||
|
point.x / g_cursor.scale.x;
|
||||||
|
local->y = (g_state.dstRect.y + g_state.dstRect.h) -
|
||||||
|
point.y / g_cursor.scale.y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LG_ROTATE_270:
|
||||||
|
local->x = (point.y / g_cursor.scale.y) + g_state.dstRect.x;
|
||||||
|
local->y = (g_state.dstRect.y + g_state.dstRect.h) -
|
||||||
|
point.x / g_cursor.scale.x;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void util_localCurToGuest(struct DoublePoint *guest)
|
||||||
|
{
|
||||||
|
const struct DoublePoint point =
|
||||||
|
g_cursor.pos;
|
||||||
|
|
||||||
|
switch((g_state.rotate + g_params.winRotate) % LG_ROTATE_MAX)
|
||||||
|
{
|
||||||
|
case LG_ROTATE_0:
|
||||||
|
guest->x = (point.x - g_state.dstRect.x) * g_cursor.scale.x;
|
||||||
|
guest->y = (point.y - g_state.dstRect.y) * g_cursor.scale.y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LG_ROTATE_90:
|
||||||
|
guest->x = (point.y - g_state.dstRect.y) * g_cursor.scale.y;
|
||||||
|
guest->y = (g_state.dstRect.w - point.x + g_state.dstRect.x)
|
||||||
|
* g_cursor.scale.x;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LG_ROTATE_180:
|
||||||
|
guest->x = (g_state.dstRect.w - point.x + g_state.dstRect.x)
|
||||||
|
* g_cursor.scale.x;
|
||||||
|
guest->y = (g_state.dstRect.h - point.y + g_state.dstRect.y)
|
||||||
|
* g_cursor.scale.y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LG_ROTATE_270:
|
||||||
|
guest->x = (g_state.dstRect.h - point.y + g_state.dstRect.y)
|
||||||
|
* g_cursor.scale.y;
|
||||||
|
guest->y = (point.x - g_state.dstRect.x) * g_cursor.scale.x;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(!"unreachable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void util_rotatePoint(struct DoublePoint *point)
|
||||||
|
{
|
||||||
|
double temp;
|
||||||
|
|
||||||
|
switch((g_state.rotate + g_params.winRotate) % LG_ROTATE_MAX)
|
||||||
|
{
|
||||||
|
case LG_ROTATE_0:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LG_ROTATE_90:
|
||||||
|
temp = point->x;
|
||||||
|
point->x = point->y;
|
||||||
|
point->y = -temp;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LG_ROTATE_180:
|
||||||
|
point->x = -point->x;
|
||||||
|
point->y = -point->y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LG_ROTATE_270:
|
||||||
|
temp = point->x;
|
||||||
|
point->x = -point->y;
|
||||||
|
point->y = temp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool util_isValidCursorLocation(int x, int y)
|
||||||
|
{
|
||||||
|
const int displays = SDL_GetNumVideoDisplays();
|
||||||
|
for(int i = 0; i < displays; ++i)
|
||||||
|
{
|
||||||
|
SDL_Rect r;
|
||||||
|
SDL_GetDisplayBounds(i, &r);
|
||||||
|
if ((x >= r.x && x < r.x + r.w) &&
|
||||||
|
(y >= r.y && y < r.y + r.h))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
#include "common/debug.h"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
bool file_get_contents(const char * filename, char ** buffer, size_t * length)
|
|
||||||
{
|
|
||||||
FILE * fh = fopen(filename, "r");
|
|
||||||
if (!fh)
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to open the file: %s", filename);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fseek(fh, 0, SEEK_END) != 0)
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to seek");
|
|
||||||
fclose(fh);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
long fsize = ftell(fh);
|
|
||||||
if (fseek(fh, 0, SEEK_SET) != 0)
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to seek");
|
|
||||||
fclose(fh);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*buffer = malloc(fsize + 1);
|
|
||||||
if (!*buffer)
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to allocate buffer of %lu bytes", fsize + 1);
|
|
||||||
fclose(fh);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fread(*buffer, 1, fsize, fh) != fsize)
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to read the entire file");
|
|
||||||
fclose(fh);
|
|
||||||
free(*buffer);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fh);
|
|
||||||
buffer[fsize] = 0;
|
|
||||||
*length = fsize;
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR)
|
Looking Glass - KVM FrameRelay (KVMFR)
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2021 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -16,9 +16,17 @@ 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
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _H_LG_COMMON_KVMFR_
|
||||||
|
#define _H_LG_COMMON_KVMFR_
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#define KVMFR_MAGIC "KVMFR---"
|
||||||
|
#define KVMFR_VERSION 8
|
||||||
|
|
||||||
#define LGMP_Q_POINTER 1
|
#define LGMP_Q_POINTER 1
|
||||||
#define LGMP_Q_FRAME 2
|
#define LGMP_Q_FRAME 2
|
||||||
@ -26,47 +34,15 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#define LGMP_Q_FRAME_LEN 2
|
#define LGMP_Q_FRAME_LEN 2
|
||||||
#define LGMP_Q_POINTER_LEN 20
|
#define LGMP_Q_POINTER_LEN 20
|
||||||
|
|
||||||
typedef enum FrameType
|
|
||||||
{
|
|
||||||
FRAME_TYPE_INVALID ,
|
|
||||||
FRAME_TYPE_BGRA , // BGRA interleaved: B,G,R,A 32bpp
|
|
||||||
FRAME_TYPE_RGBA , // RGBA interleaved: R,G,B,A 32bpp
|
|
||||||
FRAME_TYPE_RGBA10 , // RGBA interleaved: R,G,B,A 10,10,10,2 bpp
|
|
||||||
FRAME_TYPE_RGBA16F , // RGBA interleaved: R,G,B,A 16,16,16,16 bpp float
|
|
||||||
FRAME_TYPE_MAX , // sentinel value
|
|
||||||
}
|
|
||||||
FrameType;
|
|
||||||
|
|
||||||
typedef enum FrameRotation
|
|
||||||
{
|
|
||||||
FRAME_ROT_0,
|
|
||||||
FRAME_ROT_90,
|
|
||||||
FRAME_ROT_180,
|
|
||||||
FRAME_ROT_270
|
|
||||||
}
|
|
||||||
FrameRotation;
|
|
||||||
|
|
||||||
extern const char * FrameTypeStr[FRAME_TYPE_MAX];
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
CURSOR_FLAG_POSITION = 0x1,
|
CURSOR_FLAG_POSITION = 0x1,
|
||||||
CURSOR_FLAG_VISIBLE = 0x2,
|
CURSOR_FLAG_VISIBLE = 0x2,
|
||||||
CURSOR_FLAG_SHAPE = 0x4
|
CURSOR_FLAG_SHAPE = 0x4
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef uint32_t KVMFRCursorFlags;
|
typedef uint32_t KVMFRCursorFlags;
|
||||||
|
|
||||||
typedef enum CursorType
|
|
||||||
{
|
|
||||||
CURSOR_TYPE_COLOR ,
|
|
||||||
CURSOR_TYPE_MONOCHROME ,
|
|
||||||
CURSOR_TYPE_MASKED_COLOR
|
|
||||||
}
|
|
||||||
CursorType;
|
|
||||||
|
|
||||||
#define KVMFR_MAGIC "KVMFR---"
|
|
||||||
#define KVMFR_VERSION 8
|
|
||||||
|
|
||||||
typedef struct KVMFR
|
typedef struct KVMFR
|
||||||
{
|
{
|
||||||
char magic[8];
|
char magic[8];
|
||||||
@ -99,3 +75,5 @@ typedef struct KVMFRFrame
|
|||||||
uint32_t mouseScalePercent; // movement scale factor of the mouse (relates to DPI of display, 100 = no scale)
|
uint32_t mouseScalePercent; // movement scale factor of the mouse (relates to DPI of display, 100 = no scale)
|
||||||
}
|
}
|
||||||
KVMFRFrame;
|
KVMFRFrame;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KVMGFX Client - A KVM Client for VGA Passthrough
|
KVMGFX Client - A KVM Client for VGA Passthrough
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2021 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -17,7 +17,12 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _H_LG_COMMON_CRASH_
|
||||||
|
#define _H_LG_COMMON_CRASH_
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
bool installCrashHandler(const char * exe);
|
bool installCrashHandler(const char * exe);
|
||||||
void cleanupCrashHandler(void);
|
void cleanupCrashHandler(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -17,6 +17,9 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _H_LG_COMMON_DEBUG_
|
||||||
|
#define _H_LG_COMMON_DEBUG_
|
||||||
|
|
||||||
#ifndef __STDC_FORMAT_MACROS
|
#ifndef __STDC_FORMAT_MACROS
|
||||||
#define __STDC_FORMAT_MACROS
|
#define __STDC_FORMAT_MACROS
|
||||||
#endif
|
#endif
|
||||||
@ -82,3 +85,5 @@ void printBacktrace(void);
|
|||||||
#else
|
#else
|
||||||
#define DEBUG_PROTO(fmt, ...) do {} while(0)
|
#define DEBUG_PROTO(fmt, ...) do {} while(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -17,9 +17,14 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _H_LG_COMMON_DPI_
|
||||||
|
#define _H_LG_COMMON_DPI_
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
// At 100% scaling, Windows reports 96 DPI.
|
// At 100% scaling, Windows reports 96 DPI.
|
||||||
#define DPI_100_PERCENT 96
|
#define DPI_100_PERCENT 96
|
||||||
|
|
||||||
UINT monitor_dpi(HMONITOR hMonitor);
|
UINT monitor_dpi(HMONITOR hMonitor);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2021 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -17,7 +17,8 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#ifndef _H_LG_COMMON_EVENT_
|
||||||
|
#define _H_LG_COMMON_EVENT_
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
@ -40,3 +41,5 @@ LGEvent * lgWrapEvent(void * handle);
|
|||||||
// Posix specific, not implmented/possible in windows
|
// Posix specific, not implmented/possible in windows
|
||||||
bool lgWaitEventAbs(LGEvent * handle, struct timespec * ts);
|
bool lgWaitEventAbs(LGEvent * handle, struct timespec * ts);
|
||||||
bool lgWaitEventNS (LGEvent * handle, unsigned int timeout);
|
bool lgWaitEventNS (LGEvent * handle, unsigned int timeout);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KVMGFX Client - A KVM Client for VGA Passthrough
|
KVMGFX Client - A KVM Client for VGA Passthrough
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2021 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -17,7 +17,8 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#ifndef _H_LG_COMMON_FRAMEBUFFER_
|
||||||
|
#define _H_LG_COMMON_FRAMEBUFFER_
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@ -58,3 +59,5 @@ void framebuffer_prepare(FrameBuffer * frame);
|
|||||||
* Write data from the src buffer into the KVMFRFrame
|
* Write data from the src buffer into the KVMFRFrame
|
||||||
*/
|
*/
|
||||||
bool framebuffer_write(FrameBuffer * frame, const void * src, size_t size);
|
bool framebuffer_write(FrameBuffer * frame, const void * src, size_t size);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2021 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -17,7 +17,8 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#ifndef _H_LG_COMMON_IVSHMEM_
|
||||||
|
#define _H_LG_COMMON_IVSHMEM_
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -41,3 +42,5 @@ void ivshmemFree(struct IVSHMEM * dev);
|
|||||||
/* Linux KVMFR support only for now (VM->VM) */
|
/* Linux KVMFR support only for now (VM->VM) */
|
||||||
bool ivshmemHasDMA (struct IVSHMEM * dev);
|
bool ivshmemHasDMA (struct IVSHMEM * dev);
|
||||||
int ivshmemGetDMABuf(struct IVSHMEM * dev, uint64_t offset, uint64_t size);
|
int ivshmemGetDMABuf(struct IVSHMEM * dev, uint64_t offset, uint64_t size);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2021 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -16,7 +16,9 @@ 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
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
#pragma once
|
|
||||||
|
#ifndef _H_LG_COMMON_LOCKING_
|
||||||
|
#define _H_LG_COMMON_LOCKING_
|
||||||
|
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
|
|
||||||
@ -38,3 +40,5 @@ typedef atomic_flag LG_Lock;
|
|||||||
LG_LOCK(lock) \
|
LG_LOCK(lock) \
|
||||||
x \
|
x \
|
||||||
LG_UNLOCK(lock)
|
LG_UNLOCK(lock)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -1,135 +0,0 @@
|
|||||||
/*
|
|
||||||
KVMGFX Client - A KVM Client for VGA Passthrough
|
|
||||||
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 <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <tmmintrin.h>
|
|
||||||
#include <immintrin.h>
|
|
||||||
|
|
||||||
#include "debug.h"
|
|
||||||
|
|
||||||
#if defined(NATIVE_MEMCPY)
|
|
||||||
#define memcpySSE memcpy
|
|
||||||
#elif defined(_MSC_VER)
|
|
||||||
extern "C" void * memcpySSE(void *dst, const void * src, size_t length);
|
|
||||||
#elif (defined(__GNUC__) || defined(__GNUG__)) && defined(__i386__)
|
|
||||||
inline static void * memcpySSE(void *dst, const void * src, size_t length)
|
|
||||||
{
|
|
||||||
if (length == 0 || dst == src)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// copies under 1MB are faster with the inlined memcpy
|
|
||||||
// tell the dev to use that instead
|
|
||||||
if (length < 1048576)
|
|
||||||
{
|
|
||||||
static bool smallBufferWarn = false;
|
|
||||||
if (!smallBufferWarn)
|
|
||||||
{
|
|
||||||
DEBUG_WARN("Do not use memcpySSE for copies under 1MB in size!");
|
|
||||||
smallBufferWarn = true;
|
|
||||||
}
|
|
||||||
memcpy(dst, src, length);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const void * end = dst + (length & ~0x7F);
|
|
||||||
const size_t off = (7 - ((length & 0x7F) >> 4)) * 9;
|
|
||||||
|
|
||||||
__asm__ __volatile__ (
|
|
||||||
"cmp %[dst],%[end] \n\t"
|
|
||||||
"je Remain_%= \n\t"
|
|
||||||
|
|
||||||
// perform SIMD block copy
|
|
||||||
"loop_%=: \n\t"
|
|
||||||
"movaps 0x00(%[src]),%%xmm0 \n\t"
|
|
||||||
"movaps 0x10(%[src]),%%xmm1 \n\t"
|
|
||||||
"movaps 0x20(%[src]),%%xmm2 \n\t"
|
|
||||||
"movaps 0x30(%[src]),%%xmm3 \n\t"
|
|
||||||
"movaps 0x40(%[src]),%%xmm4 \n\t"
|
|
||||||
"movaps 0x50(%[src]),%%xmm5 \n\t"
|
|
||||||
"movaps 0x60(%[src]),%%xmm6 \n\t"
|
|
||||||
"movaps 0x70(%[src]),%%xmm7 \n\t"
|
|
||||||
"movntdq %%xmm0 ,0x00(%[dst]) \n\t"
|
|
||||||
"movntdq %%xmm1 ,0x10(%[dst]) \n\t"
|
|
||||||
"movntdq %%xmm2 ,0x20(%[dst]) \n\t"
|
|
||||||
"movntdq %%xmm3 ,0x30(%[dst]) \n\t"
|
|
||||||
"movntdq %%xmm4 ,0x40(%[dst]) \n\t"
|
|
||||||
"movntdq %%xmm5 ,0x50(%[dst]) \n\t"
|
|
||||||
"movntdq %%xmm6 ,0x60(%[dst]) \n\t"
|
|
||||||
"movntdq %%xmm7 ,0x70(%[dst]) \n\t"
|
|
||||||
"add $0x80,%[dst] \n\t"
|
|
||||||
"add $0x80,%[src] \n\t"
|
|
||||||
"cmp %[dst],%[end] \n\t"
|
|
||||||
"jne loop_%= \n\t"
|
|
||||||
|
|
||||||
"Remain_%=: \n\t"
|
|
||||||
|
|
||||||
// copy any remaining 16 byte blocks
|
|
||||||
"call GetPC_%=\n\t"
|
|
||||||
"Offset_%=:\n\t"
|
|
||||||
"add $(BlockTable_%= - Offset_%=), %%eax \n\t"
|
|
||||||
"add %[off],%%eax \n\t"
|
|
||||||
"jmp *%%eax \n\t"
|
|
||||||
|
|
||||||
"GetPC_%=:\n\t"
|
|
||||||
"mov (%%esp), %%eax \n\t"
|
|
||||||
"ret \n\t"
|
|
||||||
|
|
||||||
"BlockTable_%=:\n\t"
|
|
||||||
"movaps 0x60(%[src]),%%xmm6 \n\t"
|
|
||||||
"movntdq %%xmm6 ,0x60(%[dst]) \n\t"
|
|
||||||
"movaps 0x50(%[src]),%%xmm5 \n\t"
|
|
||||||
"movntdq %%xmm5 ,0x50(%[dst]) \n\t"
|
|
||||||
"movaps 0x40(%[src]),%%xmm4 \n\t"
|
|
||||||
"movntdq %%xmm4 ,0x40(%[dst]) \n\t"
|
|
||||||
"movaps 0x30(%[src]),%%xmm3 \n\t"
|
|
||||||
"movntdq %%xmm3 ,0x30(%[dst]) \n\t"
|
|
||||||
"movaps 0x20(%[src]),%%xmm2 \n\t"
|
|
||||||
"movntdq %%xmm2 ,0x20(%[dst]) \n\t"
|
|
||||||
"movaps 0x10(%[src]),%%xmm1 \n\t"
|
|
||||||
"movntdq %%xmm1 ,0x10(%[dst]) \n\t"
|
|
||||||
"movaps 0x00(%[src]),%%xmm0 \n\t"
|
|
||||||
"movntdq %%xmm0 ,0x00(%[dst]) \n\t"
|
|
||||||
"nop\n\t"
|
|
||||||
"nop\n\t"
|
|
||||||
|
|
||||||
: [dst]"+r" (dst),
|
|
||||||
[src]"+r" (src)
|
|
||||||
: [off]"r" (off),
|
|
||||||
[end]"r" (end)
|
|
||||||
: "eax",
|
|
||||||
"xmm0",
|
|
||||||
"xmm1",
|
|
||||||
"xmm2",
|
|
||||||
"xmm3",
|
|
||||||
"xmm4",
|
|
||||||
"xmm5",
|
|
||||||
"xmm6",
|
|
||||||
"xmm7",
|
|
||||||
"memory"
|
|
||||||
);
|
|
||||||
|
|
||||||
//copy any remaining bytes
|
|
||||||
memcpy(dst, src, length & 0xF);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define memcpySSE memcpy
|
|
||||||
#endif
|
|
@ -17,6 +17,9 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _H_COMMON_OPTION_
|
||||||
|
#define _H_COMMON_OPTION_
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "common/stringlist.h"
|
#include "common/stringlist.h"
|
||||||
|
|
||||||
@ -53,7 +56,7 @@ struct Option
|
|||||||
char * (*toString )(struct Option * opt);
|
char * (*toString )(struct Option * opt);
|
||||||
StringList (*getValues)(struct Option * opt);
|
StringList (*getValues)(struct Option * opt);
|
||||||
|
|
||||||
void (*printHelp)();
|
void (*printHelp)(void);
|
||||||
|
|
||||||
// internal use only
|
// internal use only
|
||||||
bool failed_set;
|
bool failed_set;
|
||||||
@ -75,10 +78,12 @@ bool option_parse(int argc, char * argv[]);
|
|||||||
bool option_load(const char * filename);
|
bool option_load(const char * filename);
|
||||||
|
|
||||||
// called by the main application to validate the option values
|
// called by the main application to validate the option values
|
||||||
bool option_validate();
|
bool option_validate(void);
|
||||||
|
|
||||||
// print out the options, help, and their current values
|
// print out the options, help, and their current values
|
||||||
void option_print();
|
void option_print(void);
|
||||||
|
|
||||||
// final cleanup
|
// final cleanup
|
||||||
void option_free();
|
void option_free(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -17,6 +17,9 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _H_LG_COMMON_STRINGLIST_
|
||||||
|
#define _H_LG_COMMON_STRINGLIST_
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
typedef struct StringList * StringList;
|
typedef struct StringList * StringList;
|
||||||
@ -26,3 +29,5 @@ void stringlist_free (StringList * sl);
|
|||||||
int stringlist_push (StringList sl, char * str);
|
int stringlist_push (StringList sl, char * str);
|
||||||
unsigned int stringlist_count(StringList sl);
|
unsigned int stringlist_count(StringList sl);
|
||||||
char * stringlist_at (StringList sl, unsigned int index);
|
char * stringlist_at (StringList sl, unsigned int index);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KVMGFX Client - A KVM Client for VGA Passthrough
|
KVMGFX Client - A KVM Client for VGA Passthrough
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2021 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -17,6 +17,11 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _H_LG_COMMON_STRINGUTILS
|
||||||
|
#define _H_LG_COMMON_STRINGUTILS
|
||||||
|
|
||||||
// sprintf but with buffer allocation
|
// sprintf but with buffer allocation
|
||||||
int alloc_sprintf(char ** str, const char * format, ...)
|
int alloc_sprintf(char ** str, const char * format, ...)
|
||||||
__attribute__ ((format (printf, 2, 3)));
|
__attribute__ ((format (printf, 2, 3)));
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KVMGFX Client - A KVM Client for VGA Passthrough
|
KVMGFX Client - A KVM Client for VGA Passthrough
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2021 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -17,5 +17,10 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _H_LG_COMMON_SYSUTILS
|
||||||
|
#define _H_LG_COMMON_SYSUTILS
|
||||||
|
|
||||||
// returns the page size
|
// returns the page size
|
||||||
long sysinfo_getPageSize();
|
long sysinfo_getPageSize();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2021 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -17,12 +17,16 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#ifndef _H_LG_COMMON_THREAD_
|
||||||
|
#define _H_LG_COMMON_THREAD_
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
typedef struct LGThread LGThread;
|
typedef struct LGThread LGThread;
|
||||||
typedef int (*LGThreadFunction)(void * opaque);
|
typedef int (*LGThreadFunction)(void * opaque);
|
||||||
|
|
||||||
bool lgCreateThread(const char * name, LGThreadFunction function, void * opaque, LGThread ** handle);
|
bool lgCreateThread(const char * name, LGThreadFunction function, void * opaque,
|
||||||
|
LGThread ** handle);
|
||||||
bool lgJoinThread (LGThread * handle, int * resultCode);
|
bool lgJoinThread (LGThread * handle, int * resultCode);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
58
common/include/common/types.h
Normal file
58
common/include/common/types.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
|
Copyright (C) 2017-2021 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LG_TYPES_H_
|
||||||
|
#define _LG_TYPES_H_
|
||||||
|
|
||||||
|
struct DoublePoint
|
||||||
|
{
|
||||||
|
double x, y;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum FrameType
|
||||||
|
{
|
||||||
|
FRAME_TYPE_INVALID ,
|
||||||
|
FRAME_TYPE_BGRA , // BGRA interleaved: B,G,R,A 32bpp
|
||||||
|
FRAME_TYPE_RGBA , // RGBA interleaved: R,G,B,A 32bpp
|
||||||
|
FRAME_TYPE_RGBA10 , // RGBA interleaved: R,G,B,A 10,10,10,2 bpp
|
||||||
|
FRAME_TYPE_RGBA16F , // RGBA interleaved: R,G,B,A 16,16,16,16 bpp float
|
||||||
|
FRAME_TYPE_MAX , // sentinel value
|
||||||
|
}
|
||||||
|
FrameType;
|
||||||
|
|
||||||
|
typedef enum FrameRotation
|
||||||
|
{
|
||||||
|
FRAME_ROT_0,
|
||||||
|
FRAME_ROT_90,
|
||||||
|
FRAME_ROT_180,
|
||||||
|
FRAME_ROT_270
|
||||||
|
}
|
||||||
|
FrameRotation;
|
||||||
|
|
||||||
|
extern const char * FrameTypeStr[FRAME_TYPE_MAX];
|
||||||
|
|
||||||
|
typedef enum CursorType
|
||||||
|
{
|
||||||
|
CURSOR_TYPE_COLOR ,
|
||||||
|
CURSOR_TYPE_MONOCHROME ,
|
||||||
|
CURSOR_TYPE_MASKED_COLOR
|
||||||
|
}
|
||||||
|
CursorType;
|
||||||
|
|
||||||
|
#endif
|
@ -1 +1,25 @@
|
|||||||
|
/*
|
||||||
|
KVMGFX Client - A KVM Client for VGA Passthrough
|
||||||
|
Copyright (C) 2017-2021 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _H_LG_COMMON_VERSION_
|
||||||
|
#define _H_LG_COMMON_VERSION_
|
||||||
|
|
||||||
extern char * BUILD_VERSION;
|
extern char * BUILD_VERSION;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2021 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -17,7 +17,8 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#ifndef _H_LG_COMMON_WINDEBUG_
|
||||||
|
#define _H_LG_COMMON_WINDEBUG_
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -36,3 +37,5 @@ bool IsWindows8();
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -1,237 +0,0 @@
|
|||||||
.code
|
|
||||||
memcpySSE proc
|
|
||||||
; dst = rcx
|
|
||||||
; src = rdx
|
|
||||||
; len = r8
|
|
||||||
|
|
||||||
mov rax, rcx
|
|
||||||
|
|
||||||
test r8, r8
|
|
||||||
jz @Exit
|
|
||||||
|
|
||||||
cmp rcx, rdx
|
|
||||||
je @Exit
|
|
||||||
|
|
||||||
sub rsp, 8 + 2*16 + 4*8
|
|
||||||
movdqa oword ptr [rsp + 4*8 + 00 ], xmm6
|
|
||||||
movdqa oword ptr [rsp + 4*8 + 16 ], xmm7
|
|
||||||
|
|
||||||
; void * end = dst + (length & ~0x7F);
|
|
||||||
; end = r10
|
|
||||||
mov r9 , r8
|
|
||||||
and r9 , 0FFFFFFFFFFFFFF80h
|
|
||||||
jz @RemainingBlocks
|
|
||||||
mov r10, rcx
|
|
||||||
add r10, r9
|
|
||||||
|
|
||||||
@FullLoop:
|
|
||||||
movaps xmm0 , xmmword ptr [rdx + 000h]
|
|
||||||
movaps xmm1 , xmmword ptr [rdx + 010h]
|
|
||||||
movaps xmm2 , xmmword ptr [rdx + 020h]
|
|
||||||
movaps xmm3 , xmmword ptr [rdx + 030h]
|
|
||||||
movaps xmm4 , xmmword ptr [rdx + 040h]
|
|
||||||
movaps xmm5 , xmmword ptr [rdx + 050h]
|
|
||||||
movaps xmm6 , xmmword ptr [rdx + 060h]
|
|
||||||
movaps xmm7 , xmmword ptr [rdx + 070h]
|
|
||||||
movntdq xmmword ptr [rcx + 000h], xmm0
|
|
||||||
movntdq xmmword ptr [rcx + 010h], xmm1
|
|
||||||
movntdq xmmword ptr [rcx + 020h], xmm2
|
|
||||||
movntdq xmmword ptr [rcx + 030h], xmm3
|
|
||||||
movntdq xmmword ptr [rcx + 040h], xmm4
|
|
||||||
movntdq xmmword ptr [rcx + 050h], xmm5
|
|
||||||
movntdq xmmword ptr [rcx + 060h], xmm6
|
|
||||||
movntdq xmmword ptr [rcx + 070h], xmm7
|
|
||||||
add rdx, 080h
|
|
||||||
add rcx, 080h
|
|
||||||
cmp rcx, r10
|
|
||||||
jne @FullLoop
|
|
||||||
|
|
||||||
@RemainingBlocks:
|
|
||||||
; size_t rem = (length & 0x7F) >> 4);
|
|
||||||
; rem = r11
|
|
||||||
mov r11, r8
|
|
||||||
and r11, 07Fh
|
|
||||||
jz @RestoreExit
|
|
||||||
shr r11, 4
|
|
||||||
jz @FinalBytes
|
|
||||||
|
|
||||||
mov r10, 7
|
|
||||||
sub r10, r11
|
|
||||||
imul r10, 9
|
|
||||||
lea r9 , @FinalBlocks
|
|
||||||
add r9 , r10
|
|
||||||
jmp r9
|
|
||||||
|
|
||||||
@RestoreExit:
|
|
||||||
movdqa xmm6 , oword ptr [rsp + 4*8 + 00]
|
|
||||||
movdqa xmm7 , oword ptr [rsp + 4*8 + 16]
|
|
||||||
add rsp, 8 + 2*16 + 4*8
|
|
||||||
|
|
||||||
@Exit:
|
|
||||||
ret
|
|
||||||
|
|
||||||
@FinalBlocks:
|
|
||||||
movaps xmm6 , xmmword ptr [rdx + 060h]
|
|
||||||
movntdq xmmword ptr [rcx + 060h], xmm6
|
|
||||||
movaps xmm5 , xmmword ptr [rdx + 050h]
|
|
||||||
movntdq xmmword ptr [rcx + 050h], xmm5
|
|
||||||
movaps xmm4 , xmmword ptr [rdx + 040h]
|
|
||||||
movntdq xmmword ptr [rcx + 040h], xmm4
|
|
||||||
movaps xmm3 , xmmword ptr [rdx + 030h]
|
|
||||||
movntdq xmmword ptr [rcx + 030h], xmm3
|
|
||||||
movaps xmm2 , xmmword ptr [rdx + 020h]
|
|
||||||
movntdq xmmword ptr [rcx + 020h], xmm2
|
|
||||||
movaps xmm1 , xmmword ptr [rdx + 010h]
|
|
||||||
movntdq xmmword ptr [rcx + 010h], xmm1
|
|
||||||
movaps xmm0 , xmmword ptr [rdx + 000h]
|
|
||||||
movntdq xmmword ptr [rcx + 000h], xmm0
|
|
||||||
|
|
||||||
movdqa xmm6 , oword ptr [rsp + 4*8 + 00]
|
|
||||||
movdqa xmm7 , oword ptr [rsp + 4*8 + 16]
|
|
||||||
add rsp, 8 + 2*16 + 4*8
|
|
||||||
sfence
|
|
||||||
|
|
||||||
shl r11, 4
|
|
||||||
add rdx, r11
|
|
||||||
add rcx, r11
|
|
||||||
|
|
||||||
@FinalBytes:
|
|
||||||
and r8, 0Fh
|
|
||||||
jz @Exit
|
|
||||||
imul r8, 5
|
|
||||||
lea r9, @FinalBytesTable
|
|
||||||
add r9, r8
|
|
||||||
jmp r9
|
|
||||||
|
|
||||||
@FinalBytesTable:
|
|
||||||
jmp @Copy1
|
|
||||||
jmp @Copy2
|
|
||||||
jmp @Copy3
|
|
||||||
jmp @Copy4
|
|
||||||
jmp @Copy5
|
|
||||||
jmp @Copy6
|
|
||||||
jmp @Copy7
|
|
||||||
jmp @Copy8
|
|
||||||
jmp @Copy9
|
|
||||||
jmp @Copy10
|
|
||||||
jmp @Copy11
|
|
||||||
jmp @Copy12
|
|
||||||
jmp @Copy13
|
|
||||||
jmp @Copy14
|
|
||||||
jmp @Copy15
|
|
||||||
|
|
||||||
db 128 DUP(0CCh)
|
|
||||||
|
|
||||||
; fall through - 1 byte
|
|
||||||
@Copy1:
|
|
||||||
mov al, byte ptr [rdx]
|
|
||||||
mov byte ptr [rcx], al
|
|
||||||
ret
|
|
||||||
|
|
||||||
@Copy2:
|
|
||||||
mov r10w, word ptr [rdx]
|
|
||||||
mov word ptr [rcx], r10w
|
|
||||||
ret
|
|
||||||
|
|
||||||
@Copy3:
|
|
||||||
mov r10w, word ptr [rdx]
|
|
||||||
mov word ptr [rcx], r10w
|
|
||||||
mov r11b, byte ptr [rdx + 02h]
|
|
||||||
mov byte ptr [rcx + 02h], r11b
|
|
||||||
ret
|
|
||||||
|
|
||||||
@Copy4:
|
|
||||||
mov r9d, dword ptr [rdx]
|
|
||||||
mov dword ptr [rcx], r9d
|
|
||||||
ret
|
|
||||||
|
|
||||||
@Copy5:
|
|
||||||
mov r9d, dword ptr [rdx ]
|
|
||||||
mov r11b , byte ptr [rdx + 04h]
|
|
||||||
mov dword ptr [rcx ], r9d
|
|
||||||
mov byte ptr [rcx + 04h], r11b
|
|
||||||
ret
|
|
||||||
|
|
||||||
@Copy6:
|
|
||||||
mov r9d , dword ptr [rdx ]
|
|
||||||
mov r10w, word ptr [rdx + 04h]
|
|
||||||
mov dword ptr [rcx ], r9d
|
|
||||||
mov word ptr [rcx + 04h], r10w
|
|
||||||
ret
|
|
||||||
|
|
||||||
@Copy7:
|
|
||||||
mov r9d , dword ptr [rdx ]
|
|
||||||
mov r10w, word ptr [rdx + 04h]
|
|
||||||
mov r11b, byte ptr [rdx + 06h]
|
|
||||||
mov dword ptr [rcx ], r9d
|
|
||||||
mov word ptr [rcx + 04h], r10w
|
|
||||||
mov byte ptr [rcx + 06h], r11b
|
|
||||||
ret
|
|
||||||
|
|
||||||
@Copy8:
|
|
||||||
mov r8, qword ptr [rdx]
|
|
||||||
mov qword ptr [rcx], r8
|
|
||||||
ret
|
|
||||||
|
|
||||||
@Copy9:
|
|
||||||
mov r8 , qword ptr [rdx ]
|
|
||||||
mov r11b, byte ptr [rdx + 08h]
|
|
||||||
mov qword ptr [rcx ], r8
|
|
||||||
mov byte ptr [rcx + 08h], r11b
|
|
||||||
ret
|
|
||||||
|
|
||||||
@Copy10:
|
|
||||||
mov r8 , qword ptr [rdx ]
|
|
||||||
mov r10w, word ptr [rdx + 08h]
|
|
||||||
mov qword ptr [rcx ], r8
|
|
||||||
mov word ptr [rcx + 08h], r10w
|
|
||||||
ret
|
|
||||||
|
|
||||||
@Copy11:
|
|
||||||
mov r8 , qword ptr [rdx ]
|
|
||||||
mov r10w, word ptr [rdx + 08h]
|
|
||||||
mov r11b, byte ptr [rdx + 0Ah]
|
|
||||||
mov qword ptr [rcx ], r8
|
|
||||||
mov word ptr [rcx + 08h], r10w
|
|
||||||
mov byte ptr [rcx + 0Ah], r11b
|
|
||||||
ret
|
|
||||||
|
|
||||||
@Copy12:
|
|
||||||
mov r8 , qword ptr [rdx ]
|
|
||||||
mov r9d, dword ptr [rdx + 08h]
|
|
||||||
mov qword ptr [rcx ], r8
|
|
||||||
mov dword ptr [rcx + 08h], r9d
|
|
||||||
ret
|
|
||||||
|
|
||||||
@Copy13:
|
|
||||||
mov r8 , qword ptr [rdx ]
|
|
||||||
mov r9d , dword ptr [rdx + 08h]
|
|
||||||
mov r11b, byte ptr [rdx + 0Ch]
|
|
||||||
mov qword ptr [rcx ], r8
|
|
||||||
mov dword ptr [rcx + 08h], r9d
|
|
||||||
mov byte ptr [rcx + 0Ch], r11b
|
|
||||||
ret
|
|
||||||
|
|
||||||
@Copy14:
|
|
||||||
mov r8 , qword ptr [rdx ]
|
|
||||||
mov r9d , dword ptr [rdx + 08h]
|
|
||||||
mov r10w, word ptr [rdx + 0Ch]
|
|
||||||
mov qword ptr [rcx ], r8
|
|
||||||
mov dword ptr [rcx + 08h], r9d
|
|
||||||
mov word ptr [rcx + 0Ch], r10w
|
|
||||||
ret
|
|
||||||
|
|
||||||
; copy 15
|
|
||||||
@Copy15:
|
|
||||||
mov r8 , qword ptr [rdx + 00h]
|
|
||||||
mov r9d , dword ptr [rdx + 08h]
|
|
||||||
mov r10w, word ptr [rdx + 0Ch]
|
|
||||||
mov r11b, byte ptr [rdx + 0Eh]
|
|
||||||
mov qword ptr [rcx + 00h], r8
|
|
||||||
mov dword ptr [rcx + 08h], r9d
|
|
||||||
mov word ptr [rcx + 0Ch], r10w
|
|
||||||
mov byte ptr [rcx + 0Eh], r11b
|
|
||||||
ret
|
|
||||||
|
|
||||||
memcpySSE endp
|
|
||||||
end
|
|
Loading…
Reference in New Issue
Block a user