shadow: start structuring X11 code as shadow subsystem

This commit is contained in:
Marc-André Moreau 2014-07-11 23:01:34 -04:00
parent 5135467037
commit 3d57659efb
8 changed files with 352 additions and 476 deletions

View File

@ -30,6 +30,7 @@ typedef struct rdp_shadow_server rdpShadowServer;
typedef struct rdp_shadow_screen rdpShadowScreen; typedef struct rdp_shadow_screen rdpShadowScreen;
typedef struct rdp_shadow_surface rdpShadowSurface; typedef struct rdp_shadow_surface rdpShadowSurface;
typedef struct rdp_shadow_encoder rdpShadowEncoder; typedef struct rdp_shadow_encoder rdpShadowEncoder;
typedef struct rdp_shadow_subsystem rdpShadowSubsystem;
struct rdp_shadow_client struct rdp_shadow_client
{ {
@ -47,10 +48,19 @@ struct rdp_shadow_server
rdpShadowScreen* screen; rdpShadowScreen* screen;
rdpShadowSurface* surface; rdpShadowSurface* surface;
rdpShadowEncoder* encoder; rdpShadowEncoder* encoder;
rdpShadowSubsystem* subsystem;
DWORD port; DWORD port;
freerdp_listener* listener; freerdp_listener* listener;
}; };
#define RDP_SHADOW_SUBSYSTEM_COMMON() \
rdpShadowServer* server
struct rdp_shadow_subsystem
{
RDP_SHADOW_SUBSYSTEM_COMMON();
};
#endif /* FREERDP_SERVER_SHADOW_H */ #endif /* FREERDP_SERVER_SHADOW_H */

View File

@ -38,294 +38,5 @@
#include <winpr/synch.h> #include <winpr/synch.h>
#include <winpr/thread.h> #include <winpr/thread.h>
#include <freerdp/freerdp.h>
#include <freerdp/codec/color.h>
#include <freerdp/locale/keyboard.h>
#include <winpr/tools/makecert.h>
#include "x11_shadow.h" #include "x11_shadow.h"
#ifdef WITH_XDAMAGE
void x11_shadow_xdamage_init(x11ShadowServer* server)
{
int damage_event;
int damage_error;
int major, minor;
XGCValues values;
if (XDamageQueryExtension(server->display, &damage_event, &damage_error) == 0)
{
fprintf(stderr, "XDamageQueryExtension failed\n");
return;
}
XDamageQueryVersion(server->display, &major, &minor);
if (XDamageQueryVersion(server->display, &major, &minor) == 0)
{
fprintf(stderr, "XDamageQueryVersion failed\n");
return;
}
else if (major < 1)
{
fprintf(stderr, "XDamageQueryVersion failed: major:%d minor:%d\n", major, minor);
return;
}
server->xdamage_notify_event = damage_event + XDamageNotify;
server->xdamage = XDamageCreate(server->display, server->root_window, XDamageReportDeltaRectangles);
if (server->xdamage == None)
{
fprintf(stderr, "XDamageCreate failed\n");
return;
}
#ifdef WITH_XFIXES
server->xdamage_region = XFixesCreateRegion(server->display, NULL, 0);
if (server->xdamage_region == None)
{
fprintf(stderr, "XFixesCreateRegion failed\n");
XDamageDestroy(server->display, server->xdamage);
server->xdamage = None;
return;
}
#endif
values.subwindow_mode = IncludeInferiors;
server->xdamage_gc = XCreateGC(server->display, server->root_window, GCSubwindowMode, &values);
XSetFunction(server->display, server->xdamage_gc, GXcopy);
}
#endif
int x11_shadow_xshm_init(x11ShadowServer* server)
{
Bool pixmaps;
int major, minor;
if (XShmQueryExtension(server->display) != False)
{
XShmQueryVersion(server->display, &major, &minor, &pixmaps);
if (pixmaps != True)
{
fprintf(stderr, "XShmQueryVersion failed\n");
return -1;
}
}
else
{
fprintf(stderr, "XShmQueryExtension failed\n");
return -1;
}
server->fb_shm_info.shmid = -1;
server->fb_shm_info.shmaddr = (char*) -1;
server->fb_image = XShmCreateImage(server->display, server->visual, server->depth,
ZPixmap, NULL, &(server->fb_shm_info), server->width, server->height);
if (!server->fb_image)
{
fprintf(stderr, "XShmCreateImage failed\n");
return -1;
}
server->fb_shm_info.shmid = shmget(IPC_PRIVATE,
server->fb_image->bytes_per_line * server->fb_image->height, IPC_CREAT | 0600);
if (server->fb_shm_info.shmid == -1)
{
fprintf(stderr, "shmget failed\n");
return -1;
}
server->fb_shm_info.readOnly = False;
server->fb_shm_info.shmaddr = shmat(server->fb_shm_info.shmid, 0, 0);
server->fb_image->data = server->fb_shm_info.shmaddr;
if (server->fb_shm_info.shmaddr == ((char*) -1))
{
fprintf(stderr, "shmat failed\n");
return -1;
}
XShmAttach(server->display, &(server->fb_shm_info));
XSync(server->display, False);
shmctl(server->fb_shm_info.shmid, IPC_RMID, 0);
fprintf(stderr, "display: %p root_window: %p width: %d height: %d depth: %d\n",
server->display, (void*) server->root_window, server->fb_image->width, server->fb_image->height, server->fb_image->depth);
server->fb_pixmap = XShmCreatePixmap(server->display,
server->root_window, server->fb_image->data, &(server->fb_shm_info),
server->fb_image->width, server->fb_image->height, server->fb_image->depth);
return 0;
}
x11ShadowClient* x11_shadow_client_new(rdpShadowClient* rdp)
{
int i;
int pf_count;
int vi_count;
XVisualInfo* vi;
XVisualInfo* vis;
XVisualInfo template;
XPixmapFormatValues* pf;
XPixmapFormatValues* pfs;
x11ShadowServer* server;
x11ShadowClient* client;
client = (x11ShadowClient*) calloc(1, sizeof(x11ShadowClient));
if (!client)
return NULL;
server = (x11ShadowServer*) rdp->server->ext;
client->server = server;
/**
* Recent X11 servers drop support for shared pixmaps
* To see if your X11 server supports shared pixmaps, use:
* xdpyinfo -ext MIT-SHM | grep "shared pixmaps"
*/
server->use_xshm = TRUE;
setenv("DISPLAY", ":0", 1); /* Set DISPLAY variable if not already set */
if (!XInitThreads())
fprintf(stderr, "warning: XInitThreads() failure\n");
server->display = XOpenDisplay(NULL);
if (!server->display)
{
fprintf(stderr, "failed to open display: %s\n", XDisplayName(NULL));
exit(1);
}
server->xfds = ConnectionNumber(server->display);
server->number = DefaultScreen(server->display);
server->screen = ScreenOfDisplay(server->display, server->number);
server->depth = DefaultDepthOfScreen(server->screen);
server->width = WidthOfScreen(server->screen);
server->height = HeightOfScreen(server->screen);
server->root_window = DefaultRootWindow(server->display);
pfs = XListPixmapFormats(server->display, &pf_count);
if (!pfs)
{
fprintf(stderr, "XListPixmapFormats failed\n");
exit(1);
}
for (i = 0; i < pf_count; i++)
{
pf = pfs + i;
if (pf->depth == server->depth)
{
server->bpp = pf->bits_per_pixel;
server->scanline_pad = pf->scanline_pad;
break;
}
}
XFree(pfs);
ZeroMemory(&template, sizeof(template));
template.class = TrueColor;
template.screen = server->number;
vis = XGetVisualInfo(server->display, VisualClassMask | VisualScreenMask, &template, &vi_count);
if (!vis)
{
fprintf(stderr, "XGetVisualInfo failed\n");
exit(1);
}
for (i = 0; i < vi_count; i++)
{
vi = vis + i;
if (vi->depth == server->depth)
{
server->visual = vi->visual;
break;
}
}
XFree(vis);
XSelectInput(server->display, server->root_window, SubstructureNotifyMask);
if (server->use_xshm)
{
if (x11_shadow_xshm_init(server) < 0)
server->use_xshm = FALSE;
}
if (server->use_xshm)
printf("Using X Shared Memory Extension (XShm)\n");
#ifdef WITH_XDAMAGE
x11_shadow_xdamage_init(server);
#endif
x11_shadow_cursor_init(server);
server->bytesPerPixel = 4;
server->activePeerCount = 0;
freerdp_keyboard_init(0);
client->rfx_context = rfx_context_new(TRUE);
client->rfx_context->mode = RLGR3;
client->rfx_context->width = server->width;
client->rfx_context->height = server->height;
rfx_context_set_pixel_format(client->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
client->s = Stream_New(NULL, 65536);
Stream_Clear(client->s);
return client;
}
void x11_shadow_client_free(x11ShadowClient* client)
{
x11ShadowServer* server;
if (!client)
return;
server = client->server;
if (server->display)
XCloseDisplay(server->display);
Stream_Free(client->s, TRUE);
rfx_context_free(client->rfx_context);
}
BOOL x11_shadow_peer_activate(freerdp_peer* client)
{
x11ShadowClient* context = (x11ShadowClient*) client->context;
x11ShadowServer* server = context->server;
rfx_context_reset(context->rfx_context);
context->activated = TRUE;
server->activePeerCount++;
context->monitorThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
x11_shadow_update_thread, (void*) client, 0, NULL);
return TRUE;
}

View File

@ -23,46 +23,22 @@
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <freerdp/locale/keyboard.h>
#include <winpr/crt.h> #include <winpr/crt.h>
#include <winpr/input.h> #include <winpr/input.h>
#include "x11_shadow.h" #include "x11_shadow.h"
int x11_shadow_cursor_init(x11ShadowServer* server) void x11_shadow_input_synchronize_event(x11ShadowSubsystem* subsystem, UINT32 flags)
{
#ifdef WITH_XFIXES
int event;
int error;
if (!XFixesQueryExtension(server->display, &event, &error))
{
fprintf(stderr, "XFixesQueryExtension failed\n");
return -1;
}
server->xfixes_notify_event = event + XFixesCursorNotify;
XFixesSelectCursorInput(server->display, DefaultRootWindow(server->display), XFixesDisplayCursorNotifyMask);
#endif
return 0;
}
void x11_shadow_input_synchronize_event(rdpInput* input, UINT32 flags)
{ {
fprintf(stderr, "Client sent a synchronize event (flags:0x%X)\n", flags); fprintf(stderr, "Client sent a synchronize event (flags:0x%X)\n", flags);
} }
void x11_shadow_input_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) void x11_shadow_input_keyboard_event(x11ShadowSubsystem* subsystem, UINT16 flags, UINT16 code)
{ {
#ifdef WITH_XTEST #ifdef WITH_XTEST
DWORD vkcode; DWORD vkcode;
DWORD keycode; DWORD keycode;
BOOL extended = FALSE; BOOL extended = FALSE;
x11ShadowClient* context = (x11ShadowClient*) input->context;
x11ShadowServer* server = context->server;
if (flags & KBD_FLAGS_EXTENDED) if (flags & KBD_FLAGS_EXTENDED)
extended = TRUE; extended = TRUE;
@ -75,32 +51,30 @@ void x11_shadow_input_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
if (keycode != 0) if (keycode != 0)
{ {
XTestGrabControl(server->display, True); XTestGrabControl(subsystem->display, True);
if (flags & KBD_FLAGS_DOWN) if (flags & KBD_FLAGS_DOWN)
XTestFakeKeyEvent(server->display, keycode, True, 0); XTestFakeKeyEvent(subsystem->display, keycode, True, 0);
else if (flags & KBD_FLAGS_RELEASE) else if (flags & KBD_FLAGS_RELEASE)
XTestFakeKeyEvent(server->display, keycode, False, 0); XTestFakeKeyEvent(subsystem->display, keycode, False, 0);
XTestGrabControl(server->display, False); XTestGrabControl(subsystem->display, False);
} }
#endif #endif
} }
void x11_shadow_input_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) void x11_shadow_input_unicode_keyboard_event(x11ShadowSubsystem* subsystem, UINT16 flags, UINT16 code)
{ {
fprintf(stderr, "Client sent a unicode keyboard event (flags:0x%X code:0x%X)\n", flags, code); fprintf(stderr, "Client sent a unicode keyboard event (flags:0x%X code:0x%X)\n", flags, code);
} }
void x11_shadow_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, UINT16 x, UINT16 y)
{ {
#ifdef WITH_XTEST #ifdef WITH_XTEST
int button = 0; int button = 0;
BOOL down = FALSE; BOOL down = FALSE;
x11ShadowClient* context = (x11ShadowClient*) input->context;
x11ShadowServer* server = context->server;
XTestGrabControl(server->display, True); XTestGrabControl(subsystem->display, True);
if (flags & PTR_FLAGS_WHEEL) if (flags & PTR_FLAGS_WHEEL)
{ {
@ -111,13 +85,13 @@ void x11_shadow_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT1
button = (negative) ? 5 : 4; button = (negative) ? 5 : 4;
XTestFakeButtonEvent(server->display, button, True, 0); XTestFakeButtonEvent(subsystem->display, button, True, 0);
XTestFakeButtonEvent(server->display, button, False, 0); XTestFakeButtonEvent(subsystem->display, button, False, 0);
} }
else else
{ {
if (flags & PTR_FLAGS_MOVE) if (flags & PTR_FLAGS_MOVE)
XTestFakeMotionEvent(server->display, 0, x, y, 0); XTestFakeMotionEvent(subsystem->display, 0, x, y, 0);
if (flags & PTR_FLAGS_BUTTON1) if (flags & PTR_FLAGS_BUTTON1)
button = 1; button = 1;
@ -130,23 +104,21 @@ void x11_shadow_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT1
down = TRUE; down = TRUE;
if (button != 0) if (button != 0)
XTestFakeButtonEvent(server->display, button, down, 0); XTestFakeButtonEvent(subsystem->display, button, down, 0);
} }
XTestGrabControl(server->display, False); XTestGrabControl(subsystem->display, False);
#endif #endif
} }
void x11_shadow_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, UINT16 x, UINT16 y)
{ {
#ifdef WITH_XTEST #ifdef WITH_XTEST
int button = 0; int button = 0;
BOOL down = FALSE; BOOL down = FALSE;
x11ShadowClient* context = (x11ShadowClient*) input->context;
x11ShadowServer* server = context->server;
XTestGrabControl(server->display, True); XTestGrabControl(subsystem->display, True);
XTestFakeMotionEvent(server->display, 0, x, y, CurrentTime); XTestFakeMotionEvent(subsystem->display, 0, x, y, CurrentTime);
if (flags & PTR_XFLAGS_BUTTON1) if (flags & PTR_XFLAGS_BUTTON1)
button = 8; button = 8;
@ -157,17 +129,9 @@ void x11_shadow_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16
down = TRUE; down = TRUE;
if (button != 0) if (button != 0)
XTestFakeButtonEvent(server->display, button, down, 0); XTestFakeButtonEvent(subsystem->display, button, down, 0);
XTestGrabControl(server->display, False); XTestGrabControl(subsystem->display, False);
#endif #endif
} }
void x11_shadow_input_register_callbacks(rdpInput* input)
{
input->SynchronizeEvent = x11_shadow_input_synchronize_event;
input->KeyboardEvent = x11_shadow_input_keyboard_event;
input->UnicodeKeyboardEvent = x11_shadow_input_unicode_keyboard_event;
input->MouseEvent = x11_shadow_input_mouse_event;
input->ExtendedMouseEvent = x11_shadow_input_extended_mouse_event;
}

View File

@ -20,7 +20,10 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/signal.h> #include <sys/signal.h>
@ -29,24 +32,292 @@
#include "x11_shadow.h" #include "x11_shadow.h"
x11ShadowServer* x11_shadow_server_new(rdpShadowServer* rdp) int x11_shadow_cursor_init(x11ShadowSubsystem* subsystem)
{ {
x11ShadowServer* server; #ifdef WITH_XFIXES
int event;
int error;
server = (x11ShadowServer*) calloc(1, sizeof(x11ShadowServer)); if (!XFixesQueryExtension(subsystem->display, &event, &error))
{
fprintf(stderr, "XFixesQueryExtension failed\n");
return -1;
}
if (!server) subsystem->xfixes_notify_event = event + XFixesCursorNotify;
XFixesSelectCursorInput(subsystem->display, DefaultRootWindow(subsystem->display), XFixesDisplayCursorNotifyMask);
#endif
return 0;
}
#ifdef WITH_XDAMAGE
void x11_shadow_xdamage_init(x11ShadowSubsystem* subsystem)
{
int damage_event;
int damage_error;
int major, minor;
XGCValues values;
if (XDamageQueryExtension(subsystem->display, &damage_event, &damage_error) == 0)
{
fprintf(stderr, "XDamageQueryExtension failed\n");
return;
}
XDamageQueryVersion(subsystem->display, &major, &minor);
if (XDamageQueryVersion(subsystem->display, &major, &minor) == 0)
{
fprintf(stderr, "XDamageQueryVersion failed\n");
return;
}
else if (major < 1)
{
fprintf(stderr, "XDamageQueryVersion failed: major:%d minor:%d\n", major, minor);
return;
}
subsystem->xdamage_notify_event = damage_event + XDamageNotify;
subsystem->xdamage = XDamageCreate(subsystem->display, subsystem->root_window, XDamageReportDeltaRectangles);
if (subsystem->xdamage == None)
{
fprintf(stderr, "XDamageCreate failed\n");
return;
}
#ifdef WITH_XFIXES
subsystem->xdamage_region = XFixesCreateRegion(subsystem->display, NULL, 0);
if (subsystem->xdamage_region == None)
{
fprintf(stderr, "XFixesCreateRegion failed\n");
XDamageDestroy(subsystem->display, subsystem->xdamage);
subsystem->xdamage = None;
return;
}
#endif
values.subwindow_mode = IncludeInferiors;
subsystem->xdamage_gc = XCreateGC(subsystem->display, subsystem->root_window, GCSubwindowMode, &values);
XSetFunction(subsystem->display, subsystem->xdamage_gc, GXcopy);
}
#endif
int x11_shadow_xshm_init(x11ShadowSubsystem* server)
{
Bool pixmaps;
int major, minor;
if (XShmQueryExtension(server->display) != False)
{
XShmQueryVersion(server->display, &major, &minor, &pixmaps);
if (pixmaps != True)
{
fprintf(stderr, "XShmQueryVersion failed\n");
return -1;
}
}
else
{
fprintf(stderr, "XShmQueryExtension failed\n");
return -1;
}
server->fb_shm_info.shmid = -1;
server->fb_shm_info.shmaddr = (char*) -1;
server->fb_image = XShmCreateImage(server->display, server->visual, server->depth,
ZPixmap, NULL, &(server->fb_shm_info), server->width, server->height);
if (!server->fb_image)
{
fprintf(stderr, "XShmCreateImage failed\n");
return -1;
}
server->fb_shm_info.shmid = shmget(IPC_PRIVATE,
server->fb_image->bytes_per_line * server->fb_image->height, IPC_CREAT | 0600);
if (server->fb_shm_info.shmid == -1)
{
fprintf(stderr, "shmget failed\n");
return -1;
}
server->fb_shm_info.readOnly = False;
server->fb_shm_info.shmaddr = shmat(server->fb_shm_info.shmid, 0, 0);
server->fb_image->data = server->fb_shm_info.shmaddr;
if (server->fb_shm_info.shmaddr == ((char*) -1))
{
fprintf(stderr, "shmat failed\n");
return -1;
}
XShmAttach(server->display, &(server->fb_shm_info));
XSync(server->display, False);
shmctl(server->fb_shm_info.shmid, IPC_RMID, 0);
fprintf(stderr, "display: %p root_window: %p width: %d height: %d depth: %d\n",
server->display, (void*) server->root_window, server->fb_image->width, server->fb_image->height, server->fb_image->depth);
server->fb_pixmap = XShmCreatePixmap(server->display,
server->root_window, server->fb_image->data, &(server->fb_shm_info),
server->fb_image->width, server->fb_image->height, server->fb_image->depth);
return 0;
}
int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
{
int i;
int pf_count;
int vi_count;
XVisualInfo* vi;
XVisualInfo* vis;
XVisualInfo template;
XPixmapFormatValues* pf;
XPixmapFormatValues* pfs;
/**
* Recent X11 servers drop support for shared pixmaps
* To see if your X11 server supports shared pixmaps, use:
* xdpyinfo -ext MIT-SHM | grep "shared pixmaps"
*/
subsystem->use_xshm = TRUE;
setenv("DISPLAY", ":0", 1); /* Set DISPLAY variable if not already set */
if (!XInitThreads())
fprintf(stderr, "warning: XInitThreads() failure\n");
subsystem->display = XOpenDisplay(NULL);
if (!subsystem->display)
{
fprintf(stderr, "failed to open display: %s\n", XDisplayName(NULL));
exit(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);
pfs = XListPixmapFormats(subsystem->display, &pf_count);
if (!pfs)
{
fprintf(stderr, "XListPixmapFormats failed\n");
exit(1);
}
for (i = 0; i < pf_count; i++)
{
pf = pfs + i;
if (pf->depth == subsystem->depth)
{
subsystem->bpp = pf->bits_per_pixel;
subsystem->scanline_pad = pf->scanline_pad;
break;
}
}
XFree(pfs);
ZeroMemory(&template, sizeof(template));
template.class = TrueColor;
template.screen = subsystem->number;
vis = XGetVisualInfo(subsystem->display, VisualClassMask | VisualScreenMask, &template, &vi_count);
if (!vis)
{
fprintf(stderr, "XGetVisualInfo failed\n");
exit(1);
}
for (i = 0; i < vi_count; i++)
{
vi = vis + i;
if (vi->depth == subsystem->depth)
{
subsystem->visual = vi->visual;
break;
}
}
XFree(vis);
XSelectInput(subsystem->display, subsystem->root_window, SubstructureNotifyMask);
if (subsystem->use_xshm)
{
if (x11_shadow_xshm_init(subsystem) < 0)
subsystem->use_xshm = FALSE;
}
if (subsystem->use_xshm)
printf("Using X Shared Memory Extension (XShm)\n");
#ifdef WITH_XDAMAGE
x11_shadow_xdamage_init(subsystem);
#endif
x11_shadow_cursor_init(subsystem);
subsystem->bytesPerPixel = 4;
return 1;
}
int x11_shadow_subsystem_uninit(x11ShadowSubsystem* subsystem)
{
if (!subsystem)
return -1;
if (subsystem->display)
{
XCloseDisplay(subsystem->display);
subsystem->display = NULL;
}
return 1;
}
rdpShadowSubsystem* x11_shadow_subsystem_new(rdpShadowServer* server)
{
x11ShadowSubsystem* subsystem;
subsystem = (x11ShadowSubsystem*) calloc(1, sizeof(x11ShadowSubsystem));
if (!subsystem)
return NULL; return NULL;
signal(SIGPIPE, SIG_IGN); subsystem->server = server;
return server; x11_shadow_subsystem_init(subsystem);
return (rdpShadowSubsystem*) subsystem;
} }
void x11_shadow_server_free(x11ShadowServer* server) void x11_shadow_subsystem_free(rdpShadowSubsystem* subsystem)
{ {
if (!server) if (!subsystem)
return; return;
free(server); x11_shadow_subsystem_uninit((x11ShadowSubsystem*) subsystem);
free(subsystem);
} }

View File

@ -21,8 +21,7 @@
#include <freerdp/server/shadow.h> #include <freerdp/server/shadow.h>
typedef struct x11_shadow_client x11ShadowClient; typedef struct x11_shadow_subsystem x11ShadowSubsystem;
typedef struct x11_shadow_server x11ShadowServer;
#include <winpr/crt.h> #include <winpr/crt.h>
#include <winpr/synch.h> #include <winpr/synch.h>
@ -55,11 +54,11 @@ typedef struct x11_shadow_server x11ShadowServer;
#include <X11/extensions/Xdamage.h> #include <X11/extensions/Xdamage.h>
#endif #endif
struct x11_shadow_server struct x11_shadow_subsystem
{ {
DWORD port; RDP_SHADOW_SUBSYSTEM_COMMON();
HANDLE thread; HANDLE thread;
freerdp_listener* listener;
int bpp; int bpp;
int xfds; int xfds;
@ -73,7 +72,6 @@ struct x11_shadow_server
Display* display; Display* display;
int scanline_pad; int scanline_pad;
int bytesPerPixel; int bytesPerPixel;
int activePeerCount;
BOOL use_xshm; BOOL use_xshm;
XImage* fb_image; XImage* fb_image;
@ -93,32 +91,12 @@ struct x11_shadow_server
#endif #endif
}; };
struct x11_shadow_client
{
rdpContext _p;
wStream* s;
BOOL activated;
HANDLE monitorThread;
RFX_CONTEXT* rfx_context;
x11ShadowServer* server;
};
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
FREERDP_API x11ShadowServer* x11_shadow_server_new(rdpShadowServer* rdp); rdpShadowSubsystem* x11_shadow_subsystem_new(rdpShadowServer* server);
FREERDP_API void x11_shadow_server_free(x11ShadowServer* server); void x11_shadow_subsystem_free(rdpShadowSubsystem* subsystem);
x11ShadowClient* x11_shadow_client_new(rdpShadowClient* rdp);
void x11_shadow_client_free(x11ShadowClient* client);
void* x11_shadow_update_thread(void* param);
int x11_shadow_cursor_init(x11ShadowServer* server);
void x11_shadow_input_register_callbacks(rdpInput* input);
int x11_shadow_update_encode(freerdp_peer* client, int x, int y, int width, int height);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -29,28 +29,26 @@
#include "x11_shadow.h" #include "x11_shadow.h"
XImage* x11_shadow_snapshot(x11ShadowClient* context, int x, int y, int width, int height) XImage* x11_shadow_snapshot(x11ShadowSubsystem* subsystem, int x, int y, int width, int height)
{ {
XImage* image; XImage* image;
x11ShadowServer* server = context->server;
if (server->use_xshm) if (subsystem->use_xshm)
{ {
XCopyArea(server->display, server->root_window, server->fb_pixmap, server->xdamage_gc, x, y, width, height, x, y); XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap, subsystem->xdamage_gc, x, y, width, height, x, y);
image = server->fb_image; image = subsystem->fb_image;
} }
else else
{ {
image = XGetImage(server->display, server->root_window, x, y, width, height, AllPlanes, ZPixmap); image = XGetImage(subsystem->display, subsystem->root_window, x, y, width, height, AllPlanes, ZPixmap);
} }
return image; return image;
} }
void x11_shadow_xdamage_subtract_region(x11ShadowClient* context, int x, int y, int width, int height) void x11_shadow_xdamage_subtract_region(x11ShadowSubsystem* subsystem, int x, int y, int width, int height)
{ {
XRectangle region; XRectangle region;
x11ShadowServer* server = context->server;
region.x = x; region.x = x;
region.y = y; region.y = y;
@ -58,39 +56,18 @@ void x11_shadow_xdamage_subtract_region(x11ShadowClient* context, int x, int y,
region.height = height; region.height = height;
#ifdef WITH_XFIXES #ifdef WITH_XFIXES
XFixesSetRegion(server->display, server->xdamage_region, &region, 1); XFixesSetRegion(subsystem->display, subsystem->xdamage_region, &region, 1);
XDamageSubtract(server->display, server->xdamage, server->xdamage_region, None); XDamageSubtract(subsystem->display, subsystem->xdamage, subsystem->xdamage_region, None);
#endif #endif
} }
int x11_shadow_update_encode(freerdp_peer* client, int x, int y, int width, int height) int x11_shadow_update_encode(x11ShadowSubsystem* subsystem, int x, int y, int width, int height)
{ {
wStream* s;
BYTE* data; BYTE* data;
RFX_RECT rect;
XImage* image; XImage* image;
rdpUpdate* update; RFX_RECT rect;
x11ShadowClient* context;
x11ShadowServer* server;
SURFACE_BITS_COMMAND* cmd;
context = (x11ShadowClient*) client->context; if (subsystem->use_xshm)
server = context->server;
update = client->update;
cmd = &update->surface_bits_command;
if (width * height <= 0)
{
cmd->bitmapDataLength = 0;
return -1;
}
s = context->s;
Stream_Clear(s);
Stream_SetPosition(s, 0);
if (server->use_xshm)
{ {
/** /**
* Passing an offset source rectangle to rfx_compose_message() * Passing an offset source rectangle to rfx_compose_message()
@ -102,18 +79,10 @@ int x11_shadow_update_encode(freerdp_peer* client, int x, int y, int width, int
rect.width = width; rect.width = width;
rect.height = height; rect.height = height;
image = x11_shadow_snapshot(context, x, y, width, height); image = x11_shadow_snapshot(subsystem, x, y, width, height);
data = (BYTE*) image->data; data = (BYTE*) image->data;
data = &data[(y * image->bytes_per_line) + (x * image->bits_per_pixel / 8)]; data = &data[(y * image->bytes_per_line) + (x * image->bits_per_pixel / 8)];
rfx_compose_message(context->rfx_context, s, &rect, 1, data,
width, height, image->bytes_per_line);
cmd->destLeft = x;
cmd->destTop = y;
cmd->destRight = x + width;
cmd->destBottom = y + height;
} }
else else
{ {
@ -122,73 +91,40 @@ int x11_shadow_update_encode(freerdp_peer* client, int x, int y, int width, int
rect.width = width; rect.width = width;
rect.height = height; rect.height = height;
image = x11_shadow_snapshot(context, x, y, width, height); image = x11_shadow_snapshot(subsystem, x, y, width, height);
data = (BYTE*) image->data; data = (BYTE*) image->data;
rfx_compose_message(context->rfx_context, s, &rect, 1, data,
width, height, image->bytes_per_line);
cmd->destLeft = x;
cmd->destTop = y;
cmd->destRight = x + width;
cmd->destBottom = y + height;
XDestroyImage(image); XDestroyImage(image);
} }
cmd->bpp = 32;
cmd->codecID = client->settings->RemoteFxCodecId;
cmd->width = width;
cmd->height = height;
cmd->bitmapDataLength = Stream_GetPosition(s);
cmd->bitmapData = Stream_Buffer(s);
return 0; return 0;
} }
void x11_shadow_client_send_update(freerdp_peer* client) void* x11_shadow_update_thread(x11ShadowSubsystem* subsystem)
{
rdpUpdate* update;
SURFACE_BITS_COMMAND* cmd;
update = client->update;
cmd = &update->surface_bits_command;
if (cmd->bitmapDataLength)
update->SurfaceBits(update->context, cmd);
}
void* x11_shadow_update_thread(void* param)
{ {
HANDLE event; HANDLE event;
XEvent xevent; XEvent xevent;
DWORD beg, end; DWORD beg, end;
DWORD diff, rate; DWORD diff, rate;
x11ShadowClient* context; XFixesCursorImage* ci;
x11ShadowServer* server;
freerdp_peer* client;
int x, y, width, height; int x, y, width, height;
XDamageNotifyEvent* notify; XDamageNotifyEvent* notify;
client = (freerdp_peer*) param;
context = (x11ShadowClient*) client->context;
server = context->server;
rate = 1000 / 10; rate = 1000 / 10;
event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, server->xfds); event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, subsystem->xfds);
while (WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0) while (WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0)
{ {
beg = GetTickCount(); beg = GetTickCount();
while (XPending(server->display) > 0) while (XPending(subsystem->display) > 0)
{ {
ZeroMemory(&xevent, sizeof(xevent)); ZeroMemory(&xevent, sizeof(xevent));
XNextEvent(server->display, &xevent); XNextEvent(subsystem->display, &xevent);
if (xevent.type == server->xdamage_notify_event) if (xevent.type == subsystem->xdamage_notify_event)
{ {
notify = (XDamageNotifyEvent*) &xevent; notify = (XDamageNotifyEvent*) &xevent;
@ -197,18 +133,17 @@ void* x11_shadow_update_thread(void* param)
width = notify->area.width; width = notify->area.width;
height = notify->area.height; height = notify->area.height;
if (x11_shadow_update_encode(client, x, y, width, height) >= 0) if (x11_shadow_update_encode(subsystem, x, y, width, height) >= 0)
{ {
x11_shadow_xdamage_subtract_region(context, x, y, width, height); x11_shadow_xdamage_subtract_region(subsystem, x, y, width, height);
if (context->activated) /* send update */
x11_shadow_client_send_update(client);
} }
} }
#ifdef WITH_XFIXES #ifdef WITH_XFIXES
else if (xevent.type == server->xfixes_notify_event) else if (xevent.type == subsystem->xfixes_notify_event)
{ {
XFixesCursorImage* ci = XFixesGetCursorImage(server->display); ci = XFixesGetCursorImage(subsystem->display);
XFree(ci); XFree(ci);
} }
#endif #endif

View File

@ -20,6 +20,11 @@
#include "config.h" #include "config.h"
#endif #endif
#ifndef _WIN32
#include <sys/select.h>
#include <sys/signal.h>
#endif
#include "shadow.h" #include "shadow.h"
void* shadow_server_thread(rdpShadowServer* server) void* shadow_server_thread(rdpShadowServer* server)
@ -59,6 +64,10 @@ void* shadow_server_thread(rdpShadowServer* server)
int shadow_server_start(rdpShadowServer* server) int shadow_server_start(rdpShadowServer* server)
{ {
#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif
if (server->listener->Open(server->listener, NULL, server->port)) if (server->listener->Open(server->listener, NULL, server->port))
{ {
server->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) server->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
@ -116,9 +125,9 @@ rdpShadowServer* shadow_server_new(int argc, char** argv)
if (!server->encoder) if (!server->encoder)
return NULL; return NULL;
server->ext = x11_shadow_server_new(server); server->subsystem = x11_shadow_subsystem_new(server);
if (!server->ext) if (!server->subsystem)
return NULL; return NULL;
return server; return server;
@ -133,7 +142,7 @@ void shadow_server_free(rdpShadowServer* server)
shadow_encoder_free(server->encoder); shadow_encoder_free(server->encoder);
x11_shadow_server_free(server->ext); x11_shadow_subsystem_free(server->subsystem);
free(server); free(server);
} }

View File

@ -36,13 +36,11 @@ void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
server = (rdpShadowServer*) peer->ContextExtra; server = (rdpShadowServer*) peer->ContextExtra;
client->server = server; client->server = server;
client->ext = x11_shadow_client_new(client);
} }
void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client) void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client)
{ {
x11_shadow_client_free(client->ext);
} }
BOOL shadow_client_get_fds(freerdp_peer* peer, void** rfds, int* rcount) BOOL shadow_client_get_fds(freerdp_peer* peer, void** rfds, int* rcount)