[server,sample] implement relative mouse event

* implement callbacks for relative mouse input events
* optimize drawing:
  * only send drawing rectangle for current cursor position (background
    image data) and then the current cursor
This commit is contained in:
akallabeth
2025-04-10 16:08:20 +02:00
parent 25f54d866f
commit f708f90937

View File

@@ -219,28 +219,22 @@ static BOOL stream_surface_bits_supported(const rdpSettings* settings)
return ((supported & SURFCMDS_STREAM_SURFACE_BITS) != 0);
}
static BOOL test_peer_draw_background(freerdp_peer* client)
static BOOL test_peer_draw_background(freerdp_peer* client, const RFX_RECT* rect)
{
size_t size = 0;
wStream* s = NULL;
RFX_RECT rect;
BYTE* rgb_data = NULL;
const rdpSettings* settings = NULL;
rdpUpdate* update = NULL;
SURFACE_BITS_COMMAND cmd = { 0 };
testPeerContext* context = NULL;
BOOL ret = FALSE;
const UINT32 colorFormat = PIXEL_FORMAT_RGB24;
const size_t bpp = FreeRDPGetBytesPerPixel(colorFormat);
WINPR_ASSERT(client);
context = (testPeerContext*)client->context;
testPeerContext* context = (testPeerContext*)client->context;
WINPR_ASSERT(context);
settings = client->context->settings;
rdpSettings* settings = client->context->settings;
WINPR_ASSERT(settings);
update = client->context->update;
rdpUpdate* update = client->context->update;
WINPR_ASSERT(update);
const BOOL RemoteFxCodec = freerdp_settings_get_bool(settings, FreeRDP_RemoteFxCodec);
@@ -250,14 +244,13 @@ static BOOL test_peer_draw_background(freerdp_peer* client)
WINPR_ASSERT(freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth) <= UINT16_MAX);
WINPR_ASSERT(freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight) <= UINT16_MAX);
s = test_peer_stream_init(context);
rect.x = 0;
rect.y = 0;
rect.width = (UINT16)freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
rect.height = (UINT16)freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
size = bpp * rect.width * rect.height;
wStream* s = test_peer_stream_init(context);
const size_t size = bpp * rect->width * rect->height;
if (size == 0)
return FALSE;
if (!(rgb_data = malloc(size)))
BYTE* rgb_data = malloc(size);
if (!rgb_data)
{
WLog_ERR(TAG, "Problem allocating memory");
return FALSE;
@@ -271,8 +264,10 @@ static BOOL test_peer_draw_background(freerdp_peer* client)
rfx_context_set_pixel_format(context->rfx_context, colorFormat);
WINPR_ASSERT(bpp <= UINT16_MAX);
if (!rfx_compose_message(context->rfx_context, s, &rect, 1, rgb_data, rect.width,
rect.height, (UINT32)(bpp * rect.width)))
RFX_RECT rrect = { .x = 0, .y = 0, .width = rect->width, .height = rect->height };
if (!rfx_compose_message(context->rfx_context, s, &rrect, 1, rgb_data, rect->width,
rect->height, (UINT32)(bpp * rect->width)))
{
goto out;
}
@@ -289,28 +284,27 @@ static BOOL test_peer_draw_background(freerdp_peer* client)
nsc_context_set_parameters(context->nsc_context, NSC_COLOR_FORMAT, colorFormat);
WINPR_ASSERT(bpp <= UINT16_MAX);
nsc_compose_message(context->nsc_context, s, rgb_data, rect.width, rect.height,
(UINT32)(bpp * rect.width));
nsc_compose_message(context->nsc_context, s, rgb_data, rect->width, rect->height,
(UINT32)(bpp * rect->width));
const UINT32 NSCodecId = freerdp_settings_get_uint32(settings, FreeRDP_NSCodecId);
WINPR_ASSERT(NSCodecId <= UINT16_MAX);
cmd.bmp.codecID = (UINT16)NSCodecId;
cmd.cmdType = CMDTYPE_SET_SURFACE_BITS;
}
cmd.destLeft = 0;
cmd.destTop = 0;
cmd.destRight = rect.width;
cmd.destBottom = rect.height;
cmd.destLeft = rect->x;
cmd.destTop = rect->y;
cmd.destRight = rect->x + rect->width;
cmd.destBottom = rect->y + rect->height;
cmd.bmp.bpp = 32;
cmd.bmp.flags = 0;
cmd.bmp.width = rect.width;
cmd.bmp.height = rect.height;
cmd.bmp.width = rect->width;
cmd.bmp.height = rect->height;
WINPR_ASSERT(Stream_GetPosition(s) <= UINT32_MAX);
cmd.bmp.bitmapDataLength = (UINT32)Stream_GetPosition(s);
cmd.bmp.bitmapData = Stream_Buffer(s);
test_peer_begin_frame(client);
update->SurfaceBits(update->context, &cmd);
test_peer_end_frame(client);
ret = TRUE;
out:
free(rgb_data);
@@ -377,37 +371,24 @@ out_fail:
return FALSE;
}
static void test_peer_draw_icon(freerdp_peer* client, UINT32 x, UINT32 y)
static void test_send_cursor_update(freerdp_peer* client, UINT32 x, UINT32 y)
{
wStream* s = NULL;
RFX_RECT rect;
rdpUpdate* update = NULL;
rdpSettings* settings = NULL;
SURFACE_BITS_COMMAND cmd = { 0 };
testPeerContext* context = NULL;
WINPR_ASSERT(client);
context = (testPeerContext*)client->context;
testPeerContext* context = (testPeerContext*)client->context;
WINPR_ASSERT(context);
update = client->context->update;
WINPR_ASSERT(update);
rdpSettings* settings = client->context->settings;
settings = client->context->settings;
WINPR_ASSERT(settings);
if (freerdp_settings_get_bool(settings, FreeRDP_DumpRemoteFx))
return;
const BOOL RemoteFxCodec = freerdp_settings_get_bool(settings, FreeRDP_RemoteFxCodec);
if (context->image->width < 1 || !context->activated)
return;
rect.x = 0;
rect.y = 0;
rect.width = WINPR_ASSERTING_INT_CAST(UINT16, context->image->width);
rect.height = WINPR_ASSERTING_INT_CAST(UINT16, context->image->height);
RFX_RECT rect = { .x = 0,
.y = 0,
.width = WINPR_ASSERTING_INT_CAST(UINT16, context->image->width),
.height = WINPR_ASSERTING_INT_CAST(UINT16, context->image->height) };
const UINT32 w = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
const UINT32 h = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
@@ -420,9 +401,7 @@ static void test_peer_draw_icon(freerdp_peer* client, UINT32 x, UINT32 y)
if (y + context->image->height > h)
return;
test_peer_begin_frame(client);
const BOOL RemoteFxCodec = freerdp_settings_get_bool(settings, FreeRDP_RemoteFxCodec);
SURFACE_BITS_COMMAND cmd = { 0 };
if (RemoteFxCodec && stream_surface_bits_supported(settings))
{
const UINT32 RemoteFxCodecId =
@@ -439,40 +418,7 @@ static void test_peer_draw_icon(freerdp_peer* client, UINT32 x, UINT32 y)
cmd.cmdType = CMDTYPE_SET_SURFACE_BITS;
}
if (context->icon_x != UINT32_MAX)
{
const UINT32 colorFormat = PIXEL_FORMAT_RGB24;
const UINT32 bpp = FreeRDPGetBytesPerPixel(colorFormat);
s = test_peer_stream_init(context);
if (RemoteFxCodec)
{
rfx_context_set_pixel_format(context->rfx_context, colorFormat);
rfx_compose_message(context->rfx_context, s, &rect, 1, context->bg_data, rect.width,
rect.height, rect.width * bpp);
}
else
{
nsc_context_set_parameters(context->nsc_context, NSC_COLOR_FORMAT, colorFormat);
nsc_compose_message(context->nsc_context, s, context->bg_data, rect.width, rect.height,
rect.width * bpp);
}
cmd.destLeft = context->icon_x;
cmd.destTop = context->icon_y;
cmd.destRight = context->icon_x + rect.width;
cmd.destBottom = context->icon_y + rect.height;
cmd.bmp.bpp = 32;
cmd.bmp.flags = 0;
cmd.bmp.width = rect.width;
cmd.bmp.height = rect.height;
cmd.bmp.bitmapDataLength = (UINT32)Stream_GetPosition(s);
cmd.bmp.bitmapData = Stream_Buffer(s);
WINPR_ASSERT(update->SurfaceBits);
update->SurfaceBits(update->context, &cmd);
}
s = test_peer_stream_init(context);
wStream* s = test_peer_stream_init(context);
{
const UINT32 colorFormat =
@@ -501,10 +447,38 @@ static void test_peer_draw_icon(freerdp_peer* client, UINT32 x, UINT32 y)
cmd.bmp.height = rect.height;
cmd.bmp.bitmapDataLength = (UINT32)Stream_GetPosition(s);
cmd.bmp.bitmapData = Stream_Buffer(s);
rdpUpdate* update = client->context->update;
WINPR_ASSERT(update);
WINPR_ASSERT(update->SurfaceBits);
update->SurfaceBits(update->context, &cmd);
context->icon_x = x;
context->icon_y = y;
}
static void test_peer_draw_icon(freerdp_peer* client, UINT32 x, UINT32 y)
{
WINPR_ASSERT(client);
rdpSettings* settings = client->context->settings;
WINPR_ASSERT(settings);
if (freerdp_settings_get_bool(settings, FreeRDP_DumpRemoteFx))
return;
test_peer_begin_frame(client);
testPeerContext* context = (testPeerContext*)client->context;
if ((context->icon_x != UINT32_MAX) && (context->icon_y != UINT32_MAX))
{
RFX_RECT rect = { .x = WINPR_ASSERTING_INT_CAST(uint16_t, context->icon_x),
.y = WINPR_ASSERTING_INT_CAST(uint16_t, context->icon_y),
.width = WINPR_ASSERTING_INT_CAST(uint16_t, context->image->width),
.height = WINPR_ASSERTING_INT_CAST(uint16_t, context->image->height) };
test_peer_draw_background(client, &rect);
}
test_send_cursor_update(client, x, y);
test_peer_end_frame(client);
}
@@ -826,7 +800,17 @@ static BOOL tf_peer_activate(freerdp_peer* client)
return FALSE;
}
else
test_peer_draw_background(client);
{
const RFX_RECT rect = {
.x = 0,
.y = 0,
.width = (UINT16)freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth),
.height = (UINT16)freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight)
};
test_peer_begin_frame(client);
test_peer_draw_background(client, &rect);
test_peer_end_frame(client);
}
return TRUE;
}
@@ -943,20 +927,56 @@ static BOOL tf_peer_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16
WINPR_ASSERT(input);
WINPR_ASSERT(input->context);
// WLog_DBG(TAG, "Client sent a mouse event (flags:0x%04"PRIX16" pos:%"PRIu16",%"PRIu16")",
// flags, x, y);
WLog_DBG(TAG, "Client sent a mouse event (flags:0x%04" PRIX16 " pos:%" PRIu16 ",%" PRIu16 ")",
flags, x, y);
test_peer_draw_icon(input->context->peer, x + 10, y);
return TRUE;
}
static UINT32 add(UINT32 old, UINT32 max, INT16 diff)
{
INT64 val = old;
val += diff;
if (val > max)
val = val % max;
else if (val < 0)
val = max - val;
return WINPR_ASSERTING_INT_CAST(uint32_t, val);
}
static BOOL tf_peer_rel_mouse_event(rdpInput* input, UINT16 flags, INT16 xDelta, INT16 yDelta)
{
WINPR_UNUSED(flags);
WINPR_ASSERT(input);
WINPR_ASSERT(input->context);
const UINT32 w = freerdp_settings_get_uint32(input->context->settings, FreeRDP_DesktopWidth);
const UINT32 h = freerdp_settings_get_uint32(input->context->settings, FreeRDP_DesktopHeight);
static UINT32 xpos = 0;
static UINT32 ypos = 0;
xpos = add(xpos, w, xDelta);
ypos = add(ypos, h, yDelta);
WLog_DBG(TAG,
"Client sent a relative mouse event (flags:0x%04" PRIX16 " pos:%" PRId16 ",%" PRId16
")",
flags, xDelta, yDelta);
test_peer_draw_icon(input->context->peer, xpos + 10, ypos);
return TRUE;
}
static BOOL tf_peer_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
{
WINPR_UNUSED(flags);
WINPR_ASSERT(input);
WINPR_ASSERT(input->context);
// WLog_DBG(TAG, "Client sent an extended mouse event (flags:0x%04"PRIX16"
// pos:%"PRIu16",%"PRIu16")", flags, x, y);
WLog_DBG(TAG,
"Client sent an extended mouse event (flags:0x%04" PRIX16 " pos:%" PRIu16 ",%" PRIu16
")",
flags, x, y);
test_peer_draw_icon(input->context->peer, x + 10, y);
return TRUE;
}
@@ -1128,6 +1148,8 @@ static DWORD WINAPI test_peer_mainloop(LPVOID arg)
goto fail;
if (!freerdp_settings_set_bool(settings, FreeRDP_RefreshRect, TRUE))
goto fail;
if (!freerdp_settings_set_bool(settings, FreeRDP_HasRelativeMouseEvent, TRUE))
goto fail;
client->PostConnect = tf_peer_post_connect;
client->Activate = tf_peer_activate;
@@ -1140,6 +1162,7 @@ static DWORD WINAPI test_peer_mainloop(LPVOID arg)
input->KeyboardEvent = tf_peer_keyboard_event;
input->UnicodeKeyboardEvent = tf_peer_unicode_keyboard_event;
input->MouseEvent = tf_peer_mouse_event;
input->RelMouseEvent = tf_peer_rel_mouse_event;
input->ExtendedMouseEvent = tf_peer_extended_mouse_event;
update = client->context->update;