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_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 */
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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, ®ion, 1);
|
||||
XDamageSubtract(server->display, server->xdamage, server->xdamage_region, None);
|
||||
XFixesSetRegion(subsystem->display, subsystem->xdamage_region, ®ion, 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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user