wfreerdp: partial RemoteApp support
This commit is contained in:
parent
5df3e2368d
commit
55ea4caf11
@ -405,7 +405,7 @@ BOOL wf_post_connect(freerdp* instance)
|
||||
wfc->hwnd = CreateWindowEx((DWORD) NULL, wfc->wndClassName, lpWindowName, dwStyle,
|
||||
0, 0, 0, 0, wfc->hWndParent, NULL, wfc->hInstance, NULL);
|
||||
|
||||
SetWindowLongPtr(wfc->hwnd, GWLP_USERDATA, (LONG_PTR) wfc);
|
||||
SetWindowLongPtr(wfc->hwnd, GWLP_USERDATA, (LONG_PTR) wfc);
|
||||
}
|
||||
|
||||
wf_resize_window(wfc);
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
#include <winpr/windows.h>
|
||||
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/gdi/gdi.h>
|
||||
@ -38,16 +40,17 @@
|
||||
#include <freerdp/codec/nsc.h>
|
||||
#include <freerdp/client/file.h>
|
||||
|
||||
typedef struct wf_context wfContext;
|
||||
|
||||
#include "wf_channels.h"
|
||||
#include "wf_floatbar.h"
|
||||
#include "wf_event.h"
|
||||
#include "wf_cliprdr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "wf_cliprdr.h"
|
||||
|
||||
// System menu constants
|
||||
#define SYSCOMMAND_ID_SMARTSIZING 1000
|
||||
|
||||
@ -140,8 +143,8 @@ struct wf_context
|
||||
FloatBar* floatbar;
|
||||
|
||||
RailClientContext* rail;
|
||||
wHashTable* railWindows;
|
||||
};
|
||||
typedef struct wf_context wfContext;
|
||||
|
||||
/**
|
||||
* Client Interface
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include "wf_rail.h"
|
||||
@ -276,110 +277,318 @@ static void PrintRailIconInfo(WINDOW_ORDER_INFO* orderInfo, ICON_INFO* iconInfo)
|
||||
fprintf(stderr, "}\n");
|
||||
}
|
||||
|
||||
LRESULT CALLBACK wf_RailWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
HDC hDC;
|
||||
int x, y;
|
||||
int width;
|
||||
int height;
|
||||
PAINTSTRUCT ps;
|
||||
wfContext* wfc = NULL;
|
||||
wfRailWindow* railWindow;
|
||||
|
||||
railWindow = (wfRailWindow*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
|
||||
|
||||
if (railWindow)
|
||||
wfc = railWindow->wfc;
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case WM_PAINT:
|
||||
{
|
||||
if (!wfc)
|
||||
return 0;
|
||||
|
||||
hDC = BeginPaint(hWnd, &ps);
|
||||
|
||||
x = ps.rcPaint.left;
|
||||
y = ps.rcPaint.top;
|
||||
width = ps.rcPaint.right - ps.rcPaint.left + 1;
|
||||
height = ps.rcPaint.bottom - ps.rcPaint.top + 1;
|
||||
|
||||
BitBlt(hDC, x, y, width, height, wfc->primary->hdc,
|
||||
railWindow->x + x, railWindow->y + y, SRCCOPY);
|
||||
|
||||
EndPaint(hWnd, &ps);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
DestroyWindow(hWnd);
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RAIL_DISABLED_WINDOW_STYLES (WS_BORDER | WS_THICKFRAME | WS_DLGFRAME | WS_CAPTION | WS_OVERLAPPED)
|
||||
#define RAIL_DISABLED_EXTENDED_WINDOW_STYLES (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE)
|
||||
|
||||
static void wf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* windowState)
|
||||
{
|
||||
wfRailWindow* railWindow = NULL;
|
||||
wfContext* wfc = (wfContext*) context;
|
||||
RailClientContext* rail = wfc->rail;
|
||||
UINT32 fieldFlags = orderInfo->fieldFlags;
|
||||
|
||||
PrintRailWindowState(orderInfo, windowState);
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW)
|
||||
if (fieldFlags & WINDOW_ORDER_STATE_NEW)
|
||||
{
|
||||
HANDLE hInstance;
|
||||
WCHAR* titleW = NULL;
|
||||
WNDCLASSEX wndClassEx;
|
||||
|
||||
railWindow = (wfRailWindow*) calloc(1, sizeof(wfRailWindow));
|
||||
|
||||
if (!railWindow)
|
||||
return;
|
||||
|
||||
railWindow->wfc = wfc;
|
||||
|
||||
railWindow->dwStyle = windowState->style;
|
||||
railWindow->dwStyle &= ~RAIL_DISABLED_WINDOW_STYLES;
|
||||
railWindow->dwExStyle = windowState->extendedStyle;
|
||||
railWindow->dwExStyle &= ~RAIL_DISABLED_EXTENDED_WINDOW_STYLES;
|
||||
|
||||
railWindow->x = windowState->windowOffsetX;
|
||||
railWindow->y = windowState->windowOffsetY;
|
||||
railWindow->width = windowState->windowWidth;
|
||||
railWindow->height = windowState->windowHeight;
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_TITLE)
|
||||
{
|
||||
char* title = NULL;
|
||||
|
||||
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string,
|
||||
windowState->titleInfo.length / 2, &title, 0, NULL, NULL);
|
||||
|
||||
railWindow->title = title;
|
||||
}
|
||||
else
|
||||
{
|
||||
railWindow->title = _strdup("RdpRailWindow");
|
||||
}
|
||||
|
||||
ConvertToUnicode(CP_UTF8, 0, railWindow->title, -1, &titleW, 0);
|
||||
|
||||
hInstance = GetModuleHandle(NULL);
|
||||
|
||||
ZeroMemory(&wndClassEx, sizeof(WNDCLASSEX));
|
||||
wndClassEx.cbSize = sizeof(WNDCLASSEX);
|
||||
wndClassEx.style = 0;
|
||||
wndClassEx.lpfnWndProc = wf_RailWndProc;
|
||||
wndClassEx.cbClsExtra = 0;
|
||||
wndClassEx.cbWndExtra = 0;
|
||||
wndClassEx.hIcon = NULL;
|
||||
wndClassEx.hCursor = NULL;
|
||||
wndClassEx.hbrBackground = NULL;
|
||||
wndClassEx.lpszMenuName = NULL;
|
||||
wndClassEx.lpszClassName = _T("RdpRailWindow");
|
||||
wndClassEx.hInstance = hInstance;
|
||||
wndClassEx.hIconSm = NULL;
|
||||
|
||||
RegisterClassEx(&wndClassEx);
|
||||
|
||||
railWindow->hWnd = CreateWindowExW(
|
||||
railWindow->dwExStyle, /* dwExStyle */
|
||||
_T("RdpRailWindow"), /* lpClassName */
|
||||
titleW, /* lpWindowName */
|
||||
railWindow->dwStyle, /* dwStyle */
|
||||
railWindow->x, /* x */
|
||||
railWindow->y, /* y */
|
||||
railWindow->width, /* nWidth */
|
||||
railWindow->height, /* nHeight */
|
||||
NULL, /* hWndParent */
|
||||
NULL, /* hMenu */
|
||||
hInstance, /* hInstance */
|
||||
NULL /* lpParam */
|
||||
);
|
||||
|
||||
SetWindowLongPtr(railWindow->hWnd, GWLP_USERDATA, (LONG_PTR) railWindow);
|
||||
|
||||
HashTable_Add(wfc->railWindows, (void*) (UINT_PTR) orderInfo->windowId, (void*) railWindow);
|
||||
|
||||
free(titleW);
|
||||
|
||||
UpdateWindow(railWindow->hWnd);
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
railWindow = (wfRailWindow*) HashTable_GetItemValue(wfc->railWindows,
|
||||
(void*) (UINT_PTR) orderInfo->windowId);
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET)
|
||||
if (!railWindow)
|
||||
return;
|
||||
|
||||
if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) ||
|
||||
(fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE))
|
||||
{
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET)
|
||||
{
|
||||
railWindow->x = windowState->windowOffsetX;
|
||||
railWindow->y = windowState->windowOffsetY;
|
||||
}
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)
|
||||
{
|
||||
railWindow->width = windowState->windowWidth;
|
||||
railWindow->height = windowState->windowHeight;
|
||||
}
|
||||
|
||||
SetWindowPos(railWindow->hWnd, NULL,
|
||||
railWindow->x,
|
||||
railWindow->y,
|
||||
railWindow->width,
|
||||
railWindow->height,
|
||||
0);
|
||||
}
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_OWNER)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_STYLE)
|
||||
{
|
||||
|
||||
railWindow->dwStyle = windowState->style;
|
||||
railWindow->dwStyle &= ~RAIL_DISABLED_WINDOW_STYLES;
|
||||
railWindow->dwExStyle = windowState->extendedStyle;
|
||||
railWindow->dwExStyle &= ~RAIL_DISABLED_EXTENDED_WINDOW_STYLES;
|
||||
|
||||
SetWindowLongPtr(railWindow->hWnd, GWL_STYLE, (LONG) railWindow->dwStyle);
|
||||
SetWindowLongPtr(railWindow->hWnd, GWL_EXSTYLE, (LONG) railWindow->dwExStyle);
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER)
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_SHOW)
|
||||
{
|
||||
|
||||
ShowWindow(railWindow->hWnd, windowState->showState);
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE)
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_TITLE)
|
||||
{
|
||||
char* title = NULL;
|
||||
WCHAR* titleW = NULL;
|
||||
|
||||
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string,
|
||||
windowState->titleInfo.length / 2, &title, 0, NULL, NULL);
|
||||
windowState->titleInfo.length / 2, &title, 0, NULL, NULL);
|
||||
|
||||
free(title);
|
||||
free(railWindow->title);
|
||||
railWindow->title = title;
|
||||
|
||||
ConvertToUnicode(CP_UTF8, 0, railWindow->title, -1, &titleW, 0);
|
||||
|
||||
SetWindowTextW(railWindow->hWnd, titleW);
|
||||
|
||||
free(titleW);
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT)
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT)
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS)
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS)
|
||||
{
|
||||
UINT32 index;
|
||||
HRGN hWndRect;
|
||||
HRGN hWndRects;
|
||||
RECTANGLE_16* rect;
|
||||
|
||||
if (windowState->numWindowRects > 0)
|
||||
{
|
||||
rect = &(windowState->windowRects[0]);
|
||||
hWndRects = CreateRectRgn(rect->left, rect->top, rect->right, rect->bottom);
|
||||
|
||||
for (index = 1; index < windowState->numWindowRects; index++)
|
||||
{
|
||||
rect = &(windowState->windowRects[index]);
|
||||
hWndRect = CreateRectRgn(rect->left, rect->top, rect->right, rect->bottom);
|
||||
CombineRgn(hWndRects, hWndRects, hWndRect, RGN_OR);
|
||||
DeleteObject(hWndRect);
|
||||
}
|
||||
|
||||
SetWindowRgn(railWindow->hWnd, hWndRects, TRUE);
|
||||
DeleteObject(hWndRects);
|
||||
}
|
||||
}
|
||||
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET)
|
||||
if (fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
|
||||
{
|
||||
|
||||
}
|
||||
UpdateWindow(railWindow->hWnd);
|
||||
}
|
||||
|
||||
static void wf_rail_window_delete(rdpContext* context, WINDOW_ORDER_INFO* orderInfo)
|
||||
{
|
||||
wfRailWindow* railWindow = NULL;
|
||||
wfContext* wfc = (wfContext*) context;
|
||||
RailClientContext* rail = wfc->rail;
|
||||
|
||||
fprintf(stderr, "RailWindowDelete\n");
|
||||
|
||||
railWindow = (wfRailWindow*) HashTable_GetItemValue(wfc->railWindows,
|
||||
(void*) (UINT_PTR) orderInfo->windowId);
|
||||
|
||||
if (!railWindow)
|
||||
return;
|
||||
|
||||
HashTable_Remove(wfc->railWindows, (void*) (UINT_PTR) orderInfo->windowId);
|
||||
|
||||
DestroyWindow(railWindow->hWnd);
|
||||
|
||||
free(railWindow);
|
||||
}
|
||||
|
||||
static void wf_rail_window_icon(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_ICON_ORDER* windowIcon)
|
||||
{
|
||||
HDC hDC;
|
||||
int bpp;
|
||||
int width;
|
||||
int height;
|
||||
HICON hIcon;
|
||||
BOOL bigIcon;
|
||||
ICON_INFO* iconInfo;
|
||||
ICONINFO iconInfo;
|
||||
BITMAPINFO bitmapInfo;
|
||||
wfRailWindow* railWindow;
|
||||
BITMAPINFOHEADER* bitmapInfoHeader;
|
||||
wfContext* wfc = (wfContext*) context;
|
||||
RailClientContext* rail = wfc->rail;
|
||||
|
||||
@ -387,11 +596,65 @@ static void wf_rail_window_icon(rdpContext* context, WINDOW_ORDER_INFO* orderInf
|
||||
|
||||
PrintRailIconInfo(orderInfo, windowIcon->iconInfo);
|
||||
|
||||
iconInfo = windowIcon->iconInfo;
|
||||
railWindow = (wfRailWindow*) HashTable_GetItemValue(wfc->railWindows,
|
||||
(void*) (UINT_PTR) orderInfo->windowId);
|
||||
|
||||
if (!railWindow)
|
||||
return;
|
||||
|
||||
bigIcon = (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ICON_BIG) ? TRUE : FALSE;
|
||||
|
||||
if (iconInfo->cacheEntry != 0xFFFF)
|
||||
hDC = GetDC(railWindow->hWnd);
|
||||
|
||||
iconInfo.fIcon = TRUE;
|
||||
iconInfo.xHotspot = 0;
|
||||
iconInfo.yHotspot = 0;
|
||||
|
||||
ZeroMemory(&bitmapInfo, sizeof(BITMAPINFO));
|
||||
bitmapInfoHeader = &(bitmapInfo.bmiHeader);
|
||||
|
||||
bpp = windowIcon->iconInfo->bpp;
|
||||
width = windowIcon->iconInfo->width;
|
||||
height = windowIcon->iconInfo->height;
|
||||
|
||||
bitmapInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
|
||||
bitmapInfoHeader->biWidth = width;
|
||||
bitmapInfoHeader->biHeight = height;
|
||||
bitmapInfoHeader->biPlanes = 1;
|
||||
bitmapInfoHeader->biBitCount = bpp;
|
||||
bitmapInfoHeader->biCompression = 0;
|
||||
bitmapInfoHeader->biSizeImage = height * width * ((bpp + 7) / 8);
|
||||
bitmapInfoHeader->biXPelsPerMeter = width;
|
||||
bitmapInfoHeader->biYPelsPerMeter = height;
|
||||
bitmapInfoHeader->biClrUsed = 0;
|
||||
bitmapInfoHeader->biClrImportant = 0;
|
||||
|
||||
iconInfo.hbmMask = CreateDIBitmap(hDC,
|
||||
bitmapInfoHeader, CBM_INIT,
|
||||
windowIcon->iconInfo->bitsMask,
|
||||
&bitmapInfo, DIB_RGB_COLORS);
|
||||
|
||||
iconInfo.hbmColor = CreateDIBitmap(hDC,
|
||||
bitmapInfoHeader, CBM_INIT,
|
||||
windowIcon->iconInfo->bitsColor,
|
||||
&bitmapInfo, DIB_RGB_COLORS);
|
||||
|
||||
hIcon = CreateIconIndirect(&iconInfo);
|
||||
|
||||
if (hIcon)
|
||||
{
|
||||
WPARAM wParam;
|
||||
LPARAM lParam;
|
||||
|
||||
wParam = (WPARAM) bigIcon ? ICON_BIG : ICON_SMALL;
|
||||
lParam = (LPARAM) hIcon;
|
||||
|
||||
SendMessage(railWindow->hWnd, WM_SETICON, wParam, lParam);
|
||||
}
|
||||
|
||||
ReleaseDC(NULL, hDC);
|
||||
|
||||
if (windowIcon->iconInfo->cacheEntry != 0xFFFF)
|
||||
{
|
||||
/* icon should be cached */
|
||||
}
|
||||
@ -602,6 +865,8 @@ static int wf_rail_server_get_appid_response(RailClientContext* context, RAIL_GE
|
||||
|
||||
void wf_rail_init(wfContext* wfc, RailClientContext* rail)
|
||||
{
|
||||
rdpContext* context = (rdpContext*) wfc;
|
||||
|
||||
wfc->rail = rail;
|
||||
rail->custom = (void*) wfc;
|
||||
|
||||
@ -613,10 +878,16 @@ void wf_rail_init(wfContext* wfc, RailClientContext* rail)
|
||||
rail->ServerMinMaxInfo = wf_rail_server_min_max_info;
|
||||
rail->ServerLanguageBarInfo = wf_rail_server_language_bar_info;
|
||||
rail->ServerGetAppIdResponse = wf_rail_server_get_appid_response;
|
||||
|
||||
wf_rail_register_update_callbacks(context->update);
|
||||
|
||||
wfc->railWindows = HashTable_New(TRUE);
|
||||
}
|
||||
|
||||
void wf_rail_uninit(wfContext* wfc, RailClientContext* rail)
|
||||
{
|
||||
wfc->rail = NULL;
|
||||
rail->custom = NULL;
|
||||
|
||||
HashTable_Free(wfc->railWindows);
|
||||
}
|
||||
|
@ -19,10 +19,28 @@
|
||||
#ifndef __WF_RAIL_H
|
||||
#define __WF_RAIL_H
|
||||
|
||||
typedef struct wf_rail_window wfRailWindow;
|
||||
|
||||
#include "wf_client.h"
|
||||
|
||||
#include <freerdp/client/rail.h>
|
||||
|
||||
struct wf_rail_window
|
||||
{
|
||||
wfContext* wfc;
|
||||
|
||||
HWND hWnd;
|
||||
|
||||
DWORD dwStyle;
|
||||
DWORD dwExStyle;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
char* title;
|
||||
};
|
||||
|
||||
void wf_rail_init(wfContext* wfc, RailClientContext* rail);
|
||||
void wf_rail_uninit(wfContext* wfc, RailClientContext* rail);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user