From 34756850e48391ca34d6168d9c22eb5eed811ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 10 Sep 2014 14:58:14 -0400 Subject: [PATCH 01/21] shadow: add ability to select monitor to share --- include/freerdp/server/shadow.h | 1 + server/shadow/X11/x11_shadow.c | 29 +++++++++++++++++--- server/shadow/shadow_client.c | 12 ++++----- server/shadow/shadow_screen.c | 2 +- server/shadow/shadow_server.c | 47 ++++++++++++++++++++++++--------- 5 files changed, 68 insertions(+), 23 deletions(-) diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h index 0620cf626..159ca02ab 100644 --- a/include/freerdp/server/shadow.h +++ b/include/freerdp/server/shadow.h @@ -111,6 +111,7 @@ struct rdp_shadow_server #define RDP_SHADOW_SUBSYSTEM_COMMON() \ HANDLE event; \ int monitorCount; \ + int selectedMonitor; \ MONITOR_DEF monitors[16]; \ MONITOR_DEF virtualScreen; \ HANDLE updateEvent; \ diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index ffd068e60..717181f47 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -88,6 +88,11 @@ void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, U #ifdef WITH_XTEST int button = 0; BOOL down = FALSE; + rdpShadowServer* server; + rdpShadowSurface* surface; + + server = subsystem->server; + surface = server->surface; XTestGrabControl(subsystem->display, True); @@ -105,6 +110,9 @@ void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, U } else { + x += surface->x; + y += surface->y; + if (flags & PTR_FLAGS_MOVE) XTestFakeMotionEvent(subsystem->display, 0, x, y, 0); @@ -131,6 +139,14 @@ void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16 #ifdef WITH_XTEST int button = 0; BOOL down = FALSE; + rdpShadowServer* server; + rdpShadowSurface* surface; + + server = subsystem->server; + surface = server->surface; + + x += surface->x; + y += surface->y; XTestGrabControl(subsystem->display, True); XTestFakeMotionEvent(subsystem->display, 0, x, y, CurrentTime); @@ -201,6 +217,11 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) surface = server->surface; screen = server->screen; + count = ArrayList_Count(server->clients); + + if (count < 1) + return 1; + if (subsystem->use_xshm) { XLockDisplay(subsystem->display); @@ -215,7 +236,7 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) image = subsystem->fb_image; status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height, - (BYTE*) image->data, image->bytes_per_line, &invalidRect); + (BYTE*) &(image->data[surface->width * 4]), image->bytes_per_line, &invalidRect); if (status > 0) { @@ -251,7 +272,7 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) XLockDisplay(subsystem->display); image = XGetImage(subsystem->display, subsystem->root_window, - 0, 0, subsystem->width, subsystem->height, AllPlanes, ZPixmap); + surface->x, surface->y, surface->width, surface->height, AllPlanes, ZPixmap); XUnlockDisplay(subsystem->display); @@ -266,7 +287,7 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) height = invalidRect.bottom - invalidRect.top; freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, - surface->scanline, x - surface->x, y - surface->y, width, height, + surface->scanline, x, y, width, height, (BYTE*) image->data, PIXEL_FORMAT_XRGB32, image->bytes_per_line, x, y); @@ -768,7 +789,7 @@ x11ShadowSubsystem* x11_shadow_subsystem_new(rdpShadowServer* server) subsystem->ExtendedMouseEvent = (pfnShadowExtendedMouseEvent) x11_shadow_input_extended_mouse_event; subsystem->composite = FALSE; - subsystem->use_xshm = TRUE; + subsystem->use_xshm = FALSE; /* temporarily disabled */ subsystem->use_xfixes = TRUE; subsystem->use_xdamage = FALSE; subsystem->use_xinerama = TRUE; diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index 5098a35ea..d7afb84d7 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -550,10 +550,10 @@ int shadow_client_send_surface_update(rdpShadowClient* client) LeaveCriticalSection(&(client->lock)); - surfaceRect.left = surface->x; - surfaceRect.top = surface->y; - surfaceRect.right = surface->x + surface->width; - surfaceRect.bottom = surface->y + surface->height; + surfaceRect.left = 0; + surfaceRect.top = 0; + surfaceRect.right = surface->width; + surfaceRect.bottom = surface->height; region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect); @@ -565,8 +565,8 @@ int shadow_client_send_surface_update(rdpShadowClient* client) extents = region16_extents(&invalidRegion); - nXSrc = extents->left - surface->x; - nYSrc = extents->top - surface->y; + nXSrc = extents->left - 0; + nYSrc = extents->top - 0; nWidth = extents->right - extents->left; nHeight = extents->bottom - extents->top; diff --git a/server/shadow/shadow_screen.c b/server/shadow/shadow_screen.c index 0b4c87f93..3182b642c 100644 --- a/server/shadow/shadow_screen.c +++ b/server/shadow/shadow_screen.c @@ -45,7 +45,7 @@ rdpShadowScreen* shadow_screen_new(rdpShadowServer* server) region16_init(&(screen->invalidRegion)); - primary = &(subsystem->monitors[0]); + primary = &(subsystem->monitors[subsystem->selectedMonitor]); x = primary->left; y = primary->top; diff --git a/server/shadow/shadow_server.c b/server/shadow/shadow_server.c index c990d1fcf..a40837248 100644 --- a/server/shadow/shadow_server.c +++ b/server/shadow/shadow_server.c @@ -213,16 +213,27 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a if (arg && (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)) { + int index; + rdpShadowSubsystem* subsystem = server->subsystem; + if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) { /* Select monitors */ + + index = atoi(arg->Value); + + if (index < 0) + index = 0; + + if (index >= subsystem->monitorCount) + index = 0; + + subsystem->selectedMonitor = index; } else { - int index; int width, height; MONITOR_DEF* monitor; - rdpShadowSubsystem* subsystem = server->subsystem; /* List monitors */ @@ -343,6 +354,16 @@ int shadow_server_start(rdpShadowServer* server) signal(SIGPIPE, SIG_IGN); #endif + server->screen = shadow_screen_new(server); + + if (!server->screen) + return -1; + + server->capture = shadow_capture_new(server); + + if (!server->capture) + return -1; + if (!server->ipcSocket) status = server->listener->Open(server->listener, NULL, (UINT16) server->port); else @@ -369,6 +390,18 @@ int shadow_server_stop(rdpShadowServer* server) server->listener->Close(server->listener); } + if (server->screen) + { + shadow_screen_free(server->screen); + server->screen = NULL; + } + + if (server->capture) + { + shadow_capture_free(server->capture); + server->capture = NULL; + } + return 0; } @@ -476,16 +509,6 @@ int shadow_server_init(rdpShadowServer* server) fprintf(stderr, "subsystem init failure: %d\n", status); } - server->screen = shadow_screen_new(server); - - if (!server->screen) - return -1; - - server->capture = shadow_capture_new(server); - - if (!server->capture) - return -1; - return 1; } From e1e8da94901b33feae6425ed4438f8328ef8818b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 10 Sep 2014 16:27:24 -0400 Subject: [PATCH 02/21] shadow: add ability to share rectangle within monitor --- include/freerdp/codec/region.h | 6 ++++ include/freerdp/server/shadow.h | 4 ++- libfreerdp/codec/region.c | 5 ++++ server/shadow/X11/x11_shadow.c | 18 ++++++++++-- server/shadow/shadow_client.c | 40 ++++++++++++++++++++++---- server/shadow/shadow_server.c | 51 +++++++++++++++++++++++++++++++++ 6 files changed, 115 insertions(+), 9 deletions(-) diff --git a/include/freerdp/codec/region.h b/include/freerdp/codec/region.h index f6e3b01fd..44bfb2558 100644 --- a/include/freerdp/codec/region.h +++ b/include/freerdp/codec/region.h @@ -77,6 +77,12 @@ FREERDP_API const RECTANGLE_16 *region16_rects(const REGION16 *region, int *nbRe /** @return the extents rectangle of this region */ FREERDP_API const RECTANGLE_16 *region16_extents(const REGION16 *region); +/** returns if the rectangle is empty + * @param rect + * @return if the rectangle is empty + */ +FREERDP_API BOOL rectangle_is_empty(const RECTANGLE_16 *rect); + /** returns if the region is empty * @param region * @return if the region is empty diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h index 159ca02ab..929e6fa5f 100644 --- a/include/freerdp/server/shadow.h +++ b/include/freerdp/server/shadow.h @@ -56,7 +56,7 @@ typedef int (*pfnShadowSubsystemStop)(rdpShadowSubsystem* subsystem); typedef void (*pfnShadowSubsystemFree)(rdpShadowSubsystem* subsystem); typedef int (*pfnShadowSurfaceCopy)(rdpShadowSubsystem* subsystem); -typedef int (*pfnShadowSurfaceUpdate)(rdpShadowSubsystem* subsystem, REGION16* region); +typedef int (*pfnShadowSurfaceUpdate)(rdpShadowSubsystem* subsystem, REGION16* subRect); typedef int (*pfnShadowSynchronizeEvent)(rdpShadowSubsystem* subsystem, UINT32 flags); typedef int (*pfnShadowKeyboardEvent)(rdpShadowSubsystem* subsystem, UINT16 flags, UINT16 code); @@ -99,6 +99,8 @@ struct rdp_shadow_server DWORD port; BOOL mayView; BOOL mayInteract; + BOOL shareSubRect; + RECTANGLE_16 subRect; char* ipcSocket; char* ConfigPath; char* CertificateFile; diff --git a/libfreerdp/codec/region.c b/libfreerdp/codec/region.c index b2afb0de5..2c01d265e 100644 --- a/libfreerdp/codec/region.c +++ b/libfreerdp/codec/region.c @@ -128,6 +128,11 @@ static RECTANGLE_16 *region16_extents_noconst(REGION16 *region) return ®ion->extents; } +BOOL rectangle_is_empty(const RECTANGLE_16 *rect) +{ + return (rect->left + rect->top + rect->right + rect->bottom) ? TRUE : FALSE; +} + BOOL region16_is_empty(const REGION16 *region) { assert(region); diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index 717181f47..9f3229f00 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -94,6 +94,15 @@ void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, U server = subsystem->server; surface = server->surface; + x += surface->x; + y += surface->y; + + if (server->shareSubRect) + { + x += server->subRect.left; + y += server->subRect.top; + } + XTestGrabControl(subsystem->display, True); if (flags & PTR_FLAGS_WHEEL) @@ -110,9 +119,6 @@ void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, U } else { - x += surface->x; - y += surface->y; - if (flags & PTR_FLAGS_MOVE) XTestFakeMotionEvent(subsystem->display, 0, x, y, 0); @@ -148,6 +154,12 @@ void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16 x += surface->x; y += surface->y; + if (server->shareSubRect) + { + x += server->subRect.left; + y += server->subRect.top; + } + XTestGrabControl(subsystem->display, True); XTestFakeMotionEvent(subsystem->display, 0, x, y, CurrentTime); diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index d7afb84d7..a0cbdfe4d 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -110,13 +110,26 @@ BOOL shadow_client_post_connect(freerdp_peer* peer) rdpSettings* settings; rdpShadowClient* client; rdpShadowSurface* lobby; + rdpShadowServer* server; RECTANGLE_16 invalidRect; client = (rdpShadowClient*) peer->context; settings = peer->settings; + server = client->server; - settings->DesktopWidth = client->server->screen->width; - settings->DesktopHeight = client->server->screen->height; + if (!server->shareSubRect) + { + width = server->screen->width; + height = server->screen->height; + } + else + { + width = server->subRect.right - server->subRect.left; + height = server->subRect.bottom - server->subRect.top; + } + + settings->DesktopWidth = width; + settings->DesktopHeight = height; if (settings->ColorDepth == 24) settings->ColorDepth = 16; /* disable 24bpp */ @@ -128,9 +141,6 @@ BOOL shadow_client_post_connect(freerdp_peer* peer) shadow_client_channels_post_connect(client); - width = settings->DesktopWidth; - height = settings->DesktopHeight; - invalidRect.left = 0; invalidRect.top = 0; invalidRect.right = width; @@ -224,6 +234,21 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s pSrcData = surface->data; nSrcStep = surface->scanline; + if (server->shareSubRect) + { + int subX, subY; + int subWidth, subHeight; + + subX = server->subRect.left; + subY = server->subRect.top; + subWidth = server->subRect.right - server->subRect.left; + subHeight = server->subRect.bottom - server->subRect.top; + + nXSrc -= subX; + nYSrc -= subY; + pSrcData = &pSrcData[(subY * nSrcStep) + (subX * 4)]; + } + if (encoder->frameAck) { frameId = (UINT32) shadow_encoder_create_frame_id(encoder); @@ -557,6 +582,11 @@ int shadow_client_send_surface_update(rdpShadowClient* client) region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect); + if (server->shareSubRect) + { + region16_intersect_rect(&invalidRegion, &invalidRegion, &(server->subRect)); + } + if (region16_is_empty(&invalidRegion)) { region16_uninit(&invalidRegion); diff --git a/server/shadow/shadow_server.c b/server/shadow/shadow_server.c index a40837248..84d61adab 100644 --- a/server/shadow/shadow_server.c +++ b/server/shadow/shadow_server.c @@ -65,6 +65,7 @@ static COMMAND_LINE_ARGUMENT_A shadow_args[] = { "port", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Server port" }, { "ipc-socket", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Server IPC socket" }, { "monitors", COMMAND_LINE_VALUE_OPTIONAL, "<0,1,2...>", NULL, NULL, -1, NULL, "Select or list monitors" }, + { "rect", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Select rectangle within monitor to share" }, { "may-view", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Clients may view without prompt" }, { "may-interact", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Clients may interact without prompt" }, { "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, NULL, NULL, NULL, -1, NULL, "Print version" }, @@ -200,6 +201,56 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a { server->mayInteract = arg->Value ? TRUE : FALSE; } + CommandLineSwitchCase(arg, "rect") + { + char* p; + char* tok[4]; + int x, y, w, h; + char* str = _strdup(arg->Value); + + if (!str) + return -1; + + tok[0] = p = str; + + p = strchr(p + 1, ','); + + if (!p) + return -1; + + *p++ = '\0'; + tok[1] = p; + + p = strchr(p + 1, ','); + + if (!p) + return -1; + + *p++ = '\0'; + tok[2] = p; + + p = strchr(p + 1, ','); + + if (!p) + return -1; + + *p++ = '\0'; + tok[3] = p; + + x = atoi(tok[0]); + y = atoi(tok[1]); + w = atoi(tok[2]); + h = atoi(tok[3]); + + if ((x < 0) || (y < 0) || (w < 1) || (h < 1)) + return -1; + + server->subRect.left = x; + server->subRect.top = y; + server->subRect.right = x + w; + server->subRect.bottom = y + h; + server->shareSubRect = TRUE; + } CommandLineSwitchDefault(arg) { From f90f859f491b55a4d27059a80ccf090b736bd11b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 10 Sep 2014 19:04:28 -0400 Subject: [PATCH 03/21] shadow: add X11 cursor monitoring --- server/shadow/X11/x11_shadow.c | 98 ++++++++++++++++++++++++++++++++-- server/shadow/X11/x11_shadow.h | 11 +++- 2 files changed, 104 insertions(+), 5 deletions(-) diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index 9f3229f00..df62b98ff 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -178,6 +178,76 @@ void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16 #endif } +int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage) +{ + int x, y; + + if (getImage) + { +#ifdef WITH_XFIXES + XFixesCursorImage* ci; + + ci = XFixesGetCursorImage(subsystem->display); + + x = ci->x; + y = ci->y; + + if (ci->width > subsystem->cursorMaxWidth) + return -1; + + if (ci->height > subsystem->cursorMaxHeight) + return -1; + + subsystem->cursorWidth = ci->width; + subsystem->cursorHeight = ci->height; + + subsystem->cursorId = ci->cursor_serial; + + CopyMemory(subsystem->cursorPixels, ci->pixels, ci->width * ci->height * 4); + + XFree(ci); +#endif + } + else + { + UINT32 mask; + int win_x, win_y; + int root_x, root_y; + Window root, child; + + if (!XQueryPointer(subsystem->display, subsystem->root_window, + &root, &child, &root_x, &root_y, &win_x, &win_y, &mask)) + { + return -1; + } + + x = root_x; + y = root_y; + } + + subsystem->cursorX = x; + subsystem->cursorY = y; + + return 1; +} + +int x11_shadow_handle_xevent(x11ShadowSubsystem* subsystem, XEvent* xevent) +{ + if (xevent->type == MotionNotify) + { + + } + +#ifdef WITH_XFIXES + if (xevent->type == subsystem->xfixes_cursor_notify_event) + { + x11_shadow_query_cursor(subsystem, TRUE); + } +#endif + + return 1; +} + void x11_shadow_validate_region(x11ShadowSubsystem* subsystem, int x, int y, int width, int height) { XRectangle region; @@ -329,6 +399,7 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem) { int fps; + XEvent xevent; DWORD status; DWORD nCount; UINT64 cTime; @@ -360,8 +431,15 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem) break; } + if (WaitForSingleObject(subsystem->event, 0) == WAIT_OBJECT_0) + { + XNextEvent(subsystem->display, &xevent); + x11_shadow_handle_xevent(subsystem, &xevent); + } + if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime)) { + x11_shadow_query_cursor(subsystem, FALSE); x11_shadow_screen_grab(subsystem); dwInterval = 1000 / fps; @@ -386,7 +464,7 @@ int x11_shadow_xfixes_init(x11ShadowSubsystem* subsystem) if (!XFixesQueryVersion(subsystem->display, &major, &minor)) return -1; - subsystem->xfixes_notify_event = xfixes_event + XFixesCursorNotify; + subsystem->xfixes_cursor_notify_event = xfixes_event + XFixesCursorNotify; XFixesSelectCursorInput(subsystem->display, DefaultRootWindow(subsystem->display), XFixesDisplayCursorNotifyMask); @@ -609,9 +687,6 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem) if (subsystem->composite) subsystem->use_xdamage = FALSE; - if (!subsystem->use_xdamage) - subsystem->use_xfixes = FALSE; - subsystem->xfds = ConnectionNumber(subsystem->display); subsystem->number = DefaultScreen(subsystem->display); subsystem->screen = ScreenOfDisplay(subsystem->display, subsystem->number); @@ -667,6 +742,15 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem) XSelectInput(subsystem->display, subsystem->root_window, SubstructureNotifyMask); + subsystem->cursorMaxWidth = 96; + subsystem->cursorMaxHeight = 96; + subsystem->cursorPixels = _aligned_malloc(subsystem->cursorMaxWidth * subsystem->cursorMaxHeight * 4, 16); + + if (!subsystem->cursorPixels) + return -1; + + x11_shadow_query_cursor(subsystem, TRUE); + if (subsystem->use_xfixes) { if (x11_shadow_xfixes_init(subsystem) < 0) @@ -734,6 +818,12 @@ int x11_shadow_subsystem_uninit(x11ShadowSubsystem* subsystem) subsystem->event = NULL; } + if (subsystem->cursorPixels) + { + _aligned_free(subsystem->cursorPixels); + subsystem->cursorPixels = NULL; + } + return 1; } diff --git a/server/shadow/X11/x11_shadow.h b/server/shadow/X11/x11_shadow.h index 1a6f6fa4d..dfe5ea361 100644 --- a/server/shadow/X11/x11_shadow.h +++ b/server/shadow/X11/x11_shadow.h @@ -80,6 +80,15 @@ struct x11_shadow_subsystem Window root_window; XShmSegmentInfo fb_shm_info; + int cursorX; + int cursorY; + int cursorWidth; + int cursorHeight; + UINT32 cursorId; + BYTE* cursorPixels; + int cursorMaxWidth; + int cursorMaxHeight; + #ifdef WITH_XDAMAGE GC xshm_gc; Damage xdamage; @@ -88,7 +97,7 @@ struct x11_shadow_subsystem #endif #ifdef WITH_XFIXES - int xfixes_notify_event; + int xfixes_cursor_notify_event; #endif }; From a16252d78b3c952b807e9cfa02ecbc01d9f5af77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 10 Sep 2014 22:52:19 -0400 Subject: [PATCH 04/21] shadow: add initial cursor blending --- server/shadow/X11/x11_shadow.c | 144 ++++++++++++++++++++++++++++++++- server/shadow/X11/x11_shadow.h | 2 + 2 files changed, 142 insertions(+), 4 deletions(-) diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index df62b98ff..82281833e 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -180,11 +181,17 @@ void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16 int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage) { - int x, y; + int x, y, n, k; + rdpShadowServer* server; + rdpShadowSurface* surface; + + server = subsystem->server; + surface = server->surface; if (getImage) { #ifdef WITH_XFIXES + UINT32* pDstPixel; XFixesCursorImage* ci; ci = XFixesGetCursorImage(subsystem->display); @@ -198,12 +205,22 @@ int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage) if (ci->height > subsystem->cursorMaxHeight) return -1; + subsystem->cursorHotX = ci->xhot; + subsystem->cursorHotY = ci->yhot; + subsystem->cursorWidth = ci->width; subsystem->cursorHeight = ci->height; subsystem->cursorId = ci->cursor_serial; - CopyMemory(subsystem->cursorPixels, ci->pixels, ci->width * ci->height * 4); + n = ci->width * ci->height; + pDstPixel = (UINT32*) subsystem->cursorPixels; + + for (k = 0; k < n; k++) + { + /* XFixesCursorImage.pixels is in *unsigned long*, which may be 8 bytes */ + *pDstPixel++ = (UINT32) ci->pixels[k]; + } XFree(ci); #endif @@ -283,6 +300,121 @@ int x11_shadow_invalidate_region(x11ShadowSubsystem* subsystem, int x, int y, in return 1; } +int x11_shadow_blend_cursor(x11ShadowSubsystem* subsystem) +{ + int x, y; + int nXSrc; + int nYSrc; + int nXDst; + int nYDst; + int nWidth; + int nHeight; + int nSrcStep; + int nDstStep; + int nSrcPad; + int nDstPad; + BYTE* pSrcData; + BYTE* pDstData; + BYTE* pSrcPixel; + BYTE* pDstPixel; + BYTE A, R, G, B; + rdpShadowSurface* surface; + + surface = subsystem->server->surface; + + nXSrc = 0; + nYSrc = 0; + + nWidth = subsystem->cursorWidth; + nHeight = subsystem->cursorHeight; + + nXDst = subsystem->cursorX - surface->x - subsystem->cursorHotX; + nYDst = subsystem->cursorY - surface->y - subsystem->cursorHotY; + + if (nXDst >= surface->width) + return 1; + + if (nXDst < 0) + { + nXDst *= -1; + + if (nXDst >= nWidth) + return 1; + + nXSrc = nXDst; + nWidth -= nXDst; + nXDst = 0; + } + + if (nYDst >= surface->height) + return 1; + + if (nYDst < 0) + { + nYDst *= -1; + + if (nYDst >= nHeight) + return 1; + + nYSrc = nYDst; + nHeight -= nYDst; + nYDst = 0; + } + + if ((nXDst + nWidth) > surface->width) + nWidth = surface->width - nXDst; + + if ((nYDst + nHeight) > surface->height) + nHeight = surface->height - nYDst; + + pSrcData = subsystem->cursorPixels; + nSrcStep = subsystem->cursorWidth * 4; + + pDstData = surface->data; + nDstStep = surface->scanline; + + nSrcPad = (nSrcStep - (nWidth * 4)); + nDstPad = (nDstStep - (nWidth * 4)); + + pSrcPixel = &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)]; + pDstPixel = &pDstData[(nYDst * nDstStep) + (nXDst * 4)]; + + for (y = 0; y < nHeight; y++) + { + pSrcPixel = &pSrcData[((nYSrc + y) * nSrcStep) + (nXSrc * 4)]; + pDstPixel = &pDstData[((nYDst + y) * nDstStep) + (nXDst * 4)]; + + for (x = 0; x < nWidth; x++) + { + B = *pSrcPixel++; + G = *pSrcPixel++; + R = *pSrcPixel++; + A = *pSrcPixel++; + + if (A == 0xFF) + { + pDstPixel[0] = B; + pDstPixel[1] = G; + pDstPixel[2] = R; + } + else + { + pDstPixel[0] = B + (pDstPixel[0] * (0xFF - A) + (0xFF / 2)) / 0xFF; + pDstPixel[1] = G + (pDstPixel[1] * (0xFF - A) + (0xFF / 2)) / 0xFF; + pDstPixel[2] = R + (pDstPixel[2] * (0xFF - A) + (0xFF / 2)) / 0xFF; + } + + pDstPixel[3] = 0xFF; + pDstPixel += 4; + } + + pSrcPixel += nSrcPad; + pDstPixel += nDstPad; + } + + return 1; +} + int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) { int count; @@ -334,6 +466,8 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); + x11_shadow_blend_cursor(subsystem); + count = ArrayList_Count(server->clients); InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1); @@ -375,6 +509,8 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); + x11_shadow_blend_cursor(subsystem); + count = ArrayList_Count(server->clients); InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1); @@ -742,8 +878,8 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem) XSelectInput(subsystem->display, subsystem->root_window, SubstructureNotifyMask); - subsystem->cursorMaxWidth = 96; - subsystem->cursorMaxHeight = 96; + subsystem->cursorMaxWidth = 256; + subsystem->cursorMaxHeight = 256; subsystem->cursorPixels = _aligned_malloc(subsystem->cursorMaxWidth * subsystem->cursorMaxHeight * 4, 16); if (!subsystem->cursorPixels) diff --git a/server/shadow/X11/x11_shadow.h b/server/shadow/X11/x11_shadow.h index dfe5ea361..31233e233 100644 --- a/server/shadow/X11/x11_shadow.h +++ b/server/shadow/X11/x11_shadow.h @@ -82,6 +82,8 @@ struct x11_shadow_subsystem int cursorX; int cursorY; + int cursorHotX; + int cursorHotY; int cursorWidth; int cursorHeight; UINT32 cursorId; From aa49e63cda39f4097e9269f71ea8e417ff15aac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Moreau?= Date: Sat, 13 Sep 2014 12:33:33 -0400 Subject: [PATCH 05/21] mfreerdp-server: fix build --- server/Mac/mf_audin.c | 5 +- server/Mac/mf_event.c | 15 +----- server/Mac/mf_info.c | 90 ++++------------------------------ server/Mac/mf_mountain_lion.c | 16 ++---- server/Mac/mf_peer.c | 72 +++------------------------ server/Mac/mf_rdpsnd.c | 9 +--- server/Mac/mfreerdp.c | 3 -- server/shadow/Mac/mac_shadow.c | 25 +++++++--- 8 files changed, 43 insertions(+), 192 deletions(-) diff --git a/server/Mac/mf_audin.c b/server/Mac/mf_audin.c index c4b2d8f39..02f77699b 100644 --- a/server/Mac/mf_audin.c +++ b/server/Mac/mf_audin.c @@ -34,19 +34,18 @@ static const AUDIO_FORMAT supported_audio_formats[] = static void mf_peer_audin_opening(audin_server_context* context) { - DEBUG_WARN( "AUDIN opening.\n"); /* Simply choose the first format supported by the client. */ context->SelectFormat(context, 0); } static void mf_peer_audin_open_result(audin_server_context* context, UINT32 result) { - DEBUG_WARN( "AUDIN open result %d.\n", result); + } static void mf_peer_audin_receive_samples(audin_server_context* context, const void* buf, int nframes) { - DEBUG_WARN( "AUDIN receive %d frames.\n", nframes); + } void mf_peer_audin_init(mfPeerContext* context) diff --git a/server/Mac/mf_event.c b/server/Mac/mf_event.c index a2e2e1a40..669d97454 100644 --- a/server/Mac/mf_event.c +++ b/server/Mac/mf_event.c @@ -26,7 +26,6 @@ #include #include #include -//#include #include "mf_event.h" @@ -49,9 +48,6 @@ void mf_signal_event(mfEventQueue* event_queue) int length; length = write(event_queue->pipe_fd[1], "sig", 4); - - if (length != 4) - DEBUG_WARN( "mf_signal_event: error\n"); } void mf_set_event(mfEventQueue* event_queue) @@ -59,9 +55,6 @@ void mf_set_event(mfEventQueue* event_queue) int length; length = write(event_queue->pipe_fd[1], "sig", 4); - - if (length != 4) - DEBUG_WARN( "mf_set_event: error\n"); } void mf_clear_events(mfEventQueue* event_queue) @@ -71,9 +64,6 @@ void mf_clear_events(mfEventQueue* event_queue) while (mf_is_event_set(event_queue)) { length = read(event_queue->pipe_fd[0], &length, 4); - - if (length != 4) - DEBUG_WARN( "mf_clear_event: error\n"); } } @@ -82,9 +72,6 @@ void mf_clear_event(mfEventQueue* event_queue) int length; length = read(event_queue->pipe_fd[0], &length, 4); - - if (length != 4) - DEBUG_WARN( "mf_clear_event: error\n"); } void mf_event_push(mfEventQueue* event_queue, mfEvent* event) @@ -188,7 +175,7 @@ mfEventQueue* mf_event_queue_new() event_queue->events = (mfEvent**) malloc(sizeof(mfEvent*) * event_queue->size); if (pipe(event_queue->pipe_fd) < 0) - DEBUG_WARN( "mf_event_queue_new: pipe failed\n"); + return NULL; pthread_mutex_init(&(event_queue->mutex), NULL); } diff --git a/server/Mac/mf_info.c b/server/Mac/mf_info.c index dfa686a5f..4a9f3ade8 100644 --- a/server/Mac/mf_info.c +++ b/server/Mac/mf_info.c @@ -34,16 +34,15 @@ static mfInfo* mfInfoInstance = NULL; int mf_info_lock(mfInfo* mfi) { - int status = pthread_mutex_lock(&mfi->mutex); - switch (status) { + switch (status) + { case 0: return TRUE; break; default: - DEBUG_MSG("mf_info_lock failed with %#X\n", status); return -1; break; } @@ -55,7 +54,8 @@ int mf_info_try_lock(mfInfo* mfi, UINT32 ms) int status = pthread_mutex_trylock(&mfi->mutex); - switch (status) { + switch (status) + { case 0: return TRUE; break; @@ -65,7 +65,6 @@ int mf_info_try_lock(mfInfo* mfi, UINT32 ms) break; default: - DEBUG_MSG("mf_info_try_lock failed with %#X\n", status); return -1; break; } @@ -76,13 +75,13 @@ int mf_info_unlock(mfInfo* mfi) { int status = pthread_mutex_unlock(&mfi->mutex); - switch (status) { + switch (status) + { case 0: return TRUE; break; default: - DEBUG_MSG("mf_info_unlock failed with %#X\n", status); return -1; break; } @@ -96,52 +95,16 @@ mfInfo* mf_info_init() mfi = (mfInfo*) malloc(sizeof(mfInfo)); memset(mfi, 0, sizeof(mfInfo)); - if (mfi != NULL) { - /* HKEY hKey; - LONG status; - DWORD dwType; - DWORD dwSize; - DWORD dwValue; - */ - - int mutexInitStatus = pthread_mutex_init(&mfi->mutex, NULL); - - if (mutexInitStatus != 0) - { - DEBUG_MSG(_T("CreateMutex error: %#X\n"), mutexInitStatus); - } + pthread_mutex_init(&mfi->mutex, NULL); mfi->peers = (freerdp_peer**) malloc(sizeof(freerdp_peer*) * MF_INFO_MAXPEERS); memset(mfi->peers, 0, sizeof(freerdp_peer*) * MF_INFO_MAXPEERS); - //Set FPS mfi->framesPerSecond = MF_INFO_DEFAULT_FPS; - /*status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey); - if (status == ERROR_SUCCESS) - { - if (RegQueryValueEx(hKey, _T("FramesPerSecond"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS) - mfi->framesPerSecond = dwValue; - } - RegCloseKey(hKey);*/ - - //Set input toggle mfi->input_disabled = FALSE; - - /*status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey); - if (status == ERROR_SUCCESS) - { - if (RegQueryValueEx(hKey, _T("DisableInput"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS) - { - if (dwValue != 0) - mfi->input_disabled = TRUE; - } - } - RegCloseKey(hKey);*/ - - } return mfi; @@ -161,9 +124,9 @@ void mf_info_peer_register(mfInfo* mfi, mfPeerContext* context) { int i; int peerId; + if (mfi->peerCount == MF_INFO_MAXPEERS) { - DEBUG_MSG("TODO: socketClose on OS X\n"); //context->socketClose = TRUE; mf_info_unlock(mfi); return; @@ -171,10 +134,6 @@ void mf_info_peer_register(mfInfo* mfi, mfPeerContext* context) context->info = mfi; - //get the offset of the top left corner of selected screen - //EnumDisplayMonitors(NULL, NULL, mf_info_monEnumCB, 0); - //_IDcount = 0; - //initialize screen capture if (mfi->peerCount == 0) { @@ -201,8 +160,6 @@ void mf_info_peer_register(mfInfo* mfi, mfPeerContext* context) //printf("Registering Peer: id=%d #=%d\n", peerId, mfi->peerCount); mf_info_unlock(mfi); - - //mfreerdp_server_peer_callback_event(peerId, MF_SRV_CALLBACK_EVENT_CONNECT); } } @@ -216,16 +173,12 @@ void mf_info_peer_unregister(mfInfo* mfi, mfPeerContext* context) mfi->peers[peerId] = NULL; mfi->peerCount--; - //printf("Unregistering Peer: id=%d, #=%d\n", peerId, mfi->peerCount); - //screen capture cleanup if (mfi->peerCount == 0) { mf_mlion_stop_getting_screen_updates(); } mf_info_unlock(mfi); - - //mfreerdp_server_peer_callback_event(peerId, MF_SRV_CALLBACK_EVENT_DISCONNECT); } } @@ -239,14 +192,7 @@ BOOL mf_info_have_updates(mfInfo* mfi) void mf_info_update_changes(mfInfo* mfi) { - /*#ifdef WITH_WIN8 - mf_dxgi_nextFrame(mfi, mfi->framesPerSecond * 1000); - #else - GETCHANGESBUF* buf; - - buf = (GETCHANGESBUF*) mfi->changeBuffer; - mfi->nextUpdate = buf->buffer->counter; - #endif*/ + } void mf_info_find_invalid_region(mfInfo* mfi) @@ -289,21 +235,3 @@ void mf_info_getScreenData(mfInfo* mfi, long* width, long* height, BYTE** pBits, } -/* - BOOL CALLBACK mf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) - { - mfInfo * mfi; - - mfi = mf_info_get_instance(); - - if(_IDcount == mfi->screenID) - { - mfi->servscreen_xoffset = lprcMonitor->left; - mfi->servscreen_yoffset = lprcMonitor->top; - } - - _IDcount++; - - return TRUE; - } - */ diff --git a/server/Mac/mf_mountain_lion.c b/server/Mac/mf_mountain_lion.c index f9777a261..be3398734 100644 --- a/server/Mac/mf_mountain_lion.c +++ b/server/Mac/mf_mountain_lion.c @@ -82,24 +82,19 @@ void (^streamHandler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfaceRef, CGDisp if (status != kCGDisplayStreamFrameStatusFrameComplete) { - //unhandled switch(status) { case kCGDisplayStreamFrameStatusFrameIdle: - DEBUG_MSG("kCGDisplayStreamFrameStatusFrameIdle\n"); break; case kCGDisplayStreamFrameStatusStopped: - //we dont need to clean up - //printf("kCGDisplayStreamFrameStatusStopped\n"); break; case kCGDisplayStreamFrameStatusFrameBlank: - DEBUG_MSG("kCGDisplayStreamFrameStatusFrameBlank\n"); break; default: - DEBUG_MSG("Unhandled Frame Status!!!\n"); + break; } } @@ -191,9 +186,9 @@ int mf_mlion_start_getting_screen_updates() CGError err; err = CGDisplayStreamStart(stream); - if(err != kCGErrorSuccess) + + if (err != kCGErrorSuccess) { - DEBUG_MSG("Failed to start displaystream!! err = %d\n", err); return 1; } @@ -205,9 +200,9 @@ int mf_mlion_stop_getting_screen_updates() CGError err; err = CGDisplayStreamStop(stream); - if(err != kCGErrorSuccess) + + if (err != kCGErrorSuccess) { - DEBUG_MSG("Failed to stop displaystream!! err = %d\n", err); return 1; } @@ -225,7 +220,6 @@ int mf_mlion_get_dirty_region(RFX_RECT* invalid) mf_mlion_peek_dirty_region(invalid); } - dispatch_semaphore_signal(region_sem); return 0; diff --git a/server/Mac/mf_peer.c b/server/Mac/mf_peer.c index 6eee3d892..15c225732 100644 --- a/server/Mac/mf_peer.c +++ b/server/Mac/mf_peer.c @@ -83,7 +83,7 @@ BOOL mf_peer_check_fds(freerdp_peer* client) { if (event->type == MF_EVENT_TYPE_REGION) { - DEBUG_WARN( "unhandled event\n"); + } else if (event->type == MF_EVENT_TYPE_FRAME_TICK) { @@ -253,18 +253,6 @@ BOOL mf_peer_post_connect(freerdp_peer* client) mfPeerContext* context = (mfPeerContext*) client->context; rdpSettings* settings = client->settings; - DEBUG_WARN( "Client %s post connect\n", client->hostname); - - if (client->settings->AutoLogonEnabled) - { - DEBUG_WARN( " and wants to login automatically as %s\\%s", - client->settings->Domain ? client->settings->Domain : "", - client->settings->Username); - - /* A real server may perform OS login here if NLA is not executed previously. */ - } - DEBUG_WARN( "\n"); - mfInfo* mfi = mf_info_get_instance(); mfi->scale = 1; @@ -274,8 +262,7 @@ BOOL mf_peer_post_connect(freerdp_peer* client) if ((settings->DesktopWidth != mfi->servscreen_width) || (settings->DesktopHeight != mfi->servscreen_height)) { - DEBUG_WARN( "Client requested resolution %dx%d, but will resize to %dx%d\n", - settings->DesktopWidth, settings->DesktopHeight, mfi->servscreen_width, mfi->servscreen_height); + } settings->DesktopWidth = mfi->servscreen_width; @@ -314,13 +301,11 @@ BOOL mf_peer_activate(freerdp_peer* client) void mf_peer_synchronize_event(rdpInput* input, UINT32 flags) { - DEBUG_WARN( "Client sent a synchronize event (flags:0x%08X)\n", flags); + } void mf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) { - DEBUG_WARN( "Client sent a keyboard event (flags:0x%04X code:0x%04X)\n", flags, code); - UINT16 down = 0x4000; //UINT16 up = 0x8000; @@ -330,52 +315,16 @@ void mf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) { state_down = TRUE; } - - /* - CGEventRef event; - event = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)code, state_down); - CGEventPost(kCGHIDEventTap, event); - CFRelease(event); - */ } void mf_peer_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) { - DEBUG_WARN( "Client sent a unicode keyboard event (flags:0x%04X code:0x%04X)\n", flags, code); + } -/*void mf_peer_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) -{ - //DEBUG_WARN( "Client sent a mouse event (flags:0x%04X pos: %d,%d)\n", flags, x, y); -} - -void mf_peer_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) -{ - //DEBUG_WARN( "Client sent an extended mouse event (flags:0x%04X pos: %d,%d)\n", flags, x, y); -} -*/ -/*static void mf_peer_refresh_rect(rdpContext* context, BYTE count, RECTANGLE_16* areas) - { - BYTE i; - - DEBUG_WARN( "Client requested to refresh:\n"); - - for (i = 0; i < count; i++) - { - DEBUG_WARN( " (%d, %d) (%d, %d)\n", areas[i].left, areas[i].top, areas[i].right, areas[i].bottom); - } - }*/ - static void mf_peer_suppress_output(rdpContext* context, BYTE allow, RECTANGLE_16* area) { - if (allow > 0) - { - DEBUG_WARN( "Client restore output (%d, %d) (%d, %d).\n", area->left, area->top, area->right, area->bottom); - } - else - { - DEBUG_WARN( "Client minimized and suppress output.\n"); - } + } void mf_peer_accepted(freerdp_listener* instance, freerdp_peer* client) @@ -425,20 +374,18 @@ void* mf_peer_main_loop(void* arg) client->Initialize(client); context = (mfPeerContext*) client->context; - DEBUG_WARN( "We've got a client %s\n", client->local ? "(local)" : client->hostname); - + while (1) { rcount = 0; if (client->GetFileDescriptor(client, rfds, &rcount) != TRUE) { - DEBUG_WARN( "Failed to get FreeRDP file descriptor\n"); break; } + if (mf_peer_get_fds(client, rfds, &rcount) != TRUE) { - DEBUG_WARN( "Failed to get mfreerdp file descriptor\n"); break; } @@ -468,20 +415,17 @@ void* mf_peer_main_loop(void* arg) (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { - DEBUG_WARN( "select failed\n"); break; } } if (client->CheckFileDescriptor(client) != TRUE) { - DEBUG_WARN( "Failed to check freerdp file descriptor\n"); break; } if ((mf_peer_check_fds(client)) != TRUE) { - DEBUG_WARN( "Failed to check mfreerdp file descriptor\n"); break; } @@ -491,8 +435,6 @@ void* mf_peer_main_loop(void* arg) } } - DEBUG_WARN( "Client %s disconnected.\n", client->local ? "(local)" : client->hostname); - client->Disconnect(client); freerdp_peer_context_free(client); freerdp_peer_free(client); diff --git a/server/Mac/mf_rdpsnd.c b/server/Mac/mf_rdpsnd.c index 5278713ac..5e4b00230 100644 --- a/server/Mac/mf_rdpsnd.c +++ b/server/Mac/mf_rdpsnd.c @@ -47,8 +47,6 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context) //we should actually loop through the list of client formats here //and see if we can send the client something that it supports... - DEBUG_MSG("Client supports the following %d formats: \n", context->num_client_formats); - for (i = 0; i < context->num_client_formats; i++) { /* TODO: improve the way we agree on a format */ @@ -58,7 +56,6 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context) (context->client_formats[i].nChannels == context->server_formats[j].nChannels) && (context->client_formats[i].nSamplesPerSec == context->server_formats[j].nSamplesPerSec)) { - DEBUG_MSG("agreed on format!\n"); formatAgreed = TRUE; agreedFormat = (AUDIO_FORMAT*)&context->server_formats[j]; break; @@ -71,7 +68,6 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context) if (formatAgreed == FALSE) { - DEBUG_MSG("Could not agree on a audio format with the server\n"); return; } @@ -114,10 +110,9 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context) if (status != noErr) { - DEBUG_MSG("Failed to create a new Audio Queue. Status code: %d\n", status); + } - UInt32 dataFormatSize = sizeof (recorderState.dataFormat); AudioQueueGetProperty(recorderState.queue, @@ -211,7 +206,7 @@ void mf_peer_rdpsnd_input_callback (void *inUserD if (status != noErr) { - DEBUG_MSG("AudioQueueEnqueueBuffer() returned status = %d\n", status); + } } diff --git a/server/Mac/mfreerdp.c b/server/Mac/mfreerdp.c index 1a1092964..b20c76451 100644 --- a/server/Mac/mfreerdp.c +++ b/server/Mac/mfreerdp.c @@ -60,7 +60,6 @@ static void mf_server_main_loop(freerdp_listener* instance) if (instance->GetFileDescriptor(instance, rfds, &rcount) != TRUE) { - DEBUG_WARN( "Failed to get FreeRDP file descriptor\n"); break; } @@ -88,14 +87,12 @@ static void mf_server_main_loop(freerdp_listener* instance) (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { - DEBUG_WARN( "select failed\n"); break; } } if (instance->CheckFileDescriptor(instance) != TRUE) { - DEBUG_WARN( "Failed to check FreeRDP file descriptor\n"); break; } } diff --git a/server/shadow/Mac/mac_shadow.c b/server/shadow/Mac/mac_shadow.c index a303277b2..e181a81bc 100644 --- a/server/shadow/Mac/mac_shadow.c +++ b/server/shadow/Mac/mac_shadow.c @@ -53,11 +53,6 @@ void mac_shadow_input_extended_mouse_event(macShadowSubsystem* subsystem, UINT16 } -int mac_shadow_surface_copy(macShadowSubsystem* subsystem) -{ - return 1; -} - void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem) { DWORD status; @@ -66,7 +61,7 @@ void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem) HANDLE StopEvent; StopEvent = subsystem->server->StopEvent; - + nCount = 0; events[nCount++] = StopEvent; @@ -86,6 +81,18 @@ void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem) int mac_shadow_subsystem_init(macShadowSubsystem* subsystem) { + MONITOR_DEF* monitor; + + subsystem->monitorCount = 1; + + monitor = &(subsystem->monitors[0]); + + monitor->left = 0; + monitor->top = 0; + monitor->right = 1024; + monitor->bottom = 768; + monitor->flags = 1; + return 1; } @@ -139,6 +146,10 @@ macShadowSubsystem* mac_shadow_subsystem_new(rdpShadowServer* server) return NULL; subsystem->server = server; + + subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + region16_init(&(subsystem->invalidRegion)); subsystem->Init = (pfnShadowSubsystemInit) mac_shadow_subsystem_init; subsystem->Uninit = (pfnShadowSubsystemInit) mac_shadow_subsystem_uninit; @@ -146,8 +157,6 @@ macShadowSubsystem* mac_shadow_subsystem_new(rdpShadowServer* server) subsystem->Stop = (pfnShadowSubsystemStop) mac_shadow_subsystem_stop; subsystem->Free = (pfnShadowSubsystemFree) mac_shadow_subsystem_free; - subsystem->SurfaceCopy = (pfnShadowSurfaceCopy) mac_shadow_surface_copy; - subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) mac_shadow_input_synchronize_event; subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) mac_shadow_input_keyboard_event; subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) mac_shadow_input_unicode_keyboard_event; From 6a1b76e42a5ec1fd409ded4e787e44a340a35d83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Moreau?= Date: Sat, 13 Sep 2014 13:12:55 -0400 Subject: [PATCH 06/21] shadow/mac: add monitor detection --- server/Mac/mf_input.c | 94 +--------------------------------- server/shadow/CMakeLists.txt | 30 ++++++----- server/shadow/Mac/mac_shadow.c | 72 ++++++++++++++++++++++++-- server/shadow/Mac/mac_shadow.h | 15 +++++- 4 files changed, 102 insertions(+), 109 deletions(-) diff --git a/server/Mac/mf_input.c b/server/Mac/mf_input.c index 4165d596c..2a10617bf 100644 --- a/server/Mac/mf_input.c +++ b/server/Mac/mf_input.c @@ -357,21 +357,7 @@ void mf_input_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) void mf_input_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) { - /* - INPUT keyboard_event; - - keyboard_event.type = INPUT_KEYBOARD; - keyboard_event.ki.wVk = 0; - keyboard_event.ki.wScan = code; - keyboard_event.ki.dwFlags = KEYEVENTF_UNICODE; - keyboard_event.ki.dwExtraInfo = 0; - keyboard_event.ki.time = 0; - - if (flags & KBD_FLAGS_RELEASE) - keyboard_event.ki.dwFlags |= KEYEVENTF_KEYUP; - - SendInput(1, &keyboard_event, sizeof(INPUT)); - */ + } void mf_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) @@ -406,34 +392,6 @@ void mf_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) CFRelease(scroll); CFRelease(source); } - /* - /////////////////////////////////////////////// - // We dont support horizontal scrolling yet... - /////////////////////////////////////////////// - else if (flags & PTR_FLAGS_) - { - scroll_y = flags & WheelRotationMask; - - if (flags & PTR_FLAGS_WHEEL_NEGATIVE) - { - scroll_y = -(flags & WheelRotationMask) / 392; - } - else - { - scroll_y = (flags & WheelRotationMask) / 120; - } - - CGEventSourceRef source = CGEventSourceCreate (kCGEventSourceStateCombinedSessionState); - CGEventRef scroll = CGEventCreateScrollWheelEvent(source, - kCGScrollEventUnitLine, - wheelCount, - scroll_y, - scroll_x); - CGEventPost(kCGHIDEventTap, scroll); - - CFRelease(scroll); - CFRelease(source); - } */ else { @@ -542,55 +500,7 @@ void mf_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) void mf_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) { - /* - if ((flags & PTR_XFLAGS_BUTTON1) || (flags & PTR_XFLAGS_BUTTON2)) - { - INPUT mouse_event; - ZeroMemory(&mouse_event, sizeof(INPUT)); - - mouse_event.type = INPUT_MOUSE; - - if (flags & PTR_FLAGS_MOVE) - { - float width, height; - wfInfo * wfi; - - wfi = wf_info_get_instance(); - //width and height of primary screen (even in multimon setups - width = (float) GetSystemMetrics(SM_CXSCREEN); - height = (float) GetSystemMetrics(SM_CYSCREEN); - - x += wfi->servscreen_xoffset; - y += wfi->servscreen_yoffset; - - //mouse_event.mi.dx = x * (0xFFFF / width); - //mouse_event.mi.dy = y * (0xFFFF / height); - mouse_event.mi.dx = (LONG) ((float) x * (65535.0f / width)); - mouse_event.mi.dy = (LONG) ((float) y * (65535.0f / height)); - mouse_event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; - - SendInput(1, &mouse_event, sizeof(INPUT)); - } - - mouse_event.mi.dx = mouse_event.mi.dy = mouse_event.mi.dwFlags = 0; - - if (flags & PTR_XFLAGS_DOWN) - mouse_event.mi.dwFlags |= MOUSEEVENTF_XDOWN; - else - mouse_event.mi.dwFlags |= MOUSEEVENTF_XUP; - - if (flags & PTR_XFLAGS_BUTTON1) - mouse_event.mi.mouseData = XBUTTON1; - else if (flags & PTR_XFLAGS_BUTTON2) - mouse_event.mi.mouseData = XBUTTON2; - - SendInput(1, &mouse_event, sizeof(INPUT)); - } - else - { - mf_input_mouse_event(input, flags, x, y); - } - */ + } diff --git a/server/shadow/CMakeLists.txt b/server/shadow/CMakeLists.txt index e68c84589..4f55d6568 100644 --- a/server/shadow/CMakeLists.txt +++ b/server/shadow/CMakeLists.txt @@ -18,7 +18,15 @@ set(MODULE_NAME "freerdp-shadow") set(MODULE_PREFIX "FREERDP_SERVER_SHADOW") -if(WITH_X11) +if(WIN32) + set(WITH_SHADOW_WIN 1) +elseif(X11_FOUND AND NOT APPLE) + set(WITH_SHADOW_X11 1) +elseif(APPLE AND NOT IOS) + set(WITH_SHADOW_MAC 1) +endif() + +if(WITH_SHADOW_X11) set(XEXT_FEATURE_TYPE "RECOMMENDED") set(XEXT_FEATURE_PURPOSE "X11 extension") set(XEXT_FEATURE_DESCRIPTION "X11 core extensions") @@ -115,6 +123,13 @@ if(WITH_X11) endif() endif() +if(WITH_SHADOW_MAC) + find_library(IOKIT IOKit) + find_library(IOSURFACE IOSurface) + find_library(CARBON Carbon) + list(APPEND ${MODULE_PREFIX}_MAC_LIBS ${IOKIT} ${IOSURFACE} ${CARBON}) +endif() + include_directories(${OPENSSL_INCLUDE_DIR}) set(${MODULE_PREFIX}_SRCS @@ -157,14 +172,6 @@ set(${MODULE_PREFIX}_MAC_SRCS Mac/mac_shadow.c Mac/mac_shadow.h) -if(WIN32) - set(WITH_SHADOW_WIN 1) -elseif(X11_FOUND AND NOT APPLE) - set(WITH_SHADOW_X11 1) -elseif(APPLE AND NOT IOS) - set(WITH_SHADOW_MAC 1) -endif() - if(WITH_SHADOW_WIN) add_definitions(-DWITH_SHADOW_WIN) list(APPEND ${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_WIN_SRCS}) @@ -183,15 +190,14 @@ add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "freerdp-shadow") -list(APPEND ${MODULE_PREFIX}_LIBS freerdp-server) - set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE freerdp MODULES freerdp-core freerdp-common freerdp-codec freerdp-primitives freerdp-utils freerdp-gdi freerdp-crypto freerdp-locale) +list(APPEND ${MODULE_PREFIX}_LIBS freerdp-server) list(APPEND ${MODULE_PREFIX}_LIBS freerdp-client) -list(APPEND ${MODULE_PREFIX}_LIBS winpr-makecert-tool winpr) +list(APPEND ${MODULE_PREFIX}_LIBS winpr winpr-makecert-tool) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) diff --git a/server/shadow/Mac/mac_shadow.c b/server/shadow/Mac/mac_shadow.c index e181a81bc..7605f7139 100644 --- a/server/shadow/Mac/mac_shadow.c +++ b/server/shadow/Mac/mac_shadow.c @@ -79,23 +79,87 @@ void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem) return NULL; } -int mac_shadow_subsystem_init(macShadowSubsystem* subsystem) +int mac_shadow_detect_monitors(macShadowSubsystem* subsystem) { + size_t wide, high; MONITOR_DEF* monitor; + CGDirectDisplayID displayId; + + displayId = CGMainDisplayID(); + + CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId); + + subsystem->pixelWidth = CGDisplayModeGetPixelWidth(mode); + subsystem->pixelHeight = CGDisplayModeGetPixelHeight(mode); + + wide = CGDisplayPixelsWide(displayId); + high = CGDisplayPixelsHigh(displayId); + + CGDisplayModeRelease(mode); + + subsystem->retina = ((subsystem->pixelWidth / wide) == 2) ? TRUE : FALSE; + + if (subsystem->retina) + { + subsystem->width = wide; + subsystem->height = high; + } + else + { + subsystem->width = subsystem->pixelWidth; + subsystem->height = subsystem->pixelHeight; + } subsystem->monitorCount = 1; monitor = &(subsystem->monitors[0]); - + monitor->left = 0; monitor->top = 0; - monitor->right = 1024; - monitor->bottom = 768; + monitor->right = subsystem->width; + monitor->bottom = subsystem->height; monitor->flags = 1; return 1; } +void (^streamHandler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfaceRef, CGDisplayStreamUpdateRef) = ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef) +{ + +}; + +int mac_shadow_capture_init(macShadowSubsystem* subsystem) +{ + void* keys[2]; + void* values[2]; + CFDictionaryRef opts; + CGDirectDisplayID displayId; + + displayId = CGMainDisplayID(); + + subsystem->captureQueue = dispatch_queue_create("mac.shadow.capture", NULL); + + keys[0] = (void*) kCGDisplayStreamShowCursor; + values[0] = (void*) kCFBooleanFalse; + + opts = CFDictionaryCreate(kCFAllocatorDefault, (const void**) keys, (const void**) values, 1, NULL, NULL); + + subsystem->stream = CGDisplayStreamCreateWithDispatchQueue(displayId, + subsystem->pixelWidth, subsystem->pixelHeight, + 'BGRA', opts, subsystem->captureQueue, streamHandler); + + CFRelease(opts); + + return 1; +} + +int mac_shadow_subsystem_init(macShadowSubsystem* subsystem) +{ + mac_shadow_detect_monitors(subsystem); + + return 1; +} + int mac_shadow_subsystem_uninit(macShadowSubsystem* subsystem) { if (!subsystem) diff --git a/server/shadow/Mac/mac_shadow.h b/server/shadow/Mac/mac_shadow.h index 88dbf2593..2080c4186 100644 --- a/server/shadow/Mac/mac_shadow.h +++ b/server/shadow/Mac/mac_shadow.h @@ -29,11 +29,24 @@ typedef struct mac_shadow_subsystem macShadowSubsystem; #include #include +#include +#include +#include +#include +#include + struct mac_shadow_subsystem { RDP_SHADOW_SUBSYSTEM_COMMON(); - + int width; + int height; + BOOL retina; + int pixelWidth; + int pixelHeight; + + CGDisplayStreamRef stream; + dispatch_queue_t captureQueue; }; #ifdef __cplusplus From 464f74805eced4c20207bd571494603716497dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Moreau?= Date: Sat, 13 Sep 2014 13:21:34 -0400 Subject: [PATCH 07/21] shadow/mac: add mouse movement --- server/shadow/Mac/mac_shadow.c | 101 ++++++++++++++++++++++++++++++++- server/shadow/Mac/mac_shadow.h | 4 +- 2 files changed, 103 insertions(+), 2 deletions(-) diff --git a/server/shadow/Mac/mac_shadow.c b/server/shadow/Mac/mac_shadow.c index 7605f7139..e203c01f4 100644 --- a/server/shadow/Mac/mac_shadow.c +++ b/server/shadow/Mac/mac_shadow.c @@ -45,7 +45,106 @@ void mac_shadow_input_unicode_keyboard_event(macShadowSubsystem* subsystem, UINT void mac_shadow_input_mouse_event(macShadowSubsystem* subsystem, UINT16 flags, UINT16 x, UINT16 y) { - + UINT32 scrollX = 0; + UINT32 scrollY = 0; + CGWheelCount wheelCount = 2; + + if (flags & PTR_FLAGS_WHEEL) + { + scrollY = flags & WheelRotationMask; + + if (flags & PTR_FLAGS_WHEEL_NEGATIVE) + { + scrollY = -(flags & WheelRotationMask) / 392; + } + else + { + scrollY = (flags & WheelRotationMask) / 120; + } + + CGEventSourceRef source = CGEventSourceCreate (kCGEventSourceStateHIDSystemState); + CGEventRef scroll = CGEventCreateScrollWheelEvent(source, kCGScrollEventUnitLine, + wheelCount, scrollY, scrollX); + CGEventPost(kCGHIDEventTap, scroll); + + CFRelease(scroll); + CFRelease(source); + } + else + { + CGEventSourceRef source = CGEventSourceCreate (kCGEventSourceStateHIDSystemState); + CGEventType mouseType = kCGEventNull; + CGMouseButton mouseButton = kCGMouseButtonLeft; + + if (flags & PTR_FLAGS_MOVE) + { + if (subsystem->mouseDownLeft) + mouseType = kCGEventLeftMouseDragged; + else if (subsystem->mouseDownRight) + mouseType = kCGEventRightMouseDragged; + else if (subsystem->mouseDownOther) + mouseType = kCGEventOtherMouseDragged; + else + mouseType = kCGEventMouseMoved; + + CGEventRef move = CGEventCreateMouseEvent(source, mouseType, CGPointMake(x, y), mouseButton); + CGEventPost(kCGHIDEventTap, move); + CFRelease(move); + } + + if (flags & PTR_FLAGS_BUTTON1) + { + mouseButton = kCGMouseButtonLeft; + + if (flags & PTR_FLAGS_DOWN) + { + mouseType = kCGEventLeftMouseDown; + subsystem->mouseDownLeft = TRUE; + } + else + { + mouseType = kCGEventLeftMouseUp; + subsystem->mouseDownLeft = FALSE; + } + } + else if (flags & PTR_FLAGS_BUTTON2) + { + mouseButton = kCGMouseButtonRight; + + if (flags & PTR_FLAGS_DOWN) + { + mouseType = kCGEventRightMouseDown; + subsystem->mouseDownRight = TRUE; + } + else + { + mouseType = kCGEventRightMouseUp; + subsystem->mouseDownRight = FALSE; + } + + } + else if (flags & PTR_FLAGS_BUTTON3) + { + mouseButton = kCGMouseButtonCenter; + + if (flags & PTR_FLAGS_DOWN) + { + mouseType = kCGEventOtherMouseDown; + subsystem->mouseDownOther = TRUE; + } + else + { + mouseType = kCGEventOtherMouseUp; + subsystem->mouseDownOther = FALSE; + } + } + + CGEventRef mouseEvent = CGEventCreateMouseEvent(source, mouseType, CGPointMake(x, y), mouseButton); + CGEventPost(kCGHIDEventTap, mouseEvent); + + CFRelease(mouseEvent); + CFRelease(source); + } } void mac_shadow_input_extended_mouse_event(macShadowSubsystem* subsystem, UINT16 flags, UINT16 x, UINT16 y) diff --git a/server/shadow/Mac/mac_shadow.h b/server/shadow/Mac/mac_shadow.h index 2080c4186..0cbeb5817 100644 --- a/server/shadow/Mac/mac_shadow.h +++ b/server/shadow/Mac/mac_shadow.h @@ -44,7 +44,9 @@ struct mac_shadow_subsystem BOOL retina; int pixelWidth; int pixelHeight; - + BOOL mouseDownLeft; + BOOL mouseDownRight; + BOOL mouseDownOther; CGDisplayStreamRef stream; dispatch_queue_t captureQueue; }; From 06dc76bce2469f9d9e1d780823232b387cc6dedf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Moreau?= Date: Sun, 14 Sep 2014 20:08:38 -0400 Subject: [PATCH 08/21] shadow/mac: add initial screen capture support --- include/freerdp/codec/color.h | 3 + libfreerdp/codec/color.c | 59 +++++++ server/shadow/Mac/mac_shadow.c | 313 +++++++++++++++++++++++++++++---- server/shadow/Mac/mac_shadow.h | 5 + 4 files changed, 350 insertions(+), 30 deletions(-) diff --git a/include/freerdp/codec/color.h b/include/freerdp/codec/color.h index 855a9b330..b4a602445 100644 --- a/include/freerdp/codec/color.h +++ b/include/freerdp/codec/color.h @@ -454,6 +454,9 @@ FREERDP_API int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstSt int nWidth, int nHeight, BYTE* pSrcData, DWORD dwSrcFormat, int nSrcStep, int nXSrc, int nYSrc); FREERDP_API int freerdp_image_fill(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, UINT32 color); + +FREERDP_API int freerdp_image_copy_from_retina(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, + int nWidth, int nHeight, BYTE* pSrcData, int nSrcStep, int nXSrc, int nYSrc); #ifdef __cplusplus } diff --git a/libfreerdp/codec/color.c b/libfreerdp/codec/color.c index 76c3800f6..a3b838ec5 100644 --- a/libfreerdp/codec/color.c +++ b/libfreerdp/codec/color.c @@ -1712,3 +1712,62 @@ int freerdp_image_fill(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs return 0; } +int freerdp_image_copy_from_retina(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, + int nWidth, int nHeight, BYTE* pSrcData, int nSrcStep, int nXSrc, int nYSrc) +{ + int x, y; + int nSrcPad; + int nDstPad; + int srcBitsPerPixel; + int srcBytesPerPixel; + int dstBitsPerPixel; + int dstBytesPerPixel; + + srcBitsPerPixel = 24; + srcBytesPerPixel = 8; + + if (nSrcStep < 0) + nSrcStep = srcBytesPerPixel * nWidth; + + dstBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(DstFormat); + dstBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(DstFormat) / 8); + + if (nDstStep < 0) + nDstStep = dstBytesPerPixel * nWidth; + + nSrcPad = (nSrcStep - (nWidth * srcBytesPerPixel)); + nDstPad = (nDstStep - (nWidth * dstBytesPerPixel)); + + if (dstBytesPerPixel == 4) + { + UINT32 R, G, B; + BYTE* pSrcPixel; + BYTE* pDstPixel; + + pSrcPixel = &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)]; + pDstPixel = &pDstData[(nYDst * nDstStep) + (nXDst * 4)]; + + for (y = 0; y < nHeight; y++) + { + for (x = 0; x < nWidth; x++) + { + /* simple box filter scaling, could be improved with better algorithm */ + + B = pSrcPixel[0] + pSrcPixel[4] + pSrcPixel[nSrcStep + 0] + pSrcPixel[nSrcStep + 4]; + G = pSrcPixel[1] + pSrcPixel[5] + pSrcPixel[nSrcStep + 1] + pSrcPixel[nSrcStep + 5]; + R = pSrcPixel[2] + pSrcPixel[6] + pSrcPixel[nSrcStep + 2] + pSrcPixel[nSrcStep + 6]; + pSrcPixel += 8; + + *pDstPixel++ = (BYTE) (B >> 2); + *pDstPixel++ = (BYTE) (G >> 2); + *pDstPixel++ = (BYTE) (R >> 2); + *pDstPixel++ = 0xFF; + } + + pSrcPixel = &pSrcPixel[nSrcPad + nSrcStep]; + pDstPixel = &pDstPixel[nDstPad]; + } + } + + return 1; +} diff --git a/server/shadow/Mac/mac_shadow.c b/server/shadow/Mac/mac_shadow.c index e203c01f4..ed5fafd70 100644 --- a/server/shadow/Mac/mac_shadow.c +++ b/server/shadow/Mac/mac_shadow.c @@ -28,6 +28,8 @@ #include "mac_shadow.h" +static macShadowSubsystem* g_Subsystem = NULL; + void mac_shadow_input_synchronize_event(macShadowSubsystem* subsystem, UINT32 flags) { @@ -152,32 +154,6 @@ void mac_shadow_input_extended_mouse_event(macShadowSubsystem* subsystem, UINT16 } -void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem) -{ - DWORD status; - DWORD nCount; - HANDLE events[32]; - HANDLE StopEvent; - - StopEvent = subsystem->server->StopEvent; - - nCount = 0; - events[nCount++] = StopEvent; - - while (1) - { - status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); - - if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0) - { - break; - } - } - - ExitThread(0); - return NULL; -} - int mac_shadow_detect_monitors(macShadowSubsystem* subsystem) { size_t wide, high; @@ -222,9 +198,222 @@ int mac_shadow_detect_monitors(macShadowSubsystem* subsystem) return 1; } -void (^streamHandler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfaceRef, CGDisplayStreamUpdateRef) = ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef) +int mac_shadow_capture_start(macShadowSubsystem* subsystem) { + CGError err; + err = CGDisplayStreamStart(subsystem->stream); + + if (err != kCGErrorSuccess) + return -1; + + return 1; +} + +int mac_shadow_capture_stop(macShadowSubsystem* subsystem) +{ + CGError err; + + err = CGDisplayStreamStop(subsystem->stream); + + if (err != kCGErrorSuccess) + return -1; + + return 1; +} + +int mac_shadow_capture_peek_dirty_region(macShadowSubsystem* subsystem) +{ + size_t index; + size_t numRects; + const CGRect* rects; + RECTANGLE_16 invalidRect; + + rects = CGDisplayStreamUpdateGetRects(subsystem->lastUpdate, kCGDisplayStreamUpdateDirtyRects, &numRects); + + if (!numRects) + return -1; + + for (index = 0; index < numRects; index++) + { + invalidRect.left = (UINT16) rects[index].origin.x; + invalidRect.top = (UINT16) rects[index].origin.y; + invalidRect.right = invalidRect.left + (UINT16) rects[index].size.width; + invalidRect.bottom = invalidRect.top + (UINT16) rects[index].size.height; + + if (subsystem->retina) + { + /* scale invalid rect */ + invalidRect.left /= 2; + invalidRect.top /= 2; + invalidRect.right /= 2; + invalidRect.bottom /= 2; + } + + region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); + } + + return 0; +} + +int mac_shadow_capture_get_dirty_region(macShadowSubsystem* subsystem) +{ + dispatch_semaphore_wait(subsystem->regionSemaphore, DISPATCH_TIME_FOREVER); + + if (subsystem->lastUpdate) + { + mac_shadow_capture_peek_dirty_region(subsystem); + } + + dispatch_semaphore_signal(subsystem->regionSemaphore); + + return 1; +} + +int mac_shadow_capture_clear_dirty_region(macShadowSubsystem* subsystem) +{ + dispatch_semaphore_wait(subsystem->regionSemaphore, DISPATCH_TIME_FOREVER); + + CFRelease(subsystem->lastUpdate); + subsystem->lastUpdate = NULL; + + dispatch_semaphore_signal(subsystem->regionSemaphore); + + return 1; +} + +int mac_shadow_capture_surface_copy(macShadowSubsystem* subsystem) +{ + dispatch_semaphore_wait(subsystem->regionSemaphore, DISPATCH_TIME_FOREVER); + subsystem->updateReady = TRUE; + + dispatch_semaphore_wait(subsystem->dataSemaphore, DISPATCH_TIME_FOREVER); + dispatch_semaphore_signal(subsystem->regionSemaphore); + + dispatch_semaphore_wait(subsystem->dataSemaphore, DISPATCH_TIME_FOREVER); + dispatch_semaphore_signal(subsystem->dataSemaphore); + + return 1; +} + +void (^mac_capture_stream_handler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfaceRef, CGDisplayStreamUpdateRef) = + ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef) +{ + int x, y; + int count; + int width; + int height; + int nSrcStep; + BYTE* pSrcData; + RECTANGLE_16 surfaceRect; + const RECTANGLE_16* extents; + macShadowSubsystem* subsystem = g_Subsystem; + rdpShadowServer* server = subsystem->server; + rdpShadowSurface* surface = server->surface; + + if (ArrayList_Count(server->clients) < 1) + { + region16_clear(&(subsystem->invalidRegion)); + return; + } + + dispatch_semaphore_wait(subsystem->regionSemaphore, DISPATCH_TIME_FOREVER); + + if (!subsystem->updateReady) + { + dispatch_semaphore_signal(subsystem->regionSemaphore); + return; + } + + mac_shadow_capture_peek_dirty_region(subsystem); + + surfaceRect.left = surface->x; + surfaceRect.top = surface->y; + surfaceRect.right = surface->x + surface->width; + surfaceRect.bottom = surface->y + surface->height; + + region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect); + + if (region16_is_empty(&(subsystem->invalidRegion))) + { + + } + + extents = region16_extents(&(subsystem->invalidRegion)); + + x = extents->left; + y = extents->top; + width = extents->right - extents->left; + height = extents->bottom - extents->top; + + IOSurfaceLock(frameSurface, kIOSurfaceLockReadOnly, NULL); + + pSrcData = (BYTE*) IOSurfaceGetBaseAddress(frameSurface); + nSrcStep = (int) IOSurfaceGetBytesPerRow(frameSurface); + + if (subsystem->retina) + { + freerdp_image_copy_from_retina(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, + x, y, width, height, pSrcData, nSrcStep, x, y); + } + else + { + freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, + x, y, width, height, pSrcData, PIXEL_FORMAT_XRGB32, nSrcStep, x, y); + } + + IOSurfaceUnlock(frameSurface, kIOSurfaceLockReadOnly, NULL); + + subsystem->updateReady = FALSE; + dispatch_semaphore_signal(subsystem->dataSemaphore); + + ArrayList_Lock(server->clients); + + count = ArrayList_Count(server->clients); + + InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1); + + SetEvent(subsystem->updateEvent); + + EnterSynchronizationBarrier(&(subsystem->barrier), 0); + ResetEvent(subsystem->updateEvent); + + DeleteSynchronizationBarrier(&(subsystem->barrier)); + + ArrayList_Unlock(server->clients); + + region16_clear(&(subsystem->invalidRegion)); + + if (status != kCGDisplayStreamFrameStatusFrameComplete) + { + switch (status) + { + case kCGDisplayStreamFrameStatusFrameIdle: + break; + + case kCGDisplayStreamFrameStatusStopped: + break; + + case kCGDisplayStreamFrameStatusFrameBlank: + break; + + default: + break; + } + } + else if (!subsystem->lastUpdate) + { + CFRetain(updateRef); + subsystem->lastUpdate = updateRef; + } + else + { + CGDisplayStreamUpdateRef tmpRef = subsystem->lastUpdate; + subsystem->lastUpdate = CGDisplayStreamUpdateCreateMergedUpdate(tmpRef, updateRef); + CFRelease(tmpRef); + } + + dispatch_semaphore_signal(subsystem->regionSemaphore); }; int mac_shadow_capture_init(macShadowSubsystem* subsystem) @@ -236,6 +425,11 @@ int mac_shadow_capture_init(macShadowSubsystem* subsystem) displayId = CGMainDisplayID(); + subsystem->regionSemaphore = dispatch_semaphore_create(1); + subsystem->dataSemaphore = dispatch_semaphore_create(1); + + subsystem->updateBuffer = (BYTE*) malloc(subsystem->pixelWidth * subsystem->pixelHeight * 4); + subsystem->captureQueue = dispatch_queue_create("mac.shadow.capture", NULL); keys[0] = (void*) kCGDisplayStreamShowCursor; @@ -243,19 +437,76 @@ int mac_shadow_capture_init(macShadowSubsystem* subsystem) opts = CFDictionaryCreate(kCFAllocatorDefault, (const void**) keys, (const void**) values, 1, NULL, NULL); - subsystem->stream = CGDisplayStreamCreateWithDispatchQueue(displayId, - subsystem->pixelWidth, subsystem->pixelHeight, - 'BGRA', opts, subsystem->captureQueue, streamHandler); + subsystem->stream = CGDisplayStreamCreateWithDispatchQueue(displayId, subsystem->pixelWidth, subsystem->pixelHeight, + 'BGRA', opts, subsystem->captureQueue, mac_capture_stream_handler); CFRelease(opts); return 1; } +int mac_shadow_screen_grab(macShadowSubsystem* subsystem) +{ + mac_shadow_capture_get_dirty_region(subsystem); + mac_shadow_capture_surface_copy(subsystem); + + return 1; +} + +void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem) +{ + int fps; + DWORD status; + DWORD nCount; + UINT64 cTime; + DWORD dwTimeout; + DWORD dwInterval; + UINT64 frameTime; + HANDLE events[32]; + HANDLE StopEvent; + + StopEvent = subsystem->server->StopEvent; + + nCount = 0; + events[nCount++] = StopEvent; + + fps = 16; + dwInterval = 1000 / fps; + frameTime = GetTickCount64() + dwInterval; + + while (1) + { + cTime = GetTickCount64(); + dwTimeout = (cTime > frameTime) ? 0 : frameTime - cTime; + + status = WaitForMultipleObjects(nCount, events, FALSE, dwTimeout); + + if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0) + { + break; + } + + if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime)) + { + mac_shadow_screen_grab(subsystem); + + dwInterval = 1000 / fps; + frameTime += dwInterval; + } + } + + ExitThread(0); + return NULL; +} + int mac_shadow_subsystem_init(macShadowSubsystem* subsystem) { + g_Subsystem = subsystem; + mac_shadow_detect_monitors(subsystem); + mac_shadow_capture_init(subsystem); + return 1; } @@ -274,6 +525,8 @@ int mac_shadow_subsystem_start(macShadowSubsystem* subsystem) if (!subsystem) return -1; + mac_shadow_capture_start(subsystem); + thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) mac_shadow_subsystem_thread, (void*) subsystem, 0, NULL); diff --git a/server/shadow/Mac/mac_shadow.h b/server/shadow/Mac/mac_shadow.h index 0cbeb5817..a5479d5d5 100644 --- a/server/shadow/Mac/mac_shadow.h +++ b/server/shadow/Mac/mac_shadow.h @@ -47,8 +47,13 @@ struct mac_shadow_subsystem BOOL mouseDownLeft; BOOL mouseDownRight; BOOL mouseDownOther; + BOOL updateReady; + BYTE* updateBuffer; CGDisplayStreamRef stream; dispatch_queue_t captureQueue; + dispatch_semaphore_t dataSemaphore; + dispatch_semaphore_t regionSemaphore; + CGDisplayStreamUpdateRef lastUpdate; }; #ifdef __cplusplus From 41814b1b1c2999953f309f05d6d849be4e789dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Moreau?= Date: Sun, 14 Sep 2014 20:23:40 -0400 Subject: [PATCH 09/21] shadow/mac: add keyboard support --- server/shadow/Mac/mac_shadow.c | 43 +++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/server/shadow/Mac/mac_shadow.c b/server/shadow/Mac/mac_shadow.c index ed5fafd70..3b5ce4964 100644 --- a/server/shadow/Mac/mac_shadow.c +++ b/server/shadow/Mac/mac_shadow.c @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -37,7 +38,43 @@ void mac_shadow_input_synchronize_event(macShadowSubsystem* subsystem, UINT32 fl void mac_shadow_input_keyboard_event(macShadowSubsystem* subsystem, UINT16 flags, UINT16 code) { - + DWORD vkcode; + DWORD keycode; + BOOL extended; + CGEventRef kbdEvent; + CGEventSourceRef source; + + extended = (flags & KBD_FLAGS_EXTENDED) ? TRUE : FALSE; + + if (extended) + code |= KBDEXT; + + vkcode = GetVirtualKeyCodeFromVirtualScanCode(code, 4); + + if (extended) + vkcode |= KBDEXT; + + keycode = GetKeycodeFromVirtualKeyCode(vkcode, KEYCODE_TYPE_APPLE) - 8; + + if (keycode) + { + source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); + + if (flags & KBD_FLAGS_DOWN) + { + kbdEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode) keycode, TRUE); + CGEventPost(kCGHIDEventTap, kbdEvent); + CFRelease(kbdEvent); + } + else if (flags & KBD_FLAGS_RELEASE) + { + kbdEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode) keycode, FALSE); + CGEventPost(kCGHIDEventTap, kbdEvent); + CFRelease(kbdEvent); + } + + CFRelease(source); + } } void mac_shadow_input_unicode_keyboard_event(macShadowSubsystem* subsystem, UINT16 flags, UINT16 code) @@ -64,7 +101,7 @@ void mac_shadow_input_mouse_event(macShadowSubsystem* subsystem, UINT16 flags, U scrollY = (flags & WheelRotationMask) / 120; } - CGEventSourceRef source = CGEventSourceCreate (kCGEventSourceStateHIDSystemState); + CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); CGEventRef scroll = CGEventCreateScrollWheelEvent(source, kCGScrollEventUnitLine, wheelCount, scrollY, scrollX); CGEventPost(kCGHIDEventTap, scroll); @@ -74,7 +111,7 @@ void mac_shadow_input_mouse_event(macShadowSubsystem* subsystem, UINT16 flags, U } else { - CGEventSourceRef source = CGEventSourceCreate (kCGEventSourceStateHIDSystemState); + CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); CGEventType mouseType = kCGEventNull; CGMouseButton mouseButton = kCGMouseButtonLeft; From c66f27234283696ded8a97509228dc8c89f91c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 17 Sep 2014 15:19:35 -0400 Subject: [PATCH 10/21] shadow: fix encoder grid bug --- server/shadow/shadow_encoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/shadow/shadow_encoder.c b/server/shadow/shadow_encoder.c index 8388267a6..8150d4bdd 100644 --- a/server/shadow/shadow_encoder.c +++ b/server/shadow/shadow_encoder.c @@ -84,7 +84,7 @@ int shadow_encoder_init_grid(rdpShadowEncoder* encoder) { for (j = 0; j < encoder->gridWidth; j++) { - k = (i * encoder->gridHeight) + j; + k = (i * encoder->gridWidth) + j; encoder->grid[k] = &(encoder->gridBuffer[k * tileSize]); } } From e84e7928e3b15d1053657e9e4bf4d958610a8c7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 17 Sep 2014 21:18:47 -0400 Subject: [PATCH 11/21] server/shadow: split into library + executable --- include/freerdp/server/shadow.h | 20 ++++++++ server/shadow/CMakeLists.txt | 22 +++++++-- server/shadow/shadow.c | 86 +++++++++++++++++++++++++++++++++ server/shadow/shadow_server.c | 54 +-------------------- 4 files changed, 126 insertions(+), 56 deletions(-) create mode 100644 server/shadow/shadow.c diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h index 929e6fa5f..8f010b54c 100644 --- a/include/freerdp/server/shadow.h +++ b/include/freerdp/server/shadow.h @@ -142,5 +142,25 @@ struct rdp_shadow_subsystem RDP_SHADOW_SUBSYSTEM_COMMON(); }; +#ifdef __cplusplus +extern "C" { +#endif + +FREERDP_API int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** argv); +FREERDP_API int shadow_server_command_line_status_print(rdpShadowServer* server, int argc, char** argv, int status); + +FREERDP_API int shadow_server_start(rdpShadowServer* server); +FREERDP_API int shadow_server_stop(rdpShadowServer* server); + +FREERDP_API int shadow_server_init(rdpShadowServer* server); +FREERDP_API int shadow_server_uninit(rdpShadowServer* server); + +FREERDP_API rdpShadowServer* shadow_server_new(); +FREERDP_API void shadow_server_free(rdpShadowServer* server); + +#ifdef __cplusplus +} +#endif + #endif /* FREERDP_SERVER_SHADOW_H */ diff --git a/server/shadow/CMakeLists.txt b/server/shadow/CMakeLists.txt index 9577611cc..b928a2799 100644 --- a/server/shadow/CMakeLists.txt +++ b/server/shadow/CMakeLists.txt @@ -186,9 +186,7 @@ elseif(WITH_SHADOW_MAC) list(APPEND ${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_MAC_LIBS}) endif() -add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) - -set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "freerdp-shadow") +add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) list(APPEND ${MODULE_PREFIX}_LIBS freerdp) list(APPEND ${MODULE_PREFIX}_LIBS freerdp-server) @@ -203,3 +201,21 @@ install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ser set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/shadow") +# command-line executable + +set(MODULE_NAME "freerdp-shadow-cli") +set(MODULE_PREFIX "FREERDP_SERVER_SHADOW_CLI") + +set(${MODULE_PREFIX}_SRCS + shadow.c) + +add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) +set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "freerdp-shadow") + +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-shadow) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +install(TARGETS ${MODULE_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT server) + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/shadow") diff --git a/server/shadow/shadow.c b/server/shadow/shadow.c new file mode 100644 index 000000000..8386024e9 --- /dev/null +++ b/server/shadow/shadow.c @@ -0,0 +1,86 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef _WIN32 +#include +#endif + +#ifdef _WIN32 +static BOOL g_MessagePump = TRUE; +#else +static BOOL g_MessagePump = FALSE; +#endif + +#include + +int main(int argc, char** argv) +{ + MSG msg; + int status; + DWORD dwExitCode; + rdpShadowServer* server; + + server = shadow_server_new(); + + if (!server) + return 0; + + if (shadow_server_init(server) < 0) + return 0; + + status = shadow_server_parse_command_line(server, argc, argv); + + status = shadow_server_command_line_status_print(server, argc, argv, status); + + if (status < 0) + return 0; + + if (shadow_server_start(server) < 0) + return 0; + + if (g_MessagePump) + { + while (GetMessage(&msg, 0, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + WaitForSingleObject(server->thread, INFINITE); + + GetExitCodeThread(server->thread, &dwExitCode); + + shadow_server_free(server); + + return 0; +} + diff --git a/server/shadow/shadow_server.c b/server/shadow/shadow_server.c index 49b4c1480..e44808fd7 100644 --- a/server/shadow/shadow_server.c +++ b/server/shadow/shadow_server.c @@ -27,15 +27,11 @@ #include #include -#include #include +#include #include -#ifdef _WIN32 -#include -#endif - #ifndef _WIN32 #include #include @@ -45,12 +41,6 @@ #define TAG SERVER_TAG("shadow") -#ifdef _WIN32 -static BOOL g_MessagePump = TRUE; -#else -static BOOL g_MessagePump = FALSE; -#endif - #ifdef WITH_SHADOW_X11 extern rdpShadowSubsystem* X11_ShadowCreateSubsystem(rdpShadowServer* server); #endif @@ -648,45 +638,3 @@ void shadow_server_free(rdpShadowServer* server) free(server); } -int main(int argc, char** argv) -{ - MSG msg; - int status; - DWORD dwExitCode; - rdpShadowServer* server; - - server = shadow_server_new(); - - if (!server) - return 0; - - if (shadow_server_init(server) < 0) - return 0; - - status = shadow_server_parse_command_line(server, argc, argv); - - status = shadow_server_command_line_status_print(server, argc, argv, status); - - if (status < 0) - return 0; - - if (shadow_server_start(server) < 0) - return 0; - - if (g_MessagePump) - { - while (GetMessage(&msg, 0, 0, 0)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - - WaitForSingleObject(server->thread, INFINITE); - - GetExitCodeThread(server->thread, &dwExitCode); - - shadow_server_free(server); - - return 0; -} From 48d15998e75bd5f6adb5a86248434bfc4d8d4558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 17 Sep 2014 22:58:57 -0400 Subject: [PATCH 12/21] shadow: add common subsystem code --- include/freerdp/server/shadow.h | 1 + server/shadow/CMakeLists.txt | 2 ++ server/shadow/Mac/mac_shadow.c | 9 ++++--- server/shadow/Win/win_shadow.c | 12 +++------ server/shadow/X11/x11_shadow.c | 15 +++++------ server/shadow/shadow_client.c | 7 +++++ server/shadow/shadow_subsystem.c | 45 ++++++++++++++++++++++++++++++++ server/shadow/shadow_subsystem.h | 41 +++++++++++++++++++++++++++++ 8 files changed, 111 insertions(+), 21 deletions(-) create mode 100644 server/shadow/shadow_subsystem.c create mode 100644 server/shadow/shadow_subsystem.h diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h index 8f010b54c..23789c672 100644 --- a/include/freerdp/server/shadow.h +++ b/include/freerdp/server/shadow.h @@ -118,6 +118,7 @@ struct rdp_shadow_server MONITOR_DEF virtualScreen; \ HANDLE updateEvent; \ REGION16 invalidRegion; \ + wMessagePipe* MsgPipe; \ SYNCHRONIZATION_BARRIER barrier; \ \ pfnShadowSubsystemInit Init; \ diff --git a/server/shadow/CMakeLists.txt b/server/shadow/CMakeLists.txt index b928a2799..5c25c415c 100644 --- a/server/shadow/CMakeLists.txt +++ b/server/shadow/CMakeLists.txt @@ -151,6 +151,8 @@ set(${MODULE_PREFIX}_SRCS shadow_encomsp.h shadow_remdesk.c shadow_remdesk.h + shadow_subsystem.c + shadow_subsystem.h shadow_server.c shadow.h) diff --git a/server/shadow/Mac/mac_shadow.c b/server/shadow/Mac/mac_shadow.c index 65e8b8bc9..abec9e812 100644 --- a/server/shadow/Mac/mac_shadow.c +++ b/server/shadow/Mac/mac_shadow.c @@ -26,6 +26,8 @@ #include "../shadow_screen.h" #include "../shadow_surface.h" +#include "../shadow_capture.h" +#include "../shadow_subsystem.h" #include "mac_shadow.h" @@ -586,6 +588,8 @@ void mac_shadow_subsystem_free(macShadowSubsystem* subsystem) mac_shadow_subsystem_uninit(subsystem); + shadow_subsystem_common_free((rdpShadowSubsystem*) subsystem); + free(subsystem); } @@ -599,10 +603,7 @@ macShadowSubsystem* mac_shadow_subsystem_new(rdpShadowServer* server) return NULL; subsystem->server = server; - - subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - - region16_init(&(subsystem->invalidRegion)); + shadow_subsystem_common_new((rdpShadowSubsystem*) subsystem); subsystem->Init = (pfnShadowSubsystemInit) mac_shadow_subsystem_init; subsystem->Uninit = (pfnShadowSubsystemInit) mac_shadow_subsystem_uninit; diff --git a/server/shadow/Win/win_shadow.c b/server/shadow/Win/win_shadow.c index 1615764a4..e5d4b2844 100644 --- a/server/shadow/Win/win_shadow.c +++ b/server/shadow/Win/win_shadow.c @@ -20,13 +20,14 @@ #include #include +#include #include #include -#include #include "../shadow_screen.h" #include "../shadow_surface.h" #include "../shadow_capture.h" +#include "../shadow_subsystem.h" #include "win_shadow.h" @@ -492,9 +493,7 @@ void win_shadow_subsystem_free(winShadowSubsystem* subsystem) win_shadow_subsystem_uninit(subsystem); - region16_uninit(&(subsystem->invalidRegion)); - - CloseHandle(subsystem->updateEvent); + shadow_subsystem_common_free((rdpShadowSubsystem*) subsystem); free(subsystem); } @@ -509,10 +508,7 @@ winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server) return NULL; subsystem->server = server; - - subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - - region16_init(&(subsystem->invalidRegion)); + shadow_subsystem_common_new((rdpShadowSubsystem*) subsystem); subsystem->Init = (pfnShadowSubsystemInit) win_shadow_subsystem_init; subsystem->Uninit = (pfnShadowSubsystemInit) win_shadow_subsystem_uninit; diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index eff82b7a8..b3ef07837 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -42,6 +42,7 @@ #include "../shadow_screen.h" #include "../shadow_capture.h" #include "../shadow_surface.h" +#include "../shadow_subsystem.h" #include "x11_shadow.h" @@ -136,7 +137,7 @@ void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, U if (flags & PTR_FLAGS_DOWN) down = TRUE; - if (button != 0) + if (button) XTestFakeButtonEvent(subsystem->display, button, down, 0); } @@ -165,6 +166,7 @@ void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16 } XTestGrabControl(subsystem->display, True); + XTestFakeMotionEvent(subsystem->display, 0, x, y, CurrentTime); if (flags & PTR_XFLAGS_BUTTON1) @@ -175,7 +177,7 @@ void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16 if (flags & PTR_XFLAGS_DOWN) down = TRUE; - if (button != 0) + if (button) XTestFakeButtonEvent(subsystem->display, button, down, 0); XTestGrabControl(subsystem->display, False); @@ -995,9 +997,7 @@ void x11_shadow_subsystem_free(x11ShadowSubsystem* subsystem) x11_shadow_subsystem_uninit(subsystem); - region16_uninit(&(subsystem->invalidRegion)); - - CloseHandle(subsystem->updateEvent); + shadow_subsystem_common_free((rdpShadowSubsystem*) subsystem); free(subsystem); } @@ -1012,10 +1012,7 @@ x11ShadowSubsystem* x11_shadow_subsystem_new(rdpShadowServer* server) return NULL; subsystem->server = server; - - subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - - region16_init(&(subsystem->invalidRegion)); + shadow_subsystem_common_new((rdpShadowSubsystem*) subsystem); subsystem->Init = (pfnShadowSubsystemInit) x11_shadow_subsystem_init; subsystem->Uninit = (pfnShadowSubsystemInit) x11_shadow_subsystem_uninit; diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index 5002fa76b..6728ee82b 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -194,6 +194,11 @@ void shadow_client_surface_frame_acknowledge(rdpShadowClient* client, UINT32 fra } } +void shadow_client_refresh_rect(rdpContext* context, BYTE count, RECTANGLE_16* areas) +{ + +} + void shadow_client_suppress_output(rdpShadowClient* client, BYTE allow, RECTANGLE_16* area) { @@ -682,6 +687,8 @@ void* shadow_client_thread(rdpShadowClient* client) peer->update->SurfaceFrameAcknowledge = (pSurfaceFrameAcknowledge) shadow_client_surface_frame_acknowledge; + + peer->update->RefreshRect = (pRefreshRect) shadow_client_refresh_rect; peer->update->SuppressOutput = (pSuppressOutput) shadow_client_suppress_output; StopEvent = client->StopEvent; diff --git a/server/shadow/shadow_subsystem.c b/server/shadow/shadow_subsystem.c new file mode 100644 index 000000000..8193755be --- /dev/null +++ b/server/shadow/shadow_subsystem.c @@ -0,0 +1,45 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "shadow.h" + +#include "shadow_subsystem.h" + +int shadow_subsystem_common_new(rdpShadowSubsystem* subsystem) +{ + subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + subsystem->MsgPipe = MessagePipe_New(); + + region16_init(&(subsystem->invalidRegion)); + + return 1; +} + +void shadow_subsystem_common_free(rdpShadowSubsystem* subsystem) +{ + CloseHandle(subsystem->updateEvent); + + MessagePipe_Free(subsystem->MsgPipe); + + region16_uninit(&(subsystem->invalidRegion)); +} diff --git a/server/shadow/shadow_subsystem.h b/server/shadow/shadow_subsystem.h new file mode 100644 index 000000000..bc8a2413a --- /dev/null +++ b/server/shadow/shadow_subsystem.h @@ -0,0 +1,41 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_SHADOW_SERVER_SUBSYSTEM_H +#define FREERDP_SHADOW_SERVER_SUBSYSTEM_H + +#include + +#include +#include + +#include "shadow_subsystem.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int shadow_subsystem_common_new(rdpShadowSubsystem* subsystem); +void shadow_subsystem_common_free(rdpShadowSubsystem* subsystem); + +#ifdef __cplusplus +} +#endif + +#endif /* FREERDP_SHADOW_SERVER_SUBSYSTEM_H */ + From 4f498d68301cc7af1a5dc0cbfaa8045dd8ffee55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 17 Sep 2014 22:59:58 -0400 Subject: [PATCH 13/21] mfreerdp-server: disable in favor of shadow server --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 266fe93cf..75acf2563 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -27,7 +27,7 @@ if(FREERDP_VENDOR) if(NOT WIN32) if(APPLE AND (NOT IOS)) - add_subdirectory(Mac) + #add_subdirectory(Mac) endif() else() #add_subdirectory(Windows) From a77279fb4cf93d600ade8be47220c01a6023c711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 18 Sep 2014 10:06:59 -0400 Subject: [PATCH 14/21] shadow: fix and improve config path detection --- server/shadow/shadow_server.c | 68 +++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/server/shadow/shadow_server.c b/server/shadow/shadow_server.c index e44808fd7..2e8b69471 100644 --- a/server/shadow/shadow_server.c +++ b/server/shadow/shadow_server.c @@ -449,6 +449,67 @@ int shadow_server_stop(rdpShadowServer* server) return 0; } +int shadow_server_init_config_path(rdpShadowServer* server) +{ +#ifdef _WIN32 + if (!server->ConfigPath) + { + server->ConfigPath = GetEnvironmentSubPath("LOCALAPPDATA", "freerdp"); + } +#endif + +#ifdef __APPLE__ + if (!server->ConfigPath) + { + char* userLibraryPath; + char* userApplicationSupportPath; + + userLibraryPath = GetKnownSubPath(KNOWN_PATH_HOME, "Library"); + + if (userLibraryPath) + { + if (!PathFileExistsA(userLibraryPath)) + CreateDirectoryA(userLibraryPath, 0); + + userApplicationSupportPath = GetCombinedPath(userLibraryPath, "Application Support"); + + if (userApplicationSupportPath) + { + if (!PathFileExistsA(userApplicationSupportPath)) + CreateDirectoryA(userApplicationSupportPath, 0); + + server->ConfigPath = GetCombinedPath(userApplicationSupportPath, "freerdp"); + } + + free(userLibraryPath); + free(userApplicationSupportPath); + } + } +#endif + + if (!server->ConfigPath) + { + char* configHome; + + configHome = GetKnownPath(KNOWN_PATH_XDG_CONFIG_HOME); + + if (configHome) + { + if (!PathFileExistsA(configHome)) + CreateDirectoryA(configHome, 0); + + server->ConfigPath = GetKnownSubPath(KNOWN_PATH_XDG_CONFIG_HOME, "freerdp"); + + free(configHome); + } + } + + if (!server->ConfigPath) + return -1; /* no usable config path */ + + return 1; +} + int shadow_server_init_certificate(rdpShadowServer* server) { char* filepath; @@ -606,12 +667,7 @@ rdpShadowServer* shadow_server_new() server->mayView = TRUE; server->mayInteract = TRUE; -#ifdef _WIN32 - server->ConfigPath = GetEnvironmentSubPath("LOCALAPPDATA", "freerdp"); -#endif - - if (!server->ConfigPath) - server->ConfigPath = GetKnownSubPath(KNOWN_PATH_XDG_CONFIG_HOME, "freerdp"); + shadow_server_init_config_path(server); InitializeCriticalSectionAndSpinCount(&(server->lock), 4000); From 527638c69116d533d66e9c0f2c730bbc4cd15578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 18 Sep 2014 13:06:49 -0400 Subject: [PATCH 15/21] shadow: delay subsystem initialization for monitor enumeration --- include/freerdp/server/shadow.h | 9 +- libfreerdp/core/listener.c | 37 ++++--- server/shadow/Mac/mac_shadow.c | 7 +- server/shadow/Win/win_shadow.c | 9 +- server/shadow/X11/x11_shadow.c | 161 ++++++++++++++++++------------- server/shadow/shadow.c | 6 +- server/shadow/shadow.h | 1 + server/shadow/shadow_server.c | 115 ++++++++-------------- server/shadow/shadow_subsystem.c | 80 +++++++++++++-- server/shadow/shadow_subsystem.h | 7 +- 10 files changed, 250 insertions(+), 182 deletions(-) diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h index 23789c672..f3b10c35a 100644 --- a/include/freerdp/server/shadow.h +++ b/include/freerdp/server/shadow.h @@ -55,6 +55,8 @@ typedef int (*pfnShadowSubsystemStart)(rdpShadowSubsystem* subsystem); typedef int (*pfnShadowSubsystemStop)(rdpShadowSubsystem* subsystem); typedef void (*pfnShadowSubsystemFree)(rdpShadowSubsystem* subsystem); +typedef int (*pfnShadowEnumMonitors)(rdpShadowSubsystem* subsystem, MONITOR_DEF* monitors, int maxMonitors); + typedef int (*pfnShadowSurfaceCopy)(rdpShadowSubsystem* subsystem); typedef int (*pfnShadowSurfaceUpdate)(rdpShadowSubsystem* subsystem, REGION16* subRect); @@ -100,6 +102,7 @@ struct rdp_shadow_server BOOL mayView; BOOL mayInteract; BOOL shareSubRect; + int selectedMonitor; RECTANGLE_16 subRect; char* ipcSocket; char* ConfigPath; @@ -107,12 +110,11 @@ struct rdp_shadow_server char* PrivateKeyFile; CRITICAL_SECTION lock; freerdp_listener* listener; - pfnShadowCreateSubsystem CreateSubsystem; }; #define RDP_SHADOW_SUBSYSTEM_COMMON() \ HANDLE event; \ - int monitorCount; \ + int numMonitors; \ int selectedMonitor; \ MONITOR_DEF monitors[16]; \ MONITOR_DEF virtualScreen; \ @@ -127,6 +129,7 @@ struct rdp_shadow_server pfnShadowSubsystemStop Stop; \ pfnShadowSubsystemFree Free; \ \ + pfnShadowEnumMonitors EnumMonitors; \ pfnShadowSurfaceCopy SurfaceCopy; \ pfnShadowSurfaceUpdate SurfaceUpdate; \ \ @@ -156,6 +159,8 @@ FREERDP_API int shadow_server_stop(rdpShadowServer* server); FREERDP_API int shadow_server_init(rdpShadowServer* server); FREERDP_API int shadow_server_uninit(rdpShadowServer* server); +FREERDP_API int shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors, UINT32 flags); + FREERDP_API rdpShadowServer* shadow_server_new(); FREERDP_API void shadow_server_free(rdpShadowServer* server); diff --git a/libfreerdp/core/listener.c b/libfreerdp/core/listener.c index 0a3f47538..5920a9bbf 100644 --- a/libfreerdp/core/listener.c +++ b/libfreerdp/core/listener.c @@ -79,16 +79,16 @@ static const char* inet_ntop(int af, const void* src, char* dst, size_t cnt) static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_address, UINT16 port) { - rdpListener* listener = (rdpListener*) instance->listener; int status; int sockfd; - char servname[10]; - struct addrinfo hints = { 0 }; - struct addrinfo* res; - struct addrinfo* ai; - int option_value; + char addr[64]; void* sin_addr; - char buf[50]; + int option_value; + char servname[16]; + struct addrinfo* ai; + struct addrinfo* res; + struct addrinfo hints = { 0 }; + rdpListener* listener = (rdpListener*) instance->listener; #ifdef _WIN32 u_long arg; #endif @@ -96,7 +96,7 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - if (bind_address == NULL) + if (!bind_address) hints.ai_flags = AI_PASSIVE; sprintf_s(servname, sizeof(servname), "%d", port); @@ -112,9 +112,9 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a return FALSE; } - for (ai = res; ai && listener->num_sockfds < 5; ai = ai->ai_next) + for (ai = res; ai && (listener->num_sockfds < 5); ai = ai->ai_next) { - if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) + if ((ai->ai_family != AF_INET) && (ai->ai_family != AF_INET6)) continue; sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); @@ -125,6 +125,16 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a continue; } + if (ai->ai_family == AF_INET) + sin_addr = &(((struct sockaddr_in*) ai->ai_addr)->sin_addr); + else + sin_addr = &(((struct sockaddr_in6*) ai->ai_addr)->sin6_addr); + + inet_ntop(ai->ai_family, sin_addr, addr, sizeof(addr)); + + if (strcmp(addr, "::") == 0) + continue; + option_value = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &option_value, sizeof(option_value)) == -1) @@ -166,12 +176,7 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a listener->events[listener->num_sockfds] = CreateFileDescriptorEvent(NULL, FALSE, FALSE, sockfd); listener->num_sockfds++; - if (ai->ai_family == AF_INET) - sin_addr = &(((struct sockaddr_in*) ai->ai_addr)->sin_addr); - else - sin_addr = &(((struct sockaddr_in6*) ai->ai_addr)->sin6_addr); - - WLog_ERR(TAG, "Listening on %s port %s.\n", inet_ntop(ai->ai_family, sin_addr, buf, sizeof(buf)), servname); + WLog_INFO(TAG, "Listening on %s:%s", addr, servname); } freeaddrinfo(res); diff --git a/server/shadow/Mac/mac_shadow.c b/server/shadow/Mac/mac_shadow.c index abec9e812..db9de54df 100644 --- a/server/shadow/Mac/mac_shadow.c +++ b/server/shadow/Mac/mac_shadow.c @@ -224,7 +224,7 @@ int mac_shadow_detect_monitors(macShadowSubsystem* subsystem) subsystem->height = subsystem->pixelHeight; } - subsystem->monitorCount = 1; + subsystem->numMonitors = 1; monitor = &(subsystem->monitors[0]); @@ -588,8 +588,6 @@ void mac_shadow_subsystem_free(macShadowSubsystem* subsystem) mac_shadow_subsystem_uninit(subsystem); - shadow_subsystem_common_free((rdpShadowSubsystem*) subsystem); - free(subsystem); } @@ -602,9 +600,6 @@ macShadowSubsystem* mac_shadow_subsystem_new(rdpShadowServer* server) if (!subsystem) return NULL; - subsystem->server = server; - shadow_subsystem_common_new((rdpShadowSubsystem*) subsystem); - subsystem->Init = (pfnShadowSubsystemInit) mac_shadow_subsystem_init; subsystem->Uninit = (pfnShadowSubsystemInit) mac_shadow_subsystem_uninit; subsystem->Start = (pfnShadowSubsystemStart) mac_shadow_subsystem_start; diff --git a/server/shadow/Win/win_shadow.c b/server/shadow/Win/win_shadow.c index e5d4b2844..1a156cea1 100644 --- a/server/shadow/Win/win_shadow.c +++ b/server/shadow/Win/win_shadow.c @@ -435,9 +435,9 @@ int win_shadow_subsystem_init(winShadowSubsystem* subsystem) virtualScreen->bottom = subsystem->height; virtualScreen->flags = 1; - if (subsystem->monitorCount < 1) + if (subsystem->numMonitors < 1) { - subsystem->monitorCount = 1; + subsystem->numMonitors = 1; subsystem->monitors[0].left = virtualScreen->left; subsystem->monitors[0].top = virtualScreen->top; subsystem->monitors[0].right = virtualScreen->right; @@ -493,8 +493,6 @@ void win_shadow_subsystem_free(winShadowSubsystem* subsystem) win_shadow_subsystem_uninit(subsystem); - shadow_subsystem_common_free((rdpShadowSubsystem*) subsystem); - free(subsystem); } @@ -507,9 +505,6 @@ winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server) if (!subsystem) return NULL; - subsystem->server = server; - shadow_subsystem_common_new((rdpShadowSubsystem*) subsystem); - subsystem->Init = (pfnShadowSubsystemInit) win_shadow_subsystem_init; subsystem->Uninit = (pfnShadowSubsystemInit) win_shadow_subsystem_uninit; subsystem->Start = (pfnShadowSubsystemStart) win_shadow_subsystem_start; diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index b3ef07837..d25176e10 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -592,6 +592,36 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem) return NULL; } +int x11_shadow_subsystem_base_init(x11ShadowSubsystem* subsystem) +{ + if (subsystem->display) + return 1; /* initialize once */ + + if (!getenv("DISPLAY")) + setenv("DISPLAY", ":0", 1); + + if (!XInitThreads()) + return -1; + + subsystem->display = XOpenDisplay(NULL); + + if (!subsystem->display) + { + WLog_ERR(TAG, "failed to open display: %s", XDisplayName(NULL)); + return -1; + } + + subsystem->xfds = ConnectionNumber(subsystem->display); + subsystem->number = DefaultScreen(subsystem->display); + subsystem->screen = ScreenOfDisplay(subsystem->display, subsystem->number); + subsystem->depth = DefaultDepthOfScreen(subsystem->screen); + subsystem->width = WidthOfScreen(subsystem->screen); + subsystem->height = HeightOfScreen(subsystem->screen); + subsystem->root_window = DefaultRootWindow(subsystem->display); + + return 1; +} + int x11_shadow_xfixes_init(x11ShadowSubsystem* subsystem) { #ifdef WITH_XFIXES @@ -618,14 +648,11 @@ int x11_shadow_xfixes_init(x11ShadowSubsystem* subsystem) int x11_shadow_xinerama_init(x11ShadowSubsystem* subsystem) { #ifdef WITH_XINERAMA - int index; - int numMonitors; int major, minor; int xinerama_event; int xinerama_error; - MONITOR_DEF* monitor; - XineramaScreenInfo* screen; - XineramaScreenInfo* screens; + + x11_shadow_subsystem_base_init(subsystem); if (!XineramaQueryExtension(subsystem->display, &xinerama_event, &xinerama_error)) return -1; @@ -636,32 +663,10 @@ int x11_shadow_xinerama_init(x11ShadowSubsystem* subsystem) if (!XineramaIsActive(subsystem->display)) return -1; - screens = XineramaQueryScreens(subsystem->display, &numMonitors); - - if (numMonitors > 16) - numMonitors = 16; - - if (!screens || (numMonitors < 1)) - return -1; - - subsystem->monitorCount = numMonitors; - - for (index = 0; index < numMonitors; index++) - { - screen = &screens[index]; - monitor = &(subsystem->monitors[index]); - - monitor->left = screen->x_org; - monitor->top = screen->y_org; - monitor->right = monitor->left + screen->width; - monitor->bottom = monitor->top + screen->height; - monitor->flags = (index == 0) ? 1 : 0; - } - - XFree(screens); -#endif - return 1; +#else + return -1; +#endif } int x11_shadow_xdamage_init(x11ShadowSubsystem* subsystem) @@ -776,6 +781,61 @@ int x11_shadow_xshm_init(x11ShadowSubsystem* subsystem) return 1; } +int x11_shadow_enum_monitors(x11ShadowSubsystem* subsystem, MONITOR_DEF* monitors, int maxMonitors) +{ + int index; + int numMonitors = 0; + MONITOR_DEF* monitor; + +#ifdef WITH_XINERAMA + if (x11_shadow_xinerama_init(subsystem) > 0) + { + XineramaScreenInfo* screen; + XineramaScreenInfo* screens; + + screens = XineramaQueryScreens(subsystem->display, &numMonitors); + + if (numMonitors > maxMonitors) + numMonitors = maxMonitors; + + if (screens && (numMonitors > 0)) + { + for (index = 0; index < numMonitors; index++) + { + screen = &screens[index]; + monitor = &monitors[index]; + + monitor->left = screen->x_org; + monitor->top = screen->y_org; + monitor->right = monitor->left + screen->width; + monitor->bottom = monitor->top + screen->height; + monitor->flags = (index == 0) ? 1 : 0; + } + } + + XFree(screens); + } +#endif + + if (numMonitors < 1) + { + index = 0; + numMonitors = 1; + + x11_shadow_subsystem_base_init(subsystem); + + monitor = &monitors[index]; + + monitor->left = 0; + monitor->top = 0; + monitor->right = subsystem->width; + monitor->bottom = subsystem->height; + monitor->flags = 1; + } + + return numMonitors; +} + int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem) { int i; @@ -790,27 +850,9 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem) XPixmapFormatValues* pfs; MONITOR_DEF* virtualScreen; - /** - * To see if your X11 server supports shared pixmaps, use: - * xdpyinfo -ext MIT-SHM | grep "shared pixmaps" - */ + x11_shadow_subsystem_base_init(subsystem); - if (!getenv("DISPLAY")) - { - /* Set DISPLAY variable if not already set */ - setenv("DISPLAY", ":0", 1); - } - - if (!XInitThreads()) - return -1; - - subsystem->display = XOpenDisplay(NULL); - - if (!subsystem->display) - { - WLog_ERR(TAG, "failed to open display: %s", XDisplayName(NULL)); - return -1; - } + subsystem->numMonitors = x11_shadow_enum_monitors(subsystem, subsystem->monitors, 16); extensions = XListExtensions(subsystem->display, &nextensions); @@ -828,14 +870,6 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem) if (subsystem->composite) subsystem->use_xdamage = FALSE; - subsystem->xfds = ConnectionNumber(subsystem->display); - subsystem->number = DefaultScreen(subsystem->display); - subsystem->screen = ScreenOfDisplay(subsystem->display, subsystem->number); - subsystem->depth = DefaultDepthOfScreen(subsystem->screen); - subsystem->width = WidthOfScreen(subsystem->screen); - subsystem->height = HeightOfScreen(subsystem->screen); - subsystem->root_window = DefaultRootWindow(subsystem->display); - pfs = XListPixmapFormats(subsystem->display, &pf_count); if (!pfs) @@ -926,9 +960,9 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem) virtualScreen->bottom = subsystem->height; virtualScreen->flags = 1; - if (subsystem->monitorCount < 1) + if (subsystem->numMonitors < 1) { - subsystem->monitorCount = 1; + subsystem->numMonitors = 1; subsystem->monitors[0].left = virtualScreen->left; subsystem->monitors[0].top = virtualScreen->top; subsystem->monitors[0].right = virtualScreen->right; @@ -997,8 +1031,6 @@ void x11_shadow_subsystem_free(x11ShadowSubsystem* subsystem) x11_shadow_subsystem_uninit(subsystem); - shadow_subsystem_common_free((rdpShadowSubsystem*) subsystem); - free(subsystem); } @@ -1011,15 +1043,14 @@ x11ShadowSubsystem* x11_shadow_subsystem_new(rdpShadowServer* server) if (!subsystem) return NULL; - subsystem->server = server; - shadow_subsystem_common_new((rdpShadowSubsystem*) subsystem); - subsystem->Init = (pfnShadowSubsystemInit) x11_shadow_subsystem_init; subsystem->Uninit = (pfnShadowSubsystemInit) x11_shadow_subsystem_uninit; subsystem->Start = (pfnShadowSubsystemStart) x11_shadow_subsystem_start; subsystem->Stop = (pfnShadowSubsystemStop) x11_shadow_subsystem_stop; subsystem->Free = (pfnShadowSubsystemFree) x11_shadow_subsystem_free; + subsystem->EnumMonitors = (pfnShadowEnumMonitors) x11_shadow_enum_monitors; + subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) x11_shadow_input_synchronize_event; subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) x11_shadow_input_keyboard_event; subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) x11_shadow_input_unicode_keyboard_event; diff --git a/server/shadow/shadow.c b/server/shadow/shadow.c index 8386024e9..607081950 100644 --- a/server/shadow/shadow.c +++ b/server/shadow/shadow.c @@ -53,9 +53,6 @@ int main(int argc, char** argv) if (!server) return 0; - if (shadow_server_init(server) < 0) - return 0; - status = shadow_server_parse_command_line(server, argc, argv); status = shadow_server_command_line_status_print(server, argc, argv, status); @@ -63,6 +60,9 @@ int main(int argc, char** argv) if (status < 0) return 0; + if (shadow_server_init(server) < 0) + return 0; + if (shadow_server_start(server) < 0) return 0; diff --git a/server/shadow/shadow.h b/server/shadow/shadow.h index c6f3109bc..f2114bde7 100644 --- a/server/shadow/shadow.h +++ b/server/shadow/shadow.h @@ -28,6 +28,7 @@ #include "shadow_encoder.h" #include "shadow_capture.h" #include "shadow_channels.h" +#include "shadow_subsystem.h" #ifdef __cplusplus extern "C" { diff --git a/server/shadow/shadow_server.c b/server/shadow/shadow_server.c index 2e8b69471..430063322 100644 --- a/server/shadow/shadow_server.c +++ b/server/shadow/shadow_server.c @@ -41,18 +41,6 @@ #define TAG SERVER_TAG("shadow") -#ifdef WITH_SHADOW_X11 -extern rdpShadowSubsystem* X11_ShadowCreateSubsystem(rdpShadowServer* server); -#endif - -#ifdef WITH_SHADOW_MAC -extern rdpShadowSubsystem* Mac_ShadowCreateSubsystem(rdpShadowServer* server); -#endif - -#ifdef WITH_SHADOW_WIN -extern rdpShadowSubsystem* Win_ShadowCreateSubsystem(rdpShadowServer* server); -#endif - static COMMAND_LINE_ARGUMENT_A shadow_args[] = { { "port", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Server port" }, @@ -258,7 +246,10 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a if (arg && (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)) { int index; - rdpShadowSubsystem* subsystem = server->subsystem; + int numMonitors; + MONITOR_DEF monitors[16]; + + numMonitors = shadow_enum_monitors(monitors, 16, 0); if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) { @@ -269,10 +260,10 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a if (index < 0) index = 0; - if (index >= subsystem->monitorCount) + if (index >= numMonitors) index = 0; - subsystem->selectedMonitor = index; + server->selectedMonitor = index; } else { @@ -281,9 +272,9 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a /* List monitors */ - for (index = 0; index < subsystem->monitorCount; index++) + for (index = 0; index < numMonitors; index++) { - monitor = &(subsystem->monitors[index]); + monitor = &monitors[index]; width = monitor->right - monitor->left; height = monitor->bottom - monitor->top; @@ -300,32 +291,6 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a return status; } -int shadow_server_surface_update(rdpShadowSubsystem* subsystem, REGION16* region) -{ - int index; - int count; - wArrayList* clients; - rdpShadowServer* server; - rdpShadowClient* client; - - server = subsystem->server; - clients = server->clients; - - ArrayList_Lock(clients); - - count = ArrayList_Count(clients); - - for (index = 0; index < count; index++) - { - client = ArrayList_GetItem(clients, index); - shadow_client_surface_update(client, region); - } - - ArrayList_Unlock(clients); - - return 1; -} - void* shadow_server_thread(rdpShadowServer* server) { DWORD status; @@ -571,8 +536,17 @@ int shadow_server_init(rdpShadowServer* server) WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi()); + server->clients = ArrayList_New(TRUE); + server->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + InitializeCriticalSectionAndSpinCount(&(server->lock), 4000); + + status = shadow_server_init_config_path(server); + + if (status < 0) + return -1; + status = shadow_server_init_certificate(server); if (status < 0) @@ -586,35 +560,14 @@ int shadow_server_init(rdpShadowServer* server) server->listener->info = (void*) server; server->listener->PeerAccepted = shadow_client_accepted; -#ifdef WITH_SHADOW_X11 - server->CreateSubsystem = X11_ShadowCreateSubsystem; -#endif - -#ifdef WITH_SHADOW_MAC - server->CreateSubsystem = Mac_ShadowCreateSubsystem; -#endif - -#ifdef WITH_SHADOW_WIN - server->CreateSubsystem = Win_ShadowCreateSubsystem; -#endif - - if (server->CreateSubsystem) - server->subsystem = server->CreateSubsystem(server); + server->subsystem = shadow_subsystem_new(0); if (!server->subsystem) return -1; - server->subsystem->SurfaceUpdate = shadow_server_surface_update; + status = shadow_subsystem_init(server->subsystem, server); - if (server->subsystem->Init) - { - status = server->subsystem->Init(server->subsystem); - - if (status < 0) - WLog_ERR(TAG, "subsystem init failure: %d", status); - } - - return 1; + return status; } int shadow_server_uninit(rdpShadowServer* server) @@ -651,9 +604,31 @@ int shadow_server_uninit(rdpShadowServer* server) server->ipcSocket = NULL; } + shadow_subsystem_uninit(server->subsystem); + return 1; } +int shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors, UINT32 flags) +{ + int numMonitors = 0; + rdpShadowSubsystem* subsystem; + + subsystem = shadow_subsystem_new(flags); + + if (!subsystem) + return -1; + + if (!subsystem->EnumMonitors) + return -1; + + numMonitors = subsystem->EnumMonitors(subsystem, monitors, maxMonitors); + + shadow_subsystem_free(subsystem); + + return numMonitors; +} + rdpShadowServer* shadow_server_new() { rdpShadowServer* server; @@ -667,12 +642,6 @@ rdpShadowServer* shadow_server_new() server->mayView = TRUE; server->mayInteract = TRUE; - shadow_server_init_config_path(server); - - InitializeCriticalSectionAndSpinCount(&(server->lock), 4000); - - server->clients = ArrayList_New(TRUE); - return server; } diff --git a/server/shadow/shadow_subsystem.c b/server/shadow/shadow_subsystem.c index 8193755be..42211374f 100644 --- a/server/shadow/shadow_subsystem.c +++ b/server/shadow/shadow_subsystem.c @@ -24,22 +24,86 @@ #include "shadow_subsystem.h" -int shadow_subsystem_common_new(rdpShadowSubsystem* subsystem) +#ifdef WITH_SHADOW_X11 +extern rdpShadowSubsystem* X11_ShadowCreateSubsystem(rdpShadowServer* server); +#endif + +#ifdef WITH_SHADOW_MAC +extern rdpShadowSubsystem* Mac_ShadowCreateSubsystem(rdpShadowServer* server); +#endif + +#ifdef WITH_SHADOW_WIN +extern rdpShadowSubsystem* Win_ShadowCreateSubsystem(rdpShadowServer* server); +#endif + +rdpShadowSubsystem* shadow_subsystem_new(UINT32 flags) { + rdpShadowSubsystem* subsystem = NULL; + pfnShadowCreateSubsystem CreateSubsystem = NULL; + +#ifdef WITH_SHADOW_X11 + CreateSubsystem = X11_ShadowCreateSubsystem; +#endif + +#ifdef WITH_SHADOW_MAC + CreateSubsystem = Mac_ShadowCreateSubsystem; +#endif + +#ifdef WITH_SHADOW_WIN + CreateSubsystem = Win_ShadowCreateSubsystem; +#endif + + if (CreateSubsystem) + subsystem = CreateSubsystem(NULL); + + return subsystem; +} + +void shadow_subsystem_free(rdpShadowSubsystem* subsystem) +{ + if (subsystem->Free) + subsystem->Free(subsystem); +} + +int shadow_subsystem_init(rdpShadowSubsystem* subsystem, rdpShadowServer* server) +{ + int status; + + subsystem->server = server; + subsystem->selectedMonitor = server->selectedMonitor; + subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - subsystem->MsgPipe = MessagePipe_New(); - region16_init(&(subsystem->invalidRegion)); - return 1; + if (!subsystem->Init) + return -1; + + if (subsystem->Init) + status = subsystem->Init(subsystem); + + return status; } -void shadow_subsystem_common_free(rdpShadowSubsystem* subsystem) +void shadow_subsystem_uninit(rdpShadowSubsystem* subsystem) { - CloseHandle(subsystem->updateEvent); + if (subsystem->Uninit) + subsystem->Uninit(subsystem); - MessagePipe_Free(subsystem->MsgPipe); + if (subsystem->updateEvent) + { + CloseHandle(subsystem->updateEvent); + subsystem->updateEvent = NULL; + } - region16_uninit(&(subsystem->invalidRegion)); + if (subsystem->MsgPipe) + { + MessagePipe_Free(subsystem->MsgPipe); + subsystem->MsgPipe = NULL; + } + + if (subsystem->invalidRegion.data) + { + region16_uninit(&(subsystem->invalidRegion)); + } } diff --git a/server/shadow/shadow_subsystem.h b/server/shadow/shadow_subsystem.h index bc8a2413a..e22b545db 100644 --- a/server/shadow/shadow_subsystem.h +++ b/server/shadow/shadow_subsystem.h @@ -30,8 +30,11 @@ extern "C" { #endif -int shadow_subsystem_common_new(rdpShadowSubsystem* subsystem); -void shadow_subsystem_common_free(rdpShadowSubsystem* subsystem); +rdpShadowSubsystem* shadow_subsystem_new(UINT32 flags); +void shadow_subsystem_free(rdpShadowSubsystem* subsystem); + +int shadow_subsystem_init(rdpShadowSubsystem* subsystem, rdpShadowServer* server); +void shadow_subsystem_uninit(rdpShadowSubsystem* subsystem); #ifdef __cplusplus } From a5f8bdf51cda7dc3cc38a873f26e013d69e0b077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 18 Sep 2014 14:29:42 -0400 Subject: [PATCH 16/21] shadow: add EnumMonitor functions --- server/shadow/Mac/mac_shadow.c | 32 ++++++++++++++++++++++++++ server/shadow/Win/win_shadow.c | 41 +++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/server/shadow/Mac/mac_shadow.c b/server/shadow/Mac/mac_shadow.c index db9de54df..ed1e09b34 100644 --- a/server/shadow/Mac/mac_shadow.c +++ b/server/shadow/Mac/mac_shadow.c @@ -538,6 +538,36 @@ void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem) return NULL; } +int mac_shadow_enum_monitors(macShadowSubsystem* subsystem, MONITOR_DEF* monitors, int maxMonitors) +{ + int index; + size_t wide, high; + int numMonitors = 0; + MONITOR_DEF* monitor; + CGDirectDisplayID displayId; + + displayId = CGMainDisplayID(); + CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId); + + wide = CGDisplayPixelsWide(displayId); + high = CGDisplayPixelsHigh(displayId); + + CGDisplayModeRelease(mode); + + index = 0; + numMonitors = 1; + + monitor = &monitors[index]; + + monitor->left = 0; + monitor->top = 0; + monitor->right = (int) wide; + monitor->bottom = (int) high; + monitor->flags = 1; + + return numMonitors; +} + int mac_shadow_subsystem_init(macShadowSubsystem* subsystem) { g_Subsystem = subsystem; @@ -606,6 +636,8 @@ macShadowSubsystem* mac_shadow_subsystem_new(rdpShadowServer* server) subsystem->Stop = (pfnShadowSubsystemStop) mac_shadow_subsystem_stop; subsystem->Free = (pfnShadowSubsystemFree) mac_shadow_subsystem_free; + subsystem->EnumMonitors = (pfnShadowEnumMonitors) mac_shadow_enum_monitors; + subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) mac_shadow_input_synchronize_event; subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) mac_shadow_input_keyboard_event; subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) mac_shadow_input_unicode_keyboard_event; diff --git a/server/shadow/Win/win_shadow.c b/server/shadow/Win/win_shadow.c index 1a156cea1..6574567f4 100644 --- a/server/shadow/Win/win_shadow.c +++ b/server/shadow/Win/win_shadow.c @@ -399,6 +399,45 @@ void* win_shadow_subsystem_thread(winShadowSubsystem* subsystem) #endif +int win_shadow_enum_monitors(winShadowSubsystem* subsystem, MONITOR_DEF* monitors, int maxMonitors) +{ + HDC hdc; + int index; + int desktopWidth; + int desktopHeight; + DWORD iDevNum = 0; + int numMonitors = 0; + MONITOR_DEF* monitor; + MONITOR_DEF* virtualScreen; + DISPLAY_DEVICE displayDevice; + + ZeroMemory(&displayDevice, sizeof(DISPLAY_DEVICE)); + displayDevice.cb = sizeof(DISPLAY_DEVICE); + + if (EnumDisplayDevices(NULL, iDevNum, &displayDevice, 0)) + { + hdc = CreateDC(displayDevice.DeviceName, NULL, NULL, NULL); + + desktopWidth = GetDeviceCaps(hdc, HORZRES); + desktopHeight = GetDeviceCaps(hdc, VERTRES); + + index = 0; + numMonitors = 1; + + monitor = &monitors[index]; + + monitor->left = 0; + monitor->top = 0; + monitor->right = desktopWidth; + monitor->bottom = desktopHeight; + monitor->flags = 1; + + DeleteDC(hdc); + } + + return numMonitors; +} + int win_shadow_subsystem_init(winShadowSubsystem* subsystem) { HDC hdc; @@ -511,7 +550,7 @@ winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server) subsystem->Stop = (pfnShadowSubsystemStop) win_shadow_subsystem_stop; subsystem->Free = (pfnShadowSubsystemFree) win_shadow_subsystem_free; - subsystem->SurfaceCopy = (pfnShadowSurfaceCopy) win_shadow_surface_copy; + subsystem->EnumMonitors = (pfnShadowEnumMonitors) win_shadow_enum_monitors; subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) win_shadow_input_synchronize_event; subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) win_shadow_input_keyboard_event; From 7ef55ab9b7fadf66d3e3424ffb525aa7ccdffbf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 18 Sep 2014 15:43:11 -0400 Subject: [PATCH 17/21] shadow: improve subsystem structure --- include/freerdp/server/shadow.h | 37 +++++--- server/shadow/Mac/mac_shadow.c | 27 +++--- server/shadow/Win/win_shadow.c | 54 ++++------- server/shadow/X11/x11_shadow.c | 106 ++++++++++++--------- server/shadow/shadow_server.c | 40 +------- server/shadow/shadow_subsystem.c | 156 +++++++++++++++++++++++++------ server/shadow/shadow_subsystem.h | 5 +- 7 files changed, 251 insertions(+), 174 deletions(-) diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h index f3b10c35a..eee56432d 100644 --- a/include/freerdp/server/shadow.h +++ b/include/freerdp/server/shadow.h @@ -47,15 +47,19 @@ typedef struct rdp_shadow_encoder rdpShadowEncoder; typedef struct rdp_shadow_capture rdpShadowCapture; typedef struct rdp_shadow_subsystem rdpShadowSubsystem; -typedef rdpShadowSubsystem* (*pfnShadowCreateSubsystem)(rdpShadowServer* server); +typedef struct _RDP_SHADOW_ENTRY_POINTS RDP_SHADOW_ENTRY_POINTS; +typedef int (*pfnShadowSubsystemEntry)(RDP_SHADOW_ENTRY_POINTS* pEntryPoints); + +typedef rdpShadowSubsystem* (*pfnShadowSubsystemNew)(); +typedef void (*pfnShadowSubsystemFree)(rdpShadowSubsystem* subsystem); typedef int (*pfnShadowSubsystemInit)(rdpShadowSubsystem* subsystem); typedef int (*pfnShadowSubsystemUninit)(rdpShadowSubsystem* subsystem); + typedef int (*pfnShadowSubsystemStart)(rdpShadowSubsystem* subsystem); typedef int (*pfnShadowSubsystemStop)(rdpShadowSubsystem* subsystem); -typedef void (*pfnShadowSubsystemFree)(rdpShadowSubsystem* subsystem); -typedef int (*pfnShadowEnumMonitors)(rdpShadowSubsystem* subsystem, MONITOR_DEF* monitors, int maxMonitors); +typedef int (*pfnShadowEnumMonitors)(MONITOR_DEF* monitors, int maxMonitors); typedef int (*pfnShadowSurfaceCopy)(rdpShadowSubsystem* subsystem); typedef int (*pfnShadowSurfaceUpdate)(rdpShadowSubsystem* subsystem, REGION16* subRect); @@ -112,7 +116,22 @@ struct rdp_shadow_server freerdp_listener* listener; }; +struct _RDP_SHADOW_ENTRY_POINTS +{ + pfnShadowSubsystemNew New; + pfnShadowSubsystemFree Free; + + pfnShadowSubsystemInit Init; + pfnShadowSubsystemUninit Uninit; + + pfnShadowSubsystemStart Start; + pfnShadowSubsystemStop Stop; + + pfnShadowEnumMonitors EnumMonitors; +}; + #define RDP_SHADOW_SUBSYSTEM_COMMON() \ + RDP_SHADOW_ENTRY_POINTS ep; \ HANDLE event; \ int numMonitors; \ int selectedMonitor; \ @@ -123,16 +142,6 @@ struct rdp_shadow_server wMessagePipe* MsgPipe; \ SYNCHRONIZATION_BARRIER barrier; \ \ - pfnShadowSubsystemInit Init; \ - pfnShadowSubsystemUninit Uninit; \ - pfnShadowSubsystemStart Start; \ - pfnShadowSubsystemStop Stop; \ - pfnShadowSubsystemFree Free; \ - \ - pfnShadowEnumMonitors EnumMonitors; \ - pfnShadowSurfaceCopy SurfaceCopy; \ - pfnShadowSurfaceUpdate SurfaceUpdate; \ - \ pfnShadowSynchronizeEvent SynchronizeEvent; \ pfnShadowKeyboardEvent KeyboardEvent; \ pfnShadowUnicodeKeyboardEvent UnicodeKeyboardEvent; \ @@ -159,7 +168,7 @@ FREERDP_API int shadow_server_stop(rdpShadowServer* server); FREERDP_API int shadow_server_init(rdpShadowServer* server); FREERDP_API int shadow_server_uninit(rdpShadowServer* server); -FREERDP_API int shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors, UINT32 flags); +FREERDP_API int shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors, const char* name); FREERDP_API rdpShadowServer* shadow_server_new(); FREERDP_API void shadow_server_free(rdpShadowServer* server); diff --git a/server/shadow/Mac/mac_shadow.c b/server/shadow/Mac/mac_shadow.c index ed1e09b34..9132027ce 100644 --- a/server/shadow/Mac/mac_shadow.c +++ b/server/shadow/Mac/mac_shadow.c @@ -538,7 +538,7 @@ void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem) return NULL; } -int mac_shadow_enum_monitors(macShadowSubsystem* subsystem, MONITOR_DEF* monitors, int maxMonitors) +int mac_shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors) { int index; size_t wide, high; @@ -621,7 +621,7 @@ void mac_shadow_subsystem_free(macShadowSubsystem* subsystem) free(subsystem); } -macShadowSubsystem* mac_shadow_subsystem_new(rdpShadowServer* server) +macShadowSubsystem* mac_shadow_subsystem_new() { macShadowSubsystem* subsystem; @@ -630,14 +630,6 @@ macShadowSubsystem* mac_shadow_subsystem_new(rdpShadowServer* server) if (!subsystem) return NULL; - subsystem->Init = (pfnShadowSubsystemInit) mac_shadow_subsystem_init; - subsystem->Uninit = (pfnShadowSubsystemInit) mac_shadow_subsystem_uninit; - subsystem->Start = (pfnShadowSubsystemStart) mac_shadow_subsystem_start; - subsystem->Stop = (pfnShadowSubsystemStop) mac_shadow_subsystem_stop; - subsystem->Free = (pfnShadowSubsystemFree) mac_shadow_subsystem_free; - - subsystem->EnumMonitors = (pfnShadowEnumMonitors) mac_shadow_enum_monitors; - subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) mac_shadow_input_synchronize_event; subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) mac_shadow_input_keyboard_event; subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) mac_shadow_input_unicode_keyboard_event; @@ -647,7 +639,18 @@ macShadowSubsystem* mac_shadow_subsystem_new(rdpShadowServer* server) return subsystem; } -rdpShadowSubsystem* Mac_ShadowCreateSubsystem(rdpShadowServer* server) +int Mac_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints) { - return (rdpShadowSubsystem*) mac_shadow_subsystem_new(server); + pEntryPoints->New = (pfnShadowSubsystemNew) mac_shadow_subsystem_new; + pEntryPoints->Free = (pfnShadowSubsystemFree) mac_shadow_subsystem_free; + + pEntryPoints->Init = (pfnShadowSubsystemInit) mac_shadow_subsystem_init; + pEntryPoints->Uninit = (pfnShadowSubsystemInit) mac_shadow_subsystem_uninit; + + pEntryPoints->Start = (pfnShadowSubsystemStart) mac_shadow_subsystem_start; + pEntryPoints->Stop = (pfnShadowSubsystemStop) mac_shadow_subsystem_stop; + + pEntryPoints->EnumMonitors = (pfnShadowEnumMonitors) mac_shadow_enum_monitors; + + return 1; } diff --git a/server/shadow/Win/win_shadow.c b/server/shadow/Win/win_shadow.c index 6574567f4..b70b61f79 100644 --- a/server/shadow/Win/win_shadow.c +++ b/server/shadow/Win/win_shadow.c @@ -399,7 +399,7 @@ void* win_shadow_subsystem_thread(winShadowSubsystem* subsystem) #endif -int win_shadow_enum_monitors(winShadowSubsystem* subsystem, MONITOR_DEF* monitors, int maxMonitors) +int win_shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors) { HDC hdc; int index; @@ -440,25 +440,10 @@ int win_shadow_enum_monitors(winShadowSubsystem* subsystem, MONITOR_DEF* monitor int win_shadow_subsystem_init(winShadowSubsystem* subsystem) { - HDC hdc; int status; - DWORD iDevNum = 0; MONITOR_DEF* virtualScreen; - DISPLAY_DEVICE DisplayDevice; - ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE)); - DisplayDevice.cb = sizeof(DISPLAY_DEVICE); - - if (!EnumDisplayDevices(NULL, iDevNum, &DisplayDevice, 0)) - return -1; - - hdc = CreateDC(DisplayDevice.DeviceName, NULL, NULL, NULL); - - subsystem->width = GetDeviceCaps(hdc, HORZRES); - subsystem->height = GetDeviceCaps(hdc, VERTRES); - subsystem->bpp = GetDeviceCaps(hdc, BITSPIXEL); - - DeleteDC(hdc); + subsystem->numMonitors = win_shadow_enum_monitors(subsystem->monitors, 16); #if defined(WITH_WDS_API) status = win_shadow_wds_init(subsystem); @@ -474,16 +459,6 @@ int win_shadow_subsystem_init(winShadowSubsystem* subsystem) virtualScreen->bottom = subsystem->height; virtualScreen->flags = 1; - if (subsystem->numMonitors < 1) - { - subsystem->numMonitors = 1; - subsystem->monitors[0].left = virtualScreen->left; - subsystem->monitors[0].top = virtualScreen->top; - subsystem->monitors[0].right = virtualScreen->right; - subsystem->monitors[0].bottom = virtualScreen->bottom; - subsystem->monitors[0].flags = 1; - } - WLog_INFO(TAG, "width: %d height: %d", subsystem->width, subsystem->height); return 1; @@ -535,7 +510,7 @@ void win_shadow_subsystem_free(winShadowSubsystem* subsystem) free(subsystem); } -winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server) +winShadowSubsystem* win_shadow_subsystem_new() { winShadowSubsystem* subsystem; @@ -544,14 +519,6 @@ winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server) if (!subsystem) return NULL; - subsystem->Init = (pfnShadowSubsystemInit) win_shadow_subsystem_init; - subsystem->Uninit = (pfnShadowSubsystemInit) win_shadow_subsystem_uninit; - subsystem->Start = (pfnShadowSubsystemStart) win_shadow_subsystem_start; - subsystem->Stop = (pfnShadowSubsystemStop) win_shadow_subsystem_stop; - subsystem->Free = (pfnShadowSubsystemFree) win_shadow_subsystem_free; - - subsystem->EnumMonitors = (pfnShadowEnumMonitors) win_shadow_enum_monitors; - subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) win_shadow_input_synchronize_event; subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) win_shadow_input_keyboard_event; subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) win_shadow_input_unicode_keyboard_event; @@ -561,7 +528,18 @@ winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server) return subsystem; } -rdpShadowSubsystem* Win_ShadowCreateSubsystem(rdpShadowServer* server) +int Win_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints) { - return (rdpShadowSubsystem*) win_shadow_subsystem_new(server); + pEntryPoints->New = (pfnShadowSubsystemNew) win_shadow_subsystem_new; + pEntryPoints->Free = (pfnShadowSubsystemFree) win_shadow_subsystem_free; + + pEntryPoints->Init = (pfnShadowSubsystemInit) win_shadow_subsystem_init; + pEntryPoints->Uninit = (pfnShadowSubsystemInit) win_shadow_subsystem_uninit; + + pEntryPoints->Start = (pfnShadowSubsystemStart) win_shadow_subsystem_start; + pEntryPoints->Stop = (pfnShadowSubsystemStop) win_shadow_subsystem_stop; + + pEntryPoints->EnumMonitors = (pfnShadowEnumMonitors) win_shadow_enum_monitors; + + return 1; } diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index d25176e10..1c0b5e822 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -781,39 +781,62 @@ int x11_shadow_xshm_init(x11ShadowSubsystem* subsystem) return 1; } -int x11_shadow_enum_monitors(x11ShadowSubsystem* subsystem, MONITOR_DEF* monitors, int maxMonitors) +int x11_shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors) { int index; + Display* display; + int displayWidth; + int displayHeight; int numMonitors = 0; MONITOR_DEF* monitor; -#ifdef WITH_XINERAMA - if (x11_shadow_xinerama_init(subsystem) > 0) + if (!getenv("DISPLAY")) + setenv("DISPLAY", ":0", 1); + + display = XOpenDisplay(NULL); + + if (!display) { + WLog_ERR(TAG, "failed to open display: %s", XDisplayName(NULL)); + return -1; + } + + displayWidth = WidthOfScreen(DefaultScreenOfDisplay(display)); + displayHeight = HeightOfScreen(DefaultScreenOfDisplay(display)); + +#ifdef WITH_XINERAMA + { + int major, minor; + int xinerama_event; + int xinerama_error; XineramaScreenInfo* screen; XineramaScreenInfo* screens; - screens = XineramaQueryScreens(subsystem->display, &numMonitors); - - if (numMonitors > maxMonitors) - numMonitors = maxMonitors; - - if (screens && (numMonitors > 0)) + if (XineramaQueryExtension(display, &xinerama_event, &xinerama_error) && + XDamageQueryVersion(display, &major, &minor) && XineramaIsActive(display)) { - for (index = 0; index < numMonitors; index++) + screens = XineramaQueryScreens(display, &numMonitors); + + if (numMonitors > maxMonitors) + numMonitors = maxMonitors; + + if (screens && (numMonitors > 0)) { - screen = &screens[index]; - monitor = &monitors[index]; + for (index = 0; index < numMonitors; index++) + { + screen = &screens[index]; + monitor = &monitors[index]; - monitor->left = screen->x_org; - monitor->top = screen->y_org; - monitor->right = monitor->left + screen->width; - monitor->bottom = monitor->top + screen->height; - monitor->flags = (index == 0) ? 1 : 0; + monitor->left = screen->x_org; + monitor->top = screen->y_org; + monitor->right = monitor->left + screen->width; + monitor->bottom = monitor->top + screen->height; + monitor->flags = (index == 0) ? 1 : 0; + } } - } - XFree(screens); + XFree(screens); + } } #endif @@ -822,14 +845,12 @@ int x11_shadow_enum_monitors(x11ShadowSubsystem* subsystem, MONITOR_DEF* monitor index = 0; numMonitors = 1; - x11_shadow_subsystem_base_init(subsystem); - monitor = &monitors[index]; monitor->left = 0; monitor->top = 0; - monitor->right = subsystem->width; - monitor->bottom = subsystem->height; + monitor->right = displayWidth; + monitor->bottom = displayHeight; monitor->flags = 1; } @@ -850,9 +871,9 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem) XPixmapFormatValues* pfs; MONITOR_DEF* virtualScreen; - x11_shadow_subsystem_base_init(subsystem); + subsystem->numMonitors = x11_shadow_enum_monitors(subsystem->monitors, 16); - subsystem->numMonitors = x11_shadow_enum_monitors(subsystem, subsystem->monitors, 16); + x11_shadow_subsystem_base_init(subsystem); extensions = XListExtensions(subsystem->display, &nextensions); @@ -960,16 +981,6 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem) virtualScreen->bottom = subsystem->height; virtualScreen->flags = 1; - if (subsystem->numMonitors < 1) - { - subsystem->numMonitors = 1; - subsystem->monitors[0].left = virtualScreen->left; - subsystem->monitors[0].top = virtualScreen->top; - subsystem->monitors[0].right = virtualScreen->right; - subsystem->monitors[0].bottom = virtualScreen->bottom; - subsystem->monitors[0].flags = 1; - } - WLog_INFO(TAG, "X11 Extensions: XFixes: %d Xinerama: %d XDamage: %d XShm: %d", subsystem->use_xfixes, subsystem->use_xinerama, subsystem->use_xdamage, subsystem->use_xshm); @@ -1034,7 +1045,7 @@ void x11_shadow_subsystem_free(x11ShadowSubsystem* subsystem) free(subsystem); } -x11ShadowSubsystem* x11_shadow_subsystem_new(rdpShadowServer* server) +x11ShadowSubsystem* x11_shadow_subsystem_new() { x11ShadowSubsystem* subsystem; @@ -1043,14 +1054,6 @@ x11ShadowSubsystem* x11_shadow_subsystem_new(rdpShadowServer* server) if (!subsystem) return NULL; - subsystem->Init = (pfnShadowSubsystemInit) x11_shadow_subsystem_init; - subsystem->Uninit = (pfnShadowSubsystemInit) x11_shadow_subsystem_uninit; - subsystem->Start = (pfnShadowSubsystemStart) x11_shadow_subsystem_start; - subsystem->Stop = (pfnShadowSubsystemStop) x11_shadow_subsystem_stop; - subsystem->Free = (pfnShadowSubsystemFree) x11_shadow_subsystem_free; - - subsystem->EnumMonitors = (pfnShadowEnumMonitors) x11_shadow_enum_monitors; - subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) x11_shadow_input_synchronize_event; subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) x11_shadow_input_keyboard_event; subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) x11_shadow_input_unicode_keyboard_event; @@ -1066,7 +1069,18 @@ x11ShadowSubsystem* x11_shadow_subsystem_new(rdpShadowServer* server) return subsystem; } -rdpShadowSubsystem* X11_ShadowCreateSubsystem(rdpShadowServer* server) +int X11_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints) { - return (rdpShadowSubsystem*) x11_shadow_subsystem_new(server); + pEntryPoints->New = (pfnShadowSubsystemNew) x11_shadow_subsystem_new; + pEntryPoints->Free = (pfnShadowSubsystemFree) x11_shadow_subsystem_free; + + pEntryPoints->Init = (pfnShadowSubsystemInit) x11_shadow_subsystem_init; + pEntryPoints->Uninit = (pfnShadowSubsystemInit) x11_shadow_subsystem_uninit; + + pEntryPoints->Start = (pfnShadowSubsystemStart) x11_shadow_subsystem_start; + pEntryPoints->Stop = (pfnShadowSubsystemStop) x11_shadow_subsystem_stop; + + pEntryPoints->EnumMonitors = (pfnShadowEnumMonitors) x11_shadow_enum_monitors; + + return 1; } diff --git a/server/shadow/shadow_server.c b/server/shadow/shadow_server.c index 430063322..792102fed 100644 --- a/server/shadow/shadow_server.c +++ b/server/shadow/shadow_server.c @@ -304,10 +304,7 @@ void* shadow_server_thread(rdpShadowServer* server) StopEvent = server->StopEvent; subsystem = server->subsystem; - if (subsystem->Start) - { - subsystem->Start(subsystem); - } + shadow_subsystem_start(server->subsystem); while (1) { @@ -341,10 +338,7 @@ void* shadow_server_thread(rdpShadowServer* server) listener->Close(listener); - if (subsystem->Stop) - { - subsystem->Stop(subsystem); - } + shadow_subsystem_stop(server->subsystem); ExitThread(0); @@ -560,7 +554,7 @@ int shadow_server_init(rdpShadowServer* server) server->listener->info = (void*) server; server->listener->PeerAccepted = shadow_client_accepted; - server->subsystem = shadow_subsystem_new(0); + server->subsystem = shadow_subsystem_new(NULL); if (!server->subsystem) return -1; @@ -580,12 +574,6 @@ int shadow_server_uninit(rdpShadowServer* server) server->listener = NULL; } - if (server->subsystem) - { - server->subsystem->Free(server->subsystem); - server->subsystem = NULL; - } - if (server->CertificateFile) { free(server->CertificateFile); @@ -609,26 +597,6 @@ int shadow_server_uninit(rdpShadowServer* server) return 1; } -int shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors, UINT32 flags) -{ - int numMonitors = 0; - rdpShadowSubsystem* subsystem; - - subsystem = shadow_subsystem_new(flags); - - if (!subsystem) - return -1; - - if (!subsystem->EnumMonitors) - return -1; - - numMonitors = subsystem->EnumMonitors(subsystem, monitors, maxMonitors); - - shadow_subsystem_free(subsystem); - - return numMonitors; -} - rdpShadowServer* shadow_server_new() { rdpShadowServer* server; @@ -658,7 +626,7 @@ void shadow_server_free(rdpShadowServer* server) server->clients = NULL; } - shadow_server_uninit(server); + shadow_subsystem_free(server->subsystem); free(server); } diff --git a/server/shadow/shadow_subsystem.c b/server/shadow/shadow_subsystem.c index 42211374f..9d41a8f7e 100644 --- a/server/shadow/shadow_subsystem.c +++ b/server/shadow/shadow_subsystem.c @@ -24,45 +24,110 @@ #include "shadow_subsystem.h" -#ifdef WITH_SHADOW_X11 -extern rdpShadowSubsystem* X11_ShadowCreateSubsystem(rdpShadowServer* server); -#endif - -#ifdef WITH_SHADOW_MAC -extern rdpShadowSubsystem* Mac_ShadowCreateSubsystem(rdpShadowServer* server); -#endif - -#ifdef WITH_SHADOW_WIN -extern rdpShadowSubsystem* Win_ShadowCreateSubsystem(rdpShadowServer* server); -#endif - -rdpShadowSubsystem* shadow_subsystem_new(UINT32 flags) +struct _RDP_SHADOW_SUBSYSTEM { - rdpShadowSubsystem* subsystem = NULL; - pfnShadowCreateSubsystem CreateSubsystem = NULL; + const char* name; + pfnShadowSubsystemEntry entry; +}; +typedef struct _RDP_SHADOW_SUBSYSTEM RDP_SHADOW_SUBSYSTEM; + #ifdef WITH_SHADOW_X11 - CreateSubsystem = X11_ShadowCreateSubsystem; +extern int X11_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints); #endif #ifdef WITH_SHADOW_MAC - CreateSubsystem = Mac_ShadowCreateSubsystem; +extern int Mac_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints); #endif #ifdef WITH_SHADOW_WIN - CreateSubsystem = Win_ShadowCreateSubsystem; +extern int Win_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints); #endif - if (CreateSubsystem) - subsystem = CreateSubsystem(NULL); + +static RDP_SHADOW_SUBSYSTEM g_Subsystems[] = +{ + +#ifdef WITH_SHADOW_X11 + { "X11", X11_ShadowSubsystemEntry }, +#endif + +#ifdef WITH_SHADOW_MAC + { "Mac", Mac_ShadowSubsystemEntry }, +#endif + +#ifdef WITH_SHADOW_WIN + { "Win", Win_ShadowSubsystemEntry }, +#endif + + { "", NULL } +}; + +static int g_SubsystemCount = (sizeof(g_Subsystems) / sizeof(g_Subsystems[0])); + +pfnShadowSubsystemEntry shadow_subsystem_load_static_entry(const char* name) +{ + int index; + + if (!name) + { + for (index = 0; index < g_SubsystemCount; index++) + { + if (g_Subsystems[index].name) + return g_Subsystems[index].entry; + } + } + + for (index = 0; index < g_SubsystemCount; index++) + { + if (strcmp(name, g_Subsystems[index].name) == 0) + return g_Subsystems[index].entry; + } + + return NULL; +} + +int shadow_subsystem_load_entry_points(RDP_SHADOW_ENTRY_POINTS* pEntryPoints, const char* name) +{ + pfnShadowSubsystemEntry entry; + + entry = shadow_subsystem_load_static_entry(name); + + if (!entry) + return -1; + + ZeroMemory(pEntryPoints, sizeof(RDP_SHADOW_ENTRY_POINTS)); + + if (entry(pEntryPoints) < 0) + return -1; + + return 1; +} + +rdpShadowSubsystem* shadow_subsystem_new(const char* name) +{ + RDP_SHADOW_ENTRY_POINTS ep; + rdpShadowSubsystem* subsystem = NULL; + + shadow_subsystem_load_entry_points(&ep, name); + + if (!ep.New) + return NULL; + + subsystem = ep.New(); + + if (!subsystem) + return NULL; + + CopyMemory(&(subsystem->ep), &ep, sizeof(RDP_SHADOW_ENTRY_POINTS)); return subsystem; } void shadow_subsystem_free(rdpShadowSubsystem* subsystem) { - if (subsystem->Free) - subsystem->Free(subsystem); + if (subsystem->ep.Free) + subsystem->ep.Free(subsystem); } int shadow_subsystem_init(rdpShadowSubsystem* subsystem, rdpShadowServer* server) @@ -76,19 +141,19 @@ int shadow_subsystem_init(rdpShadowSubsystem* subsystem, rdpShadowServer* server subsystem->MsgPipe = MessagePipe_New(); region16_init(&(subsystem->invalidRegion)); - if (!subsystem->Init) + if (!subsystem->ep.Init) return -1; - if (subsystem->Init) - status = subsystem->Init(subsystem); + if (subsystem->ep.Init) + status = subsystem->ep.Init(subsystem); return status; } void shadow_subsystem_uninit(rdpShadowSubsystem* subsystem) { - if (subsystem->Uninit) - subsystem->Uninit(subsystem); + if (subsystem->ep.Uninit) + subsystem->ep.Uninit(subsystem); if (subsystem->updateEvent) { @@ -107,3 +172,40 @@ void shadow_subsystem_uninit(rdpShadowSubsystem* subsystem) region16_uninit(&(subsystem->invalidRegion)); } } + +int shadow_subsystem_start(rdpShadowSubsystem* subsystem) +{ + int status; + + if (!subsystem->ep.Start) + return -1; + + status = subsystem->ep.Start(subsystem); + + return status; +} + +int shadow_subsystem_stop(rdpShadowSubsystem* subsystem) +{ + int status; + + if (!subsystem->ep.Stop) + return -1; + + status = subsystem->ep.Stop(subsystem); + + return status; +} + +int shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors, const char* name) +{ + int numMonitors = 0; + RDP_SHADOW_ENTRY_POINTS ep; + + if (shadow_subsystem_load_entry_points(&ep, name) < 0) + return -1; + + numMonitors = ep.EnumMonitors(monitors, maxMonitors); + + return numMonitors; +} diff --git a/server/shadow/shadow_subsystem.h b/server/shadow/shadow_subsystem.h index e22b545db..9e61d6ce3 100644 --- a/server/shadow/shadow_subsystem.h +++ b/server/shadow/shadow_subsystem.h @@ -30,12 +30,15 @@ extern "C" { #endif -rdpShadowSubsystem* shadow_subsystem_new(UINT32 flags); +rdpShadowSubsystem* shadow_subsystem_new(const char* name); void shadow_subsystem_free(rdpShadowSubsystem* subsystem); int shadow_subsystem_init(rdpShadowSubsystem* subsystem, rdpShadowServer* server); void shadow_subsystem_uninit(rdpShadowSubsystem* subsystem); +int shadow_subsystem_start(rdpShadowSubsystem* subsystem); +int shadow_subsystem_stop(rdpShadowSubsystem* subsystem); + #ifdef __cplusplus } #endif From aa7571648cdee6dab53d9df2cab6838459a3b9d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 18 Sep 2014 17:22:44 -0400 Subject: [PATCH 18/21] shadow: start using message queue --- include/freerdp/server/shadow.h | 1 + server/shadow/CMakeLists.txt | 2 +- server/shadow/X11/x11_shadow.c | 100 ++++++++++++++++++++++---------- server/shadow/shadow_client.c | 39 ++++++++----- 4 files changed, 95 insertions(+), 47 deletions(-) diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h index eee56432d..496342965 100644 --- a/include/freerdp/server/shadow.h +++ b/include/freerdp/server/shadow.h @@ -85,6 +85,7 @@ struct rdp_shadow_client rdpShadowServer* server; rdpShadowSurface* lobby; rdpShadowEncoder* encoder; + rdpShadowSubsystem* subsystem; HANDLE vcm; EncomspServerContext* encomsp; diff --git a/server/shadow/CMakeLists.txt b/server/shadow/CMakeLists.txt index 5c25c415c..3ce55436f 100644 --- a/server/shadow/CMakeLists.txt +++ b/server/shadow/CMakeLists.txt @@ -199,7 +199,7 @@ list(APPEND ${MODULE_PREFIX}_LIBS winpr-makecert-tool) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) -install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT server) +install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT server) set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/shadow") diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index 1c0b5e822..2dbdcec1d 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -431,6 +431,8 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) rdpShadowServer* server; rdpShadowSurface* surface; RECTANGLE_16 invalidRect; + RECTANGLE_16 surfaceRect; + const RECTANGLE_16 *extents; server = subsystem->server; surface = server->surface; @@ -441,6 +443,11 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) if (count < 1) return 1; + surfaceRect.left = 0; + surfaceRect.top = 0; + surfaceRect.right = surface->width; + surfaceRect.bottom = surface->height; + if (subsystem->use_xshm) { XLockDisplay(subsystem->display); @@ -457,20 +464,23 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height, (BYTE*) &(image->data[surface->width * 4]), image->bytes_per_line, &invalidRect); - if (status > 0) + region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); + region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect); + + if (!region16_is_empty(&(subsystem->invalidRegion))) { - x = invalidRect.left; - y = invalidRect.top; - width = invalidRect.right - invalidRect.left; - height = invalidRect.bottom - invalidRect.top; + extents = region16_extents(&(subsystem->invalidRegion)); + + x = extents->left; + y = extents->top; + width = extents->right - extents->left; + height = extents->bottom - extents->top; freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, x - surface->x, y - surface->y, width, height, (BYTE*) image->data, PIXEL_FORMAT_XRGB32, image->bytes_per_line, x, y, NULL); - region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); - x11_shadow_blend_cursor(subsystem); count = ArrayList_Count(server->clients); @@ -500,20 +510,23 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height, (BYTE*) image->data, image->bytes_per_line, &invalidRect); - if (status > 0) + region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); + region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect); + + if (!region16_is_empty(&(subsystem->invalidRegion))) { - x = invalidRect.left; - y = invalidRect.top; - width = invalidRect.right - invalidRect.left; - height = invalidRect.bottom - invalidRect.top; + extents = region16_extents(&(subsystem->invalidRegion)); + + x = extents->left; + y = extents->top; + width = extents->right - extents->left; + height = extents->bottom - extents->top; 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, NULL); - region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); - x11_shadow_blend_cursor(subsystem); count = ArrayList_Count(server->clients); @@ -548,13 +561,14 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem) DWORD dwInterval; UINT64 frameTime; HANDLE events[32]; - HANDLE StopEvent; + wMessage message; + wMessagePipe* MsgPipe; - StopEvent = subsystem->server->StopEvent; + MsgPipe = subsystem->MsgPipe; nCount = 0; - events[nCount++] = StopEvent; events[nCount++] = subsystem->event; + events[nCount++] = MessageQueue_Event(MsgPipe->In); fps = 16; dwInterval = 1000 / fps; @@ -567,9 +581,25 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem) status = WaitForMultipleObjects(nCount, events, FALSE, dwTimeout); - if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0) + if (WaitForSingleObject(MessageQueue_Event(MsgPipe->In), 0) == WAIT_OBJECT_0) { - break; + if (MessageQueue_Peek(MsgPipe->In, &message, TRUE)) + { + if (message.id == WMQ_QUIT) + break; + + if (message.id == 1) + { + RECTANGLE_16 refreshRect; + + refreshRect.left = 0; + refreshRect.top = 0; + refreshRect.right = subsystem->width; + refreshRect.bottom = subsystem->height; + + region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &refreshRect); + } + } } if (WaitForSingleObject(subsystem->event, 0) == WAIT_OBJECT_0) @@ -1015,12 +1045,10 @@ int x11_shadow_subsystem_uninit(x11ShadowSubsystem* subsystem) int x11_shadow_subsystem_start(x11ShadowSubsystem* subsystem) { - HANDLE thread; - if (!subsystem) return -1; - thread = CreateThread(NULL, 0, + subsystem->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) x11_shadow_subsystem_thread, (void*) subsystem, 0, NULL); @@ -1032,19 +1060,17 @@ int x11_shadow_subsystem_stop(x11ShadowSubsystem* subsystem) if (!subsystem) return -1; + if (subsystem->thread) + { + MessageQueue_PostQuit(subsystem->MsgPipe->In, 0); + WaitForSingleObject(subsystem->thread, INFINITE); + CloseHandle(subsystem->thread); + subsystem->thread = NULL; + } + return 1; } -void x11_shadow_subsystem_free(x11ShadowSubsystem* subsystem) -{ - if (!subsystem) - return; - - x11_shadow_subsystem_uninit(subsystem); - - free(subsystem); -} - x11ShadowSubsystem* x11_shadow_subsystem_new() { x11ShadowSubsystem* subsystem; @@ -1069,6 +1095,16 @@ x11ShadowSubsystem* x11_shadow_subsystem_new() return subsystem; } +void x11_shadow_subsystem_free(x11ShadowSubsystem* subsystem) +{ + if (!subsystem) + return; + + x11_shadow_subsystem_uninit(subsystem); + + free(subsystem); +} + int X11_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints) { pEntryPoints->New = (pfnShadowSubsystemNew) x11_shadow_subsystem_new; diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index 6728ee82b..6aa5b6a02 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -40,6 +40,7 @@ void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client) server = (rdpShadowServer*) peer->ContextExtra; client->server = server; + client->subsystem = server->subsystem; settings = peer->settings; @@ -165,6 +166,24 @@ BOOL shadow_client_post_connect(freerdp_peer* peer) return TRUE; } +void shadow_client_refresh_rect(rdpShadowClient* client, BYTE count, RECTANGLE_16* areas) +{ + wMessagePipe* MsgPipe = client->subsystem->MsgPipe; + + printf("RefreshRect: %d\n", count); + + MessageQueue_Post(MsgPipe->In, (void*) client, 1, NULL, NULL); +} + +void shadow_client_suppress_output(rdpShadowClient* client, BYTE allow, RECTANGLE_16* area) +{ + wMessagePipe* MsgPipe = client->subsystem->MsgPipe; + + printf("SuppressOutput: %d\n", allow); + + MessageQueue_Post(MsgPipe->In, (void*) client, 2, NULL, NULL); +} + BOOL shadow_client_activate(freerdp_peer* peer) { rdpShadowClient* client; @@ -176,6 +195,8 @@ BOOL shadow_client_activate(freerdp_peer* peer) shadow_encoder_reset(client->encoder); + shadow_client_refresh_rect(client, 0, NULL); + return TRUE; } @@ -194,16 +215,6 @@ void shadow_client_surface_frame_acknowledge(rdpShadowClient* client, UINT32 fra } } -void shadow_client_refresh_rect(rdpContext* context, BYTE count, RECTANGLE_16* areas) -{ - -} - -void shadow_client_suppress_output(rdpShadowClient* client, BYTE allow, RECTANGLE_16* area) -{ - -} - int shadow_client_send_surface_frame_marker(rdpShadowClient* client, UINT32 action, UINT32 id) { SURFACE_FRAME_MARKER surfaceFrameMarker; @@ -663,6 +674,7 @@ void* shadow_client_thread(rdpShadowClient* client) HANDLE ChannelEvent; HANDLE UpdateEvent; freerdp_peer* peer; + rdpContext* context; rdpSettings* settings; rdpShadowServer* server; rdpShadowScreen* screen; @@ -674,7 +686,8 @@ void* shadow_client_thread(rdpShadowClient* client) encoder = client->encoder; subsystem = server->subsystem; - peer = ((rdpContext*) client)->peer; + context = (rdpContext*) client; + peer = context->peer; settings = peer->settings; peer->Capabilities = shadow_client_capabilities; @@ -685,11 +698,9 @@ void* shadow_client_thread(rdpShadowClient* client) peer->Initialize(peer); - peer->update->SurfaceFrameAcknowledge = (pSurfaceFrameAcknowledge) - shadow_client_surface_frame_acknowledge; - peer->update->RefreshRect = (pRefreshRect) shadow_client_refresh_rect; peer->update->SuppressOutput = (pSuppressOutput) shadow_client_suppress_output; + peer->update->SurfaceFrameAcknowledge = (pSurfaceFrameAcknowledge) shadow_client_surface_frame_acknowledge; StopEvent = client->StopEvent; UpdateEvent = subsystem->updateEvent; From 09fc388e033c3d88ea0bad39f9bd161807516a4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 18 Sep 2014 22:18:58 -0400 Subject: [PATCH 19/21] shadow: add RefreshRect/SuppressOutput support --- include/freerdp/codec/region.h | 7 + include/freerdp/server/shadow.h | 6 +- libfreerdp/codec/region.c | 6 + libfreerdp/core/gcc.c | 11 +- server/shadow/X11/x11_shadow.c | 213 +++++++++--------- server/shadow/shadow_client.c | 63 +++++- server/shadow/shadow_subsystem.c | 17 +- server/shadow/shadow_subsystem.h | 17 +- .../libwinpr/utils/collections/MessageQueue.c | 1 + 9 files changed, 210 insertions(+), 131 deletions(-) diff --git a/include/freerdp/codec/region.h b/include/freerdp/codec/region.h index 44bfb2558..bced79140 100644 --- a/include/freerdp/codec/region.h +++ b/include/freerdp/codec/region.h @@ -43,6 +43,13 @@ struct _REGION16 { }; typedef struct _REGION16 REGION16; +/** computes if two rectangles are equal + * @param r1 first rectangle + * @param r2 second rectangle + * @return if the two rectangles are equal + */ +FREERDP_API BOOL rectangles_equal(const RECTANGLE_16 *r1, const RECTANGLE_16 *r2); + /** computes if two rectangles intersect * @param r1 first rectangle * @param r2 second rectangle diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h index 496342965..f76f5e2f7 100644 --- a/include/freerdp/server/shadow.h +++ b/include/freerdp/server/shadow.h @@ -50,7 +50,7 @@ typedef struct rdp_shadow_subsystem rdpShadowSubsystem; typedef struct _RDP_SHADOW_ENTRY_POINTS RDP_SHADOW_ENTRY_POINTS; typedef int (*pfnShadowSubsystemEntry)(RDP_SHADOW_ENTRY_POINTS* pEntryPoints); -typedef rdpShadowSubsystem* (*pfnShadowSubsystemNew)(); +typedef rdpShadowSubsystem* (*pfnShadowSubsystemNew)(void); typedef void (*pfnShadowSubsystemFree)(rdpShadowSubsystem* subsystem); typedef int (*pfnShadowSubsystemInit)(rdpShadowSubsystem* subsystem); @@ -61,9 +61,6 @@ typedef int (*pfnShadowSubsystemStop)(rdpShadowSubsystem* subsystem); typedef int (*pfnShadowEnumMonitors)(MONITOR_DEF* monitors, int maxMonitors); -typedef int (*pfnShadowSurfaceCopy)(rdpShadowSubsystem* subsystem); -typedef int (*pfnShadowSurfaceUpdate)(rdpShadowSubsystem* subsystem, REGION16* subRect); - typedef int (*pfnShadowSynchronizeEvent)(rdpShadowSubsystem* subsystem, UINT32 flags); typedef int (*pfnShadowKeyboardEvent)(rdpShadowSubsystem* subsystem, UINT16 flags, UINT16 code); typedef int (*pfnShadowUnicodeKeyboardEvent)(rdpShadowSubsystem* subsystem, UINT16 flags, UINT16 code); @@ -139,6 +136,7 @@ struct _RDP_SHADOW_ENTRY_POINTS MONITOR_DEF monitors[16]; \ MONITOR_DEF virtualScreen; \ HANDLE updateEvent; \ + BOOL suppressOutput; \ REGION16 invalidRegion; \ wMessagePipe* MsgPipe; \ SYNCHRONIZATION_BARRIER barrier; \ diff --git a/libfreerdp/codec/region.c b/libfreerdp/codec/region.c index c1d433760..79f00147a 100644 --- a/libfreerdp/codec/region.c +++ b/libfreerdp/codec/region.c @@ -143,6 +143,12 @@ BOOL region16_is_empty(const REGION16 *region) return (region->data->nbRects == 0); } +BOOL rectangles_equal(const RECTANGLE_16 *r1, const RECTANGLE_16 *r2) +{ + return ((r1->left == r2->left) && (r1->top == r2->top) && + (r1->right == r2->right) && (r1->bottom == r2->bottom)) ? TRUE : FALSE; +} + BOOL rectangles_intersects(const RECTANGLE_16 *r1, const RECTANGLE_16 *r2) { RECTANGLE_16 tmp; diff --git a/libfreerdp/core/gcc.c b/libfreerdp/core/gcc.c index 23b14174c..79a966f8d 100644 --- a/libfreerdp/core/gcc.c +++ b/libfreerdp/core/gcc.c @@ -388,7 +388,7 @@ BOOL gcc_read_client_data_blocks(wStream* s, rdpMcs* mcs, int length) if (endPos != (begPos + blockLength)) { WLog_ERR(TAG, "Error parsing GCC client data block 0x%04X: Actual Offset: %d Expected Offset: %d", - type, endPos, begPos + blockLength); + type, endPos, begPos + blockLength); } length -= blockLength; @@ -1337,6 +1337,15 @@ BOOL gcc_read_client_cluster_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) if (flags & REDIRECTED_SESSIONID_FIELD_VALID) settings->RedirectedSessionId = redirectedSessionId; + if (blockLength != 8) + { + if (Stream_GetRemainingLength(s) >= (blockLength - 8)) + { + /* The old Microsoft Mac RDP client can send a pad here */ + Stream_Seek(s, (blockLength - 8)); + } + } + return TRUE; } diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index 2dbdcec1d..1edf22abc 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -288,23 +288,6 @@ void x11_shadow_validate_region(x11ShadowSubsystem* subsystem, int x, int y, int #endif } -int x11_shadow_invalidate_region(x11ShadowSubsystem* subsystem, int x, int y, int width, int height) -{ - rdpShadowServer* server; - RECTANGLE_16 invalidRect; - - server = subsystem->server; - - invalidRect.left = x; - invalidRect.top = y; - invalidRect.right = x + width; - invalidRect.bottom = y + height; - - region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); - - return 1; -} - int x11_shadow_blend_cursor(x11ShadowSubsystem* subsystem) { int x, y; @@ -443,110 +426,123 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) if (count < 1) return 1; + if ((count == 1) && subsystem->suppressOutput) + return 1; + surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = surface->width; surfaceRect.bottom = surface->height; + XLockDisplay(subsystem->display); + if (subsystem->use_xshm) { - XLockDisplay(subsystem->display); + image = subsystem->fb_image; XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap, subsystem->xshm_gc, 0, 0, subsystem->width, subsystem->height, 0, 0); - XSync(subsystem->display, False); - - XUnlockDisplay(subsystem->display); - - image = subsystem->fb_image; - status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height, (BYTE*) &(image->data[surface->width * 4]), image->bytes_per_line, &invalidRect); - - region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); - region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect); - - if (!region16_is_empty(&(subsystem->invalidRegion))) - { - extents = region16_extents(&(subsystem->invalidRegion)); - - x = extents->left; - y = extents->top; - width = extents->right - extents->left; - height = extents->bottom - extents->top; - - freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, - surface->scanline, x - surface->x, y - surface->y, width, height, - (BYTE*) image->data, PIXEL_FORMAT_XRGB32, - image->bytes_per_line, x, y, NULL); - - x11_shadow_blend_cursor(subsystem); - - count = ArrayList_Count(server->clients); - - InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1); - - SetEvent(subsystem->updateEvent); - - EnterSynchronizationBarrier(&(subsystem->barrier), 0); - - DeleteSynchronizationBarrier(&(subsystem->barrier)); - - ResetEvent(subsystem->updateEvent); - - region16_clear(&(subsystem->invalidRegion)); - } } else { - XLockDisplay(subsystem->display); - image = XGetImage(subsystem->display, subsystem->root_window, - surface->x, surface->y, surface->width, surface->height, AllPlanes, ZPixmap); - - XUnlockDisplay(subsystem->display); + surface->x, surface->y, surface->width, surface->height, AllPlanes, ZPixmap); status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height, (BYTE*) image->data, image->bytes_per_line, &invalidRect); - - region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); - region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect); - - if (!region16_is_empty(&(subsystem->invalidRegion))) - { - extents = region16_extents(&(subsystem->invalidRegion)); - - x = extents->left; - y = extents->top; - width = extents->right - extents->left; - height = extents->bottom - extents->top; - - 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, NULL); - - x11_shadow_blend_cursor(subsystem); - - count = ArrayList_Count(server->clients); - - InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1); - - SetEvent(subsystem->updateEvent); - - EnterSynchronizationBarrier(&(subsystem->barrier), 0); - - DeleteSynchronizationBarrier(&(subsystem->barrier)); - - ResetEvent(subsystem->updateEvent); - - region16_clear(&(subsystem->invalidRegion)); - } - - XDestroyImage(image); } + XSync(subsystem->display, False); + + XUnlockDisplay(subsystem->display); + + region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); + region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect); + + if (!region16_is_empty(&(subsystem->invalidRegion))) + { + extents = region16_extents(&(subsystem->invalidRegion)); + + x = extents->left; + y = extents->top; + width = extents->right - extents->left; + height = extents->bottom - extents->top; + + 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, NULL); + + x11_shadow_blend_cursor(subsystem); + + count = ArrayList_Count(server->clients); + + InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1); + + SetEvent(subsystem->updateEvent); + + EnterSynchronizationBarrier(&(subsystem->barrier), 0); + + DeleteSynchronizationBarrier(&(subsystem->barrier)); + + ResetEvent(subsystem->updateEvent); + + region16_clear(&(subsystem->invalidRegion)); + } + + if (!subsystem->use_xshm) + XDestroyImage(image); + + return 1; +} + +int x11_shadow_subsystem_process_message(x11ShadowSubsystem* subsystem, wMessage* message) +{ + if (message->id == SHADOW_MSG_IN_REFRESH_OUTPUT_ID) + { + UINT32 index; + SHADOW_MSG_IN_REFRESH_OUTPUT* msg = (SHADOW_MSG_IN_REFRESH_OUTPUT*) message->wParam; + + if (msg->numRects) + { + for (index = 0; index < msg->numRects; index++) + { + region16_union_rect(&(subsystem->invalidRegion), + &(subsystem->invalidRegion), &msg->rects[index]); + } + } + else + { + RECTANGLE_16 refreshRect; + + refreshRect.left = 0; + refreshRect.top = 0; + refreshRect.right = subsystem->width; + refreshRect.bottom = subsystem->height; + + region16_union_rect(&(subsystem->invalidRegion), + &(subsystem->invalidRegion), &refreshRect); + } + } + else if (message->id == SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID) + { + SHADOW_MSG_IN_SUPPRESS_OUTPUT* msg = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) message->wParam; + + subsystem->suppressOutput = (msg->allow) ? FALSE : TRUE; + + if (msg->allow) + { + region16_union_rect(&(subsystem->invalidRegion), + &(subsystem->invalidRegion), &(msg->rect)); + } + } + + if (message->Free) + message->Free(message); + return 1; } @@ -588,24 +584,17 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem) if (message.id == WMQ_QUIT) break; - if (message.id == 1) - { - RECTANGLE_16 refreshRect; - - refreshRect.left = 0; - refreshRect.top = 0; - refreshRect.right = subsystem->width; - refreshRect.bottom = subsystem->height; - - region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &refreshRect); - } + x11_shadow_subsystem_process_message(subsystem, &message); } } if (WaitForSingleObject(subsystem->event, 0) == WAIT_OBJECT_0) { - XNextEvent(subsystem->display, &xevent); - x11_shadow_handle_xevent(subsystem, &xevent); + if (XEventsQueued(subsystem->display, QueuedAlready)) + { + XNextEvent(subsystem->display, &xevent); + x11_shadow_handle_xevent(subsystem, &xevent); + } } if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime)) diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index 6aa5b6a02..24dab2d51 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -104,6 +104,22 @@ void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client) } } +void shadow_client_message_free(wMessage* message) +{ + if (message->id == SHADOW_MSG_IN_REFRESH_OUTPUT_ID) + { + SHADOW_MSG_IN_REFRESH_OUTPUT* wParam = (SHADOW_MSG_IN_REFRESH_OUTPUT*) message->wParam; + + free(wParam->rects); + free(wParam); + } + else if (message->id == SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID) + { + SHADOW_MSG_IN_SUPPRESS_OUTPUT* wParam = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) message->wParam; + free(wParam); + } +} + BOOL shadow_client_capabilities(freerdp_peer* peer) { return TRUE; @@ -168,20 +184,59 @@ BOOL shadow_client_post_connect(freerdp_peer* peer) void shadow_client_refresh_rect(rdpShadowClient* client, BYTE count, RECTANGLE_16* areas) { + wMessage message = { 0 }; + SHADOW_MSG_IN_REFRESH_OUTPUT* wParam; wMessagePipe* MsgPipe = client->subsystem->MsgPipe; - printf("RefreshRect: %d\n", count); + wParam = (SHADOW_MSG_IN_REFRESH_OUTPUT*) calloc(1, sizeof(SHADOW_MSG_IN_REFRESH_OUTPUT)); - MessageQueue_Post(MsgPipe->In, (void*) client, 1, NULL, NULL); + if (!wParam) + return; + + wParam->numRects = (UINT32) count; + + if (wParam->numRects) + { + wParam->rects = (RECTANGLE_16*) calloc(wParam->numRects, sizeof(RECTANGLE_16)); + + if (!wParam->rects) + return; + } + + CopyMemory(wParam->rects, areas, wParam->numRects * sizeof(RECTANGLE_16)); + + message.id = SHADOW_MSG_IN_REFRESH_OUTPUT_ID; + message.wParam = (void*) wParam; + message.lParam = NULL; + message.context = (void*) client; + message.Free = shadow_client_message_free; + + MessageQueue_Dispatch(MsgPipe->In, &message); } void shadow_client_suppress_output(rdpShadowClient* client, BYTE allow, RECTANGLE_16* area) { + wMessage message = { 0 }; + SHADOW_MSG_IN_SUPPRESS_OUTPUT* wParam; wMessagePipe* MsgPipe = client->subsystem->MsgPipe; - printf("SuppressOutput: %d\n", allow); + wParam = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) calloc(1, sizeof(SHADOW_MSG_IN_SUPPRESS_OUTPUT)); - MessageQueue_Post(MsgPipe->In, (void*) client, 2, NULL, NULL); + if (!wParam) + return; + + wParam->allow = (UINT32) allow; + + if (area) + CopyMemory(&(wParam->rect), area, sizeof(RECTANGLE_16)); + + message.id = SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID; + message.wParam = (void*) wParam; + message.lParam = NULL; + message.context = (void*) client; + message.Free = shadow_client_message_free; + + MessageQueue_Dispatch(MsgPipe->In, &message); } BOOL shadow_client_activate(freerdp_peer* peer) diff --git a/server/shadow/shadow_subsystem.c b/server/shadow/shadow_subsystem.c index 9d41a8f7e..0a08c7c1f 100644 --- a/server/shadow/shadow_subsystem.c +++ b/server/shadow/shadow_subsystem.c @@ -137,8 +137,9 @@ int shadow_subsystem_init(rdpShadowSubsystem* subsystem, rdpShadowServer* server subsystem->server = server; subsystem->selectedMonitor = server->selectedMonitor; - subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL); subsystem->MsgPipe = MessagePipe_New(); + subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + region16_init(&(subsystem->invalidRegion)); if (!subsystem->ep.Init) @@ -155,22 +156,20 @@ void shadow_subsystem_uninit(rdpShadowSubsystem* subsystem) if (subsystem->ep.Uninit) subsystem->ep.Uninit(subsystem); - if (subsystem->updateEvent) - { - CloseHandle(subsystem->updateEvent); - subsystem->updateEvent = NULL; - } - if (subsystem->MsgPipe) { MessagePipe_Free(subsystem->MsgPipe); subsystem->MsgPipe = NULL; } - if (subsystem->invalidRegion.data) + if (subsystem->updateEvent) { - region16_uninit(&(subsystem->invalidRegion)); + CloseHandle(subsystem->updateEvent); + subsystem->updateEvent = NULL; } + + if (subsystem->invalidRegion.data) + region16_uninit(&(subsystem->invalidRegion)); } int shadow_subsystem_start(rdpShadowSubsystem* subsystem) diff --git a/server/shadow/shadow_subsystem.h b/server/shadow/shadow_subsystem.h index 9e61d6ce3..2ddbce864 100644 --- a/server/shadow/shadow_subsystem.h +++ b/server/shadow/shadow_subsystem.h @@ -24,7 +24,22 @@ #include #include -#include "shadow_subsystem.h" +#define SHADOW_MSG_IN_REFRESH_OUTPUT_ID 1001 +#define SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID 1002 + +struct _SHADOW_MSG_IN_REFRESH_OUTPUT +{ + UINT32 numRects; + RECTANGLE_16* rects; +}; +typedef struct _SHADOW_MSG_IN_REFRESH_OUTPUT SHADOW_MSG_IN_REFRESH_OUTPUT; + +struct _SHADOW_MSG_IN_SUPPRESS_OUTPUT +{ + BOOL allow; + RECTANGLE_16 rect; +}; +typedef struct _SHADOW_MSG_IN_SUPPRESS_OUTPUT SHADOW_MSG_IN_SUPPRESS_OUTPUT; #ifdef __cplusplus extern "C" { diff --git a/winpr/libwinpr/utils/collections/MessageQueue.c b/winpr/libwinpr/utils/collections/MessageQueue.c index b4dc6c295..8b8ec1e15 100644 --- a/winpr/libwinpr/utils/collections/MessageQueue.c +++ b/winpr/libwinpr/utils/collections/MessageQueue.c @@ -111,6 +111,7 @@ void MessageQueue_Post(wMessageQueue* queue, void* context, UINT32 type, void* w message.id = type; message.wParam = wParam; message.lParam = lParam; + message.Free = NULL; MessageQueue_Dispatch(queue, &message); } From aa2e6dacbbc8c72e209701347aa12b87c0c9bb6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 19 Sep 2014 12:06:12 -0400 Subject: [PATCH 20/21] shadow: fix frame acks + bitmap negotiation --- include/freerdp/server/shadow.h | 1 + libfreerdp/core/capabilities.c | 13 +++++++++++-- server/shadow/X11/x11_shadow.c | 23 ++++++++++++++++++----- server/shadow/shadow_client.c | 2 +- server/shadow/shadow_encoder.c | 12 +++++++++--- server/shadow/shadow_encoder.h | 3 ++- 6 files changed, 42 insertions(+), 12 deletions(-) diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h index f76f5e2f7..46e9e17ed 100644 --- a/include/freerdp/server/shadow.h +++ b/include/freerdp/server/shadow.h @@ -132,6 +132,7 @@ struct _RDP_SHADOW_ENTRY_POINTS RDP_SHADOW_ENTRY_POINTS ep; \ HANDLE event; \ int numMonitors; \ + int captureFrameRate; \ int selectedMonitor; \ MONITOR_DEF monitors[16]; \ MONITOR_DEF virtualScreen; \ diff --git a/libfreerdp/core/capabilities.c b/libfreerdp/core/capabilities.c index 2449ff7a2..c1771a44d 100644 --- a/libfreerdp/core/capabilities.c +++ b/libfreerdp/core/capabilities.c @@ -341,6 +341,15 @@ BOOL rdp_read_bitmap_capability_set(wStream* s, UINT16 length, rdpSettings* sett settings->DesktopHeight = desktopHeight; } + if (settings->DrawAllowSkipAlpha) + settings->DrawAllowSkipAlpha = (drawingFlags & DRAW_ALLOW_SKIP_ALPHA) ? TRUE : FALSE; + + if (settings->DrawAllowDynamicColorFidelity) + settings->DrawAllowDynamicColorFidelity = (drawingFlags & DRAW_ALLOW_DYNAMIC_COLOR_FIDELITY) ? TRUE : FALSE; + + if (settings->DrawAllowColorSubsampling) + settings->DrawAllowColorSubsampling = (drawingFlags & DRAW_ALLOW_COLOR_SUBSAMPLING) ? TRUE : FALSE; + return TRUE; } @@ -365,10 +374,10 @@ void rdp_write_bitmap_capability_set(wStream* s, rdpSettings* settings) if (settings->DrawAllowSkipAlpha) drawingFlags |= DRAW_ALLOW_SKIP_ALPHA; - if (settings->DrawAllowColorSubsampling) + if (settings->DrawAllowDynamicColorFidelity) drawingFlags |= DRAW_ALLOW_DYNAMIC_COLOR_FIDELITY; - if (settings->DrawAllowDynamicColorFidelity) + if (settings->DrawAllowColorSubsampling) drawingFlags |= DRAW_ALLOW_COLOR_SUBSAMPLING; /* currently unimplemented */ /* While bitmap_decode.c now implements YCoCg, in turning it diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index 1edf22abc..e8e255798 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -35,11 +35,13 @@ #include #include +#include #include #include -#include #include "../shadow_screen.h" +#include "../shadow_client.h" +#include "../shadow_encoder.h" #include "../shadow_capture.h" #include "../shadow_surface.h" #include "../shadow_subsystem.h" @@ -488,6 +490,18 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) DeleteSynchronizationBarrier(&(subsystem->barrier)); + if (count == 1) + { + rdpShadowClient* client; + + client = (rdpShadowClient*) ArrayList_GetItem(server->clients, 0); + + if (client) + { + subsystem->captureFrameRate = client->encoder->fps; + } + } + ResetEvent(subsystem->updateEvent); region16_clear(&(subsystem->invalidRegion)); @@ -548,7 +562,6 @@ int x11_shadow_subsystem_process_message(x11ShadowSubsystem* subsystem, wMessage void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem) { - int fps; XEvent xevent; DWORD status; DWORD nCount; @@ -566,8 +579,8 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem) events[nCount++] = subsystem->event; events[nCount++] = MessageQueue_Event(MsgPipe->In); - fps = 16; - dwInterval = 1000 / fps; + subsystem->captureFrameRate = 16; + dwInterval = 1000 / subsystem->captureFrameRate; frameTime = GetTickCount64() + dwInterval; while (1) @@ -602,7 +615,7 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem) x11_shadow_query_cursor(subsystem, FALSE); x11_shadow_screen_grab(subsystem); - dwInterval = 1000 / fps; + dwInterval = 1000 / subsystem->captureFrameRate; frameTime += dwInterval; } } diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index 24dab2d51..6038bfeec 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -72,7 +72,7 @@ void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client) client->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - client->encoder = shadow_encoder_new(server); + client->encoder = shadow_encoder_new(client); ArrayList_Add(server->clients, (void*) client); } diff --git a/server/shadow/shadow_encoder.c b/server/shadow/shadow_encoder.c index 8150d4bdd..1c1c73222 100644 --- a/server/shadow/shadow_encoder.c +++ b/server/shadow/shadow_encoder.c @@ -166,9 +166,13 @@ int shadow_encoder_init_nsc(rdpShadowEncoder* encoder) int shadow_encoder_init_bitmap(rdpShadowEncoder* encoder) { - DWORD planarFlags; + DWORD planarFlags = 0; + rdpContext* context = (rdpContext*) encoder->client; + rdpSettings* settings = context->settings; + + if (settings->DrawAllowSkipAlpha) + planarFlags |= PLANAR_FORMAT_HEADER_NA; - planarFlags = PLANAR_FORMAT_HEADER_NA; planarFlags |= PLANAR_FORMAT_HEADER_RLE; if (!encoder->planar) @@ -346,15 +350,17 @@ int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs) return 1; } -rdpShadowEncoder* shadow_encoder_new(rdpShadowServer* server) +rdpShadowEncoder* shadow_encoder_new(rdpShadowClient* client) { rdpShadowEncoder* encoder; + rdpShadowServer* server = client->server; encoder = (rdpShadowEncoder*) calloc(1, sizeof(rdpShadowEncoder)); if (!encoder) return NULL; + encoder->client = client; encoder->server = server; encoder->fps = 16; diff --git a/server/shadow/shadow_encoder.h b/server/shadow/shadow_encoder.h index d1ae552d7..fc1b5e763 100644 --- a/server/shadow/shadow_encoder.h +++ b/server/shadow/shadow_encoder.h @@ -35,6 +35,7 @@ struct rdp_shadow_encoder { + rdpShadowClient* client; rdpShadowServer* server; int width; @@ -70,7 +71,7 @@ int shadow_encoder_reset(rdpShadowEncoder* encoder); int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs); int shadow_encoder_create_frame_id(rdpShadowEncoder* encoder); -rdpShadowEncoder* shadow_encoder_new(rdpShadowServer* server); +rdpShadowEncoder* shadow_encoder_new(rdpShadowClient* client); void shadow_encoder_free(rdpShadowEncoder* encoder); #ifdef __cplusplus From 3ddbb128cc4a52f31dc9066cad3c8fb84b4bedaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 19 Sep 2014 14:23:17 -0400 Subject: [PATCH 21/21] libfreerdp-core: add SurfaceFrameBits function to combine frame marker with surface commands --- include/freerdp/update.h | 10 +++++---- libfreerdp/core/update.c | 40 +++++++++++++++++++++++++++++------ server/shadow/shadow_client.c | 26 ++++++++++++++--------- 3 files changed, 56 insertions(+), 20 deletions(-) diff --git a/include/freerdp/update.h b/include/freerdp/update.h index 8428ab6a9..f0c5b4541 100644 --- a/include/freerdp/update.h +++ b/include/freerdp/update.h @@ -147,8 +147,9 @@ typedef void (*pRefreshRect)(rdpContext* context, BYTE count, RECTANGLE_16* area typedef void (*pSuppressOutput)(rdpContext* context, BYTE allow, RECTANGLE_16* area); typedef void (*pSurfaceCommand)(rdpContext* context, wStream* s); -typedef void (*pSurfaceBits)(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command); -typedef void (*pSurfaceFrameMarker)(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker); +typedef void (*pSurfaceBits)(rdpContext* context, SURFACE_BITS_COMMAND* surfaceBitsCommand); +typedef void (*pSurfaceFrameMarker)(rdpContext* context, SURFACE_FRAME_MARKER* surfaceFrameMarker); +typedef void (*pSurfaceFrameBits)(rdpContext* context, SURFACE_BITS_COMMAND* cmd, BOOL first, BOOL last, UINT32 frameId); typedef void (*pSurfaceFrameAcknowledge)(rdpContext* context, UINT32 frameId); struct rdp_update @@ -180,8 +181,9 @@ struct rdp_update pSurfaceCommand SurfaceCommand; /* 64 */ pSurfaceBits SurfaceBits; /* 65 */ pSurfaceFrameMarker SurfaceFrameMarker; /* 66 */ - pSurfaceFrameAcknowledge SurfaceFrameAcknowledge; /* 67 */ - UINT32 paddingE[80 - 68]; /* 68 */ + pSurfaceFrameBits SurfaceFrameBits; /* 67 */ + pSurfaceFrameAcknowledge SurfaceFrameAcknowledge; /* 68 */ + UINT32 paddingE[80 - 69]; /* 69 */ /* internal */ diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c index daeef3f29..f3ec6fe80 100644 --- a/libfreerdp/core/update.c +++ b/libfreerdp/core/update.c @@ -867,7 +867,7 @@ static void update_send_surface_command(rdpContext* context, wStream* s) Stream_Release(update); } -static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command) +static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surfaceBitsCommand) { wStream* s; rdpRdp* rdp = context->rdp; @@ -875,9 +875,9 @@ static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* update_force_flush(context); s = fastpath_update_pdu_init(rdp->fastpath); - Stream_EnsureRemainingCapacity(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH + (int) surface_bits_command->bitmapDataLength); - update_write_surfcmd_surface_bits_header(s, surface_bits_command); - Stream_Write(s, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); + Stream_EnsureRemainingCapacity(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH + (int) surfaceBitsCommand->bitmapDataLength); + update_write_surfcmd_surface_bits_header(s, surfaceBitsCommand); + Stream_Write(s, surfaceBitsCommand->bitmapData, surfaceBitsCommand->bitmapDataLength); fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s); update_force_flush(context); @@ -885,7 +885,7 @@ static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* Stream_Release(s); } -static void update_send_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker) +static void update_send_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surfaceFrameMarker) { wStream* s; rdpRdp* rdp = context->rdp; @@ -893,7 +893,34 @@ static void update_send_surface_frame_marker(rdpContext* context, SURFACE_FRAME_ update_force_flush(context); s = fastpath_update_pdu_init(rdp->fastpath); - update_write_surfcmd_frame_marker(s, surface_frame_marker->frameAction, surface_frame_marker->frameId); + update_write_surfcmd_frame_marker(s, surfaceFrameMarker->frameAction, surfaceFrameMarker->frameId); + fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s); + + update_force_flush(context); + + Stream_Release(s); +} + +static void update_send_surface_frame_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd, BOOL first, BOOL last, UINT32 frameId) +{ + wStream* s; + rdpRdp* rdp = context->rdp; + + update_force_flush(context); + + s = fastpath_update_pdu_init(rdp->fastpath); + Stream_EnsureRemainingCapacity(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH + (int) cmd->bitmapDataLength + 16); + + if (first) + update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_BEGIN, frameId); + + update_write_surfcmd_surface_bits_header(s, cmd); + Stream_Write(s, cmd->bitmapData, cmd->bitmapDataLength); + + + if (last) + update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_END, frameId); + fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s); update_force_flush(context); @@ -1596,6 +1623,7 @@ void update_register_server_callbacks(rdpUpdate* update) update->SurfaceBits = update_send_surface_bits; update->SurfaceFrameMarker = update_send_surface_frame_marker; update->SurfaceCommand = update_send_surface_command; + update->SurfaceFrameBits = update_send_surface_frame_bits; update->PlaySound = update_send_play_sound; update->primary->DstBlt = update_send_dstblt; update->primary->PatBlt = update_send_patblt; diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index 6038bfeec..96aea63a9 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -287,6 +287,8 @@ int shadow_client_send_surface_frame_marker(rdpShadowClient* client, UINT32 acti int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* surface, int nXSrc, int nYSrc, int nWidth, int nHeight) { int i; + BOOL first; + BOOL last; wStream* s; int nSrcStep; BYTE* pSrcData; @@ -325,10 +327,7 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s } if (encoder->frameAck) - { frameId = (UINT32) shadow_encoder_create_frame_id(encoder); - shadow_client_send_surface_frame_marker(client, SURFACECMD_FRAMEACTION_BEGIN, frameId); - } if (settings->RemoteFxCodec) { @@ -366,7 +365,13 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s cmd.bitmapDataLength = Stream_GetPosition(s); cmd.bitmapData = Stream_Buffer(s); - IFCALL(update->SurfaceBits, update->context, &cmd); + first = (i == 0) ? TRUE : FALSE; + last = ((i + 1) == numMessages) ? TRUE : FALSE; + + if (!encoder->frameAck) + IFCALL(update->SurfaceBits, update->context, &cmd); + else + IFCALL(update->SurfaceFrameBits, update->context, &cmd, first, last, frameId); } free(messages); @@ -401,17 +406,18 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s cmd.bitmapDataLength = Stream_GetPosition(s); cmd.bitmapData = Stream_Buffer(s); - IFCALL(update->SurfaceBits, update->context, &cmd); + first = (i == 0) ? TRUE : FALSE; + last = ((i + 1) == numMessages) ? TRUE : FALSE; + + if (!encoder->frameAck) + IFCALL(update->SurfaceBits, update->context, &cmd); + else + IFCALL(update->SurfaceFrameBits, update->context, &cmd, first, last, frameId); } free(messages); } - if (encoder->frameAck) - { - shadow_client_send_surface_frame_marker(client, SURFACECMD_FRAMEACTION_END, frameId); - } - return 1; }