Merge branch 'shadow' of github.com:awakecoding/FreeRDP

Conflicts:
	libfreerdp/core/capabilities.c
This commit is contained in:
Marc-André Moreau 2014-09-19 14:39:43 -04:00
commit 72e7507bee
35 changed files with 2258 additions and 859 deletions

View File

@ -467,6 +467,9 @@ FREERDP_API int freerdp_image_move(BYTE* pData, DWORD Format, int nStep, int nXD
FREERDP_API int freerdp_image_fill(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, FREERDP_API int freerdp_image_fill(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst,
int nWidth, int nHeight, UINT32 color); int nWidth, int nHeight, UINT32 color);
FREERDP_API int freerdp_image_copy_from_retina(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst,
int nWidth, int nHeight, BYTE* pSrcData, int nSrcStep, int nXSrc, int nYSrc);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -43,6 +43,13 @@ struct _REGION16 {
}; };
typedef struct _REGION16 REGION16; typedef struct _REGION16 REGION16;
/** computes if two rectangles are equal
* @param r1 first rectangle
* @param r2 second rectangle
* @return if the two rectangles are equal
*/
FREERDP_API BOOL rectangles_equal(const RECTANGLE_16 *r1, const RECTANGLE_16 *r2);
/** computes if two rectangles intersect /** computes if two rectangles intersect
* @param r1 first rectangle * @param r1 first rectangle
* @param r2 second rectangle * @param r2 second rectangle
@ -77,6 +84,12 @@ FREERDP_API const RECTANGLE_16 *region16_rects(const REGION16 *region, int *nbRe
/** @return the extents rectangle of this region */ /** @return the extents rectangle of this region */
FREERDP_API const RECTANGLE_16 *region16_extents(const REGION16 *region); FREERDP_API const RECTANGLE_16 *region16_extents(const REGION16 *region);
/** returns if the rectangle is empty
* @param rect
* @return if the rectangle is empty
*/
FREERDP_API BOOL rectangle_is_empty(const RECTANGLE_16 *rect);
/** returns if the region is empty /** returns if the region is empty
* @param region * @param region
* @return if the region is empty * @return if the region is empty

View File

@ -47,16 +47,19 @@ typedef struct rdp_shadow_encoder rdpShadowEncoder;
typedef struct rdp_shadow_capture rdpShadowCapture; typedef struct rdp_shadow_capture rdpShadowCapture;
typedef struct rdp_shadow_subsystem rdpShadowSubsystem; typedef struct rdp_shadow_subsystem rdpShadowSubsystem;
typedef rdpShadowSubsystem* (*pfnShadowCreateSubsystem)(rdpShadowServer* server); typedef struct _RDP_SHADOW_ENTRY_POINTS RDP_SHADOW_ENTRY_POINTS;
typedef int (*pfnShadowSubsystemEntry)(RDP_SHADOW_ENTRY_POINTS* pEntryPoints);
typedef rdpShadowSubsystem* (*pfnShadowSubsystemNew)(void);
typedef void (*pfnShadowSubsystemFree)(rdpShadowSubsystem* subsystem);
typedef int (*pfnShadowSubsystemInit)(rdpShadowSubsystem* subsystem); typedef int (*pfnShadowSubsystemInit)(rdpShadowSubsystem* subsystem);
typedef int (*pfnShadowSubsystemUninit)(rdpShadowSubsystem* subsystem); typedef int (*pfnShadowSubsystemUninit)(rdpShadowSubsystem* subsystem);
typedef int (*pfnShadowSubsystemStart)(rdpShadowSubsystem* subsystem); typedef int (*pfnShadowSubsystemStart)(rdpShadowSubsystem* subsystem);
typedef int (*pfnShadowSubsystemStop)(rdpShadowSubsystem* subsystem); typedef int (*pfnShadowSubsystemStop)(rdpShadowSubsystem* subsystem);
typedef void (*pfnShadowSubsystemFree)(rdpShadowSubsystem* subsystem);
typedef int (*pfnShadowSurfaceCopy)(rdpShadowSubsystem* subsystem); typedef int (*pfnShadowEnumMonitors)(MONITOR_DEF* monitors, int maxMonitors);
typedef int (*pfnShadowSurfaceUpdate)(rdpShadowSubsystem* subsystem, REGION16* region);
typedef int (*pfnShadowSynchronizeEvent)(rdpShadowSubsystem* subsystem, UINT32 flags); typedef int (*pfnShadowSynchronizeEvent)(rdpShadowSubsystem* subsystem, UINT32 flags);
typedef int (*pfnShadowKeyboardEvent)(rdpShadowSubsystem* subsystem, UINT16 flags, UINT16 code); typedef int (*pfnShadowKeyboardEvent)(rdpShadowSubsystem* subsystem, UINT16 flags, UINT16 code);
@ -79,6 +82,7 @@ struct rdp_shadow_client
rdpShadowServer* server; rdpShadowServer* server;
rdpShadowSurface* lobby; rdpShadowSurface* lobby;
rdpShadowEncoder* encoder; rdpShadowEncoder* encoder;
rdpShadowSubsystem* subsystem;
HANDLE vcm; HANDLE vcm;
EncomspServerContext* encomsp; EncomspServerContext* encomsp;
@ -99,33 +103,45 @@ struct rdp_shadow_server
DWORD port; DWORD port;
BOOL mayView; BOOL mayView;
BOOL mayInteract; BOOL mayInteract;
BOOL shareSubRect;
int selectedMonitor;
RECTANGLE_16 subRect;
char* ipcSocket; char* ipcSocket;
char* ConfigPath; char* ConfigPath;
char* CertificateFile; char* CertificateFile;
char* PrivateKeyFile; char* PrivateKeyFile;
CRITICAL_SECTION lock; CRITICAL_SECTION lock;
freerdp_listener* listener; freerdp_listener* listener;
pfnShadowCreateSubsystem CreateSubsystem; };
struct _RDP_SHADOW_ENTRY_POINTS
{
pfnShadowSubsystemNew New;
pfnShadowSubsystemFree Free;
pfnShadowSubsystemInit Init;
pfnShadowSubsystemUninit Uninit;
pfnShadowSubsystemStart Start;
pfnShadowSubsystemStop Stop;
pfnShadowEnumMonitors EnumMonitors;
}; };
#define RDP_SHADOW_SUBSYSTEM_COMMON() \ #define RDP_SHADOW_SUBSYSTEM_COMMON() \
RDP_SHADOW_ENTRY_POINTS ep; \
HANDLE event; \ HANDLE event; \
int monitorCount; \ int numMonitors; \
int captureFrameRate; \
int selectedMonitor; \
MONITOR_DEF monitors[16]; \ MONITOR_DEF monitors[16]; \
MONITOR_DEF virtualScreen; \ MONITOR_DEF virtualScreen; \
HANDLE updateEvent; \ HANDLE updateEvent; \
BOOL suppressOutput; \
REGION16 invalidRegion; \ REGION16 invalidRegion; \
wMessagePipe* MsgPipe; \
SYNCHRONIZATION_BARRIER barrier; \ SYNCHRONIZATION_BARRIER barrier; \
\ \
pfnShadowSubsystemInit Init; \
pfnShadowSubsystemUninit Uninit; \
pfnShadowSubsystemStart Start; \
pfnShadowSubsystemStop Stop; \
pfnShadowSubsystemFree Free; \
\
pfnShadowSurfaceCopy SurfaceCopy; \
pfnShadowSurfaceUpdate SurfaceUpdate; \
\
pfnShadowSynchronizeEvent SynchronizeEvent; \ pfnShadowSynchronizeEvent SynchronizeEvent; \
pfnShadowKeyboardEvent KeyboardEvent; \ pfnShadowKeyboardEvent KeyboardEvent; \
pfnShadowUnicodeKeyboardEvent UnicodeKeyboardEvent; \ pfnShadowUnicodeKeyboardEvent UnicodeKeyboardEvent; \
@ -139,5 +155,27 @@ struct rdp_shadow_subsystem
RDP_SHADOW_SUBSYSTEM_COMMON(); RDP_SHADOW_SUBSYSTEM_COMMON();
}; };
#ifdef __cplusplus
extern "C" {
#endif
FREERDP_API int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** argv);
FREERDP_API int shadow_server_command_line_status_print(rdpShadowServer* server, int argc, char** argv, int status);
FREERDP_API int shadow_server_start(rdpShadowServer* server);
FREERDP_API int shadow_server_stop(rdpShadowServer* server);
FREERDP_API int shadow_server_init(rdpShadowServer* server);
FREERDP_API int shadow_server_uninit(rdpShadowServer* server);
FREERDP_API int shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors, const char* name);
FREERDP_API rdpShadowServer* shadow_server_new();
FREERDP_API void shadow_server_free(rdpShadowServer* server);
#ifdef __cplusplus
}
#endif
#endif /* FREERDP_SERVER_SHADOW_H */ #endif /* FREERDP_SERVER_SHADOW_H */

View File

@ -147,8 +147,9 @@ typedef void (*pRefreshRect)(rdpContext* context, BYTE count, RECTANGLE_16* area
typedef void (*pSuppressOutput)(rdpContext* context, BYTE allow, RECTANGLE_16* area); typedef void (*pSuppressOutput)(rdpContext* context, BYTE allow, RECTANGLE_16* area);
typedef void (*pSurfaceCommand)(rdpContext* context, wStream* s); typedef void (*pSurfaceCommand)(rdpContext* context, wStream* s);
typedef void (*pSurfaceBits)(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command); typedef void (*pSurfaceBits)(rdpContext* context, SURFACE_BITS_COMMAND* surfaceBitsCommand);
typedef void (*pSurfaceFrameMarker)(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker); typedef void (*pSurfaceFrameMarker)(rdpContext* context, SURFACE_FRAME_MARKER* surfaceFrameMarker);
typedef void (*pSurfaceFrameBits)(rdpContext* context, SURFACE_BITS_COMMAND* cmd, BOOL first, BOOL last, UINT32 frameId);
typedef void (*pSurfaceFrameAcknowledge)(rdpContext* context, UINT32 frameId); typedef void (*pSurfaceFrameAcknowledge)(rdpContext* context, UINT32 frameId);
struct rdp_update struct rdp_update
@ -180,8 +181,9 @@ struct rdp_update
pSurfaceCommand SurfaceCommand; /* 64 */ pSurfaceCommand SurfaceCommand; /* 64 */
pSurfaceBits SurfaceBits; /* 65 */ pSurfaceBits SurfaceBits; /* 65 */
pSurfaceFrameMarker SurfaceFrameMarker; /* 66 */ pSurfaceFrameMarker SurfaceFrameMarker; /* 66 */
pSurfaceFrameAcknowledge SurfaceFrameAcknowledge; /* 67 */ pSurfaceFrameBits SurfaceFrameBits; /* 67 */
UINT32 paddingE[80 - 68]; /* 68 */ pSurfaceFrameAcknowledge SurfaceFrameAcknowledge; /* 68 */
UINT32 paddingE[80 - 69]; /* 69 */
/* internal */ /* internal */

View File

@ -3075,3 +3075,62 @@ int freerdp_image_fill(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst,
return 0; return 0;
} }
int freerdp_image_copy_from_retina(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst,
int nWidth, int nHeight, BYTE* pSrcData, int nSrcStep, int nXSrc, int nYSrc)
{
int x, y;
int nSrcPad;
int nDstPad;
int srcBitsPerPixel;
int srcBytesPerPixel;
int dstBitsPerPixel;
int dstBytesPerPixel;
srcBitsPerPixel = 24;
srcBytesPerPixel = 8;
if (nSrcStep < 0)
nSrcStep = srcBytesPerPixel * nWidth;
dstBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(DstFormat);
dstBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(DstFormat) / 8);
if (nDstStep < 0)
nDstStep = dstBytesPerPixel * nWidth;
nSrcPad = (nSrcStep - (nWidth * srcBytesPerPixel));
nDstPad = (nDstStep - (nWidth * dstBytesPerPixel));
if (dstBytesPerPixel == 4)
{
UINT32 R, G, B;
BYTE* pSrcPixel;
BYTE* pDstPixel;
pSrcPixel = &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)];
pDstPixel = &pDstData[(nYDst * nDstStep) + (nXDst * 4)];
for (y = 0; y < nHeight; y++)
{
for (x = 0; x < nWidth; x++)
{
/* simple box filter scaling, could be improved with better algorithm */
B = pSrcPixel[0] + pSrcPixel[4] + pSrcPixel[nSrcStep + 0] + pSrcPixel[nSrcStep + 4];
G = pSrcPixel[1] + pSrcPixel[5] + pSrcPixel[nSrcStep + 1] + pSrcPixel[nSrcStep + 5];
R = pSrcPixel[2] + pSrcPixel[6] + pSrcPixel[nSrcStep + 2] + pSrcPixel[nSrcStep + 6];
pSrcPixel += 8;
*pDstPixel++ = (BYTE) (B >> 2);
*pDstPixel++ = (BYTE) (G >> 2);
*pDstPixel++ = (BYTE) (R >> 2);
*pDstPixel++ = 0xFF;
}
pSrcPixel = &pSrcPixel[nSrcPad + nSrcStep];
pDstPixel = &pDstPixel[nDstPad];
}
}
return 1;
}

View File

@ -130,6 +130,11 @@ static RECTANGLE_16 *region16_extents_noconst(REGION16 *region)
return &region->extents; return &region->extents;
} }
BOOL rectangle_is_empty(const RECTANGLE_16 *rect)
{
return (rect->left + rect->top + rect->right + rect->bottom) ? TRUE : FALSE;
}
BOOL region16_is_empty(const REGION16 *region) BOOL region16_is_empty(const REGION16 *region)
{ {
assert(region); assert(region);
@ -138,6 +143,12 @@ BOOL region16_is_empty(const REGION16 *region)
return (region->data->nbRects == 0); return (region->data->nbRects == 0);
} }
BOOL rectangles_equal(const RECTANGLE_16 *r1, const RECTANGLE_16 *r2)
{
return ((r1->left == r2->left) && (r1->top == r2->top) &&
(r1->right == r2->right) && (r1->bottom == r2->bottom)) ? TRUE : FALSE;
}
BOOL rectangles_intersects(const RECTANGLE_16 *r1, const RECTANGLE_16 *r2) BOOL rectangles_intersects(const RECTANGLE_16 *r1, const RECTANGLE_16 *r2)
{ {
RECTANGLE_16 tmp; RECTANGLE_16 tmp;

View File

@ -344,8 +344,15 @@ BOOL rdp_read_bitmap_capability_set(wStream* s, UINT16 length, rdpSettings* sett
settings->DesktopHeight = desktopHeight; settings->DesktopHeight = desktopHeight;
} }
if (settings->DrawAllowSkipAlpha)
settings->DrawAllowSkipAlpha = (drawingFlags & DRAW_ALLOW_SKIP_ALPHA) ? TRUE : FALSE; settings->DrawAllowSkipAlpha = (drawingFlags & DRAW_ALLOW_SKIP_ALPHA) ? TRUE : FALSE;
if (settings->DrawAllowDynamicColorFidelity)
settings->DrawAllowDynamicColorFidelity = (drawingFlags & DRAW_ALLOW_DYNAMIC_COLOR_FIDELITY) ? TRUE : FALSE;
if (settings->DrawAllowColorSubsampling)
settings->DrawAllowColorSubsampling = (drawingFlags & DRAW_ALLOW_COLOR_SUBSAMPLING) ? TRUE : FALSE;
return TRUE; return TRUE;
} }
@ -370,10 +377,10 @@ void rdp_write_bitmap_capability_set(wStream* s, rdpSettings* settings)
if (settings->DrawAllowSkipAlpha) if (settings->DrawAllowSkipAlpha)
drawingFlags |= DRAW_ALLOW_SKIP_ALPHA; drawingFlags |= DRAW_ALLOW_SKIP_ALPHA;
if (settings->DrawAllowColorSubsampling) if (settings->DrawAllowDynamicColorFidelity)
drawingFlags |= DRAW_ALLOW_DYNAMIC_COLOR_FIDELITY; drawingFlags |= DRAW_ALLOW_DYNAMIC_COLOR_FIDELITY;
if (settings->DrawAllowDynamicColorFidelity) if (settings->DrawAllowColorSubsampling)
drawingFlags |= DRAW_ALLOW_COLOR_SUBSAMPLING; /* currently unimplemented */ drawingFlags |= DRAW_ALLOW_COLOR_SUBSAMPLING; /* currently unimplemented */
/* While bitmap_decode.c now implements YCoCg, in turning it /* While bitmap_decode.c now implements YCoCg, in turning it

View File

@ -1337,6 +1337,15 @@ BOOL gcc_read_client_cluster_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
if (flags & REDIRECTED_SESSIONID_FIELD_VALID) if (flags & REDIRECTED_SESSIONID_FIELD_VALID)
settings->RedirectedSessionId = redirectedSessionId; settings->RedirectedSessionId = redirectedSessionId;
if (blockLength != 8)
{
if (Stream_GetRemainingLength(s) >= (blockLength - 8))
{
/* The old Microsoft Mac RDP client can send a pad here */
Stream_Seek(s, (blockLength - 8));
}
}
return TRUE; return TRUE;
} }

View File

@ -79,16 +79,16 @@ static const char* inet_ntop(int af, const void* src, char* dst, size_t cnt)
static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_address, UINT16 port) static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_address, UINT16 port)
{ {
rdpListener* listener = (rdpListener*) instance->listener;
int status; int status;
int sockfd; int sockfd;
char servname[10]; char addr[64];
struct addrinfo hints = { 0 };
struct addrinfo* res;
struct addrinfo* ai;
int option_value;
void* sin_addr; void* sin_addr;
char buf[50]; int option_value;
char servname[16];
struct addrinfo* ai;
struct addrinfo* res;
struct addrinfo hints = { 0 };
rdpListener* listener = (rdpListener*) instance->listener;
#ifdef _WIN32 #ifdef _WIN32
u_long arg; u_long arg;
#endif #endif
@ -96,7 +96,7 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a
hints.ai_family = AF_UNSPEC; hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
if (bind_address == NULL) if (!bind_address)
hints.ai_flags = AI_PASSIVE; hints.ai_flags = AI_PASSIVE;
sprintf_s(servname, sizeof(servname), "%d", port); sprintf_s(servname, sizeof(servname), "%d", port);
@ -112,9 +112,9 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a
return FALSE; return FALSE;
} }
for (ai = res; ai && listener->num_sockfds < 5; ai = ai->ai_next) for (ai = res; ai && (listener->num_sockfds < 5); ai = ai->ai_next)
{ {
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) if ((ai->ai_family != AF_INET) && (ai->ai_family != AF_INET6))
continue; continue;
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
@ -125,6 +125,16 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a
continue; continue;
} }
if (ai->ai_family == AF_INET)
sin_addr = &(((struct sockaddr_in*) ai->ai_addr)->sin_addr);
else
sin_addr = &(((struct sockaddr_in6*) ai->ai_addr)->sin6_addr);
inet_ntop(ai->ai_family, sin_addr, addr, sizeof(addr));
if (strcmp(addr, "::") == 0)
continue;
option_value = 1; option_value = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &option_value, sizeof(option_value)) == -1) if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &option_value, sizeof(option_value)) == -1)
@ -166,12 +176,7 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a
listener->events[listener->num_sockfds] = CreateFileDescriptorEvent(NULL, FALSE, FALSE, sockfd); listener->events[listener->num_sockfds] = CreateFileDescriptorEvent(NULL, FALSE, FALSE, sockfd);
listener->num_sockfds++; listener->num_sockfds++;
if (ai->ai_family == AF_INET) WLog_INFO(TAG, "Listening on %s:%s", addr, servname);
sin_addr = &(((struct sockaddr_in*) ai->ai_addr)->sin_addr);
else
sin_addr = &(((struct sockaddr_in6*) ai->ai_addr)->sin6_addr);
WLog_ERR(TAG, "Listening on %s port %s.\n", inet_ntop(ai->ai_family, sin_addr, buf, sizeof(buf)), servname);
} }
freeaddrinfo(res); freeaddrinfo(res);

View File

@ -867,7 +867,7 @@ static void update_send_surface_command(rdpContext* context, wStream* s)
Stream_Release(update); Stream_Release(update);
} }
static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command) static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surfaceBitsCommand)
{ {
wStream* s; wStream* s;
rdpRdp* rdp = context->rdp; rdpRdp* rdp = context->rdp;
@ -875,9 +875,9 @@ static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND*
update_force_flush(context); update_force_flush(context);
s = fastpath_update_pdu_init(rdp->fastpath); s = fastpath_update_pdu_init(rdp->fastpath);
Stream_EnsureRemainingCapacity(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH + (int) surface_bits_command->bitmapDataLength); Stream_EnsureRemainingCapacity(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH + (int) surfaceBitsCommand->bitmapDataLength);
update_write_surfcmd_surface_bits_header(s, surface_bits_command); update_write_surfcmd_surface_bits_header(s, surfaceBitsCommand);
Stream_Write(s, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); Stream_Write(s, surfaceBitsCommand->bitmapData, surfaceBitsCommand->bitmapDataLength);
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s); fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s);
update_force_flush(context); update_force_flush(context);
@ -885,7 +885,7 @@ static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND*
Stream_Release(s); Stream_Release(s);
} }
static void update_send_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker) static void update_send_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surfaceFrameMarker)
{ {
wStream* s; wStream* s;
rdpRdp* rdp = context->rdp; rdpRdp* rdp = context->rdp;
@ -893,7 +893,34 @@ static void update_send_surface_frame_marker(rdpContext* context, SURFACE_FRAME_
update_force_flush(context); update_force_flush(context);
s = fastpath_update_pdu_init(rdp->fastpath); s = fastpath_update_pdu_init(rdp->fastpath);
update_write_surfcmd_frame_marker(s, surface_frame_marker->frameAction, surface_frame_marker->frameId); update_write_surfcmd_frame_marker(s, surfaceFrameMarker->frameAction, surfaceFrameMarker->frameId);
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s);
update_force_flush(context);
Stream_Release(s);
}
static void update_send_surface_frame_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd, BOOL first, BOOL last, UINT32 frameId)
{
wStream* s;
rdpRdp* rdp = context->rdp;
update_force_flush(context);
s = fastpath_update_pdu_init(rdp->fastpath);
Stream_EnsureRemainingCapacity(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH + (int) cmd->bitmapDataLength + 16);
if (first)
update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_BEGIN, frameId);
update_write_surfcmd_surface_bits_header(s, cmd);
Stream_Write(s, cmd->bitmapData, cmd->bitmapDataLength);
if (last)
update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_END, frameId);
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s); fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s);
update_force_flush(context); update_force_flush(context);
@ -1596,6 +1623,7 @@ void update_register_server_callbacks(rdpUpdate* update)
update->SurfaceBits = update_send_surface_bits; update->SurfaceBits = update_send_surface_bits;
update->SurfaceFrameMarker = update_send_surface_frame_marker; update->SurfaceFrameMarker = update_send_surface_frame_marker;
update->SurfaceCommand = update_send_surface_command; update->SurfaceCommand = update_send_surface_command;
update->SurfaceFrameBits = update_send_surface_frame_bits;
update->PlaySound = update_send_play_sound; update->PlaySound = update_send_play_sound;
update->primary->DstBlt = update_send_dstblt; update->primary->DstBlt = update_send_dstblt;
update->primary->PatBlt = update_send_patblt; update->primary->PatBlt = update_send_patblt;

View File

@ -27,7 +27,7 @@ if(FREERDP_VENDOR)
if(NOT WIN32) if(NOT WIN32)
if(APPLE AND (NOT IOS)) if(APPLE AND (NOT IOS))
add_subdirectory(Mac) #add_subdirectory(Mac)
endif() endif()
else() else()
#add_subdirectory(Windows) #add_subdirectory(Windows)

View File

@ -30,26 +30,23 @@
static const AUDIO_FORMAT supported_audio_formats[] = static const AUDIO_FORMAT supported_audio_formats[] =
{ {
{ WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, NULL }, { WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, NULL },
{ WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, NULL } { WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, NULL }
}; };
static void mf_peer_audin_opening(audin_server_context* context) static void mf_peer_audin_opening(audin_server_context* context)
{ {
WLog_INFO(TAG, "AUDIN opening.");
/* Simply choose the first format supported by the client. */
context->SelectFormat(context, 0); context->SelectFormat(context, 0);
} }
static void mf_peer_audin_open_result(audin_server_context* context, UINT32 result) static void mf_peer_audin_open_result(audin_server_context* context, UINT32 result)
{ {
WLog_INFO(TAG, "AUDIN open result %d.", result);
} }
static void mf_peer_audin_receive_samples(audin_server_context* context, const void* buf, int nframes) static void mf_peer_audin_receive_samples(audin_server_context* context, const void* buf, int nframes)
{ {
WLog_INFO(TAG, "AUDIN receive %d frames.", nframes);
} }
void mf_peer_audin_init(mfPeerContext* context) void mf_peer_audin_init(mfPeerContext* context)

View File

@ -26,7 +26,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
//#include <util.h>
#include "mf_event.h" #include "mf_event.h"
@ -191,7 +190,7 @@ mfEventQueue* mf_event_queue_new()
event_queue->events = (mfEvent**) malloc(sizeof(mfEvent*) * event_queue->size); event_queue->events = (mfEvent**) malloc(sizeof(mfEvent*) * event_queue->size);
if (pipe(event_queue->pipe_fd) < 0) if (pipe(event_queue->pipe_fd) < 0)
WLog_ERR(TAG, "mf_event_queue_new: pipe failed"); return NULL;
pthread_mutex_init(&(event_queue->mutex), NULL); pthread_mutex_init(&(event_queue->mutex), NULL);
} }

View File

@ -27,38 +27,33 @@
#include "mf_info.h" #include "mf_info.h"
#include "mf_mountain_lion.h" #include "mf_mountain_lion.h"
//#include "mf_update.h"
#include <freerdp/log.h>
#define TAG SERVER_TAG("mac")
static mfInfo* mfInfoInstance = NULL; static mfInfo* mfInfoInstance = NULL;
//static int _IDcount = 0;
int mf_info_lock(mfInfo* mfi) int mf_info_lock(mfInfo* mfi)
{ {
int status = pthread_mutex_lock(&mfi->mutex); int status = pthread_mutex_lock(&mfi->mutex);
switch (status) { switch (status)
{
case 0: case 0:
return TRUE; return TRUE;
break; break;
default: default:
WLog_ERR(TAG, "mf_info_lock failed with %#X", status);
return -1; return -1;
break; break;
} }
return 1;
} }
int mf_info_try_lock(mfInfo* mfi, UINT32 ms) int mf_info_try_lock(mfInfo* mfi, UINT32 ms)
{ {
int status = pthread_mutex_trylock(&mfi->mutex); int status = pthread_mutex_trylock(&mfi->mutex);
switch (status) { switch (status)
{
case 0: case 0:
return TRUE; return TRUE;
break; break;
@ -68,28 +63,29 @@ int mf_info_try_lock(mfInfo* mfi, UINT32 ms)
break; break;
default: default:
WLog_ERR(TAG, "mf_info_try_lock failed with %#X", status);
return -1; return -1;
break; break;
} }
return 1;
} }
int mf_info_unlock(mfInfo* mfi) int mf_info_unlock(mfInfo* mfi)
{ {
int status = pthread_mutex_unlock(&mfi->mutex); int status = pthread_mutex_unlock(&mfi->mutex);
switch (status) { switch (status)
{
case 0: case 0:
return TRUE; return TRUE;
break; break;
default: default:
WLog_ERR(TAG, "mf_info_unlock failed with %#X", status);
return -1; return -1;
break; break;
} }
return 1;
} }
mfInfo* mf_info_init() mfInfo* mf_info_init()
@ -99,52 +95,16 @@ mfInfo* mf_info_init()
mfi = (mfInfo*) malloc(sizeof(mfInfo)); mfi = (mfInfo*) malloc(sizeof(mfInfo));
memset(mfi, 0, sizeof(mfInfo)); memset(mfi, 0, sizeof(mfInfo));
if (mfi != NULL) if (mfi != NULL)
{ {
/* HKEY hKey; pthread_mutex_init(&mfi->mutex, NULL);
LONG status;
DWORD dwType;
DWORD dwSize;
DWORD dwValue;
*/
int mutexInitStatus = pthread_mutex_init(&mfi->mutex, NULL);
if (mutexInitStatus != 0)
{
WLog_ERR(TAG, _T("CreateMutex error: %#X"), mutexInitStatus);
}
mfi->peers = (freerdp_peer**) malloc(sizeof(freerdp_peer*) * MF_INFO_MAXPEERS); mfi->peers = (freerdp_peer**) malloc(sizeof(freerdp_peer*) * MF_INFO_MAXPEERS);
memset(mfi->peers, 0, sizeof(freerdp_peer*) * MF_INFO_MAXPEERS); memset(mfi->peers, 0, sizeof(freerdp_peer*) * MF_INFO_MAXPEERS);
//Set FPS
mfi->framesPerSecond = MF_INFO_DEFAULT_FPS; mfi->framesPerSecond = MF_INFO_DEFAULT_FPS;
/*status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
if (status == ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey, _T("FramesPerSecond"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
mfi->framesPerSecond = dwValue;
}
RegCloseKey(hKey);*/
//Set input toggle
mfi->input_disabled = FALSE; mfi->input_disabled = FALSE;
/*status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
if (status == ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey, _T("DisableInput"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
{
if (dwValue != 0)
mfi->input_disabled = TRUE;
}
}
RegCloseKey(hKey);*/
} }
return mfi; return mfi;
@ -164,21 +124,15 @@ void mf_info_peer_register(mfInfo* mfi, mfPeerContext* context)
{ {
int i; int i;
int peerId; int peerId;
if (mfi->peerCount == MF_INFO_MAXPEERS) if (mfi->peerCount == MF_INFO_MAXPEERS)
{ {
WLog_ERR(TAG, "TODO: socketClose on OS X");
//context->socketClose = TRUE;
mf_info_unlock(mfi); mf_info_unlock(mfi);
return; return;
} }
context->info = mfi; context->info = mfi;
//get the offset of the top left corner of selected screen
//EnumDisplayMonitors(NULL, NULL, mf_info_monEnumCB, 0);
//_IDcount = 0;
//initialize screen capture
if (mfi->peerCount == 0) if (mfi->peerCount == 0)
{ {
mf_mlion_display_info(&mfi->servscreen_width, &mfi->servscreen_height, &mfi->scale); mf_mlion_display_info(&mfi->servscreen_width, &mfi->servscreen_height, &mfi->scale);
@ -186,8 +140,8 @@ void mf_info_peer_register(mfInfo* mfi, mfPeerContext* context)
mf_mlion_start_getting_screen_updates(); mf_mlion_start_getting_screen_updates();
} }
//look trhough the array of peers until an empty slot
peerId = NULL; peerId = NULL;
for(i=0; i<MF_INFO_MAXPEERS; ++i) for(i=0; i<MF_INFO_MAXPEERS; ++i)
{ {
//empty index will be our peer id //empty index will be our peer id
@ -201,11 +155,8 @@ void mf_info_peer_register(mfInfo* mfi, mfPeerContext* context)
mfi->peers[peerId] = ((rdpContext*) context)->peer; mfi->peers[peerId] = ((rdpContext*) context)->peer;
mfi->peers[peerId]->pId = peerId; mfi->peers[peerId]->pId = peerId;
mfi->peerCount++; mfi->peerCount++;
//WLog_DBG(TAG, "Registering Peer: id=%d #=%d\n", peerId, mfi->peerCount);
mf_info_unlock(mfi); mf_info_unlock(mfi);
//mfreerdp_server_peer_callback_event(peerId, MF_SRV_CALLBACK_EVENT_CONNECT);
} }
} }
@ -219,16 +170,10 @@ void mf_info_peer_unregister(mfInfo* mfi, mfPeerContext* context)
mfi->peers[peerId] = NULL; mfi->peers[peerId] = NULL;
mfi->peerCount--; mfi->peerCount--;
//WLog_DBG(TAG, "Unregistering Peer: id=%d, #=%d\n", peerId, mfi->peerCount);
//screen capture cleanup
if (mfi->peerCount == 0) if (mfi->peerCount == 0)
{
mf_mlion_stop_getting_screen_updates(); mf_mlion_stop_getting_screen_updates();
}
mf_info_unlock(mfi);
//mfreerdp_server_peer_callback_event(peerId, MF_SRV_CALLBACK_EVENT_DISCONNECT); mf_info_unlock(mfi);
} }
} }
@ -242,14 +187,7 @@ BOOL mf_info_have_updates(mfInfo* mfi)
void mf_info_update_changes(mfInfo* mfi) void mf_info_update_changes(mfInfo* mfi)
{ {
/*#ifdef WITH_WIN8
mf_dxgi_nextFrame(mfi, mfi->framesPerSecond * 1000);
#else
GETCHANGESBUF* buf;
buf = (GETCHANGESBUF*) mfi->changeBuffer;
mfi->nextUpdate = buf->buffer->counter;
#endif*/
} }
void mf_info_find_invalid_region(mfInfo* mfi) void mf_info_find_invalid_region(mfInfo* mfi)
@ -274,9 +212,9 @@ void mf_info_invalidate_full_screen(mfInfo* mfi)
BOOL mf_info_have_invalid_region(mfInfo* mfi) BOOL mf_info_have_invalid_region(mfInfo* mfi)
{ {
if (mfi->invalid.width * mfi->invalid.height == 0) { if (mfi->invalid.width * mfi->invalid.height == 0)
return FALSE; return FALSE;
}
return TRUE; return TRUE;
} }
@ -291,22 +229,3 @@ void mf_info_getScreenData(mfInfo* mfi, long* width, long* height, BYTE** pBits,
*pBits = *pBits + (mfi->invalid.x * 4) + (*pitch * mfi->invalid.y); *pBits = *pBits + (mfi->invalid.x * 4) + (*pitch * mfi->invalid.y);
} }
/*
BOOL CALLBACK mf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
mfInfo * mfi;
mfi = mf_info_get_instance();
if(_IDcount == mfi->screenID)
{
mfi->servscreen_xoffset = lprcMonitor->left;
mfi->servscreen_yoffset = lprcMonitor->top;
}
_IDcount++;
return TRUE;
}
*/

View File

@ -396,34 +396,6 @@ void mf_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
CFRelease(scroll); CFRelease(scroll);
CFRelease(source); CFRelease(source);
} }
/*
///////////////////////////////////////////////
// We dont support horizontal scrolling yet...
///////////////////////////////////////////////
else if (flags & PTR_FLAGS_)
{
scroll_y = flags & WheelRotationMask;
if (flags & PTR_FLAGS_WHEEL_NEGATIVE)
{
scroll_y = -(flags & WheelRotationMask) / 392;
}
else
{
scroll_y = (flags & WheelRotationMask) / 120;
}
CGEventSourceRef source = CGEventSourceCreate (kCGEventSourceStateCombinedSessionState);
CGEventRef scroll = CGEventCreateScrollWheelEvent(source,
kCGScrollEventUnitLine,
wheelCount,
scroll_y,
scroll_x);
CGEventPost(kCGHIDEventTap, scroll);
CFRelease(scroll);
CFRelease(source);
} */
else else
{ {

View File

@ -25,9 +25,6 @@
#include "mf_mountain_lion.h" #include "mf_mountain_lion.h"
#include <freerdp/log.h>
#define TAG SERVER_TAG("mac")
dispatch_semaphore_t region_sem; dispatch_semaphore_t region_sem;
dispatch_semaphore_t data_sem; dispatch_semaphore_t data_sem;
dispatch_queue_t screen_update_q; dispatch_queue_t screen_update_q;
@ -85,24 +82,20 @@ void (^streamHandler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfaceRef, CGDisp
if (status != kCGDisplayStreamFrameStatusFrameComplete) if (status != kCGDisplayStreamFrameStatusFrameComplete)
{ {
//unhandled
switch(status) switch(status)
{ {
case kCGDisplayStreamFrameStatusFrameIdle: case kCGDisplayStreamFrameStatusFrameIdle:
WLog_DBG(TAG, "kCGDisplayStreamFrameStatusFrameIdle");
break; break;
case kCGDisplayStreamFrameStatusStopped: case kCGDisplayStreamFrameStatusStopped:
//we dont need to clean up
//WLog_DBG(TAG, "kCGDisplayStreamFrameStatusStopped");
break; break;
case kCGDisplayStreamFrameStatusFrameBlank: case kCGDisplayStreamFrameStatusFrameBlank:
WLog_DBG(TAG, "kCGDisplayStreamFrameStatusFrameBlank");
break; break;
default: default:
WLog_WARN(TAG, "Unhandled Frame Status!!!"); break;
} }
} }
else if (lastUpdate == NULL) else if (lastUpdate == NULL)
@ -193,9 +186,9 @@ int mf_mlion_start_getting_screen_updates()
CGError err; CGError err;
err = CGDisplayStreamStart(stream); err = CGDisplayStreamStart(stream);
if(err != kCGErrorSuccess)
if (err != kCGErrorSuccess)
{ {
WLog_WARN(TAG, "Failed to start displaystream!! err = %d", err);
return 1; return 1;
} }
@ -207,13 +200,15 @@ int mf_mlion_stop_getting_screen_updates()
CGError err; CGError err;
err = CGDisplayStreamStop(stream); err = CGDisplayStreamStop(stream);
if(err != kCGErrorSuccess)
if (err != kCGErrorSuccess)
{ {
WLog_WARN(TAG, "Failed to stop displaystream!! err = %d", err);
return 1; return 1;
} }
return 0; return 0;
return 0;
} }
int mf_mlion_get_dirty_region(RFX_RECT* invalid) int mf_mlion_get_dirty_region(RFX_RECT* invalid)
@ -225,7 +220,6 @@ int mf_mlion_get_dirty_region(RFX_RECT* invalid)
mf_mlion_peek_dirty_region(invalid); mf_mlion_peek_dirty_region(invalid);
} }
dispatch_semaphore_signal(region_sem); dispatch_semaphore_signal(region_sem);
return 0; return 0;
@ -283,4 +277,3 @@ int mf_mlion_get_pixelData(long x, long y, long width, long height, BYTE** pxDat
return 0; return 0;
} }

View File

@ -42,9 +42,6 @@
#include "CoreVideo/CoreVideo.h" #include "CoreVideo/CoreVideo.h"
#include <freerdp/log.h>
#define TAG SERVER_TAG("mac")
//refactor these //refactor these
int info_last_sec = 0; int info_last_sec = 0;
int info_last_nsec = 0; int info_last_nsec = 0;
@ -86,7 +83,7 @@ BOOL mf_peer_check_fds(freerdp_peer* client)
{ {
if (event->type == MF_EVENT_TYPE_REGION) if (event->type == MF_EVENT_TYPE_REGION)
{ {
WLog_ERR(TAG, "unhandled event");
} }
else if (event->type == MF_EVENT_TYPE_FRAME_TICK) else if (event->type == MF_EVENT_TYPE_FRAME_TICK)
{ {
@ -240,10 +237,10 @@ void mf_peer_init(freerdp_peer* client)
if(info_timer) if(info_timer)
{ {
//WLog_ERR(TAG, "created timer"); //DEBUG_WARN( "created timer\n");
dispatch_source_set_timer(info_timer, DISPATCH_TIME_NOW, 42ull * NSEC_PER_MSEC, 100ull * NSEC_PER_MSEC); dispatch_source_set_timer(info_timer, DISPATCH_TIME_NOW, 42ull * NSEC_PER_MSEC, 100ull * NSEC_PER_MSEC);
dispatch_source_set_event_handler(info_timer, ^{ dispatch_source_set_event_handler(info_timer, ^{
//WLog_ERR(TAG, "dispatch"); //DEBUG_WARN( "dispatch\n");
mfEvent* event = mf_event_new(MF_EVENT_TYPE_FRAME_TICK); mfEvent* event = mf_event_new(MF_EVENT_TYPE_FRAME_TICK);
mf_event_push(info_event_queue, (mfEvent*) event);} mf_event_push(info_event_queue, (mfEvent*) event);}
); );
@ -255,15 +252,6 @@ BOOL mf_peer_post_connect(freerdp_peer* client)
{ {
mfPeerContext* context = (mfPeerContext*) client->context; mfPeerContext* context = (mfPeerContext*) client->context;
rdpSettings* settings = client->settings; rdpSettings* settings = client->settings;
WLog_INFO(TAG, "Client %s post connect", client->hostname);
if (client->settings->AutoLogonEnabled)
{
WLog_INFO(TAG, " and wants to login automatically as %s\\%s",
client->settings->Domain ? client->settings->Domain : "",
client->settings->Username);
/* A real server may perform OS login here if NLA is not executed previously. */
}
mfInfo* mfi = mf_info_get_instance(); mfInfo* mfi = mf_info_get_instance();
mfi->scale = 1; mfi->scale = 1;
@ -274,8 +262,7 @@ BOOL mf_peer_post_connect(freerdp_peer* client)
if ((settings->DesktopWidth != mfi->servscreen_width) || (settings->DesktopHeight != mfi->servscreen_height)) if ((settings->DesktopWidth != mfi->servscreen_width) || (settings->DesktopHeight != mfi->servscreen_height))
{ {
WLog_INFO(TAG, "Client requested resolution %dx%d, but will resize to %dx%d",
settings->DesktopWidth, settings->DesktopHeight, mfi->servscreen_width, mfi->servscreen_height);
} }
settings->DesktopWidth = mfi->servscreen_width; settings->DesktopWidth = mfi->servscreen_width;
@ -314,12 +301,11 @@ BOOL mf_peer_activate(freerdp_peer* client)
void mf_peer_synchronize_event(rdpInput* input, UINT32 flags) void mf_peer_synchronize_event(rdpInput* input, UINT32 flags)
{ {
WLog_WARN(TAG, "Client sent a synchronize event (flags:0x%08X)", flags);
} }
void mf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) void mf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
{ {
WLog_INFO(TAG, "Client sent a keyboard event (flags:0x%04X code:0x%04X)", flags, code);
UINT16 down = 0x4000; UINT16 down = 0x4000;
//UINT16 up = 0x8000; //UINT16 up = 0x8000;
@ -329,52 +315,16 @@ void mf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
{ {
state_down = TRUE; state_down = TRUE;
} }
/*
CGEventRef event;
event = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)code, state_down);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
*/
} }
void mf_peer_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) void mf_peer_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
{ {
WLog_ERR(TAG, "Client sent a unicode keyboard event (flags:0x%04X code:0x%04X)", flags, code);
} }
/*void mf_peer_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
{
//WLog_ERR(TAG, "Client sent a mouse event (flags:0x%04X pos: %d,%d)", flags, x, y);
}
void mf_peer_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
{
//WLog_ERR(TAG, "Client sent an extended mouse event (flags:0x%04X pos: %d,%d)", flags, x, y);
}
*/
/*static void mf_peer_refresh_rect(rdpContext* context, BYTE count, RECTANGLE_16* areas)
{
BYTE i;
WLog_ERR(TAG, "Client requested to refresh:");
for (i = 0; i < count; i++)
{
WLog_ERR(TAG, " (%d, %d) (%d, %d)", areas[i].left, areas[i].top, areas[i].right, areas[i].bottom);
}
}*/
static void mf_peer_suppress_output(rdpContext* context, BYTE allow, RECTANGLE_16* area) static void mf_peer_suppress_output(rdpContext* context, BYTE allow, RECTANGLE_16* area)
{ {
if (allow > 0)
{
WLog_WARN(TAG, "Client restore output (%d, %d) (%d, %d).", area->left, area->top, area->right, area->bottom);
}
else
{
WLog_WARN(TAG, "Client minimized and suppress output.");
}
} }
void mf_peer_accepted(freerdp_listener* instance, freerdp_peer* client) void mf_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
@ -423,7 +373,7 @@ void* mf_peer_main_loop(void* arg)
client->Initialize(client); client->Initialize(client);
context = (mfPeerContext*) client->context; context = (mfPeerContext*) client->context;
WLog_INFO(TAG, "We've got a client %s", client->local ? "(local)" : client->hostname);
while (1) while (1)
{ {
@ -431,12 +381,11 @@ void* mf_peer_main_loop(void* arg)
if (client->GetFileDescriptor(client, rfds, &rcount) != TRUE) if (client->GetFileDescriptor(client, rfds, &rcount) != TRUE)
{ {
WLog_ERR(TAG, "Failed to get FreeRDP file descriptor");
break; break;
} }
if (mf_peer_get_fds(client, rfds, &rcount) != TRUE) if (mf_peer_get_fds(client, rfds, &rcount) != TRUE)
{ {
WLog_ERR(TAG, "Failed to get mfreerdp file descriptor");
break; break;
} }
@ -466,20 +415,17 @@ void* mf_peer_main_loop(void* arg)
(errno == EINPROGRESS) || (errno == EINPROGRESS) ||
(errno == EINTR))) /* signal occurred */ (errno == EINTR))) /* signal occurred */
{ {
WLog_ERR(TAG, "select failed");
break; break;
} }
} }
if (client->CheckFileDescriptor(client) != TRUE) if (client->CheckFileDescriptor(client) != TRUE)
{ {
WLog_ERR(TAG, "Failed to check freerdp file descriptor");
break; break;
} }
if ((mf_peer_check_fds(client)) != TRUE) if ((mf_peer_check_fds(client)) != TRUE)
{ {
WLog_ERR(TAG, "Failed to check mfreerdp file descriptor");
break; break;
} }
@ -489,7 +435,6 @@ void* mf_peer_main_loop(void* arg)
} }
} }
WLog_INFO(TAG, "Client %s disconnected.", client->local ? "(local)" : client->hostname);
client->Disconnect(client); client->Disconnect(client);
freerdp_peer_context_free(client); freerdp_peer_context_free(client);
freerdp_peer_free(client); freerdp_peer_free(client);

View File

@ -46,8 +46,12 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context)
//we should actually loop through the list of client formats here //we should actually loop through the list of client formats here
//and see if we can send the client something that it supports... //and see if we can send the client something that it supports...
<<<<<<< HEAD
=======
WLog_DBG(TAG, "Client supports the following %d formats: ", context->num_client_formats); WLog_DBG(TAG, "Client supports the following %d formats: ", context->num_client_formats);
>>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a
for (i = 0; i < context->num_client_formats; i++) for (i = 0; i < context->num_client_formats; i++)
{ {
/* TODO: improve the way we agree on a format */ /* TODO: improve the way we agree on a format */
@ -57,7 +61,10 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context)
(context->client_formats[i].nChannels == context->server_formats[j].nChannels) && (context->client_formats[i].nChannels == context->server_formats[j].nChannels) &&
(context->client_formats[i].nSamplesPerSec == context->server_formats[j].nSamplesPerSec)) (context->client_formats[i].nSamplesPerSec == context->server_formats[j].nSamplesPerSec))
{ {
<<<<<<< HEAD
=======
WLog_DBG(TAG, "agreed on format!"); WLog_DBG(TAG, "agreed on format!");
>>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a
formatAgreed = TRUE; formatAgreed = TRUE;
agreedFormat = (AUDIO_FORMAT*)&context->server_formats[j]; agreedFormat = (AUDIO_FORMAT*)&context->server_formats[j];
break; break;
@ -70,7 +77,10 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context)
if (formatAgreed == FALSE) if (formatAgreed == FALSE)
{ {
<<<<<<< HEAD
=======
WLog_DBG(TAG, "Could not agree on a audio format with the server"); WLog_DBG(TAG, "Could not agree on a audio format with the server");
>>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a
return; return;
} }
@ -113,9 +123,12 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context)
if (status != noErr) if (status != noErr)
{ {
WLog_DBG(TAG, "Failed to create a new Audio Queue. Status code: %d", status); <<<<<<< HEAD
}
=======
WLog_DBG(TAG, "Failed to create a new Audio Queue. Status code: %d", status);
>>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a
}
UInt32 dataFormatSize = sizeof (recorderState.dataFormat); UInt32 dataFormatSize = sizeof (recorderState.dataFormat);
@ -210,7 +223,11 @@ void mf_peer_rdpsnd_input_callback (void *inUserD
if (status != noErr) if (status != noErr)
{ {
<<<<<<< HEAD
=======
WLog_DBG(TAG, "AudioQueueEnqueueBuffer() returned status = %d", status); WLog_DBG(TAG, "AudioQueueEnqueueBuffer() returned status = %d", status);
>>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a
} }
} }

View File

@ -43,9 +43,6 @@
#include "mfreerdp.h" #include "mfreerdp.h"
#include "mf_peer.h" #include "mf_peer.h"
#include <freerdp/log.h>
#define TAG SERVER_TAG("mac")
static void mf_server_main_loop(freerdp_listener* instance) static void mf_server_main_loop(freerdp_listener* instance)
{ {
int i; int i;
@ -63,7 +60,6 @@ static void mf_server_main_loop(freerdp_listener* instance)
if (instance->GetFileDescriptor(instance, rfds, &rcount) != TRUE) if (instance->GetFileDescriptor(instance, rfds, &rcount) != TRUE)
{ {
WLog_ERR(TAG, "Failed to get FreeRDP file descriptor");
break; break;
} }
@ -91,14 +87,12 @@ static void mf_server_main_loop(freerdp_listener* instance)
(errno == EINPROGRESS) || (errno == EINPROGRESS) ||
(errno == EINTR))) /* signal occurred */ (errno == EINTR))) /* signal occurred */
{ {
WLog_ERR(TAG, "select failed");
break; break;
} }
} }
if (instance->CheckFileDescriptor(instance) != TRUE) if (instance->CheckFileDescriptor(instance) != TRUE)
{ {
WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
break; break;
} }
} }
@ -127,4 +121,3 @@ int main(int argc, char* argv[])
return 0; return 0;
} }

View File

@ -18,7 +18,15 @@
set(MODULE_NAME "freerdp-shadow") set(MODULE_NAME "freerdp-shadow")
set(MODULE_PREFIX "FREERDP_SERVER_SHADOW") set(MODULE_PREFIX "FREERDP_SERVER_SHADOW")
if(WITH_X11) if(WIN32)
set(WITH_SHADOW_WIN 1)
elseif(X11_FOUND AND NOT APPLE)
set(WITH_SHADOW_X11 1)
elseif(APPLE AND NOT IOS)
set(WITH_SHADOW_MAC 1)
endif()
if(WITH_SHADOW_X11)
set(XEXT_FEATURE_TYPE "RECOMMENDED") set(XEXT_FEATURE_TYPE "RECOMMENDED")
set(XEXT_FEATURE_PURPOSE "X11 extension") set(XEXT_FEATURE_PURPOSE "X11 extension")
set(XEXT_FEATURE_DESCRIPTION "X11 core extensions") set(XEXT_FEATURE_DESCRIPTION "X11 core extensions")
@ -115,6 +123,13 @@ if(WITH_X11)
endif() endif()
endif() endif()
if(WITH_SHADOW_MAC)
find_library(IOKIT IOKit)
find_library(IOSURFACE IOSurface)
find_library(CARBON Carbon)
list(APPEND ${MODULE_PREFIX}_MAC_LIBS ${IOKIT} ${IOSURFACE} ${CARBON})
endif()
include_directories(${OPENSSL_INCLUDE_DIR}) include_directories(${OPENSSL_INCLUDE_DIR})
set(${MODULE_PREFIX}_SRCS set(${MODULE_PREFIX}_SRCS
@ -136,6 +151,8 @@ set(${MODULE_PREFIX}_SRCS
shadow_encomsp.h shadow_encomsp.h
shadow_remdesk.c shadow_remdesk.c
shadow_remdesk.h shadow_remdesk.h
shadow_subsystem.c
shadow_subsystem.h
shadow_server.c shadow_server.c
shadow.h) shadow.h)
@ -157,14 +174,6 @@ set(${MODULE_PREFIX}_MAC_SRCS
Mac/mac_shadow.c Mac/mac_shadow.c
Mac/mac_shadow.h) Mac/mac_shadow.h)
if(WIN32)
set(WITH_SHADOW_WIN 1)
elseif(X11_FOUND AND NOT APPLE)
set(WITH_SHADOW_X11 1)
elseif(APPLE AND NOT IOS)
set(WITH_SHADOW_MAC 1)
endif()
if(WITH_SHADOW_WIN) if(WITH_SHADOW_WIN)
add_definitions(-DWITH_SHADOW_WIN) add_definitions(-DWITH_SHADOW_WIN)
list(APPEND ${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_WIN_SRCS}) list(APPEND ${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_WIN_SRCS})
@ -179,18 +188,36 @@ elseif(WITH_SHADOW_MAC)
list(APPEND ${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_MAC_LIBS}) list(APPEND ${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_MAC_LIBS})
endif() endif()
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "freerdp-shadow")
list(APPEND ${MODULE_PREFIX}_LIBS freerdp)
list(APPEND ${MODULE_PREFIX}_LIBS freerdp-server) list(APPEND ${MODULE_PREFIX}_LIBS freerdp-server)
list(APPEND ${MODULE_PREFIX}_LIBS freerdp-client) list(APPEND ${MODULE_PREFIX}_LIBS freerdp-client)
list(APPEND ${MODULE_PREFIX}_LIBS winpr-makecert-tool winpr)
list(APPEND ${MODULE_PREFIX}_LIBS freerdp) list(APPEND ${MODULE_PREFIX}_LIBS winpr)
list(APPEND ${MODULE_PREFIX}_LIBS winpr-makecert-tool)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT server) install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT server)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/shadow") set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/shadow")
# command-line executable
set(MODULE_NAME "freerdp-shadow-cli")
set(MODULE_PREFIX "FREERDP_SERVER_SHADOW_CLI")
set(${MODULE_PREFIX}_SRCS
shadow.c)
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "freerdp-shadow")
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-shadow)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT server)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/shadow")

View File

@ -18,6 +18,7 @@
#include <winpr/crt.h> #include <winpr/crt.h>
#include <winpr/synch.h> #include <winpr/synch.h>
#include <winpr/input.h>
#include <winpr/sysinfo.h> #include <winpr/sysinfo.h>
#include <freerdp/codec/color.h> #include <freerdp/codec/color.h>
@ -25,9 +26,13 @@
#include "../shadow_screen.h" #include "../shadow_screen.h"
#include "../shadow_surface.h" #include "../shadow_surface.h"
#include "../shadow_capture.h"
#include "../shadow_subsystem.h"
#include "mac_shadow.h" #include "mac_shadow.h"
static macShadowSubsystem* g_Subsystem = NULL;
void mac_shadow_input_synchronize_event(macShadowSubsystem* subsystem, UINT32 flags) void mac_shadow_input_synchronize_event(macShadowSubsystem* subsystem, UINT32 flags)
{ {
@ -35,7 +40,43 @@ void mac_shadow_input_synchronize_event(macShadowSubsystem* subsystem, UINT32 fl
void mac_shadow_input_keyboard_event(macShadowSubsystem* subsystem, UINT16 flags, UINT16 code) void mac_shadow_input_keyboard_event(macShadowSubsystem* subsystem, UINT16 flags, UINT16 code)
{ {
DWORD vkcode;
DWORD keycode;
BOOL extended;
CGEventRef kbdEvent;
CGEventSourceRef source;
extended = (flags & KBD_FLAGS_EXTENDED) ? TRUE : FALSE;
if (extended)
code |= KBDEXT;
vkcode = GetVirtualKeyCodeFromVirtualScanCode(code, 4);
if (extended)
vkcode |= KBDEXT;
keycode = GetKeycodeFromVirtualKeyCode(vkcode, KEYCODE_TYPE_APPLE) - 8;
if (keycode)
{
source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
if (flags & KBD_FLAGS_DOWN)
{
kbdEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode) keycode, TRUE);
CGEventPost(kCGHIDEventTap, kbdEvent);
CFRelease(kbdEvent);
}
else if (flags & KBD_FLAGS_RELEASE)
{
kbdEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode) keycode, FALSE);
CGEventPost(kCGHIDEventTap, kbdEvent);
CFRelease(kbdEvent);
}
CFRelease(source);
}
} }
void mac_shadow_input_unicode_keyboard_event(macShadowSubsystem* subsystem, UINT16 flags, UINT16 code) void mac_shadow_input_unicode_keyboard_event(macShadowSubsystem* subsystem, UINT16 flags, UINT16 code)
@ -45,7 +86,106 @@ void mac_shadow_input_unicode_keyboard_event(macShadowSubsystem* subsystem, UINT
void mac_shadow_input_mouse_event(macShadowSubsystem* subsystem, UINT16 flags, UINT16 x, UINT16 y) void mac_shadow_input_mouse_event(macShadowSubsystem* subsystem, UINT16 flags, UINT16 x, UINT16 y)
{ {
UINT32 scrollX = 0;
UINT32 scrollY = 0;
CGWheelCount wheelCount = 2;
if (flags & PTR_FLAGS_WHEEL)
{
scrollY = flags & WheelRotationMask;
if (flags & PTR_FLAGS_WHEEL_NEGATIVE)
{
scrollY = -(flags & WheelRotationMask) / 392;
}
else
{
scrollY = (flags & WheelRotationMask) / 120;
}
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef scroll = CGEventCreateScrollWheelEvent(source, kCGScrollEventUnitLine,
wheelCount, scrollY, scrollX);
CGEventPost(kCGHIDEventTap, scroll);
CFRelease(scroll);
CFRelease(source);
}
else
{
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventType mouseType = kCGEventNull;
CGMouseButton mouseButton = kCGMouseButtonLeft;
if (flags & PTR_FLAGS_MOVE)
{
if (subsystem->mouseDownLeft)
mouseType = kCGEventLeftMouseDragged;
else if (subsystem->mouseDownRight)
mouseType = kCGEventRightMouseDragged;
else if (subsystem->mouseDownOther)
mouseType = kCGEventOtherMouseDragged;
else
mouseType = kCGEventMouseMoved;
CGEventRef move = CGEventCreateMouseEvent(source, mouseType, CGPointMake(x, y), mouseButton);
CGEventPost(kCGHIDEventTap, move);
CFRelease(move);
}
if (flags & PTR_FLAGS_BUTTON1)
{
mouseButton = kCGMouseButtonLeft;
if (flags & PTR_FLAGS_DOWN)
{
mouseType = kCGEventLeftMouseDown;
subsystem->mouseDownLeft = TRUE;
}
else
{
mouseType = kCGEventLeftMouseUp;
subsystem->mouseDownLeft = FALSE;
}
}
else if (flags & PTR_FLAGS_BUTTON2)
{
mouseButton = kCGMouseButtonRight;
if (flags & PTR_FLAGS_DOWN)
{
mouseType = kCGEventRightMouseDown;
subsystem->mouseDownRight = TRUE;
}
else
{
mouseType = kCGEventRightMouseUp;
subsystem->mouseDownRight = FALSE;
}
}
else if (flags & PTR_FLAGS_BUTTON3)
{
mouseButton = kCGMouseButtonCenter;
if (flags & PTR_FLAGS_DOWN)
{
mouseType = kCGEventOtherMouseDown;
subsystem->mouseDownOther = TRUE;
}
else
{
mouseType = kCGEventOtherMouseUp;
subsystem->mouseDownOther = FALSE;
}
}
CGEventRef mouseEvent = CGEventCreateMouseEvent(source, mouseType, CGPointMake(x, y), mouseButton);
CGEventPost(kCGHIDEventTap, mouseEvent);
CFRelease(mouseEvent);
CFRelease(source);
}
} }
void mac_shadow_input_extended_mouse_event(macShadowSubsystem* subsystem, UINT16 flags, UINT16 x, UINT16 y) void mac_shadow_input_extended_mouse_event(macShadowSubsystem* subsystem, UINT16 flags, UINT16 x, UINT16 y)
@ -53,15 +193,314 @@ void mac_shadow_input_extended_mouse_event(macShadowSubsystem* subsystem, UINT16
} }
int mac_shadow_surface_copy(macShadowSubsystem* subsystem) int mac_shadow_detect_monitors(macShadowSubsystem* subsystem)
{ {
size_t wide, high;
MONITOR_DEF* monitor;
CGDirectDisplayID displayId;
displayId = CGMainDisplayID();
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId);
subsystem->pixelWidth = CGDisplayModeGetPixelWidth(mode);
subsystem->pixelHeight = CGDisplayModeGetPixelHeight(mode);
wide = CGDisplayPixelsWide(displayId);
high = CGDisplayPixelsHigh(displayId);
CGDisplayModeRelease(mode);
subsystem->retina = ((subsystem->pixelWidth / wide) == 2) ? TRUE : FALSE;
if (subsystem->retina)
{
subsystem->width = wide;
subsystem->height = high;
}
else
{
subsystem->width = subsystem->pixelWidth;
subsystem->height = subsystem->pixelHeight;
}
subsystem->numMonitors = 1;
monitor = &(subsystem->monitors[0]);
monitor->left = 0;
monitor->top = 0;
monitor->right = subsystem->width;
monitor->bottom = subsystem->height;
monitor->flags = 1;
return 1;
}
int mac_shadow_capture_start(macShadowSubsystem* subsystem)
{
CGError err;
err = CGDisplayStreamStart(subsystem->stream);
if (err != kCGErrorSuccess)
return -1;
return 1;
}
int mac_shadow_capture_stop(macShadowSubsystem* subsystem)
{
CGError err;
err = CGDisplayStreamStop(subsystem->stream);
if (err != kCGErrorSuccess)
return -1;
return 1;
}
int mac_shadow_capture_peek_dirty_region(macShadowSubsystem* subsystem)
{
size_t index;
size_t numRects;
const CGRect* rects;
RECTANGLE_16 invalidRect;
rects = CGDisplayStreamUpdateGetRects(subsystem->lastUpdate, kCGDisplayStreamUpdateDirtyRects, &numRects);
if (!numRects)
return -1;
for (index = 0; index < numRects; index++)
{
invalidRect.left = (UINT16) rects[index].origin.x;
invalidRect.top = (UINT16) rects[index].origin.y;
invalidRect.right = invalidRect.left + (UINT16) rects[index].size.width;
invalidRect.bottom = invalidRect.top + (UINT16) rects[index].size.height;
if (subsystem->retina)
{
/* scale invalid rect */
invalidRect.left /= 2;
invalidRect.top /= 2;
invalidRect.right /= 2;
invalidRect.bottom /= 2;
}
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
}
return 0;
}
int mac_shadow_capture_get_dirty_region(macShadowSubsystem* subsystem)
{
dispatch_semaphore_wait(subsystem->regionSemaphore, DISPATCH_TIME_FOREVER);
if (subsystem->lastUpdate)
{
mac_shadow_capture_peek_dirty_region(subsystem);
}
dispatch_semaphore_signal(subsystem->regionSemaphore);
return 1;
}
int mac_shadow_capture_clear_dirty_region(macShadowSubsystem* subsystem)
{
dispatch_semaphore_wait(subsystem->regionSemaphore, DISPATCH_TIME_FOREVER);
CFRelease(subsystem->lastUpdate);
subsystem->lastUpdate = NULL;
dispatch_semaphore_signal(subsystem->regionSemaphore);
return 1;
}
int mac_shadow_capture_surface_copy(macShadowSubsystem* subsystem)
{
dispatch_semaphore_wait(subsystem->regionSemaphore, DISPATCH_TIME_FOREVER);
subsystem->updateReady = TRUE;
dispatch_semaphore_wait(subsystem->dataSemaphore, DISPATCH_TIME_FOREVER);
dispatch_semaphore_signal(subsystem->regionSemaphore);
dispatch_semaphore_wait(subsystem->dataSemaphore, DISPATCH_TIME_FOREVER);
dispatch_semaphore_signal(subsystem->dataSemaphore);
return 1;
}
void (^mac_capture_stream_handler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfaceRef, CGDisplayStreamUpdateRef) =
^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef)
{
int x, y;
int count;
int width;
int height;
int nSrcStep;
BYTE* pSrcData;
RECTANGLE_16 surfaceRect;
const RECTANGLE_16* extents;
macShadowSubsystem* subsystem = g_Subsystem;
rdpShadowServer* server = subsystem->server;
rdpShadowSurface* surface = server->surface;
if (ArrayList_Count(server->clients) < 1)
{
region16_clear(&(subsystem->invalidRegion));
return;
}
dispatch_semaphore_wait(subsystem->regionSemaphore, DISPATCH_TIME_FOREVER);
if (!subsystem->updateReady)
{
dispatch_semaphore_signal(subsystem->regionSemaphore);
return;
}
mac_shadow_capture_peek_dirty_region(subsystem);
surfaceRect.left = surface->x;
surfaceRect.top = surface->y;
surfaceRect.right = surface->x + surface->width;
surfaceRect.bottom = surface->y + surface->height;
region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect);
if (region16_is_empty(&(subsystem->invalidRegion)))
{
}
extents = region16_extents(&(subsystem->invalidRegion));
x = extents->left;
y = extents->top;
width = extents->right - extents->left;
height = extents->bottom - extents->top;
IOSurfaceLock(frameSurface, kIOSurfaceLockReadOnly, NULL);
pSrcData = (BYTE*) IOSurfaceGetBaseAddress(frameSurface);
nSrcStep = (int) IOSurfaceGetBytesPerRow(frameSurface);
if (subsystem->retina)
{
freerdp_image_copy_from_retina(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
x, y, width, height, pSrcData, nSrcStep, x, y);
}
else
{
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
x, y, width, height, pSrcData, PIXEL_FORMAT_XRGB32, nSrcStep, x, y, NULL);
}
IOSurfaceUnlock(frameSurface, kIOSurfaceLockReadOnly, NULL);
subsystem->updateReady = FALSE;
dispatch_semaphore_signal(subsystem->dataSemaphore);
ArrayList_Lock(server->clients);
count = ArrayList_Count(server->clients);
InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1);
SetEvent(subsystem->updateEvent);
EnterSynchronizationBarrier(&(subsystem->barrier), 0);
ResetEvent(subsystem->updateEvent);
DeleteSynchronizationBarrier(&(subsystem->barrier));
ArrayList_Unlock(server->clients);
region16_clear(&(subsystem->invalidRegion));
if (status != kCGDisplayStreamFrameStatusFrameComplete)
{
switch (status)
{
case kCGDisplayStreamFrameStatusFrameIdle:
break;
case kCGDisplayStreamFrameStatusStopped:
break;
case kCGDisplayStreamFrameStatusFrameBlank:
break;
default:
break;
}
}
else if (!subsystem->lastUpdate)
{
CFRetain(updateRef);
subsystem->lastUpdate = updateRef;
}
else
{
CGDisplayStreamUpdateRef tmpRef = subsystem->lastUpdate;
subsystem->lastUpdate = CGDisplayStreamUpdateCreateMergedUpdate(tmpRef, updateRef);
CFRelease(tmpRef);
}
dispatch_semaphore_signal(subsystem->regionSemaphore);
};
int mac_shadow_capture_init(macShadowSubsystem* subsystem)
{
void* keys[2];
void* values[2];
CFDictionaryRef opts;
CGDirectDisplayID displayId;
displayId = CGMainDisplayID();
subsystem->regionSemaphore = dispatch_semaphore_create(1);
subsystem->dataSemaphore = dispatch_semaphore_create(1);
subsystem->updateBuffer = (BYTE*) malloc(subsystem->pixelWidth * subsystem->pixelHeight * 4);
subsystem->captureQueue = dispatch_queue_create("mac.shadow.capture", NULL);
keys[0] = (void*) kCGDisplayStreamShowCursor;
values[0] = (void*) kCFBooleanFalse;
opts = CFDictionaryCreate(kCFAllocatorDefault, (const void**) keys, (const void**) values, 1, NULL, NULL);
subsystem->stream = CGDisplayStreamCreateWithDispatchQueue(displayId, subsystem->pixelWidth, subsystem->pixelHeight,
'BGRA', opts, subsystem->captureQueue, mac_capture_stream_handler);
CFRelease(opts);
return 1;
}
int mac_shadow_screen_grab(macShadowSubsystem* subsystem)
{
mac_shadow_capture_get_dirty_region(subsystem);
mac_shadow_capture_surface_copy(subsystem);
return 1; return 1;
} }
void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem) void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem)
{ {
int fps;
DWORD status; DWORD status;
DWORD nCount; DWORD nCount;
UINT64 cTime;
DWORD dwTimeout;
DWORD dwInterval;
UINT64 frameTime;
HANDLE events[32]; HANDLE events[32];
HANDLE StopEvent; HANDLE StopEvent;
@ -70,22 +509,73 @@ void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem)
nCount = 0; nCount = 0;
events[nCount++] = StopEvent; events[nCount++] = StopEvent;
fps = 16;
dwInterval = 1000 / fps;
frameTime = GetTickCount64() + dwInterval;
while (1) while (1)
{ {
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); cTime = GetTickCount64();
dwTimeout = (cTime > frameTime) ? 0 : frameTime - cTime;
status = WaitForMultipleObjects(nCount, events, FALSE, dwTimeout);
if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0) if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0)
{ {
break; break;
} }
if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime))
{
mac_shadow_screen_grab(subsystem);
dwInterval = 1000 / fps;
frameTime += dwInterval;
}
} }
ExitThread(0); ExitThread(0);
return NULL; return NULL;
} }
int mac_shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors)
{
int index;
size_t wide, high;
int numMonitors = 0;
MONITOR_DEF* monitor;
CGDirectDisplayID displayId;
displayId = CGMainDisplayID();
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId);
wide = CGDisplayPixelsWide(displayId);
high = CGDisplayPixelsHigh(displayId);
CGDisplayModeRelease(mode);
index = 0;
numMonitors = 1;
monitor = &monitors[index];
monitor->left = 0;
monitor->top = 0;
monitor->right = (int) wide;
monitor->bottom = (int) high;
monitor->flags = 1;
return numMonitors;
}
int mac_shadow_subsystem_init(macShadowSubsystem* subsystem) int mac_shadow_subsystem_init(macShadowSubsystem* subsystem)
{ {
g_Subsystem = subsystem;
mac_shadow_detect_monitors(subsystem);
mac_shadow_capture_init(subsystem);
return 1; return 1;
} }
@ -104,6 +594,8 @@ int mac_shadow_subsystem_start(macShadowSubsystem* subsystem)
if (!subsystem) if (!subsystem)
return -1; return -1;
mac_shadow_capture_start(subsystem);
thread = CreateThread(NULL, 0, thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) mac_shadow_subsystem_thread, (LPTHREAD_START_ROUTINE) mac_shadow_subsystem_thread,
(void*) subsystem, 0, NULL); (void*) subsystem, 0, NULL);
@ -129,7 +621,7 @@ void mac_shadow_subsystem_free(macShadowSubsystem* subsystem)
free(subsystem); free(subsystem);
} }
macShadowSubsystem* mac_shadow_subsystem_new(rdpShadowServer* server) macShadowSubsystem* mac_shadow_subsystem_new()
{ {
macShadowSubsystem* subsystem; macShadowSubsystem* subsystem;
@ -138,16 +630,6 @@ macShadowSubsystem* mac_shadow_subsystem_new(rdpShadowServer* server)
if (!subsystem) if (!subsystem)
return NULL; return NULL;
subsystem->server = server;
subsystem->Init = (pfnShadowSubsystemInit) mac_shadow_subsystem_init;
subsystem->Uninit = (pfnShadowSubsystemInit) mac_shadow_subsystem_uninit;
subsystem->Start = (pfnShadowSubsystemStart) mac_shadow_subsystem_start;
subsystem->Stop = (pfnShadowSubsystemStop) mac_shadow_subsystem_stop;
subsystem->Free = (pfnShadowSubsystemFree) mac_shadow_subsystem_free;
subsystem->SurfaceCopy = (pfnShadowSurfaceCopy) mac_shadow_surface_copy;
subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) mac_shadow_input_synchronize_event; subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) mac_shadow_input_synchronize_event;
subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) mac_shadow_input_keyboard_event; subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) mac_shadow_input_keyboard_event;
subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) mac_shadow_input_unicode_keyboard_event; subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) mac_shadow_input_unicode_keyboard_event;
@ -157,7 +639,18 @@ macShadowSubsystem* mac_shadow_subsystem_new(rdpShadowServer* server)
return subsystem; return subsystem;
} }
rdpShadowSubsystem* Mac_ShadowCreateSubsystem(rdpShadowServer* server) int Mac_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints)
{ {
return (rdpShadowSubsystem*) mac_shadow_subsystem_new(server); pEntryPoints->New = (pfnShadowSubsystemNew) mac_shadow_subsystem_new;
pEntryPoints->Free = (pfnShadowSubsystemFree) mac_shadow_subsystem_free;
pEntryPoints->Init = (pfnShadowSubsystemInit) mac_shadow_subsystem_init;
pEntryPoints->Uninit = (pfnShadowSubsystemInit) mac_shadow_subsystem_uninit;
pEntryPoints->Start = (pfnShadowSubsystemStart) mac_shadow_subsystem_start;
pEntryPoints->Stop = (pfnShadowSubsystemStop) mac_shadow_subsystem_stop;
pEntryPoints->EnumMonitors = (pfnShadowEnumMonitors) mac_shadow_enum_monitors;
return 1;
} }

View File

@ -29,11 +29,31 @@ typedef struct mac_shadow_subsystem macShadowSubsystem;
#include <winpr/stream.h> #include <winpr/stream.h>
#include <winpr/collections.h> #include <winpr/collections.h>
#include <dispatch/dispatch.h>
#include <IOKit/IOKitLib.h>
#include <IOSurface/IOSurface.h>
#include <CoreVideo/CoreVideo.h>
#include <CoreGraphics/CoreGraphics.h>
struct mac_shadow_subsystem struct mac_shadow_subsystem
{ {
RDP_SHADOW_SUBSYSTEM_COMMON(); RDP_SHADOW_SUBSYSTEM_COMMON();
int width;
int height;
BOOL retina;
int pixelWidth;
int pixelHeight;
BOOL mouseDownLeft;
BOOL mouseDownRight;
BOOL mouseDownOther;
BOOL updateReady;
BYTE* updateBuffer;
CGDisplayStreamRef stream;
dispatch_queue_t captureQueue;
dispatch_semaphore_t dataSemaphore;
dispatch_semaphore_t regionSemaphore;
CGDisplayStreamUpdateRef lastUpdate;
}; };
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -20,13 +20,14 @@
#include <winpr/synch.h> #include <winpr/synch.h>
#include <winpr/sysinfo.h> #include <winpr/sysinfo.h>
#include <freerdp/log.h>
#include <freerdp/codec/color.h> #include <freerdp/codec/color.h>
#include <freerdp/codec/region.h> #include <freerdp/codec/region.h>
#include <freerdp/log.h>
#include "../shadow_screen.h" #include "../shadow_screen.h"
#include "../shadow_surface.h" #include "../shadow_surface.h"
#include "../shadow_capture.h" #include "../shadow_capture.h"
#include "../shadow_subsystem.h"
#include "win_shadow.h" #include "win_shadow.h"
@ -280,7 +281,7 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem)
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
surface->scanline, x - surface->x, y - surface->y, width, height, surface->scanline, x - surface->x, y - surface->y, width, height,
pDstData, PIXEL_FORMAT_XRGB32, nDstStep, 0, 0); pDstData, PIXEL_FORMAT_XRGB32, nDstStep, 0, 0, NULL);
ArrayList_Lock(server->clients); ArrayList_Lock(server->clients);
@ -398,27 +399,51 @@ void* win_shadow_subsystem_thread(winShadowSubsystem* subsystem)
#endif #endif
int win_shadow_subsystem_init(winShadowSubsystem* subsystem) int win_shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors)
{ {
HDC hdc; HDC hdc;
int status; int index;
int desktopWidth;
int desktopHeight;
DWORD iDevNum = 0; DWORD iDevNum = 0;
int numMonitors = 0;
MONITOR_DEF* monitor;
MONITOR_DEF* virtualScreen; MONITOR_DEF* virtualScreen;
DISPLAY_DEVICE DisplayDevice; DISPLAY_DEVICE displayDevice;
ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE)); ZeroMemory(&displayDevice, sizeof(DISPLAY_DEVICE));
DisplayDevice.cb = sizeof(DISPLAY_DEVICE); displayDevice.cb = sizeof(DISPLAY_DEVICE);
if (!EnumDisplayDevices(NULL, iDevNum, &DisplayDevice, 0)) if (EnumDisplayDevices(NULL, iDevNum, &displayDevice, 0))
return -1; {
hdc = CreateDC(displayDevice.DeviceName, NULL, NULL, NULL);
hdc = CreateDC(DisplayDevice.DeviceName, NULL, NULL, NULL); desktopWidth = GetDeviceCaps(hdc, HORZRES);
desktopHeight = GetDeviceCaps(hdc, VERTRES);
subsystem->width = GetDeviceCaps(hdc, HORZRES); index = 0;
subsystem->height = GetDeviceCaps(hdc, VERTRES); numMonitors = 1;
subsystem->bpp = GetDeviceCaps(hdc, BITSPIXEL);
monitor = &monitors[index];
monitor->left = 0;
monitor->top = 0;
monitor->right = desktopWidth;
monitor->bottom = desktopHeight;
monitor->flags = 1;
DeleteDC(hdc); DeleteDC(hdc);
}
return numMonitors;
}
int win_shadow_subsystem_init(winShadowSubsystem* subsystem)
{
int status;
MONITOR_DEF* virtualScreen;
subsystem->numMonitors = win_shadow_enum_monitors(subsystem->monitors, 16);
#if defined(WITH_WDS_API) #if defined(WITH_WDS_API)
status = win_shadow_wds_init(subsystem); status = win_shadow_wds_init(subsystem);
@ -434,16 +459,6 @@ int win_shadow_subsystem_init(winShadowSubsystem* subsystem)
virtualScreen->bottom = subsystem->height; virtualScreen->bottom = subsystem->height;
virtualScreen->flags = 1; virtualScreen->flags = 1;
if (subsystem->monitorCount < 1)
{
subsystem->monitorCount = 1;
subsystem->monitors[0].left = virtualScreen->left;
subsystem->monitors[0].top = virtualScreen->top;
subsystem->monitors[0].right = virtualScreen->right;
subsystem->monitors[0].bottom = virtualScreen->bottom;
subsystem->monitors[0].flags = 1;
}
WLog_INFO(TAG, "width: %d height: %d", subsystem->width, subsystem->height); WLog_INFO(TAG, "width: %d height: %d", subsystem->width, subsystem->height);
return 1; return 1;
@ -492,14 +507,10 @@ void win_shadow_subsystem_free(winShadowSubsystem* subsystem)
win_shadow_subsystem_uninit(subsystem); win_shadow_subsystem_uninit(subsystem);
region16_uninit(&(subsystem->invalidRegion));
CloseHandle(subsystem->updateEvent);
free(subsystem); free(subsystem);
} }
winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server) winShadowSubsystem* win_shadow_subsystem_new()
{ {
winShadowSubsystem* subsystem; winShadowSubsystem* subsystem;
@ -508,20 +519,6 @@ winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server)
if (!subsystem) if (!subsystem)
return NULL; return NULL;
subsystem->server = server;
subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
region16_init(&(subsystem->invalidRegion));
subsystem->Init = (pfnShadowSubsystemInit) win_shadow_subsystem_init;
subsystem->Uninit = (pfnShadowSubsystemInit) win_shadow_subsystem_uninit;
subsystem->Start = (pfnShadowSubsystemStart) win_shadow_subsystem_start;
subsystem->Stop = (pfnShadowSubsystemStop) win_shadow_subsystem_stop;
subsystem->Free = (pfnShadowSubsystemFree) win_shadow_subsystem_free;
subsystem->SurfaceCopy = (pfnShadowSurfaceCopy) win_shadow_surface_copy;
subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) win_shadow_input_synchronize_event; subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) win_shadow_input_synchronize_event;
subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) win_shadow_input_keyboard_event; subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) win_shadow_input_keyboard_event;
subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) win_shadow_input_unicode_keyboard_event; subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) win_shadow_input_unicode_keyboard_event;
@ -531,7 +528,18 @@ winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server)
return subsystem; return subsystem;
} }
rdpShadowSubsystem* Win_ShadowCreateSubsystem(rdpShadowServer* server) int Win_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints)
{ {
return (rdpShadowSubsystem*) win_shadow_subsystem_new(server); pEntryPoints->New = (pfnShadowSubsystemNew) win_shadow_subsystem_new;
pEntryPoints->Free = (pfnShadowSubsystemFree) win_shadow_subsystem_free;
pEntryPoints->Init = (pfnShadowSubsystemInit) win_shadow_subsystem_init;
pEntryPoints->Uninit = (pfnShadowSubsystemInit) win_shadow_subsystem_uninit;
pEntryPoints->Start = (pfnShadowSubsystemStart) win_shadow_subsystem_start;
pEntryPoints->Stop = (pfnShadowSubsystemStop) win_shadow_subsystem_stop;
pEntryPoints->EnumMonitors = (pfnShadowEnumMonitors) win_shadow_enum_monitors;
return 1;
} }

View File

@ -32,15 +32,19 @@
#include <winpr/crt.h> #include <winpr/crt.h>
#include <winpr/synch.h> #include <winpr/synch.h>
#include <winpr/image.h>
#include <winpr/sysinfo.h> #include <winpr/sysinfo.h>
#include <freerdp/log.h>
#include <freerdp/codec/color.h> #include <freerdp/codec/color.h>
#include <freerdp/codec/region.h> #include <freerdp/codec/region.h>
#include <freerdp/log.h>
#include "../shadow_screen.h" #include "../shadow_screen.h"
#include "../shadow_client.h"
#include "../shadow_encoder.h"
#include "../shadow_capture.h" #include "../shadow_capture.h"
#include "../shadow_surface.h" #include "../shadow_surface.h"
#include "../shadow_subsystem.h"
#include "x11_shadow.h" #include "x11_shadow.h"
@ -91,6 +95,20 @@ void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, U
#ifdef WITH_XTEST #ifdef WITH_XTEST
int button = 0; int button = 0;
BOOL down = FALSE; BOOL down = FALSE;
rdpShadowServer* server;
rdpShadowSurface* surface;
server = subsystem->server;
surface = server->surface;
x += surface->x;
y += surface->y;
if (server->shareSubRect)
{
x += server->subRect.left;
y += server->subRect.top;
}
XTestGrabControl(subsystem->display, True); XTestGrabControl(subsystem->display, True);
@ -121,7 +139,7 @@ void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, U
if (flags & PTR_FLAGS_DOWN) if (flags & PTR_FLAGS_DOWN)
down = TRUE; down = TRUE;
if (button != 0) if (button)
XTestFakeButtonEvent(subsystem->display, button, down, 0); XTestFakeButtonEvent(subsystem->display, button, down, 0);
} }
@ -134,8 +152,23 @@ void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16
#ifdef WITH_XTEST #ifdef WITH_XTEST
int button = 0; int button = 0;
BOOL down = FALSE; BOOL down = FALSE;
rdpShadowServer* server;
rdpShadowSurface* surface;
server = subsystem->server;
surface = server->surface;
x += surface->x;
y += surface->y;
if (server->shareSubRect)
{
x += server->subRect.left;
y += server->subRect.top;
}
XTestGrabControl(subsystem->display, True); XTestGrabControl(subsystem->display, True);
XTestFakeMotionEvent(subsystem->display, 0, x, y, CurrentTime); XTestFakeMotionEvent(subsystem->display, 0, x, y, CurrentTime);
if (flags & PTR_XFLAGS_BUTTON1) if (flags & PTR_XFLAGS_BUTTON1)
@ -146,13 +179,99 @@ void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16
if (flags & PTR_XFLAGS_DOWN) if (flags & PTR_XFLAGS_DOWN)
down = TRUE; down = TRUE;
if (button != 0) if (button)
XTestFakeButtonEvent(subsystem->display, button, down, 0); XTestFakeButtonEvent(subsystem->display, button, down, 0);
XTestGrabControl(subsystem->display, False); XTestGrabControl(subsystem->display, False);
#endif #endif
} }
int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage)
{
int x, y, n, k;
rdpShadowServer* server;
rdpShadowSurface* surface;
server = subsystem->server;
surface = server->surface;
if (getImage)
{
#ifdef WITH_XFIXES
UINT32* pDstPixel;
XFixesCursorImage* ci;
ci = XFixesGetCursorImage(subsystem->display);
x = ci->x;
y = ci->y;
if (ci->width > subsystem->cursorMaxWidth)
return -1;
if (ci->height > subsystem->cursorMaxHeight)
return -1;
subsystem->cursorHotX = ci->xhot;
subsystem->cursorHotY = ci->yhot;
subsystem->cursorWidth = ci->width;
subsystem->cursorHeight = ci->height;
subsystem->cursorId = ci->cursor_serial;
n = ci->width * ci->height;
pDstPixel = (UINT32*) subsystem->cursorPixels;
for (k = 0; k < n; k++)
{
/* XFixesCursorImage.pixels is in *unsigned long*, which may be 8 bytes */
*pDstPixel++ = (UINT32) ci->pixels[k];
}
XFree(ci);
#endif
}
else
{
UINT32 mask;
int win_x, win_y;
int root_x, root_y;
Window root, child;
if (!XQueryPointer(subsystem->display, subsystem->root_window,
&root, &child, &root_x, &root_y, &win_x, &win_y, &mask))
{
return -1;
}
x = root_x;
y = root_y;
}
subsystem->cursorX = x;
subsystem->cursorY = y;
return 1;
}
int x11_shadow_handle_xevent(x11ShadowSubsystem* subsystem, XEvent* xevent)
{
if (xevent->type == MotionNotify)
{
}
#ifdef WITH_XFIXES
if (xevent->type == subsystem->xfixes_cursor_notify_event)
{
x11_shadow_query_cursor(subsystem, TRUE);
}
#endif
return 1;
}
void x11_shadow_validate_region(x11ShadowSubsystem* subsystem, int x, int y, int width, int height) void x11_shadow_validate_region(x11ShadowSubsystem* subsystem, int x, int y, int width, int height)
{ {
XRectangle region; XRectangle region;
@ -171,19 +290,117 @@ void x11_shadow_validate_region(x11ShadowSubsystem* subsystem, int x, int y, int
#endif #endif
} }
int x11_shadow_invalidate_region(x11ShadowSubsystem* subsystem, int x, int y, int width, int height) int x11_shadow_blend_cursor(x11ShadowSubsystem* subsystem)
{ {
rdpShadowServer* server; int x, y;
RECTANGLE_16 invalidRect; int nXSrc;
int nYSrc;
int nXDst;
int nYDst;
int nWidth;
int nHeight;
int nSrcStep;
int nDstStep;
int nSrcPad;
int nDstPad;
BYTE* pSrcData;
BYTE* pDstData;
BYTE* pSrcPixel;
BYTE* pDstPixel;
BYTE A, R, G, B;
rdpShadowSurface* surface;
server = subsystem->server; surface = subsystem->server->surface;
invalidRect.left = x; nXSrc = 0;
invalidRect.top = y; nYSrc = 0;
invalidRect.right = x + width;
invalidRect.bottom = y + height;
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); nWidth = subsystem->cursorWidth;
nHeight = subsystem->cursorHeight;
nXDst = subsystem->cursorX - surface->x - subsystem->cursorHotX;
nYDst = subsystem->cursorY - surface->y - subsystem->cursorHotY;
if (nXDst >= surface->width)
return 1;
if (nXDst < 0)
{
nXDst *= -1;
if (nXDst >= nWidth)
return 1;
nXSrc = nXDst;
nWidth -= nXDst;
nXDst = 0;
}
if (nYDst >= surface->height)
return 1;
if (nYDst < 0)
{
nYDst *= -1;
if (nYDst >= nHeight)
return 1;
nYSrc = nYDst;
nHeight -= nYDst;
nYDst = 0;
}
if ((nXDst + nWidth) > surface->width)
nWidth = surface->width - nXDst;
if ((nYDst + nHeight) > surface->height)
nHeight = surface->height - nYDst;
pSrcData = subsystem->cursorPixels;
nSrcStep = subsystem->cursorWidth * 4;
pDstData = surface->data;
nDstStep = surface->scanline;
nSrcPad = (nSrcStep - (nWidth * 4));
nDstPad = (nDstStep - (nWidth * 4));
pSrcPixel = &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)];
pDstPixel = &pDstData[(nYDst * nDstStep) + (nXDst * 4)];
for (y = 0; y < nHeight; y++)
{
pSrcPixel = &pSrcData[((nYSrc + y) * nSrcStep) + (nXSrc * 4)];
pDstPixel = &pDstData[((nYDst + y) * nDstStep) + (nXDst * 4)];
for (x = 0; x < nWidth; x++)
{
B = *pSrcPixel++;
G = *pSrcPixel++;
R = *pSrcPixel++;
A = *pSrcPixel++;
if (A == 0xFF)
{
pDstPixel[0] = B;
pDstPixel[1] = G;
pDstPixel[2] = R;
}
else
{
pDstPixel[0] = B + (pDstPixel[0] * (0xFF - A) + (0xFF / 2)) / 0xFF;
pDstPixel[1] = G + (pDstPixel[1] * (0xFF - A) + (0xFF / 2)) / 0xFF;
pDstPixel[2] = R + (pDstPixel[2] * (0xFF - A) + (0xFF / 2)) / 0xFF;
}
pDstPixel[3] = 0xFF;
pDstPixel += 4;
}
pSrcPixel += nSrcPad;
pDstPixel += nDstPad;
}
return 1; return 1;
} }
@ -199,40 +416,69 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
rdpShadowServer* server; rdpShadowServer* server;
rdpShadowSurface* surface; rdpShadowSurface* surface;
RECTANGLE_16 invalidRect; RECTANGLE_16 invalidRect;
RECTANGLE_16 surfaceRect;
const RECTANGLE_16 *extents;
server = subsystem->server; server = subsystem->server;
surface = server->surface; surface = server->surface;
screen = server->screen; screen = server->screen;
count = ArrayList_Count(server->clients);
if (count < 1)
return 1;
if ((count == 1) && subsystem->suppressOutput)
return 1;
surfaceRect.left = 0;
surfaceRect.top = 0;
surfaceRect.right = surface->width;
surfaceRect.bottom = surface->height;
XLockDisplay(subsystem->display);
if (subsystem->use_xshm) if (subsystem->use_xshm)
{ {
XLockDisplay(subsystem->display); image = subsystem->fb_image;
XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap, XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap,
subsystem->xshm_gc, 0, 0, subsystem->width, subsystem->height, 0, 0); subsystem->xshm_gc, 0, 0, subsystem->width, subsystem->height, 0, 0);
status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height,
(BYTE*) &(image->data[surface->width * 4]), image->bytes_per_line, &invalidRect);
}
else
{
image = XGetImage(subsystem->display, subsystem->root_window,
surface->x, surface->y, surface->width, surface->height, AllPlanes, ZPixmap);
status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height,
(BYTE*) image->data, image->bytes_per_line, &invalidRect);
}
XSync(subsystem->display, False); XSync(subsystem->display, False);
XUnlockDisplay(subsystem->display); XUnlockDisplay(subsystem->display);
image = subsystem->fb_image; region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect);
status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height, if (!region16_is_empty(&(subsystem->invalidRegion)))
(BYTE*) image->data, image->bytes_per_line, &invalidRect);
if (status > 0)
{ {
x = invalidRect.left; extents = region16_extents(&(subsystem->invalidRegion));
y = invalidRect.top;
width = invalidRect.right - invalidRect.left; x = extents->left;
height = invalidRect.bottom - invalidRect.top; y = extents->top;
width = extents->right - extents->left;
height = extents->bottom - extents->top;
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
surface->scanline, x - surface->x, y - surface->y, width, height, surface->scanline, x, y, width, height,
(BYTE*) image->data, PIXEL_FORMAT_XRGB32, (BYTE*) image->data, PIXEL_FORMAT_XRGB32,
image->bytes_per_line, x, y, NULL); image->bytes_per_line, x, y, NULL);
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); x11_shadow_blend_cursor(subsystem);
count = ArrayList_Count(server->clients); count = ArrayList_Count(server->clients);
@ -244,61 +490,79 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
DeleteSynchronizationBarrier(&(subsystem->barrier)); DeleteSynchronizationBarrier(&(subsystem->barrier));
if (count == 1)
{
rdpShadowClient* client;
client = (rdpShadowClient*) ArrayList_GetItem(server->clients, 0);
if (client)
{
subsystem->captureFrameRate = client->encoder->fps;
}
}
ResetEvent(subsystem->updateEvent); ResetEvent(subsystem->updateEvent);
region16_clear(&(subsystem->invalidRegion)); region16_clear(&(subsystem->invalidRegion));
} }
if (!subsystem->use_xshm)
XDestroyImage(image);
return 1;
}
int x11_shadow_subsystem_process_message(x11ShadowSubsystem* subsystem, wMessage* message)
{
if (message->id == SHADOW_MSG_IN_REFRESH_OUTPUT_ID)
{
UINT32 index;
SHADOW_MSG_IN_REFRESH_OUTPUT* msg = (SHADOW_MSG_IN_REFRESH_OUTPUT*) message->wParam;
if (msg->numRects)
{
for (index = 0; index < msg->numRects; index++)
{
region16_union_rect(&(subsystem->invalidRegion),
&(subsystem->invalidRegion), &msg->rects[index]);
}
} }
else else
{ {
XLockDisplay(subsystem->display); RECTANGLE_16 refreshRect;
image = XGetImage(subsystem->display, subsystem->root_window, refreshRect.left = 0;
0, 0, subsystem->width, subsystem->height, AllPlanes, ZPixmap); refreshRect.top = 0;
refreshRect.right = subsystem->width;
refreshRect.bottom = subsystem->height;
XUnlockDisplay(subsystem->display); region16_union_rect(&(subsystem->invalidRegion),
&(subsystem->invalidRegion), &refreshRect);
status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height, }
(BYTE*) image->data, image->bytes_per_line, &invalidRect); }
else if (message->id == SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID)
if (status > 0)
{ {
x = invalidRect.left; SHADOW_MSG_IN_SUPPRESS_OUTPUT* msg = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) message->wParam;
y = invalidRect.top;
width = invalidRect.right - invalidRect.left;
height = invalidRect.bottom - invalidRect.top;
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, subsystem->suppressOutput = (msg->allow) ? FALSE : TRUE;
surface->scanline, x - surface->x, y - surface->y, width, height,
(BYTE*) image->data, PIXEL_FORMAT_XRGB32,
image->bytes_per_line, x, y, NULL);
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect); if (msg->allow)
{
count = ArrayList_Count(server->clients); region16_union_rect(&(subsystem->invalidRegion),
&(subsystem->invalidRegion), &(msg->rect));
InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1); }
SetEvent(subsystem->updateEvent);
EnterSynchronizationBarrier(&(subsystem->barrier), 0);
DeleteSynchronizationBarrier(&(subsystem->barrier));
ResetEvent(subsystem->updateEvent);
region16_clear(&(subsystem->invalidRegion));
} }
XDestroyImage(image); if (message->Free)
} message->Free(message);
return 1; return 1;
} }
void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem) void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
{ {
int fps; XEvent xevent;
DWORD status; DWORD status;
DWORD nCount; DWORD nCount;
UINT64 cTime; UINT64 cTime;
@ -306,16 +570,17 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
DWORD dwInterval; DWORD dwInterval;
UINT64 frameTime; UINT64 frameTime;
HANDLE events[32]; HANDLE events[32];
HANDLE StopEvent; wMessage message;
wMessagePipe* MsgPipe;
StopEvent = subsystem->server->StopEvent; MsgPipe = subsystem->MsgPipe;
nCount = 0; nCount = 0;
events[nCount++] = StopEvent;
events[nCount++] = subsystem->event; events[nCount++] = subsystem->event;
events[nCount++] = MessageQueue_Event(MsgPipe->In);
fps = 16; subsystem->captureFrameRate = 16;
dwInterval = 1000 / fps; dwInterval = 1000 / subsystem->captureFrameRate;
frameTime = GetTickCount64() + dwInterval; frameTime = GetTickCount64() + dwInterval;
while (1) while (1)
@ -325,16 +590,32 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
status = WaitForMultipleObjects(nCount, events, FALSE, dwTimeout); status = WaitForMultipleObjects(nCount, events, FALSE, dwTimeout);
if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0) if (WaitForSingleObject(MessageQueue_Event(MsgPipe->In), 0) == WAIT_OBJECT_0)
{ {
if (MessageQueue_Peek(MsgPipe->In, &message, TRUE))
{
if (message.id == WMQ_QUIT)
break; break;
x11_shadow_subsystem_process_message(subsystem, &message);
}
}
if (WaitForSingleObject(subsystem->event, 0) == WAIT_OBJECT_0)
{
if (XEventsQueued(subsystem->display, QueuedAlready))
{
XNextEvent(subsystem->display, &xevent);
x11_shadow_handle_xevent(subsystem, &xevent);
}
} }
if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime)) if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime))
{ {
x11_shadow_query_cursor(subsystem, FALSE);
x11_shadow_screen_grab(subsystem); x11_shadow_screen_grab(subsystem);
dwInterval = 1000 / fps; dwInterval = 1000 / subsystem->captureFrameRate;
frameTime += dwInterval; frameTime += dwInterval;
} }
} }
@ -343,6 +624,36 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
return NULL; return NULL;
} }
int x11_shadow_subsystem_base_init(x11ShadowSubsystem* subsystem)
{
if (subsystem->display)
return 1; /* initialize once */
if (!getenv("DISPLAY"))
setenv("DISPLAY", ":0", 1);
if (!XInitThreads())
return -1;
subsystem->display = XOpenDisplay(NULL);
if (!subsystem->display)
{
WLog_ERR(TAG, "failed to open display: %s", XDisplayName(NULL));
return -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);
return 1;
}
int x11_shadow_xfixes_init(x11ShadowSubsystem* subsystem) int x11_shadow_xfixes_init(x11ShadowSubsystem* subsystem)
{ {
#ifdef WITH_XFIXES #ifdef WITH_XFIXES
@ -356,7 +667,7 @@ int x11_shadow_xfixes_init(x11ShadowSubsystem* subsystem)
if (!XFixesQueryVersion(subsystem->display, &major, &minor)) if (!XFixesQueryVersion(subsystem->display, &major, &minor))
return -1; return -1;
subsystem->xfixes_notify_event = xfixes_event + XFixesCursorNotify; subsystem->xfixes_cursor_notify_event = xfixes_event + XFixesCursorNotify;
XFixesSelectCursorInput(subsystem->display, DefaultRootWindow(subsystem->display), XFixesDisplayCursorNotifyMask); XFixesSelectCursorInput(subsystem->display, DefaultRootWindow(subsystem->display), XFixesDisplayCursorNotifyMask);
@ -369,14 +680,11 @@ int x11_shadow_xfixes_init(x11ShadowSubsystem* subsystem)
int x11_shadow_xinerama_init(x11ShadowSubsystem* subsystem) int x11_shadow_xinerama_init(x11ShadowSubsystem* subsystem)
{ {
#ifdef WITH_XINERAMA #ifdef WITH_XINERAMA
int index;
int numMonitors;
int major, minor; int major, minor;
int xinerama_event; int xinerama_event;
int xinerama_error; int xinerama_error;
MONITOR_DEF* monitor;
XineramaScreenInfo* screen; x11_shadow_subsystem_base_init(subsystem);
XineramaScreenInfo* screens;
if (!XineramaQueryExtension(subsystem->display, &xinerama_event, &xinerama_error)) if (!XineramaQueryExtension(subsystem->display, &xinerama_event, &xinerama_error))
return -1; return -1;
@ -387,32 +695,10 @@ int x11_shadow_xinerama_init(x11ShadowSubsystem* subsystem)
if (!XineramaIsActive(subsystem->display)) if (!XineramaIsActive(subsystem->display))
return -1; return -1;
screens = XineramaQueryScreens(subsystem->display, &numMonitors);
if (numMonitors > 16)
numMonitors = 16;
if (!screens || (numMonitors < 1))
return -1;
subsystem->monitorCount = numMonitors;
for (index = 0; index < numMonitors; index++)
{
screen = &screens[index];
monitor = &(subsystem->monitors[index]);
monitor->left = screen->x_org;
monitor->top = screen->y_org;
monitor->right = monitor->left + screen->width;
monitor->bottom = monitor->top + screen->height;
monitor->flags = (index == 0) ? 1 : 0;
}
XFree(screens);
#endif
return 1; return 1;
#else
return -1;
#endif
} }
int x11_shadow_xdamage_init(x11ShadowSubsystem* subsystem) int x11_shadow_xdamage_init(x11ShadowSubsystem* subsystem)
@ -527,6 +813,82 @@ int x11_shadow_xshm_init(x11ShadowSubsystem* subsystem)
return 1; return 1;
} }
int x11_shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors)
{
int index;
Display* display;
int displayWidth;
int displayHeight;
int numMonitors = 0;
MONITOR_DEF* monitor;
if (!getenv("DISPLAY"))
setenv("DISPLAY", ":0", 1);
display = XOpenDisplay(NULL);
if (!display)
{
WLog_ERR(TAG, "failed to open display: %s", XDisplayName(NULL));
return -1;
}
displayWidth = WidthOfScreen(DefaultScreenOfDisplay(display));
displayHeight = HeightOfScreen(DefaultScreenOfDisplay(display));
#ifdef WITH_XINERAMA
{
int major, minor;
int xinerama_event;
int xinerama_error;
XineramaScreenInfo* screen;
XineramaScreenInfo* screens;
if (XineramaQueryExtension(display, &xinerama_event, &xinerama_error) &&
XDamageQueryVersion(display, &major, &minor) && XineramaIsActive(display))
{
screens = XineramaQueryScreens(display, &numMonitors);
if (numMonitors > maxMonitors)
numMonitors = maxMonitors;
if (screens && (numMonitors > 0))
{
for (index = 0; index < numMonitors; index++)
{
screen = &screens[index];
monitor = &monitors[index];
monitor->left = screen->x_org;
monitor->top = screen->y_org;
monitor->right = monitor->left + screen->width;
monitor->bottom = monitor->top + screen->height;
monitor->flags = (index == 0) ? 1 : 0;
}
}
XFree(screens);
}
}
#endif
if (numMonitors < 1)
{
index = 0;
numMonitors = 1;
monitor = &monitors[index];
monitor->left = 0;
monitor->top = 0;
monitor->right = displayWidth;
monitor->bottom = displayHeight;
monitor->flags = 1;
}
return numMonitors;
}
int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem) int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
{ {
int i; int i;
@ -541,27 +903,9 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
XPixmapFormatValues* pfs; XPixmapFormatValues* pfs;
MONITOR_DEF* virtualScreen; MONITOR_DEF* virtualScreen;
/** subsystem->numMonitors = x11_shadow_enum_monitors(subsystem->monitors, 16);
* To see if your X11 server supports shared pixmaps, use:
* xdpyinfo -ext MIT-SHM | grep "shared pixmaps"
*/
if (!getenv("DISPLAY")) x11_shadow_subsystem_base_init(subsystem);
{
/* Set DISPLAY variable if not already set */
setenv("DISPLAY", ":0", 1);
}
if (!XInitThreads())
return -1;
subsystem->display = XOpenDisplay(NULL);
if (!subsystem->display)
{
WLog_ERR(TAG, "failed to open display: %s", XDisplayName(NULL));
return -1;
}
extensions = XListExtensions(subsystem->display, &nextensions); extensions = XListExtensions(subsystem->display, &nextensions);
@ -579,17 +923,6 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
if (subsystem->composite) if (subsystem->composite)
subsystem->use_xdamage = FALSE; subsystem->use_xdamage = FALSE;
if (!subsystem->use_xdamage)
subsystem->use_xfixes = FALSE;
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); pfs = XListPixmapFormats(subsystem->display, &pf_count);
if (!pfs) if (!pfs)
@ -637,6 +970,15 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
XSelectInput(subsystem->display, subsystem->root_window, SubstructureNotifyMask); XSelectInput(subsystem->display, subsystem->root_window, SubstructureNotifyMask);
subsystem->cursorMaxWidth = 256;
subsystem->cursorMaxHeight = 256;
subsystem->cursorPixels = _aligned_malloc(subsystem->cursorMaxWidth * subsystem->cursorMaxHeight * 4, 16);
if (!subsystem->cursorPixels)
return -1;
x11_shadow_query_cursor(subsystem, TRUE);
if (subsystem->use_xfixes) if (subsystem->use_xfixes)
{ {
if (x11_shadow_xfixes_init(subsystem) < 0) if (x11_shadow_xfixes_init(subsystem) < 0)
@ -671,16 +1013,6 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
virtualScreen->bottom = subsystem->height; virtualScreen->bottom = subsystem->height;
virtualScreen->flags = 1; virtualScreen->flags = 1;
if (subsystem->monitorCount < 1)
{
subsystem->monitorCount = 1;
subsystem->monitors[0].left = virtualScreen->left;
subsystem->monitors[0].top = virtualScreen->top;
subsystem->monitors[0].right = virtualScreen->right;
subsystem->monitors[0].bottom = virtualScreen->bottom;
subsystem->monitors[0].flags = 1;
}
WLog_INFO(TAG, "X11 Extensions: XFixes: %d Xinerama: %d XDamage: %d XShm: %d", WLog_INFO(TAG, "X11 Extensions: XFixes: %d Xinerama: %d XDamage: %d XShm: %d",
subsystem->use_xfixes, subsystem->use_xinerama, subsystem->use_xdamage, subsystem->use_xshm); subsystem->use_xfixes, subsystem->use_xinerama, subsystem->use_xdamage, subsystem->use_xshm);
@ -704,17 +1036,21 @@ int x11_shadow_subsystem_uninit(x11ShadowSubsystem* subsystem)
subsystem->event = NULL; subsystem->event = NULL;
} }
if (subsystem->cursorPixels)
{
_aligned_free(subsystem->cursorPixels);
subsystem->cursorPixels = NULL;
}
return 1; return 1;
} }
int x11_shadow_subsystem_start(x11ShadowSubsystem* subsystem) int x11_shadow_subsystem_start(x11ShadowSubsystem* subsystem)
{ {
HANDLE thread;
if (!subsystem) if (!subsystem)
return -1; return -1;
thread = CreateThread(NULL, 0, subsystem->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) x11_shadow_subsystem_thread, (LPTHREAD_START_ROUTINE) x11_shadow_subsystem_thread,
(void*) subsystem, 0, NULL); (void*) subsystem, 0, NULL);
@ -726,9 +1062,41 @@ int x11_shadow_subsystem_stop(x11ShadowSubsystem* subsystem)
if (!subsystem) if (!subsystem)
return -1; return -1;
if (subsystem->thread)
{
MessageQueue_PostQuit(subsystem->MsgPipe->In, 0);
WaitForSingleObject(subsystem->thread, INFINITE);
CloseHandle(subsystem->thread);
subsystem->thread = NULL;
}
return 1; return 1;
} }
x11ShadowSubsystem* x11_shadow_subsystem_new()
{
x11ShadowSubsystem* subsystem;
subsystem = (x11ShadowSubsystem*) calloc(1, sizeof(x11ShadowSubsystem));
if (!subsystem)
return NULL;
subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) x11_shadow_input_synchronize_event;
subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) x11_shadow_input_keyboard_event;
subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) x11_shadow_input_unicode_keyboard_event;
subsystem->MouseEvent = (pfnShadowMouseEvent) x11_shadow_input_mouse_event;
subsystem->ExtendedMouseEvent = (pfnShadowExtendedMouseEvent) x11_shadow_input_extended_mouse_event;
subsystem->composite = FALSE;
subsystem->use_xshm = FALSE; /* temporarily disabled */
subsystem->use_xfixes = TRUE;
subsystem->use_xdamage = FALSE;
subsystem->use_xinerama = TRUE;
return subsystem;
}
void x11_shadow_subsystem_free(x11ShadowSubsystem* subsystem) void x11_shadow_subsystem_free(x11ShadowSubsystem* subsystem)
{ {
if (!subsystem) if (!subsystem)
@ -736,50 +1104,21 @@ void x11_shadow_subsystem_free(x11ShadowSubsystem* subsystem)
x11_shadow_subsystem_uninit(subsystem); x11_shadow_subsystem_uninit(subsystem);
region16_uninit(&(subsystem->invalidRegion));
CloseHandle(subsystem->updateEvent);
free(subsystem); free(subsystem);
} }
x11ShadowSubsystem* x11_shadow_subsystem_new(rdpShadowServer* server) int X11_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints)
{ {
x11ShadowSubsystem* subsystem; pEntryPoints->New = (pfnShadowSubsystemNew) x11_shadow_subsystem_new;
pEntryPoints->Free = (pfnShadowSubsystemFree) x11_shadow_subsystem_free;
subsystem = (x11ShadowSubsystem*) calloc(1, sizeof(x11ShadowSubsystem)); pEntryPoints->Init = (pfnShadowSubsystemInit) x11_shadow_subsystem_init;
pEntryPoints->Uninit = (pfnShadowSubsystemInit) x11_shadow_subsystem_uninit;
if (!subsystem) pEntryPoints->Start = (pfnShadowSubsystemStart) x11_shadow_subsystem_start;
return NULL; pEntryPoints->Stop = (pfnShadowSubsystemStop) x11_shadow_subsystem_stop;
subsystem->server = server; pEntryPoints->EnumMonitors = (pfnShadowEnumMonitors) x11_shadow_enum_monitors;
subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL); return 1;
region16_init(&(subsystem->invalidRegion));
subsystem->Init = (pfnShadowSubsystemInit) x11_shadow_subsystem_init;
subsystem->Uninit = (pfnShadowSubsystemInit) x11_shadow_subsystem_uninit;
subsystem->Start = (pfnShadowSubsystemStart) x11_shadow_subsystem_start;
subsystem->Stop = (pfnShadowSubsystemStop) x11_shadow_subsystem_stop;
subsystem->Free = (pfnShadowSubsystemFree) x11_shadow_subsystem_free;
subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) x11_shadow_input_synchronize_event;
subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) x11_shadow_input_keyboard_event;
subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) x11_shadow_input_unicode_keyboard_event;
subsystem->MouseEvent = (pfnShadowMouseEvent) x11_shadow_input_mouse_event;
subsystem->ExtendedMouseEvent = (pfnShadowExtendedMouseEvent) x11_shadow_input_extended_mouse_event;
subsystem->composite = FALSE;
subsystem->use_xshm = TRUE;
subsystem->use_xfixes = TRUE;
subsystem->use_xdamage = FALSE;
subsystem->use_xinerama = TRUE;
return subsystem;
}
rdpShadowSubsystem* X11_ShadowCreateSubsystem(rdpShadowServer* server)
{
return (rdpShadowSubsystem*) x11_shadow_subsystem_new(server);
} }

View File

@ -80,6 +80,17 @@ struct x11_shadow_subsystem
Window root_window; Window root_window;
XShmSegmentInfo fb_shm_info; XShmSegmentInfo fb_shm_info;
int cursorX;
int cursorY;
int cursorHotX;
int cursorHotY;
int cursorWidth;
int cursorHeight;
UINT32 cursorId;
BYTE* cursorPixels;
int cursorMaxWidth;
int cursorMaxHeight;
#ifdef WITH_XDAMAGE #ifdef WITH_XDAMAGE
GC xshm_gc; GC xshm_gc;
Damage xdamage; Damage xdamage;
@ -88,7 +99,7 @@ struct x11_shadow_subsystem
#endif #endif
#ifdef WITH_XFIXES #ifdef WITH_XFIXES
int xfixes_notify_event; int xfixes_cursor_notify_event;
#endif #endif
}; };

86
server/shadow/shadow.c Normal file
View File

@ -0,0 +1,86 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/ssl.h>
#include <winpr/wnd.h>
#include <winpr/path.h>
#include <winpr/cmdline.h>
#include <winpr/winsock.h>
#include <winpr/tools/makecert.h>
#ifdef _WIN32
#include <openssl/applink.c>
#endif
#ifdef _WIN32
static BOOL g_MessagePump = TRUE;
#else
static BOOL g_MessagePump = FALSE;
#endif
#include <freerdp/server/shadow.h>
int main(int argc, char** argv)
{
MSG msg;
int status;
DWORD dwExitCode;
rdpShadowServer* server;
server = shadow_server_new();
if (!server)
return 0;
status = shadow_server_parse_command_line(server, argc, argv);
status = shadow_server_command_line_status_print(server, argc, argv, status);
if (status < 0)
return 0;
if (shadow_server_init(server) < 0)
return 0;
if (shadow_server_start(server) < 0)
return 0;
if (g_MessagePump)
{
while (GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
WaitForSingleObject(server->thread, INFINITE);
GetExitCodeThread(server->thread, &dwExitCode);
shadow_server_free(server);
return 0;
}

View File

@ -28,6 +28,7 @@
#include "shadow_encoder.h" #include "shadow_encoder.h"
#include "shadow_capture.h" #include "shadow_capture.h"
#include "shadow_channels.h" #include "shadow_channels.h"
#include "shadow_subsystem.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -40,6 +40,7 @@ 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->subsystem = server->subsystem;
settings = peer->settings; settings = peer->settings;
@ -71,7 +72,7 @@ void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
client->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); client->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
client->encoder = shadow_encoder_new(server); client->encoder = shadow_encoder_new(client);
ArrayList_Add(server->clients, (void*) client); ArrayList_Add(server->clients, (void*) client);
} }
@ -103,6 +104,22 @@ void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client)
} }
} }
void shadow_client_message_free(wMessage* message)
{
if (message->id == SHADOW_MSG_IN_REFRESH_OUTPUT_ID)
{
SHADOW_MSG_IN_REFRESH_OUTPUT* wParam = (SHADOW_MSG_IN_REFRESH_OUTPUT*) message->wParam;
free(wParam->rects);
free(wParam);
}
else if (message->id == SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID)
{
SHADOW_MSG_IN_SUPPRESS_OUTPUT* wParam = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) message->wParam;
free(wParam);
}
}
BOOL shadow_client_capabilities(freerdp_peer* peer) BOOL shadow_client_capabilities(freerdp_peer* peer)
{ {
return TRUE; return TRUE;
@ -114,13 +131,26 @@ BOOL shadow_client_post_connect(freerdp_peer* peer)
rdpSettings* settings; rdpSettings* settings;
rdpShadowClient* client; rdpShadowClient* client;
rdpShadowSurface* lobby; rdpShadowSurface* lobby;
rdpShadowServer* server;
RECTANGLE_16 invalidRect; RECTANGLE_16 invalidRect;
client = (rdpShadowClient*) peer->context; client = (rdpShadowClient*) peer->context;
settings = peer->settings; settings = peer->settings;
server = client->server;
settings->DesktopWidth = client->server->screen->width; if (!server->shareSubRect)
settings->DesktopHeight = client->server->screen->height; {
width = server->screen->width;
height = server->screen->height;
}
else
{
width = server->subRect.right - server->subRect.left;
height = server->subRect.bottom - server->subRect.top;
}
settings->DesktopWidth = width;
settings->DesktopHeight = height;
if (settings->ColorDepth == 24) if (settings->ColorDepth == 24)
settings->ColorDepth = 16; /* disable 24bpp */ settings->ColorDepth = 16; /* disable 24bpp */
@ -132,9 +162,6 @@ BOOL shadow_client_post_connect(freerdp_peer* peer)
shadow_client_channels_post_connect(client); shadow_client_channels_post_connect(client);
width = settings->DesktopWidth;
height = settings->DesktopHeight;
invalidRect.left = 0; invalidRect.left = 0;
invalidRect.top = 0; invalidRect.top = 0;
invalidRect.right = width; invalidRect.right = width;
@ -155,6 +182,63 @@ BOOL shadow_client_post_connect(freerdp_peer* peer)
return TRUE; return TRUE;
} }
void shadow_client_refresh_rect(rdpShadowClient* client, BYTE count, RECTANGLE_16* areas)
{
wMessage message = { 0 };
SHADOW_MSG_IN_REFRESH_OUTPUT* wParam;
wMessagePipe* MsgPipe = client->subsystem->MsgPipe;
wParam = (SHADOW_MSG_IN_REFRESH_OUTPUT*) calloc(1, sizeof(SHADOW_MSG_IN_REFRESH_OUTPUT));
if (!wParam)
return;
wParam->numRects = (UINT32) count;
if (wParam->numRects)
{
wParam->rects = (RECTANGLE_16*) calloc(wParam->numRects, sizeof(RECTANGLE_16));
if (!wParam->rects)
return;
}
CopyMemory(wParam->rects, areas, wParam->numRects * sizeof(RECTANGLE_16));
message.id = SHADOW_MSG_IN_REFRESH_OUTPUT_ID;
message.wParam = (void*) wParam;
message.lParam = NULL;
message.context = (void*) client;
message.Free = shadow_client_message_free;
MessageQueue_Dispatch(MsgPipe->In, &message);
}
void shadow_client_suppress_output(rdpShadowClient* client, BYTE allow, RECTANGLE_16* area)
{
wMessage message = { 0 };
SHADOW_MSG_IN_SUPPRESS_OUTPUT* wParam;
wMessagePipe* MsgPipe = client->subsystem->MsgPipe;
wParam = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) calloc(1, sizeof(SHADOW_MSG_IN_SUPPRESS_OUTPUT));
if (!wParam)
return;
wParam->allow = (UINT32) allow;
if (area)
CopyMemory(&(wParam->rect), area, sizeof(RECTANGLE_16));
message.id = SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID;
message.wParam = (void*) wParam;
message.lParam = NULL;
message.context = (void*) client;
message.Free = shadow_client_message_free;
MessageQueue_Dispatch(MsgPipe->In, &message);
}
BOOL shadow_client_activate(freerdp_peer* peer) BOOL shadow_client_activate(freerdp_peer* peer)
{ {
rdpShadowClient* client; rdpShadowClient* client;
@ -166,6 +250,8 @@ BOOL shadow_client_activate(freerdp_peer* peer)
shadow_encoder_reset(client->encoder); shadow_encoder_reset(client->encoder);
shadow_client_refresh_rect(client, 0, NULL);
return TRUE; return TRUE;
} }
@ -184,11 +270,6 @@ void shadow_client_surface_frame_acknowledge(rdpShadowClient* client, UINT32 fra
} }
} }
void shadow_client_suppress_output(rdpShadowClient* client, BYTE allow, RECTANGLE_16* area)
{
}
int shadow_client_send_surface_frame_marker(rdpShadowClient* client, UINT32 action, UINT32 id) int shadow_client_send_surface_frame_marker(rdpShadowClient* client, UINT32 action, UINT32 id)
{ {
SURFACE_FRAME_MARKER surfaceFrameMarker; SURFACE_FRAME_MARKER surfaceFrameMarker;
@ -206,6 +287,8 @@ int shadow_client_send_surface_frame_marker(rdpShadowClient* client, UINT32 acti
int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* surface, int nXSrc, int nYSrc, int nWidth, int nHeight) int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* surface, int nXSrc, int nYSrc, int nWidth, int nHeight)
{ {
int i; int i;
BOOL first;
BOOL last;
wStream* s; wStream* s;
int nSrcStep; int nSrcStep;
BYTE* pSrcData; BYTE* pSrcData;
@ -228,12 +311,24 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s
pSrcData = surface->data; pSrcData = surface->data;
nSrcStep = surface->scanline; nSrcStep = surface->scanline;
if (encoder->frameAck) if (server->shareSubRect)
{ {
frameId = (UINT32) shadow_encoder_create_frame_id(encoder); int subX, subY;
shadow_client_send_surface_frame_marker(client, SURFACECMD_FRAMEACTION_BEGIN, frameId); int subWidth, subHeight;
subX = server->subRect.left;
subY = server->subRect.top;
subWidth = server->subRect.right - server->subRect.left;
subHeight = server->subRect.bottom - server->subRect.top;
nXSrc -= subX;
nYSrc -= subY;
pSrcData = &pSrcData[(subY * nSrcStep) + (subX * 4)];
} }
if (encoder->frameAck)
frameId = (UINT32) shadow_encoder_create_frame_id(encoder);
if (settings->RemoteFxCodec) if (settings->RemoteFxCodec)
{ {
RFX_RECT rect; RFX_RECT rect;
@ -270,7 +365,13 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s
cmd.bitmapDataLength = Stream_GetPosition(s); cmd.bitmapDataLength = Stream_GetPosition(s);
cmd.bitmapData = Stream_Buffer(s); cmd.bitmapData = Stream_Buffer(s);
first = (i == 0) ? TRUE : FALSE;
last = ((i + 1) == numMessages) ? TRUE : FALSE;
if (!encoder->frameAck)
IFCALL(update->SurfaceBits, update->context, &cmd); IFCALL(update->SurfaceBits, update->context, &cmd);
else
IFCALL(update->SurfaceFrameBits, update->context, &cmd, first, last, frameId);
} }
free(messages); free(messages);
@ -305,17 +406,18 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s
cmd.bitmapDataLength = Stream_GetPosition(s); cmd.bitmapDataLength = Stream_GetPosition(s);
cmd.bitmapData = Stream_Buffer(s); cmd.bitmapData = Stream_Buffer(s);
first = (i == 0) ? TRUE : FALSE;
last = ((i + 1) == numMessages) ? TRUE : FALSE;
if (!encoder->frameAck)
IFCALL(update->SurfaceBits, update->context, &cmd); IFCALL(update->SurfaceBits, update->context, &cmd);
else
IFCALL(update->SurfaceFrameBits, update->context, &cmd, first, last, frameId);
} }
free(messages); free(messages);
} }
if (encoder->frameAck)
{
shadow_client_send_surface_frame_marker(client, SURFACECMD_FRAMEACTION_END, frameId);
}
return 1; return 1;
} }
@ -554,13 +656,18 @@ int shadow_client_send_surface_update(rdpShadowClient* client)
LeaveCriticalSection(&(client->lock)); LeaveCriticalSection(&(client->lock));
surfaceRect.left = surface->x; surfaceRect.left = 0;
surfaceRect.top = surface->y; surfaceRect.top = 0;
surfaceRect.right = surface->x + surface->width; surfaceRect.right = surface->width;
surfaceRect.bottom = surface->y + surface->height; surfaceRect.bottom = surface->height;
region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect); region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect);
if (server->shareSubRect)
{
region16_intersect_rect(&invalidRegion, &invalidRegion, &(server->subRect));
}
if (region16_is_empty(&invalidRegion)) if (region16_is_empty(&invalidRegion))
{ {
region16_uninit(&invalidRegion); region16_uninit(&invalidRegion);
@ -569,8 +676,8 @@ int shadow_client_send_surface_update(rdpShadowClient* client)
extents = region16_extents(&invalidRegion); extents = region16_extents(&invalidRegion);
nXSrc = extents->left - surface->x; nXSrc = extents->left - 0;
nYSrc = extents->top - surface->y; nYSrc = extents->top - 0;
nWidth = extents->right - extents->left; nWidth = extents->right - extents->left;
nHeight = extents->bottom - extents->top; nHeight = extents->bottom - extents->top;
@ -628,6 +735,7 @@ void* shadow_client_thread(rdpShadowClient* client)
HANDLE ChannelEvent; HANDLE ChannelEvent;
HANDLE UpdateEvent; HANDLE UpdateEvent;
freerdp_peer* peer; freerdp_peer* peer;
rdpContext* context;
rdpSettings* settings; rdpSettings* settings;
rdpShadowServer* server; rdpShadowServer* server;
rdpShadowScreen* screen; rdpShadowScreen* screen;
@ -639,7 +747,8 @@ void* shadow_client_thread(rdpShadowClient* client)
encoder = client->encoder; encoder = client->encoder;
subsystem = server->subsystem; subsystem = server->subsystem;
peer = ((rdpContext*) client)->peer; context = (rdpContext*) client;
peer = context->peer;
settings = peer->settings; settings = peer->settings;
peer->Capabilities = shadow_client_capabilities; peer->Capabilities = shadow_client_capabilities;
@ -650,9 +759,9 @@ void* shadow_client_thread(rdpShadowClient* client)
peer->Initialize(peer); peer->Initialize(peer);
peer->update->SurfaceFrameAcknowledge = (pSurfaceFrameAcknowledge) peer->update->RefreshRect = (pRefreshRect) shadow_client_refresh_rect;
shadow_client_surface_frame_acknowledge;
peer->update->SuppressOutput = (pSuppressOutput) shadow_client_suppress_output; peer->update->SuppressOutput = (pSuppressOutput) shadow_client_suppress_output;
peer->update->SurfaceFrameAcknowledge = (pSurfaceFrameAcknowledge) shadow_client_surface_frame_acknowledge;
StopEvent = client->StopEvent; StopEvent = client->StopEvent;
UpdateEvent = subsystem->updateEvent; UpdateEvent = subsystem->updateEvent;

View File

@ -84,7 +84,7 @@ int shadow_encoder_init_grid(rdpShadowEncoder* encoder)
{ {
for (j = 0; j < encoder->gridWidth; j++) for (j = 0; j < encoder->gridWidth; j++)
{ {
k = (i * encoder->gridHeight) + j; k = (i * encoder->gridWidth) + j;
encoder->grid[k] = &(encoder->gridBuffer[k * tileSize]); encoder->grid[k] = &(encoder->gridBuffer[k * tileSize]);
} }
} }
@ -166,9 +166,13 @@ int shadow_encoder_init_nsc(rdpShadowEncoder* encoder)
int shadow_encoder_init_bitmap(rdpShadowEncoder* encoder) int shadow_encoder_init_bitmap(rdpShadowEncoder* encoder)
{ {
DWORD planarFlags; DWORD planarFlags = 0;
rdpContext* context = (rdpContext*) encoder->client;
rdpSettings* settings = context->settings;
if (settings->DrawAllowSkipAlpha)
planarFlags |= PLANAR_FORMAT_HEADER_NA;
planarFlags = PLANAR_FORMAT_HEADER_NA;
planarFlags |= PLANAR_FORMAT_HEADER_RLE; planarFlags |= PLANAR_FORMAT_HEADER_RLE;
if (!encoder->planar) if (!encoder->planar)
@ -346,15 +350,17 @@ int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs)
return 1; return 1;
} }
rdpShadowEncoder* shadow_encoder_new(rdpShadowServer* server) rdpShadowEncoder* shadow_encoder_new(rdpShadowClient* client)
{ {
rdpShadowEncoder* encoder; rdpShadowEncoder* encoder;
rdpShadowServer* server = client->server;
encoder = (rdpShadowEncoder*) calloc(1, sizeof(rdpShadowEncoder)); encoder = (rdpShadowEncoder*) calloc(1, sizeof(rdpShadowEncoder));
if (!encoder) if (!encoder)
return NULL; return NULL;
encoder->client = client;
encoder->server = server; encoder->server = server;
encoder->fps = 16; encoder->fps = 16;

View File

@ -35,6 +35,7 @@
struct rdp_shadow_encoder struct rdp_shadow_encoder
{ {
rdpShadowClient* client;
rdpShadowServer* server; rdpShadowServer* server;
int width; int width;
@ -70,7 +71,7 @@ int shadow_encoder_reset(rdpShadowEncoder* encoder);
int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs); int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs);
int shadow_encoder_create_frame_id(rdpShadowEncoder* encoder); int shadow_encoder_create_frame_id(rdpShadowEncoder* encoder);
rdpShadowEncoder* shadow_encoder_new(rdpShadowServer* server); rdpShadowEncoder* shadow_encoder_new(rdpShadowClient* client);
void shadow_encoder_free(rdpShadowEncoder* encoder); void shadow_encoder_free(rdpShadowEncoder* encoder);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -45,7 +45,7 @@ rdpShadowScreen* shadow_screen_new(rdpShadowServer* server)
region16_init(&(screen->invalidRegion)); region16_init(&(screen->invalidRegion));
primary = &(subsystem->monitors[0]); primary = &(subsystem->monitors[subsystem->selectedMonitor]);
x = primary->left; x = primary->left;
y = primary->top; y = primary->top;

View File

@ -27,15 +27,11 @@
#include <winpr/cmdline.h> #include <winpr/cmdline.h>
#include <winpr/winsock.h> #include <winpr/winsock.h>
#include <freerdp/version.h>
#include <freerdp/log.h> #include <freerdp/log.h>
#include <freerdp/version.h>
#include <winpr/tools/makecert.h> #include <winpr/tools/makecert.h>
#ifdef _WIN32
#include <openssl/applink.c>
#endif
#ifndef _WIN32 #ifndef _WIN32
#include <sys/select.h> #include <sys/select.h>
#include <sys/signal.h> #include <sys/signal.h>
@ -45,29 +41,12 @@
#define TAG SERVER_TAG("shadow") #define TAG SERVER_TAG("shadow")
#ifdef _WIN32
static BOOL g_MessagePump = TRUE;
#else
static BOOL g_MessagePump = FALSE;
#endif
#ifdef WITH_SHADOW_X11
extern rdpShadowSubsystem* X11_ShadowCreateSubsystem(rdpShadowServer* server);
#endif
#ifdef WITH_SHADOW_MAC
extern rdpShadowSubsystem* Mac_ShadowCreateSubsystem(rdpShadowServer* server);
#endif
#ifdef WITH_SHADOW_WIN
extern rdpShadowSubsystem* Win_ShadowCreateSubsystem(rdpShadowServer* server);
#endif
static COMMAND_LINE_ARGUMENT_A shadow_args[] = static COMMAND_LINE_ARGUMENT_A shadow_args[] =
{ {
{ "port", COMMAND_LINE_VALUE_REQUIRED, "<number>", NULL, NULL, -1, NULL, "Server port" }, { "port", COMMAND_LINE_VALUE_REQUIRED, "<number>", NULL, NULL, -1, NULL, "Server port" },
{ "ipc-socket", COMMAND_LINE_VALUE_REQUIRED, "<ipc-socket>", NULL, NULL, -1, NULL, "Server IPC socket" }, { "ipc-socket", COMMAND_LINE_VALUE_REQUIRED, "<ipc-socket>", NULL, NULL, -1, NULL, "Server IPC socket" },
{ "monitors", COMMAND_LINE_VALUE_OPTIONAL, "<0,1,2...>", NULL, NULL, -1, NULL, "Select or list monitors" }, { "monitors", COMMAND_LINE_VALUE_OPTIONAL, "<0,1,2...>", NULL, NULL, -1, NULL, "Select or list monitors" },
{ "rect", COMMAND_LINE_VALUE_REQUIRED, "<x,y,w,h>", NULL, NULL, -1, NULL, "Select rectangle within monitor to share" },
{ "may-view", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Clients may view without prompt" }, { "may-view", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Clients may view without prompt" },
{ "may-interact", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Clients may interact without prompt" }, { "may-interact", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Clients may interact without prompt" },
{ "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, NULL, NULL, NULL, -1, NULL, "Print version" }, { "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, NULL, NULL, NULL, -1, NULL, "Print version" },
@ -203,6 +182,56 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
{ {
server->mayInteract = arg->Value ? TRUE : FALSE; server->mayInteract = arg->Value ? TRUE : FALSE;
} }
CommandLineSwitchCase(arg, "rect")
{
char* p;
char* tok[4];
int x, y, w, h;
char* str = _strdup(arg->Value);
if (!str)
return -1;
tok[0] = p = str;
p = strchr(p + 1, ',');
if (!p)
return -1;
*p++ = '\0';
tok[1] = p;
p = strchr(p + 1, ',');
if (!p)
return -1;
*p++ = '\0';
tok[2] = p;
p = strchr(p + 1, ',');
if (!p)
return -1;
*p++ = '\0';
tok[3] = p;
x = atoi(tok[0]);
y = atoi(tok[1]);
w = atoi(tok[2]);
h = atoi(tok[3]);
if ((x < 0) || (y < 0) || (w < 1) || (h < 1))
return -1;
server->subRect.left = x;
server->subRect.top = y;
server->subRect.right = x + w;
server->subRect.bottom = y + h;
server->shareSubRect = TRUE;
}
CommandLineSwitchDefault(arg) CommandLineSwitchDefault(arg)
{ {
@ -216,22 +245,36 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
if (arg && (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)) if (arg && (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT))
{ {
int index;
int numMonitors;
MONITOR_DEF monitors[16];
numMonitors = shadow_enum_monitors(monitors, 16, 0);
if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
{ {
/* Select monitors */ /* Select monitors */
index = atoi(arg->Value);
if (index < 0)
index = 0;
if (index >= numMonitors)
index = 0;
server->selectedMonitor = index;
} }
else else
{ {
int index;
int width, height; int width, height;
MONITOR_DEF* monitor; MONITOR_DEF* monitor;
rdpShadowSubsystem* subsystem = server->subsystem;
/* List monitors */ /* List monitors */
for (index = 0; index < subsystem->monitorCount; index++) for (index = 0; index < numMonitors; index++)
{ {
monitor = &(subsystem->monitors[index]); monitor = &monitors[index];
width = monitor->right - monitor->left; width = monitor->right - monitor->left;
height = monitor->bottom - monitor->top; height = monitor->bottom - monitor->top;
@ -248,32 +291,6 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
return status; return status;
} }
int shadow_server_surface_update(rdpShadowSubsystem* subsystem, REGION16* region)
{
int index;
int count;
wArrayList* clients;
rdpShadowServer* server;
rdpShadowClient* client;
server = subsystem->server;
clients = server->clients;
ArrayList_Lock(clients);
count = ArrayList_Count(clients);
for (index = 0; index < count; index++)
{
client = ArrayList_GetItem(clients, index);
shadow_client_surface_update(client, region);
}
ArrayList_Unlock(clients);
return 1;
}
void* shadow_server_thread(rdpShadowServer* server) void* shadow_server_thread(rdpShadowServer* server)
{ {
DWORD status; DWORD status;
@ -287,10 +304,7 @@ void* shadow_server_thread(rdpShadowServer* server)
StopEvent = server->StopEvent; StopEvent = server->StopEvent;
subsystem = server->subsystem; subsystem = server->subsystem;
if (subsystem->Start) shadow_subsystem_start(server->subsystem);
{
subsystem->Start(subsystem);
}
while (1) while (1)
{ {
@ -324,10 +338,7 @@ void* shadow_server_thread(rdpShadowServer* server)
listener->Close(listener); listener->Close(listener);
if (subsystem->Stop) shadow_subsystem_stop(server->subsystem);
{
subsystem->Stop(subsystem);
}
ExitThread(0); ExitThread(0);
@ -346,6 +357,16 @@ int shadow_server_start(rdpShadowServer* server)
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
#endif #endif
server->screen = shadow_screen_new(server);
if (!server->screen)
return -1;
server->capture = shadow_capture_new(server);
if (!server->capture)
return -1;
if (!server->ipcSocket) if (!server->ipcSocket)
status = server->listener->Open(server->listener, NULL, (UINT16) server->port); status = server->listener->Open(server->listener, NULL, (UINT16) server->port);
else else
@ -372,9 +393,82 @@ int shadow_server_stop(rdpShadowServer* server)
server->listener->Close(server->listener); server->listener->Close(server->listener);
} }
if (server->screen)
{
shadow_screen_free(server->screen);
server->screen = NULL;
}
if (server->capture)
{
shadow_capture_free(server->capture);
server->capture = NULL;
}
return 0; return 0;
} }
int shadow_server_init_config_path(rdpShadowServer* server)
{
#ifdef _WIN32
if (!server->ConfigPath)
{
server->ConfigPath = GetEnvironmentSubPath("LOCALAPPDATA", "freerdp");
}
#endif
#ifdef __APPLE__
if (!server->ConfigPath)
{
char* userLibraryPath;
char* userApplicationSupportPath;
userLibraryPath = GetKnownSubPath(KNOWN_PATH_HOME, "Library");
if (userLibraryPath)
{
if (!PathFileExistsA(userLibraryPath))
CreateDirectoryA(userLibraryPath, 0);
userApplicationSupportPath = GetCombinedPath(userLibraryPath, "Application Support");
if (userApplicationSupportPath)
{
if (!PathFileExistsA(userApplicationSupportPath))
CreateDirectoryA(userApplicationSupportPath, 0);
server->ConfigPath = GetCombinedPath(userApplicationSupportPath, "freerdp");
}
free(userLibraryPath);
free(userApplicationSupportPath);
}
}
#endif
if (!server->ConfigPath)
{
char* configHome;
configHome = GetKnownPath(KNOWN_PATH_XDG_CONFIG_HOME);
if (configHome)
{
if (!PathFileExistsA(configHome))
CreateDirectoryA(configHome, 0);
server->ConfigPath = GetKnownSubPath(KNOWN_PATH_XDG_CONFIG_HOME, "freerdp");
free(configHome);
}
}
if (!server->ConfigPath)
return -1; /* no usable config path */
return 1;
}
int shadow_server_init_certificate(rdpShadowServer* server) int shadow_server_init_certificate(rdpShadowServer* server)
{ {
char* filepath; char* filepath;
@ -436,8 +530,17 @@ int shadow_server_init(rdpShadowServer* server)
WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi()); WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi());
server->clients = ArrayList_New(TRUE);
server->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); server->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
InitializeCriticalSectionAndSpinCount(&(server->lock), 4000);
status = shadow_server_init_config_path(server);
if (status < 0)
return -1;
status = shadow_server_init_certificate(server); status = shadow_server_init_certificate(server);
if (status < 0) if (status < 0)
@ -451,45 +554,14 @@ int shadow_server_init(rdpShadowServer* server)
server->listener->info = (void*) server; server->listener->info = (void*) server;
server->listener->PeerAccepted = shadow_client_accepted; server->listener->PeerAccepted = shadow_client_accepted;
#ifdef WITH_SHADOW_X11 server->subsystem = shadow_subsystem_new(NULL);
server->CreateSubsystem = X11_ShadowCreateSubsystem;
#endif
#ifdef WITH_SHADOW_MAC
server->CreateSubsystem = Mac_ShadowCreateSubsystem;
#endif
#ifdef WITH_SHADOW_WIN
server->CreateSubsystem = Win_ShadowCreateSubsystem;
#endif
if (server->CreateSubsystem)
server->subsystem = server->CreateSubsystem(server);
if (!server->subsystem) if (!server->subsystem)
return -1; return -1;
server->subsystem->SurfaceUpdate = shadow_server_surface_update; status = shadow_subsystem_init(server->subsystem, server);
if (server->subsystem->Init) return status;
{
status = server->subsystem->Init(server->subsystem);
if (status < 0)
WLog_ERR(TAG, "subsystem init failure: %d", status);
}
server->screen = shadow_screen_new(server);
if (!server->screen)
return -1;
server->capture = shadow_capture_new(server);
if (!server->capture)
return -1;
return 1;
} }
int shadow_server_uninit(rdpShadowServer* server) int shadow_server_uninit(rdpShadowServer* server)
@ -502,12 +574,6 @@ int shadow_server_uninit(rdpShadowServer* server)
server->listener = NULL; server->listener = NULL;
} }
if (server->subsystem)
{
server->subsystem->Free(server->subsystem);
server->subsystem = NULL;
}
if (server->CertificateFile) if (server->CertificateFile)
{ {
free(server->CertificateFile); free(server->CertificateFile);
@ -526,6 +592,8 @@ int shadow_server_uninit(rdpShadowServer* server)
server->ipcSocket = NULL; server->ipcSocket = NULL;
} }
shadow_subsystem_uninit(server->subsystem);
return 1; return 1;
} }
@ -542,17 +610,6 @@ rdpShadowServer* shadow_server_new()
server->mayView = TRUE; server->mayView = TRUE;
server->mayInteract = TRUE; server->mayInteract = TRUE;
#ifdef _WIN32
server->ConfigPath = GetEnvironmentSubPath("LOCALAPPDATA", "freerdp");
#endif
if (!server->ConfigPath)
server->ConfigPath = GetKnownSubPath(KNOWN_PATH_XDG_CONFIG_HOME, "freerdp");
InitializeCriticalSectionAndSpinCount(&(server->lock), 4000);
server->clients = ArrayList_New(TRUE);
return server; return server;
} }
@ -569,50 +626,8 @@ void shadow_server_free(rdpShadowServer* server)
server->clients = NULL; server->clients = NULL;
} }
shadow_server_uninit(server); shadow_subsystem_free(server->subsystem);
free(server); free(server);
} }
int main(int argc, char** argv)
{
MSG msg;
int status;
DWORD dwExitCode;
rdpShadowServer* server;
server = shadow_server_new();
if (!server)
return 0;
if (shadow_server_init(server) < 0)
return 0;
status = shadow_server_parse_command_line(server, argc, argv);
status = shadow_server_command_line_status_print(server, argc, argv, status);
if (status < 0)
return 0;
if (shadow_server_start(server) < 0)
return 0;
if (g_MessagePump)
{
while (GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
WaitForSingleObject(server->thread, INFINITE);
GetExitCodeThread(server->thread, &dwExitCode);
shadow_server_free(server);
return 0;
}

View File

@ -0,0 +1,210 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "shadow.h"
#include "shadow_subsystem.h"
struct _RDP_SHADOW_SUBSYSTEM
{
const char* name;
pfnShadowSubsystemEntry entry;
};
typedef struct _RDP_SHADOW_SUBSYSTEM RDP_SHADOW_SUBSYSTEM;
#ifdef WITH_SHADOW_X11
extern int X11_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints);
#endif
#ifdef WITH_SHADOW_MAC
extern int Mac_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints);
#endif
#ifdef WITH_SHADOW_WIN
extern int Win_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints);
#endif
static RDP_SHADOW_SUBSYSTEM g_Subsystems[] =
{
#ifdef WITH_SHADOW_X11
{ "X11", X11_ShadowSubsystemEntry },
#endif
#ifdef WITH_SHADOW_MAC
{ "Mac", Mac_ShadowSubsystemEntry },
#endif
#ifdef WITH_SHADOW_WIN
{ "Win", Win_ShadowSubsystemEntry },
#endif
{ "", NULL }
};
static int g_SubsystemCount = (sizeof(g_Subsystems) / sizeof(g_Subsystems[0]));
pfnShadowSubsystemEntry shadow_subsystem_load_static_entry(const char* name)
{
int index;
if (!name)
{
for (index = 0; index < g_SubsystemCount; index++)
{
if (g_Subsystems[index].name)
return g_Subsystems[index].entry;
}
}
for (index = 0; index < g_SubsystemCount; index++)
{
if (strcmp(name, g_Subsystems[index].name) == 0)
return g_Subsystems[index].entry;
}
return NULL;
}
int shadow_subsystem_load_entry_points(RDP_SHADOW_ENTRY_POINTS* pEntryPoints, const char* name)
{
pfnShadowSubsystemEntry entry;
entry = shadow_subsystem_load_static_entry(name);
if (!entry)
return -1;
ZeroMemory(pEntryPoints, sizeof(RDP_SHADOW_ENTRY_POINTS));
if (entry(pEntryPoints) < 0)
return -1;
return 1;
}
rdpShadowSubsystem* shadow_subsystem_new(const char* name)
{
RDP_SHADOW_ENTRY_POINTS ep;
rdpShadowSubsystem* subsystem = NULL;
shadow_subsystem_load_entry_points(&ep, name);
if (!ep.New)
return NULL;
subsystem = ep.New();
if (!subsystem)
return NULL;
CopyMemory(&(subsystem->ep), &ep, sizeof(RDP_SHADOW_ENTRY_POINTS));
return subsystem;
}
void shadow_subsystem_free(rdpShadowSubsystem* subsystem)
{
if (subsystem->ep.Free)
subsystem->ep.Free(subsystem);
}
int shadow_subsystem_init(rdpShadowSubsystem* subsystem, rdpShadowServer* server)
{
int status;
subsystem->server = server;
subsystem->selectedMonitor = server->selectedMonitor;
subsystem->MsgPipe = MessagePipe_New();
subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
region16_init(&(subsystem->invalidRegion));
if (!subsystem->ep.Init)
return -1;
if (subsystem->ep.Init)
status = subsystem->ep.Init(subsystem);
return status;
}
void shadow_subsystem_uninit(rdpShadowSubsystem* subsystem)
{
if (subsystem->ep.Uninit)
subsystem->ep.Uninit(subsystem);
if (subsystem->MsgPipe)
{
MessagePipe_Free(subsystem->MsgPipe);
subsystem->MsgPipe = NULL;
}
if (subsystem->updateEvent)
{
CloseHandle(subsystem->updateEvent);
subsystem->updateEvent = NULL;
}
if (subsystem->invalidRegion.data)
region16_uninit(&(subsystem->invalidRegion));
}
int shadow_subsystem_start(rdpShadowSubsystem* subsystem)
{
int status;
if (!subsystem->ep.Start)
return -1;
status = subsystem->ep.Start(subsystem);
return status;
}
int shadow_subsystem_stop(rdpShadowSubsystem* subsystem)
{
int status;
if (!subsystem->ep.Stop)
return -1;
status = subsystem->ep.Stop(subsystem);
return status;
}
int shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors, const char* name)
{
int numMonitors = 0;
RDP_SHADOW_ENTRY_POINTS ep;
if (shadow_subsystem_load_entry_points(&ep, name) < 0)
return -1;
numMonitors = ep.EnumMonitors(monitors, maxMonitors);
return numMonitors;
}

View File

@ -0,0 +1,62 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_SHADOW_SERVER_SUBSYSTEM_H
#define FREERDP_SHADOW_SERVER_SUBSYSTEM_H
#include <freerdp/server/shadow.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
#define SHADOW_MSG_IN_REFRESH_OUTPUT_ID 1001
#define SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID 1002
struct _SHADOW_MSG_IN_REFRESH_OUTPUT
{
UINT32 numRects;
RECTANGLE_16* rects;
};
typedef struct _SHADOW_MSG_IN_REFRESH_OUTPUT SHADOW_MSG_IN_REFRESH_OUTPUT;
struct _SHADOW_MSG_IN_SUPPRESS_OUTPUT
{
BOOL allow;
RECTANGLE_16 rect;
};
typedef struct _SHADOW_MSG_IN_SUPPRESS_OUTPUT SHADOW_MSG_IN_SUPPRESS_OUTPUT;
#ifdef __cplusplus
extern "C" {
#endif
rdpShadowSubsystem* shadow_subsystem_new(const char* name);
void shadow_subsystem_free(rdpShadowSubsystem* subsystem);
int shadow_subsystem_init(rdpShadowSubsystem* subsystem, rdpShadowServer* server);
void shadow_subsystem_uninit(rdpShadowSubsystem* subsystem);
int shadow_subsystem_start(rdpShadowSubsystem* subsystem);
int shadow_subsystem_stop(rdpShadowSubsystem* subsystem);
#ifdef __cplusplus
}
#endif
#endif /* FREERDP_SHADOW_SERVER_SUBSYSTEM_H */

View File

@ -111,6 +111,7 @@ void MessageQueue_Post(wMessageQueue* queue, void* context, UINT32 type, void* w
message.id = type; message.id = type;
message.wParam = wParam; message.wParam = wParam;
message.lParam = lParam; message.lParam = lParam;
message.Free = NULL;
MessageQueue_Dispatch(queue, &message); MessageQueue_Dispatch(queue, &message);
} }