mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
server/shadow: Enhancement regarding the screen and resolution - add resize support and fix subRect feature
Detail fixes: 1. Add resize support in shadow framework layer 2. Enhance X11 implementation to detect desktop resolution change 3. Fix the subRect feature. It seems not completely finished and it looks incompatible in different source code. Fix it to be consistent in all source code as following: a. The subRect is only awared in framework layer, subsystem implementation should not be aware of it. It only take effect at shadow_client and corresponding shadow_input. b. The screen and surface should only represent a monitor screen. They don't need to consider subRect feature. 4. A lobby should be alternative image shown to client when the client is not 'mayView'. We don't need to have seperate lobby for each client, move it into server structure as 'another surface' 5. Fix display handle leak in enum monitor of X11 6. Suppress BadMatch Error while capturing the image
This commit is contained in:
@@ -90,7 +90,6 @@ struct rdp_shadow_client
|
||||
CRITICAL_SECTION lock;
|
||||
REGION16 invalidRegion;
|
||||
rdpShadowServer* server;
|
||||
rdpShadowSurface* lobby;
|
||||
rdpShadowEncoder* encoder;
|
||||
rdpShadowSubsystem* subsystem;
|
||||
|
||||
@@ -112,6 +111,7 @@ struct rdp_shadow_server
|
||||
wArrayList* clients;
|
||||
rdpShadowScreen* screen;
|
||||
rdpShadowSurface* surface;
|
||||
rdpShadowSurface* lobby;
|
||||
rdpShadowCapture* capture;
|
||||
rdpShadowSubsystem* subsystem;
|
||||
|
||||
@@ -282,6 +282,8 @@ FREERDP_API int shadow_client_boardcast_quit(rdpShadowServer* server, int nExitC
|
||||
FREERDP_API int shadow_encoder_preferred_fps(rdpShadowEncoder* encoder);
|
||||
FREERDP_API UINT32 shadow_encoder_inflight_frames(rdpShadowEncoder* encoder);
|
||||
|
||||
FREERDP_API BOOL shadow_screen_resize(rdpShadowScreen* screen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
|
||||
#define TAG SERVER_TAG("shadow.x11")
|
||||
|
||||
int x11_shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors);
|
||||
|
||||
#ifdef WITH_PAM
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
@@ -273,12 +275,6 @@ void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, U
|
||||
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)
|
||||
@@ -332,12 +328,6 @@ 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);
|
||||
@@ -495,6 +485,13 @@ int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage)
|
||||
y = root_y;
|
||||
}
|
||||
|
||||
/* Convert to offset based on current surface */
|
||||
if (surface)
|
||||
{
|
||||
x -= surface->x;
|
||||
y -= surface->y;
|
||||
}
|
||||
|
||||
if ((x != subsystem->pointerX) || (y != subsystem->pointerY))
|
||||
{
|
||||
subsystem->pointerX = x;
|
||||
@@ -572,8 +569,8 @@ int x11_shadow_blend_cursor(x11ShadowSubsystem* subsystem)
|
||||
nWidth = subsystem->cursorWidth;
|
||||
nHeight = subsystem->cursorHeight;
|
||||
|
||||
nXDst = subsystem->pointerX - surface->x - subsystem->cursorHotX;
|
||||
nYDst = subsystem->pointerY - surface->y - subsystem->cursorHotY;
|
||||
nXDst = subsystem->pointerX - subsystem->cursorHotX;
|
||||
nYDst = subsystem->pointerY - subsystem->cursorHotY;
|
||||
|
||||
if (nXDst >= surface->width)
|
||||
return 1;
|
||||
@@ -659,6 +656,51 @@ int x11_shadow_blend_cursor(x11ShadowSubsystem* subsystem)
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL x11_shadow_check_resize(x11ShadowSubsystem* subsystem)
|
||||
{
|
||||
MONITOR_DEF* virtualScreen;
|
||||
XWindowAttributes attr;
|
||||
XGetWindowAttributes(subsystem->display, subsystem->root_window, &attr);
|
||||
|
||||
if (attr.width != subsystem->width || attr.height != subsystem->height)
|
||||
{
|
||||
/* Screen size changed. Refresh monitor definitions and trigger screen resize */
|
||||
subsystem->numMonitors = x11_shadow_enum_monitors(subsystem->monitors, 16);
|
||||
|
||||
shadow_screen_resize(subsystem->server->screen);
|
||||
|
||||
subsystem->width = attr.width;
|
||||
subsystem->height = attr.height;
|
||||
|
||||
virtualScreen = &(subsystem->virtualScreen);
|
||||
virtualScreen->left = 0;
|
||||
virtualScreen->top = 0;
|
||||
virtualScreen->right = subsystem->width;
|
||||
virtualScreen->bottom = subsystem->height;
|
||||
virtualScreen->flags = 1;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int x11_shadow_error_handler_for_capture(Display * display, XErrorEvent * event)
|
||||
{
|
||||
char msg[256];
|
||||
XGetErrorText(display, event->error_code, (char *) &msg, sizeof(msg));
|
||||
WLog_ERR(TAG, "X11 error: %s Error code: %x, request code: %x, minor code: %x",
|
||||
msg, event->error_code, event->request_code, event->minor_code);
|
||||
|
||||
/* Ignore BAD MATCH error during image capture. Abort in other case */
|
||||
if (event->error_code != BadMatch)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
|
||||
{
|
||||
int count;
|
||||
@@ -692,6 +734,12 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
|
||||
|
||||
XLockDisplay(subsystem->display);
|
||||
|
||||
/*
|
||||
* Ignore BadMatch error during image capture. The screen size may be
|
||||
* changed outside. We will resize to correct resolution at next frame
|
||||
*/
|
||||
XSetErrorHandler(x11_shadow_error_handler_for_capture);
|
||||
|
||||
if (subsystem->use_xshm)
|
||||
{
|
||||
image = subsystem->fb_image;
|
||||
@@ -707,10 +755,22 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
|
||||
image = XGetImage(subsystem->display, subsystem->root_window,
|
||||
surface->x, surface->y, surface->width, surface->height, AllPlanes, ZPixmap);
|
||||
|
||||
if (!image)
|
||||
{
|
||||
/*
|
||||
* BadMatch error happened. The size may have been changed again.
|
||||
* Give up this frame and we will resize again in next frame
|
||||
*/
|
||||
goto fail_capture;
|
||||
}
|
||||
|
||||
status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height,
|
||||
(BYTE*) image->data, image->bytes_per_line, &invalidRect);
|
||||
}
|
||||
|
||||
/* Restore the default error handler */
|
||||
XSetErrorHandler(NULL);
|
||||
|
||||
XSync(subsystem->display, False);
|
||||
|
||||
XUnlockDisplay(subsystem->display);
|
||||
@@ -757,6 +817,12 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
|
||||
XDestroyImage(image);
|
||||
|
||||
return 1;
|
||||
|
||||
fail_capture:
|
||||
XSetErrorHandler(NULL);
|
||||
XSync(subsystem->display, False);
|
||||
XUnlockDisplay(subsystem->display);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int x11_shadow_subsystem_process_message(x11ShadowSubsystem* subsystem, wMessage* message)
|
||||
@@ -866,6 +932,7 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
|
||||
|
||||
if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime))
|
||||
{
|
||||
x11_shadow_check_resize(subsystem);
|
||||
x11_shadow_screen_grab(subsystem);
|
||||
x11_shadow_query_cursor(subsystem, FALSE);
|
||||
|
||||
@@ -1127,6 +1194,8 @@ int x11_shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors)
|
||||
}
|
||||
#endif
|
||||
|
||||
XCloseDisplay(display);
|
||||
|
||||
if (numMonitors < 1)
|
||||
{
|
||||
index = 0;
|
||||
|
||||
@@ -150,12 +150,6 @@ void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client)
|
||||
MessageQueue_Clear(client->MsgQueue);
|
||||
MessageQueue_Free(client->MsgQueue);
|
||||
|
||||
if (client->lobby)
|
||||
{
|
||||
shadow_surface_free(client->lobby);
|
||||
client->lobby = NULL;
|
||||
}
|
||||
|
||||
if (client->encoder)
|
||||
{
|
||||
shadow_encoder_free(client->encoder);
|
||||
@@ -188,6 +182,19 @@ BOOL shadow_client_capabilities(freerdp_peer* peer)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INLINE void shadow_client_calc_desktop_size(rdpShadowServer* server, int* pWidth, int* pHeight)
|
||||
{
|
||||
RECTANGLE_16 viewport = {0, 0, server->screen->width, server->screen->height};
|
||||
|
||||
if (server->shareSubRect)
|
||||
{
|
||||
rectangles_intersection(&viewport, &(server->subRect), &viewport);
|
||||
}
|
||||
|
||||
(*pWidth) = viewport.right - viewport.left;
|
||||
(*pHeight) = viewport.bottom - viewport.top;
|
||||
}
|
||||
|
||||
BOOL shadow_client_post_connect(freerdp_peer* peer)
|
||||
{
|
||||
int authStatus;
|
||||
@@ -203,17 +210,7 @@ BOOL shadow_client_post_connect(freerdp_peer* peer)
|
||||
server = client->server;
|
||||
subsystem = server->subsystem;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
shadow_client_calc_desktop_size(server, &width, &height);
|
||||
settings->DesktopWidth = width;
|
||||
settings->DesktopHeight = height;
|
||||
|
||||
@@ -232,13 +229,11 @@ BOOL shadow_client_post_connect(freerdp_peer* peer)
|
||||
|
||||
invalidRect.left = 0;
|
||||
invalidRect.top = 0;
|
||||
invalidRect.right = width;
|
||||
invalidRect.bottom = height;
|
||||
invalidRect.right = server->screen->width;
|
||||
invalidRect.bottom = server->screen->height;
|
||||
|
||||
region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &invalidRect);
|
||||
|
||||
shadow_client_init_lobby(client);
|
||||
|
||||
authStatus = -1;
|
||||
|
||||
if (settings->Username && settings->Password)
|
||||
@@ -270,6 +265,30 @@ BOOL shadow_client_post_connect(freerdp_peer* peer)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Convert rects in sub rect coordinate to client/surface coordinate */
|
||||
static INLINE void shadow_client_convert_rects(rdpShadowClient* client,
|
||||
RECTANGLE_16* dst, RECTANGLE_16* src, UINT32 numRects)
|
||||
{
|
||||
if (client->server->shareSubRect)
|
||||
{
|
||||
int i = 0;
|
||||
UINT16 offsetX = client->server->subRect.left;
|
||||
UINT16 offsetY = client->server->subRect.top;
|
||||
|
||||
for (i = 0; i < numRects; i++)
|
||||
{
|
||||
dst[i].left = src[i].left + offsetX;
|
||||
dst[i].right = src[i].right + offsetX;
|
||||
dst[i].top = src[i].top + offsetY;
|
||||
dst[i].bottom = src[i].bottom + offsetY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyMemory(dst, src, numRects * sizeof(RECTANGLE_16));
|
||||
}
|
||||
}
|
||||
|
||||
BOOL shadow_client_refresh_rect(rdpShadowClient* client, BYTE count, RECTANGLE_16* areas)
|
||||
{
|
||||
wMessage message = { 0 };
|
||||
@@ -294,7 +313,7 @@ BOOL shadow_client_refresh_rect(rdpShadowClient* client, BYTE count, RECTANGLE_1
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CopyMemory(wParam->rects, areas, wParam->numRects * sizeof(RECTANGLE_16));
|
||||
shadow_client_convert_rects(client, wParam->rects, areas, wParam->numRects);
|
||||
}
|
||||
|
||||
message.id = SHADOW_MSG_IN_REFRESH_OUTPUT_ID;
|
||||
@@ -319,7 +338,7 @@ BOOL shadow_client_suppress_output(rdpShadowClient* client, BYTE allow, RECTANGL
|
||||
wParam->allow = (UINT32) allow;
|
||||
|
||||
if (area)
|
||||
CopyMemory(&(wParam->rect), area, sizeof(RECTANGLE_16));
|
||||
shadow_client_convert_rects(client, &(wParam->rect), area, 1);
|
||||
|
||||
message.id = SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID;
|
||||
message.wParam = (void*) wParam;
|
||||
@@ -445,7 +464,7 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s
|
||||
rect.height = nHeight;
|
||||
|
||||
if (!(messages = rfx_encode_messages(encoder->rfx, &rect, 1, pSrcData,
|
||||
surface->width, surface->height, nSrcStep, &numMessages,
|
||||
settings->DesktopWidth, settings->DesktopHeight, nSrcStep, &numMessages,
|
||||
settings->MultifragMaxRequestSize)))
|
||||
{
|
||||
return 0;
|
||||
@@ -455,12 +474,12 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s
|
||||
|
||||
cmd.destLeft = 0;
|
||||
cmd.destTop = 0;
|
||||
cmd.destRight = surface->width;
|
||||
cmd.destBottom = surface->height;
|
||||
cmd.destRight = settings->DesktopWidth;
|
||||
cmd.destBottom = settings->DesktopHeight;
|
||||
|
||||
cmd.bpp = 32;
|
||||
cmd.width = surface->width;
|
||||
cmd.height = surface->height;
|
||||
cmd.width = settings->DesktopWidth;
|
||||
cmd.height = settings->DesktopHeight;
|
||||
cmd.skipCompression = TRUE;
|
||||
|
||||
if (numMessages > 0)
|
||||
@@ -569,6 +588,21 @@ int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface*
|
||||
nSrcStep = surface->scanline;
|
||||
SrcFormat = PIXEL_FORMAT_RGB32;
|
||||
|
||||
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 ((nXSrc % 4) != 0)
|
||||
{
|
||||
nWidth += (nXSrc % 4);
|
||||
@@ -747,7 +781,7 @@ int shadow_client_send_surface_update(rdpShadowClient* client)
|
||||
server = client->server;
|
||||
encoder = client->encoder;
|
||||
|
||||
surface = client->inLobby ? client->lobby : server->surface;
|
||||
surface = client->inLobby ? server->lobby : server->surface;
|
||||
|
||||
EnterCriticalSection(&(client->lock));
|
||||
|
||||
@@ -915,6 +949,12 @@ int shadow_client_subsystem_process_message(rdpShadowClient* client, wMessage* m
|
||||
pointerPosition.xPos = msg->xPos;
|
||||
pointerPosition.yPos = msg->yPos;
|
||||
|
||||
if (client->server->shareSubRect)
|
||||
{
|
||||
pointerPosition.xPos -= client->server->subRect.left;
|
||||
pointerPosition.yPos -= client->server->subRect.top;
|
||||
}
|
||||
|
||||
if (client->activated)
|
||||
{
|
||||
if ((msg->xPos != client->pointerX) || (msg->yPos != client->pointerY))
|
||||
@@ -1060,15 +1100,44 @@ void* shadow_client_thread(rdpShadowClient* client)
|
||||
int index;
|
||||
int numRects = 0;
|
||||
const RECTANGLE_16* rects;
|
||||
int width, height;
|
||||
|
||||
rects = region16_rects(&(subsystem->invalidRegion), &numRects);
|
||||
|
||||
for (index = 0; index < numRects; index++)
|
||||
/* Check resize */
|
||||
shadow_client_calc_desktop_size(server, &width, &height);
|
||||
if (settings->DesktopWidth != (UINT32)width || settings->DesktopHeight != (UINT32)height)
|
||||
{
|
||||
region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]);
|
||||
}
|
||||
/* Screen size changed, do resize */
|
||||
settings->DesktopWidth = width;
|
||||
settings->DesktopHeight = height;
|
||||
|
||||
shadow_client_send_surface_update(client);
|
||||
/**
|
||||
* Unset client activated flag to avoid sending update message during
|
||||
* resize. DesktopResize will reactive the client and
|
||||
* shadow_client_activate would be invoked later.
|
||||
*/
|
||||
client->activated = FALSE;
|
||||
|
||||
/* Send Resize */
|
||||
peer->update->DesktopResize(peer->update->context); // update_send_desktop_resize
|
||||
|
||||
/* Clear my invalidRegion. shadow_client_activate refreshes fullscreen */
|
||||
region16_clear(&(client->invalidRegion));
|
||||
|
||||
WLog_ERR(TAG, "Client from %s is resized (%dx%d@%d)",
|
||||
peer->hostname, settings->DesktopWidth, settings->DesktopHeight, settings->ColorDepth);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Send frame */
|
||||
rects = region16_rects(&(subsystem->invalidRegion), &numRects);
|
||||
|
||||
for (index = 0; index < numRects; index++)
|
||||
{
|
||||
region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]);
|
||||
}
|
||||
|
||||
shadow_client_send_surface_update(client);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -224,6 +224,9 @@ int shadow_encoder_init_interleaved(rdpShadowEncoder* encoder)
|
||||
|
||||
int shadow_encoder_init(rdpShadowEncoder* encoder)
|
||||
{
|
||||
encoder->width = encoder->server->screen->width;
|
||||
encoder->height = encoder->server->screen->height;
|
||||
|
||||
encoder->maxTileWidth = 64;
|
||||
encoder->maxTileHeight = 64;
|
||||
|
||||
@@ -401,9 +404,6 @@ rdpShadowEncoder* shadow_encoder_new(rdpShadowClient* client)
|
||||
encoder->fps = 16;
|
||||
encoder->maxFps = 32;
|
||||
|
||||
encoder->width = server->screen->width;
|
||||
encoder->height = server->screen->height;
|
||||
|
||||
if (shadow_encoder_init(encoder) < 0)
|
||||
{
|
||||
free (encoder);
|
||||
|
||||
@@ -72,6 +72,12 @@ BOOL shadow_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
||||
rdpShadowClient* client = (rdpShadowClient*) input->context;
|
||||
rdpShadowSubsystem* subsystem = client->server->subsystem;
|
||||
|
||||
if (client->server->shareSubRect)
|
||||
{
|
||||
x += client->server->subRect.left;
|
||||
y += client->server->subRect.top;
|
||||
}
|
||||
|
||||
if (!(flags & PTR_FLAGS_WHEEL))
|
||||
{
|
||||
client->pointerX = x;
|
||||
@@ -102,6 +108,12 @@ BOOL shadow_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x,
|
||||
rdpShadowClient* client = (rdpShadowClient*) input->context;
|
||||
rdpShadowSubsystem* subsystem = client->server->subsystem;
|
||||
|
||||
if (client->server->shareSubRect)
|
||||
{
|
||||
x += client->server->subRect.left;
|
||||
y += client->server->subRect.top;
|
||||
}
|
||||
|
||||
client->pointerX = x;
|
||||
client->pointerY = y;
|
||||
|
||||
|
||||
@@ -26,31 +26,44 @@
|
||||
|
||||
#include "shadow_lobby.h"
|
||||
|
||||
int shadow_client_init_lobby(rdpShadowClient* client)
|
||||
BOOL shadow_client_init_lobby(rdpShadowServer* server)
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
rdtkEngine* engine;
|
||||
rdtkSurface* surface;
|
||||
RECTANGLE_16 invalidRect;
|
||||
rdpShadowSurface* lobby;
|
||||
rdpContext* context = (rdpContext*) client;
|
||||
rdpSettings* settings = context->settings;
|
||||
rdpShadowSurface* lobby = server->lobby;
|
||||
|
||||
width = settings->DesktopWidth;
|
||||
height = settings->DesktopHeight;
|
||||
if (!lobby)
|
||||
return FALSE;
|
||||
|
||||
lobby = client->lobby = shadow_surface_new(client->server, 0, 0, width, height);
|
||||
if (!(engine = rdtk_engine_new()))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!client->lobby)
|
||||
return -1;
|
||||
if (!(surface = rdtk_surface_new(engine, lobby->data, lobby->width, lobby->height, lobby->scanline)))
|
||||
{
|
||||
rdtk_engine_free(engine);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
engine = rdtk_engine_new();
|
||||
invalidRect.left = 0;
|
||||
invalidRect.top = 0;
|
||||
invalidRect.right = lobby->width;
|
||||
invalidRect.bottom = lobby->height;
|
||||
if (server->shareSubRect)
|
||||
{
|
||||
/* If we have shared sub rect setting, only fill shared rect */
|
||||
rectangles_intersection(&invalidRect, &(server->subRect), &invalidRect);
|
||||
}
|
||||
|
||||
surface = rdtk_surface_new(engine, lobby->data, lobby->width, lobby->height, lobby->scanline);
|
||||
width = invalidRect.right - invalidRect.left;
|
||||
height = invalidRect.bottom - invalidRect.top;
|
||||
rdtk_surface_fill(surface, invalidRect.left, invalidRect.top, width, height, 0x3BB9FF);
|
||||
|
||||
rdtk_surface_fill(surface, 0, 0, width, height, 0x3BB9FF);
|
||||
//rdtk_label_draw(surface, 16, 16, 128, 32, NULL, "label", 0, 0);
|
||||
rdtk_label_draw(surface, invalidRect.left, invalidRect.top, width, height, NULL, "Welcome", 0, 0);
|
||||
//rdtk_button_draw(surface, 16, 64, 128, 32, NULL, "button");
|
||||
//rdtk_text_field_draw(surface, 16, 128, 128, 32, NULL, "text field");
|
||||
|
||||
@@ -58,12 +71,7 @@ int shadow_client_init_lobby(rdpShadowClient* client)
|
||||
|
||||
rdtk_engine_free(engine);
|
||||
|
||||
invalidRect.left = 0;
|
||||
invalidRect.top = 0;
|
||||
invalidRect.right = width;
|
||||
invalidRect.bottom = height;
|
||||
|
||||
region16_union_rect(&(lobby->invalidRegion), &(lobby->invalidRegion), &invalidRect);
|
||||
|
||||
return 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int shadow_client_init_lobby(rdpShadowClient* client);
|
||||
BOOL shadow_client_init_lobby(rdpShadowServer* server);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "shadow_surface.h"
|
||||
|
||||
#include "shadow_screen.h"
|
||||
#include "shadow_lobby.h"
|
||||
|
||||
rdpShadowScreen* shadow_screen_new(rdpShadowServer* server)
|
||||
{
|
||||
@@ -30,35 +31,27 @@ rdpShadowScreen* shadow_screen_new(rdpShadowServer* server)
|
||||
int width, height;
|
||||
rdpShadowScreen* screen;
|
||||
rdpShadowSubsystem* subsystem;
|
||||
MONITOR_DEF* primary;
|
||||
|
||||
screen = (rdpShadowScreen*) calloc(1, sizeof(rdpShadowScreen));
|
||||
|
||||
if (!screen)
|
||||
return NULL;
|
||||
goto out_error;
|
||||
|
||||
screen->server = server;
|
||||
subsystem = server->subsystem;
|
||||
|
||||
if (!InitializeCriticalSectionAndSpinCount(&(screen->lock), 4000))
|
||||
return NULL;
|
||||
goto out_free;
|
||||
|
||||
region16_init(&(screen->invalidRegion));
|
||||
|
||||
if (server->shareSubRect) {
|
||||
x = server->subRect.left;
|
||||
y = server->subRect.top;
|
||||
width = server->subRect.right - server->subRect.left;
|
||||
height = server->subRect.bottom - server->subRect.top;
|
||||
} else {
|
||||
MONITOR_DEF* primary;
|
||||
primary = &(subsystem->monitors[subsystem->selectedMonitor]);
|
||||
|
||||
primary = &(subsystem->monitors[subsystem->selectedMonitor]);
|
||||
|
||||
x = primary->left;
|
||||
y = primary->top;
|
||||
width = primary->right - primary->left;
|
||||
height = primary->bottom - primary->top;
|
||||
}
|
||||
x = primary->left;
|
||||
y = primary->top;
|
||||
width = primary->right - primary->left;
|
||||
height = primary->bottom - primary->top;
|
||||
|
||||
screen->width = width;
|
||||
screen->height = height;
|
||||
@@ -66,11 +59,31 @@ rdpShadowScreen* shadow_screen_new(rdpShadowServer* server)
|
||||
screen->primary = shadow_surface_new(server, x, y, width, height);
|
||||
|
||||
if (!screen->primary)
|
||||
return NULL;
|
||||
goto out_free_region;
|
||||
|
||||
server->surface = screen->primary;
|
||||
|
||||
screen->lobby = shadow_surface_new(server, x, y, width, height);
|
||||
|
||||
if (!screen->lobby)
|
||||
goto out_free_primary;
|
||||
|
||||
server->lobby = screen->lobby;
|
||||
|
||||
shadow_client_init_lobby(server);
|
||||
|
||||
return screen;
|
||||
|
||||
out_free_primary:
|
||||
shadow_surface_free(screen->primary);
|
||||
server->surface = screen->primary = NULL;
|
||||
out_free_region:
|
||||
region16_uninit(&(screen->invalidRegion));
|
||||
DeleteCriticalSection(&(screen->lock));
|
||||
out_free:
|
||||
free(screen);
|
||||
out_error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void shadow_screen_free(rdpShadowScreen* screen)
|
||||
@@ -88,6 +101,45 @@ void shadow_screen_free(rdpShadowScreen* screen)
|
||||
screen->primary = NULL;
|
||||
}
|
||||
|
||||
if (screen->lobby)
|
||||
{
|
||||
shadow_surface_free(screen->lobby);
|
||||
screen->lobby = NULL;
|
||||
}
|
||||
|
||||
free(screen);
|
||||
}
|
||||
|
||||
BOOL shadow_screen_resize(rdpShadowScreen* screen)
|
||||
{
|
||||
int x, y;
|
||||
int width, height;
|
||||
MONITOR_DEF* primary;
|
||||
rdpShadowSubsystem* subsystem;
|
||||
|
||||
if (!screen)
|
||||
return FALSE;
|
||||
|
||||
subsystem = screen->server->subsystem;
|
||||
primary = &(subsystem->monitors[subsystem->selectedMonitor]);
|
||||
|
||||
x = primary->left;
|
||||
y = primary->top;
|
||||
width = primary->right - primary->left;
|
||||
height = primary->bottom - primary->top;
|
||||
|
||||
if (shadow_surface_resize(screen->primary, x, y, width, height)
|
||||
&& shadow_surface_resize(screen->lobby, x, y, width, height))
|
||||
{
|
||||
if ((width != screen->width) || (height != screen->height))
|
||||
{
|
||||
/* screen size is changed. Store new size and reinit lobby */
|
||||
screen->width = width;
|
||||
screen->height = height;
|
||||
shadow_client_init_lobby(screen->server);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ struct rdp_shadow_screen
|
||||
REGION16 invalidRegion;
|
||||
|
||||
rdpShadowSurface* primary;
|
||||
rdpShadowSurface* lobby;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -41,16 +41,13 @@ rdpShadowSurface* shadow_surface_new(rdpShadowServer* server, int x, int y, int
|
||||
surface->height = height;
|
||||
surface->scanline = (surface->width + (surface->width % 4)) * 4;
|
||||
|
||||
surface->data = (BYTE*) malloc(surface->scanline * surface->height);
|
||||
|
||||
surface->data = (BYTE*) calloc(1, surface->scanline * surface->height);
|
||||
if (!surface->data)
|
||||
{
|
||||
free (surface);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZeroMemory(surface->data, surface->scanline * surface->height);
|
||||
|
||||
if (!InitializeCriticalSectionAndSpinCount(&(surface->lock), 4000))
|
||||
{
|
||||
free (surface->data);
|
||||
@@ -76,3 +73,35 @@ void shadow_surface_free(rdpShadowSurface* surface)
|
||||
|
||||
free(surface);
|
||||
}
|
||||
|
||||
BOOL shadow_surface_resize(rdpShadowSurface *surface, int x, int y, int width, int height)
|
||||
{
|
||||
BYTE* buffer = NULL;
|
||||
int scanline = (width + (width % 4)) * 4;
|
||||
|
||||
if (!surface)
|
||||
return FALSE;
|
||||
|
||||
if ((width == surface->width) && (height == surface->height))
|
||||
{
|
||||
/* We don't need to reset frame buffer, just update left top */
|
||||
surface->x = x;
|
||||
surface->y = y;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
buffer = (BYTE*) realloc(surface->data, scanline * height);
|
||||
if (buffer)
|
||||
{
|
||||
surface->x = x;
|
||||
surface->y = y;
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
surface->scanline = scanline;
|
||||
surface->data = buffer;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ extern "C" {
|
||||
|
||||
rdpShadowSurface* shadow_surface_new(rdpShadowServer* server, int x, int y, int width, int height);
|
||||
void shadow_surface_free(rdpShadowSurface* surface);
|
||||
BOOL shadow_surface_resize(rdpShadowSurface *surface, int x, int y, int width, int height);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user