mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2025-06-03 00:00:20 +00:00
shadow: start structuring X11 code as shadow subsystem
This commit is contained in:
parent
5135467037
commit
3d57659efb
@ -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 */
|
||||||
|
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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, ®ion, 1);
|
XFixesSetRegion(subsystem->display, subsystem->xdamage_region, ®ion, 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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user