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_surface rdpShadowSurface;
typedef struct rdp_shadow_encoder rdpShadowEncoder;
typedef struct rdp_shadow_subsystem rdpShadowSubsystem;
struct rdp_shadow_client
{
@ -47,10 +48,19 @@ struct rdp_shadow_server
rdpShadowScreen* screen;
rdpShadowSurface* surface;
rdpShadowEncoder* encoder;
rdpShadowSubsystem* subsystem;
DWORD port;
freerdp_listener* listener;
};
#define RDP_SHADOW_SUBSYSTEM_COMMON() \
rdpShadowServer* server
struct rdp_shadow_subsystem
{
RDP_SHADOW_SUBSYSTEM_COMMON();
};
#endif /* FREERDP_SERVER_SHADOW_H */

View File

@ -38,294 +38,5 @@
#include <winpr/synch.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"
#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 <freerdp/locale/keyboard.h>
#include <winpr/crt.h>
#include <winpr/input.h>
#include "x11_shadow.h"
int x11_shadow_cursor_init(x11ShadowServer* server)
{
#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)
void x11_shadow_input_synchronize_event(x11ShadowSubsystem* subsystem, UINT32 flags)
{
fprintf(stderr, "Client sent a synchronize event (flags:0x%X)\n", flags);
}
void x11_shadow_input_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
void x11_shadow_input_keyboard_event(x11ShadowSubsystem* subsystem, UINT16 flags, UINT16 code)
{
#ifdef WITH_XTEST
DWORD vkcode;
DWORD keycode;
BOOL extended = FALSE;
x11ShadowClient* context = (x11ShadowClient*) input->context;
x11ShadowServer* server = context->server;
if (flags & KBD_FLAGS_EXTENDED)
extended = TRUE;
@ -75,32 +51,30 @@ void x11_shadow_input_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
if (keycode != 0)
{
XTestGrabControl(server->display, True);
XTestGrabControl(subsystem->display, True);
if (flags & KBD_FLAGS_DOWN)
XTestFakeKeyEvent(server->display, keycode, True, 0);
XTestFakeKeyEvent(subsystem->display, keycode, True, 0);
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
}
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);
}
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
int button = 0;
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)
{
@ -111,13 +85,13 @@ void x11_shadow_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT1
button = (negative) ? 5 : 4;
XTestFakeButtonEvent(server->display, button, True, 0);
XTestFakeButtonEvent(server->display, button, False, 0);
XTestFakeButtonEvent(subsystem->display, button, True, 0);
XTestFakeButtonEvent(subsystem->display, button, False, 0);
}
else
{
if (flags & PTR_FLAGS_MOVE)
XTestFakeMotionEvent(server->display, 0, x, y, 0);
XTestFakeMotionEvent(subsystem->display, 0, x, y, 0);
if (flags & PTR_FLAGS_BUTTON1)
button = 1;
@ -130,23 +104,21 @@ void x11_shadow_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT1
down = TRUE;
if (button != 0)
XTestFakeButtonEvent(server->display, button, down, 0);
XTestFakeButtonEvent(subsystem->display, button, down, 0);
}
XTestGrabControl(server->display, False);
XTestGrabControl(subsystem->display, False);
#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
int button = 0;
BOOL down = FALSE;
x11ShadowClient* context = (x11ShadowClient*) input->context;
x11ShadowServer* server = context->server;
XTestGrabControl(server->display, True);
XTestFakeMotionEvent(server->display, 0, x, y, CurrentTime);
XTestGrabControl(subsystem->display, True);
XTestFakeMotionEvent(subsystem->display, 0, x, y, CurrentTime);
if (flags & PTR_XFLAGS_BUTTON1)
button = 8;
@ -157,17 +129,9 @@ void x11_shadow_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16
down = TRUE;
if (button != 0)
XTestFakeButtonEvent(server->display, button, down, 0);
XTestFakeButtonEvent(subsystem->display, button, down, 0);
XTestGrabControl(server->display, False);
XTestGrabControl(subsystem->display, False);
#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 <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/select.h>
#include <sys/signal.h>
@ -29,24 +32,292 @@
#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;
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;
free(server);
x11_shadow_subsystem_uninit((x11ShadowSubsystem*) subsystem);
free(subsystem);
}

View File

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

View File

@ -29,28 +29,26 @@
#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;
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);
image = server->fb_image;
XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap, subsystem->xdamage_gc, x, y, width, height, x, y);
image = subsystem->fb_image;
}
else
{
image = XGetImage(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;
}
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;
x11ShadowServer* server = context->server;
region.x = x;
region.y = y;
@ -58,39 +56,18 @@ void x11_shadow_xdamage_subtract_region(x11ShadowClient* context, int x, int y,
region.height = height;
#ifdef WITH_XFIXES
XFixesSetRegion(server->display, server->xdamage_region, &region, 1);
XDamageSubtract(server->display, server->xdamage, server->xdamage_region, None);
XFixesSetRegion(subsystem->display, subsystem->xdamage_region, &region, 1);
XDamageSubtract(subsystem->display, subsystem->xdamage, subsystem->xdamage_region, None);
#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;
RFX_RECT rect;
XImage* image;
rdpUpdate* update;
x11ShadowClient* context;
x11ShadowServer* server;
SURFACE_BITS_COMMAND* cmd;
RFX_RECT rect;
context = (x11ShadowClient*) client->context;
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)
if (subsystem->use_xshm)
{
/**
* 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.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 = &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
{
@ -122,73 +91,40 @@ int x11_shadow_update_encode(freerdp_peer* client, int x, int y, int width, int
rect.width = width;
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;
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);
}
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;
}
void x11_shadow_client_send_update(freerdp_peer* client)
{
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)
void* x11_shadow_update_thread(x11ShadowSubsystem* subsystem)
{
HANDLE event;
XEvent xevent;
DWORD beg, end;
DWORD diff, rate;
x11ShadowClient* context;
x11ShadowServer* server;
freerdp_peer* client;
XFixesCursorImage* ci;
int x, y, width, height;
XDamageNotifyEvent* notify;
client = (freerdp_peer*) param;
context = (x11ShadowClient*) client->context;
server = context->server;
rate = 1000 / 10;
event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, server->xfds);
event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, subsystem->xfds);
while (WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0)
{
beg = GetTickCount();
while (XPending(server->display) > 0)
while (XPending(subsystem->display) > 0)
{
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;
@ -197,18 +133,17 @@ void* x11_shadow_update_thread(void* param)
width = notify->area.width;
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)
x11_shadow_client_send_update(client);
/* send update */
}
}
#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);
}
#endif

View File

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

View File

@ -36,13 +36,11 @@ void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
server = (rdpShadowServer*) peer->ContextExtra;
client->server = server;
client->ext = x11_shadow_client_new(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)