shadow: initial X11 multi-monitor support
This commit is contained in:
parent
8c9434f0dc
commit
f0ce0b8148
@ -85,6 +85,7 @@ struct rdp_shadow_server
|
||||
HANDLE event; \
|
||||
int monitorCount; \
|
||||
MONITOR_DEF monitors[16]; \
|
||||
MONITOR_DEF virtualScreen; \
|
||||
\
|
||||
pfnShadowSubsystemInit Init; \
|
||||
pfnShadowSubsystemUninit Uninit; \
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/codec/region.h>
|
||||
|
||||
#include "../shadow_screen.h"
|
||||
#include "../shadow_surface.h"
|
||||
|
||||
#include "x11_shadow.h"
|
||||
@ -152,6 +153,9 @@ void x11_shadow_validate_region(x11ShadowSubsystem* subsystem, int x, int y, int
|
||||
{
|
||||
XRectangle region;
|
||||
|
||||
if (!subsystem->use_xfixes)
|
||||
return;
|
||||
|
||||
region.x = x;
|
||||
region.y = y;
|
||||
region.width = width;
|
||||
@ -166,20 +170,20 @@ void x11_shadow_validate_region(x11ShadowSubsystem* subsystem, int x, int y, int
|
||||
int x11_shadow_invalidate_region(x11ShadowSubsystem* subsystem, int x, int y, int width, int height)
|
||||
{
|
||||
rdpShadowServer* server;
|
||||
rdpShadowSurface* surface;
|
||||
rdpShadowScreen* screen;
|
||||
RECTANGLE_16 invalidRect;
|
||||
|
||||
server = subsystem->server;
|
||||
surface = server->surface;
|
||||
screen = server->screen;
|
||||
|
||||
invalidRect.left = x;
|
||||
invalidRect.top = y;
|
||||
invalidRect.right = x + width;
|
||||
invalidRect.bottom = y + height;
|
||||
|
||||
EnterCriticalSection(&(surface->lock));
|
||||
region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
|
||||
LeaveCriticalSection(&(surface->lock));
|
||||
EnterCriticalSection(&(screen->lock));
|
||||
region16_union_rect(&(screen->invalidRegion), &(screen->invalidRegion), &invalidRect);
|
||||
LeaveCriticalSection(&(screen->lock));
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -190,12 +194,23 @@ int x11_shadow_surface_copy(x11ShadowSubsystem* subsystem)
|
||||
int width;
|
||||
int height;
|
||||
XImage* image;
|
||||
rdpShadowScreen* screen;
|
||||
rdpShadowServer* server;
|
||||
rdpShadowSurface* surface;
|
||||
RECTANGLE_16 surfaceRect;
|
||||
const RECTANGLE_16* extents;
|
||||
|
||||
server = subsystem->server;
|
||||
surface = server->surface;
|
||||
screen = server->screen;
|
||||
|
||||
surfaceRect.left = surface->x;
|
||||
surfaceRect.top = surface->y;
|
||||
surfaceRect.right = surface->x + surface->width;
|
||||
surfaceRect.bottom = surface->y + surface->height;
|
||||
|
||||
region16_clear(&(surface->invalidRegion));
|
||||
region16_intersect_rect(&(surface->invalidRegion), &(screen->invalidRegion), &surfaceRect);
|
||||
|
||||
if (region16_is_empty(&(surface->invalidRegion)))
|
||||
return 1;
|
||||
@ -219,7 +234,7 @@ int x11_shadow_surface_copy(x11ShadowSubsystem* subsystem)
|
||||
image = subsystem->fb_image;
|
||||
|
||||
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
|
||||
surface->scanline, x, y, width, height,
|
||||
surface->scanline, x - surface->x, y - surface->y, width, height,
|
||||
(BYTE*) image->data, PIXEL_FORMAT_XRGB32,
|
||||
image->bytes_per_line, x, y);
|
||||
}
|
||||
@ -229,7 +244,7 @@ int x11_shadow_surface_copy(x11ShadowSubsystem* subsystem)
|
||||
x, y, width, height, AllPlanes, ZPixmap);
|
||||
|
||||
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
|
||||
surface->scanline, x, y, width, height,
|
||||
surface->scanline, x - surface->x, y - surface->y, width, height,
|
||||
(BYTE*) image->data, PIXEL_FORMAT_XRGB32,
|
||||
image->bytes_per_line, 0, 0);
|
||||
|
||||
@ -291,29 +306,87 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int x11_shadow_cursor_init(x11ShadowSubsystem* subsystem)
|
||||
int x11_shadow_xfixes_init(x11ShadowSubsystem* subsystem)
|
||||
{
|
||||
#ifdef WITH_XFIXES
|
||||
int event;
|
||||
int error;
|
||||
int xfixes_event;
|
||||
int xfixes_error;
|
||||
int major, minor;
|
||||
|
||||
if (!XFixesQueryExtension(subsystem->display, &event, &error))
|
||||
if (!XFixesQueryExtension(subsystem->display, &xfixes_event, &xfixes_error))
|
||||
return -1;
|
||||
|
||||
subsystem->xfixes_notify_event = event + XFixesCursorNotify;
|
||||
if (!XFixesQueryVersion(subsystem->display, &major, &minor))
|
||||
return -1;
|
||||
|
||||
subsystem->xfixes_notify_event = xfixes_event + XFixesCursorNotify;
|
||||
|
||||
XFixesSelectCursorInput(subsystem->display, DefaultRootWindow(subsystem->display), XFixesDisplayCursorNotifyMask);
|
||||
|
||||
return 1;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (!XineramaQueryExtension(subsystem->display, &xinerama_event, &xinerama_error))
|
||||
return -1;
|
||||
|
||||
if (!XDamageQueryVersion(subsystem->display, &major, &minor))
|
||||
return -1;
|
||||
|
||||
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 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x11_shadow_xdamage_init(x11ShadowSubsystem* subsystem)
|
||||
{
|
||||
#ifdef WITH_XDAMAGE
|
||||
int major, minor;
|
||||
int damage_event;
|
||||
int damage_error;
|
||||
int major, minor;
|
||||
|
||||
if (!subsystem->use_xfixes)
|
||||
return -1;
|
||||
|
||||
if (!XDamageQueryExtension(subsystem->display, &damage_event, &damage_error))
|
||||
return -1;
|
||||
@ -396,9 +469,6 @@ int x11_shadow_xshm_init(x11ShadowSubsystem* subsystem)
|
||||
|
||||
shmctl(subsystem->fb_shm_info.shmid, IPC_RMID, 0);
|
||||
|
||||
fprintf(stderr, "display: %p root_window: %p width: %d height: %d depth: %d\n",
|
||||
subsystem->display, (void*) subsystem->root_window, subsystem->fb_image->width, subsystem->fb_image->height, subsystem->fb_image->depth);
|
||||
|
||||
subsystem->fb_pixmap = XShmCreatePixmap(subsystem->display,
|
||||
subsystem->root_window, subsystem->fb_image->data, &(subsystem->fb_shm_info),
|
||||
subsystem->fb_image->width, subsystem->fb_image->height, subsystem->fb_image->depth);
|
||||
@ -430,15 +500,13 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
|
||||
XVisualInfo template;
|
||||
XPixmapFormatValues* pf;
|
||||
XPixmapFormatValues* pfs;
|
||||
MONITOR_DEF* virtualScreen;
|
||||
|
||||
/**
|
||||
* To see if your X11 server supports shared pixmaps, use:
|
||||
* xdpyinfo -ext MIT-SHM | grep "shared pixmaps"
|
||||
*/
|
||||
|
||||
subsystem->use_xshm = TRUE;
|
||||
subsystem->use_xdamage = TRUE;
|
||||
|
||||
if (!getenv("DISPLAY"))
|
||||
{
|
||||
/* Set DISPLAY variable if not already set */
|
||||
@ -511,6 +579,18 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
|
||||
|
||||
XSelectInput(subsystem->display, subsystem->root_window, SubstructureNotifyMask);
|
||||
|
||||
if (subsystem->use_xfixes)
|
||||
{
|
||||
if (x11_shadow_xfixes_init(subsystem) < 0)
|
||||
subsystem->use_xfixes = FALSE;
|
||||
}
|
||||
|
||||
if (subsystem->use_xinerama)
|
||||
{
|
||||
if (x11_shadow_xinerama_init(subsystem) < 0)
|
||||
subsystem->use_xinerama = FALSE;
|
||||
}
|
||||
|
||||
if (subsystem->use_xshm)
|
||||
{
|
||||
if (x11_shadow_xshm_init(subsystem) < 0)
|
||||
@ -523,19 +603,28 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
|
||||
subsystem->use_xdamage = FALSE;
|
||||
}
|
||||
|
||||
x11_shadow_cursor_init(subsystem);
|
||||
|
||||
subsystem->event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, subsystem->xfds);
|
||||
|
||||
subsystem->monitorCount = 1;
|
||||
subsystem->monitors[0].left = 0;
|
||||
subsystem->monitors[0].top = 0;
|
||||
subsystem->monitors[0].right = subsystem->width;
|
||||
subsystem->monitors[0].bottom = subsystem->height;
|
||||
subsystem->monitors[0].flags = 1;
|
||||
virtualScreen = &(subsystem->virtualScreen);
|
||||
|
||||
if (subsystem->use_xshm)
|
||||
printf("Using X Shared Memory Extension (XShm)\n");
|
||||
virtualScreen->left = 0;
|
||||
virtualScreen->top = 0;
|
||||
virtualScreen->right = subsystem->width;
|
||||
virtualScreen->bottom = subsystem->height;
|
||||
virtualScreen->flags = 1;
|
||||
|
||||
if (subsystem->monitorCount < 1)
|
||||
{
|
||||
subsystem->monitorCount = 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;
|
||||
}
|
||||
|
||||
printf("X11 Extensions: XFixes: %d Xinerama: %d XDamage: %d XShm: %d\n",
|
||||
subsystem->use_xfixes, subsystem->use_xinerama, subsystem->use_xdamage, subsystem->use_xshm);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -617,6 +706,11 @@ x11ShadowSubsystem* x11_shadow_subsystem_new(rdpShadowServer* server)
|
||||
subsystem->MouseEvent = (pfnShadowMouseEvent) x11_shadow_input_mouse_event;
|
||||
subsystem->ExtendedMouseEvent = (pfnShadowExtendedMouseEvent) x11_shadow_input_extended_mouse_event;
|
||||
|
||||
subsystem->use_xshm = TRUE;
|
||||
subsystem->use_xfixes = TRUE;
|
||||
subsystem->use_xdamage = TRUE;
|
||||
subsystem->use_xinerama = TRUE;
|
||||
|
||||
return subsystem;
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,10 @@ typedef struct x11_shadow_subsystem x11ShadowSubsystem;
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#endif
|
||||
|
||||
#ifdef WITH_XINERAMA
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
#endif
|
||||
|
||||
struct x11_shadow_subsystem
|
||||
{
|
||||
RDP_SHADOW_SUBSYSTEM_COMMON();
|
||||
@ -66,7 +70,10 @@ struct x11_shadow_subsystem
|
||||
int scanline_pad;
|
||||
|
||||
BOOL use_xshm;
|
||||
BOOL use_xfixes;
|
||||
BOOL use_xdamage;
|
||||
BOOL use_xinerama;
|
||||
|
||||
XImage* fb_image;
|
||||
Pixmap fb_pixmap;
|
||||
Window root_window;
|
||||
|
@ -20,6 +20,11 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <freerdp/version.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
@ -35,6 +40,175 @@
|
||||
extern rdpShadowSubsystem* X11_ShadowCreateSubsystem(rdpShadowServer* server);
|
||||
#endif
|
||||
|
||||
static COMMAND_LINE_ARGUMENT_A shadow_args[] =
|
||||
{
|
||||
{ "port", COMMAND_LINE_VALUE_REQUIRED, "<number>", NULL, NULL, -1, NULL, "Server port" },
|
||||
{ "monitors", COMMAND_LINE_VALUE_OPTIONAL, "<0,1,2...>", NULL, NULL, -1, NULL, "Select or list monitors" },
|
||||
{ "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, NULL, NULL, NULL, -1, NULL, "Print version" },
|
||||
{ "help", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_HELP, NULL, NULL, NULL, -1, "?", "Print help" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
int shadow_server_print_command_line_help(int argc, char** argv)
|
||||
{
|
||||
char* str;
|
||||
int length;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
|
||||
printf("Usage: %s [options]\n", argv[0]);
|
||||
printf("\n");
|
||||
|
||||
printf("Syntax:\n");
|
||||
printf(" /flag (enables flag)\n");
|
||||
printf(" /option:<value> (specifies option with value)\n");
|
||||
printf(" +toggle -toggle (enables or disables toggle, where '/' is a synonym of '+')\n");
|
||||
printf("\n");
|
||||
|
||||
arg = shadow_args;
|
||||
|
||||
do
|
||||
{
|
||||
if (arg->Flags & COMMAND_LINE_VALUE_FLAG)
|
||||
{
|
||||
printf(" %s", "/");
|
||||
printf("%-20s", arg->Name);
|
||||
printf("\t%s\n", arg->Text);
|
||||
}
|
||||
else if ((arg->Flags & COMMAND_LINE_VALUE_REQUIRED) || (arg->Flags & COMMAND_LINE_VALUE_OPTIONAL))
|
||||
{
|
||||
printf(" %s", "/");
|
||||
|
||||
if (arg->Format)
|
||||
{
|
||||
length = (int) (strlen(arg->Name) + strlen(arg->Format) + 2);
|
||||
str = (char*) malloc(length + 1);
|
||||
sprintf_s(str, length + 1, "%s:%s", arg->Name, arg->Format);
|
||||
printf("%-20s", str);
|
||||
free(str);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%-20s", arg->Name);
|
||||
}
|
||||
|
||||
printf("\t%s\n", arg->Text);
|
||||
}
|
||||
else if (arg->Flags & COMMAND_LINE_VALUE_BOOL)
|
||||
{
|
||||
length = (int) strlen(arg->Name) + 32;
|
||||
str = (char*) malloc(length + 1);
|
||||
sprintf_s(str, length + 1, "%s (default:%s)", arg->Name,
|
||||
arg->Default ? "on" : "off");
|
||||
|
||||
printf(" %s", arg->Default ? "-" : "+");
|
||||
|
||||
printf("%-20s", str);
|
||||
free(str);
|
||||
|
||||
printf("\t%s\n", arg->Text);
|
||||
}
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int shadow_server_command_line_status_print(rdpShadowServer* server, int argc, char** argv, int status)
|
||||
{
|
||||
if (status == COMMAND_LINE_STATUS_PRINT_VERSION)
|
||||
{
|
||||
printf("FreeRDP version %s (git %s)\n", FREERDP_VERSION_FULL, GIT_REVISION);
|
||||
return COMMAND_LINE_STATUS_PRINT_VERSION;
|
||||
}
|
||||
else if (status == COMMAND_LINE_STATUS_PRINT)
|
||||
{
|
||||
return COMMAND_LINE_STATUS_PRINT;
|
||||
}
|
||||
else if (status < 0)
|
||||
{
|
||||
shadow_server_print_command_line_help(argc, argv);
|
||||
return COMMAND_LINE_STATUS_PRINT_HELP;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** argv)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
|
||||
if (argc < 2)
|
||||
return 1;
|
||||
|
||||
CommandLineClearArgumentsA(shadow_args);
|
||||
|
||||
flags = COMMAND_LINE_SEPARATOR_COLON;
|
||||
flags |= COMMAND_LINE_SIGIL_SLASH | COMMAND_LINE_SIGIL_PLUS_MINUS;
|
||||
|
||||
status = CommandLineParseArgumentsA(argc, (const char**) argv, shadow_args, flags, server, NULL, NULL);
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
arg = shadow_args;
|
||||
|
||||
do
|
||||
{
|
||||
if (!(arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT))
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "port")
|
||||
{
|
||||
server->port = (DWORD) atoi(arg->Value);
|
||||
}
|
||||
CommandLineSwitchDefault(arg)
|
||||
{
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
|
||||
arg = CommandLineFindArgumentA(shadow_args, "monitors");
|
||||
|
||||
if (arg)
|
||||
{
|
||||
if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
|
||||
{
|
||||
/* Select monitors */
|
||||
}
|
||||
else
|
||||
{
|
||||
int index;
|
||||
int width, height;
|
||||
MONITOR_DEF* monitor;
|
||||
rdpShadowSubsystem* subsystem = server->subsystem;
|
||||
|
||||
/* List monitors */
|
||||
|
||||
for (index = 0; index < subsystem->monitorCount; index++)
|
||||
{
|
||||
monitor = &(subsystem->monitors[index]);
|
||||
|
||||
width = monitor->right - monitor->left;
|
||||
height = monitor->bottom - monitor->top;
|
||||
|
||||
printf(" %s [%d] %dx%d\t+%d+%d\n",
|
||||
(monitor->flags == 1) ? "*" : " ", index,
|
||||
width, height, monitor->left, monitor->top);
|
||||
}
|
||||
|
||||
status = COMMAND_LINE_STATUS_PRINT;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void* shadow_server_thread(rdpShadowServer* server)
|
||||
{
|
||||
DWORD status;
|
||||
@ -121,23 +295,14 @@ int shadow_server_stop(rdpShadowServer* server)
|
||||
return 0;
|
||||
}
|
||||
|
||||
rdpShadowServer* shadow_server_new(int argc, char** argv)
|
||||
int shadow_server_init(rdpShadowServer* server)
|
||||
{
|
||||
rdpShadowServer* server;
|
||||
|
||||
server = (rdpShadowServer*) calloc(1, sizeof(rdpShadowServer));
|
||||
|
||||
if (!server)
|
||||
return NULL;
|
||||
|
||||
server->port = 3389;
|
||||
|
||||
server->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
server->listener = freerdp_listener_new();
|
||||
|
||||
if (!server->listener)
|
||||
return NULL;
|
||||
return -1;
|
||||
|
||||
server->listener->info = (void*) server;
|
||||
server->listener->PeerAccepted = shadow_client_accepted;
|
||||
@ -150,18 +315,60 @@ rdpShadowServer* shadow_server_new(int argc, char** argv)
|
||||
server->subsystem = server->CreateSubsystem(server);
|
||||
|
||||
if (!server->subsystem)
|
||||
return NULL;
|
||||
return -1;
|
||||
|
||||
if (server->subsystem->Init)
|
||||
server->subsystem->Init(server->subsystem);
|
||||
|
||||
server->screen = shadow_screen_new(server);
|
||||
|
||||
if (!server->screen)
|
||||
return NULL;
|
||||
return -1;
|
||||
|
||||
server->encoder = shadow_encoder_new(server);
|
||||
|
||||
if (!server->encoder)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int shadow_server_uninit(rdpShadowServer* server)
|
||||
{
|
||||
shadow_server_stop(server);
|
||||
|
||||
if (server->listener)
|
||||
{
|
||||
freerdp_listener_free(server->listener);
|
||||
server->listener = NULL;
|
||||
}
|
||||
|
||||
if (server->encoder)
|
||||
{
|
||||
shadow_encoder_free(server->encoder);
|
||||
server->encoder = NULL;
|
||||
}
|
||||
|
||||
if (server->subsystem)
|
||||
{
|
||||
server->subsystem->Free(server->subsystem);
|
||||
server->subsystem = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
rdpShadowServer* shadow_server_new()
|
||||
{
|
||||
rdpShadowServer* server;
|
||||
|
||||
server = (rdpShadowServer*) calloc(1, sizeof(rdpShadowServer));
|
||||
|
||||
if (!server)
|
||||
return NULL;
|
||||
|
||||
server->port = 3389;
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
@ -170,28 +377,34 @@ void shadow_server_free(rdpShadowServer* server)
|
||||
if (!server)
|
||||
return;
|
||||
|
||||
shadow_server_stop(server);
|
||||
|
||||
freerdp_listener_free(server->listener);
|
||||
|
||||
shadow_encoder_free(server->encoder);
|
||||
|
||||
server->subsystem->Free(server->subsystem);
|
||||
shadow_server_uninit(server);
|
||||
|
||||
free(server);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int status;
|
||||
DWORD dwExitCode;
|
||||
rdpShadowServer* server;
|
||||
|
||||
server = shadow_server_new(argc, argv);
|
||||
server = shadow_server_new();
|
||||
|
||||
if (!server)
|
||||
return 0;
|
||||
|
||||
shadow_server_start(server);
|
||||
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;
|
||||
|
||||
WaitForSingleObject(server->thread, INFINITE);
|
||||
|
||||
|
@ -61,15 +61,18 @@ BOOL shadow_client_capabilities(freerdp_peer* peer)
|
||||
|
||||
BOOL shadow_client_post_connect(freerdp_peer* peer)
|
||||
{
|
||||
rdpSettings* settings;
|
||||
rdpShadowClient* client;
|
||||
|
||||
client = (rdpShadowClient*) peer->context;
|
||||
settings = peer->settings;
|
||||
|
||||
fprintf(stderr, "Client from %s is activated\n", peer->hostname);
|
||||
settings->DesktopWidth = client->server->screen->width;
|
||||
settings->DesktopHeight = client->server->screen->height;
|
||||
settings->ColorDepth = 32;
|
||||
|
||||
peer->settings->DesktopWidth = client->server->screen->width;
|
||||
peer->settings->DesktopHeight = client->server->screen->height;
|
||||
peer->settings->ColorDepth = 32;
|
||||
fprintf(stderr, "Client from %s is activated (%dx%d@%d)\n",
|
||||
peer->hostname, settings->DesktopWidth, settings->DesktopHeight, settings->ColorDepth);
|
||||
|
||||
peer->update->DesktopResize(peer->update->context);
|
||||
|
||||
@ -151,10 +154,10 @@ int shadow_client_send_surface_bits(rdpShadowClient* client)
|
||||
encoder = server->encoder;
|
||||
surface = server->surface;
|
||||
|
||||
surfaceRect.left = 0;
|
||||
surfaceRect.top = 0;
|
||||
surfaceRect.right = surface->width;
|
||||
surfaceRect.bottom = surface->height;
|
||||
surfaceRect.left = surface->x;
|
||||
surfaceRect.top = surface->y;
|
||||
surfaceRect.right = surface->x + surface->width;
|
||||
surfaceRect.bottom = surface->y + surface->height;
|
||||
|
||||
region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect);
|
||||
|
||||
@ -163,8 +166,8 @@ int shadow_client_send_surface_bits(rdpShadowClient* client)
|
||||
|
||||
extents = region16_extents(&(surface->invalidRegion));
|
||||
|
||||
nXSrc = extents->left;
|
||||
nYSrc = extents->top;
|
||||
nXSrc = extents->left - surface->x;
|
||||
nYSrc = extents->top - surface->y;
|
||||
nWidth = extents->right - extents->left;
|
||||
nHeight = extents->bottom - extents->top;
|
||||
pSrcData = surface->data;
|
||||
@ -324,13 +327,13 @@ void* shadow_client_thread(rdpShadowClient* client)
|
||||
freerdp_peer* peer;
|
||||
rdpSettings* settings;
|
||||
rdpShadowServer* server;
|
||||
rdpShadowSurface* surface;
|
||||
rdpShadowScreen* screen;
|
||||
rdpShadowEncoder* encoder;
|
||||
rdpShadowSubsystem* subsystem;
|
||||
|
||||
server = client->server;
|
||||
screen = server->screen;
|
||||
encoder = server->encoder;
|
||||
surface = server->surface;
|
||||
subsystem = server->subsystem;
|
||||
|
||||
peer = ((rdpContext*) client)->peer;
|
||||
@ -393,14 +396,15 @@ void* shadow_client_thread(rdpShadowClient* client)
|
||||
{
|
||||
if (client->activated)
|
||||
{
|
||||
EnterCriticalSection(&(surface->lock));
|
||||
EnterCriticalSection(&(screen->lock));
|
||||
|
||||
if (subsystem->SurfaceCopy)
|
||||
subsystem->SurfaceCopy(subsystem);
|
||||
|
||||
shadow_client_send_surface_bits(client);
|
||||
region16_clear(&(surface->invalidRegion));
|
||||
LeaveCriticalSection(&(surface->lock));
|
||||
region16_clear(&(screen->invalidRegion));
|
||||
|
||||
LeaveCriticalSection(&(screen->lock));
|
||||
}
|
||||
|
||||
fps = encoder->fps;
|
||||
|
@ -26,6 +26,8 @@
|
||||
|
||||
rdpShadowScreen* shadow_screen_new(rdpShadowServer* server)
|
||||
{
|
||||
int x, y;
|
||||
int width, height;
|
||||
MONITOR_DEF* primary;
|
||||
rdpShadowScreen* screen;
|
||||
rdpShadowSubsystem* subsystem;
|
||||
@ -38,11 +40,22 @@ rdpShadowScreen* shadow_screen_new(rdpShadowServer* server)
|
||||
screen->server = server;
|
||||
subsystem = server->subsystem;
|
||||
|
||||
primary = &(subsystem->monitors[0]);
|
||||
screen->width = primary->right;
|
||||
screen->height = primary->bottom;
|
||||
if (!InitializeCriticalSectionAndSpinCount(&(screen->lock), 4000))
|
||||
return NULL;
|
||||
|
||||
screen->primary = shadow_surface_new(server, screen->width, screen->height);
|
||||
region16_init(&(screen->invalidRegion));
|
||||
|
||||
primary = &(subsystem->monitors[0]);
|
||||
|
||||
x = primary->left;
|
||||
y = primary->top;
|
||||
width = primary->right - primary->left;
|
||||
height = primary->bottom - primary->top;
|
||||
|
||||
screen->width = width;
|
||||
screen->height = height;
|
||||
|
||||
screen->primary = shadow_surface_new(server, x, y, width, height);
|
||||
|
||||
if (!screen->primary)
|
||||
return NULL;
|
||||
@ -57,6 +70,10 @@ void shadow_screen_free(rdpShadowScreen* screen)
|
||||
if (!screen)
|
||||
return;
|
||||
|
||||
DeleteCriticalSection(&(screen->lock));
|
||||
|
||||
region16_uninit(&(screen->invalidRegion));
|
||||
|
||||
if (screen->primary)
|
||||
{
|
||||
shadow_surface_free(screen->primary);
|
||||
|
@ -21,6 +21,9 @@
|
||||
|
||||
#include <freerdp/server/shadow.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
|
||||
struct rdp_shadow_screen
|
||||
{
|
||||
rdpShadowServer* server;
|
||||
@ -28,6 +31,9 @@ struct rdp_shadow_screen
|
||||
int width;
|
||||
int height;
|
||||
|
||||
CRITICAL_SECTION lock;
|
||||
REGION16 invalidRegion;
|
||||
|
||||
rdpShadowSurface* primary;
|
||||
};
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
#include "shadow_surface.h"
|
||||
|
||||
rdpShadowSurface* shadow_surface_new(rdpShadowServer* server, int width, int height)
|
||||
rdpShadowSurface* shadow_surface_new(rdpShadowServer* server, int x, int y, int width, int height)
|
||||
{
|
||||
rdpShadowSurface* surface;
|
||||
|
||||
@ -35,6 +35,8 @@ rdpShadowSurface* shadow_surface_new(rdpShadowServer* server, int width, int hei
|
||||
|
||||
surface->server = server;
|
||||
|
||||
surface->x = x;
|
||||
surface->y = y;
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
surface->scanline = (surface->width + (surface->width % 4)) * 4;
|
||||
|
@ -28,6 +28,8 @@ struct rdp_shadow_surface
|
||||
{
|
||||
rdpShadowServer* server;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
int scanline;
|
||||
@ -41,7 +43,7 @@ struct rdp_shadow_surface
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
rdpShadowSurface* shadow_surface_new(rdpShadowServer* server, int width, int height);
|
||||
rdpShadowSurface* shadow_surface_new(rdpShadowServer* server, int x, int y, int width, int height);
|
||||
void shadow_surface_free(rdpShadowSurface* surface);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
Loading…
Reference in New Issue
Block a user