19 #include <freerdp/config.h>
21 #include <winpr/crt.h>
22 #include <freerdp/log.h>
23 #include <freerdp/client/rail.h>
24 #include <winpr/tchar.h>
25 #include <winpr/print.h>
29 #define TAG CLIENT_TAG("windows")
31 #define GET_X_LPARAM(lParam) ((UINT16)(lParam & 0xFFFF))
32 #define GET_Y_LPARAM(lParam) ((UINT16)((lParam >> 16) & 0xFFFF))
59 static const WINDOW_STYLE WINDOW_STYLES[] = { { WS_BORDER,
"WS_BORDER", FALSE },
60 { WS_CAPTION,
"WS_CAPTION", FALSE },
61 { WS_CHILD,
"WS_CHILD", FALSE },
62 { WS_CLIPCHILDREN,
"WS_CLIPCHILDREN", FALSE },
63 { WS_CLIPSIBLINGS,
"WS_CLIPSIBLINGS", FALSE },
64 { WS_DISABLED,
"WS_DISABLED", FALSE },
65 { WS_DLGFRAME,
"WS_DLGFRAME", FALSE },
66 { WS_GROUP,
"WS_GROUP", FALSE },
67 { WS_HSCROLL,
"WS_HSCROLL", FALSE },
68 { WS_ICONIC,
"WS_ICONIC", FALSE },
69 { WS_MAXIMIZE,
"WS_MAXIMIZE", FALSE },
70 { WS_MAXIMIZEBOX,
"WS_MAXIMIZEBOX", FALSE },
71 { WS_MINIMIZE,
"WS_MINIMIZE", FALSE },
72 { WS_MINIMIZEBOX,
"WS_MINIMIZEBOX", FALSE },
73 { WS_OVERLAPPED,
"WS_OVERLAPPED", FALSE },
74 { WS_OVERLAPPEDWINDOW,
"WS_OVERLAPPEDWINDOW", TRUE },
75 { WS_POPUP,
"WS_POPUP", FALSE },
76 { WS_POPUPWINDOW,
"WS_POPUPWINDOW", TRUE },
77 { WS_SIZEBOX,
"WS_SIZEBOX", FALSE },
78 { WS_SYSMENU,
"WS_SYSMENU", FALSE },
79 { WS_TABSTOP,
"WS_TABSTOP", FALSE },
80 { WS_THICKFRAME,
"WS_THICKFRAME", FALSE },
81 { WS_VISIBLE,
"WS_VISIBLE", FALSE } };
83 static const WINDOW_STYLE EXTENDED_WINDOW_STYLES[] = {
84 { WS_EX_ACCEPTFILES,
"WS_EX_ACCEPTFILES", FALSE },
85 { WS_EX_APPWINDOW,
"WS_EX_APPWINDOW", FALSE },
86 { WS_EX_CLIENTEDGE,
"WS_EX_CLIENTEDGE", FALSE },
87 { WS_EX_COMPOSITED,
"WS_EX_COMPOSITED", FALSE },
88 { WS_EX_CONTEXTHELP,
"WS_EX_CONTEXTHELP", FALSE },
89 { WS_EX_CONTROLPARENT,
"WS_EX_CONTROLPARENT", FALSE },
90 { WS_EX_DLGMODALFRAME,
"WS_EX_DLGMODALFRAME", FALSE },
91 { WS_EX_LAYERED,
"WS_EX_LAYERED", FALSE },
92 { WS_EX_LAYOUTRTL,
"WS_EX_LAYOUTRTL", FALSE },
93 { WS_EX_LEFT,
"WS_EX_LEFT", FALSE },
94 { WS_EX_LEFTSCROLLBAR,
"WS_EX_LEFTSCROLLBAR", FALSE },
95 { WS_EX_LTRREADING,
"WS_EX_LTRREADING", FALSE },
96 { WS_EX_MDICHILD,
"WS_EX_MDICHILD", FALSE },
97 { WS_EX_NOACTIVATE,
"WS_EX_NOACTIVATE", FALSE },
98 { WS_EX_NOINHERITLAYOUT,
"WS_EX_NOINHERITLAYOUT", FALSE },
99 { WS_EX_NOPARENTNOTIFY,
"WS_EX_NOPARENTNOTIFY", FALSE },
100 { WS_EX_OVERLAPPEDWINDOW,
"WS_EX_OVERLAPPEDWINDOW", TRUE },
101 { WS_EX_PALETTEWINDOW,
"WS_EX_PALETTEWINDOW", TRUE },
102 { WS_EX_RIGHT,
"WS_EX_RIGHT", FALSE },
103 { WS_EX_RIGHTSCROLLBAR,
"WS_EX_RIGHTSCROLLBAR", FALSE },
104 { WS_EX_RTLREADING,
"WS_EX_RTLREADING", FALSE },
105 { WS_EX_STATICEDGE,
"WS_EX_STATICEDGE", FALSE },
106 { WS_EX_TOOLWINDOW,
"WS_EX_TOOLWINDOW", FALSE },
107 { WS_EX_TOPMOST,
"WS_EX_TOPMOST", FALSE },
108 { WS_EX_TRANSPARENT,
"WS_EX_TRANSPARENT", FALSE },
109 { WS_EX_WINDOWEDGE,
"WS_EX_WINDOWEDGE", FALSE }
112 static void PrintWindowStyles(UINT32 style)
114 WLog_INFO(TAG,
"\tWindow Styles:\t{");
116 for (
size_t i = 0; i < ARRAYSIZE(WINDOW_STYLES); i++)
118 if (style & WINDOW_STYLES[i].style)
120 if (WINDOW_STYLES[i].multi)
122 if ((style & WINDOW_STYLES[i].style) != WINDOW_STYLES[i].style)
126 WLog_INFO(TAG,
"\t\t%s", WINDOW_STYLES[i].name);
131 static void PrintExtendedWindowStyles(UINT32 style)
133 WLog_INFO(TAG,
"\tExtended Window Styles:\t{");
135 for (
size_t i = 0; i < ARRAYSIZE(EXTENDED_WINDOW_STYLES); i++)
137 if (style & EXTENDED_WINDOW_STYLES[i].style)
139 if (EXTENDED_WINDOW_STYLES[i].multi)
141 if ((style & EXTENDED_WINDOW_STYLES[i].style) != EXTENDED_WINDOW_STYLES[i].style)
145 WLog_INFO(TAG,
"\t\t%s", EXTENDED_WINDOW_STYLES[i].name);
153 if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW)
154 WLog_INFO(TAG,
"WindowCreate: WindowId: 0x%08X", orderInfo->windowId);
156 WLog_INFO(TAG,
"WindowUpdate: WindowId: 0x%08X", orderInfo->windowId);
160 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER)
162 WLog_INFO(TAG,
"\tOwnerWindowId: 0x%08X", windowState->ownerWindowId);
165 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE)
167 WLog_INFO(TAG,
"\tStyle: 0x%08X ExtendedStyle: 0x%08X", windowState->style,
168 windowState->extendedStyle);
169 PrintWindowStyles(windowState->style);
170 PrintExtendedWindowStyles(windowState->extendedStyle);
173 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW)
175 WLog_INFO(TAG,
"\tShowState: %u", windowState->showState);
178 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE)
180 const WCHAR* str = (
const WCHAR*)windowState->titleInfo.string;
182 ConvertWCharNToUtf8Alloc(str, windowState->titleInfo.length /
sizeof(WCHAR), NULL);
183 WLog_INFO(TAG,
"\tTitleInfo: %s (length = %hu)", title, windowState->titleInfo.length);
187 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
189 WLog_INFO(TAG,
"\tClientOffsetX: %d ClientOffsetY: %d", windowState->clientOffsetX,
190 windowState->clientOffsetY);
193 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
195 WLog_INFO(TAG,
"\tClientAreaWidth: %u ClientAreaHeight: %u", windowState->clientAreaWidth,
196 windowState->clientAreaHeight);
199 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT)
201 WLog_INFO(TAG,
"\tRPContent: %u", windowState->RPContent);
204 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT)
206 WLog_INFO(TAG,
"\tRootParentHandle: 0x%08X", windowState->rootParentHandle);
209 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET)
211 WLog_INFO(TAG,
"\tWindowOffsetX: %d WindowOffsetY: %d", windowState->windowOffsetX,
212 windowState->windowOffsetY);
215 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
217 WLog_INFO(TAG,
"\tWindowClientDeltaX: %d WindowClientDeltaY: %d",
218 windowState->windowClientDeltaX, windowState->windowClientDeltaY);
221 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)
223 WLog_INFO(TAG,
"\tWindowWidth: %u WindowHeight: %u", windowState->windowWidth,
224 windowState->windowHeight);
227 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS)
230 WLog_INFO(TAG,
"\tnumWindowRects: %u", windowState->numWindowRects);
232 for (UINT32 index = 0; index < windowState->numWindowRects; index++)
234 rect = &windowState->windowRects[index];
235 WLog_INFO(TAG,
"\twindowRect[%u]: left: %hu top: %hu right: %hu bottom: %hu", index,
236 rect->left, rect->top, rect->right, rect->bottom);
240 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET)
242 WLog_INFO(TAG,
"\tvisibileOffsetX: %d visibleOffsetY: %d", windowState->visibleOffsetX,
243 windowState->visibleOffsetY);
246 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
249 WLog_INFO(TAG,
"\tnumVisibilityRects: %u", windowState->numVisibilityRects);
251 for (UINT32 index = 0; index < windowState->numVisibilityRects; index++)
253 rect = &windowState->visibilityRects[index];
254 WLog_INFO(TAG,
"\tvisibilityRect[%u]: left: %hu top: %hu right: %hu bottom: %hu", index,
255 rect->left, rect->top, rect->right, rect->bottom);
264 WLog_INFO(TAG,
"ICON_INFO");
266 WLog_INFO(TAG,
"\tbigIcon: %s",
267 (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ICON_BIG) ?
"true" :
"false");
268 WLog_INFO(TAG,
"\tcacheEntry; 0x%08X", iconInfo->cacheEntry);
269 WLog_INFO(TAG,
"\tcacheId: 0x%08X", iconInfo->cacheId);
270 WLog_INFO(TAG,
"\tbpp: %u", iconInfo->bpp);
271 WLog_INFO(TAG,
"\twidth: %u", iconInfo->width);
272 WLog_INFO(TAG,
"\theight: %u", iconInfo->height);
273 WLog_INFO(TAG,
"\tcbColorTable: %u", iconInfo->cbColorTable);
274 WLog_INFO(TAG,
"\tcbBitsMask: %u", iconInfo->cbBitsMask);
275 WLog_INFO(TAG,
"\tcbBitsColor: %u", iconInfo->cbBitsColor);
276 WLog_INFO(TAG,
"\tcolorTable: %p", (
void*)iconInfo->colorTable);
277 WLog_INFO(TAG,
"\tbitsMask: %p", (
void*)iconInfo->bitsMask);
278 WLog_INFO(TAG,
"\tbitsColor: %p", (
void*)iconInfo->bitsColor);
282 LRESULT CALLBACK wf_RailWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
292 wfContext* wfc = NULL;
293 rdpInput* input = NULL;
294 rdpContext* context = NULL;
295 wfRailWindow* railWindow;
296 railWindow = (wfRailWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
299 wfc = railWindow->wfc;
302 context = (rdpContext*)wfc;
305 input = context->input;
314 hDC = BeginPaint(hWnd, &ps);
317 width = ps.rcPaint.right - ps.rcPaint.left + 1;
318 height = ps.rcPaint.bottom - ps.rcPaint.top + 1;
319 BitBlt(hDC, x, y, width, height, wfc->primary->hdc, railWindow->x + x,
320 railWindow->y + y, SRCCOPY);
327 if (!railWindow || !input)
330 xPos = GET_X_LPARAM(lParam) + railWindow->x;
331 yPos = GET_Y_LPARAM(lParam) + railWindow->y;
332 inputFlags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1;
335 input->MouseEvent(input, inputFlags, xPos, yPos);
341 if (!railWindow || !input)
344 xPos = GET_X_LPARAM(lParam) + railWindow->x;
345 yPos = GET_Y_LPARAM(lParam) + railWindow->y;
346 inputFlags = PTR_FLAGS_BUTTON1;
349 input->MouseEvent(input, inputFlags, xPos, yPos);
355 if (!railWindow || !input)
358 xPos = GET_X_LPARAM(lParam) + railWindow->x;
359 yPos = GET_Y_LPARAM(lParam) + railWindow->y;
360 inputFlags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2;
363 input->MouseEvent(input, inputFlags, xPos, yPos);
369 if (!railWindow || !input)
372 xPos = GET_X_LPARAM(lParam) + railWindow->x;
373 yPos = GET_Y_LPARAM(lParam) + railWindow->y;
374 inputFlags = PTR_FLAGS_BUTTON2;
377 input->MouseEvent(input, inputFlags, xPos, yPos);
383 if (!railWindow || !input)
386 xPos = GET_X_LPARAM(lParam) + railWindow->x;
387 yPos = GET_Y_LPARAM(lParam) + railWindow->y;
388 inputFlags = PTR_FLAGS_MOVE;
391 input->MouseEvent(input, inputFlags, xPos, yPos);
407 return DefWindowProc(hWnd, msg, wParam, lParam);
413 #define RAIL_DISABLED_WINDOW_STYLES \
414 (WS_BORDER | WS_THICKFRAME | WS_DLGFRAME | WS_CAPTION | WS_OVERLAPPED | WS_VSCROLL | \
415 WS_HSCROLL | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
416 #define RAIL_DISABLED_EXTENDED_WINDOW_STYLES \
417 (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE | WS_EX_WINDOWEDGE)
419 static BOOL wf_rail_window_common(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
422 wfRailWindow* railWindow = NULL;
423 wfContext* wfc = (wfContext*)context;
424 RailClientContext* rail = wfc->rail;
425 UINT32 fieldFlags = orderInfo->fieldFlags;
426 PrintRailWindowState(orderInfo, windowState);
428 if (fieldFlags & WINDOW_ORDER_STATE_NEW)
432 WCHAR* titleW = NULL;
433 WNDCLASSEX wndClassEx = { 0 };
434 railWindow = (wfRailWindow*)calloc(1,
sizeof(wfRailWindow));
439 railWindow->wfc = wfc;
440 railWindow->dwStyle = windowState->style;
441 railWindow->dwStyle &= ~RAIL_DISABLED_WINDOW_STYLES;
442 railWindow->dwExStyle = windowState->extendedStyle;
443 railWindow->dwExStyle &= ~RAIL_DISABLED_EXTENDED_WINDOW_STYLES;
444 railWindow->x = windowState->windowOffsetX;
445 railWindow->y = windowState->windowOffsetY;
446 railWindow->width = windowState->windowWidth;
447 railWindow->height = windowState->windowHeight;
449 if (fieldFlags & WINDOW_ORDER_FIELD_TITLE)
451 const WCHAR* str = (
const WCHAR*)windowState->titleInfo.string;
454 if (windowState->titleInfo.length == 0)
456 if (!(title = _strdup(
"")))
458 WLog_ERR(TAG,
"failed to duplicate empty window title string");
462 else if (!(title = ConvertWCharNToUtf8Alloc(
463 str, windowState->titleInfo.length /
sizeof(WCHAR), NULL)))
465 WLog_ERR(TAG,
"failed to convert window title");
469 railWindow->title = title;
473 if (!(railWindow->title = _strdup(
"RdpRailWindow")))
474 WLog_ERR(TAG,
"failed to duplicate default window title string");
477 if (!railWindow->title)
483 titleW = ConvertUtf8ToWCharAlloc(railWindow->title, NULL);
484 hInstance = GetModuleHandle(NULL);
486 wndClassEx.cbSize =
sizeof(WNDCLASSEX);
487 wndClassEx.style = 0;
488 wndClassEx.lpfnWndProc = wf_RailWndProc;
489 wndClassEx.cbClsExtra = 0;
490 wndClassEx.cbWndExtra = 0;
491 wndClassEx.hIcon = NULL;
492 wndClassEx.hCursor = NULL;
493 wndClassEx.hbrBackground = NULL;
494 wndClassEx.lpszMenuName = NULL;
495 wndClassEx.lpszClassName = _T(
"RdpRailWindow");
496 wndClassEx.hInstance = hInstance;
497 wndClassEx.hIconSm = NULL;
498 RegisterClassEx(&wndClassEx);
499 railWindow->hWnd = CreateWindowExW(railWindow->dwExStyle,
513 if (!railWindow->hWnd)
516 free(railWindow->title);
518 WLog_ERR(TAG,
"CreateWindowExW failed with error %" PRIu32
"", GetLastError());
522 SetWindowLongPtr(railWindow->hWnd, GWLP_USERDATA, (LONG_PTR)railWindow);
523 rc = HashTable_Insert(wfc->railWindows, (
void*)(UINT_PTR)orderInfo->windowId,
526 UpdateWindow(railWindow->hWnd);
531 railWindow = (wfRailWindow*)HashTable_GetItemValue(wfc->railWindows,
532 (
void*)(UINT_PTR)orderInfo->windowId);
538 if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) || (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE))
540 if (fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET)
542 railWindow->x = windowState->windowOffsetX;
543 railWindow->y = windowState->windowOffsetY;
546 if (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)
548 railWindow->width = windowState->windowWidth;
549 railWindow->height = windowState->windowHeight;
552 SetWindowPos(railWindow->hWnd, NULL, railWindow->x, railWindow->y, railWindow->width,
553 railWindow->height, 0);
556 if (fieldFlags & WINDOW_ORDER_FIELD_OWNER)
560 if (fieldFlags & WINDOW_ORDER_FIELD_STYLE)
562 railWindow->dwStyle = windowState->style;
563 railWindow->dwStyle &= ~RAIL_DISABLED_WINDOW_STYLES;
564 railWindow->dwExStyle = windowState->extendedStyle;
565 railWindow->dwExStyle &= ~RAIL_DISABLED_EXTENDED_WINDOW_STYLES;
566 SetWindowLongPtr(railWindow->hWnd, GWL_STYLE, (LONG)railWindow->dwStyle);
567 SetWindowLongPtr(railWindow->hWnd, GWL_EXSTYLE, (LONG)railWindow->dwExStyle);
570 if (fieldFlags & WINDOW_ORDER_FIELD_SHOW)
572 ShowWindow(railWindow->hWnd, windowState->showState);
575 if (fieldFlags & WINDOW_ORDER_FIELD_TITLE)
577 const WCHAR* str = (
const WCHAR*)windowState->titleInfo.string;
580 if (windowState->titleInfo.length == 0)
582 if (!(title = _strdup(
"")))
584 WLog_ERR(TAG,
"failed to duplicate empty window title string");
588 else if (!(title = ConvertWCharNToUtf8Alloc(
589 str, windowState->titleInfo.length /
sizeof(WCHAR), NULL)))
591 WLog_ERR(TAG,
"failed to convert window title");
595 free(railWindow->title);
596 railWindow->title = title;
597 SetWindowTextW(railWindow->hWnd, str);
600 if (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
604 if (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
608 if (fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
612 if (fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT)
616 if (fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT)
620 if (fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS)
626 if (windowState->numWindowRects > 0)
628 rect = &(windowState->windowRects[0]);
629 hWndRects = CreateRectRgn(rect->left, rect->top, rect->right, rect->bottom);
631 for (UINT32 index = 1; index < windowState->numWindowRects; index++)
633 rect = &(windowState->windowRects[index]);
634 hWndRect = CreateRectRgn(rect->left, rect->top, rect->right, rect->bottom);
635 CombineRgn(hWndRects, hWndRects, hWndRect, RGN_OR);
636 DeleteObject(hWndRect);
639 SetWindowRgn(railWindow->hWnd, hWndRects, TRUE);
640 DeleteObject(hWndRects);
644 if (fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET)
648 if (fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
652 UpdateWindow(railWindow->hWnd);
656 static BOOL wf_rail_window_delete(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo)
658 wfRailWindow* railWindow = NULL;
659 wfContext* wfc = (wfContext*)context;
660 RailClientContext* rail = wfc->rail;
661 WLog_DBG(TAG,
"RailWindowDelete");
662 railWindow = (wfRailWindow*)HashTable_GetItemValue(wfc->railWindows,
663 (
void*)(UINT_PTR)orderInfo->windowId);
668 HashTable_Remove(wfc->railWindows, (
void*)(UINT_PTR)orderInfo->windowId);
669 DestroyWindow(railWindow->hWnd);
674 static BOOL wf_rail_window_icon(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
683 ICONINFO iconInfo = { 0 };
685 wfRailWindow* railWindow;
687 wfContext* wfc = (wfContext*)context;
688 RailClientContext* rail = wfc->rail;
689 WLog_DBG(TAG,
"RailWindowIcon");
690 PrintRailIconInfo(orderInfo, windowIcon->iconInfo);
691 railWindow = (wfRailWindow*)HashTable_GetItemValue(wfc->railWindows,
692 (
void*)(UINT_PTR)orderInfo->windowId);
697 bigIcon = (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ICON_BIG) ? TRUE : FALSE;
698 hDC = GetDC(railWindow->hWnd);
699 iconInfo.fIcon = TRUE;
700 iconInfo.xHotspot = 0;
701 iconInfo.yHotspot = 0;
703 bitmapInfoHeader = &(bitmapInfo.bmiHeader);
704 bpp = windowIcon->iconInfo->bpp;
705 width = windowIcon->iconInfo->width;
706 height = windowIcon->iconInfo->height;
708 bitmapInfoHeader->biWidth = width;
709 bitmapInfoHeader->biHeight = height;
710 bitmapInfoHeader->biPlanes = 1;
711 bitmapInfoHeader->biBitCount = bpp;
712 bitmapInfoHeader->biCompression = 0;
713 bitmapInfoHeader->biSizeImage = height * width * ((bpp + 7) / 8);
714 bitmapInfoHeader->biXPelsPerMeter = width;
715 bitmapInfoHeader->biYPelsPerMeter = height;
716 bitmapInfoHeader->biClrUsed = 0;
717 bitmapInfoHeader->biClrImportant = 0;
718 iconInfo.hbmMask = CreateDIBitmap(hDC, bitmapInfoHeader, CBM_INIT,
719 windowIcon->iconInfo->bitsMask, &bitmapInfo, DIB_RGB_COLORS);
721 CreateDIBitmap(hDC, bitmapInfoHeader, CBM_INIT, windowIcon->iconInfo->bitsColor,
722 &bitmapInfo, DIB_RGB_COLORS);
723 hIcon = CreateIconIndirect(&iconInfo);
729 wParam = (WPARAM)bigIcon ? ICON_BIG : ICON_SMALL;
730 lParam = (LPARAM)hIcon;
731 SendMessage(railWindow->hWnd, WM_SETICON, wParam, lParam);
734 ReleaseDC(NULL, hDC);
736 if (windowIcon->iconInfo->cacheEntry != 0xFFFF)
744 static BOOL wf_rail_window_cached_icon(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
747 WLog_DBG(TAG,
"RailWindowCachedIcon");
751 static void wf_rail_notify_icon_common(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
754 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION)
758 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP)
762 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP)
766 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE)
770 if (orderInfo->fieldFlags & WINDOW_ORDER_ICON)
772 const ICON_INFO* iconInfo = &(notifyIconState->icon);
773 PrintRailIconInfo(orderInfo, iconInfo);
776 if (orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON)
781 static BOOL wf_rail_notify_icon_create(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
784 wfContext* wfc = (wfContext*)context;
785 RailClientContext* rail = wfc->rail;
786 WLog_DBG(TAG,
"RailNotifyIconCreate");
787 wf_rail_notify_icon_common(context, orderInfo, notifyIconState);
791 static BOOL wf_rail_notify_icon_update(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
794 wfContext* wfc = (wfContext*)context;
795 RailClientContext* rail = wfc->rail;
796 WLog_DBG(TAG,
"RailNotifyIconUpdate");
797 wf_rail_notify_icon_common(context, orderInfo, notifyIconState);
801 static BOOL wf_rail_notify_icon_delete(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo)
803 wfContext* wfc = (wfContext*)context;
804 RailClientContext* rail = wfc->rail;
805 WLog_DBG(TAG,
"RailNotifyIconDelete");
809 static BOOL wf_rail_monitored_desktop(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
812 wfContext* wfc = (wfContext*)context;
813 RailClientContext* rail = wfc->rail;
814 WLog_DBG(TAG,
"RailMonitorDesktop");
818 static BOOL wf_rail_non_monitored_desktop(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo)
820 wfContext* wfc = (wfContext*)context;
821 RailClientContext* rail = wfc->rail;
822 WLog_DBG(TAG,
"RailNonMonitorDesktop");
826 void wf_rail_register_update_callbacks(rdpUpdate* update)
828 rdpWindowUpdate* window = update->window;
829 window->WindowCreate = wf_rail_window_common;
830 window->WindowUpdate = wf_rail_window_common;
831 window->WindowDelete = wf_rail_window_delete;
832 window->WindowIcon = wf_rail_window_icon;
833 window->WindowCachedIcon = wf_rail_window_cached_icon;
834 window->NotifyIconCreate = wf_rail_notify_icon_create;
835 window->NotifyIconUpdate = wf_rail_notify_icon_update;
836 window->NotifyIconDelete = wf_rail_notify_icon_delete;
837 window->MonitoredDesktop = wf_rail_monitored_desktop;
838 window->NonMonitoredDesktop = wf_rail_non_monitored_desktop;
848 static UINT wf_rail_server_execute_result(RailClientContext* context,
851 WLog_DBG(TAG,
"RailServerExecuteResult: 0x%08X", execResult->rawResult);
852 return CHANNEL_RC_OK;
860 static UINT wf_rail_server_system_param(RailClientContext* context,
863 return CHANNEL_RC_OK;
871 static UINT wf_rail_server_handshake(RailClientContext* context,
874 return client_rail_server_start_cmd(context);
882 static UINT wf_rail_server_handshake_ex(RailClientContext* context,
885 return client_rail_server_start_cmd(context);
893 static UINT wf_rail_server_local_move_size(RailClientContext* context,
896 return CHANNEL_RC_OK;
904 static UINT wf_rail_server_min_max_info(RailClientContext* context,
907 return CHANNEL_RC_OK;
915 static UINT wf_rail_server_language_bar_info(RailClientContext* context,
918 return CHANNEL_RC_OK;
926 static UINT wf_rail_server_get_appid_response(RailClientContext* context,
929 return CHANNEL_RC_OK;
932 void wf_rail_invalidate_region(wfContext* wfc,
REGION16* invalidRegion)
936 ULONG_PTR* pKeys = NULL;
937 wfRailWindow* railWindow;
940 region16_init(&windowInvalidRegion);
941 size_t count = HashTable_GetKeys(wfc->railWindows, &pKeys);
943 for (
size_t index = 0; index < count; index++)
945 railWindow = (wfRailWindow*)HashTable_GetItemValue(wfc->railWindows, (
void*)pKeys[index]);
949 windowRect.left = railWindow->x;
950 windowRect.top = railWindow->y;
951 windowRect.right = railWindow->x + railWindow->width;
952 windowRect.bottom = railWindow->y + railWindow->height;
953 region16_clear(&windowInvalidRegion);
954 region16_intersect_rect(&windowInvalidRegion, invalidRegion, &windowRect);
956 if (!region16_is_empty(&windowInvalidRegion))
958 extents = region16_extents(&windowInvalidRegion);
959 updateRect.left = extents->left - railWindow->x;
960 updateRect.top = extents->top - railWindow->y;
961 updateRect.right = extents->right - railWindow->x;
962 updateRect.bottom = extents->bottom - railWindow->y;
963 InvalidateRect(railWindow->hWnd, &updateRect, FALSE);
968 region16_uninit(&windowInvalidRegion);
971 BOOL wf_rail_init(wfContext* wfc, RailClientContext* rail)
973 rdpContext* context = (rdpContext*)wfc;
975 rail->custom = (
void*)wfc;
976 rail->ServerExecuteResult = wf_rail_server_execute_result;
977 rail->ServerSystemParam = wf_rail_server_system_param;
978 rail->ServerHandshake = wf_rail_server_handshake;
979 rail->ServerHandshakeEx = wf_rail_server_handshake_ex;
980 rail->ServerLocalMoveSize = wf_rail_server_local_move_size;
981 rail->ServerMinMaxInfo = wf_rail_server_min_max_info;
982 rail->ServerLanguageBarInfo = wf_rail_server_language_bar_info;
983 rail->ServerGetAppIdResponse = wf_rail_server_get_appid_response;
984 wf_rail_register_update_callbacks(context->update);
985 wfc->railWindows = HashTable_New(TRUE);
986 return (wfc->railWindows != NULL);
989 void wf_rail_uninit(wfContext* wfc, RailClientContext* rail)
993 HashTable_Free(wfc->railWindows);