2021-06-06 01:26:18 +00:00
|
|
|
/**
|
|
|
|
* Looking Glass
|
2022-01-05 08:42:46 +00:00
|
|
|
* Copyright © 2017-2022 The Looking Glass Authors
|
2021-06-06 01:26:18 +00:00
|
|
|
* https://looking-glass.io
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
2019-03-30 01:26:06 +00:00
|
|
|
|
|
|
|
#include <stdbool.h>
|
2020-08-09 05:14:17 +00:00
|
|
|
#include <stdatomic.h>
|
2021-01-18 02:54:21 +00:00
|
|
|
#include <linux/input.h>
|
2019-03-30 01:26:06 +00:00
|
|
|
|
2021-01-15 09:30:03 +00:00
|
|
|
#include "dynamic/displayservers.h"
|
2019-03-30 01:26:06 +00:00
|
|
|
#include "dynamic/renderers.h"
|
2023-01-24 02:33:48 +00:00
|
|
|
#include "dynamic/audiodev.h"
|
2021-01-25 08:58:36 +00:00
|
|
|
|
2021-01-25 16:34:22 +00:00
|
|
|
#include "common/thread.h"
|
2021-01-25 08:58:36 +00:00
|
|
|
#include "common/types.h"
|
2020-01-03 04:17:14 +00:00
|
|
|
#include "common/ivshmem.h"
|
2021-07-04 11:54:44 +00:00
|
|
|
#include "common/locking.h"
|
2021-07-08 15:53:49 +00:00
|
|
|
#include "common/ringbuffer.h"
|
2021-07-25 05:29:29 +00:00
|
|
|
#include "common/event.h"
|
2022-01-12 01:22:18 +00:00
|
|
|
#include "common/ll.h"
|
2019-03-30 01:26:06 +00:00
|
|
|
|
2021-12-28 13:18:25 +00:00
|
|
|
#include <purespice.h>
|
2020-01-09 09:32:42 +00:00
|
|
|
#include <lgmp/client.h>
|
2019-03-30 01:26:06 +00:00
|
|
|
|
2021-07-08 04:05:42 +00:00
|
|
|
#include "cimgui.h"
|
|
|
|
|
2020-08-11 05:14:58 +00:00
|
|
|
enum RunState
|
|
|
|
{
|
|
|
|
APP_STATE_RUNNING,
|
|
|
|
APP_STATE_RESTART,
|
|
|
|
APP_STATE_SHUTDOWN
|
|
|
|
};
|
|
|
|
|
2022-05-22 04:08:33 +00:00
|
|
|
enum MicDefaultState {
|
|
|
|
MIC_DEFAULT_PROMPT,
|
|
|
|
MIC_DEFAULT_ALLOW,
|
|
|
|
MIC_DEFAULT_DENY
|
|
|
|
};
|
2022-06-02 03:00:22 +00:00
|
|
|
#define MIC_DEFAULT_MAX (MIC_DEFAULT_DENY + 1)
|
2022-05-22 04:08:33 +00:00
|
|
|
|
2019-03-30 01:26:06 +00:00
|
|
|
struct AppState
|
|
|
|
{
|
2021-01-15 09:30:03 +00:00
|
|
|
enum RunState state;
|
|
|
|
|
2021-07-29 21:36:28 +00:00
|
|
|
ImGuiIO * io;
|
|
|
|
ImGuiStyle * style;
|
|
|
|
struct ll * overlays;
|
|
|
|
char * fontName;
|
|
|
|
ImFont * fontLarge;
|
2022-01-15 05:33:54 +00:00
|
|
|
ImVector_ImWchar fontRange;
|
2021-07-29 21:36:28 +00:00
|
|
|
bool overlayInput;
|
|
|
|
ImGuiMouseCursor cursorLast;
|
2021-07-31 11:14:23 +00:00
|
|
|
char * imGuiIni;
|
2021-08-19 19:57:20 +00:00
|
|
|
bool modCtrl;
|
|
|
|
bool modShift;
|
|
|
|
bool modAlt;
|
|
|
|
bool modSuper;
|
2021-08-30 10:48:41 +00:00
|
|
|
uint64_t lastImGuiFrame;
|
2022-01-07 13:46:16 +00:00
|
|
|
bool renderImGuiTwice;
|
2021-07-23 09:58:33 +00:00
|
|
|
|
2021-01-15 09:30:03 +00:00
|
|
|
struct LG_DisplayServerOps * ds;
|
2021-01-27 08:27:19 +00:00
|
|
|
bool dsInitialized;
|
2021-08-01 00:07:05 +00:00
|
|
|
bool jitRender;
|
2021-01-15 09:30:03 +00:00
|
|
|
|
2022-01-06 03:38:46 +00:00
|
|
|
uint8_t spiceUUID[16];
|
2022-01-17 09:26:45 +00:00
|
|
|
bool spiceReady;
|
2022-05-23 23:48:54 +00:00
|
|
|
bool initialSpiceDisplay;
|
2022-01-06 03:38:46 +00:00
|
|
|
uint8_t guestUUID[16];
|
|
|
|
bool guestUUIDValid;
|
2022-01-17 09:26:45 +00:00
|
|
|
KVMFROS guestOS;
|
2022-01-06 03:38:46 +00:00
|
|
|
|
2022-05-23 14:05:22 +00:00
|
|
|
bool lgHostConnected;
|
|
|
|
|
2020-10-14 08:32:21 +00:00
|
|
|
bool stopVideo;
|
2019-03-30 01:26:06 +00:00
|
|
|
bool ignoreInput;
|
|
|
|
bool escapeActive;
|
2021-02-25 09:01:22 +00:00
|
|
|
uint64_t escapeTime;
|
2021-01-26 10:46:30 +00:00
|
|
|
int escapeAction;
|
2021-02-25 23:21:56 +00:00
|
|
|
bool escapeHelp;
|
2022-06-29 08:24:53 +00:00
|
|
|
struct ll * bindings;
|
2021-01-18 02:54:21 +00:00
|
|
|
bool keyDown[KEY_MAX];
|
2019-03-30 01:26:06 +00:00
|
|
|
|
|
|
|
bool haveSrcSize;
|
2021-01-26 10:46:30 +00:00
|
|
|
struct Point windowPos;
|
2019-03-30 01:26:06 +00:00
|
|
|
int windowW, windowH;
|
2021-01-04 01:59:14 +00:00
|
|
|
int windowCX, windowCY;
|
2021-02-21 05:08:52 +00:00
|
|
|
double windowScale;
|
2021-01-18 15:44:56 +00:00
|
|
|
LG_RendererRotate rotate;
|
2021-01-08 09:26:32 +00:00
|
|
|
bool focused;
|
2021-01-25 11:23:53 +00:00
|
|
|
struct Border border;
|
2021-01-26 10:46:30 +00:00
|
|
|
struct Point srcSize;
|
2019-03-30 01:26:06 +00:00
|
|
|
LG_RendererRect dstRect;
|
2021-01-18 18:56:40 +00:00
|
|
|
bool posInfoValid;
|
|
|
|
bool alignToGuest;
|
2022-01-08 08:32:58 +00:00
|
|
|
bool spiceClose;
|
2020-08-20 04:52:24 +00:00
|
|
|
|
2021-08-08 05:32:01 +00:00
|
|
|
LG_Renderer * lgr;
|
2021-01-04 02:40:03 +00:00
|
|
|
atomic_int lgrResize;
|
2021-07-04 11:54:44 +00:00
|
|
|
LG_Lock lgrLock;
|
2021-08-02 13:37:33 +00:00
|
|
|
bool useDMA;
|
2019-03-30 01:26:06 +00:00
|
|
|
|
2021-01-15 09:30:03 +00:00
|
|
|
bool cbAvailable;
|
2021-12-28 11:03:48 +00:00
|
|
|
PSDataType cbType;
|
2020-12-03 01:01:51 +00:00
|
|
|
bool cbChunked;
|
|
|
|
size_t cbXfer;
|
2019-03-30 01:26:06 +00:00
|
|
|
struct ll * cbRequestList;
|
|
|
|
|
2020-01-03 04:17:14 +00:00
|
|
|
struct IVSHMEM shm;
|
2020-01-09 09:32:42 +00:00
|
|
|
PLGMPClient lgmp;
|
2020-01-10 00:00:46 +00:00
|
|
|
PLGMPClientQueue pointerQueue;
|
2022-01-26 06:20:12 +00:00
|
|
|
LG_Lock pointerQueueLock;
|
2021-08-05 12:19:35 +00:00
|
|
|
KVMFRFeatureFlags kvmfrFeatures;
|
2019-03-30 01:26:06 +00:00
|
|
|
|
2021-10-06 09:04:06 +00:00
|
|
|
LGThread * cursorThread;
|
2021-01-25 16:34:22 +00:00
|
|
|
LGThread * frameThread;
|
2021-07-25 05:29:29 +00:00
|
|
|
LGEvent * frameEvent;
|
|
|
|
atomic_bool invalidateWindow;
|
2021-01-21 04:39:15 +00:00
|
|
|
bool formatValid;
|
2021-07-31 06:19:55 +00:00
|
|
|
uint64_t frameTime;
|
|
|
|
uint64_t overlayFrameTime;
|
2020-08-09 05:14:17 +00:00
|
|
|
uint64_t lastFrameTime;
|
2021-07-10 04:20:28 +00:00
|
|
|
bool lastFrameTimeValid;
|
2021-07-08 15:53:49 +00:00
|
|
|
uint64_t lastRenderTime;
|
2021-07-10 04:20:28 +00:00
|
|
|
bool lastRenderTimeValid;
|
2021-07-08 15:53:49 +00:00
|
|
|
RingBuffer renderTimings;
|
2021-08-03 10:34:55 +00:00
|
|
|
RingBuffer renderDuration;
|
2021-08-03 21:39:44 +00:00
|
|
|
RingBuffer uploadTimings;
|
2021-07-19 00:58:40 +00:00
|
|
|
|
2021-08-01 09:32:01 +00:00
|
|
|
atomic_uint_least64_t pendingCount;
|
2021-07-21 06:47:37 +00:00
|
|
|
atomic_uint_least64_t renderCount, frameCount;
|
2021-07-19 00:58:40 +00:00
|
|
|
_Atomic(float) fps, ups;
|
2020-01-03 04:53:44 +00:00
|
|
|
|
|
|
|
uint64_t resizeTimeout;
|
|
|
|
bool resizeDone;
|
2021-02-03 23:01:53 +00:00
|
|
|
|
|
|
|
bool autoIdleInhibitState;
|
2022-06-02 02:50:42 +00:00
|
|
|
|
|
|
|
enum MicDefaultState micDefaultState;
|
2022-09-19 00:30:18 +00:00
|
|
|
|
|
|
|
int spiceHotX, spiceHotY;
|
2019-03-30 01:26:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct AppParams
|
|
|
|
{
|
2022-05-22 04:08:33 +00:00
|
|
|
bool autoResize;
|
|
|
|
bool allowResize;
|
|
|
|
bool keepAspect;
|
|
|
|
bool forceAspect;
|
|
|
|
bool dontUpscale;
|
|
|
|
bool intUpscale;
|
|
|
|
bool shrinkOnUpscale;
|
|
|
|
bool borderless;
|
|
|
|
bool fullscreen;
|
|
|
|
bool maximize;
|
|
|
|
bool minimizeOnFocusLoss;
|
|
|
|
bool center;
|
|
|
|
int x, y;
|
|
|
|
unsigned int w, h;
|
|
|
|
int fpsMin;
|
|
|
|
LG_RendererRotate winRotate;
|
|
|
|
bool useSpice;
|
|
|
|
bool useSpiceInput;
|
|
|
|
bool useSpiceClipboard;
|
|
|
|
bool useSpiceAudio;
|
|
|
|
const char * spiceHost;
|
|
|
|
unsigned int spicePort;
|
|
|
|
bool clipboardToVM;
|
|
|
|
bool clipboardToLocal;
|
|
|
|
bool scaleMouseInput;
|
|
|
|
bool hideMouse;
|
|
|
|
bool ignoreQuit;
|
|
|
|
bool noScreensaver;
|
|
|
|
bool autoScreensaver;
|
2023-09-11 11:01:19 +00:00
|
|
|
bool captureOnFocus;
|
2022-05-22 04:08:33 +00:00
|
|
|
bool grabKeyboard;
|
|
|
|
bool grabKeyboardOnFocus;
|
|
|
|
int escapeKey;
|
|
|
|
bool ignoreWindowsKeys;
|
|
|
|
bool releaseKeysOnFocusLoss;
|
|
|
|
bool showAlerts;
|
|
|
|
bool captureOnStart;
|
|
|
|
bool quickSplash;
|
2022-05-27 01:36:39 +00:00
|
|
|
bool overlayDim;
|
2022-05-22 04:08:33 +00:00
|
|
|
bool alwaysShowCursor;
|
|
|
|
uint64_t helpMenuDelayUs;
|
|
|
|
const char * uiFont;
|
|
|
|
int uiSize;
|
|
|
|
bool jitRender;
|
|
|
|
|
|
|
|
unsigned int cursorPollInterval;
|
|
|
|
unsigned int framePollInterval;
|
|
|
|
bool allowDMA;
|
|
|
|
|
|
|
|
bool forceRenderer;
|
|
|
|
unsigned int forceRendererIndex;
|
|
|
|
|
|
|
|
const char * windowTitle;
|
|
|
|
bool mouseRedraw;
|
|
|
|
int mouseSens;
|
|
|
|
bool mouseSmoothing;
|
|
|
|
bool rawMouse;
|
|
|
|
bool autoCapture;
|
|
|
|
bool captureInputOnly;
|
|
|
|
bool showCursorDot;
|
|
|
|
|
|
|
|
int audioPeriodSize;
|
|
|
|
int audioBufferLatency;
|
|
|
|
bool micShowIndicator;
|
|
|
|
enum MicDefaultState micDefaultState;
|
2023-04-16 09:10:04 +00:00
|
|
|
bool audioSyncVolume;
|
2019-03-30 01:26:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct CBRequest
|
|
|
|
{
|
2021-12-28 11:03:48 +00:00
|
|
|
PSDataType type;
|
2019-03-30 01:26:06 +00:00
|
|
|
LG_ClipboardReplyFn replyFn;
|
|
|
|
void * opaque;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct KeybindHandle
|
|
|
|
{
|
2022-06-29 08:24:53 +00:00
|
|
|
int sc;
|
|
|
|
int charcode;
|
|
|
|
KeybindFn callback;
|
|
|
|
const char * description;
|
|
|
|
void * opaque;
|
2019-03-30 01:26:06 +00:00
|
|
|
};
|
|
|
|
|
2021-01-04 01:04:43 +00:00
|
|
|
enum WarpState
|
|
|
|
{
|
|
|
|
WARP_STATE_ON,
|
|
|
|
WARP_STATE_OFF
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CursorInfo
|
|
|
|
{
|
|
|
|
/* x & y postiion */
|
|
|
|
int x , y;
|
|
|
|
|
|
|
|
/* pointer hotspot offsets */
|
|
|
|
int hx, hy;
|
|
|
|
|
|
|
|
/* true if the pointer is visible on the guest */
|
|
|
|
bool visible;
|
|
|
|
|
|
|
|
/* true if the details in this struct are valid */
|
|
|
|
bool valid;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CursorState
|
|
|
|
{
|
|
|
|
/* cursor is in grab mode */
|
2021-01-08 09:49:20 +00:00
|
|
|
bool grab;
|
2021-01-04 01:04:43 +00:00
|
|
|
|
|
|
|
/* true if we are to draw the cursor on screen */
|
2021-01-08 09:49:20 +00:00
|
|
|
bool draw;
|
2021-01-04 01:04:43 +00:00
|
|
|
|
|
|
|
/* true if the cursor is currently in our window */
|
2021-01-08 09:49:20 +00:00
|
|
|
bool inWindow;
|
2021-01-04 01:04:43 +00:00
|
|
|
|
|
|
|
/* true if the cursor is currently in the guest view area */
|
2021-01-08 09:49:20 +00:00
|
|
|
bool inView;
|
2021-01-04 01:04:43 +00:00
|
|
|
|
2021-01-17 01:53:55 +00:00
|
|
|
/* true if the guest should be realigned to the host when next drawn */
|
|
|
|
bool realign;
|
|
|
|
|
2022-01-15 05:00:34 +00:00
|
|
|
/* true if the guest is currently realigning to the host */
|
|
|
|
bool realigning;
|
|
|
|
|
2021-01-04 01:04:43 +00:00
|
|
|
/* true if the cursor needs re-drawing/updating */
|
2021-01-08 09:49:20 +00:00
|
|
|
bool redraw;
|
2021-01-04 01:04:43 +00:00
|
|
|
|
|
|
|
/* true if the cursor movements should be scaled */
|
2021-01-08 09:49:20 +00:00
|
|
|
bool useScale;
|
2021-01-04 01:04:43 +00:00
|
|
|
|
|
|
|
/* the amount to scale the X & Y movements by */
|
2021-01-08 09:49:20 +00:00
|
|
|
struct DoublePoint scale;
|
2021-01-04 01:04:43 +00:00
|
|
|
|
2021-01-08 09:49:20 +00:00
|
|
|
/* the error accumulator */
|
|
|
|
struct DoublePoint acc;
|
2021-01-04 01:04:43 +00:00
|
|
|
|
2021-01-08 09:49:20 +00:00
|
|
|
/* the local position */
|
2021-01-08 02:17:42 +00:00
|
|
|
struct DoublePoint pos;
|
2021-01-06 11:11:28 +00:00
|
|
|
|
2021-01-18 18:56:40 +00:00
|
|
|
/* true if the position is valid */
|
|
|
|
bool valid;
|
|
|
|
|
2021-01-17 04:13:45 +00:00
|
|
|
/* the button state */
|
|
|
|
unsigned int buttons;
|
|
|
|
|
2021-01-08 08:41:10 +00:00
|
|
|
/* the delta since last warp when in auto capture mode */
|
|
|
|
struct DoublePoint delta;
|
|
|
|
|
2021-01-08 02:17:42 +00:00
|
|
|
/* the scale factor for the mouse sensitiviy */
|
|
|
|
int sens;
|
2021-01-04 01:04:43 +00:00
|
|
|
|
2021-01-08 02:17:42 +00:00
|
|
|
/* the mouse warp state */
|
2021-01-04 01:04:43 +00:00
|
|
|
enum WarpState warpState;
|
|
|
|
|
|
|
|
/* the guest's cursor position */
|
|
|
|
struct CursorInfo guest;
|
[client] spice/wayland: improve cursor tracking logic
One of the major issues with the old tracking code is a data race
between the cursor thread updating g_cursor.guest and the
app_handleMouseBasic function. Specifically, the latter may have
sent mouse input via spice that has not been processed by the guest
and updated g_cursor.guest, but the guest may overwrite g_cursor.guest
to a previous state before the input is processed. This causes some
movements to be doubled. Eventually, the cursor positions will
synchronize, but this nevertheless causes a lot of jitter.
In this commit, we introduce a new field g_cursor.projected, which
is unambiguously the position of the cursor after taking into account
all the input already sent via spice. This is synced up to the guest
cursor upon entering the window and when the host restarts. Afterwards,
all mouse movements will be based on this position. This eliminates
all cursor jitter as far as I could tell.
Also, the cursor is now synced to the host position when exiting
capture mode.
A downside of this commit is that if the 1:1 movement patch is not
correctly applied, the cursor position would be wildly off instead
of simply jittering, but that is an unsupported configuration and
should not matter.
Also unsupported is when an application in guest moves the cursor
programmatically and bypassing spice. When using those applications,
capture mode must be on. Before this commit, we try to move the guest
cursor back to where it should be, but it's inherently fragile and
may lead to scenarios such as wild movements in first-person shooters.
2021-01-21 02:05:50 +00:00
|
|
|
|
|
|
|
/* the projected position after move, for app_handleMouseBasic only */
|
|
|
|
struct Point projected;
|
2021-01-04 01:04:43 +00:00
|
|
|
};
|
|
|
|
|
2019-03-30 01:26:06 +00:00
|
|
|
// forwards
|
2021-01-25 08:58:36 +00:00
|
|
|
extern struct AppState g_state;
|
|
|
|
extern struct CursorState g_cursor;
|
|
|
|
extern struct AppParams g_params;
|
2021-01-25 16:34:22 +00:00
|
|
|
|
2021-10-06 09:04:06 +00:00
|
|
|
int main_cursorThread(void * unused);
|
2021-01-25 16:34:22 +00:00
|
|
|
int main_frameThread(void * unused);
|
2021-08-08 05:32:01 +00:00
|
|
|
|
|
|
|
#define RENDERER(fn, ...) g_state.lgr->ops.fn(g_state.lgr, ##__VA_ARGS__)
|