20 #include <freerdp/config.h>
23 #include <X11/Xatom.h>
24 #include <X11/Xutil.h>
26 #include <winpr/assert.h>
27 #include <winpr/wlog.h>
28 #include <winpr/print.h>
30 #include <freerdp/client/rail.h>
32 #include "xf_window.h"
36 #include <freerdp/log.h>
37 #define TAG CLIENT_TAG("x11")
39 static const char* error_code_names[] = {
"RAIL_EXEC_S_OK",
40 "RAIL_EXEC_E_HOOK_NOT_LOADED",
41 "RAIL_EXEC_E_DECODE_FAILED",
42 "RAIL_EXEC_E_NOT_IN_ALLOWLIST",
43 "RAIL_EXEC_E_FILE_NOT_FOUND",
45 "RAIL_EXEC_E_SESSION_LOCKED" };
47 #ifdef WITH_DEBUG_RAIL
48 static const char* movetype_names[] = {
49 "(invalid)",
"RAIL_WMSZ_LEFT",
"RAIL_WMSZ_RIGHT",
50 "RAIL_WMSZ_TOP",
"RAIL_WMSZ_TOPLEFT",
"RAIL_WMSZ_TOPRIGHT",
51 "RAIL_WMSZ_BOTTOM",
"RAIL_WMSZ_BOTTOMLEFT",
"RAIL_WMSZ_BOTTOMRIGHT",
52 "RAIL_WMSZ_MOVE",
"RAIL_WMSZ_KEYMOVE",
"RAIL_WMSZ_KEYSIZE"
61 typedef struct xf_rail_icon xfRailIcon;
63 struct xf_rail_icon_cache
67 UINT32 numCacheEntries;
75 } rail_paint_fn_arg_t;
77 void xf_rail_enable_remoteapp_mode(xfContext* xfc)
81 xfc->remote_app = TRUE;
82 xfc->drawable = xf_CreateDummyWindow(xfc);
83 xf_DestroyDesktopWindow(xfc, xfc->window);
88 void xf_rail_disable_remoteapp_mode(xfContext* xfc)
92 xfc->remote_app = FALSE;
93 xf_DestroyDummyWindow(xfc, xfc->drawable);
94 xf_create_window(xfc);
99 void xf_rail_send_activate(xfContext* xfc, Window xwindow, BOOL enabled)
102 xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, xwindow);
108 xf_SetWindowStyle(xfc, appWindow, appWindow->dwStyle, appWindow->dwExStyle);
110 WINPR_ASSERT(appWindow->windowId <= UINT32_MAX);
111 activate.windowId = (UINT32)appWindow->windowId;
112 activate.enabled = enabled;
113 xfc->rail->ClientActivate(xfc->rail, &activate);
116 BOOL xf_rail_send_client_system_command(xfContext* xfc, UINT64 windowId, UINT16 command)
119 WINPR_ASSERT(xfc->rail);
120 WINPR_ASSERT(xfc->rail->ClientSystemCommand);
121 if (windowId > UINT32_MAX)
125 const UINT rc = xfc->rail->ClientSystemCommand(xfc->rail, &syscommand);
126 return rc == CHANNEL_RC_OK;
135 void xf_rail_adjust_position(xfContext* xfc, xfAppWindow* appWindow)
139 if (!appWindow->is_mapped || appWindow->local_move.state != LMS_NOT_ACTIVE)
143 if (appWindow->x != appWindow->windowOffsetX || appWindow->y != appWindow->windowOffsetY ||
144 appWindow->width != (INT64)appWindow->windowWidth ||
145 appWindow->height != (INT64)appWindow->windowHeight)
147 WINPR_ASSERT(appWindow->windowId <= UINT32_MAX);
148 windowMove.windowId = (UINT32)appWindow->windowId;
153 windowMove.left = appWindow->x - appWindow->resizeMarginLeft;
154 windowMove.top = appWindow->y - appWindow->resizeMarginTop;
155 windowMove.right = appWindow->x + appWindow->width + appWindow->resizeMarginRight;
156 windowMove.bottom = appWindow->y + appWindow->height + appWindow->resizeMarginBottom;
157 xfc->rail->ClientWindowMove(xfc->rail, &windowMove);
161 void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow)
167 unsigned int mask = 0;
168 Window root_window = 0;
169 Window child_window = 0;
170 rdpInput* input = NULL;
174 input = xfc->common.context.input;
177 if ((appWindow->local_move.direction == _NET_WM_MOVERESIZE_MOVE_KEYBOARD) ||
178 (appWindow->local_move.direction == _NET_WM_MOVERESIZE_SIZE_KEYBOARD))
185 WINPR_ASSERT(appWindow->windowId <= UINT32_MAX);
186 windowMove.windowId = (UINT32)appWindow->windowId;
192 windowMove.left = appWindow->x - appWindow->resizeMarginLeft;
193 windowMove.top = appWindow->y - appWindow->resizeMarginTop;
195 appWindow->x + appWindow->width +
198 windowMove.bottom = appWindow->y + appWindow->height + appWindow->resizeMarginBottom;
199 xfc->rail->ClientWindowMove(xfc->rail, &windowMove);
205 XQueryPointer(xfc->display, appWindow->handle, &root_window, &child_window, &x, &y, &child_x,
209 if ((appWindow->local_move.direction != _NET_WM_MOVERESIZE_MOVE_KEYBOARD) &&
210 (appWindow->local_move.direction != _NET_WM_MOVERESIZE_SIZE_KEYBOARD))
212 freerdp_client_send_button_event(&xfc->common, FALSE, PTR_FLAGS_BUTTON1, x, y);
220 appWindow->windowOffsetX = appWindow->x;
221 appWindow->windowOffsetY = appWindow->y;
222 appWindow->windowWidth = appWindow->width;
223 appWindow->windowHeight = appWindow->height;
224 appWindow->local_move.state = LMS_TERMINATING;
227 BOOL xf_rail_paint_surface(xfContext* xfc, UINT64 windowId,
const RECTANGLE_16* rect)
229 xfAppWindow* appWindow = xf_rail_get_window(xfc, windowId);
236 const RECTANGLE_16 windowRect = { .left = MAX(appWindow->x, 0),
237 .top = MAX(appWindow->y, 0),
238 .right = MAX(appWindow->x + appWindow->width, 0),
239 .bottom = MAX(appWindow->y + appWindow->height, 0) };
241 REGION16 windowInvalidRegion = { 0 };
242 region16_init(&windowInvalidRegion);
243 region16_union_rect(&windowInvalidRegion, &windowInvalidRegion, &windowRect);
244 region16_intersect_rect(&windowInvalidRegion, &windowInvalidRegion, rect);
246 if (!region16_is_empty(&windowInvalidRegion))
248 const RECTANGLE_16* extents = region16_extents(&windowInvalidRegion);
249 const RECTANGLE_16 updateRect = { .left = extents->left - appWindow->x,
250 .top = extents->top - appWindow->y,
251 .right = extents->right - appWindow->x,
252 .bottom = extents->bottom - appWindow->y };
254 xf_UpdateWindowArea(xfc, appWindow, updateRect.left, updateRect.top,
255 updateRect.right - updateRect.left, updateRect.bottom - updateRect.top);
257 region16_uninit(&windowInvalidRegion);
261 static BOOL rail_paint_fn(
const void* pvkey,
void* value,
void* pvarg)
263 rail_paint_fn_arg_t* arg = pvarg;
267 const UINT64 key = *(
const UINT64*)pvkey;
268 return xf_rail_paint_surface(arg->xfc, key, arg->rect);
271 BOOL xf_rail_paint(xfContext* xfc,
const RECTANGLE_16* rect)
273 rail_paint_fn_arg_t arg = { .xfc = xfc, .rect = rect };
278 if (!xfc->railWindows)
281 return HashTable_Foreach(xfc->railWindows, rail_paint_fn, &arg);
284 #define window_state_log_style(log, windowState) \
285 window_state_log_style_int((log), (windowState), __FILE__, __func__, __LINE__)
286 static void window_state_log_style_int(wLog* log,
const WINDOW_STATE_ORDER* windowState,
287 const char* file,
const char* fkt,
size_t line)
289 const DWORD log_level = WLOG_DEBUG;
292 WINPR_ASSERT(windowState);
293 if (WLog_IsLevelActive(log, log_level))
295 char buffer1[128] = { 0 };
296 char buffer2[128] = { 0 };
298 window_styles_to_string(windowState->style, buffer1,
sizeof(buffer1));
299 window_styles_ex_to_string(windowState->extendedStyle, buffer2,
sizeof(buffer2));
300 WLog_PrintMessage(log, WLOG_MESSAGE_TEXT, log_level, line, file, fkt,
301 "windowStyle={%s, %s}", buffer1, buffer2);
307 static BOOL xf_rail_window_common(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
310 xfAppWindow* appWindow = NULL;
311 xfContext* xfc = (xfContext*)context;
312 UINT32 fieldFlags = orderInfo->fieldFlags;
313 BOOL position_or_size_updated = FALSE;
314 appWindow = xf_rail_get_window(xfc, orderInfo->windowId);
316 if (fieldFlags & WINDOW_ORDER_STATE_NEW)
319 appWindow = xf_rail_add_window(xfc, orderInfo->windowId, windowState->windowOffsetX,
320 windowState->windowOffsetY, windowState->windowWidth,
321 windowState->windowHeight, 0xFFFFFFFF);
326 appWindow->dwStyle = windowState->style;
327 appWindow->dwExStyle = windowState->extendedStyle;
328 window_state_log_style(xfc->log, windowState);
331 if (fieldFlags & WINDOW_ORDER_FIELD_TITLE)
340 cnv.b = windowState->titleInfo.string;
341 if (windowState->titleInfo.length == 0)
343 if (!(title = _strdup(
"")))
345 WLog_ERR(TAG,
"failed to duplicate empty window title string");
349 else if (!(title = ConvertWCharNToUtf8Alloc(
350 cnv.wc, windowState->titleInfo.length /
sizeof(WCHAR), NULL)))
352 WLog_ERR(TAG,
"failed to convert window title");
356 appWindow->title = title;
360 if (!(appWindow->title = _strdup(
"RdpRailWindow")))
361 WLog_ERR(TAG,
"failed to duplicate default window title string");
364 if (!appWindow->title)
370 xf_AppWindowInit(xfc, appWindow);
377 if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) ||
378 (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) ||
379 (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) ||
380 (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) ||
381 (fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) ||
382 (fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) ||
383 (fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY))
385 position_or_size_updated = TRUE;
390 if (fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET)
392 appWindow->windowOffsetX = windowState->windowOffsetX;
393 appWindow->windowOffsetY = windowState->windowOffsetY;
396 if (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)
398 appWindow->windowWidth = windowState->windowWidth;
399 appWindow->windowHeight = windowState->windowHeight;
402 if (fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_X)
404 appWindow->resizeMarginLeft = windowState->resizeMarginLeft;
405 appWindow->resizeMarginRight = windowState->resizeMarginRight;
408 if (fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_Y)
410 appWindow->resizeMarginTop = windowState->resizeMarginTop;
411 appWindow->resizeMarginBottom = windowState->resizeMarginBottom;
414 if (fieldFlags & WINDOW_ORDER_FIELD_OWNER)
416 appWindow->ownerWindowId = windowState->ownerWindowId;
419 if (fieldFlags & WINDOW_ORDER_FIELD_STYLE)
421 appWindow->dwStyle = windowState->style;
422 appWindow->dwExStyle = windowState->extendedStyle;
423 window_state_log_style(xfc->log, windowState);
426 if (fieldFlags & WINDOW_ORDER_FIELD_SHOW)
428 appWindow->showState = windowState->showState;
431 if (fieldFlags & WINDOW_ORDER_FIELD_TITLE)
440 cnv.b = windowState->titleInfo.string;
441 if (windowState->titleInfo.length == 0)
443 if (!(title = _strdup(
"")))
445 WLog_ERR(TAG,
"failed to duplicate empty window title string");
449 else if (!(title = ConvertWCharNToUtf8Alloc(
450 cnv.wc, windowState->titleInfo.length /
sizeof(WCHAR), NULL)))
452 WLog_ERR(TAG,
"failed to convert window title");
456 free(appWindow->title);
457 appWindow->title = title;
460 if (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
462 appWindow->clientOffsetX = windowState->clientOffsetX;
463 appWindow->clientOffsetY = windowState->clientOffsetY;
466 if (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
468 appWindow->clientAreaWidth = windowState->clientAreaWidth;
469 appWindow->clientAreaHeight = windowState->clientAreaHeight;
472 if (fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
474 appWindow->windowClientDeltaX = windowState->windowClientDeltaX;
475 appWindow->windowClientDeltaY = windowState->windowClientDeltaY;
478 if (fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS)
480 if (appWindow->windowRects)
482 free(appWindow->windowRects);
483 appWindow->windowRects = NULL;
486 appWindow->numWindowRects = windowState->numWindowRects;
488 if (appWindow->numWindowRects)
490 appWindow->windowRects =
493 if (!appWindow->windowRects)
496 CopyMemory(appWindow->windowRects, windowState->windowRects,
501 if (fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET)
503 appWindow->visibleOffsetX = windowState->visibleOffsetX;
504 appWindow->visibleOffsetY = windowState->visibleOffsetY;
507 if (fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
509 if (appWindow->visibilityRects)
511 free(appWindow->visibilityRects);
512 appWindow->visibilityRects = NULL;
515 appWindow->numVisibilityRects = windowState->numVisibilityRects;
517 if (appWindow->numVisibilityRects)
519 appWindow->visibilityRects =
522 if (!appWindow->visibilityRects)
525 CopyMemory(appWindow->visibilityRects, windowState->visibilityRects,
532 if (fieldFlags & WINDOW_ORDER_FIELD_STYLE)
536 if (fieldFlags & WINDOW_ORDER_FIELD_SHOW)
538 xf_ShowWindow(xfc, appWindow, appWindow->showState);
541 if (fieldFlags & WINDOW_ORDER_FIELD_TITLE)
543 if (appWindow->title)
544 xf_SetWindowText(xfc, appWindow, appWindow->title);
547 if (position_or_size_updated)
549 UINT32 visibilityRectsOffsetX =
550 (appWindow->visibleOffsetX -
551 (appWindow->clientOffsetX - appWindow->windowClientDeltaX));
552 UINT32 visibilityRectsOffsetY =
553 (appWindow->visibleOffsetY -
554 (appWindow->clientOffsetY - appWindow->windowClientDeltaY));
561 if (appWindow->rail_state != WINDOW_SHOW_MINIMIZED)
564 if (appWindow->x == (INT64)appWindow->windowOffsetX &&
565 appWindow->y == (INT64)appWindow->windowOffsetY &&
566 appWindow->width == (INT64)appWindow->windowWidth &&
567 appWindow->height == (INT64)appWindow->windowHeight)
569 xf_UpdateWindowArea(xfc, appWindow, 0, 0, appWindow->windowWidth,
570 appWindow->windowHeight);
574 xf_MoveWindow(xfc, appWindow, appWindow->windowOffsetX, appWindow->windowOffsetY,
575 appWindow->windowWidth, appWindow->windowHeight);
578 xf_SetWindowVisibilityRects(xfc, appWindow, visibilityRectsOffsetX,
579 visibilityRectsOffsetY, appWindow->visibilityRects,
580 appWindow->numVisibilityRects);
583 if (appWindow->rail_state == WINDOW_SHOW_MAXIMIZED)
585 xf_SendClientEvent(xfc, appWindow->handle, xfc->_NET_WM_STATE, 4, _NET_WM_STATE_ADD,
586 xfc->_NET_WM_STATE_MAXIMIZED_VERT, xfc->_NET_WM_STATE_MAXIMIZED_HORZ,
591 if ((fieldFlags & WINDOW_ORDER_STATE_NEW) == 0)
592 xf_SetWindowStyle(xfc, appWindow, appWindow->dwStyle, appWindow->dwExStyle);
602 static BOOL xf_rail_window_delete(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo)
604 xfContext* xfc = (xfContext*)context;
605 return xf_rail_del_window(xfc, orderInfo->windowId);
608 static xfRailIconCache* RailIconCache_New(rdpSettings* settings)
610 xfRailIconCache* cache = NULL;
611 cache = calloc(1,
sizeof(xfRailIconCache));
617 cache->numCacheEntries =
619 cache->entries = calloc(1ull * cache->numCaches * cache->numCacheEntries,
sizeof(xfRailIcon));
623 WLog_ERR(TAG,
"failed to allocate icon cache %" PRIu32
" x %" PRIu32
" entries",
624 cache->numCaches, cache->numCacheEntries);
632 static void RailIconCache_Free(xfRailIconCache* cache)
636 for (UINT32 i = 0; i < cache->numCaches * cache->numCacheEntries; i++)
638 free(cache->entries[i].data);
641 free(cache->scratch.data);
642 free(cache->entries);
647 static xfRailIcon* RailIconCache_Lookup(xfRailIconCache* cache, UINT8 cacheId, UINT16 cacheEntry)
659 return &cache->scratch;
661 if (cacheId >= cache->numCaches)
664 if (cacheEntry >= cache->numCacheEntries)
667 return &cache->entries[cache->numCacheEntries * cacheId + cacheEntry];
680 static BOOL convert_rail_icon(
const ICON_INFO* iconInfo, xfRailIcon* railIcon)
682 BYTE* argbPixels = NULL;
683 BYTE* nextPixel = NULL;
686 argbPixels = calloc(1ull * iconInfo->width * iconInfo->height, 4);
691 if (!freerdp_image_copy_from_icon_data(
692 argbPixels, PIXEL_FORMAT_ARGB32, 0, 0, 0, iconInfo->width, iconInfo->height,
693 iconInfo->bitsColor, iconInfo->cbBitsColor, iconInfo->bitsMask, iconInfo->cbBitsMask,
694 iconInfo->colorTable, iconInfo->cbColorTable, iconInfo->bpp))
697 nelements = 2 + iconInfo->width * iconInfo->height;
698 pixels = realloc(railIcon->data, nelements *
sizeof(
long));
703 railIcon->data = pixels;
704 railIcon->length = nelements;
705 pixels[0] = iconInfo->width;
706 pixels[1] = iconInfo->height;
707 nextPixel = argbPixels;
709 for (
int i = 2; i < nelements; i++)
711 pixels[i] = FreeRDPReadColor(nextPixel, PIXEL_FORMAT_BGRA32);
722 static void xf_rail_set_window_icon(xfContext* xfc, xfAppWindow* railWindow, xfRailIcon* icon,
727 LogTagAndXChangeProperty(TAG, xfc->display, railWindow->handle, xfc->_NET_WM_ICON, XA_CARDINAL,
728 32, replace ? PropModeReplace : PropModeAppend,
729 (
unsigned char*)icon->data, icon->length);
730 XFlush(xfc->display);
733 static BOOL xf_rail_window_icon(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
736 xfContext* xfc = (xfContext*)context;
737 xfAppWindow* railWindow = NULL;
738 xfRailIcon* icon = NULL;
739 BOOL replaceIcon = 0;
740 railWindow = xf_rail_get_window(xfc, orderInfo->windowId);
745 icon = RailIconCache_Lookup(xfc->railIconCache, windowIcon->iconInfo->cacheId,
746 windowIcon->iconInfo->cacheEntry);
750 WLog_WARN(TAG,
"failed to get icon from cache %02X:%04X", windowIcon->iconInfo->cacheId,
751 windowIcon->iconInfo->cacheEntry);
755 if (!convert_rail_icon(windowIcon->iconInfo, icon))
757 WLog_WARN(TAG,
"failed to convert icon for window %08X", orderInfo->windowId);
761 replaceIcon = !!(orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW);
762 xf_rail_set_window_icon(xfc, railWindow, icon, replaceIcon);
766 static BOOL xf_rail_window_cached_icon(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
769 xfContext* xfc = (xfContext*)context;
770 xfAppWindow* railWindow = NULL;
771 xfRailIcon* icon = NULL;
772 BOOL replaceIcon = 0;
773 railWindow = xf_rail_get_window(xfc, orderInfo->windowId);
778 icon = RailIconCache_Lookup(xfc->railIconCache, windowCachedIcon->cachedIcon.cacheId,
779 windowCachedIcon->cachedIcon.cacheEntry);
783 WLog_WARN(TAG,
"failed to get icon from cache %02X:%04X",
784 windowCachedIcon->cachedIcon.cacheId, windowCachedIcon->cachedIcon.cacheEntry);
788 replaceIcon = !!(orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW);
789 xf_rail_set_window_icon(xfc, railWindow, icon, replaceIcon);
793 static BOOL xf_rail_notify_icon_common(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
796 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION)
800 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP)
804 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP)
808 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE)
812 if (orderInfo->fieldFlags & WINDOW_ORDER_ICON)
816 if (orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON)
823 static BOOL xf_rail_notify_icon_create(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
826 return xf_rail_notify_icon_common(context, orderInfo, notifyIconState);
829 static BOOL xf_rail_notify_icon_update(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
832 return xf_rail_notify_icon_common(context, orderInfo, notifyIconState);
835 static BOOL xf_rail_notify_icon_delete(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo)
840 static BOOL xf_rail_monitored_desktop(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
846 static BOOL xf_rail_non_monitored_desktop(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo)
848 xfContext* xfc = (xfContext*)context;
849 xf_rail_disable_remoteapp_mode(xfc);
853 static void xf_rail_register_update_callbacks(rdpUpdate* update)
855 rdpWindowUpdate* window = update->window;
856 window->WindowCreate = xf_rail_window_common;
857 window->WindowUpdate = xf_rail_window_common;
858 window->WindowDelete = xf_rail_window_delete;
859 window->WindowIcon = xf_rail_window_icon;
860 window->WindowCachedIcon = xf_rail_window_cached_icon;
861 window->NotifyIconCreate = xf_rail_notify_icon_create;
862 window->NotifyIconUpdate = xf_rail_notify_icon_update;
863 window->NotifyIconDelete = xf_rail_notify_icon_delete;
864 window->MonitoredDesktop = xf_rail_monitored_desktop;
865 window->NonMonitoredDesktop = xf_rail_non_monitored_desktop;
875 static UINT xf_rail_server_execute_result(RailClientContext* context,
878 xfContext* xfc = NULL;
880 WINPR_ASSERT(context);
881 WINPR_ASSERT(execResult);
883 xfc = (xfContext*)context->custom;
886 if (execResult->execResult != RAIL_EXEC_S_OK)
888 WLog_ERR(TAG,
"RAIL exec error: execResult=%s NtError=0x%X\n",
889 error_code_names[execResult->execResult], execResult->rawResult);
890 freerdp_abort_connect_context(&xfc->common.context);
894 xf_rail_enable_remoteapp_mode(xfc);
897 return CHANNEL_RC_OK;
905 static UINT xf_rail_server_system_param(RailClientContext* context,
909 return CHANNEL_RC_OK;
917 static UINT xf_rail_server_handshake(RailClientContext* context,
920 return client_rail_server_start_cmd(context);
928 static UINT xf_rail_server_handshake_ex(RailClientContext* context,
931 return client_rail_server_start_cmd(context);
939 static UINT xf_rail_server_local_move_size(RailClientContext* context,
945 Window child_window = 0;
946 xfContext* xfc = (xfContext*)context->custom;
947 xfAppWindow* appWindow = xf_rail_get_window(xfc, localMoveSize->windowId);
950 return ERROR_INTERNAL_ERROR;
952 switch (localMoveSize->moveSizeType)
955 direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
956 x = localMoveSize->posX;
957 y = localMoveSize->posY;
960 case RAIL_WMSZ_RIGHT:
961 direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
962 x = localMoveSize->posX;
963 y = localMoveSize->posY;
967 direction = _NET_WM_MOVERESIZE_SIZE_TOP;
968 x = localMoveSize->posX;
969 y = localMoveSize->posY;
972 case RAIL_WMSZ_TOPLEFT:
973 direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
974 x = localMoveSize->posX;
975 y = localMoveSize->posY;
978 case RAIL_WMSZ_TOPRIGHT:
979 direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
980 x = localMoveSize->posX;
981 y = localMoveSize->posY;
984 case RAIL_WMSZ_BOTTOM:
985 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
986 x = localMoveSize->posX;
987 y = localMoveSize->posY;
990 case RAIL_WMSZ_BOTTOMLEFT:
991 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
992 x = localMoveSize->posX;
993 y = localMoveSize->posY;
996 case RAIL_WMSZ_BOTTOMRIGHT:
997 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
998 x = localMoveSize->posX;
999 y = localMoveSize->posY;
1002 case RAIL_WMSZ_MOVE:
1003 direction = _NET_WM_MOVERESIZE_MOVE;
1004 XTranslateCoordinates(xfc->display, appWindow->handle, RootWindowOfScreen(xfc->screen),
1005 localMoveSize->posX, localMoveSize->posY, &x, &y, &child_window);
1008 case RAIL_WMSZ_KEYMOVE:
1009 direction = _NET_WM_MOVERESIZE_MOVE_KEYBOARD;
1010 x = localMoveSize->posX;
1011 y = localMoveSize->posY;
1013 return CHANNEL_RC_OK;
1015 case RAIL_WMSZ_KEYSIZE:
1016 direction = _NET_WM_MOVERESIZE_SIZE_KEYBOARD;
1017 x = localMoveSize->posX;
1018 y = localMoveSize->posY;
1020 return CHANNEL_RC_OK;
1025 if (localMoveSize->isMoveSizeStart)
1026 xf_StartLocalMoveSize(xfc, appWindow, direction, x, y);
1028 xf_EndLocalMoveSize(xfc, appWindow);
1030 return CHANNEL_RC_OK;
1038 static UINT xf_rail_server_min_max_info(RailClientContext* context,
1041 xfContext* xfc = (xfContext*)context->custom;
1042 xfAppWindow* appWindow = xf_rail_get_window(xfc, minMaxInfo->windowId);
1046 xf_SetWindowMinMaxInfo(xfc, appWindow, minMaxInfo->maxWidth, minMaxInfo->maxHeight,
1047 minMaxInfo->maxPosX, minMaxInfo->maxPosY, minMaxInfo->minTrackWidth,
1048 minMaxInfo->minTrackHeight, minMaxInfo->maxTrackWidth,
1049 minMaxInfo->maxTrackHeight);
1052 return CHANNEL_RC_OK;
1060 static UINT xf_rail_server_language_bar_info(RailClientContext* context,
1063 return CHANNEL_RC_OK;
1071 static UINT xf_rail_server_get_appid_response(RailClientContext* context,
1074 return CHANNEL_RC_OK;
1077 static BOOL rail_window_key_equals(
const void* key1,
const void* key2)
1079 const UINT64* k1 = (
const UINT64*)key1;
1080 const UINT64* k2 = (
const UINT64*)key2;
1088 static UINT32 rail_window_key_hash(
const void* key)
1090 const UINT64* k1 = (
const UINT64*)key;
1094 static void rail_window_free(
void* value)
1096 xfAppWindow* appWindow = (xfAppWindow*)value;
1101 xf_DestroyWindow(appWindow->xfc, appWindow);
1104 int xf_rail_init(xfContext* xfc, RailClientContext* rail)
1106 rdpContext* context = (rdpContext*)xfc;
1112 xf_rail_register_update_callbacks(context->update);
1113 rail->custom = (
void*)xfc;
1114 rail->ServerExecuteResult = xf_rail_server_execute_result;
1115 rail->ServerSystemParam = xf_rail_server_system_param;
1116 rail->ServerHandshake = xf_rail_server_handshake;
1117 rail->ServerHandshakeEx = xf_rail_server_handshake_ex;
1118 rail->ServerLocalMoveSize = xf_rail_server_local_move_size;
1119 rail->ServerMinMaxInfo = xf_rail_server_min_max_info;
1120 rail->ServerLanguageBarInfo = xf_rail_server_language_bar_info;
1121 rail->ServerGetAppIdResponse = xf_rail_server_get_appid_response;
1122 xfc->railWindows = HashTable_New(TRUE);
1124 if (!xfc->railWindows)
1127 if (!HashTable_SetHashFunction(xfc->railWindows, rail_window_key_hash))
1130 wObject* obj = HashTable_KeyObject(xfc->railWindows);
1131 obj->fnObjectEquals = rail_window_key_equals;
1134 wObject* obj = HashTable_ValueObject(xfc->railWindows);
1135 obj->fnObjectFree = rail_window_free;
1137 xfc->railIconCache = RailIconCache_New(xfc->common.context.settings);
1139 if (!xfc->railIconCache)
1145 HashTable_Free(xfc->railWindows);
1149 int xf_rail_uninit(xfContext* xfc, RailClientContext* rail)
1155 xfc->rail->custom = NULL;
1159 if (xfc->railWindows)
1161 HashTable_Free(xfc->railWindows);
1162 xfc->railWindows = NULL;
1165 if (xfc->railIconCache)
1167 RailIconCache_Free(xfc->railIconCache);
1168 xfc->railIconCache = NULL;
1174 xfAppWindow* xf_rail_add_window(xfContext* xfc, UINT64
id, UINT32 x, UINT32 y, UINT32 width,
1175 UINT32 height, UINT32 surfaceId)
1177 xfAppWindow* appWindow = NULL;
1182 appWindow = (xfAppWindow*)calloc(1,
sizeof(xfAppWindow));
1187 appWindow->xfc = xfc;
1188 appWindow->windowId = id;
1189 appWindow->surfaceId = surfaceId;
1192 appWindow->width = width;
1193 appWindow->height = height;
1195 if (!xf_AppWindowCreate(xfc, appWindow))
1197 if (!HashTable_Insert(xfc->railWindows, &appWindow->windowId, (
void*)appWindow))
1201 rail_window_free(appWindow);
1205 BOOL xf_rail_del_window(xfContext* xfc, UINT64
id)
1210 if (!xfc->railWindows)
1213 return HashTable_Remove(xfc->railWindows, &
id);
1216 xfAppWindow* xf_rail_get_window(xfContext* xfc, UINT64
id)
1221 if (!xfc->railWindows)
1224 return HashTable_GetItemValue(xfc->railWindows, &
id);
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
This struct contains function pointer to initialize/free objects.