mirror of https://github.com/FreeRDP/FreeRDP
shadow: hook X11 input
This commit is contained in:
parent
c865fed299
commit
e9818e95ac
|
@ -26,6 +26,9 @@
|
|||
#include <freerdp/settings.h>
|
||||
#include <freerdp/listener.h>
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/codec/region.h>
|
||||
|
||||
typedef struct rdp_shadow_client rdpShadowClient;
|
||||
typedef struct rdp_shadow_server rdpShadowServer;
|
||||
typedef struct rdp_shadow_screen rdpShadowScreen;
|
||||
|
@ -39,6 +42,7 @@ struct rdp_shadow_client
|
|||
|
||||
HANDLE thread;
|
||||
BOOL activated;
|
||||
HANDLE StopEvent;
|
||||
rdpShadowServer* server;
|
||||
};
|
||||
|
||||
|
@ -46,6 +50,7 @@ struct rdp_shadow_server
|
|||
{
|
||||
void* ext;
|
||||
HANDLE thread;
|
||||
HANDLE StopEvent;
|
||||
rdpShadowScreen* screen;
|
||||
rdpShadowSurface* surface;
|
||||
rdpShadowEncoder* encoder;
|
||||
|
@ -57,6 +62,7 @@ struct rdp_shadow_server
|
|||
|
||||
#define RDP_SHADOW_SUBSYSTEM_COMMON() \
|
||||
rdpShadowServer* server; \
|
||||
HANDLE event; \
|
||||
int monitorCount; \
|
||||
MONITOR_DEF monitors[16]
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
void x11_shadow_input_synchronize_event(x11ShadowSubsystem* subsystem, UINT32 flags)
|
||||
{
|
||||
fprintf(stderr, "Client sent a synchronize event (flags:0x%X)\n", flags);
|
||||
|
||||
}
|
||||
|
||||
void x11_shadow_input_keyboard_event(x11ShadowSubsystem* subsystem, UINT16 flags, UINT16 code)
|
||||
|
@ -65,7 +65,7 @@ void x11_shadow_input_keyboard_event(x11ShadowSubsystem* subsystem, UINT16 flags
|
|||
|
||||
void x11_shadow_input_unicode_keyboard_event(x11ShadowSubsystem* subsystem, UINT16 flags, UINT16 code)
|
||||
{
|
||||
fprintf(stderr, "Client sent a unicode keyboard event (flags:0x%X code:0x%X)\n", flags, code);
|
||||
|
||||
}
|
||||
|
||||
void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, UINT16 x, UINT16 y)
|
||||
|
|
|
@ -191,7 +191,7 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
|
|||
* To see if your X11 server supports shared pixmaps, use:
|
||||
* xdpyinfo -ext MIT-SHM | grep "shared pixmaps"
|
||||
*/
|
||||
subsystem->use_xshm = TRUE;
|
||||
subsystem->use_xshm = FALSE;
|
||||
|
||||
setenv("DISPLAY", ":0", 1); /* Set DISPLAY variable if not already set */
|
||||
|
||||
|
@ -276,6 +276,8 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
|
|||
|
||||
x11_shadow_cursor_init(subsystem);
|
||||
|
||||
subsystem->event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, subsystem->xfds);
|
||||
|
||||
subsystem->monitorCount = 1;
|
||||
subsystem->monitors[0].left = 0;
|
||||
subsystem->monitors[0].top = 0;
|
||||
|
@ -297,6 +299,12 @@ int x11_shadow_subsystem_uninit(x11ShadowSubsystem* subsystem)
|
|||
subsystem->display = NULL;
|
||||
}
|
||||
|
||||
if (subsystem->event)
|
||||
{
|
||||
CloseHandle(subsystem->event);
|
||||
subsystem->event = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,8 +29,6 @@ typedef struct x11_shadow_subsystem x11ShadowSubsystem;
|
|||
#include <winpr/stream.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include <freerdp/codec/rfx.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#ifdef WITH_XSHM
|
||||
|
@ -89,6 +87,15 @@ struct x11_shadow_subsystem
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
int x11_shadow_check_event(x11ShadowSubsystem* subsystem);
|
||||
int x11_shadow_surface_copy(x11ShadowSubsystem* subsystem, int x, int y, int width, int height);
|
||||
|
||||
void x11_shadow_input_synchronize_event(x11ShadowSubsystem* subsystem, UINT32 flags);
|
||||
void x11_shadow_input_keyboard_event(x11ShadowSubsystem* subsystem, UINT16 flags, UINT16 code);
|
||||
void x11_shadow_input_unicode_keyboard_event(x11ShadowSubsystem* subsystem, UINT16 flags, UINT16 code);
|
||||
void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, UINT16 x, UINT16 y);
|
||||
void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, UINT16 x, UINT16 y);
|
||||
|
||||
rdpShadowSubsystem* x11_shadow_subsystem_new(rdpShadowServer* server);
|
||||
void x11_shadow_subsystem_free(rdpShadowSubsystem* subsystem);
|
||||
|
||||
|
|
|
@ -24,9 +24,13 @@
|
|||
#include <winpr/synch.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#include "../shadow_surface.h"
|
||||
|
||||
#include "x11_shadow.h"
|
||||
|
||||
XImage* x11_shadow_snapshot(x11ShadowSubsystem* subsystem, int x, int y, int width, int height)
|
||||
|
@ -35,12 +39,14 @@ XImage* x11_shadow_snapshot(x11ShadowSubsystem* subsystem, int x, int y, int wid
|
|||
|
||||
if (subsystem->use_xshm)
|
||||
{
|
||||
XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap, subsystem->xdamage_gc, x, y, width, height, x, y);
|
||||
XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap,
|
||||
subsystem->xdamage_gc, x, y, width, height, x, y);
|
||||
image = subsystem->fb_image;
|
||||
}
|
||||
else
|
||||
{
|
||||
image = XGetImage(subsystem->display, subsystem->root_window, x, y, width, height, AllPlanes, ZPixmap);
|
||||
image = XGetImage(subsystem->display, subsystem->root_window,
|
||||
x, y, width, height, AllPlanes, ZPixmap);
|
||||
}
|
||||
|
||||
return image;
|
||||
|
@ -61,100 +67,76 @@ void x11_shadow_xdamage_subtract_region(x11ShadowSubsystem* subsystem, int x, in
|
|||
#endif
|
||||
}
|
||||
|
||||
int x11_shadow_update_encode(x11ShadowSubsystem* subsystem, int x, int y, int width, int height)
|
||||
int x11_shadow_surface_copy(x11ShadowSubsystem* subsystem, int x, int y, int width, int height)
|
||||
{
|
||||
BYTE* data;
|
||||
XImage* image;
|
||||
RFX_RECT rect;
|
||||
rdpShadowServer* server;
|
||||
rdpShadowSurface* surface;
|
||||
RECTANGLE_16 invalidRect;
|
||||
|
||||
server = subsystem->server;
|
||||
surface = server->surface;
|
||||
|
||||
printf("x11_shadow_surface_copy: x: %d y: %d width: %d height: %d\n",
|
||||
x, y, width, height);
|
||||
|
||||
if (subsystem->use_xshm)
|
||||
{
|
||||
/**
|
||||
* Passing an offset source rectangle to rfx_compose_message()
|
||||
* leads to protocol errors, so offset the data pointer instead.
|
||||
*/
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
|
||||
image = x11_shadow_snapshot(subsystem, x, y, width, height);
|
||||
|
||||
data = (BYTE*) image->data;
|
||||
data = &data[(y * image->bytes_per_line) + (x * image->bits_per_pixel / 8)];
|
||||
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
|
||||
surface->scanline, x, y, width, height,
|
||||
(BYTE*) image->data, PIXEL_FORMAT_XRGB32,
|
||||
image->bytes_per_line, x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
|
||||
image = x11_shadow_snapshot(subsystem, x, y, width, height);
|
||||
|
||||
data = (BYTE*) image->data;
|
||||
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
|
||||
surface->scanline, x, y, width, height,
|
||||
(BYTE*) image->data, PIXEL_FORMAT_XRGB32,
|
||||
image->bytes_per_line, x, y);
|
||||
|
||||
XDestroyImage(image);
|
||||
}
|
||||
|
||||
return 0;
|
||||
invalidRect.left = x;
|
||||
invalidRect.top = y;
|
||||
invalidRect.right = width;
|
||||
invalidRect.bottom = height;
|
||||
|
||||
region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void* x11_shadow_update_thread(x11ShadowSubsystem* subsystem)
|
||||
int x11_shadow_check_event(x11ShadowSubsystem* subsystem)
|
||||
{
|
||||
HANDLE event;
|
||||
XEvent xevent;
|
||||
DWORD beg, end;
|
||||
DWORD diff, rate;
|
||||
XFixesCursorImage* ci;
|
||||
int x, y, width, height;
|
||||
XDamageNotifyEvent* notify;
|
||||
|
||||
rate = 1000 / 10;
|
||||
|
||||
event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, subsystem->xfds);
|
||||
|
||||
while (WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0)
|
||||
while (XPending(subsystem->display) > 0)
|
||||
{
|
||||
beg = GetTickCount();
|
||||
ZeroMemory(&xevent, sizeof(xevent));
|
||||
XNextEvent(subsystem->display, &xevent);
|
||||
|
||||
while (XPending(subsystem->display) > 0)
|
||||
if (xevent.type == subsystem->xdamage_notify_event)
|
||||
{
|
||||
ZeroMemory(&xevent, sizeof(xevent));
|
||||
XNextEvent(subsystem->display, &xevent);
|
||||
notify = (XDamageNotifyEvent*) &xevent;
|
||||
|
||||
if (xevent.type == subsystem->xdamage_notify_event)
|
||||
x = notify->area.x;
|
||||
y = notify->area.y;
|
||||
width = notify->area.width;
|
||||
height = notify->area.height;
|
||||
|
||||
if (x11_shadow_surface_copy(subsystem, x, y, width, height) > 0)
|
||||
{
|
||||
notify = (XDamageNotifyEvent*) &xevent;
|
||||
|
||||
x = notify->area.x;
|
||||
y = notify->area.y;
|
||||
width = notify->area.width;
|
||||
height = notify->area.height;
|
||||
|
||||
if (x11_shadow_update_encode(subsystem, x, y, width, height) >= 0)
|
||||
{
|
||||
x11_shadow_xdamage_subtract_region(subsystem, x, y, width, height);
|
||||
|
||||
/* send update */
|
||||
}
|
||||
x11_shadow_xdamage_subtract_region(subsystem, x, y, width, height);
|
||||
}
|
||||
#ifdef WITH_XFIXES
|
||||
else if (xevent.type == subsystem->xfixes_notify_event)
|
||||
{
|
||||
ci = XFixesGetCursorImage(subsystem->display);
|
||||
XFree(ci);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
end = GetTickCount();
|
||||
diff = end - beg;
|
||||
|
||||
if (diff < rate)
|
||||
Sleep(rate - diff);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -32,9 +32,11 @@ void* shadow_server_thread(rdpShadowServer* server)
|
|||
DWORD status;
|
||||
DWORD nCount;
|
||||
HANDLE events[32];
|
||||
HANDLE StopEvent;
|
||||
freerdp_listener* listener;
|
||||
|
||||
listener = server->listener;
|
||||
StopEvent = server->StopEvent;
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
@ -46,8 +48,15 @@ void* shadow_server_thread(rdpShadowServer* server)
|
|||
break;
|
||||
}
|
||||
|
||||
events[nCount++] = server->StopEvent;
|
||||
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||
|
||||
if (WaitForSingleObject(server->StopEvent, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!listener->CheckFileDescriptor(listener))
|
||||
{
|
||||
fprintf(stderr, "Failed to check FreeRDP file descriptor\n");
|
||||
|
@ -81,9 +90,10 @@ int shadow_server_stop(rdpShadowServer* server)
|
|||
{
|
||||
if (server->thread)
|
||||
{
|
||||
TerminateThread(server->thread, 0);
|
||||
SetEvent(server->StopEvent);
|
||||
WaitForSingleObject(server->thread, INFINITE);
|
||||
CloseHandle(server->thread);
|
||||
server->thread = NULL;
|
||||
|
||||
server->listener->Close(server->listener);
|
||||
}
|
||||
|
@ -91,11 +101,6 @@ int shadow_server_stop(rdpShadowServer* server)
|
|||
return 0;
|
||||
}
|
||||
|
||||
HANDLE shadow_server_get_thread(rdpShadowServer* server)
|
||||
{
|
||||
return server->thread;
|
||||
}
|
||||
|
||||
rdpShadowServer* shadow_server_new(int argc, char** argv)
|
||||
{
|
||||
rdpShadowServer* server;
|
||||
|
@ -107,6 +112,8 @@ rdpShadowServer* shadow_server_new(int argc, char** argv)
|
|||
|
||||
server->port = 3389;
|
||||
|
||||
server->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
server->listener = freerdp_listener_new();
|
||||
|
||||
if (!server->listener)
|
||||
|
@ -138,6 +145,8 @@ void shadow_server_free(rdpShadowServer* server)
|
|||
if (!server)
|
||||
return;
|
||||
|
||||
shadow_server_stop(server);
|
||||
|
||||
freerdp_listener_free(server->listener);
|
||||
|
||||
shadow_encoder_free(server->encoder);
|
||||
|
@ -149,7 +158,6 @@ void shadow_server_free(rdpShadowServer* server)
|
|||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
HANDLE thread;
|
||||
DWORD dwExitCode;
|
||||
rdpShadowServer* server;
|
||||
|
||||
|
@ -160,11 +168,9 @@ int main(int argc, char* argv[])
|
|||
|
||||
shadow_server_start(server);
|
||||
|
||||
thread = shadow_server_get_thread(server);
|
||||
WaitForSingleObject(server->thread, INFINITE);
|
||||
|
||||
WaitForSingleObject(thread, INFINITE);
|
||||
|
||||
GetExitCodeThread(thread, &dwExitCode);
|
||||
GetExitCodeThread(server->thread, &dwExitCode);
|
||||
|
||||
shadow_server_free(server);
|
||||
|
||||
|
|
|
@ -36,11 +36,13 @@ void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
|
|||
|
||||
server = (rdpShadowServer*) peer->ContextExtra;
|
||||
client->server = server;
|
||||
|
||||
client->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
}
|
||||
|
||||
void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client)
|
||||
{
|
||||
|
||||
CloseHandle(client->StopEvent);
|
||||
}
|
||||
|
||||
BOOL shadow_client_capabilities(freerdp_peer* peer)
|
||||
|
@ -54,24 +56,7 @@ BOOL shadow_client_post_connect(freerdp_peer* peer)
|
|||
|
||||
client = (rdpShadowClient*) peer->context;
|
||||
|
||||
fprintf(stderr, "Client %s is activated", peer->hostname);
|
||||
|
||||
if (peer->settings->AutoLogonEnabled)
|
||||
{
|
||||
fprintf(stderr, " and wants to login automatically as %s\\%s",
|
||||
peer->settings->Domain ? peer->settings->Domain : "",
|
||||
peer->settings->Username);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
fprintf(stderr, "Client requested desktop: %dx%d@%d\n",
|
||||
peer->settings->DesktopWidth, peer->settings->DesktopHeight, peer->settings->ColorDepth);
|
||||
|
||||
if (!peer->settings->RemoteFxCodec)
|
||||
{
|
||||
fprintf(stderr, "Client does not support RemoteFX\n");
|
||||
return FALSE;
|
||||
}
|
||||
fprintf(stderr, "Client from %s is activated\n", peer->hostname);
|
||||
|
||||
peer->settings->DesktopWidth = client->server->screen->width;
|
||||
peer->settings->DesktopHeight = client->server->screen->height;
|
||||
|
@ -97,6 +82,12 @@ int shadow_client_send_surface_bits(rdpShadowClient* client)
|
|||
{
|
||||
int i;
|
||||
wStream* s;
|
||||
int nXSrc;
|
||||
int nYSrc;
|
||||
int nWidth;
|
||||
int nHeight;
|
||||
int nSrcStep;
|
||||
BYTE* pSrcData;
|
||||
int numMessages;
|
||||
rdpUpdate* update;
|
||||
rdpContext* context;
|
||||
|
@ -104,14 +95,9 @@ int shadow_client_send_surface_bits(rdpShadowClient* client)
|
|||
rdpShadowServer* server;
|
||||
rdpShadowSurface* surface;
|
||||
rdpShadowEncoder* encoder;
|
||||
RECTANGLE_16 surfaceRect;
|
||||
SURFACE_BITS_COMMAND cmd;
|
||||
|
||||
BYTE* pSrcData;
|
||||
int nSrcStep;
|
||||
int nXSrc;
|
||||
int nYSrc;
|
||||
int nWidth;
|
||||
int nHeight;
|
||||
const RECTANGLE_16* extents;
|
||||
|
||||
context = (rdpContext*) client;
|
||||
update = context->update;
|
||||
|
@ -121,12 +107,24 @@ int shadow_client_send_surface_bits(rdpShadowClient* client)
|
|||
encoder = server->encoder;
|
||||
surface = server->surface;
|
||||
|
||||
surfaceRect.left = 0;
|
||||
surfaceRect.top = 0;
|
||||
surfaceRect.right = surface->width;
|
||||
surfaceRect.bottom = surface->height;
|
||||
|
||||
region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect);
|
||||
|
||||
if (region16_is_empty(&(surface->invalidRegion)))
|
||||
return 1;
|
||||
|
||||
extents = region16_extents(&(surface->invalidRegion));
|
||||
|
||||
nXSrc = extents->left;
|
||||
nYSrc = extents->top;
|
||||
nWidth = extents->right - extents->left;
|
||||
nHeight = extents->bottom - extents->top;
|
||||
pSrcData = surface->data;
|
||||
nSrcStep = surface->scanline;
|
||||
nWidth = surface->width;
|
||||
nHeight = surface->height;
|
||||
nXSrc = 0;
|
||||
nYSrc = 0;
|
||||
|
||||
if (settings->RemoteFxCodec)
|
||||
{
|
||||
|
@ -168,8 +166,6 @@ int shadow_client_send_surface_bits(rdpShadowClient* client)
|
|||
}
|
||||
|
||||
free(messages);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else if (settings->NSCodec)
|
||||
{
|
||||
|
@ -205,10 +201,10 @@ int shadow_client_send_surface_bits(rdpShadowClient* client)
|
|||
}
|
||||
|
||||
free(messages);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
region16_clear(&(surface->invalidRegion));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -263,9 +259,18 @@ void* shadow_client_thread(rdpShadowClient* client)
|
|||
DWORD status;
|
||||
DWORD nCount;
|
||||
HANDLE events[32];
|
||||
HANDLE StopEvent;
|
||||
HANDLE ClientEvent;
|
||||
HANDLE SubsystemEvent;
|
||||
freerdp_peer* peer;
|
||||
rdpSettings* settings;
|
||||
rdpShadowServer* server;
|
||||
rdpShadowSurface* surface;
|
||||
rdpShadowSubsystem* subsystem;
|
||||
|
||||
server = client->server;
|
||||
surface = server->surface;
|
||||
subsystem = server->subsystem;
|
||||
|
||||
peer = ((rdpContext*) client)->peer;
|
||||
settings = peer->settings;
|
||||
|
@ -287,14 +292,23 @@ void* shadow_client_thread(rdpShadowClient* client)
|
|||
|
||||
peer->Initialize(peer);
|
||||
|
||||
StopEvent = client->StopEvent;
|
||||
ClientEvent = peer->GetEventHandle(peer);
|
||||
SubsystemEvent = subsystem->event;
|
||||
|
||||
while (1)
|
||||
{
|
||||
nCount = 0;
|
||||
events[nCount++] = StopEvent;
|
||||
events[nCount++] = ClientEvent;
|
||||
events[nCount++] = SubsystemEvent;
|
||||
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, 100);
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||
|
||||
if (WaitForSingleObject(client->StopEvent, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (WaitForSingleObject(ClientEvent, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
|
@ -305,8 +319,15 @@ void* shadow_client_thread(rdpShadowClient* client)
|
|||
}
|
||||
}
|
||||
|
||||
if (client->activated)
|
||||
shadow_client_send_surface_bits(client);
|
||||
if (WaitForSingleObject(SubsystemEvent, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
x11_shadow_check_event((x11ShadowSubsystem*) subsystem);
|
||||
|
||||
if (client->activated)
|
||||
{
|
||||
shadow_client_send_surface_bits(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
peer->Disconnect(peer);
|
||||
|
@ -321,7 +342,6 @@ void* shadow_client_thread(rdpShadowClient* client)
|
|||
|
||||
void shadow_client_accepted(freerdp_listener* listener, freerdp_peer* peer)
|
||||
{
|
||||
HANDLE thread;
|
||||
rdpShadowClient* client;
|
||||
rdpShadowServer* server;
|
||||
|
||||
|
@ -335,6 +355,6 @@ void shadow_client_accepted(freerdp_listener* listener, freerdp_peer* peer)
|
|||
|
||||
client = (rdpShadowClient*) peer->context;
|
||||
|
||||
thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
|
||||
client->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
|
||||
shadow_client_thread, client, 0, NULL);
|
||||
}
|
||||
|
|
|
@ -24,27 +24,42 @@
|
|||
|
||||
void shadow_input_synchronize_event(rdpInput* input, UINT32 flags)
|
||||
{
|
||||
rdpShadowClient* client = (rdpShadowClient*) input->context;
|
||||
rdpShadowSubsystem* subsystem = client->server->subsystem;
|
||||
|
||||
x11_shadow_input_synchronize_event((x11ShadowSubsystem*) subsystem, flags);
|
||||
}
|
||||
|
||||
void shadow_input_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
||||
{
|
||||
rdpShadowClient* client = (rdpShadowClient*) input->context;
|
||||
rdpShadowSubsystem* subsystem = client->server->subsystem;
|
||||
|
||||
x11_shadow_input_keyboard_event((x11ShadowSubsystem*) subsystem, flags, code);
|
||||
}
|
||||
|
||||
void shadow_input_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
||||
{
|
||||
rdpShadowClient* client = (rdpShadowClient*) input->context;
|
||||
rdpShadowSubsystem* subsystem = client->server->subsystem;
|
||||
|
||||
x11_shadow_input_unicode_keyboard_event((x11ShadowSubsystem*) subsystem, flags, code);
|
||||
}
|
||||
|
||||
void shadow_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
||||
{
|
||||
rdpShadowClient* client = (rdpShadowClient*) input->context;
|
||||
rdpShadowSubsystem* subsystem = client->server->subsystem;
|
||||
|
||||
x11_shadow_input_mouse_event((x11ShadowSubsystem*) subsystem, flags, x, y);
|
||||
}
|
||||
|
||||
void shadow_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
||||
{
|
||||
rdpShadowClient* client = (rdpShadowClient*) input->context;
|
||||
rdpShadowSubsystem* subsystem = client->server->subsystem;
|
||||
|
||||
x11_shadow_input_extended_mouse_event((x11ShadowSubsystem*) subsystem, flags, x, y);
|
||||
}
|
||||
|
||||
void shadow_input_register_callbacks(rdpInput* input)
|
||||
|
|
|
@ -56,5 +56,13 @@ void shadow_screen_free(rdpShadowScreen* screen)
|
|||
{
|
||||
if (!screen)
|
||||
return;
|
||||
|
||||
if (screen->primary)
|
||||
{
|
||||
shadow_surface_free(screen->primary);
|
||||
screen->primary = NULL;
|
||||
}
|
||||
|
||||
free(screen);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "shadow.h"
|
||||
|
||||
#include "shadow_surface.h"
|
||||
|
||||
rdpShadowSurface* shadow_surface_new(rdpShadowServer* server, int width, int height)
|
||||
|
@ -44,6 +46,8 @@ rdpShadowSurface* shadow_surface_new(rdpShadowServer* server, int width, int hei
|
|||
|
||||
ZeroMemory(surface->data, surface->scanline * surface->height);
|
||||
|
||||
region16_init(&(surface->invalidRegion));
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
|
@ -51,4 +55,10 @@ void shadow_surface_free(rdpShadowSurface* surface)
|
|||
{
|
||||
if (!surface)
|
||||
return;
|
||||
|
||||
free(surface->data);
|
||||
|
||||
region16_uninit(&(surface->invalidRegion));
|
||||
|
||||
free(surface);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@ struct rdp_shadow_surface
|
|||
int height;
|
||||
int scanline;
|
||||
BYTE* data;
|
||||
|
||||
REGION16 invalidRegion;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
Loading…
Reference in New Issue