Merge branch 'shadow' of github.com:awakecoding/FreeRDP
Conflicts: libfreerdp/core/capabilities.c
This commit is contained in:
commit
72e7507bee
@ -466,6 +466,9 @@ FREERDP_API int freerdp_image_move(BYTE* pData, DWORD Format, int nStep, int nXD
|
||||
int nWidth, int nHeight, int nXSrc, int nYSrc);
|
||||
FREERDP_API int freerdp_image_fill(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst,
|
||||
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
|
||||
}
|
||||
|
@ -43,6 +43,13 @@ struct _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
|
||||
* @param r1 first 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 */
|
||||
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
|
||||
* @param region
|
||||
* @return if the region is empty
|
||||
|
@ -47,16 +47,19 @@ typedef struct rdp_shadow_encoder rdpShadowEncoder;
|
||||
typedef struct rdp_shadow_capture rdpShadowCapture;
|
||||
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 (*pfnShadowSubsystemUninit)(rdpShadowSubsystem* subsystem);
|
||||
|
||||
typedef int (*pfnShadowSubsystemStart)(rdpShadowSubsystem* subsystem);
|
||||
typedef int (*pfnShadowSubsystemStop)(rdpShadowSubsystem* subsystem);
|
||||
typedef void (*pfnShadowSubsystemFree)(rdpShadowSubsystem* subsystem);
|
||||
|
||||
typedef int (*pfnShadowSurfaceCopy)(rdpShadowSubsystem* subsystem);
|
||||
typedef int (*pfnShadowSurfaceUpdate)(rdpShadowSubsystem* subsystem, REGION16* region);
|
||||
typedef int (*pfnShadowEnumMonitors)(MONITOR_DEF* monitors, int maxMonitors);
|
||||
|
||||
typedef int (*pfnShadowSynchronizeEvent)(rdpShadowSubsystem* subsystem, UINT32 flags);
|
||||
typedef int (*pfnShadowKeyboardEvent)(rdpShadowSubsystem* subsystem, UINT16 flags, UINT16 code);
|
||||
@ -79,6 +82,7 @@ struct rdp_shadow_client
|
||||
rdpShadowServer* server;
|
||||
rdpShadowSurface* lobby;
|
||||
rdpShadowEncoder* encoder;
|
||||
rdpShadowSubsystem* subsystem;
|
||||
|
||||
HANDLE vcm;
|
||||
EncomspServerContext* encomsp;
|
||||
@ -99,33 +103,45 @@ struct rdp_shadow_server
|
||||
DWORD port;
|
||||
BOOL mayView;
|
||||
BOOL mayInteract;
|
||||
BOOL shareSubRect;
|
||||
int selectedMonitor;
|
||||
RECTANGLE_16 subRect;
|
||||
char* ipcSocket;
|
||||
char* ConfigPath;
|
||||
char* CertificateFile;
|
||||
char* PrivateKeyFile;
|
||||
CRITICAL_SECTION lock;
|
||||
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() \
|
||||
RDP_SHADOW_ENTRY_POINTS ep; \
|
||||
HANDLE event; \
|
||||
int monitorCount; \
|
||||
int numMonitors; \
|
||||
int captureFrameRate; \
|
||||
int selectedMonitor; \
|
||||
MONITOR_DEF monitors[16]; \
|
||||
MONITOR_DEF virtualScreen; \
|
||||
HANDLE updateEvent; \
|
||||
BOOL suppressOutput; \
|
||||
REGION16 invalidRegion; \
|
||||
wMessagePipe* MsgPipe; \
|
||||
SYNCHRONIZATION_BARRIER barrier; \
|
||||
\
|
||||
pfnShadowSubsystemInit Init; \
|
||||
pfnShadowSubsystemUninit Uninit; \
|
||||
pfnShadowSubsystemStart Start; \
|
||||
pfnShadowSubsystemStop Stop; \
|
||||
pfnShadowSubsystemFree Free; \
|
||||
\
|
||||
pfnShadowSurfaceCopy SurfaceCopy; \
|
||||
pfnShadowSurfaceUpdate SurfaceUpdate; \
|
||||
\
|
||||
pfnShadowSynchronizeEvent SynchronizeEvent; \
|
||||
pfnShadowKeyboardEvent KeyboardEvent; \
|
||||
pfnShadowUnicodeKeyboardEvent UnicodeKeyboardEvent; \
|
||||
@ -139,5 +155,27 @@ struct rdp_shadow_subsystem
|
||||
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 */
|
||||
|
||||
|
@ -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 (*pSurfaceCommand)(rdpContext* context, wStream* s);
|
||||
typedef void (*pSurfaceBits)(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command);
|
||||
typedef void (*pSurfaceFrameMarker)(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker);
|
||||
typedef void (*pSurfaceBits)(rdpContext* context, SURFACE_BITS_COMMAND* surfaceBitsCommand);
|
||||
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);
|
||||
|
||||
struct rdp_update
|
||||
@ -180,8 +181,9 @@ struct rdp_update
|
||||
pSurfaceCommand SurfaceCommand; /* 64 */
|
||||
pSurfaceBits SurfaceBits; /* 65 */
|
||||
pSurfaceFrameMarker SurfaceFrameMarker; /* 66 */
|
||||
pSurfaceFrameAcknowledge SurfaceFrameAcknowledge; /* 67 */
|
||||
UINT32 paddingE[80 - 68]; /* 68 */
|
||||
pSurfaceFrameBits SurfaceFrameBits; /* 67 */
|
||||
pSurfaceFrameAcknowledge SurfaceFrameAcknowledge; /* 68 */
|
||||
UINT32 paddingE[80 - 69]; /* 69 */
|
||||
|
||||
/* internal */
|
||||
|
||||
|
@ -3075,3 +3075,62 @@ int freerdp_image_fill(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst,
|
||||
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;
|
||||
}
|
||||
|
@ -130,6 +130,11 @@ static RECTANGLE_16 *region16_extents_noconst(REGION16 *region)
|
||||
return ®ion->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)
|
||||
{
|
||||
assert(region);
|
||||
@ -138,6 +143,12 @@ BOOL region16_is_empty(const REGION16 *region)
|
||||
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)
|
||||
{
|
||||
RECTANGLE_16 tmp;
|
||||
|
@ -344,7 +344,14 @@ BOOL rdp_read_bitmap_capability_set(wStream* s, UINT16 length, rdpSettings* sett
|
||||
settings->DesktopHeight = desktopHeight;
|
||||
}
|
||||
|
||||
settings->DrawAllowSkipAlpha = (drawingFlags & DRAW_ALLOW_SKIP_ALPHA) ? TRUE : FALSE;
|
||||
if (settings->DrawAllowSkipAlpha)
|
||||
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;
|
||||
}
|
||||
@ -370,10 +377,10 @@ void rdp_write_bitmap_capability_set(wStream* s, rdpSettings* settings)
|
||||
if (settings->DrawAllowSkipAlpha)
|
||||
drawingFlags |= DRAW_ALLOW_SKIP_ALPHA;
|
||||
|
||||
if (settings->DrawAllowColorSubsampling)
|
||||
if (settings->DrawAllowDynamicColorFidelity)
|
||||
drawingFlags |= DRAW_ALLOW_DYNAMIC_COLOR_FIDELITY;
|
||||
|
||||
if (settings->DrawAllowDynamicColorFidelity)
|
||||
if (settings->DrawAllowColorSubsampling)
|
||||
drawingFlags |= DRAW_ALLOW_COLOR_SUBSAMPLING; /* currently unimplemented */
|
||||
|
||||
/* While bitmap_decode.c now implements YCoCg, in turning it
|
||||
|
@ -388,7 +388,7 @@ BOOL gcc_read_client_data_blocks(wStream* s, rdpMcs* mcs, int length)
|
||||
if (endPos != (begPos + blockLength))
|
||||
{
|
||||
WLog_ERR(TAG, "Error parsing GCC client data block 0x%04X: Actual Offset: %d Expected Offset: %d",
|
||||
type, endPos, begPos + blockLength);
|
||||
type, endPos, begPos + blockLength);
|
||||
}
|
||||
|
||||
length -= blockLength;
|
||||
@ -1337,6 +1337,15 @@ BOOL gcc_read_client_cluster_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
|
||||
if (flags & REDIRECTED_SESSIONID_FIELD_VALID)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
rdpListener* listener = (rdpListener*) instance->listener;
|
||||
int status;
|
||||
int sockfd;
|
||||
char servname[10];
|
||||
struct addrinfo hints = { 0 };
|
||||
struct addrinfo* res;
|
||||
struct addrinfo* ai;
|
||||
int option_value;
|
||||
char addr[64];
|
||||
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
|
||||
u_long arg;
|
||||
#endif
|
||||
@ -96,7 +96,7 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if (bind_address == NULL)
|
||||
if (!bind_address)
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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->num_sockfds++;
|
||||
|
||||
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);
|
||||
|
||||
WLog_ERR(TAG, "Listening on %s port %s.\n", inet_ntop(ai->ai_family, sin_addr, buf, sizeof(buf)), servname);
|
||||
WLog_INFO(TAG, "Listening on %s:%s", addr, servname);
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
|
@ -867,7 +867,7 @@ static void update_send_surface_command(rdpContext* context, wStream* s)
|
||||
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;
|
||||
rdpRdp* rdp = context->rdp;
|
||||
@ -875,9 +875,9 @@ static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND*
|
||||
update_force_flush(context);
|
||||
|
||||
s = fastpath_update_pdu_init(rdp->fastpath);
|
||||
Stream_EnsureRemainingCapacity(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH + (int) surface_bits_command->bitmapDataLength);
|
||||
update_write_surfcmd_surface_bits_header(s, surface_bits_command);
|
||||
Stream_Write(s, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
|
||||
Stream_EnsureRemainingCapacity(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH + (int) surfaceBitsCommand->bitmapDataLength);
|
||||
update_write_surfcmd_surface_bits_header(s, surfaceBitsCommand);
|
||||
Stream_Write(s, surfaceBitsCommand->bitmapData, surfaceBitsCommand->bitmapDataLength);
|
||||
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s);
|
||||
|
||||
update_force_flush(context);
|
||||
@ -885,7 +885,7 @@ static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND*
|
||||
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;
|
||||
rdpRdp* rdp = context->rdp;
|
||||
@ -893,7 +893,34 @@ static void update_send_surface_frame_marker(rdpContext* context, SURFACE_FRAME_
|
||||
update_force_flush(context);
|
||||
|
||||
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);
|
||||
|
||||
update_force_flush(context);
|
||||
@ -1596,6 +1623,7 @@ void update_register_server_callbacks(rdpUpdate* update)
|
||||
update->SurfaceBits = update_send_surface_bits;
|
||||
update->SurfaceFrameMarker = update_send_surface_frame_marker;
|
||||
update->SurfaceCommand = update_send_surface_command;
|
||||
update->SurfaceFrameBits = update_send_surface_frame_bits;
|
||||
update->PlaySound = update_send_play_sound;
|
||||
update->primary->DstBlt = update_send_dstblt;
|
||||
update->primary->PatBlt = update_send_patblt;
|
||||
|
@ -27,7 +27,7 @@ if(FREERDP_VENDOR)
|
||||
|
||||
if(NOT WIN32)
|
||||
if(APPLE AND (NOT IOS))
|
||||
add_subdirectory(Mac)
|
||||
#add_subdirectory(Mac)
|
||||
endif()
|
||||
else()
|
||||
#add_subdirectory(Windows)
|
||||
|
@ -30,26 +30,23 @@
|
||||
|
||||
static const AUDIO_FORMAT supported_audio_formats[] =
|
||||
{
|
||||
|
||||
{ WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, NULL },
|
||||
{ WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, NULL }
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
WLog_INFO(TAG, "AUDIN receive %d frames.", nframes);
|
||||
|
||||
}
|
||||
|
||||
void mf_peer_audin_init(mfPeerContext* context)
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
//#include <util.h>
|
||||
|
||||
#include "mf_event.h"
|
||||
|
||||
@ -191,8 +190,8 @@ mfEventQueue* mf_event_queue_new()
|
||||
event_queue->events = (mfEvent**) malloc(sizeof(mfEvent*) * event_queue->size);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -27,126 +27,86 @@
|
||||
|
||||
#include "mf_info.h"
|
||||
#include "mf_mountain_lion.h"
|
||||
//#include "mf_update.h"
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#define TAG SERVER_TAG("mac")
|
||||
|
||||
static mfInfo* mfInfoInstance = NULL;
|
||||
//static int _IDcount = 0;
|
||||
|
||||
int mf_info_lock(mfInfo* mfi)
|
||||
{
|
||||
|
||||
int status = pthread_mutex_lock(&mfi->mutex);
|
||||
|
||||
switch (status) {
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case 0:
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "mf_info_lock failed with %#X", status);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mf_info_try_lock(mfInfo* mfi, UINT32 ms)
|
||||
{
|
||||
|
||||
int status = pthread_mutex_trylock(&mfi->mutex);
|
||||
|
||||
switch (status) {
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case 0:
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
|
||||
case EBUSY:
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "mf_info_try_lock failed with %#X", status);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mf_info_unlock(mfInfo* mfi)
|
||||
{
|
||||
int status = pthread_mutex_unlock(&mfi->mutex);
|
||||
|
||||
switch (status) {
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case 0:
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "mf_info_unlock failed with %#X", status);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
mfInfo* mf_info_init()
|
||||
{
|
||||
mfInfo* mfi;
|
||||
|
||||
|
||||
mfi = (mfInfo*) malloc(sizeof(mfInfo));
|
||||
memset(mfi, 0, sizeof(mfInfo));
|
||||
|
||||
|
||||
|
||||
if (mfi != NULL)
|
||||
{
|
||||
/* HKEY hKey;
|
||||
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);
|
||||
}
|
||||
|
||||
pthread_mutex_init(&mfi->mutex, NULL);
|
||||
|
||||
mfi->peers = (freerdp_peer**) malloc(sizeof(freerdp_peer*) * MF_INFO_MAXPEERS);
|
||||
memset(mfi->peers, 0, sizeof(freerdp_peer*) * MF_INFO_MAXPEERS);
|
||||
|
||||
//Set 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;
|
||||
|
||||
/*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;
|
||||
}
|
||||
|
||||
@ -154,7 +114,7 @@ mfInfo* mf_info_get_instance()
|
||||
{
|
||||
if (mfInfoInstance == NULL)
|
||||
mfInfoInstance = mf_info_init();
|
||||
|
||||
|
||||
return mfInfoInstance;
|
||||
}
|
||||
|
||||
@ -164,31 +124,25 @@ void mf_info_peer_register(mfInfo* mfi, mfPeerContext* context)
|
||||
{
|
||||
int i;
|
||||
int peerId;
|
||||
|
||||
if (mfi->peerCount == MF_INFO_MAXPEERS)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: socketClose on OS X");
|
||||
//context->socketClose = TRUE;
|
||||
mf_info_unlock(mfi);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
mf_mlion_display_info(&mfi->servscreen_width, &mfi->servscreen_height, &mfi->scale);
|
||||
mf_mlion_screen_updates_init();
|
||||
mf_mlion_start_getting_screen_updates();
|
||||
}
|
||||
|
||||
//look trhough the array of peers until an empty slot
|
||||
|
||||
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
|
||||
if (mfi->peers[i] == NULL)
|
||||
@ -197,15 +151,12 @@ void mf_info_peer_register(mfInfo* mfi, mfPeerContext* context)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mfi->peers[peerId] = ((rdpContext*) context)->peer;
|
||||
mfi->peers[peerId]->pId = peerId;
|
||||
mfi->peerCount++;
|
||||
//WLog_DBG(TAG, "Registering Peer: id=%d #=%d\n", peerId, mfi->peerCount);
|
||||
|
||||
|
||||
mf_info_unlock(mfi);
|
||||
|
||||
//mfreerdp_server_peer_callback_event(peerId, MF_SRV_CALLBACK_EVENT_CONNECT);
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,42 +165,29 @@ void mf_info_peer_unregister(mfInfo* mfi, mfPeerContext* context)
|
||||
if (mf_info_lock(mfi) > 0)
|
||||
{
|
||||
int peerId;
|
||||
|
||||
|
||||
peerId = ((rdpContext*) context)->peer->pId;
|
||||
mfi->peers[peerId] = NULL;
|
||||
mfi->peerCount--;
|
||||
|
||||
//WLog_DBG(TAG, "Unregistering Peer: id=%d, #=%d\n", peerId, mfi->peerCount);
|
||||
|
||||
//screen capture cleanup
|
||||
|
||||
if (mfi->peerCount == 0)
|
||||
{
|
||||
mf_mlion_stop_getting_screen_updates();
|
||||
}
|
||||
|
||||
mf_info_unlock(mfi);
|
||||
|
||||
//mfreerdp_server_peer_callback_event(peerId, MF_SRV_CALLBACK_EVENT_DISCONNECT);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL mf_info_have_updates(mfInfo* mfi)
|
||||
{
|
||||
if(mfi->framesWaiting == 0)
|
||||
if(mfi->framesWaiting == 0)
|
||||
return FALSE;
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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)
|
||||
@ -274,9 +212,9 @@ void mf_info_invalidate_full_screen(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 TRUE;
|
||||
}
|
||||
|
||||
@ -285,28 +223,9 @@ void mf_info_getScreenData(mfInfo* mfi, long* width, long* height, BYTE** pBits,
|
||||
*width = mfi->invalid.width / mfi->scale;
|
||||
*height = mfi->invalid.height / mfi->scale;
|
||||
*pitch = mfi->servscreen_width * mfi->scale * 4;
|
||||
|
||||
|
||||
mf_mlion_get_pixelData(mfi->invalid.x / mfi->scale, mfi->invalid.y / mfi->scale, *width, *height, pBits);
|
||||
|
||||
|
||||
*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;
|
||||
}
|
||||
*/
|
||||
|
@ -396,34 +396,6 @@ void mf_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
||||
CFRelease(scroll);
|
||||
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
|
||||
{
|
||||
|
||||
|
@ -25,9 +25,6 @@
|
||||
|
||||
#include "mf_mountain_lion.h"
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#define TAG SERVER_TAG("mac")
|
||||
|
||||
dispatch_semaphore_t region_sem;
|
||||
dispatch_semaphore_t data_sem;
|
||||
dispatch_queue_t screen_update_q;
|
||||
@ -85,24 +82,20 @@ void (^streamHandler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfaceRef, CGDisp
|
||||
|
||||
if (status != kCGDisplayStreamFrameStatusFrameComplete)
|
||||
{
|
||||
//unhandled
|
||||
switch(status)
|
||||
{
|
||||
case kCGDisplayStreamFrameStatusFrameIdle:
|
||||
WLog_DBG(TAG, "kCGDisplayStreamFrameStatusFrameIdle");
|
||||
break;
|
||||
|
||||
case kCGDisplayStreamFrameStatusStopped:
|
||||
//we dont need to clean up
|
||||
//WLog_DBG(TAG, "kCGDisplayStreamFrameStatusStopped");
|
||||
break;
|
||||
|
||||
case kCGDisplayStreamFrameStatusFrameBlank:
|
||||
WLog_DBG(TAG, "kCGDisplayStreamFrameStatusFrameBlank");
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_WARN(TAG, "Unhandled Frame Status!!!");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
else if (lastUpdate == NULL)
|
||||
@ -193,9 +186,9 @@ int mf_mlion_start_getting_screen_updates()
|
||||
CGError err;
|
||||
|
||||
err = CGDisplayStreamStart(stream);
|
||||
if(err != kCGErrorSuccess)
|
||||
|
||||
if (err != kCGErrorSuccess)
|
||||
{
|
||||
WLog_WARN(TAG, "Failed to start displaystream!! err = %d", err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -207,13 +200,15 @@ int mf_mlion_stop_getting_screen_updates()
|
||||
CGError err;
|
||||
|
||||
err = CGDisplayStreamStop(stream);
|
||||
if(err != kCGErrorSuccess)
|
||||
|
||||
if (err != kCGErrorSuccess)
|
||||
{
|
||||
WLog_WARN(TAG, "Failed to stop displaystream!! err = %d", err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
dispatch_semaphore_signal(region_sem);
|
||||
|
||||
return 0;
|
||||
@ -283,4 +277,3 @@ int mf_mlion_get_pixelData(long x, long y, long width, long height, BYTE** pxDat
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -42,9 +42,6 @@
|
||||
|
||||
#include "CoreVideo/CoreVideo.h"
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#define TAG SERVER_TAG("mac")
|
||||
|
||||
//refactor these
|
||||
int info_last_sec = 0;
|
||||
int info_last_nsec = 0;
|
||||
@ -65,10 +62,10 @@ BOOL mf_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount)
|
||||
{
|
||||
if (info_event_queue->pipe_fd[0] == -1)
|
||||
return TRUE;
|
||||
|
||||
rfds[*rcount] = (void *)(long) info_event_queue->pipe_fd[0];
|
||||
|
||||
rfds[*rcount] = (void *)(long) info_event_queue->pipe_fd[0];
|
||||
(*rcount)++;
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -76,28 +73,28 @@ BOOL mf_peer_check_fds(freerdp_peer* client)
|
||||
{
|
||||
mfPeerContext* context = (mfPeerContext*) client->context;
|
||||
mfEvent* event;
|
||||
|
||||
|
||||
if (context->activated == FALSE)
|
||||
return TRUE;
|
||||
|
||||
|
||||
event = mf_event_peek(info_event_queue);
|
||||
|
||||
|
||||
if (event != NULL)
|
||||
{
|
||||
if (event->type == MF_EVENT_TYPE_REGION)
|
||||
{
|
||||
WLog_ERR(TAG, "unhandled event");
|
||||
|
||||
}
|
||||
else if (event->type == MF_EVENT_TYPE_FRAME_TICK)
|
||||
{
|
||||
event = mf_event_pop(info_event_queue);
|
||||
|
||||
|
||||
mf_peer_rfx_update(client);
|
||||
|
||||
|
||||
mf_event_free(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -105,73 +102,73 @@ void mf_peer_rfx_update(freerdp_peer* client)
|
||||
{
|
||||
//check
|
||||
mfInfo* mfi = mf_info_get_instance();
|
||||
|
||||
|
||||
mf_info_find_invalid_region(mfi);
|
||||
|
||||
if (mf_info_have_invalid_region(mfi) == false) {
|
||||
|
||||
if (mf_info_have_invalid_region(mfi) == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
long width;
|
||||
long height;
|
||||
int pitch;
|
||||
BYTE* dataBits = NULL;
|
||||
|
||||
|
||||
mf_info_getScreenData(mfi, &width, &height, &dataBits, &pitch);
|
||||
|
||||
|
||||
mf_info_clear_invalid_region(mfi);
|
||||
|
||||
|
||||
//encode
|
||||
|
||||
|
||||
wStream* s;
|
||||
RFX_RECT rect;
|
||||
rdpUpdate* update;
|
||||
mfPeerContext* mfp;
|
||||
SURFACE_BITS_COMMAND* cmd;
|
||||
|
||||
|
||||
update = client->update;
|
||||
mfp = (mfPeerContext*) client->context;
|
||||
cmd = &update->surface_bits_command;
|
||||
|
||||
|
||||
|
||||
|
||||
s = mfp->s;
|
||||
Stream_Clear(s);
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
|
||||
UINT32 x = mfi->invalid.x / mfi->scale;
|
||||
UINT32 y = mfi->invalid.y / mfi->scale;
|
||||
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
|
||||
|
||||
mfp->rfx_context->width = mfi->servscreen_width;
|
||||
mfp->rfx_context->height = mfi->servscreen_height;
|
||||
|
||||
|
||||
rfx_compose_message(mfp->rfx_context, s, &rect, 1,
|
||||
(BYTE*) dataBits, rect.width, rect.height, pitch);
|
||||
|
||||
(BYTE*) dataBits, rect.width, rect.height, pitch);
|
||||
|
||||
cmd->destLeft = x;
|
||||
cmd->destTop = y;
|
||||
cmd->destRight = x + rect.width;
|
||||
cmd->destBottom = y + rect.height;
|
||||
|
||||
|
||||
|
||||
|
||||
cmd->bpp = 32;
|
||||
cmd->codecID = 3;
|
||||
cmd->width = rect.width;
|
||||
cmd->height = rect.height;
|
||||
cmd->bitmapDataLength = Stream_GetPosition(s);
|
||||
cmd->bitmapData = Stream_Buffer(s);
|
||||
|
||||
|
||||
//send
|
||||
|
||||
|
||||
update->SurfaceBits(update->context, cmd);
|
||||
|
||||
|
||||
//clean up... maybe?
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* Called when we have a new peer connecting */
|
||||
@ -183,16 +180,16 @@ int mf_peer_context_new(freerdp_peer* client, mfPeerContext* context)
|
||||
context->rfx_context->width = client->settings->DesktopWidth;
|
||||
context->rfx_context->height = client->settings->DesktopHeight;
|
||||
rfx_context_set_pixel_format(context->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
|
||||
|
||||
//context->nsc_context = nsc_context_new();
|
||||
//nsc_context_set_pixel_format(context->nsc_context, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
|
||||
|
||||
context->s = Stream_New(NULL, 0xFFFF);
|
||||
|
||||
|
||||
context->vcm = WTSOpenServerA((LPSTR) client->context);
|
||||
|
||||
|
||||
mf_info_peer_register(context->info, context);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -202,25 +199,25 @@ void mf_peer_context_free(freerdp_peer* client, mfPeerContext* context)
|
||||
if (context)
|
||||
{
|
||||
mf_info_peer_unregister(context->info, context);
|
||||
|
||||
|
||||
dispatch_suspend(info_timer);
|
||||
|
||||
|
||||
Stream_Free(context->s, TRUE);
|
||||
|
||||
|
||||
rfx_context_free(context->rfx_context);
|
||||
//nsc_context_free(context->nsc_context);
|
||||
|
||||
|
||||
#ifdef CHANNEL_AUDIN_SERVER
|
||||
if (context->audin)
|
||||
audin_server_context_free(context->audin);
|
||||
#endif
|
||||
|
||||
|
||||
//#ifdef CHANNEL_RDPSND_SERVER
|
||||
mf_peer_rdpsnd_stop();
|
||||
if (context->rdpsnd)
|
||||
rdpsnd_server_context_free(context->rdpsnd);
|
||||
//#endif
|
||||
|
||||
|
||||
WTSCloseServer(context->vcm);
|
||||
}
|
||||
}
|
||||
@ -232,21 +229,21 @@ void mf_peer_init(freerdp_peer* client)
|
||||
client->ContextNew = (psPeerContextNew) mf_peer_context_new;
|
||||
client->ContextFree = (psPeerContextFree) mf_peer_context_free;
|
||||
freerdp_peer_context_new(client);
|
||||
|
||||
|
||||
info_event_queue = mf_event_queue_new();
|
||||
|
||||
|
||||
info_queue = dispatch_queue_create("FreeRDP.update.timer", DISPATCH_QUEUE_SERIAL);
|
||||
info_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, info_queue);
|
||||
|
||||
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_event_handler(info_timer, ^{
|
||||
//WLog_ERR(TAG, "dispatch");
|
||||
//DEBUG_WARN( "dispatch\n");
|
||||
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);}
|
||||
);
|
||||
dispatch_resume(info_timer);
|
||||
}
|
||||
}
|
||||
@ -255,35 +252,25 @@ BOOL mf_peer_post_connect(freerdp_peer* client)
|
||||
{
|
||||
mfPeerContext* context = (mfPeerContext*) client->context;
|
||||
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();
|
||||
mfi->scale = 1;
|
||||
|
||||
|
||||
//mfi->servscreen_width = 2880 / mfi->scale;
|
||||
//mfi->servscreen_height = 1800 / mfi->scale;
|
||||
UINT32 bitsPerPixel = 32;
|
||||
|
||||
|
||||
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->DesktopHeight = mfi->servscreen_height;
|
||||
settings->ColorDepth = bitsPerPixel;
|
||||
|
||||
|
||||
client->update->DesktopResize(client->update->context);
|
||||
|
||||
|
||||
mfi->mouse_down_left = FALSE;
|
||||
mfi->mouse_down_right = FALSE;
|
||||
mfi->mouse_down_other = FALSE;
|
||||
@ -292,95 +279,58 @@ BOOL mf_peer_post_connect(freerdp_peer* client)
|
||||
{
|
||||
mf_peer_rdpsnd_init(context); /* Audio Output */
|
||||
}
|
||||
|
||||
|
||||
/* Dynamic Virtual Channels */
|
||||
|
||||
|
||||
#ifdef CHANNEL_AUDIN_SERVER
|
||||
mf_peer_audin_init(context); /* Audio Input */
|
||||
#endif
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL mf_peer_activate(freerdp_peer* client)
|
||||
{
|
||||
mfPeerContext* context = (mfPeerContext*) client->context;
|
||||
|
||||
|
||||
rfx_context_reset(context->rfx_context);
|
||||
context->activated = TRUE;
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
WLog_INFO(TAG, "Client sent a keyboard event (flags:0x%04X code:0x%04X)", flags, code);
|
||||
UINT16 down = 0x4000;
|
||||
//UINT16 up = 0x8000;
|
||||
|
||||
|
||||
bool state_down = FALSE;
|
||||
|
||||
|
||||
if (flags == down)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
pthread_t th;
|
||||
|
||||
|
||||
pthread_create(&th, 0, mf_peer_main_loop, client);
|
||||
pthread_detach(th);
|
||||
}
|
||||
@ -395,11 +345,11 @@ void* mf_peer_main_loop(void* arg)
|
||||
fd_set rfds_set;
|
||||
mfPeerContext* context;
|
||||
freerdp_peer* client = (freerdp_peer*) arg;
|
||||
|
||||
|
||||
memset(rfds, 0, sizeof(rfds));
|
||||
|
||||
|
||||
mf_peer_init(client);
|
||||
|
||||
|
||||
/* Initialize the real server settings here */
|
||||
client->settings->CertificateFile = _strdup("server.crt");
|
||||
client->settings->PrivateKeyFile = _strdup("server.key");
|
||||
@ -408,91 +358,86 @@ void* mf_peer_main_loop(void* arg)
|
||||
client->settings->ColorDepth = 32;
|
||||
client->settings->SuppressOutput = TRUE;
|
||||
client->settings->RefreshRect = FALSE;
|
||||
|
||||
|
||||
client->PostConnect = mf_peer_post_connect;
|
||||
client->Activate = mf_peer_activate;
|
||||
|
||||
|
||||
client->input->SynchronizeEvent = mf_peer_synchronize_event;
|
||||
client->input->KeyboardEvent = mf_input_keyboard_event;//mf_peer_keyboard_event;
|
||||
client->input->UnicodeKeyboardEvent = mf_peer_unicode_keyboard_event;
|
||||
client->input->MouseEvent = mf_input_mouse_event;
|
||||
client->input->ExtendedMouseEvent = mf_input_extended_mouse_event;
|
||||
|
||||
|
||||
//client->update->RefreshRect = mf_peer_refresh_rect;
|
||||
client->update->SuppressOutput = mf_peer_suppress_output;
|
||||
|
||||
|
||||
client->Initialize(client);
|
||||
context = (mfPeerContext*) client->context;
|
||||
WLog_INFO(TAG, "We've got a client %s", client->local ? "(local)" : client->hostname);
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
rcount = 0;
|
||||
|
||||
|
||||
if (client->GetFileDescriptor(client, rfds, &rcount) != TRUE)
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to get FreeRDP file descriptor");
|
||||
break;
|
||||
}
|
||||
|
||||
if (mf_peer_get_fds(client, rfds, &rcount) != TRUE)
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to get mfreerdp file descriptor");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
WTSVirtualChannelManagerGetFileDescriptor(context->vcm, rfds, &rcount);
|
||||
|
||||
|
||||
max_fds = 0;
|
||||
FD_ZERO(&rfds_set);
|
||||
|
||||
|
||||
for (i = 0; i < rcount; i++)
|
||||
{
|
||||
fds = (int)(long)(rfds[i]);
|
||||
|
||||
|
||||
if (fds > max_fds)
|
||||
max_fds = fds;
|
||||
|
||||
|
||||
FD_SET(fds, &rfds_set);
|
||||
}
|
||||
|
||||
|
||||
if (max_fds == 0)
|
||||
break;
|
||||
|
||||
|
||||
if (select(max_fds + 1, &rfds_set, NULL, NULL, NULL) == -1)
|
||||
{
|
||||
/* these are not really errors */
|
||||
if (!((errno == EAGAIN) ||
|
||||
(errno == EWOULDBLOCK) ||
|
||||
(errno == EINPROGRESS) ||
|
||||
(errno == EINTR))) /* signal occurred */
|
||||
(errno == EWOULDBLOCK) ||
|
||||
(errno == EINPROGRESS) ||
|
||||
(errno == EINTR))) /* signal occurred */
|
||||
{
|
||||
WLog_ERR(TAG, "select failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (client->CheckFileDescriptor(client) != TRUE)
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to check freerdp file descriptor");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if ((mf_peer_check_fds(client)) != TRUE)
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to check mfreerdp file descriptor");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (WTSVirtualChannelManagerCheckFileDescriptor(context->vcm) != TRUE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "Client %s disconnected.", client->local ? "(local)" : client->hostname);
|
||||
|
||||
client->Disconnect(client);
|
||||
freerdp_peer_context_free(client);
|
||||
freerdp_peer_free(client);
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -46,8 +46,12 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context)
|
||||
|
||||
//we should actually loop through the list of client formats here
|
||||
//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);
|
||||
|
||||
>>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a
|
||||
for (i = 0; i < context->num_client_formats; i++)
|
||||
{
|
||||
/* 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].nSamplesPerSec == context->server_formats[j].nSamplesPerSec))
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
WLog_DBG(TAG, "agreed on format!");
|
||||
>>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a
|
||||
formatAgreed = TRUE;
|
||||
agreedFormat = (AUDIO_FORMAT*)&context->server_formats[j];
|
||||
break;
|
||||
@ -70,7 +77,10 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context)
|
||||
|
||||
if (formatAgreed == FALSE)
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
WLog_DBG(TAG, "Could not agree on a audio format with the server");
|
||||
>>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a
|
||||
return;
|
||||
}
|
||||
|
||||
@ -113,10 +123,13 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context)
|
||||
|
||||
if (status != noErr)
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
|
||||
=======
|
||||
WLog_DBG(TAG, "Failed to create a new Audio Queue. Status code: %d", status);
|
||||
>>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a
|
||||
}
|
||||
|
||||
|
||||
UInt32 dataFormatSize = sizeof (recorderState.dataFormat);
|
||||
|
||||
AudioQueueGetProperty(recorderState.queue,
|
||||
@ -210,7 +223,11 @@ void mf_peer_rdpsnd_input_callback (void *inUserD
|
||||
|
||||
if (status != noErr)
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
|
||||
=======
|
||||
WLog_DBG(TAG, "AudioQueueEnqueueBuffer() returned status = %d", status);
|
||||
>>>>>>> f7d21655fa2552c8813be9d2d5bac4bbaa5abf6a
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -43,9 +43,6 @@
|
||||
#include "mfreerdp.h"
|
||||
#include "mf_peer.h"
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#define TAG SERVER_TAG("mac")
|
||||
|
||||
static void mf_server_main_loop(freerdp_listener* instance)
|
||||
{
|
||||
int i;
|
||||
@ -63,7 +60,6 @@ static void mf_server_main_loop(freerdp_listener* instance)
|
||||
|
||||
if (instance->GetFileDescriptor(instance, rfds, &rcount) != TRUE)
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to get FreeRDP file descriptor");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -91,14 +87,12 @@ static void mf_server_main_loop(freerdp_listener* instance)
|
||||
(errno == EINPROGRESS) ||
|
||||
(errno == EINTR))) /* signal occurred */
|
||||
{
|
||||
WLog_ERR(TAG, "select failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (instance->CheckFileDescriptor(instance) != TRUE)
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -127,4 +121,3 @@ int main(int argc, char* argv[])
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,15 @@
|
||||
set(MODULE_NAME "freerdp-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_PURPOSE "X11 extension")
|
||||
set(XEXT_FEATURE_DESCRIPTION "X11 core extensions")
|
||||
@ -115,6 +123,13 @@ if(WITH_X11)
|
||||
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})
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
@ -136,6 +151,8 @@ set(${MODULE_PREFIX}_SRCS
|
||||
shadow_encomsp.h
|
||||
shadow_remdesk.c
|
||||
shadow_remdesk.h
|
||||
shadow_subsystem.c
|
||||
shadow_subsystem.h
|
||||
shadow_server.c
|
||||
shadow.h)
|
||||
|
||||
@ -157,14 +174,6 @@ set(${MODULE_PREFIX}_MAC_SRCS
|
||||
Mac/mac_shadow.c
|
||||
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)
|
||||
add_definitions(-DWITH_SHADOW_WIN)
|
||||
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})
|
||||
endif()
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "freerdp-shadow")
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
list(APPEND ${MODULE_PREFIX}_LIBS freerdp)
|
||||
list(APPEND ${MODULE_PREFIX}_LIBS freerdp-server)
|
||||
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})
|
||||
|
||||
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")
|
||||
|
||||
# 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")
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/input.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
@ -25,9 +26,13 @@
|
||||
|
||||
#include "../shadow_screen.h"
|
||||
#include "../shadow_surface.h"
|
||||
#include "../shadow_capture.h"
|
||||
#include "../shadow_subsystem.h"
|
||||
|
||||
#include "mac_shadow.h"
|
||||
|
||||
static macShadowSubsystem* g_Subsystem = NULL;
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
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)
|
||||
@ -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)
|
||||
{
|
||||
|
||||
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)
|
||||
@ -53,39 +193,389 @@ 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;
|
||||
}
|
||||
|
||||
void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem)
|
||||
{
|
||||
int fps;
|
||||
DWORD status;
|
||||
DWORD nCount;
|
||||
UINT64 cTime;
|
||||
DWORD dwTimeout;
|
||||
DWORD dwInterval;
|
||||
UINT64 frameTime;
|
||||
HANDLE events[32];
|
||||
HANDLE StopEvent;
|
||||
|
||||
|
||||
StopEvent = subsystem->server->StopEvent;
|
||||
|
||||
|
||||
nCount = 0;
|
||||
events[nCount++] = StopEvent;
|
||||
|
||||
|
||||
fps = 16;
|
||||
dwInterval = 1000 / fps;
|
||||
frameTime = GetTickCount64() + dwInterval;
|
||||
|
||||
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)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime))
|
||||
{
|
||||
mac_shadow_screen_grab(subsystem);
|
||||
|
||||
dwInterval = 1000 / fps;
|
||||
frameTime += dwInterval;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ExitThread(0);
|
||||
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)
|
||||
{
|
||||
g_Subsystem = subsystem;
|
||||
|
||||
mac_shadow_detect_monitors(subsystem);
|
||||
|
||||
mac_shadow_capture_init(subsystem);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -104,6 +594,8 @@ int mac_shadow_subsystem_start(macShadowSubsystem* subsystem)
|
||||
if (!subsystem)
|
||||
return -1;
|
||||
|
||||
mac_shadow_capture_start(subsystem);
|
||||
|
||||
thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) mac_shadow_subsystem_thread,
|
||||
(void*) subsystem, 0, NULL);
|
||||
@ -129,7 +621,7 @@ void mac_shadow_subsystem_free(macShadowSubsystem* subsystem)
|
||||
free(subsystem);
|
||||
}
|
||||
|
||||
macShadowSubsystem* mac_shadow_subsystem_new(rdpShadowServer* server)
|
||||
macShadowSubsystem* mac_shadow_subsystem_new()
|
||||
{
|
||||
macShadowSubsystem* subsystem;
|
||||
|
||||
@ -138,16 +630,6 @@ macShadowSubsystem* mac_shadow_subsystem_new(rdpShadowServer* server)
|
||||
if (!subsystem)
|
||||
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->KeyboardEvent = (pfnShadowKeyboardEvent) mac_shadow_input_keyboard_event;
|
||||
subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) mac_shadow_input_unicode_keyboard_event;
|
||||
@ -157,7 +639,18 @@ macShadowSubsystem* mac_shadow_subsystem_new(rdpShadowServer* server)
|
||||
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;
|
||||
}
|
||||
|
@ -29,11 +29,31 @@ typedef struct mac_shadow_subsystem macShadowSubsystem;
|
||||
#include <winpr/stream.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
|
||||
{
|
||||
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
|
||||
|
@ -20,13 +20,14 @@
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/codec/region.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "../shadow_screen.h"
|
||||
#include "../shadow_surface.h"
|
||||
#include "../shadow_capture.h"
|
||||
#include "../shadow_subsystem.h"
|
||||
|
||||
#include "win_shadow.h"
|
||||
|
||||
@ -280,7 +281,7 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem)
|
||||
|
||||
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
|
||||
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);
|
||||
|
||||
@ -398,27 +399,51 @@ void* win_shadow_subsystem_thread(winShadowSubsystem* subsystem)
|
||||
|
||||
#endif
|
||||
|
||||
int win_shadow_subsystem_init(winShadowSubsystem* subsystem)
|
||||
int win_shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors)
|
||||
{
|
||||
HDC hdc;
|
||||
int status;
|
||||
int index;
|
||||
int desktopWidth;
|
||||
int desktopHeight;
|
||||
DWORD iDevNum = 0;
|
||||
int numMonitors = 0;
|
||||
MONITOR_DEF* monitor;
|
||||
MONITOR_DEF* virtualScreen;
|
||||
DISPLAY_DEVICE DisplayDevice;
|
||||
DISPLAY_DEVICE displayDevice;
|
||||
|
||||
ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE));
|
||||
DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
|
||||
ZeroMemory(&displayDevice, sizeof(DISPLAY_DEVICE));
|
||||
displayDevice.cb = sizeof(DISPLAY_DEVICE);
|
||||
|
||||
if (!EnumDisplayDevices(NULL, iDevNum, &DisplayDevice, 0))
|
||||
return -1;
|
||||
if (EnumDisplayDevices(NULL, iDevNum, &displayDevice, 0))
|
||||
{
|
||||
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);
|
||||
subsystem->height = GetDeviceCaps(hdc, VERTRES);
|
||||
subsystem->bpp = GetDeviceCaps(hdc, BITSPIXEL);
|
||||
index = 0;
|
||||
numMonitors = 1;
|
||||
|
||||
DeleteDC(hdc);
|
||||
monitor = &monitors[index];
|
||||
|
||||
monitor->left = 0;
|
||||
monitor->top = 0;
|
||||
monitor->right = desktopWidth;
|
||||
monitor->bottom = desktopHeight;
|
||||
monitor->flags = 1;
|
||||
|
||||
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)
|
||||
status = win_shadow_wds_init(subsystem);
|
||||
@ -434,16 +459,6 @@ int win_shadow_subsystem_init(winShadowSubsystem* subsystem)
|
||||
virtualScreen->bottom = subsystem->height;
|
||||
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);
|
||||
|
||||
return 1;
|
||||
@ -492,14 +507,10 @@ void win_shadow_subsystem_free(winShadowSubsystem* subsystem)
|
||||
|
||||
win_shadow_subsystem_uninit(subsystem);
|
||||
|
||||
region16_uninit(&(subsystem->invalidRegion));
|
||||
|
||||
CloseHandle(subsystem->updateEvent);
|
||||
|
||||
free(subsystem);
|
||||
}
|
||||
|
||||
winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server)
|
||||
winShadowSubsystem* win_shadow_subsystem_new()
|
||||
{
|
||||
winShadowSubsystem* subsystem;
|
||||
|
||||
@ -508,20 +519,6 @@ winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server)
|
||||
if (!subsystem)
|
||||
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->KeyboardEvent = (pfnShadowKeyboardEvent) win_shadow_input_keyboard_event;
|
||||
subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) win_shadow_input_unicode_keyboard_event;
|
||||
@ -531,7 +528,18 @@ winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server)
|
||||
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;
|
||||
}
|
||||
|
@ -32,15 +32,19 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/image.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/codec/region.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "../shadow_screen.h"
|
||||
#include "../shadow_client.h"
|
||||
#include "../shadow_encoder.h"
|
||||
#include "../shadow_capture.h"
|
||||
#include "../shadow_surface.h"
|
||||
#include "../shadow_subsystem.h"
|
||||
|
||||
#include "x11_shadow.h"
|
||||
|
||||
@ -91,6 +95,20 @@ void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, U
|
||||
#ifdef WITH_XTEST
|
||||
int button = 0;
|
||||
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);
|
||||
|
||||
@ -121,7 +139,7 @@ void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, U
|
||||
if (flags & PTR_FLAGS_DOWN)
|
||||
down = TRUE;
|
||||
|
||||
if (button != 0)
|
||||
if (button)
|
||||
XTestFakeButtonEvent(subsystem->display, button, down, 0);
|
||||
}
|
||||
|
||||
@ -134,8 +152,23 @@ void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16
|
||||
#ifdef WITH_XTEST
|
||||
int button = 0;
|
||||
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);
|
||||
|
||||
XTestFakeMotionEvent(subsystem->display, 0, x, y, CurrentTime);
|
||||
|
||||
if (flags & PTR_XFLAGS_BUTTON1)
|
||||
@ -146,13 +179,99 @@ void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16
|
||||
if (flags & PTR_XFLAGS_DOWN)
|
||||
down = TRUE;
|
||||
|
||||
if (button != 0)
|
||||
if (button)
|
||||
XTestFakeButtonEvent(subsystem->display, button, down, 0);
|
||||
|
||||
XTestGrabControl(subsystem->display, False);
|
||||
#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)
|
||||
{
|
||||
XRectangle region;
|
||||
@ -171,19 +290,117 @@ void x11_shadow_validate_region(x11ShadowSubsystem* subsystem, int x, int y, int
|
||||
#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;
|
||||
RECTANGLE_16 invalidRect;
|
||||
int x, y;
|
||||
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;
|
||||
invalidRect.top = y;
|
||||
invalidRect.right = x + width;
|
||||
invalidRect.bottom = y + height;
|
||||
nXSrc = 0;
|
||||
nYSrc = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
@ -199,106 +416,153 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
|
||||
rdpShadowServer* server;
|
||||
rdpShadowSurface* surface;
|
||||
RECTANGLE_16 invalidRect;
|
||||
RECTANGLE_16 surfaceRect;
|
||||
const RECTANGLE_16 *extents;
|
||||
|
||||
server = subsystem->server;
|
||||
surface = server->surface;
|
||||
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)
|
||||
{
|
||||
XLockDisplay(subsystem->display);
|
||||
image = subsystem->fb_image;
|
||||
|
||||
XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap,
|
||||
subsystem->xshm_gc, 0, 0, subsystem->width, subsystem->height, 0, 0);
|
||||
|
||||
XSync(subsystem->display, False);
|
||||
|
||||
XUnlockDisplay(subsystem->display);
|
||||
|
||||
image = subsystem->fb_image;
|
||||
|
||||
status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height,
|
||||
(BYTE*) image->data, image->bytes_per_line, &invalidRect);
|
||||
|
||||
if (status > 0)
|
||||
{
|
||||
x = invalidRect.left;
|
||||
y = invalidRect.top;
|
||||
width = invalidRect.right - invalidRect.left;
|
||||
height = invalidRect.bottom - invalidRect.top;
|
||||
|
||||
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
|
||||
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);
|
||||
|
||||
count = ArrayList_Count(server->clients);
|
||||
|
||||
InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1);
|
||||
|
||||
SetEvent(subsystem->updateEvent);
|
||||
|
||||
EnterSynchronizationBarrier(&(subsystem->barrier), 0);
|
||||
|
||||
DeleteSynchronizationBarrier(&(subsystem->barrier));
|
||||
|
||||
ResetEvent(subsystem->updateEvent);
|
||||
|
||||
region16_clear(&(subsystem->invalidRegion));
|
||||
}
|
||||
(BYTE*) &(image->data[surface->width * 4]), image->bytes_per_line, &invalidRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
XLockDisplay(subsystem->display);
|
||||
|
||||
image = XGetImage(subsystem->display, subsystem->root_window,
|
||||
0, 0, subsystem->width, subsystem->height, AllPlanes, ZPixmap);
|
||||
|
||||
XUnlockDisplay(subsystem->display);
|
||||
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);
|
||||
}
|
||||
|
||||
if (status > 0)
|
||||
XSync(subsystem->display, False);
|
||||
|
||||
XUnlockDisplay(subsystem->display);
|
||||
|
||||
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
|
||||
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;
|
||||
|
||||
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
|
||||
surface->scanline, x, y, width, height,
|
||||
(BYTE*) image->data, PIXEL_FORMAT_XRGB32,
|
||||
image->bytes_per_line, x, y, NULL);
|
||||
|
||||
x11_shadow_blend_cursor(subsystem);
|
||||
|
||||
count = ArrayList_Count(server->clients);
|
||||
|
||||
InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1);
|
||||
|
||||
SetEvent(subsystem->updateEvent);
|
||||
|
||||
EnterSynchronizationBarrier(&(subsystem->barrier), 0);
|
||||
|
||||
DeleteSynchronizationBarrier(&(subsystem->barrier));
|
||||
|
||||
if (count == 1)
|
||||
{
|
||||
x = invalidRect.left;
|
||||
y = invalidRect.top;
|
||||
width = invalidRect.right - invalidRect.left;
|
||||
height = invalidRect.bottom - invalidRect.top;
|
||||
rdpShadowClient* client;
|
||||
|
||||
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
|
||||
surface->scanline, x - surface->x, y - surface->y, width, height,
|
||||
(BYTE*) image->data, PIXEL_FORMAT_XRGB32,
|
||||
image->bytes_per_line, x, y, NULL);
|
||||
client = (rdpShadowClient*) ArrayList_GetItem(server->clients, 0);
|
||||
|
||||
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
|
||||
|
||||
count = ArrayList_Count(server->clients);
|
||||
|
||||
InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1);
|
||||
|
||||
SetEvent(subsystem->updateEvent);
|
||||
|
||||
EnterSynchronizationBarrier(&(subsystem->barrier), 0);
|
||||
|
||||
DeleteSynchronizationBarrier(&(subsystem->barrier));
|
||||
|
||||
ResetEvent(subsystem->updateEvent);
|
||||
|
||||
region16_clear(&(subsystem->invalidRegion));
|
||||
if (client)
|
||||
{
|
||||
subsystem->captureFrameRate = client->encoder->fps;
|
||||
}
|
||||
}
|
||||
|
||||
XDestroyImage(image);
|
||||
ResetEvent(subsystem->updateEvent);
|
||||
|
||||
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
|
||||
{
|
||||
RECTANGLE_16 refreshRect;
|
||||
|
||||
refreshRect.left = 0;
|
||||
refreshRect.top = 0;
|
||||
refreshRect.right = subsystem->width;
|
||||
refreshRect.bottom = subsystem->height;
|
||||
|
||||
region16_union_rect(&(subsystem->invalidRegion),
|
||||
&(subsystem->invalidRegion), &refreshRect);
|
||||
}
|
||||
}
|
||||
else if (message->id == SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID)
|
||||
{
|
||||
SHADOW_MSG_IN_SUPPRESS_OUTPUT* msg = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) message->wParam;
|
||||
|
||||
subsystem->suppressOutput = (msg->allow) ? FALSE : TRUE;
|
||||
|
||||
if (msg->allow)
|
||||
{
|
||||
region16_union_rect(&(subsystem->invalidRegion),
|
||||
&(subsystem->invalidRegion), &(msg->rect));
|
||||
}
|
||||
}
|
||||
|
||||
if (message->Free)
|
||||
message->Free(message);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
|
||||
{
|
||||
int fps;
|
||||
XEvent xevent;
|
||||
DWORD status;
|
||||
DWORD nCount;
|
||||
UINT64 cTime;
|
||||
@ -306,16 +570,17 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
|
||||
DWORD dwInterval;
|
||||
UINT64 frameTime;
|
||||
HANDLE events[32];
|
||||
HANDLE StopEvent;
|
||||
wMessage message;
|
||||
wMessagePipe* MsgPipe;
|
||||
|
||||
StopEvent = subsystem->server->StopEvent;
|
||||
MsgPipe = subsystem->MsgPipe;
|
||||
|
||||
nCount = 0;
|
||||
events[nCount++] = StopEvent;
|
||||
events[nCount++] = subsystem->event;
|
||||
events[nCount++] = MessageQueue_Event(MsgPipe->In);
|
||||
|
||||
fps = 16;
|
||||
dwInterval = 1000 / fps;
|
||||
subsystem->captureFrameRate = 16;
|
||||
dwInterval = 1000 / subsystem->captureFrameRate;
|
||||
frameTime = GetTickCount64() + dwInterval;
|
||||
|
||||
while (1)
|
||||
@ -325,16 +590,32 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
|
||||
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, dwTimeout);
|
||||
|
||||
if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0)
|
||||
if (WaitForSingleObject(MessageQueue_Event(MsgPipe->In), 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
break;
|
||||
if (MessageQueue_Peek(MsgPipe->In, &message, TRUE))
|
||||
{
|
||||
if (message.id == WMQ_QUIT)
|
||||
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))
|
||||
{
|
||||
x11_shadow_query_cursor(subsystem, FALSE);
|
||||
x11_shadow_screen_grab(subsystem);
|
||||
|
||||
dwInterval = 1000 / fps;
|
||||
dwInterval = 1000 / subsystem->captureFrameRate;
|
||||
frameTime += dwInterval;
|
||||
}
|
||||
}
|
||||
@ -343,6 +624,36 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
|
||||
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)
|
||||
{
|
||||
#ifdef WITH_XFIXES
|
||||
@ -356,7 +667,7 @@ int x11_shadow_xfixes_init(x11ShadowSubsystem* subsystem)
|
||||
if (!XFixesQueryVersion(subsystem->display, &major, &minor))
|
||||
return -1;
|
||||
|
||||
subsystem->xfixes_notify_event = xfixes_event + XFixesCursorNotify;
|
||||
subsystem->xfixes_cursor_notify_event = xfixes_event + XFixesCursorNotify;
|
||||
|
||||
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)
|
||||
{
|
||||
#ifdef WITH_XINERAMA
|
||||
int index;
|
||||
int numMonitors;
|
||||
int major, minor;
|
||||
int xinerama_event;
|
||||
int xinerama_error;
|
||||
MONITOR_DEF* monitor;
|
||||
XineramaScreenInfo* screen;
|
||||
XineramaScreenInfo* screens;
|
||||
|
||||
x11_shadow_subsystem_base_init(subsystem);
|
||||
|
||||
if (!XineramaQueryExtension(subsystem->display, &xinerama_event, &xinerama_error))
|
||||
return -1;
|
||||
@ -387,32 +695,10 @@ int x11_shadow_xinerama_init(x11ShadowSubsystem* subsystem)
|
||||
if (!XineramaIsActive(subsystem->display))
|
||||
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;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int x11_shadow_xdamage_init(x11ShadowSubsystem* subsystem)
|
||||
@ -527,6 +813,82 @@ int x11_shadow_xshm_init(x11ShadowSubsystem* subsystem)
|
||||
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 i;
|
||||
@ -541,27 +903,9 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
|
||||
XPixmapFormatValues* pfs;
|
||||
MONITOR_DEF* virtualScreen;
|
||||
|
||||
/**
|
||||
* To see if your X11 server supports shared pixmaps, use:
|
||||
* xdpyinfo -ext MIT-SHM | grep "shared pixmaps"
|
||||
*/
|
||||
subsystem->numMonitors = x11_shadow_enum_monitors(subsystem->monitors, 16);
|
||||
|
||||
if (!getenv("DISPLAY"))
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
x11_shadow_subsystem_base_init(subsystem);
|
||||
|
||||
extensions = XListExtensions(subsystem->display, &nextensions);
|
||||
|
||||
@ -579,17 +923,6 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
|
||||
if (subsystem->composite)
|
||||
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);
|
||||
|
||||
if (!pfs)
|
||||
@ -637,6 +970,15 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
|
||||
|
||||
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 (x11_shadow_xfixes_init(subsystem) < 0)
|
||||
@ -671,16 +1013,6 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
|
||||
virtualScreen->bottom = subsystem->height;
|
||||
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",
|
||||
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;
|
||||
}
|
||||
|
||||
if (subsystem->cursorPixels)
|
||||
{
|
||||
_aligned_free(subsystem->cursorPixels);
|
||||
subsystem->cursorPixels = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x11_shadow_subsystem_start(x11ShadowSubsystem* subsystem)
|
||||
{
|
||||
HANDLE thread;
|
||||
|
||||
if (!subsystem)
|
||||
return -1;
|
||||
|
||||
thread = CreateThread(NULL, 0,
|
||||
subsystem->thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) x11_shadow_subsystem_thread,
|
||||
(void*) subsystem, 0, NULL);
|
||||
|
||||
@ -726,9 +1062,41 @@ int x11_shadow_subsystem_stop(x11ShadowSubsystem* subsystem)
|
||||
if (!subsystem)
|
||||
return -1;
|
||||
|
||||
if (subsystem->thread)
|
||||
{
|
||||
MessageQueue_PostQuit(subsystem->MsgPipe->In, 0);
|
||||
WaitForSingleObject(subsystem->thread, INFINITE);
|
||||
CloseHandle(subsystem->thread);
|
||||
subsystem->thread = NULL;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (!subsystem)
|
||||
@ -736,50 +1104,21 @@ void x11_shadow_subsystem_free(x11ShadowSubsystem* subsystem)
|
||||
|
||||
x11_shadow_subsystem_uninit(subsystem);
|
||||
|
||||
region16_uninit(&(subsystem->invalidRegion));
|
||||
|
||||
CloseHandle(subsystem->updateEvent);
|
||||
|
||||
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)
|
||||
return NULL;
|
||||
pEntryPoints->Start = (pfnShadowSubsystemStart) x11_shadow_subsystem_start;
|
||||
pEntryPoints->Stop = (pfnShadowSubsystemStop) x11_shadow_subsystem_stop;
|
||||
|
||||
subsystem->server = server;
|
||||
pEntryPoints->EnumMonitors = (pfnShadowEnumMonitors) x11_shadow_enum_monitors;
|
||||
|
||||
subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
|
@ -80,6 +80,17 @@ struct x11_shadow_subsystem
|
||||
Window root_window;
|
||||
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
|
||||
GC xshm_gc;
|
||||
Damage xdamage;
|
||||
@ -88,7 +99,7 @@ struct x11_shadow_subsystem
|
||||
#endif
|
||||
|
||||
#ifdef WITH_XFIXES
|
||||
int xfixes_notify_event;
|
||||
int xfixes_cursor_notify_event;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
86
server/shadow/shadow.c
Normal file
86
server/shadow/shadow.c
Normal 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;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "shadow_encoder.h"
|
||||
#include "shadow_capture.h"
|
||||
#include "shadow_channels.h"
|
||||
#include "shadow_subsystem.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -40,6 +40,7 @@ void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
|
||||
|
||||
server = (rdpShadowServer*) peer->ContextExtra;
|
||||
client->server = server;
|
||||
client->subsystem = server->subsystem;
|
||||
|
||||
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->encoder = shadow_encoder_new(server);
|
||||
client->encoder = shadow_encoder_new(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)
|
||||
{
|
||||
return TRUE;
|
||||
@ -114,13 +131,26 @@ BOOL shadow_client_post_connect(freerdp_peer* peer)
|
||||
rdpSettings* settings;
|
||||
rdpShadowClient* client;
|
||||
rdpShadowSurface* lobby;
|
||||
rdpShadowServer* server;
|
||||
RECTANGLE_16 invalidRect;
|
||||
|
||||
client = (rdpShadowClient*) peer->context;
|
||||
settings = peer->settings;
|
||||
server = client->server;
|
||||
|
||||
settings->DesktopWidth = client->server->screen->width;
|
||||
settings->DesktopHeight = client->server->screen->height;
|
||||
if (!server->shareSubRect)
|
||||
{
|
||||
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)
|
||||
settings->ColorDepth = 16; /* disable 24bpp */
|
||||
@ -132,9 +162,6 @@ BOOL shadow_client_post_connect(freerdp_peer* peer)
|
||||
|
||||
shadow_client_channels_post_connect(client);
|
||||
|
||||
width = settings->DesktopWidth;
|
||||
height = settings->DesktopHeight;
|
||||
|
||||
invalidRect.left = 0;
|
||||
invalidRect.top = 0;
|
||||
invalidRect.right = width;
|
||||
@ -155,6 +182,63 @@ BOOL shadow_client_post_connect(freerdp_peer* peer)
|
||||
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)
|
||||
{
|
||||
rdpShadowClient* client;
|
||||
@ -166,6 +250,8 @@ BOOL shadow_client_activate(freerdp_peer* peer)
|
||||
|
||||
shadow_encoder_reset(client->encoder);
|
||||
|
||||
shadow_client_refresh_rect(client, 0, NULL);
|
||||
|
||||
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)
|
||||
{
|
||||
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 i;
|
||||
BOOL first;
|
||||
BOOL last;
|
||||
wStream* s;
|
||||
int nSrcStep;
|
||||
BYTE* pSrcData;
|
||||
@ -228,12 +311,24 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s
|
||||
pSrcData = surface->data;
|
||||
nSrcStep = surface->scanline;
|
||||
|
||||
if (encoder->frameAck)
|
||||
if (server->shareSubRect)
|
||||
{
|
||||
frameId = (UINT32) shadow_encoder_create_frame_id(encoder);
|
||||
shadow_client_send_surface_frame_marker(client, SURFACECMD_FRAMEACTION_BEGIN, frameId);
|
||||
int subX, subY;
|
||||
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)
|
||||
{
|
||||
RFX_RECT rect;
|
||||
@ -270,7 +365,13 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s
|
||||
cmd.bitmapDataLength = Stream_GetPosition(s);
|
||||
cmd.bitmapData = Stream_Buffer(s);
|
||||
|
||||
IFCALL(update->SurfaceBits, update->context, &cmd);
|
||||
first = (i == 0) ? TRUE : FALSE;
|
||||
last = ((i + 1) == numMessages) ? TRUE : FALSE;
|
||||
|
||||
if (!encoder->frameAck)
|
||||
IFCALL(update->SurfaceBits, update->context, &cmd);
|
||||
else
|
||||
IFCALL(update->SurfaceFrameBits, update->context, &cmd, first, last, frameId);
|
||||
}
|
||||
|
||||
free(messages);
|
||||
@ -305,17 +406,18 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s
|
||||
cmd.bitmapDataLength = Stream_GetPosition(s);
|
||||
cmd.bitmapData = Stream_Buffer(s);
|
||||
|
||||
IFCALL(update->SurfaceBits, update->context, &cmd);
|
||||
first = (i == 0) ? TRUE : FALSE;
|
||||
last = ((i + 1) == numMessages) ? TRUE : FALSE;
|
||||
|
||||
if (!encoder->frameAck)
|
||||
IFCALL(update->SurfaceBits, update->context, &cmd);
|
||||
else
|
||||
IFCALL(update->SurfaceFrameBits, update->context, &cmd, first, last, frameId);
|
||||
}
|
||||
|
||||
free(messages);
|
||||
}
|
||||
|
||||
if (encoder->frameAck)
|
||||
{
|
||||
shadow_client_send_surface_frame_marker(client, SURFACECMD_FRAMEACTION_END, frameId);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -554,13 +656,18 @@ int shadow_client_send_surface_update(rdpShadowClient* client)
|
||||
|
||||
LeaveCriticalSection(&(client->lock));
|
||||
|
||||
surfaceRect.left = surface->x;
|
||||
surfaceRect.top = surface->y;
|
||||
surfaceRect.right = surface->x + surface->width;
|
||||
surfaceRect.bottom = surface->y + surface->height;
|
||||
surfaceRect.left = 0;
|
||||
surfaceRect.top = 0;
|
||||
surfaceRect.right = surface->width;
|
||||
surfaceRect.bottom = surface->height;
|
||||
|
||||
region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect);
|
||||
|
||||
if (server->shareSubRect)
|
||||
{
|
||||
region16_intersect_rect(&invalidRegion, &invalidRegion, &(server->subRect));
|
||||
}
|
||||
|
||||
if (region16_is_empty(&invalidRegion))
|
||||
{
|
||||
region16_uninit(&invalidRegion);
|
||||
@ -569,8 +676,8 @@ int shadow_client_send_surface_update(rdpShadowClient* client)
|
||||
|
||||
extents = region16_extents(&invalidRegion);
|
||||
|
||||
nXSrc = extents->left - surface->x;
|
||||
nYSrc = extents->top - surface->y;
|
||||
nXSrc = extents->left - 0;
|
||||
nYSrc = extents->top - 0;
|
||||
nWidth = extents->right - extents->left;
|
||||
nHeight = extents->bottom - extents->top;
|
||||
|
||||
@ -628,6 +735,7 @@ void* shadow_client_thread(rdpShadowClient* client)
|
||||
HANDLE ChannelEvent;
|
||||
HANDLE UpdateEvent;
|
||||
freerdp_peer* peer;
|
||||
rdpContext* context;
|
||||
rdpSettings* settings;
|
||||
rdpShadowServer* server;
|
||||
rdpShadowScreen* screen;
|
||||
@ -639,7 +747,8 @@ void* shadow_client_thread(rdpShadowClient* client)
|
||||
encoder = client->encoder;
|
||||
subsystem = server->subsystem;
|
||||
|
||||
peer = ((rdpContext*) client)->peer;
|
||||
context = (rdpContext*) client;
|
||||
peer = context->peer;
|
||||
settings = peer->settings;
|
||||
|
||||
peer->Capabilities = shadow_client_capabilities;
|
||||
@ -650,9 +759,9 @@ void* shadow_client_thread(rdpShadowClient* client)
|
||||
|
||||
peer->Initialize(peer);
|
||||
|
||||
peer->update->SurfaceFrameAcknowledge = (pSurfaceFrameAcknowledge)
|
||||
shadow_client_surface_frame_acknowledge;
|
||||
peer->update->RefreshRect = (pRefreshRect) shadow_client_refresh_rect;
|
||||
peer->update->SuppressOutput = (pSuppressOutput) shadow_client_suppress_output;
|
||||
peer->update->SurfaceFrameAcknowledge = (pSurfaceFrameAcknowledge) shadow_client_surface_frame_acknowledge;
|
||||
|
||||
StopEvent = client->StopEvent;
|
||||
UpdateEvent = subsystem->updateEvent;
|
||||
|
@ -84,7 +84,7 @@ int shadow_encoder_init_grid(rdpShadowEncoder* encoder)
|
||||
{
|
||||
for (j = 0; j < encoder->gridWidth; j++)
|
||||
{
|
||||
k = (i * encoder->gridHeight) + j;
|
||||
k = (i * encoder->gridWidth) + j;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
if (!encoder->planar)
|
||||
@ -346,15 +350,17 @@ int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs)
|
||||
return 1;
|
||||
}
|
||||
|
||||
rdpShadowEncoder* shadow_encoder_new(rdpShadowServer* server)
|
||||
rdpShadowEncoder* shadow_encoder_new(rdpShadowClient* client)
|
||||
{
|
||||
rdpShadowEncoder* encoder;
|
||||
rdpShadowServer* server = client->server;
|
||||
|
||||
encoder = (rdpShadowEncoder*) calloc(1, sizeof(rdpShadowEncoder));
|
||||
|
||||
if (!encoder)
|
||||
return NULL;
|
||||
|
||||
encoder->client = client;
|
||||
encoder->server = server;
|
||||
|
||||
encoder->fps = 16;
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
struct rdp_shadow_encoder
|
||||
{
|
||||
rdpShadowClient* client;
|
||||
rdpShadowServer* server;
|
||||
|
||||
int width;
|
||||
@ -70,7 +71,7 @@ int shadow_encoder_reset(rdpShadowEncoder* encoder);
|
||||
int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs);
|
||||
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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -45,7 +45,7 @@ rdpShadowScreen* shadow_screen_new(rdpShadowServer* server)
|
||||
|
||||
region16_init(&(screen->invalidRegion));
|
||||
|
||||
primary = &(subsystem->monitors[0]);
|
||||
primary = &(subsystem->monitors[subsystem->selectedMonitor]);
|
||||
|
||||
x = primary->left;
|
||||
y = primary->top;
|
||||
|
@ -27,15 +27,11 @@
|
||||
#include <winpr/cmdline.h>
|
||||
#include <winpr/winsock.h>
|
||||
|
||||
#include <freerdp/version.h>
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/version.h>
|
||||
|
||||
#include <winpr/tools/makecert.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <openssl/applink.c>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
@ -45,29 +41,12 @@
|
||||
|
||||
#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[] =
|
||||
{
|
||||
{ "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" },
|
||||
{ "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-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" },
|
||||
@ -203,6 +182,56 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
@ -216,22 +245,36 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
|
||||
|
||||
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)
|
||||
{
|
||||
/* Select monitors */
|
||||
|
||||
index = atoi(arg->Value);
|
||||
|
||||
if (index < 0)
|
||||
index = 0;
|
||||
|
||||
if (index >= numMonitors)
|
||||
index = 0;
|
||||
|
||||
server->selectedMonitor = index;
|
||||
}
|
||||
else
|
||||
{
|
||||
int index;
|
||||
int width, height;
|
||||
MONITOR_DEF* monitor;
|
||||
rdpShadowSubsystem* subsystem = server->subsystem;
|
||||
|
||||
/* 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;
|
||||
height = monitor->bottom - monitor->top;
|
||||
@ -248,32 +291,6 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
|
||||
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)
|
||||
{
|
||||
DWORD status;
|
||||
@ -287,10 +304,7 @@ void* shadow_server_thread(rdpShadowServer* server)
|
||||
StopEvent = server->StopEvent;
|
||||
subsystem = server->subsystem;
|
||||
|
||||
if (subsystem->Start)
|
||||
{
|
||||
subsystem->Start(subsystem);
|
||||
}
|
||||
shadow_subsystem_start(server->subsystem);
|
||||
|
||||
while (1)
|
||||
{
|
||||
@ -324,10 +338,7 @@ void* shadow_server_thread(rdpShadowServer* server)
|
||||
|
||||
listener->Close(listener);
|
||||
|
||||
if (subsystem->Stop)
|
||||
{
|
||||
subsystem->Stop(subsystem);
|
||||
}
|
||||
shadow_subsystem_stop(server->subsystem);
|
||||
|
||||
ExitThread(0);
|
||||
|
||||
@ -346,6 +357,16 @@ int shadow_server_start(rdpShadowServer* server)
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#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)
|
||||
status = server->listener->Open(server->listener, NULL, (UINT16) server->port);
|
||||
else
|
||||
@ -372,9 +393,82 @@ int shadow_server_stop(rdpShadowServer* server)
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
char* filepath;
|
||||
@ -436,8 +530,17 @@ int shadow_server_init(rdpShadowServer* server)
|
||||
|
||||
WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi());
|
||||
|
||||
server->clients = ArrayList_New(TRUE);
|
||||
|
||||
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);
|
||||
|
||||
if (status < 0)
|
||||
@ -451,45 +554,14 @@ int shadow_server_init(rdpShadowServer* server)
|
||||
server->listener->info = (void*) server;
|
||||
server->listener->PeerAccepted = shadow_client_accepted;
|
||||
|
||||
#ifdef WITH_SHADOW_X11
|
||||
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);
|
||||
server->subsystem = shadow_subsystem_new(NULL);
|
||||
|
||||
if (!server->subsystem)
|
||||
return -1;
|
||||
|
||||
server->subsystem->SurfaceUpdate = shadow_server_surface_update;
|
||||
status = shadow_subsystem_init(server->subsystem, server);
|
||||
|
||||
if (server->subsystem->Init)
|
||||
{
|
||||
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;
|
||||
return status;
|
||||
}
|
||||
|
||||
int shadow_server_uninit(rdpShadowServer* server)
|
||||
@ -502,12 +574,6 @@ int shadow_server_uninit(rdpShadowServer* server)
|
||||
server->listener = NULL;
|
||||
}
|
||||
|
||||
if (server->subsystem)
|
||||
{
|
||||
server->subsystem->Free(server->subsystem);
|
||||
server->subsystem = NULL;
|
||||
}
|
||||
|
||||
if (server->CertificateFile)
|
||||
{
|
||||
free(server->CertificateFile);
|
||||
@ -526,6 +592,8 @@ int shadow_server_uninit(rdpShadowServer* server)
|
||||
server->ipcSocket = NULL;
|
||||
}
|
||||
|
||||
shadow_subsystem_uninit(server->subsystem);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -542,17 +610,6 @@ rdpShadowServer* shadow_server_new()
|
||||
server->mayView = 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;
|
||||
}
|
||||
|
||||
@ -569,50 +626,8 @@ void shadow_server_free(rdpShadowServer* server)
|
||||
server->clients = NULL;
|
||||
}
|
||||
|
||||
shadow_server_uninit(server);
|
||||
shadow_subsystem_free(server->subsystem);
|
||||
|
||||
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;
|
||||
}
|
||||
|
210
server/shadow/shadow_subsystem.c
Normal file
210
server/shadow/shadow_subsystem.c
Normal 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;
|
||||
}
|
62
server/shadow/shadow_subsystem.h
Normal file
62
server/shadow/shadow_subsystem.h
Normal 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 */
|
||||
|
@ -111,6 +111,7 @@ void MessageQueue_Post(wMessageQueue* queue, void* context, UINT32 type, void* w
|
||||
message.id = type;
|
||||
message.wParam = wParam;
|
||||
message.lParam = lParam;
|
||||
message.Free = NULL;
|
||||
|
||||
MessageQueue_Dispatch(queue, &message);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user