mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-14 00:14:11 +09:00
[server,shadow] implement relative mouse support
This commit is contained in:
@@ -92,6 +92,10 @@ extern "C"
|
||||
UINT16 code);
|
||||
typedef BOOL (*pfnShadowMouseEvent)(rdpShadowSubsystem* subsystem, rdpShadowClient* client,
|
||||
UINT16 flags, UINT16 x, UINT16 y);
|
||||
typedef BOOL (*pfnShadowRelMouseEvent)(rdpShadowSubsystem* subsystem, rdpShadowClient* client,
|
||||
UINT16 flags, INT16 xDelta,
|
||||
INT16 yDelta); /** @since version 3.15.0 */
|
||||
|
||||
typedef BOOL (*pfnShadowExtendedMouseEvent)(rdpShadowSubsystem* subsystem,
|
||||
rdpShadowClient* client, UINT16 flags, UINT16 x,
|
||||
UINT16 y);
|
||||
@@ -244,6 +248,8 @@ extern "C"
|
||||
pfnShadowClientCapabilities ClientCapabilities;
|
||||
|
||||
rdpShadowServer* server;
|
||||
|
||||
pfnShadowRelMouseEvent RelMouseEvent; /** @since version 3.15.0 */
|
||||
};
|
||||
|
||||
/* Definition of message between subsystem and clients */
|
||||
|
||||
@@ -248,7 +248,8 @@ static BOOL x11_shadow_input_keyboard_event(rdpShadowSubsystem* subsystem, rdpSh
|
||||
XFlush(x11->display);
|
||||
XUnlockDisplay(x11->display);
|
||||
}
|
||||
|
||||
#else
|
||||
WLog_WARN(TAG, "KeyboardEvent not supported by backend, ignoring");
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
@@ -336,6 +337,65 @@ static BOOL x11_shadow_input_mouse_event(rdpShadowSubsystem* subsystem, rdpShado
|
||||
XTestGrabControl(x11->display, False);
|
||||
XFlush(x11->display);
|
||||
XUnlockDisplay(x11->display);
|
||||
#else
|
||||
WLog_WARN(TAG, "MouseEvent not supported by backend, ignoring");
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL x11_shadow_input_rel_mouse_event(rdpShadowSubsystem* subsystem, rdpShadowClient* client,
|
||||
UINT16 flags, INT16 xDelta, INT16 yDelta)
|
||||
{
|
||||
#ifdef WITH_XTEST
|
||||
x11ShadowSubsystem* x11 = (x11ShadowSubsystem*)subsystem;
|
||||
WINPR_ASSERT(x11);
|
||||
|
||||
unsigned int button = 0;
|
||||
BOOL down = FALSE;
|
||||
|
||||
if (!subsystem || !client)
|
||||
return FALSE;
|
||||
|
||||
rdpShadowServer* server = subsystem->server;
|
||||
|
||||
if (!server)
|
||||
return FALSE;
|
||||
|
||||
rdpShadowSurface* surface = server->surface;
|
||||
|
||||
if (!surface)
|
||||
return FALSE;
|
||||
|
||||
x11->lastMouseClient = client;
|
||||
|
||||
XLockDisplay(x11->display);
|
||||
XTestGrabControl(x11->display, True);
|
||||
|
||||
if (flags & PTR_FLAGS_MOVE)
|
||||
XTestFakeRelativeMotionEvent(x11->display, xDelta, yDelta, 0);
|
||||
|
||||
if (flags & PTR_FLAGS_BUTTON1)
|
||||
button = 1;
|
||||
else if (flags & PTR_FLAGS_BUTTON2)
|
||||
button = 3;
|
||||
else if (flags & PTR_FLAGS_BUTTON3)
|
||||
button = 2;
|
||||
else if (flags & PTR_XFLAGS_BUTTON1)
|
||||
button = 4;
|
||||
else if (flags & PTR_XFLAGS_BUTTON2)
|
||||
button = 5;
|
||||
|
||||
if (flags & PTR_FLAGS_DOWN)
|
||||
down = TRUE;
|
||||
|
||||
if (button)
|
||||
XTestFakeButtonEvent(x11->display, button, down, CurrentTime);
|
||||
|
||||
XTestGrabControl(x11->display, False);
|
||||
XFlush(x11->display);
|
||||
XUnlockDisplay(x11->display);
|
||||
#else
|
||||
WLog_WARN(TAG, "RelMouseEvent not supported by backend, ignoring");
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
@@ -385,6 +445,8 @@ static BOOL x11_shadow_input_extended_mouse_event(rdpShadowSubsystem* subsystem,
|
||||
XTestGrabControl(x11->display, False);
|
||||
XFlush(x11->display);
|
||||
XUnlockDisplay(x11->display);
|
||||
#else
|
||||
WLog_WARN(TAG, "ExtendedMouseEvent not supported by backend, ignoring");
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1480,6 +1542,7 @@ static rdpShadowSubsystem* x11_shadow_subsystem_new(void)
|
||||
subsystem->common.KeyboardEvent = x11_shadow_input_keyboard_event;
|
||||
subsystem->common.UnicodeKeyboardEvent = x11_shadow_input_unicode_keyboard_event;
|
||||
subsystem->common.MouseEvent = x11_shadow_input_mouse_event;
|
||||
subsystem->common.RelMouseEvent = x11_shadow_input_rel_mouse_event;
|
||||
subsystem->common.ExtendedMouseEvent = x11_shadow_input_extended_mouse_event;
|
||||
subsystem->composite = FALSE;
|
||||
subsystem->use_xshm = FALSE; /* temporarily disabled */
|
||||
|
||||
@@ -52,6 +52,8 @@ int main(int argc, char** argv)
|
||||
"Select or list monitors" },
|
||||
{ "max-connections", COMMAND_LINE_VALUE_REQUIRED, "<number>", 0, NULL, -1, NULL,
|
||||
"maximum connections allowed to server, 0 to deactivate" },
|
||||
{ "mouse-relative", COMMAND_LINE_VALUE_BOOL, NULL, NULL, NULL, -1, NULL,
|
||||
"enable support for relative mouse events" },
|
||||
{ "rect", COMMAND_LINE_VALUE_REQUIRED, "<x,y,w,h>", NULL, NULL, -1, NULL,
|
||||
"Select rectangle within monitor to share" },
|
||||
{ "auth", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL,
|
||||
@@ -140,7 +142,6 @@ int main(int argc, char** argv)
|
||||
!freerdp_settings_set_bool(settings, FreeRDP_GfxProgressiveV2, TRUE))
|
||||
goto fail;
|
||||
|
||||
/* TODO: We do not implement relative mouse callbacks, so deactivate it for now */
|
||||
if (!freerdp_settings_set_bool(settings, FreeRDP_MouseUseRelativeMove, FALSE) ||
|
||||
!freerdp_settings_set_bool(settings, FreeRDP_HasRelativeMouseEvent, FALSE))
|
||||
goto fail;
|
||||
|
||||
@@ -16,15 +16,24 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include "shadow.h"
|
||||
|
||||
#define TAG SERVER_TAG("shadow.input")
|
||||
|
||||
static BOOL shadow_input_synchronize_event(rdpInput* input, UINT32 flags)
|
||||
{
|
||||
WINPR_ASSERT(input);
|
||||
rdpShadowClient* client = (rdpShadowClient*)input->context;
|
||||
WINPR_ASSERT(client);
|
||||
WINPR_ASSERT(client->server);
|
||||
rdpShadowSubsystem* subsystem = client->server->subsystem;
|
||||
WINPR_ASSERT(subsystem);
|
||||
|
||||
WLog_DBG(TAG, "[%s] flags=0x%04" PRIx16, client->mayInteract ? "use" : "discard", flags);
|
||||
if (!client->mayInteract)
|
||||
return TRUE;
|
||||
|
||||
@@ -33,9 +42,14 @@ static BOOL shadow_input_synchronize_event(rdpInput* input, UINT32 flags)
|
||||
|
||||
static BOOL shadow_input_keyboard_event(rdpInput* input, UINT16 flags, UINT8 code)
|
||||
{
|
||||
WINPR_ASSERT(input);
|
||||
rdpShadowClient* client = (rdpShadowClient*)input->context;
|
||||
WINPR_ASSERT(client);
|
||||
WINPR_ASSERT(client->server);
|
||||
rdpShadowSubsystem* subsystem = client->server->subsystem;
|
||||
WINPR_ASSERT(subsystem);
|
||||
|
||||
WLog_DBG(TAG, "[%s] flags=0x%04" PRIx16, client->mayInteract ? "use" : "discard", flags);
|
||||
if (!client->mayInteract)
|
||||
return TRUE;
|
||||
|
||||
@@ -44,9 +58,14 @@ static BOOL shadow_input_keyboard_event(rdpInput* input, UINT16 flags, UINT8 cod
|
||||
|
||||
static BOOL shadow_input_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
||||
{
|
||||
WINPR_ASSERT(input);
|
||||
rdpShadowClient* client = (rdpShadowClient*)input->context;
|
||||
WINPR_ASSERT(client);
|
||||
WINPR_ASSERT(client->server);
|
||||
rdpShadowSubsystem* subsystem = client->server->subsystem;
|
||||
WINPR_ASSERT(subsystem);
|
||||
|
||||
WLog_DBG(TAG, "[%s] flags=0x%04" PRIx16, client->mayInteract ? "use" : "discard", flags);
|
||||
if (!client->mayInteract)
|
||||
return TRUE;
|
||||
|
||||
@@ -55,8 +74,12 @@ static BOOL shadow_input_unicode_keyboard_event(rdpInput* input, UINT16 flags, U
|
||||
|
||||
static BOOL shadow_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
||||
{
|
||||
WINPR_ASSERT(input);
|
||||
rdpShadowClient* client = (rdpShadowClient*)input->context;
|
||||
WINPR_ASSERT(client);
|
||||
WINPR_ASSERT(client->server);
|
||||
rdpShadowSubsystem* subsystem = client->server->subsystem;
|
||||
WINPR_ASSERT(subsystem);
|
||||
|
||||
if (client->server->shareSubRect)
|
||||
{
|
||||
@@ -64,7 +87,7 @@ static BOOL shadow_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UI
|
||||
y += client->server->subRect.top;
|
||||
}
|
||||
|
||||
if (!(flags & PTR_FLAGS_WHEEL))
|
||||
if ((flags & (PTR_FLAGS_WHEEL | PTR_FLAGS_HWHEEL | PTR_FLAGS_WHEEL_NEGATIVE)) == 0)
|
||||
{
|
||||
client->pointerX = x;
|
||||
client->pointerY = y;
|
||||
@@ -78,16 +101,47 @@ static BOOL shadow_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UI
|
||||
}
|
||||
}
|
||||
|
||||
WLog_DBG(TAG, "[%s] flags=0x%04" PRIx16 ", x=%" PRIu16 ", y=%" PRIu16,
|
||||
client->mayInteract ? "use" : "discard", flags, x, y);
|
||||
if (!client->mayInteract)
|
||||
return TRUE;
|
||||
|
||||
return IFCALLRESULT(TRUE, subsystem->MouseEvent, subsystem, client, flags, x, y);
|
||||
}
|
||||
|
||||
static BOOL shadow_input_rel_mouse_event(rdpInput* input, UINT16 flags, INT16 xDelta, INT16 yDelta)
|
||||
{
|
||||
WINPR_ASSERT(input);
|
||||
|
||||
rdpShadowClient* client = (rdpShadowClient*)input->context;
|
||||
WINPR_ASSERT(client);
|
||||
WINPR_ASSERT(client->server);
|
||||
|
||||
rdpShadowSubsystem* subsystem = client->server->subsystem;
|
||||
WINPR_ASSERT(subsystem);
|
||||
|
||||
WLog_DBG(TAG, "[%s] flags=0x%04" PRIx16 ", x=%" PRId16 ", y=%" PRId16,
|
||||
client->mayInteract ? "use" : "discard", flags, xDelta, yDelta);
|
||||
const uint16_t mask = PTR_FLAGS_MOVE | PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1 | PTR_FLAGS_BUTTON2 |
|
||||
PTR_FLAGS_BUTTON3 | PTR_XFLAGS_BUTTON1 | PTR_XFLAGS_BUTTON2;
|
||||
if ((flags & mask) != 0)
|
||||
{
|
||||
WLog_WARN(TAG, "Unknown flags 0x%04" PRIx16, flags & ~mask);
|
||||
}
|
||||
if (!client->mayInteract)
|
||||
return TRUE;
|
||||
|
||||
return IFCALLRESULT(TRUE, subsystem->RelMouseEvent, subsystem, client, flags, xDelta, yDelta);
|
||||
}
|
||||
|
||||
static BOOL shadow_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
||||
{
|
||||
WINPR_ASSERT(input);
|
||||
rdpShadowClient* client = (rdpShadowClient*)input->context;
|
||||
WINPR_ASSERT(client);
|
||||
WINPR_ASSERT(client->server);
|
||||
rdpShadowSubsystem* subsystem = client->server->subsystem;
|
||||
WINPR_ASSERT(subsystem);
|
||||
|
||||
if (client->server->shareSubRect)
|
||||
{
|
||||
@@ -98,6 +152,8 @@ static BOOL shadow_input_extended_mouse_event(rdpInput* input, UINT16 flags, UIN
|
||||
client->pointerX = x;
|
||||
client->pointerY = y;
|
||||
|
||||
WLog_DBG(TAG, "[%s] flags=0x%04" PRIx16 ", x=%" PRIu16 ", y=%" PRIu16,
|
||||
client->mayInteract ? "use" : "discard", flags, x, y);
|
||||
if (!client->mayInteract)
|
||||
return TRUE;
|
||||
|
||||
@@ -106,9 +162,11 @@ static BOOL shadow_input_extended_mouse_event(rdpInput* input, UINT16 flags, UIN
|
||||
|
||||
void shadow_input_register_callbacks(rdpInput* input)
|
||||
{
|
||||
WINPR_ASSERT(input);
|
||||
input->SynchronizeEvent = shadow_input_synchronize_event;
|
||||
input->KeyboardEvent = shadow_input_keyboard_event;
|
||||
input->UnicodeKeyboardEvent = shadow_input_unicode_keyboard_event;
|
||||
input->MouseEvent = shadow_input_mouse_event;
|
||||
input->ExtendedMouseEvent = shadow_input_extended_mouse_event;
|
||||
input->RelMouseEvent = shadow_input_rel_mouse_event;
|
||||
}
|
||||
|
||||
@@ -244,6 +244,13 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
|
||||
{
|
||||
server->mayInteract = arg->Value ? TRUE : FALSE;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "mouse-relative")
|
||||
{
|
||||
const BOOL val = arg->Value ? TRUE : FALSE;
|
||||
if (!freerdp_settings_set_bool(settings, FreeRDP_MouseUseRelativeMove, val) ||
|
||||
!freerdp_settings_set_bool(settings, FreeRDP_HasRelativeMouseEvent, val))
|
||||
return fail_at(arg, COMMAND_LINE_ERROR);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "max-connections")
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
Reference in New Issue
Block a user