2011-08-16 08:22:00 +04:00
|
|
|
/**
|
2012-10-09 07:02:04 +04:00
|
|
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
2011-08-16 08:22:00 +04:00
|
|
|
* X11 RAIL
|
|
|
|
*
|
|
|
|
* Copyright 2011 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.
|
|
|
|
*/
|
|
|
|
|
2012-08-15 01:20:53 +04:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2011-10-27 21:29:16 +04:00
|
|
|
#include <X11/Xlib.h>
|
xfreerdp: set _NET_WM_ICON to RAIL app icon
Icons on X11 windows are configured using the _NET_WM_ICON property
described in Extended Window Manager Hints. Here we implement converison
from DIB bitmaps used by RAIL to the format expected by _NET_WM_ICON,
and actually set the icon for RAIL app windows.
Both DIB format and _NET_WM_ICON (or rather, Xlib) are weird. Let's
start with RAIL's format. That's the one used in BMP and ICO formats
on Windows. It has some strange properties but thankfully FreeRDP's
freerdp_image_copy() can handle most of them for us. (With an exception
of monochrome and 16-color formats that it does not support. Sorry, but
I'm too lazy to fix them. They are not seem to be used by any real
application either.) The one thing that it can't do is to apply the
alpha transparency bitmask so we have to do it manually. This instantly
reminds us that DIB format has HISTORY: it's vertically flipped and
each must be padded to 4 bytes. Both these quirks having reasonable
(for a certain definition of 'reason') explanations. Such is life.
(Also, 8-bit images require a color palette which we must fill in.)
So okay, now comes _NET_WM_ICON. It is more sane (or rather, easier to
deal with). The bitmap is represented with a tiny [width, height] header
followed by an array of pixels in ARGB format. There is no padding, no
weird color formats. But here's a catch: you can't simply take the
output of freerdp_image_copy() and cast to (unsigned char*) of colors.
We have to allocate an array of C's longs and copy the pixels there,
because that's what Xlib expects (and this is mentioned in the spec).
Simply casting an array of bytes causes crashes on 64-bit systems.
So don't try to cheat or "optimize" and read the docs, kids.
Note that XFlush() call after XChangeProperty(). It's there because it
seems to helps see the icon quicker with Unity on Ubuntu 14.04. I don't
know why. (And Unity does not support _NET_WM_ICON officially. But it
sorta kinda works sometimes.)
Oh, and while we're here, delete some old, unused, and commented out
code that was setting window icons in the past. It's not needed anymore.
2018-11-10 15:43:36 +03:00
|
|
|
#include <X11/Xatom.h>
|
2011-10-27 21:29:16 +04:00
|
|
|
#include <X11/Xutil.h>
|
|
|
|
|
2014-08-18 19:23:13 +04:00
|
|
|
#include <winpr/wlog.h>
|
2012-12-14 08:54:54 +04:00
|
|
|
#include <winpr/print.h>
|
2014-11-12 02:32:18 +03:00
|
|
|
|
2011-08-20 02:46:10 +04:00
|
|
|
#include "xf_window.h"
|
2011-08-16 08:22:00 +04:00
|
|
|
#include "xf_rail.h"
|
|
|
|
|
2014-09-12 19:13:01 +04:00
|
|
|
#define TAG CLIENT_TAG("x11")
|
2014-08-18 19:23:13 +04:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static const char* error_code_names[] = { "RAIL_EXEC_S_OK",
|
|
|
|
"RAIL_EXEC_E_HOOK_NOT_LOADED",
|
|
|
|
"RAIL_EXEC_E_DECODE_FAILED",
|
|
|
|
"RAIL_EXEC_E_NOT_IN_ALLOWLIST",
|
|
|
|
"RAIL_EXEC_E_FILE_NOT_FOUND",
|
|
|
|
"RAIL_EXEC_E_FAIL",
|
|
|
|
"RAIL_EXEC_E_SESSION_LOCKED" };
|
2014-11-12 00:35:30 +03:00
|
|
|
|
2017-05-12 12:11:41 +03:00
|
|
|
#ifdef WITH_DEBUG_RAIL
|
2019-11-06 17:24:51 +03:00
|
|
|
static const char* movetype_names[] = {
|
|
|
|
"(invalid)", "RAIL_WMSZ_LEFT", "RAIL_WMSZ_RIGHT",
|
|
|
|
"RAIL_WMSZ_TOP", "RAIL_WMSZ_TOPLEFT", "RAIL_WMSZ_TOPRIGHT",
|
|
|
|
"RAIL_WMSZ_BOTTOM", "RAIL_WMSZ_BOTTOMLEFT", "RAIL_WMSZ_BOTTOMRIGHT",
|
|
|
|
"RAIL_WMSZ_MOVE", "RAIL_WMSZ_KEYMOVE", "RAIL_WMSZ_KEYSIZE"
|
2014-11-12 00:35:30 +03:00
|
|
|
};
|
2017-05-12 12:11:41 +03:00
|
|
|
#endif
|
2014-11-12 00:35:30 +03:00
|
|
|
|
2018-11-10 12:51:30 +03:00
|
|
|
struct xf_rail_icon
|
|
|
|
{
|
2018-11-14 13:04:59 +03:00
|
|
|
long* data;
|
2018-11-10 12:51:30 +03:00
|
|
|
int length;
|
|
|
|
};
|
|
|
|
typedef struct xf_rail_icon xfRailIcon;
|
|
|
|
|
|
|
|
struct xf_rail_icon_cache
|
|
|
|
{
|
|
|
|
xfRailIcon* entries;
|
|
|
|
UINT32 numCaches;
|
|
|
|
UINT32 numCacheEntries;
|
|
|
|
xfRailIcon scratch;
|
|
|
|
};
|
|
|
|
|
2014-08-18 21:34:47 +04:00
|
|
|
void xf_rail_enable_remoteapp_mode(xfContext* xfc)
|
2012-01-02 13:27:04 +04:00
|
|
|
{
|
2013-06-13 02:57:25 +04:00
|
|
|
if (!xfc->remote_app)
|
2012-01-02 13:27:04 +04:00
|
|
|
{
|
2013-06-13 02:57:25 +04:00
|
|
|
xfc->remote_app = TRUE;
|
2016-08-18 21:14:52 +03:00
|
|
|
xfc->drawable = xf_CreateDummyWindow(xfc);
|
2014-11-12 06:27:33 +03:00
|
|
|
xf_DestroyDesktopWindow(xfc, xfc->window);
|
2013-06-13 02:57:25 +04:00
|
|
|
xfc->window = NULL;
|
2012-01-02 13:27:04 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-18 21:34:47 +04:00
|
|
|
void xf_rail_disable_remoteapp_mode(xfContext* xfc)
|
2012-08-04 02:35:17 +04:00
|
|
|
{
|
2013-06-13 02:57:25 +04:00
|
|
|
if (xfc->remote_app)
|
2012-08-14 23:59:11 +04:00
|
|
|
{
|
2013-06-13 02:57:25 +04:00
|
|
|
xfc->remote_app = FALSE;
|
2016-08-18 21:14:52 +03:00
|
|
|
xf_DestroyDummyWindow(xfc, xfc->drawable);
|
2013-06-13 02:57:25 +04:00
|
|
|
xf_create_window(xfc);
|
2012-08-14 23:59:11 +04:00
|
|
|
}
|
2012-08-04 02:35:17 +04:00
|
|
|
}
|
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
void xf_rail_send_activate(xfContext* xfc, Window xwindow, BOOL enabled)
|
|
|
|
{
|
2014-11-13 01:00:57 +03:00
|
|
|
xfAppWindow* appWindow;
|
|
|
|
RAIL_ACTIVATE_ORDER activate;
|
|
|
|
appWindow = xf_AppWindowFromX11Window(xfc, xwindow);
|
|
|
|
|
|
|
|
if (!appWindow)
|
|
|
|
return;
|
|
|
|
|
2018-09-26 12:27:57 +03:00
|
|
|
if (enabled)
|
|
|
|
xf_SetWindowStyle(xfc, appWindow, appWindow->dwStyle, appWindow->dwExStyle);
|
|
|
|
else
|
|
|
|
xf_SetWindowStyle(xfc, appWindow, 0, 0);
|
|
|
|
|
2014-11-13 01:00:57 +03:00
|
|
|
activate.windowId = appWindow->windowId;
|
|
|
|
activate.enabled = enabled;
|
|
|
|
xfc->rail->ClientActivate(xfc->rail, &activate);
|
2014-11-13 00:42:32 +03:00
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
void xf_rail_send_client_system_command(xfContext* xfc, UINT32 windowId, UINT16 command)
|
2014-11-13 00:42:32 +03:00
|
|
|
{
|
|
|
|
RAIL_SYSCOMMAND_ORDER syscommand;
|
|
|
|
syscommand.windowId = windowId;
|
|
|
|
syscommand.command = command;
|
|
|
|
xfc->rail->ClientSystemCommand(xfc->rail, &syscommand);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The position of the X window can become out of sync with the RDP window
|
|
|
|
* if the X window is moved locally by the window manager. In this event
|
|
|
|
* send an update to the RDP server informing it of the new window position
|
|
|
|
* and size.
|
|
|
|
*/
|
|
|
|
void xf_rail_adjust_position(xfContext* xfc, xfAppWindow* appWindow)
|
|
|
|
{
|
|
|
|
RAIL_WINDOW_MOVE_ORDER windowMove;
|
|
|
|
|
|
|
|
if (!appWindow->is_mapped || appWindow->local_move.state != LMS_NOT_ACTIVE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* If current window position disagrees with RDP window position, send update to RDP server */
|
2019-11-06 17:24:51 +03:00
|
|
|
if (appWindow->x != appWindow->windowOffsetX || appWindow->y != appWindow->windowOffsetY ||
|
2019-02-07 16:40:36 +03:00
|
|
|
appWindow->width != (INT64)appWindow->windowWidth ||
|
|
|
|
appWindow->height != (INT64)appWindow->windowHeight)
|
2014-11-13 00:42:32 +03:00
|
|
|
{
|
|
|
|
windowMove.windowId = appWindow->windowId;
|
|
|
|
/*
|
2019-11-06 17:24:51 +03:00
|
|
|
* Calculate new size/position for the rail window(new values for
|
|
|
|
* windowOffsetX/windowOffsetY/windowWidth/windowHeight) on the server
|
2014-11-13 00:42:32 +03:00
|
|
|
*/
|
2015-10-16 02:41:55 +03:00
|
|
|
windowMove.left = appWindow->x;
|
|
|
|
windowMove.top = appWindow->y;
|
2014-11-13 00:42:32 +03:00
|
|
|
windowMove.right = windowMove.left + appWindow->width;
|
|
|
|
windowMove.bottom = windowMove.top + appWindow->height;
|
|
|
|
xfc->rail->ClientWindowMove(xfc->rail, &windowMove);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow)
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
int child_x;
|
|
|
|
int child_y;
|
|
|
|
unsigned int mask;
|
|
|
|
Window root_window;
|
|
|
|
Window child_window;
|
|
|
|
RAIL_WINDOW_MOVE_ORDER windowMove;
|
2016-08-03 15:16:20 +03:00
|
|
|
rdpInput* input = xfc->context.input;
|
2014-11-13 00:42:32 +03:00
|
|
|
/*
|
|
|
|
* For keyboard moves send and explicit update to RDP server
|
|
|
|
*/
|
|
|
|
windowMove.windowId = appWindow->windowId;
|
|
|
|
/*
|
2019-11-06 17:24:51 +03:00
|
|
|
* Calculate new size/position for the rail window(new values for
|
|
|
|
* windowOffsetX/windowOffsetY/windowWidth/windowHeight) on the server
|
2015-02-12 02:24:06 +03:00
|
|
|
*
|
2014-11-13 00:42:32 +03:00
|
|
|
*/
|
2015-10-16 02:41:55 +03:00
|
|
|
windowMove.left = appWindow->x;
|
|
|
|
windowMove.top = appWindow->y;
|
2019-11-06 17:24:51 +03:00
|
|
|
windowMove.right =
|
|
|
|
windowMove.left +
|
|
|
|
appWindow->width; /* In the update to RDP the position is one past the window */
|
2014-11-13 00:42:32 +03:00
|
|
|
windowMove.bottom = windowMove.top + appWindow->height;
|
|
|
|
xfc->rail->ClientWindowMove(xfc->rail, &windowMove);
|
|
|
|
/*
|
|
|
|
* Simulate button up at new position to end the local move (per RDP spec)
|
|
|
|
*/
|
2019-11-06 17:24:51 +03:00
|
|
|
XQueryPointer(xfc->display, appWindow->handle, &root_window, &child_window, &x, &y, &child_x,
|
|
|
|
&child_y, &mask);
|
2014-11-13 00:42:32 +03:00
|
|
|
|
|
|
|
/* only send the mouse coordinates if not a keyboard move or size */
|
|
|
|
if ((appWindow->local_move.direction != _NET_WM_MOVERESIZE_MOVE_KEYBOARD) &&
|
2016-08-03 15:16:20 +03:00
|
|
|
(appWindow->local_move.direction != _NET_WM_MOVERESIZE_SIZE_KEYBOARD))
|
2014-11-13 00:42:32 +03:00
|
|
|
{
|
2020-06-29 09:39:09 +03:00
|
|
|
freerdp_input_send_mouse_event(input, PTR_FLAGS_BUTTON1, x, y);
|
2014-11-13 00:42:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Proactively update the RAIL window dimensions. There is a race condition where
|
|
|
|
* we can start to receive GDI orders for the new window dimensions before we
|
|
|
|
* receive the RAIL ORDER for the new window size. This avoids that race condition.
|
|
|
|
*/
|
2015-10-16 02:41:55 +03:00
|
|
|
appWindow->windowOffsetX = appWindow->x;
|
|
|
|
appWindow->windowOffsetY = appWindow->y;
|
2014-11-13 00:42:32 +03:00
|
|
|
appWindow->windowWidth = appWindow->width;
|
|
|
|
appWindow->windowHeight = appWindow->height;
|
|
|
|
appWindow->local_move.state = LMS_TERMINATING;
|
|
|
|
}
|
|
|
|
|
2018-03-01 14:39:29 +03:00
|
|
|
static void xf_rail_invalidate_region(xfContext* xfc, REGION16* invalidRegion)
|
2014-11-12 02:32:18 +03:00
|
|
|
{
|
|
|
|
int index;
|
2019-05-08 16:36:20 +03:00
|
|
|
int count = 0;
|
2014-11-12 02:32:18 +03:00
|
|
|
RECTANGLE_16 updateRect;
|
|
|
|
RECTANGLE_16 windowRect;
|
|
|
|
ULONG_PTR* pKeys = NULL;
|
2014-11-12 06:27:33 +03:00
|
|
|
xfAppWindow* appWindow;
|
2014-11-12 02:32:18 +03:00
|
|
|
const RECTANGLE_16* extents;
|
|
|
|
REGION16 windowInvalidRegion;
|
|
|
|
region16_init(&windowInvalidRegion);
|
2019-05-08 16:36:20 +03:00
|
|
|
if (xfc->railWindows)
|
|
|
|
count = HashTable_GetKeys(xfc->railWindows, &pKeys);
|
2014-11-12 02:32:18 +03:00
|
|
|
|
|
|
|
for (index = 0; index < count; index++)
|
|
|
|
{
|
2019-05-08 16:36:20 +03:00
|
|
|
appWindow = xf_rail_get_window(xfc, *(UINT64*)pKeys[index]);
|
2014-11-12 02:32:18 +03:00
|
|
|
|
2014-11-12 06:27:33 +03:00
|
|
|
if (appWindow)
|
2014-11-12 02:32:18 +03:00
|
|
|
{
|
2015-09-04 01:42:53 +03:00
|
|
|
windowRect.left = MAX(appWindow->x, 0);
|
|
|
|
windowRect.top = MAX(appWindow->y, 0);
|
|
|
|
windowRect.right = MAX(appWindow->x + appWindow->width, 0);
|
|
|
|
windowRect.bottom = MAX(appWindow->y + appWindow->height, 0);
|
2014-11-12 02:32:18 +03:00
|
|
|
region16_clear(&windowInvalidRegion);
|
|
|
|
region16_intersect_rect(&windowInvalidRegion, invalidRegion, &windowRect);
|
|
|
|
|
|
|
|
if (!region16_is_empty(&windowInvalidRegion))
|
|
|
|
{
|
|
|
|
extents = region16_extents(&windowInvalidRegion);
|
2014-11-12 06:27:33 +03:00
|
|
|
updateRect.left = extents->left - appWindow->x;
|
|
|
|
updateRect.top = extents->top - appWindow->y;
|
|
|
|
updateRect.right = extents->right - appWindow->x;
|
|
|
|
updateRect.bottom = extents->bottom - appWindow->y;
|
2017-01-31 12:10:58 +03:00
|
|
|
xf_UpdateWindowArea(xfc, appWindow, updateRect.left, updateRect.top,
|
|
|
|
updateRect.right - updateRect.left,
|
|
|
|
updateRect.bottom - updateRect.top);
|
2014-11-12 02:32:18 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-13 11:49:51 +03:00
|
|
|
free(pKeys);
|
2014-11-12 02:32:18 +03:00
|
|
|
region16_uninit(&windowInvalidRegion);
|
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
void xf_rail_paint(xfContext* xfc, INT32 uleft, INT32 utop, UINT32 uright, UINT32 ubottom)
|
2011-08-17 10:14:02 +04:00
|
|
|
{
|
2014-11-13 00:42:32 +03:00
|
|
|
REGION16 invalidRegion;
|
|
|
|
RECTANGLE_16 invalidRect;
|
|
|
|
invalidRect.left = uleft;
|
|
|
|
invalidRect.top = utop;
|
|
|
|
invalidRect.right = uright;
|
|
|
|
invalidRect.bottom = ubottom;
|
|
|
|
region16_init(&invalidRegion);
|
|
|
|
region16_union_rect(&invalidRegion, &invalidRegion, &invalidRect);
|
|
|
|
xf_rail_invalidate_region(xfc, &invalidRegion);
|
|
|
|
region16_uninit(&invalidRegion);
|
2011-08-20 06:21:09 +04:00
|
|
|
}
|
|
|
|
|
2014-11-12 04:26:47 +03:00
|
|
|
/* RemoteApp Core Protocol Extension */
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static BOOL xf_rail_window_common(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
|
|
|
const WINDOW_STATE_ORDER* windowState)
|
2014-11-12 04:26:47 +03:00
|
|
|
{
|
2014-11-13 00:42:32 +03:00
|
|
|
xfAppWindow* appWindow = NULL;
|
2019-11-06 17:24:51 +03:00
|
|
|
xfContext* xfc = (xfContext*)context;
|
2014-11-12 04:26:47 +03:00
|
|
|
UINT32 fieldFlags = orderInfo->fieldFlags;
|
2015-10-16 02:41:55 +03:00
|
|
|
BOOL position_or_size_updated = FALSE;
|
2019-05-08 16:36:20 +03:00
|
|
|
appWindow = xf_rail_get_window(xfc, orderInfo->windowId);
|
2014-11-12 04:26:47 +03:00
|
|
|
|
|
|
|
if (fieldFlags & WINDOW_ORDER_STATE_NEW)
|
|
|
|
{
|
2019-05-08 16:36:20 +03:00
|
|
|
if (!appWindow)
|
|
|
|
appWindow = xf_rail_add_window(xfc, orderInfo->windowId, windowState->windowOffsetX,
|
|
|
|
windowState->windowOffsetY, windowState->windowWidth,
|
|
|
|
windowState->windowHeight, 0xFFFFFFFF);
|
2014-11-12 04:26:47 +03:00
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
if (!appWindow)
|
2015-04-14 11:14:23 +03:00
|
|
|
return FALSE;
|
2014-11-12 04:26:47 +03:00
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
appWindow->dwStyle = windowState->style;
|
|
|
|
appWindow->dwExStyle = windowState->extendedStyle;
|
2014-11-12 04:26:47 +03:00
|
|
|
|
2015-10-15 22:35:07 +03:00
|
|
|
/* Ensure window always gets a window title */
|
2014-11-12 04:26:47 +03:00
|
|
|
if (fieldFlags & WINDOW_ORDER_FIELD_TITLE)
|
|
|
|
{
|
|
|
|
char* title = NULL;
|
|
|
|
|
2016-03-03 18:21:12 +03:00
|
|
|
if (windowState->titleInfo.length == 0)
|
|
|
|
{
|
|
|
|
if (!(title = _strdup("")))
|
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "failed to duplicate empty window title string");
|
|
|
|
/* error handled below */
|
|
|
|
}
|
|
|
|
}
|
2019-11-06 17:24:51 +03:00
|
|
|
else if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*)windowState->titleInfo.string,
|
|
|
|
windowState->titleInfo.length / 2, &title, 0, NULL,
|
|
|
|
NULL) < 1)
|
2016-03-03 18:21:12 +03:00
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "failed to convert window title");
|
|
|
|
/* error handled below */
|
|
|
|
}
|
2014-11-12 04:26:47 +03:00
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
appWindow->title = title;
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-03-03 18:21:12 +03:00
|
|
|
if (!(appWindow->title = _strdup("RdpRailWindow")))
|
|
|
|
WLog_ERR(TAG, "failed to duplicate default window title string");
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
2016-03-03 18:21:12 +03:00
|
|
|
|
2015-06-17 23:08:02 +03:00
|
|
|
if (!appWindow->title)
|
|
|
|
{
|
|
|
|
free(appWindow);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2014-11-12 04:26:47 +03:00
|
|
|
|
2014-11-13 01:00:57 +03:00
|
|
|
xf_AppWindowInit(xfc, appWindow);
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
if (!appWindow)
|
2015-04-14 11:14:23 +03:00
|
|
|
return FALSE;
|
2014-11-12 04:26:47 +03:00
|
|
|
|
2015-10-16 02:41:55 +03:00
|
|
|
/* Keep track of any position/size update so that we can force a refresh of the window */
|
2014-11-12 04:26:47 +03:00
|
|
|
if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) ||
|
2019-11-06 17:24:51 +03:00
|
|
|
(fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) ||
|
2016-08-03 15:16:20 +03:00
|
|
|
(fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) ||
|
|
|
|
(fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) ||
|
|
|
|
(fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) ||
|
|
|
|
(fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) ||
|
|
|
|
(fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY))
|
2014-11-12 04:26:47 +03:00
|
|
|
{
|
2015-10-16 02:41:55 +03:00
|
|
|
position_or_size_updated = TRUE;
|
2016-08-03 15:16:20 +03:00
|
|
|
}
|
2015-02-12 02:24:06 +03:00
|
|
|
|
2015-10-16 02:41:55 +03:00
|
|
|
/* Update Parameters */
|
2015-02-12 02:24:06 +03:00
|
|
|
|
2015-10-16 02:41:55 +03:00
|
|
|
if (fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET)
|
|
|
|
{
|
|
|
|
appWindow->windowOffsetX = windowState->windowOffsetX;
|
|
|
|
appWindow->windowOffsetY = windowState->windowOffsetY;
|
|
|
|
}
|
2014-11-12 04:26:47 +03:00
|
|
|
|
2015-10-16 02:41:55 +03:00
|
|
|
if (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)
|
|
|
|
{
|
|
|
|
appWindow->windowWidth = windowState->windowWidth;
|
|
|
|
appWindow->windowHeight = windowState->windowHeight;
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fieldFlags & WINDOW_ORDER_FIELD_OWNER)
|
|
|
|
{
|
2014-11-13 00:42:32 +03:00
|
|
|
appWindow->ownerWindowId = windowState->ownerWindowId;
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fieldFlags & WINDOW_ORDER_FIELD_STYLE)
|
|
|
|
{
|
2014-11-13 00:42:32 +03:00
|
|
|
appWindow->dwStyle = windowState->style;
|
|
|
|
appWindow->dwExStyle = windowState->extendedStyle;
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fieldFlags & WINDOW_ORDER_FIELD_SHOW)
|
|
|
|
{
|
2014-11-13 00:42:32 +03:00
|
|
|
appWindow->showState = windowState->showState;
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fieldFlags & WINDOW_ORDER_FIELD_TITLE)
|
|
|
|
{
|
|
|
|
char* title = NULL;
|
|
|
|
|
2016-03-03 18:21:12 +03:00
|
|
|
if (windowState->titleInfo.length == 0)
|
|
|
|
{
|
|
|
|
if (!(title = _strdup("")))
|
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "failed to duplicate empty window title string");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
2019-11-06 17:24:51 +03:00
|
|
|
else if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*)windowState->titleInfo.string,
|
2016-10-04 10:00:00 +03:00
|
|
|
windowState->titleInfo.length / 2, &title, 0, NULL, NULL) < 1)
|
2016-03-03 18:21:12 +03:00
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "failed to convert window title");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2016-08-03 15:16:20 +03:00
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
free(appWindow->title);
|
|
|
|
appWindow->title = title;
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
|
|
|
|
{
|
2014-11-13 00:42:32 +03:00
|
|
|
appWindow->clientOffsetX = windowState->clientOffsetX;
|
|
|
|
appWindow->clientOffsetY = windowState->clientOffsetY;
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
|
|
|
|
{
|
2014-11-13 00:42:32 +03:00
|
|
|
appWindow->clientAreaWidth = windowState->clientAreaWidth;
|
|
|
|
appWindow->clientAreaHeight = windowState->clientAreaHeight;
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
|
|
|
|
{
|
2014-11-13 00:42:32 +03:00
|
|
|
appWindow->windowClientDeltaX = windowState->windowClientDeltaX;
|
|
|
|
appWindow->windowClientDeltaY = windowState->windowClientDeltaY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS)
|
|
|
|
{
|
|
|
|
if (appWindow->windowRects)
|
|
|
|
{
|
|
|
|
free(appWindow->windowRects);
|
|
|
|
appWindow->windowRects = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
appWindow->numWindowRects = windowState->numWindowRects;
|
|
|
|
|
|
|
|
if (appWindow->numWindowRects)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
appWindow->windowRects =
|
|
|
|
(RECTANGLE_16*)calloc(appWindow->numWindowRects, sizeof(RECTANGLE_16));
|
2014-11-13 00:42:32 +03:00
|
|
|
|
|
|
|
if (!appWindow->windowRects)
|
2015-04-14 11:14:23 +03:00
|
|
|
return FALSE;
|
2014-11-13 00:42:32 +03:00
|
|
|
|
|
|
|
CopyMemory(appWindow->windowRects, windowState->windowRects,
|
2016-10-04 10:00:00 +03:00
|
|
|
appWindow->numWindowRects * sizeof(RECTANGLE_16));
|
2014-11-13 00:42:32 +03:00
|
|
|
}
|
|
|
|
}
|
2014-11-12 04:26:47 +03:00
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
if (fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET)
|
|
|
|
{
|
|
|
|
appWindow->visibleOffsetX = windowState->visibleOffsetX;
|
|
|
|
appWindow->visibleOffsetY = windowState->visibleOffsetY;
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
if (fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
|
2014-11-12 04:26:47 +03:00
|
|
|
{
|
2014-11-13 00:42:32 +03:00
|
|
|
if (appWindow->visibilityRects)
|
|
|
|
{
|
|
|
|
free(appWindow->visibilityRects);
|
|
|
|
appWindow->visibilityRects = NULL;
|
|
|
|
}
|
2014-11-12 04:26:47 +03:00
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
appWindow->numVisibilityRects = windowState->numVisibilityRects;
|
|
|
|
|
|
|
|
if (appWindow->numVisibilityRects)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
appWindow->visibilityRects =
|
|
|
|
(RECTANGLE_16*)calloc(appWindow->numVisibilityRects, sizeof(RECTANGLE_16));
|
2014-11-13 00:42:32 +03:00
|
|
|
|
|
|
|
if (!appWindow->visibilityRects)
|
2015-04-14 11:14:23 +03:00
|
|
|
return FALSE;
|
2014-11-13 00:42:32 +03:00
|
|
|
|
|
|
|
CopyMemory(appWindow->visibilityRects, windowState->visibilityRects,
|
2016-10-04 10:00:00 +03:00
|
|
|
appWindow->numVisibilityRects * sizeof(RECTANGLE_16));
|
2014-11-13 00:42:32 +03:00
|
|
|
}
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
/* Update Window */
|
|
|
|
|
|
|
|
if (fieldFlags & WINDOW_ORDER_FIELD_STYLE)
|
2014-11-12 04:26:47 +03:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
if (fieldFlags & WINDOW_ORDER_FIELD_SHOW)
|
2014-11-12 04:26:47 +03:00
|
|
|
{
|
2014-11-13 00:42:32 +03:00
|
|
|
xf_ShowWindow(xfc, appWindow, appWindow->showState);
|
|
|
|
}
|
2014-11-12 04:26:47 +03:00
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
if (fieldFlags & WINDOW_ORDER_FIELD_TITLE)
|
|
|
|
{
|
2015-05-27 16:13:43 +03:00
|
|
|
if (appWindow->title)
|
|
|
|
xf_SetWindowText(xfc, appWindow, appWindow->title);
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
2015-10-16 02:41:55 +03:00
|
|
|
if (position_or_size_updated)
|
2014-11-12 04:26:47 +03:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
UINT32 visibilityRectsOffsetX =
|
|
|
|
(appWindow->visibleOffsetX -
|
|
|
|
(appWindow->clientOffsetX - appWindow->windowClientDeltaX));
|
|
|
|
UINT32 visibilityRectsOffsetY =
|
|
|
|
(appWindow->visibleOffsetY -
|
|
|
|
(appWindow->clientOffsetY - appWindow->windowClientDeltaY));
|
2015-10-16 02:41:55 +03:00
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
/*
|
2019-11-06 17:24:51 +03:00
|
|
|
* The rail server like to set the window to a small size when it is minimized even though
|
|
|
|
* it is hidden in some cases this can cause the window not to restore back to its original
|
|
|
|
* size. Therefore we don't update our local window when that rail window state is minimized
|
2014-11-13 00:42:32 +03:00
|
|
|
*/
|
2015-10-16 02:41:55 +03:00
|
|
|
if (appWindow->rail_state != WINDOW_SHOW_MINIMIZED)
|
|
|
|
{
|
|
|
|
/* Redraw window area if already in the correct position */
|
2019-02-07 16:40:36 +03:00
|
|
|
if (appWindow->x == (INT64)appWindow->windowOffsetX &&
|
|
|
|
appWindow->y == (INT64)appWindow->windowOffsetY &&
|
|
|
|
appWindow->width == (INT64)appWindow->windowWidth &&
|
|
|
|
appWindow->height == (INT64)appWindow->windowHeight)
|
2015-10-16 02:41:55 +03:00
|
|
|
{
|
2016-08-03 15:16:20 +03:00
|
|
|
xf_UpdateWindowArea(xfc, appWindow, 0, 0, appWindow->windowWidth,
|
2016-10-04 10:00:00 +03:00
|
|
|
appWindow->windowHeight);
|
2015-10-16 02:41:55 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
xf_MoveWindow(xfc, appWindow, appWindow->windowOffsetX, appWindow->windowOffsetY,
|
2016-10-04 10:00:00 +03:00
|
|
|
appWindow->windowWidth, appWindow->windowHeight);
|
2015-10-16 02:41:55 +03:00
|
|
|
}
|
|
|
|
|
2016-08-03 15:16:20 +03:00
|
|
|
xf_SetWindowVisibilityRects(xfc, appWindow, visibilityRectsOffsetX,
|
2016-10-04 10:00:00 +03:00
|
|
|
visibilityRectsOffsetY, appWindow->visibilityRects,
|
|
|
|
appWindow->numVisibilityRects);
|
2015-09-11 01:15:55 +03:00
|
|
|
}
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
2015-10-16 02:41:55 +03:00
|
|
|
/* We should only be using the visibility rects for shaping the window */
|
|
|
|
/*if (fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS)
|
2014-11-12 04:26:47 +03:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
xf_SetWindowRects(xfc, appWindow, appWindow->windowRects, appWindow->numWindowRects);
|
2015-10-16 02:41:55 +03:00
|
|
|
}*/
|
2015-04-14 11:14:23 +03:00
|
|
|
return TRUE;
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static BOOL xf_rail_window_delete(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo)
|
2014-11-12 04:26:47 +03:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
xfContext* xfc = (xfContext*)context;
|
2019-05-08 16:36:20 +03:00
|
|
|
return xf_rail_del_window(xfc, orderInfo->windowId);
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
2018-11-10 12:51:30 +03:00
|
|
|
static xfRailIconCache* RailIconCache_New(rdpSettings* settings)
|
|
|
|
{
|
|
|
|
xfRailIconCache* cache;
|
2018-11-14 13:04:59 +03:00
|
|
|
cache = calloc(1, sizeof(xfRailIconCache));
|
2018-11-10 12:51:30 +03:00
|
|
|
|
|
|
|
if (!cache)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
cache->numCaches = settings->RemoteAppNumIconCaches;
|
|
|
|
cache->numCacheEntries = settings->RemoteAppNumIconCacheEntries;
|
2021-01-25 12:06:01 +03:00
|
|
|
cache->entries = calloc(cache->numCaches * cache->numCacheEntries * 1ULL, sizeof(xfRailIcon));
|
2018-11-14 13:04:59 +03:00
|
|
|
|
2018-11-10 12:51:30 +03:00
|
|
|
if (!cache->entries)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_ERR(TAG, "failed to allocate icon cache %d x %d entries", cache->numCaches,
|
|
|
|
cache->numCacheEntries);
|
2018-11-10 12:51:30 +03:00
|
|
|
free(cache);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return cache;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void RailIconCache_Free(xfRailIconCache* cache)
|
|
|
|
{
|
|
|
|
UINT32 i;
|
|
|
|
|
|
|
|
if (cache)
|
|
|
|
{
|
|
|
|
for (i = 0; i < cache->numCaches * cache->numCacheEntries; i++)
|
|
|
|
{
|
|
|
|
free(cache->entries[i].data);
|
|
|
|
}
|
2018-11-14 13:04:59 +03:00
|
|
|
|
2018-11-10 12:51:30 +03:00
|
|
|
free(cache->scratch.data);
|
|
|
|
free(cache->entries);
|
|
|
|
free(cache);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static xfRailIcon* RailIconCache_Lookup(xfRailIconCache* cache, UINT8 cacheId, UINT16 cacheEntry)
|
2018-11-10 12:51:30 +03:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* MS-RDPERP 2.2.1.2.3 Icon Info (TS_ICON_INFO)
|
|
|
|
*
|
|
|
|
* CacheId (1 byte):
|
|
|
|
* If the value is 0xFFFF, the icon SHOULD NOT be cached.
|
|
|
|
*
|
|
|
|
* Yes, the spec says "0xFFFF" in the 2018-03-16 revision,
|
|
|
|
* but the actual protocol field is 1-byte wide.
|
|
|
|
*/
|
|
|
|
if (cacheId == 0xFF)
|
|
|
|
return &cache->scratch;
|
|
|
|
|
|
|
|
if (cacheId >= cache->numCaches)
|
|
|
|
return NULL;
|
2018-11-14 13:04:59 +03:00
|
|
|
|
2018-11-10 12:51:30 +03:00
|
|
|
if (cacheEntry >= cache->numCacheEntries)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return &cache->entries[cache->numCacheEntries * cacheId + cacheEntry];
|
|
|
|
}
|
|
|
|
|
xfreerdp: set _NET_WM_ICON to RAIL app icon
Icons on X11 windows are configured using the _NET_WM_ICON property
described in Extended Window Manager Hints. Here we implement converison
from DIB bitmaps used by RAIL to the format expected by _NET_WM_ICON,
and actually set the icon for RAIL app windows.
Both DIB format and _NET_WM_ICON (or rather, Xlib) are weird. Let's
start with RAIL's format. That's the one used in BMP and ICO formats
on Windows. It has some strange properties but thankfully FreeRDP's
freerdp_image_copy() can handle most of them for us. (With an exception
of monochrome and 16-color formats that it does not support. Sorry, but
I'm too lazy to fix them. They are not seem to be used by any real
application either.) The one thing that it can't do is to apply the
alpha transparency bitmask so we have to do it manually. This instantly
reminds us that DIB format has HISTORY: it's vertically flipped and
each must be padded to 4 bytes. Both these quirks having reasonable
(for a certain definition of 'reason') explanations. Such is life.
(Also, 8-bit images require a color palette which we must fill in.)
So okay, now comes _NET_WM_ICON. It is more sane (or rather, easier to
deal with). The bitmap is represented with a tiny [width, height] header
followed by an array of pixels in ARGB format. There is no padding, no
weird color formats. But here's a catch: you can't simply take the
output of freerdp_image_copy() and cast to (unsigned char*) of colors.
We have to allocate an array of C's longs and copy the pixels there,
because that's what Xlib expects (and this is mentioned in the spec).
Simply casting an array of bytes causes crashes on 64-bit systems.
So don't try to cheat or "optimize" and read the docs, kids.
Note that XFlush() call after XChangeProperty(). It's there because it
seems to helps see the icon quicker with Unity on Ubuntu 14.04. I don't
know why. (And Unity does not support _NET_WM_ICON officially. But it
sorta kinda works sometimes.)
Oh, and while we're here, delete some old, unused, and commented out
code that was setting window icons in the past. It's not needed anymore.
2018-11-10 15:43:36 +03:00
|
|
|
/*
|
|
|
|
* _NET_WM_ICON format is defined as "array of CARDINAL" values which for
|
|
|
|
* Xlib must be represented with an array of C's "long" values. Note that
|
|
|
|
* "long" != "INT32" on 64-bit systems. Therefore we can't simply cast
|
|
|
|
* the bitmap data as (unsigned char*), we have to copy all the pixels.
|
|
|
|
*
|
|
|
|
* The first two values are width and height followed by actual color data
|
|
|
|
* in ARGB format (e.g., 0xFFFF0000L is opaque red), pixels are in normal,
|
|
|
|
* left-to-right top-down order.
|
|
|
|
*/
|
2020-08-10 13:26:46 +03:00
|
|
|
static BOOL convert_rail_icon(const ICON_INFO* iconInfo, xfRailIcon* railIcon)
|
2018-11-10 12:51:30 +03:00
|
|
|
{
|
2019-05-08 16:03:06 +03:00
|
|
|
BYTE* argbPixels = NULL;
|
xfreerdp: set _NET_WM_ICON to RAIL app icon
Icons on X11 windows are configured using the _NET_WM_ICON property
described in Extended Window Manager Hints. Here we implement converison
from DIB bitmaps used by RAIL to the format expected by _NET_WM_ICON,
and actually set the icon for RAIL app windows.
Both DIB format and _NET_WM_ICON (or rather, Xlib) are weird. Let's
start with RAIL's format. That's the one used in BMP and ICO formats
on Windows. It has some strange properties but thankfully FreeRDP's
freerdp_image_copy() can handle most of them for us. (With an exception
of monochrome and 16-color formats that it does not support. Sorry, but
I'm too lazy to fix them. They are not seem to be used by any real
application either.) The one thing that it can't do is to apply the
alpha transparency bitmask so we have to do it manually. This instantly
reminds us that DIB format has HISTORY: it's vertically flipped and
each must be padded to 4 bytes. Both these quirks having reasonable
(for a certain definition of 'reason') explanations. Such is life.
(Also, 8-bit images require a color palette which we must fill in.)
So okay, now comes _NET_WM_ICON. It is more sane (or rather, easier to
deal with). The bitmap is represented with a tiny [width, height] header
followed by an array of pixels in ARGB format. There is no padding, no
weird color formats. But here's a catch: you can't simply take the
output of freerdp_image_copy() and cast to (unsigned char*) of colors.
We have to allocate an array of C's longs and copy the pixels there,
because that's what Xlib expects (and this is mentioned in the spec).
Simply casting an array of bytes causes crashes on 64-bit systems.
So don't try to cheat or "optimize" and read the docs, kids.
Note that XFlush() call after XChangeProperty(). It's there because it
seems to helps see the icon quicker with Unity on Ubuntu 14.04. I don't
know why. (And Unity does not support _NET_WM_ICON officially. But it
sorta kinda works sometimes.)
Oh, and while we're here, delete some old, unused, and commented out
code that was setting window icons in the past. It's not needed anymore.
2018-11-10 15:43:36 +03:00
|
|
|
BYTE* nextPixel;
|
|
|
|
long* pixels;
|
|
|
|
int i;
|
|
|
|
int nelements;
|
2021-01-25 12:06:01 +03:00
|
|
|
argbPixels = calloc(iconInfo->width * iconInfo->height * 1ULL, 4);
|
2018-11-14 13:04:59 +03:00
|
|
|
|
xfreerdp: set _NET_WM_ICON to RAIL app icon
Icons on X11 windows are configured using the _NET_WM_ICON property
described in Extended Window Manager Hints. Here we implement converison
from DIB bitmaps used by RAIL to the format expected by _NET_WM_ICON,
and actually set the icon for RAIL app windows.
Both DIB format and _NET_WM_ICON (or rather, Xlib) are weird. Let's
start with RAIL's format. That's the one used in BMP and ICO formats
on Windows. It has some strange properties but thankfully FreeRDP's
freerdp_image_copy() can handle most of them for us. (With an exception
of monochrome and 16-color formats that it does not support. Sorry, but
I'm too lazy to fix them. They are not seem to be used by any real
application either.) The one thing that it can't do is to apply the
alpha transparency bitmask so we have to do it manually. This instantly
reminds us that DIB format has HISTORY: it's vertically flipped and
each must be padded to 4 bytes. Both these quirks having reasonable
(for a certain definition of 'reason') explanations. Such is life.
(Also, 8-bit images require a color palette which we must fill in.)
So okay, now comes _NET_WM_ICON. It is more sane (or rather, easier to
deal with). The bitmap is represented with a tiny [width, height] header
followed by an array of pixels in ARGB format. There is no padding, no
weird color formats. But here's a catch: you can't simply take the
output of freerdp_image_copy() and cast to (unsigned char*) of colors.
We have to allocate an array of C's longs and copy the pixels there,
because that's what Xlib expects (and this is mentioned in the spec).
Simply casting an array of bytes causes crashes on 64-bit systems.
So don't try to cheat or "optimize" and read the docs, kids.
Note that XFlush() call after XChangeProperty(). It's there because it
seems to helps see the icon quicker with Unity on Ubuntu 14.04. I don't
know why. (And Unity does not support _NET_WM_ICON officially. But it
sorta kinda works sometimes.)
Oh, and while we're here, delete some old, unused, and commented out
code that was setting window icons in the past. It's not needed anymore.
2018-11-10 15:43:36 +03:00
|
|
|
if (!argbPixels)
|
|
|
|
goto error;
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
if (!freerdp_image_copy_from_icon_data(
|
|
|
|
argbPixels, PIXEL_FORMAT_ARGB32, 0, 0, 0, iconInfo->width, iconInfo->height,
|
|
|
|
iconInfo->bitsColor, iconInfo->cbBitsColor, iconInfo->bitsMask, iconInfo->cbBitsMask,
|
|
|
|
iconInfo->colorTable, iconInfo->cbColorTable, iconInfo->bpp))
|
xfreerdp: set _NET_WM_ICON to RAIL app icon
Icons on X11 windows are configured using the _NET_WM_ICON property
described in Extended Window Manager Hints. Here we implement converison
from DIB bitmaps used by RAIL to the format expected by _NET_WM_ICON,
and actually set the icon for RAIL app windows.
Both DIB format and _NET_WM_ICON (or rather, Xlib) are weird. Let's
start with RAIL's format. That's the one used in BMP and ICO formats
on Windows. It has some strange properties but thankfully FreeRDP's
freerdp_image_copy() can handle most of them for us. (With an exception
of monochrome and 16-color formats that it does not support. Sorry, but
I'm too lazy to fix them. They are not seem to be used by any real
application either.) The one thing that it can't do is to apply the
alpha transparency bitmask so we have to do it manually. This instantly
reminds us that DIB format has HISTORY: it's vertically flipped and
each must be padded to 4 bytes. Both these quirks having reasonable
(for a certain definition of 'reason') explanations. Such is life.
(Also, 8-bit images require a color palette which we must fill in.)
So okay, now comes _NET_WM_ICON. It is more sane (or rather, easier to
deal with). The bitmap is represented with a tiny [width, height] header
followed by an array of pixels in ARGB format. There is no padding, no
weird color formats. But here's a catch: you can't simply take the
output of freerdp_image_copy() and cast to (unsigned char*) of colors.
We have to allocate an array of C's longs and copy the pixels there,
because that's what Xlib expects (and this is mentioned in the spec).
Simply casting an array of bytes causes crashes on 64-bit systems.
So don't try to cheat or "optimize" and read the docs, kids.
Note that XFlush() call after XChangeProperty(). It's there because it
seems to helps see the icon quicker with Unity on Ubuntu 14.04. I don't
know why. (And Unity does not support _NET_WM_ICON officially. But it
sorta kinda works sometimes.)
Oh, and while we're here, delete some old, unused, and commented out
code that was setting window icons in the past. It's not needed anymore.
2018-11-10 15:43:36 +03:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
nelements = 2 + iconInfo->width * iconInfo->height;
|
2018-11-14 13:04:59 +03:00
|
|
|
pixels = realloc(railIcon->data, nelements * sizeof(long));
|
|
|
|
|
xfreerdp: set _NET_WM_ICON to RAIL app icon
Icons on X11 windows are configured using the _NET_WM_ICON property
described in Extended Window Manager Hints. Here we implement converison
from DIB bitmaps used by RAIL to the format expected by _NET_WM_ICON,
and actually set the icon for RAIL app windows.
Both DIB format and _NET_WM_ICON (or rather, Xlib) are weird. Let's
start with RAIL's format. That's the one used in BMP and ICO formats
on Windows. It has some strange properties but thankfully FreeRDP's
freerdp_image_copy() can handle most of them for us. (With an exception
of monochrome and 16-color formats that it does not support. Sorry, but
I'm too lazy to fix them. They are not seem to be used by any real
application either.) The one thing that it can't do is to apply the
alpha transparency bitmask so we have to do it manually. This instantly
reminds us that DIB format has HISTORY: it's vertically flipped and
each must be padded to 4 bytes. Both these quirks having reasonable
(for a certain definition of 'reason') explanations. Such is life.
(Also, 8-bit images require a color palette which we must fill in.)
So okay, now comes _NET_WM_ICON. It is more sane (or rather, easier to
deal with). The bitmap is represented with a tiny [width, height] header
followed by an array of pixels in ARGB format. There is no padding, no
weird color formats. But here's a catch: you can't simply take the
output of freerdp_image_copy() and cast to (unsigned char*) of colors.
We have to allocate an array of C's longs and copy the pixels there,
because that's what Xlib expects (and this is mentioned in the spec).
Simply casting an array of bytes causes crashes on 64-bit systems.
So don't try to cheat or "optimize" and read the docs, kids.
Note that XFlush() call after XChangeProperty(). It's there because it
seems to helps see the icon quicker with Unity on Ubuntu 14.04. I don't
know why. (And Unity does not support _NET_WM_ICON officially. But it
sorta kinda works sometimes.)
Oh, and while we're here, delete some old, unused, and commented out
code that was setting window icons in the past. It's not needed anymore.
2018-11-10 15:43:36 +03:00
|
|
|
if (!pixels)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
railIcon->data = pixels;
|
|
|
|
railIcon->length = nelements;
|
|
|
|
pixels[0] = iconInfo->width;
|
|
|
|
pixels[1] = iconInfo->height;
|
|
|
|
nextPixel = argbPixels;
|
2018-11-14 13:04:59 +03:00
|
|
|
|
xfreerdp: set _NET_WM_ICON to RAIL app icon
Icons on X11 windows are configured using the _NET_WM_ICON property
described in Extended Window Manager Hints. Here we implement converison
from DIB bitmaps used by RAIL to the format expected by _NET_WM_ICON,
and actually set the icon for RAIL app windows.
Both DIB format and _NET_WM_ICON (or rather, Xlib) are weird. Let's
start with RAIL's format. That's the one used in BMP and ICO formats
on Windows. It has some strange properties but thankfully FreeRDP's
freerdp_image_copy() can handle most of them for us. (With an exception
of monochrome and 16-color formats that it does not support. Sorry, but
I'm too lazy to fix them. They are not seem to be used by any real
application either.) The one thing that it can't do is to apply the
alpha transparency bitmask so we have to do it manually. This instantly
reminds us that DIB format has HISTORY: it's vertically flipped and
each must be padded to 4 bytes. Both these quirks having reasonable
(for a certain definition of 'reason') explanations. Such is life.
(Also, 8-bit images require a color palette which we must fill in.)
So okay, now comes _NET_WM_ICON. It is more sane (or rather, easier to
deal with). The bitmap is represented with a tiny [width, height] header
followed by an array of pixels in ARGB format. There is no padding, no
weird color formats. But here's a catch: you can't simply take the
output of freerdp_image_copy() and cast to (unsigned char*) of colors.
We have to allocate an array of C's longs and copy the pixels there,
because that's what Xlib expects (and this is mentioned in the spec).
Simply casting an array of bytes causes crashes on 64-bit systems.
So don't try to cheat or "optimize" and read the docs, kids.
Note that XFlush() call after XChangeProperty(). It's there because it
seems to helps see the icon quicker with Unity on Ubuntu 14.04. I don't
know why. (And Unity does not support _NET_WM_ICON officially. But it
sorta kinda works sometimes.)
Oh, and while we're here, delete some old, unused, and commented out
code that was setting window icons in the past. It's not needed anymore.
2018-11-10 15:43:36 +03:00
|
|
|
for (i = 2; i < nelements; i++)
|
|
|
|
{
|
2018-11-14 13:04:59 +03:00
|
|
|
pixels[i] = ReadColor(nextPixel, PIXEL_FORMAT_BGRA32);
|
xfreerdp: set _NET_WM_ICON to RAIL app icon
Icons on X11 windows are configured using the _NET_WM_ICON property
described in Extended Window Manager Hints. Here we implement converison
from DIB bitmaps used by RAIL to the format expected by _NET_WM_ICON,
and actually set the icon for RAIL app windows.
Both DIB format and _NET_WM_ICON (or rather, Xlib) are weird. Let's
start with RAIL's format. That's the one used in BMP and ICO formats
on Windows. It has some strange properties but thankfully FreeRDP's
freerdp_image_copy() can handle most of them for us. (With an exception
of monochrome and 16-color formats that it does not support. Sorry, but
I'm too lazy to fix them. They are not seem to be used by any real
application either.) The one thing that it can't do is to apply the
alpha transparency bitmask so we have to do it manually. This instantly
reminds us that DIB format has HISTORY: it's vertically flipped and
each must be padded to 4 bytes. Both these quirks having reasonable
(for a certain definition of 'reason') explanations. Such is life.
(Also, 8-bit images require a color palette which we must fill in.)
So okay, now comes _NET_WM_ICON. It is more sane (or rather, easier to
deal with). The bitmap is represented with a tiny [width, height] header
followed by an array of pixels in ARGB format. There is no padding, no
weird color formats. But here's a catch: you can't simply take the
output of freerdp_image_copy() and cast to (unsigned char*) of colors.
We have to allocate an array of C's longs and copy the pixels there,
because that's what Xlib expects (and this is mentioned in the spec).
Simply casting an array of bytes causes crashes on 64-bit systems.
So don't try to cheat or "optimize" and read the docs, kids.
Note that XFlush() call after XChangeProperty(). It's there because it
seems to helps see the icon quicker with Unity on Ubuntu 14.04. I don't
know why. (And Unity does not support _NET_WM_ICON officially. But it
sorta kinda works sometimes.)
Oh, and while we're here, delete some old, unused, and commented out
code that was setting window icons in the past. It's not needed anymore.
2018-11-10 15:43:36 +03:00
|
|
|
nextPixel += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
free(argbPixels);
|
2018-11-10 12:51:30 +03:00
|
|
|
return TRUE;
|
xfreerdp: set _NET_WM_ICON to RAIL app icon
Icons on X11 windows are configured using the _NET_WM_ICON property
described in Extended Window Manager Hints. Here we implement converison
from DIB bitmaps used by RAIL to the format expected by _NET_WM_ICON,
and actually set the icon for RAIL app windows.
Both DIB format and _NET_WM_ICON (or rather, Xlib) are weird. Let's
start with RAIL's format. That's the one used in BMP and ICO formats
on Windows. It has some strange properties but thankfully FreeRDP's
freerdp_image_copy() can handle most of them for us. (With an exception
of monochrome and 16-color formats that it does not support. Sorry, but
I'm too lazy to fix them. They are not seem to be used by any real
application either.) The one thing that it can't do is to apply the
alpha transparency bitmask so we have to do it manually. This instantly
reminds us that DIB format has HISTORY: it's vertically flipped and
each must be padded to 4 bytes. Both these quirks having reasonable
(for a certain definition of 'reason') explanations. Such is life.
(Also, 8-bit images require a color palette which we must fill in.)
So okay, now comes _NET_WM_ICON. It is more sane (or rather, easier to
deal with). The bitmap is represented with a tiny [width, height] header
followed by an array of pixels in ARGB format. There is no padding, no
weird color formats. But here's a catch: you can't simply take the
output of freerdp_image_copy() and cast to (unsigned char*) of colors.
We have to allocate an array of C's longs and copy the pixels there,
because that's what Xlib expects (and this is mentioned in the spec).
Simply casting an array of bytes causes crashes on 64-bit systems.
So don't try to cheat or "optimize" and read the docs, kids.
Note that XFlush() call after XChangeProperty(). It's there because it
seems to helps see the icon quicker with Unity on Ubuntu 14.04. I don't
know why. (And Unity does not support _NET_WM_ICON officially. But it
sorta kinda works sometimes.)
Oh, and while we're here, delete some old, unused, and commented out
code that was setting window icons in the past. It's not needed anymore.
2018-11-10 15:43:36 +03:00
|
|
|
error:
|
|
|
|
free(argbPixels);
|
|
|
|
return FALSE;
|
2018-11-10 12:51:30 +03:00
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static void xf_rail_set_window_icon(xfContext* xfc, xfAppWindow* railWindow, xfRailIcon* icon,
|
2018-11-10 12:51:30 +03:00
|
|
|
BOOL replace)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
XChangeProperty(xfc->display, railWindow->handle, xfc->_NET_WM_ICON, XA_CARDINAL, 32,
|
|
|
|
replace ? PropModeReplace : PropModeAppend, (unsigned char*)icon->data,
|
|
|
|
icon->length);
|
xfreerdp: set _NET_WM_ICON to RAIL app icon
Icons on X11 windows are configured using the _NET_WM_ICON property
described in Extended Window Manager Hints. Here we implement converison
from DIB bitmaps used by RAIL to the format expected by _NET_WM_ICON,
and actually set the icon for RAIL app windows.
Both DIB format and _NET_WM_ICON (or rather, Xlib) are weird. Let's
start with RAIL's format. That's the one used in BMP and ICO formats
on Windows. It has some strange properties but thankfully FreeRDP's
freerdp_image_copy() can handle most of them for us. (With an exception
of monochrome and 16-color formats that it does not support. Sorry, but
I'm too lazy to fix them. They are not seem to be used by any real
application either.) The one thing that it can't do is to apply the
alpha transparency bitmask so we have to do it manually. This instantly
reminds us that DIB format has HISTORY: it's vertically flipped and
each must be padded to 4 bytes. Both these quirks having reasonable
(for a certain definition of 'reason') explanations. Such is life.
(Also, 8-bit images require a color palette which we must fill in.)
So okay, now comes _NET_WM_ICON. It is more sane (or rather, easier to
deal with). The bitmap is represented with a tiny [width, height] header
followed by an array of pixels in ARGB format. There is no padding, no
weird color formats. But here's a catch: you can't simply take the
output of freerdp_image_copy() and cast to (unsigned char*) of colors.
We have to allocate an array of C's longs and copy the pixels there,
because that's what Xlib expects (and this is mentioned in the spec).
Simply casting an array of bytes causes crashes on 64-bit systems.
So don't try to cheat or "optimize" and read the docs, kids.
Note that XFlush() call after XChangeProperty(). It's there because it
seems to helps see the icon quicker with Unity on Ubuntu 14.04. I don't
know why. (And Unity does not support _NET_WM_ICON officially. But it
sorta kinda works sometimes.)
Oh, and while we're here, delete some old, unused, and commented out
code that was setting window icons in the past. It's not needed anymore.
2018-11-10 15:43:36 +03:00
|
|
|
XFlush(xfc->display);
|
2018-11-10 12:51:30 +03:00
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static BOOL xf_rail_window_icon(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
|
|
|
const WINDOW_ICON_ORDER* windowIcon)
|
2014-11-12 04:26:47 +03:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
xfContext* xfc = (xfContext*)context;
|
2018-11-10 12:51:30 +03:00
|
|
|
xfAppWindow* railWindow;
|
2018-11-14 13:04:59 +03:00
|
|
|
xfRailIcon* icon;
|
2018-11-10 12:51:30 +03:00
|
|
|
BOOL replaceIcon;
|
2019-05-08 16:36:20 +03:00
|
|
|
railWindow = xf_rail_get_window(xfc, orderInfo->windowId);
|
2018-11-14 13:04:59 +03:00
|
|
|
|
2014-11-12 04:26:47 +03:00
|
|
|
if (!railWindow)
|
2018-11-10 12:51:30 +03:00
|
|
|
return TRUE;
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
icon = RailIconCache_Lookup(xfc->railIconCache, windowIcon->iconInfo->cacheId,
|
2018-11-14 13:04:59 +03:00
|
|
|
windowIcon->iconInfo->cacheEntry);
|
|
|
|
|
2018-11-10 12:51:30 +03:00
|
|
|
if (!icon)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_WARN(TAG, "failed to get icon from cache %02X:%04X", windowIcon->iconInfo->cacheId,
|
2018-11-14 13:04:59 +03:00
|
|
|
windowIcon->iconInfo->cacheEntry);
|
2015-04-14 11:14:23 +03:00
|
|
|
return FALSE;
|
2018-11-10 12:51:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!convert_rail_icon(windowIcon->iconInfo, icon))
|
|
|
|
{
|
2018-11-14 13:04:59 +03:00
|
|
|
WLog_WARN(TAG, "failed to convert icon for window %08X", orderInfo->windowId);
|
|
|
|
return FALSE;
|
2018-11-10 12:51:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
replaceIcon = !!(orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW);
|
|
|
|
xf_rail_set_window_icon(xfc, railWindow, icon, replaceIcon);
|
2017-03-28 12:47:46 +03:00
|
|
|
return TRUE;
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static BOOL xf_rail_window_cached_icon(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
|
|
|
const WINDOW_CACHED_ICON_ORDER* windowCachedIcon)
|
2014-11-12 04:26:47 +03:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
xfContext* xfc = (xfContext*)context;
|
2018-11-10 12:51:30 +03:00
|
|
|
xfAppWindow* railWindow;
|
2018-11-14 13:04:59 +03:00
|
|
|
xfRailIcon* icon;
|
2018-11-10 12:51:30 +03:00
|
|
|
BOOL replaceIcon;
|
2019-05-08 16:36:20 +03:00
|
|
|
railWindow = xf_rail_get_window(xfc, orderInfo->windowId);
|
2018-11-14 13:04:59 +03:00
|
|
|
|
2018-11-10 12:51:30 +03:00
|
|
|
if (!railWindow)
|
|
|
|
return TRUE;
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
icon = RailIconCache_Lookup(xfc->railIconCache, windowCachedIcon->cachedIcon.cacheId,
|
2018-11-14 13:04:59 +03:00
|
|
|
windowCachedIcon->cachedIcon.cacheEntry);
|
|
|
|
|
2018-11-10 12:51:30 +03:00
|
|
|
if (!icon)
|
|
|
|
{
|
2018-11-14 13:04:59 +03:00
|
|
|
WLog_WARN(TAG, "failed to get icon from cache %02X:%04X",
|
2019-11-06 17:24:51 +03:00
|
|
|
windowCachedIcon->cachedIcon.cacheId, windowCachedIcon->cachedIcon.cacheEntry);
|
2018-11-10 12:51:30 +03:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
replaceIcon = !!(orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW);
|
|
|
|
xf_rail_set_window_icon(xfc, railWindow, icon, replaceIcon);
|
2015-04-14 11:14:23 +03:00
|
|
|
return TRUE;
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static BOOL xf_rail_notify_icon_common(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
|
|
|
const NOTIFY_ICON_STATE_ORDER* notifyIconState)
|
2014-11-12 04:26:47 +03:00
|
|
|
{
|
|
|
|
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
if (orderInfo->fieldFlags & WINDOW_ORDER_ICON)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
if (orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON)
|
|
|
|
{
|
|
|
|
}
|
2016-08-03 15:16:20 +03:00
|
|
|
|
2015-04-14 11:14:23 +03:00
|
|
|
return TRUE;
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static BOOL xf_rail_notify_icon_create(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
|
|
|
const NOTIFY_ICON_STATE_ORDER* notifyIconState)
|
2014-11-12 04:26:47 +03:00
|
|
|
{
|
2015-04-14 11:14:23 +03:00
|
|
|
return xf_rail_notify_icon_common(context, orderInfo, notifyIconState);
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static BOOL xf_rail_notify_icon_update(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
|
|
|
const NOTIFY_ICON_STATE_ORDER* notifyIconState)
|
2014-11-12 04:26:47 +03:00
|
|
|
{
|
2015-04-14 11:14:23 +03:00
|
|
|
return xf_rail_notify_icon_common(context, orderInfo, notifyIconState);
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static BOOL xf_rail_notify_icon_delete(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo)
|
2014-11-12 04:26:47 +03:00
|
|
|
{
|
2015-04-14 11:14:23 +03:00
|
|
|
return TRUE;
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static BOOL xf_rail_monitored_desktop(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
|
|
|
const MONITORED_DESKTOP_ORDER* monitoredDesktop)
|
2014-11-12 04:26:47 +03:00
|
|
|
{
|
2015-04-21 15:15:53 +03:00
|
|
|
return TRUE;
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
static BOOL xf_rail_non_monitored_desktop(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo)
|
2014-11-12 04:26:47 +03:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
xfContext* xfc = (xfContext*)context;
|
2014-11-13 01:00:57 +03:00
|
|
|
xf_rail_disable_remoteapp_mode(xfc);
|
2015-04-14 11:14:23 +03:00
|
|
|
return TRUE;
|
2014-11-12 04:26:47 +03:00
|
|
|
}
|
|
|
|
|
2018-03-01 14:39:29 +03:00
|
|
|
static void xf_rail_register_update_callbacks(rdpUpdate* update)
|
2014-11-12 04:26:47 +03:00
|
|
|
{
|
|
|
|
rdpWindowUpdate* window = update->window;
|
|
|
|
window->WindowCreate = xf_rail_window_common;
|
|
|
|
window->WindowUpdate = xf_rail_window_common;
|
|
|
|
window->WindowDelete = xf_rail_window_delete;
|
|
|
|
window->WindowIcon = xf_rail_window_icon;
|
|
|
|
window->WindowCachedIcon = xf_rail_window_cached_icon;
|
|
|
|
window->NotifyIconCreate = xf_rail_notify_icon_create;
|
|
|
|
window->NotifyIconUpdate = xf_rail_notify_icon_update;
|
|
|
|
window->NotifyIconDelete = xf_rail_notify_icon_delete;
|
|
|
|
window->MonitoredDesktop = xf_rail_monitored_desktop;
|
|
|
|
window->NonMonitoredDesktop = xf_rail_non_monitored_desktop;
|
|
|
|
}
|
|
|
|
|
2014-11-12 01:49:29 +03:00
|
|
|
/* RemoteApp Virtual Channel Extension */
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
2016-08-03 15:16:20 +03:00
|
|
|
static UINT xf_rail_server_execute_result(RailClientContext* context,
|
2019-11-06 17:24:51 +03:00
|
|
|
const RAIL_EXEC_RESULT_ORDER* execResult)
|
2011-08-19 18:10:08 +04:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
xfContext* xfc = (xfContext*)context->custom;
|
2011-08-19 18:10:08 +04:00
|
|
|
|
2014-11-12 01:49:29 +03:00
|
|
|
if (execResult->execResult != RAIL_EXEC_S_OK)
|
2011-08-19 18:10:08 +04:00
|
|
|
{
|
2014-09-12 19:13:01 +04:00
|
|
|
WLog_ERR(TAG, "RAIL exec error: execResult=%s NtError=0x%X\n",
|
2016-10-04 10:00:00 +03:00
|
|
|
error_code_names[execResult->execResult], execResult->rawResult);
|
2016-09-13 10:53:16 +03:00
|
|
|
freerdp_abort_connect(xfc->context.instance);
|
2012-01-02 13:27:04 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-06-13 02:57:25 +04:00
|
|
|
xf_rail_enable_remoteapp_mode(xfc);
|
2011-08-19 18:10:08 +04:00
|
|
|
}
|
2014-11-12 01:49:29 +03:00
|
|
|
|
2015-06-08 19:04:05 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2011-08-19 18:10:08 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
2016-08-03 15:16:20 +03:00
|
|
|
static UINT xf_rail_server_system_param(RailClientContext* context,
|
2018-09-14 11:07:22 +03:00
|
|
|
const RAIL_SYSPARAM_ORDER* sysparam)
|
2011-08-20 02:46:10 +04:00
|
|
|
{
|
2019-02-19 16:13:34 +03:00
|
|
|
// TODO: Actually apply param
|
2015-06-08 19:04:05 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2011-08-20 02:46:10 +04:00
|
|
|
}
|
|
|
|
|
2019-02-19 16:13:34 +03:00
|
|
|
static UINT xf_rail_server_start_cmd(RailClientContext* context)
|
2011-08-20 02:46:10 +04:00
|
|
|
{
|
2018-12-05 11:13:04 +03:00
|
|
|
UINT status;
|
|
|
|
RAIL_EXEC_ORDER exec = { 0 };
|
|
|
|
RAIL_SYSPARAM_ORDER sysparam = { 0 };
|
|
|
|
RAIL_CLIENT_STATUS_ORDER clientStatus = { 0 };
|
2019-11-06 17:24:51 +03:00
|
|
|
xfContext* xfc = (xfContext*)context->custom;
|
2016-08-03 15:16:20 +03:00
|
|
|
rdpSettings* settings = xfc->context.settings;
|
2019-05-08 16:36:20 +03:00
|
|
|
clientStatus.flags = TS_RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE;
|
2018-12-05 11:13:04 +03:00
|
|
|
|
2019-02-19 16:13:34 +03:00
|
|
|
if (settings->AutoReconnectionEnabled)
|
2019-05-08 16:36:20 +03:00
|
|
|
clientStatus.flags |= TS_RAIL_CLIENTSTATUS_AUTORECONNECT;
|
2018-12-05 11:13:04 +03:00
|
|
|
|
2019-05-08 16:36:20 +03:00
|
|
|
clientStatus.flags |= TS_RAIL_CLIENTSTATUS_ZORDER_SYNC;
|
|
|
|
clientStatus.flags |= TS_RAIL_CLIENTSTATUS_WINDOW_RESIZE_MARGIN_SUPPORTED;
|
|
|
|
clientStatus.flags |= TS_RAIL_CLIENTSTATUS_APPBAR_REMOTING_SUPPORTED;
|
|
|
|
clientStatus.flags |= TS_RAIL_CLIENTSTATUS_POWER_DISPLAY_REQUEST_SUPPORTED;
|
|
|
|
clientStatus.flags |= TS_RAIL_CLIENTSTATUS_BIDIRECTIONAL_CLOAK_SUPPORTED;
|
2018-12-05 11:13:04 +03:00
|
|
|
status = context->ClientInformation(context, &clientStatus);
|
|
|
|
|
|
|
|
if (status != CHANNEL_RC_OK)
|
|
|
|
return status;
|
2011-09-01 02:02:22 +04:00
|
|
|
|
2014-11-12 01:49:29 +03:00
|
|
|
if (settings->RemoteAppLanguageBarSupported)
|
2011-09-01 02:02:22 +04:00
|
|
|
{
|
2014-11-12 01:49:29 +03:00
|
|
|
RAIL_LANGBAR_INFO_ORDER langBarInfo;
|
|
|
|
langBarInfo.languageBarStatus = 0x00000008; /* TF_SFT_HIDDEN */
|
2019-02-19 16:13:34 +03:00
|
|
|
status = context->ClientLanguageBarInfo(context, &langBarInfo);
|
|
|
|
|
2019-09-03 09:07:45 +03:00
|
|
|
/* We want the language bar, but the server might not support it. */
|
2019-11-06 17:24:51 +03:00
|
|
|
switch (status)
|
2019-09-03 09:07:45 +03:00
|
|
|
{
|
|
|
|
case CHANNEL_RC_OK:
|
|
|
|
case ERROR_BAD_CONFIGURATION:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return status;
|
|
|
|
}
|
2011-09-01 02:02:22 +04:00
|
|
|
}
|
2011-08-20 02:46:10 +04:00
|
|
|
|
2014-11-12 01:49:29 +03:00
|
|
|
sysparam.params = 0;
|
|
|
|
sysparam.params |= SPI_MASK_SET_HIGH_CONTRAST;
|
|
|
|
sysparam.highContrast.colorScheme.string = NULL;
|
|
|
|
sysparam.highContrast.colorScheme.length = 0;
|
|
|
|
sysparam.highContrast.flags = 0x7E;
|
|
|
|
sysparam.params |= SPI_MASK_SET_MOUSE_BUTTON_SWAP;
|
|
|
|
sysparam.mouseButtonSwap = FALSE;
|
|
|
|
sysparam.params |= SPI_MASK_SET_KEYBOARD_PREF;
|
|
|
|
sysparam.keyboardPref = FALSE;
|
|
|
|
sysparam.params |= SPI_MASK_SET_DRAG_FULL_WINDOWS;
|
|
|
|
sysparam.dragFullWindows = FALSE;
|
|
|
|
sysparam.params |= SPI_MASK_SET_KEYBOARD_CUES;
|
|
|
|
sysparam.keyboardCues = FALSE;
|
|
|
|
sysparam.params |= SPI_MASK_SET_WORK_AREA;
|
|
|
|
sysparam.workArea.left = 0;
|
|
|
|
sysparam.workArea.top = 0;
|
|
|
|
sysparam.workArea.right = settings->DesktopWidth;
|
|
|
|
sysparam.workArea.bottom = settings->DesktopHeight;
|
|
|
|
sysparam.dragFullWindows = FALSE;
|
2018-12-05 11:13:04 +03:00
|
|
|
status = context->ClientSystemParam(context, &sysparam);
|
|
|
|
|
|
|
|
if (status != CHANNEL_RC_OK)
|
|
|
|
return status;
|
|
|
|
|
2014-11-12 01:49:29 +03:00
|
|
|
exec.RemoteApplicationProgram = settings->RemoteApplicationProgram;
|
|
|
|
exec.RemoteApplicationWorkingDir = settings->ShellWorkingDirectory;
|
|
|
|
exec.RemoteApplicationArguments = settings->RemoteApplicationCmdLine;
|
2018-12-05 11:13:04 +03:00
|
|
|
return context->ClientExecute(context, &exec);
|
2011-08-20 02:46:10 +04:00
|
|
|
}
|
2019-02-19 16:13:34 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
|
|
|
static UINT xf_rail_server_handshake(RailClientContext* context,
|
|
|
|
const RAIL_HANDSHAKE_ORDER* handshake)
|
|
|
|
{
|
|
|
|
return xf_rail_server_start_cmd(context);
|
|
|
|
}
|
2011-08-20 02:46:10 +04:00
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
2016-08-03 15:16:20 +03:00
|
|
|
static UINT xf_rail_server_handshake_ex(RailClientContext* context,
|
2018-09-14 11:07:22 +03:00
|
|
|
const RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
|
2011-08-20 02:46:10 +04:00
|
|
|
{
|
2019-02-19 16:13:34 +03:00
|
|
|
return xf_rail_server_start_cmd(context);
|
2011-08-20 02:46:10 +04:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
2016-08-03 15:16:20 +03:00
|
|
|
static UINT xf_rail_server_local_move_size(RailClientContext* context,
|
2019-11-06 17:24:51 +03:00
|
|
|
const RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
|
2011-08-18 05:33:22 +04:00
|
|
|
{
|
2014-11-12 01:49:29 +03:00
|
|
|
int x = 0, y = 0;
|
|
|
|
int direction = 0;
|
|
|
|
Window child_window;
|
2019-11-06 17:24:51 +03:00
|
|
|
xfContext* xfc = (xfContext*)context->custom;
|
2019-05-08 16:36:20 +03:00
|
|
|
xfAppWindow* appWindow = xf_rail_get_window(xfc, localMoveSize->windowId);
|
2014-11-13 01:00:57 +03:00
|
|
|
|
|
|
|
if (!appWindow)
|
2015-06-08 19:04:05 +03:00
|
|
|
return ERROR_INTERNAL_ERROR;
|
2014-11-12 01:49:29 +03:00
|
|
|
|
|
|
|
switch (localMoveSize->moveSizeType)
|
2011-08-18 05:33:22 +04:00
|
|
|
{
|
2014-11-12 01:49:29 +03:00
|
|
|
case RAIL_WMSZ_LEFT:
|
|
|
|
direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
|
|
|
|
x = localMoveSize->posX;
|
|
|
|
y = localMoveSize->posY;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RAIL_WMSZ_RIGHT:
|
|
|
|
direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
|
|
|
|
x = localMoveSize->posX;
|
|
|
|
y = localMoveSize->posY;
|
2011-08-18 05:33:22 +04:00
|
|
|
break;
|
2014-08-18 21:34:47 +04:00
|
|
|
|
2014-11-12 01:49:29 +03:00
|
|
|
case RAIL_WMSZ_TOP:
|
|
|
|
direction = _NET_WM_MOVERESIZE_SIZE_TOP;
|
|
|
|
x = localMoveSize->posX;
|
|
|
|
y = localMoveSize->posY;
|
2011-08-19 18:10:08 +04:00
|
|
|
break;
|
2014-08-18 21:34:47 +04:00
|
|
|
|
2014-11-12 01:49:29 +03:00
|
|
|
case RAIL_WMSZ_TOPLEFT:
|
|
|
|
direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
|
|
|
|
x = localMoveSize->posX;
|
|
|
|
y = localMoveSize->posY;
|
2011-08-20 02:46:10 +04:00
|
|
|
break;
|
2014-08-18 21:34:47 +04:00
|
|
|
|
2014-11-12 01:49:29 +03:00
|
|
|
case RAIL_WMSZ_TOPRIGHT:
|
|
|
|
direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
|
|
|
|
x = localMoveSize->posX;
|
|
|
|
y = localMoveSize->posY;
|
2011-08-20 02:46:10 +04:00
|
|
|
break;
|
2014-08-18 21:34:47 +04:00
|
|
|
|
2014-11-12 01:49:29 +03:00
|
|
|
case RAIL_WMSZ_BOTTOM:
|
|
|
|
direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
|
|
|
|
x = localMoveSize->posX;
|
|
|
|
y = localMoveSize->posY;
|
2011-08-20 02:46:10 +04:00
|
|
|
break;
|
2014-08-18 21:34:47 +04:00
|
|
|
|
2014-11-12 01:49:29 +03:00
|
|
|
case RAIL_WMSZ_BOTTOMLEFT:
|
|
|
|
direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
|
|
|
|
x = localMoveSize->posX;
|
|
|
|
y = localMoveSize->posY;
|
2011-08-20 02:46:10 +04:00
|
|
|
break;
|
2014-08-18 21:34:47 +04:00
|
|
|
|
2014-11-12 01:49:29 +03:00
|
|
|
case RAIL_WMSZ_BOTTOMRIGHT:
|
|
|
|
direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
|
|
|
|
x = localMoveSize->posX;
|
|
|
|
y = localMoveSize->posY;
|
2011-08-20 02:46:10 +04:00
|
|
|
break;
|
2014-08-18 21:34:47 +04:00
|
|
|
|
2014-11-12 01:49:29 +03:00
|
|
|
case RAIL_WMSZ_MOVE:
|
|
|
|
direction = _NET_WM_MOVERESIZE_MOVE;
|
2019-11-06 17:24:51 +03:00
|
|
|
XTranslateCoordinates(xfc->display, appWindow->handle, RootWindowOfScreen(xfc->screen),
|
2016-10-04 10:00:00 +03:00
|
|
|
localMoveSize->posX, localMoveSize->posY, &x, &y, &child_window);
|
2011-08-18 05:33:22 +04:00
|
|
|
break;
|
2014-11-12 01:49:29 +03:00
|
|
|
|
|
|
|
case RAIL_WMSZ_KEYMOVE:
|
|
|
|
direction = _NET_WM_MOVERESIZE_MOVE_KEYBOARD;
|
|
|
|
x = localMoveSize->posX;
|
|
|
|
y = localMoveSize->posY;
|
|
|
|
/* FIXME: local keyboard moves not working */
|
2015-06-08 19:04:05 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2014-11-12 01:49:29 +03:00
|
|
|
|
|
|
|
case RAIL_WMSZ_KEYSIZE:
|
|
|
|
direction = _NET_WM_MOVERESIZE_SIZE_KEYBOARD;
|
|
|
|
x = localMoveSize->posX;
|
|
|
|
y = localMoveSize->posY;
|
|
|
|
/* FIXME: local keyboard moves not working */
|
2015-06-08 19:04:05 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2014-11-12 01:49:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (localMoveSize->isMoveSizeStart)
|
2014-11-12 06:27:33 +03:00
|
|
|
xf_StartLocalMoveSize(xfc, appWindow, direction, x, y);
|
2014-11-12 01:49:29 +03:00
|
|
|
else
|
2014-11-12 06:27:33 +03:00
|
|
|
xf_EndLocalMoveSize(xfc, appWindow);
|
2014-11-12 01:49:29 +03:00
|
|
|
|
2015-06-08 19:04:05 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2014-11-12 01:49:29 +03:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
2016-08-03 15:16:20 +03:00
|
|
|
static UINT xf_rail_server_min_max_info(RailClientContext* context,
|
2018-09-14 11:07:22 +03:00
|
|
|
const RAIL_MINMAXINFO_ORDER* minMaxInfo)
|
2014-11-12 01:49:29 +03:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
xfContext* xfc = (xfContext*)context->custom;
|
2019-05-08 16:36:20 +03:00
|
|
|
xfAppWindow* appWindow = xf_rail_get_window(xfc, minMaxInfo->windowId);
|
2014-11-13 01:00:57 +03:00
|
|
|
|
2018-02-08 18:53:09 +03:00
|
|
|
if (appWindow)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
xf_SetWindowMinMaxInfo(xfc, appWindow, minMaxInfo->maxWidth, minMaxInfo->maxHeight,
|
|
|
|
minMaxInfo->maxPosX, minMaxInfo->maxPosY, minMaxInfo->minTrackWidth,
|
|
|
|
minMaxInfo->minTrackHeight, minMaxInfo->maxTrackWidth,
|
|
|
|
minMaxInfo->maxTrackHeight);
|
2018-02-08 18:53:09 +03:00
|
|
|
}
|
2014-11-12 01:49:29 +03:00
|
|
|
|
2015-06-08 19:04:05 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2014-11-12 01:49:29 +03:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
2016-08-03 15:16:20 +03:00
|
|
|
static UINT xf_rail_server_language_bar_info(RailClientContext* context,
|
2019-11-06 17:24:51 +03:00
|
|
|
const RAIL_LANGBAR_INFO_ORDER* langBarInfo)
|
2014-11-12 01:49:29 +03:00
|
|
|
{
|
2015-06-08 19:04:05 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2014-11-12 01:49:29 +03:00
|
|
|
}
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
2016-08-03 15:16:20 +03:00
|
|
|
static UINT xf_rail_server_get_appid_response(RailClientContext* context,
|
2019-11-06 17:24:51 +03:00
|
|
|
const RAIL_GET_APPID_RESP_ORDER* getAppIdResp)
|
2014-11-12 01:49:29 +03:00
|
|
|
{
|
2015-06-08 19:04:05 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2011-08-16 08:22:00 +04:00
|
|
|
}
|
2014-11-12 00:35:30 +03:00
|
|
|
|
2018-12-10 13:16:43 +03:00
|
|
|
static BOOL rail_window_key_equals(void* key1, void* key2)
|
2018-12-07 12:33:07 +03:00
|
|
|
{
|
2019-05-08 16:36:20 +03:00
|
|
|
const UINT64* k1 = (const UINT64*)key1;
|
|
|
|
const UINT64* k2 = (const UINT64*)key2;
|
|
|
|
|
|
|
|
if (!k1 || !k2)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return *k1 == *k2;
|
2018-12-10 13:16:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static UINT32 rail_window_key_hash(void* key)
|
|
|
|
{
|
2019-05-08 16:36:20 +03:00
|
|
|
const UINT64* k1 = (const UINT64*)key;
|
2019-11-06 17:24:51 +03:00
|
|
|
return (UINT32)*k1;
|
2018-12-07 12:33:07 +03:00
|
|
|
}
|
|
|
|
|
2018-02-09 11:35:26 +03:00
|
|
|
static void rail_window_free(void* value)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
xfAppWindow* appWindow = (xfAppWindow*)value;
|
2018-02-09 11:35:26 +03:00
|
|
|
|
|
|
|
if (!appWindow)
|
|
|
|
return;
|
|
|
|
|
|
|
|
xf_DestroyWindow(appWindow->xfc, appWindow);
|
|
|
|
}
|
|
|
|
|
2014-11-12 00:35:30 +03:00
|
|
|
int xf_rail_init(xfContext* xfc, RailClientContext* rail)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
rdpContext* context = (rdpContext*)xfc;
|
2018-02-09 11:35:26 +03:00
|
|
|
|
|
|
|
if (!xfc || !rail)
|
|
|
|
return 0;
|
|
|
|
|
2014-11-12 00:35:30 +03:00
|
|
|
xfc->rail = rail;
|
2014-11-13 00:42:32 +03:00
|
|
|
xf_rail_register_update_callbacks(context->update);
|
2019-11-06 17:24:51 +03:00
|
|
|
rail->custom = (void*)xfc;
|
2014-11-12 04:26:47 +03:00
|
|
|
rail->ServerExecuteResult = xf_rail_server_execute_result;
|
|
|
|
rail->ServerSystemParam = xf_rail_server_system_param;
|
|
|
|
rail->ServerHandshake = xf_rail_server_handshake;
|
|
|
|
rail->ServerHandshakeEx = xf_rail_server_handshake_ex;
|
|
|
|
rail->ServerLocalMoveSize = xf_rail_server_local_move_size;
|
|
|
|
rail->ServerMinMaxInfo = xf_rail_server_min_max_info;
|
|
|
|
rail->ServerLanguageBarInfo = xf_rail_server_language_bar_info;
|
|
|
|
rail->ServerGetAppIdResponse = xf_rail_server_get_appid_response;
|
2018-12-07 12:33:07 +03:00
|
|
|
xfc->railWindows = HashTable_New(TRUE);
|
2018-12-10 13:16:43 +03:00
|
|
|
|
2015-05-18 12:28:00 +03:00
|
|
|
if (!xfc->railWindows)
|
|
|
|
return 0;
|
2018-12-10 13:16:43 +03:00
|
|
|
|
2018-12-07 12:33:07 +03:00
|
|
|
xfc->railWindows->keyCompare = rail_window_key_equals;
|
2018-12-10 13:16:43 +03:00
|
|
|
xfc->railWindows->hash = rail_window_key_hash;
|
2018-02-09 11:35:26 +03:00
|
|
|
xfc->railWindows->valueFree = rail_window_free;
|
2018-11-10 12:51:30 +03:00
|
|
|
xfc->railIconCache = RailIconCache_New(xfc->context.settings);
|
|
|
|
|
|
|
|
if (!xfc->railIconCache)
|
|
|
|
{
|
|
|
|
HashTable_Free(xfc->railWindows);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-11-12 00:35:30 +03:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int xf_rail_uninit(xfContext* xfc, RailClientContext* rail)
|
|
|
|
{
|
2019-02-07 19:53:21 +03:00
|
|
|
WINPR_UNUSED(rail);
|
2019-05-08 16:36:20 +03:00
|
|
|
|
2014-11-12 00:35:30 +03:00
|
|
|
if (xfc->rail)
|
|
|
|
{
|
|
|
|
xfc->rail->custom = NULL;
|
|
|
|
xfc->rail = NULL;
|
|
|
|
}
|
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
if (xfc->railWindows)
|
|
|
|
{
|
|
|
|
HashTable_Free(xfc->railWindows);
|
|
|
|
xfc->railWindows = NULL;
|
|
|
|
}
|
|
|
|
|
2018-11-10 12:51:30 +03:00
|
|
|
if (xfc->railIconCache)
|
|
|
|
{
|
|
|
|
RailIconCache_Free(xfc->railIconCache);
|
|
|
|
xfc->railIconCache = NULL;
|
|
|
|
}
|
|
|
|
|
2014-11-12 00:35:30 +03:00
|
|
|
return 1;
|
|
|
|
}
|
2019-05-08 16:36:20 +03:00
|
|
|
|
|
|
|
xfAppWindow* xf_rail_add_window(xfContext* xfc, UINT64 id, UINT32 x, UINT32 y, UINT32 width,
|
|
|
|
UINT32 height, UINT32 surfaceId)
|
|
|
|
{
|
|
|
|
xfAppWindow* appWindow;
|
|
|
|
|
|
|
|
if (!xfc)
|
|
|
|
return NULL;
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
appWindow = (xfAppWindow*)calloc(1, sizeof(xfAppWindow));
|
2019-05-08 16:36:20 +03:00
|
|
|
|
|
|
|
if (!appWindow)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
appWindow->xfc = xfc;
|
|
|
|
appWindow->windowId = id;
|
|
|
|
appWindow->surfaceId = surfaceId;
|
|
|
|
appWindow->x = x;
|
|
|
|
appWindow->y = y;
|
|
|
|
appWindow->width = width;
|
|
|
|
appWindow->height = height;
|
|
|
|
xf_AppWindowCreate(xfc, appWindow);
|
2019-11-06 17:24:51 +03:00
|
|
|
HashTable_Add(xfc->railWindows, &appWindow->windowId, (void*)appWindow);
|
2019-05-08 16:36:20 +03:00
|
|
|
return appWindow;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL xf_rail_del_window(xfContext* xfc, UINT64 id)
|
|
|
|
{
|
|
|
|
if (!xfc)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!xfc->railWindows)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return HashTable_Remove(xfc->railWindows, &id);
|
|
|
|
}
|
|
|
|
|
|
|
|
xfAppWindow* xf_rail_get_window(xfContext* xfc, UINT64 id)
|
|
|
|
{
|
|
|
|
if (!xfc)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!xfc->railWindows)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return HashTable_GetItemValue(xfc->railWindows, &id);
|
|
|
|
}
|