mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2024-11-23 18:03:30 +08:00
shadow: add improved pointer updates
This commit is contained in:
parent
92d08cf58f
commit
a538e791b3
@ -1506,9 +1506,25 @@ static void update_send_pointer_system(rdpContext* context, POINTER_SYSTEM_UPDAT
|
||||
Stream_Release(s);
|
||||
}
|
||||
|
||||
static void update_send_pointer_position(rdpContext* context, POINTER_POSITION_UPDATE* pointerPosition)
|
||||
{
|
||||
wStream* s;
|
||||
rdpRdp* rdp = context->rdp;
|
||||
|
||||
s = fastpath_update_pdu_init(rdp->fastpath);
|
||||
|
||||
Stream_EnsureRemainingCapacity(s, 16);
|
||||
|
||||
Stream_Write_UINT16(s, pointerPosition->xPos); /* xPos (2 bytes) */
|
||||
Stream_Write_UINT16(s, pointerPosition->yPos); /* yPos (2 bytes) */
|
||||
|
||||
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_PTR_POSITION, s);
|
||||
Stream_Release(s);
|
||||
}
|
||||
|
||||
static void update_write_pointer_color(wStream* s, POINTER_COLOR_UPDATE* pointer_color)
|
||||
{
|
||||
Stream_EnsureRemainingCapacity(s, 15 + (int) pointer_color->lengthAndMask + (int) pointer_color->lengthXorMask);
|
||||
Stream_EnsureRemainingCapacity(s, 32 + (int) pointer_color->lengthAndMask + (int) pointer_color->lengthXorMask);
|
||||
|
||||
Stream_Write_UINT16(s, pointer_color->cacheIndex);
|
||||
Stream_Write_UINT16(s, pointer_color->xPos);
|
||||
@ -1544,8 +1560,12 @@ static void update_send_pointer_new(rdpContext* context, POINTER_NEW_UPDATE* poi
|
||||
rdpRdp* rdp = context->rdp;
|
||||
|
||||
s = fastpath_update_pdu_init(rdp->fastpath);
|
||||
|
||||
Stream_EnsureRemainingCapacity(s, 16);
|
||||
|
||||
Stream_Write_UINT16(s, pointer_new->xorBpp); /* xorBpp (2 bytes) */
|
||||
update_write_pointer_color(s, &pointer_new->colorPtrAttr);
|
||||
|
||||
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_POINTER, s);
|
||||
Stream_Release(s);
|
||||
}
|
||||
@ -1614,14 +1634,14 @@ BOOL update_read_suppress_output(rdpUpdate* update, wStream* s)
|
||||
|
||||
static void update_send_set_keyboard_indicators(rdpContext* context, UINT16 led_flags)
|
||||
{
|
||||
wStream* s;
|
||||
rdpRdp* rdp = context->rdp;
|
||||
wStream* s;
|
||||
rdpRdp* rdp = context->rdp;
|
||||
|
||||
s = rdp_data_pdu_init(rdp);
|
||||
Stream_Write_UINT16(s, 0); /* unitId should be 0 according to MS-RDPBCGR 2.2.8.2.1.1 */
|
||||
Stream_Write_UINT16(s, led_flags); /* ledFlags (2 bytes) */
|
||||
rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS, rdp->mcs->userId);
|
||||
Stream_Release(s);
|
||||
s = rdp_data_pdu_init(rdp);
|
||||
Stream_Write_UINT16(s, 0); /* unitId should be 0 according to MS-RDPBCGR 2.2.8.2.1.1 */
|
||||
Stream_Write_UINT16(s, led_flags); /* ledFlags (2 bytes) */
|
||||
rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS, rdp->mcs->userId);
|
||||
Stream_Release(s);
|
||||
}
|
||||
|
||||
void update_register_server_callbacks(rdpUpdate* update)
|
||||
@ -1655,6 +1675,7 @@ void update_register_server_callbacks(rdpUpdate* update)
|
||||
update->altsec->CreateOffscreenBitmap = update_send_create_offscreen_bitmap_order;
|
||||
update->altsec->SwitchSurface = update_send_switch_surface_order;
|
||||
update->pointer->PointerSystem = update_send_pointer_system;
|
||||
update->pointer->PointerPosition = update_send_pointer_position;
|
||||
update->pointer->PointerColor = update_send_pointer_color;
|
||||
update->pointer->PointerNew = update_send_pointer_new;
|
||||
update->pointer->PointerCached = update_send_pointer_cached;
|
||||
|
@ -341,6 +341,55 @@ void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16
|
||||
#endif
|
||||
}
|
||||
|
||||
int x11_shadow_pointer_position_update(x11ShadowSubsystem* subsystem)
|
||||
{
|
||||
SHADOW_MSG_OUT_POINTER_POSITION_UPDATE* msg;
|
||||
UINT32 msgId = SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID;
|
||||
wMessagePipe* MsgPipe = subsystem->MsgPipe;
|
||||
|
||||
msg = (SHADOW_MSG_OUT_POINTER_POSITION_UPDATE*) calloc(1, sizeof(SHADOW_MSG_OUT_POINTER_POSITION_UPDATE));
|
||||
|
||||
if (!msg)
|
||||
return -1;
|
||||
|
||||
msg->xPos = subsystem->cursorX;
|
||||
msg->yPos = subsystem->cursorY;
|
||||
|
||||
MessageQueue_Post(MsgPipe->Out, NULL, msgId, (void*) msg, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x11_shadow_pointer_alpha_update(x11ShadowSubsystem* subsystem)
|
||||
{
|
||||
SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* msg;
|
||||
UINT32 msgId = SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID;
|
||||
wMessagePipe* MsgPipe = subsystem->MsgPipe;
|
||||
|
||||
msg = (SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE*) calloc(1, sizeof(SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE));
|
||||
|
||||
if (!msg)
|
||||
return -1;
|
||||
|
||||
msg->xHot = subsystem->cursorHotX;
|
||||
msg->yHot = subsystem->cursorHotY;
|
||||
msg->width = subsystem->cursorWidth;
|
||||
msg->height = subsystem->cursorHeight;
|
||||
msg->scanline = msg->width * 4;
|
||||
|
||||
msg->pixels = (BYTE*) malloc(msg->scanline * msg->height);
|
||||
|
||||
if (!msg->pixels)
|
||||
return -1;
|
||||
|
||||
CopyMemory(msg->pixels, subsystem->cursorPixels, msg->scanline * msg->height);
|
||||
msg->premultiplied = TRUE;
|
||||
|
||||
MessageQueue_Post(MsgPipe->Out, NULL, msgId, (void*) msg, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage)
|
||||
{
|
||||
int x, y, n, k;
|
||||
@ -385,6 +434,8 @@ int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage)
|
||||
}
|
||||
|
||||
XFree(ci);
|
||||
|
||||
x11_shadow_pointer_alpha_update(subsystem);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@ -407,6 +458,8 @@ int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage)
|
||||
subsystem->cursorX = x;
|
||||
subsystem->cursorY = y;
|
||||
|
||||
x11_shadow_pointer_position_update(subsystem);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -633,7 +686,7 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
|
||||
(BYTE*) image->data, PIXEL_FORMAT_XRGB32,
|
||||
image->bytes_per_line, x, y, NULL);
|
||||
|
||||
x11_shadow_blend_cursor(subsystem);
|
||||
//x11_shadow_blend_cursor(subsystem);
|
||||
|
||||
count = ArrayList_Count(server->clients);
|
||||
|
||||
|
@ -736,10 +736,144 @@ int shadow_client_surface_update(rdpShadowClient* client, REGION16* region)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int shadow_client_convert_alpha_pointer_data(BYTE* pixels, BOOL premultiplied,
|
||||
UINT32 width, UINT32 height, POINTER_COLOR_UPDATE* pointerColor)
|
||||
{
|
||||
UINT32 x, y;
|
||||
BYTE* pSrc8;
|
||||
BYTE* pDst8;
|
||||
int xorStep;
|
||||
int andStep;
|
||||
UINT32 andBit;
|
||||
BYTE* andBits;
|
||||
UINT32 andPixel;
|
||||
BYTE A, R, G, B;
|
||||
|
||||
xorStep = (width * 3);
|
||||
xorStep += (xorStep % 2);
|
||||
|
||||
andStep = ((width + 7) / 8);
|
||||
andStep += (andStep % 2);
|
||||
|
||||
pointerColor->lengthXorMask = height * xorStep;
|
||||
pointerColor->xorMaskData = (BYTE*) calloc(1, pointerColor->lengthXorMask);
|
||||
|
||||
if (!pointerColor->xorMaskData)
|
||||
return -1;
|
||||
|
||||
pointerColor->lengthAndMask = height * andStep;
|
||||
pointerColor->andMaskData = (BYTE*) calloc(1, pointerColor->lengthAndMask);
|
||||
|
||||
if (!pointerColor->andMaskData)
|
||||
return -1;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
pSrc8 = &pixels[(width * 4) * (height - 1 - y)];
|
||||
pDst8 = &(pointerColor->xorMaskData[y * xorStep]);
|
||||
|
||||
andBit = 0x80;
|
||||
andBits = &(pointerColor->andMaskData[andStep * y]);
|
||||
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
B = *pSrc8++;
|
||||
G = *pSrc8++;
|
||||
R = *pSrc8++;
|
||||
A = *pSrc8++;
|
||||
|
||||
andPixel = 0;
|
||||
|
||||
if (A < 64)
|
||||
A = 0; /* pixel cannot be partially transparent */
|
||||
|
||||
if (!A)
|
||||
{
|
||||
/* transparent pixel: XOR = black, AND = 1 */
|
||||
andPixel = 1;
|
||||
B = G = R = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (premultiplied)
|
||||
{
|
||||
B = (B * 0xFF ) / A;
|
||||
G = (G * 0xFF ) / A;
|
||||
R = (R * 0xFF ) / A;
|
||||
}
|
||||
}
|
||||
|
||||
*pDst8++ = B;
|
||||
*pDst8++ = G;
|
||||
*pDst8++ = R;
|
||||
|
||||
if (andPixel) *andBits |= andBit;
|
||||
if (!(andBit >>= 1)) { andBits++; andBit = 0x80; }
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int shadow_client_subsystem_process_message(rdpShadowClient* client, wMessage* message)
|
||||
{
|
||||
rdpContext* context = (rdpContext*) client;
|
||||
rdpUpdate* update = context->update;
|
||||
|
||||
/* FIXME: the pointer updates appear to be broken when used with bulk compression and mstsc */
|
||||
|
||||
if (message->id == SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID)
|
||||
{
|
||||
POINTER_POSITION_UPDATE pointerPosition;
|
||||
SHADOW_MSG_OUT_POINTER_POSITION_UPDATE* msg = (SHADOW_MSG_OUT_POINTER_POSITION_UPDATE*) message->wParam;
|
||||
|
||||
pointerPosition.xPos = msg->xPos;
|
||||
pointerPosition.yPos = msg->yPos;
|
||||
|
||||
if (0)
|
||||
{
|
||||
IFCALL(update->pointer->PointerPosition, context, &pointerPosition);
|
||||
}
|
||||
|
||||
free(msg);
|
||||
}
|
||||
else if (message->id == SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID)
|
||||
{
|
||||
POINTER_NEW_UPDATE pointerNew;
|
||||
POINTER_COLOR_UPDATE* pointerColor;
|
||||
SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* msg = (SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE*) message->wParam;
|
||||
|
||||
ZeroMemory(&pointerNew, sizeof(POINTER_NEW_UPDATE));
|
||||
|
||||
pointerNew.xorBpp = 24;
|
||||
pointerColor = &(pointerNew.colorPtrAttr);
|
||||
|
||||
pointerColor->cacheIndex = 0;
|
||||
pointerColor->xPos = msg->xHot;
|
||||
pointerColor->yPos = msg->yHot;
|
||||
pointerColor->width = msg->width;
|
||||
pointerColor->height = msg->height;
|
||||
|
||||
shadow_client_convert_alpha_pointer_data(msg->pixels, msg->premultiplied,
|
||||
msg->width, msg->height, pointerColor);
|
||||
|
||||
if (0)
|
||||
{
|
||||
IFCALL(update->pointer->PointerNew, context, &pointerNew);
|
||||
}
|
||||
|
||||
free(msg->pixels);
|
||||
free(msg);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void* shadow_client_thread(rdpShadowClient* client)
|
||||
{
|
||||
DWORD status;
|
||||
DWORD nCount;
|
||||
wMessage message;
|
||||
HANDLE events[32];
|
||||
HANDLE StopEvent;
|
||||
HANDLE ClientEvent;
|
||||
@ -752,6 +886,7 @@ void* shadow_client_thread(rdpShadowClient* client)
|
||||
rdpShadowScreen* screen;
|
||||
rdpShadowEncoder* encoder;
|
||||
rdpShadowSubsystem* subsystem;
|
||||
wMessagePipe* MsgPipe = client->subsystem->MsgPipe;
|
||||
|
||||
server = client->server;
|
||||
screen = server->screen;
|
||||
@ -786,6 +921,7 @@ void* shadow_client_thread(rdpShadowClient* client)
|
||||
events[nCount++] = UpdateEvent;
|
||||
events[nCount++] = ClientEvent;
|
||||
events[nCount++] = ChannelEvent;
|
||||
events[nCount++] = MessageQueue_Event(MsgPipe->Out);
|
||||
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||
|
||||
@ -833,12 +969,23 @@ void* shadow_client_thread(rdpShadowClient* client)
|
||||
|
||||
if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
if (WTSVirtualChannelManagerCheckFileDescriptor(client->vcm) != TRUE)
|
||||
if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm))
|
||||
{
|
||||
WLog_ERR(TAG, "WTSVirtualChannelManagerCheckFileDescriptor failure");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (WaitForSingleObject(MessageQueue_Event(MsgPipe->Out), 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
if (MessageQueue_Peek(MsgPipe->Out, &message, TRUE))
|
||||
{
|
||||
if (message.id == WMQ_QUIT)
|
||||
break;
|
||||
|
||||
shadow_client_subsystem_process_message(client, &message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
peer->Disconnect(peer);
|
||||
|
@ -41,6 +41,28 @@ struct _SHADOW_MSG_IN_SUPPRESS_OUTPUT
|
||||
};
|
||||
typedef struct _SHADOW_MSG_IN_SUPPRESS_OUTPUT SHADOW_MSG_IN_SUPPRESS_OUTPUT;
|
||||
|
||||
#define SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID 2001
|
||||
#define SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID 2002
|
||||
|
||||
struct _SHADOW_MSG_OUT_POINTER_POSITION_UPDATE
|
||||
{
|
||||
UINT32 xPos;
|
||||
UINT32 yPos;
|
||||
};
|
||||
typedef struct _SHADOW_MSG_OUT_POINTER_POSITION_UPDATE SHADOW_MSG_OUT_POINTER_POSITION_UPDATE;
|
||||
|
||||
struct _SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE
|
||||
{
|
||||
UINT32 xHot;
|
||||
UINT32 yHot;
|
||||
UINT32 width;
|
||||
UINT32 height;
|
||||
BYTE* pixels;
|
||||
int scanline;
|
||||
BOOL premultiplied;
|
||||
};
|
||||
typedef struct _SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user