xfreerdp: separate app windows from desktop windows

This commit is contained in:
Marc-André Moreau 2014-11-11 22:27:33 -05:00
parent fb5e33440c
commit 1225c6b5ce
9 changed files with 592 additions and 516 deletions

View File

@ -62,7 +62,7 @@ struct X11Handle
static const char* get_shm_id()
{
static char shm_id[64];
snprintf(shm_id, sizeof(shm_id), "com.freerdp.xfreerpd.tsmf_%016X", GetCurrentProcessId());
snprintf(shm_id, sizeof(shm_id), "com.freerdp.xfreerdp.tsmf_%016X", GetCurrentProcessId());
return shm_id;
}

View File

@ -104,7 +104,7 @@
static const size_t password_size = 512;
void xf_transform_window(xfContext *xfc)
void xf_transform_window(xfContext* xfc)
{
int ret;
int w;
@ -133,7 +133,7 @@ void xf_transform_window(xfContext *xfc)
}
}
void xf_draw_screen_scaled(xfContext *xfc, int x, int y, int w, int h, BOOL scale)
void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h, BOOL scale)
{
#ifdef WITH_XRENDER
XTransform transform;
@ -142,10 +142,13 @@ void xf_draw_screen_scaled(xfContext *xfc, int x, int y, int w, int h, BOOL scal
XRenderPictureAttributes pa;
XRenderPictFormat *picFormat;
XRectangle xr;
picFormat = XRenderFindStandardFormat(xfc->display, PictStandardRGB24);
pa.subwindow_mode = IncludeInferiors;
primaryPicture = XRenderCreatePicture(xfc->display, xfc->primary, picFormat, CPSubwindowMode, &pa);
windowPicture = XRenderCreatePicture(xfc->display, xfc->window->handle, picFormat, CPSubwindowMode, &pa);
transform.matrix[0][0] = XDoubleToFixed(1);
transform.matrix[0][1] = XDoubleToFixed(0);
transform.matrix[0][2] = XDoubleToFixed(0);
@ -155,9 +158,10 @@ void xf_draw_screen_scaled(xfContext *xfc, int x, int y, int w, int h, BOOL scal
transform.matrix[2][0] = XDoubleToFixed(0);
transform.matrix[2][1] = XDoubleToFixed(0);
transform.matrix[2][2] = XDoubleToFixed(xfc->settings->ScalingFactor);
if ((w != 0) && (h != 0))
{
if (scale == TRUE)
if (scale)
{
xr.x = x * xfc->settings->ScalingFactor;
xr.y = y * xfc->settings->ScalingFactor;
@ -171,8 +175,10 @@ void xf_draw_screen_scaled(xfContext *xfc, int x, int y, int w, int h, BOOL scal
xr.width = w;
xr.height = h;
}
XRenderSetPictureClipRectangles(xfc->display, primaryPicture, 0, 0, &xr, 1);
}
XRenderSetPictureTransform(xfc->display, primaryPicture, &transform);
XRenderComposite(xfc->display, PictOpSrc, primaryPicture, 0, windowPicture, 0, 0, 0, 0, xfc->offset_x, xfc->offset_y, xfc->currentWidth, xfc->currentHeight);
XRenderFreePicture(xfc->display, primaryPicture);
@ -180,14 +186,14 @@ void xf_draw_screen_scaled(xfContext *xfc, int x, int y, int w, int h, BOOL scal
#endif
}
void xf_sw_begin_paint(rdpContext *context)
void xf_sw_begin_paint(rdpContext* context)
{
rdpGdi* gdi = context->gdi;
gdi->primary->hdc->hwnd->invalid->null = 1;
gdi->primary->hdc->hwnd->ninvalid = 0;
}
void xf_sw_end_paint(rdpContext *context)
void xf_sw_end_paint(rdpContext* context)
{
int i;
INT32 x, y;
@ -295,14 +301,14 @@ void xf_sw_desktop_resize(rdpContext* context)
xf_unlock_x11(xfc, TRUE);
}
void xf_hw_begin_paint(rdpContext *context)
void xf_hw_begin_paint(rdpContext* context)
{
xfContext* xfc = (xfContext*) context;
xfc->hdc->hwnd->invalid->null = 1;
xfc->hdc->hwnd->ninvalid = 0;
}
void xf_hw_end_paint(rdpContext *context)
void xf_hw_end_paint(rdpContext* context)
{
INT32 x, y;
UINT32 w, h;
@ -387,12 +393,12 @@ void xf_hw_end_paint(rdpContext *context)
}
}
void xf_hw_desktop_resize(rdpContext *context)
void xf_hw_desktop_resize(rdpContext* context)
{
BOOL same;
rdpSettings *settings;
xfContext *xfc = (xfContext *) context;
settings = xfc->instance->settings;
rdpSettings* settings;
xfContext* xfc = (xfContext*) context;
settings = xfc->settings;
xf_lock_x11(xfc, TRUE);
@ -428,30 +434,35 @@ void xf_hw_desktop_resize(rdpContext *context)
BOOL xf_get_fds(freerdp *instance, void **rfds, int *rcount, void **wfds, int *wcount)
{
xfContext *xfc = (xfContext *) instance->context;
xfContext* xfc = (xfContext*) instance->context;
rfds[*rcount] = (void *)(long)(xfc->xfds);
(*rcount)++;
return TRUE;
}
BOOL xf_process_x_events(freerdp *instance)
BOOL xf_process_x_events(freerdp* instance)
{
BOOL status;
XEvent xevent;
int pending_status;
xfContext *xfc = (xfContext *) instance->context;
xfContext* xfc = (xfContext*) instance->context;
status = TRUE;
pending_status = TRUE;
while(pending_status)
while (pending_status)
{
xf_lock_x11(xfc, FALSE);
pending_status = XPending(xfc->display);
xf_unlock_x11(xfc, FALSE);
if (pending_status)
{
ZeroMemory(&xevent, sizeof(xevent));
XNextEvent(xfc->display, &xevent);
status = xf_event_process(instance, &xevent);
if (!status)
return status;
}
@ -459,14 +470,17 @@ BOOL xf_process_x_events(freerdp *instance)
return status;
}
void xf_create_window(xfContext *xfc)
void xf_create_window(xfContext* xfc)
{
XEvent xevent;
int width, height;
char *windowTitle;
char* windowTitle;
ZeroMemory(&xevent, sizeof(xevent));
width = xfc->width;
height = xfc->height;
if (!xfc->remote_app)
{
xfc->attribs.background_pixel = BlackPixelOfScreen(xfc->screen);
@ -476,25 +490,29 @@ void xf_create_window(xfContext *xfc)
xfc->attribs.colormap = xfc->colormap;
xfc->attribs.bit_gravity = NorthWestGravity;
xfc->attribs.win_gravity = NorthWestGravity;
if (xfc->instance->settings->WindowTitle)
if (xfc->settings->WindowTitle)
{
windowTitle = _strdup(xfc->instance->settings->WindowTitle);
windowTitle = _strdup(xfc->settings->WindowTitle);
}
else if (xfc->settings->ServerPort == 3389)
{
windowTitle = malloc(1 + sizeof("FreeRDP: ") + strlen(xfc->settings->ServerHostname));
sprintf(windowTitle, "FreeRDP: %s", xfc->settings->ServerHostname);
}
else
if (xfc->instance->settings->ServerPort == 3389)
{
windowTitle = malloc(1 + sizeof("FreeRDP: ") + strlen(xfc->instance->settings->ServerHostname));
sprintf(windowTitle, "FreeRDP: %s", xfc->instance->settings->ServerHostname);
}
else
{
windowTitle = malloc(1 + sizeof("FreeRDP: ") + strlen(xfc->instance->settings->ServerHostname) + sizeof(":00000"));
sprintf(windowTitle, "FreeRDP: %s:%i", xfc->instance->settings->ServerHostname, xfc->instance->settings->ServerPort);
}
{
windowTitle = malloc(1 + sizeof("FreeRDP: ") + strlen(xfc->settings->ServerHostname) + sizeof(":00000"));
sprintf(windowTitle, "FreeRDP: %s:%i", xfc->settings->ServerHostname, xfc->settings->ServerPort);
}
xfc->window = xf_CreateDesktopWindow(xfc, windowTitle, width, height, xfc->settings->Decorations);
free(windowTitle);
if (xfc->fullscreen)
xf_SetWindowFullscreen(xfc, xfc->window, xfc->fullscreen);
xfc->unobscured = (xevent.xvisibility.state == VisibilityUnobscured);
XSetWMProtocols(xfc->display, xfc->window->handle, &(xfc->WM_DELETE_WINDOW), 1);
xfc->drawable = xfc->window->handle;
@ -509,15 +527,23 @@ void xf_toggle_fullscreen(xfContext* xfc)
{
Pixmap contents = 0;
WindowStateChangeEventArgs e;
xf_lock_x11(xfc, TRUE);
contents = XCreatePixmap(xfc->display, xfc->window->handle, xfc->width, xfc->height, xfc->depth);
XCopyArea(xfc->display, xfc->primary, contents, xfc->gc, 0, 0, xfc->width, xfc->height, 0, 0);
XDestroyWindow(xfc->display, xfc->window->handle);
xfc->fullscreen = (xfc->fullscreen) ? FALSE : TRUE;
xf_create_window(xfc);
XCopyArea(xfc->display, contents, xfc->primary, xfc->gc, 0, 0, xfc->width, xfc->height, 0, 0);
XFreePixmap(xfc->display, contents);
xf_unlock_x11(xfc, TRUE);
EventArgsInit(&e, "xfreerdp");
e.state = xfc->fullscreen ? FREERDP_WINDOW_STATE_FULLSCREEN : 0;
PubSub_OnWindowStateChange(((rdpContext *) xfc)->pubSub, xfc, &e);
@ -546,14 +572,6 @@ void xf_toggle_control(xfContext* xfc)
int xf_encomsp_participant_created(EncomspClientContext* context, ENCOMSP_PARTICIPANT_CREATED_PDU* participantCreated)
{
#if 0
xfContext* xfc = (xfContext*) context->custom;
WLog_INFO(TAG, "ParticipantCreated: ParticipantId: %d GroupId: %d Flags: 0x%04X xfc: %p",
(int) participantCreated->ParticipantId, (int) participantCreated->GroupId,
(int) participantCreated->Flags, xfc);
#endif
return 1;
}
@ -570,7 +588,7 @@ void xf_encomsp_uninit(xfContext* xfc, EncomspClientContext* encomsp)
xfc->encomsp = NULL;
}
void xf_lock_x11(xfContext *xfc, BOOL display)
void xf_lock_x11(xfContext* xfc, BOOL display)
{
if (!xfc->UseXThreads)
{
@ -583,7 +601,7 @@ void xf_lock_x11(xfContext *xfc, BOOL display)
}
}
void xf_unlock_x11(xfContext *xfc, BOOL display)
void xf_unlock_x11(xfContext* xfc, BOOL display)
{
if (!xfc->UseXThreads)
{
@ -596,7 +614,7 @@ void xf_unlock_x11(xfContext *xfc, BOOL display)
}
}
BOOL xf_get_pixmap_info(xfContext *xfc)
BOOL xf_get_pixmap_info(xfContext* xfc)
{
int i;
int vi_count;
@ -607,9 +625,10 @@ BOOL xf_get_pixmap_info(xfContext *xfc)
XPixmapFormatValues *pf;
XPixmapFormatValues *pfs;
XWindowAttributes window_attributes;
pfs = XListPixmapFormats(xfc->display, &pf_count);
if (pfs == NULL)
if (!pfs)
{
WLog_ERR(TAG, "XListPixmapFormats failed");
return 1;
@ -641,7 +660,7 @@ BOOL xf_get_pixmap_info(xfContext *xfc)
vis = XGetVisualInfo(xfc->display, VisualClassMask | VisualScreenMask, &template, &vi_count);
if (vis == NULL)
if (!vis)
{
WLog_ERR(TAG, "XGetVisualInfo failed");
return FALSE;
@ -683,19 +702,24 @@ BOOL xf_get_pixmap_info(xfContext *xfc)
static int (*_def_error_handler)(Display *, XErrorEvent *);
int xf_error_handler(Display *d, XErrorEvent *ev)
int xf_error_handler(Display* d, XErrorEvent* ev)
{
char buf[256];
int do_abort = TRUE;
XGetErrorText(d, ev->error_code, buf, sizeof(buf));
WLog_ERR(TAG, "%s", buf);
WLog_ERR(TAG, "%s", buf);
if (do_abort)
abort();
_def_error_handler(d, ev);
return FALSE;
}
int _xf_error_handler(Display *d, XErrorEvent *ev)
int _xf_error_handler(Display* d, XErrorEvent* ev)
{
/*
* ungrab the keyboard, in case a debugger is running in
@ -706,18 +730,22 @@ int _xf_error_handler(Display *d, XErrorEvent *ev)
return xf_error_handler(d, ev);
}
static void xf_post_disconnect(freerdp *instance)
static void xf_post_disconnect(freerdp* instance)
{
xfContext *xfc = (xfContext *) instance->context;
assert(NULL != instance);
assert(NULL != xfc);
assert(NULL != instance->settings);
xfContext* xfc;
if (!instance || !instance->context || !instance->settings)
return;
xfc = (xfContext*) instance->context;
if (xfc->mutex)
{
WaitForSingleObject(xfc->mutex, INFINITE);
CloseHandle(xfc->mutex);
xfc->mutex = NULL;
}
xf_monitors_free(xfc, instance->settings);
}
@ -727,11 +755,12 @@ static void xf_play_sound(rdpContext* context, PLAY_SOUND_UPDATE* play_sound)
XkbBell(xfc->display, None, 100, 0);
}
void xf_check_extensions(xfContext *context)
void xf_check_extensions(xfContext* context)
{
int xkb_opcode, xkb_event, xkb_error;
int xkb_major = XkbMajorVersion;
int xkb_minor = XkbMinorVersion;
if (XkbLibraryVersion( &xkb_major, &xkb_minor ) && XkbQueryExtension(context->display, &xkb_opcode, &xkb_event,
&xkb_error, &xkb_major, &xkb_minor))
{
@ -1039,8 +1068,10 @@ BOOL xf_authenticate(freerdp *instance, char **username, char **password, char *
// FIXME: seems this callback may be called when 'username' is not known.
// But it doesn't do anything to fix it...
*password = malloc(password_size * sizeof(char));
if (freerdp_passphrase_read("Password: ", *password, password_size, instance->settings->CredentialsFromStdin) == NULL)
return FALSE;
return TRUE;
}
@ -1054,9 +1085,10 @@ BOOL xf_authenticate(freerdp *instance, char **username, char **password, char *
* @param fingerprint
* @return TRUE if the certificate is trusted. FALSE otherwise.
*/
BOOL xf_verify_certificate(freerdp *instance, char *subject, char *issuer, char *fingerprint)
BOOL xf_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint)
{
char answer;
WLog_INFO(TAG, "Certificate details:");
WLog_INFO(TAG, "\tSubject: %s", subject);
WLog_INFO(TAG, "\tIssuer: %s", issuer);
@ -1064,10 +1096,12 @@ BOOL xf_verify_certificate(freerdp *instance, char *subject, char *issuer, char
WLog_INFO(TAG, "The above X.509 certificate could not be verified, possibly because you do not have "
"the CA certificate in your certificate store, or the certificate has expired. "
"Please look at the documentation on how to create local certificate store for a private CA.");
while(1)
while (1)
{
WLog_INFO(TAG, "Do you trust the above certificate? (Y/N) ");
answer = fgetc(stdin);
if (feof(stdin))
{
WLog_INFO(TAG, "Error: Could not read answer from stdin.");
@ -1076,28 +1110,30 @@ BOOL xf_verify_certificate(freerdp *instance, char *subject, char *issuer, char
WLog_INFO(TAG, "");
return FALSE;
}
if (answer == 'y' || answer == 'Y')
{
return TRUE;
}
else
if (answer == 'n' || answer == 'N')
{
break;
}
else if (answer == 'n' || answer == 'N')
{
break;
}
WLog_INFO(TAG, "");
}
return FALSE;
}
int xf_logon_error_info(freerdp *instance, UINT32 data, UINT32 type)
int xf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
{
xfContext *xfc = (xfContext *) instance->context;
xfContext* xfc = (xfContext*) instance->context;
xf_rail_disable_remoteapp_mode(xfc);
return 1;
}
void xf_window_free(xfContext *xfc)
void xf_window_free(xfContext* xfc)
{
rdpContext* context = (rdpContext*) xfc;
@ -1117,7 +1153,7 @@ void xf_window_free(xfContext *xfc)
if (xfc->window)
{
xf_DestroyWindow(xfc, xfc->window);
xf_DestroyDesktopWindow(xfc, xfc->window);
xfc->window = NULL;
}
@ -1146,12 +1182,6 @@ void xf_window_free(xfContext *xfc)
context->cache = NULL;
}
if (context->rail)
{
rail_free(context->rail);
context->rail = NULL;
}
if (xfc->hdc)
{
gdi_DeleteDC(xfc->hdc);
@ -1172,13 +1202,13 @@ void xf_window_free(xfContext *xfc)
void* xf_input_thread(void *arg)
{
xfContext *xfc;
xfContext* xfc;
HANDLE event;
XEvent xevent;
wMessageQueue *queue;
int pending_status = 1;
int process_status = 1;
freerdp *instance = (freerdp *) arg;
freerdp *instance = (freerdp*) arg;
assert(NULL != instance);
xfc = (xfContext *) instance->context;
assert(NULL != xfc);
@ -1196,9 +1226,12 @@ void* xf_input_thread(void *arg)
if (pending_status)
{
xf_lock_x11(xfc, FALSE);
ZeroMemory(&xevent, sizeof(xevent));
XNextEvent(xfc->display, &xevent);
process_status = xf_event_process(instance, &xevent);
xf_unlock_x11(xfc, FALSE);
if (!process_status)
@ -1219,7 +1252,7 @@ void* xf_input_thread(void *arg)
void* xf_channels_thread(void *arg)
{
int status;
xfContext *xfc;
xfContext* xfc;
HANDLE event;
rdpChannels *channels;
freerdp *instance = (freerdp *) arg;
@ -1241,29 +1274,34 @@ void* xf_channels_thread(void *arg)
return NULL;
}
BOOL xf_auto_reconnect(freerdp *instance)
BOOL xf_auto_reconnect(freerdp* instance)
{
xfContext *xfc = (xfContext *) instance->context;
xfContext* xfc = (xfContext*) instance->context;
UINT32 num_retries = 0;
UINT32 max_retries = instance->settings->AutoReconnectMaxRetries;
/* Only auto reconnect on network disconnects. */
if (freerdp_error_info(instance) != 0)
return FALSE;
/* A network disconnect was detected */
WLog_INFO(TAG, "Network disconnect!");
if (!instance->settings->AutoReconnectionEnabled)
{
/* No auto-reconnect - just quit */
return FALSE;
}
/* Perform an auto-reconnect. */
for(;;)
for (;;)
{
/* Quit retrying if max retries has been exceeded */
if (num_retries++ >= max_retries)
{
return FALSE;
}
/* Attempt the next reconnect */
WLog_INFO(TAG, "Attempting reconnect (%u of %u)", num_retries, max_retries);
if (freerdp_reconnect(instance))
@ -1273,7 +1311,9 @@ BOOL xf_auto_reconnect(freerdp *instance)
}
sleep(5);
}
WLog_ERR(TAG, "Maximum reconnect retries exceeded");
return FALSE;
}
@ -1288,7 +1328,7 @@ void* xf_thread(void *param)
{
int i;
int fds;
xfContext *xfc;
xfContext* xfc;
int max_fds;
int rcount;
int wcount;
@ -1318,8 +1358,9 @@ void* xf_thread(void *param)
ZeroMemory(wfds, sizeof(wfds));
ZeroMemory(&timeout, sizeof(struct timeval));
status = freerdp_connect(instance);
xfc = (xfContext *) instance->context;
xfc = (xfContext*) instance->context;
assert(NULL != xfc);
/* Connection succeeded. --authonly ? */
if (instance->settings->AuthenticationOnly)
{
@ -1327,6 +1368,7 @@ void* xf_thread(void *param)
WLog_ERR(TAG, "Authentication only, exit status %d", !status);
ExitThread(exit_code);
}
if (!status)
{
if (xfc->mutex)
@ -1335,10 +1377,12 @@ void* xf_thread(void *param)
CloseHandle(xfc->mutex);
xfc->mutex = NULL;
}
xf_monitors_free(xfc, instance->settings);
exit_code = XF_EXIT_CONN_FAILED;
ExitThread(exit_code);
}
channels = instance->context->channels;
settings = instance->context->settings;
async_input = settings->AsyncInput;
@ -1349,11 +1393,13 @@ void* xf_thread(void *param)
{
input_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_input_thread, instance, 0, NULL);
}
if (async_channels)
{
channels_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_channels_thread, instance, 0, NULL);
}
while(!xfc->disconnect && !freerdp_shall_disconnect(instance))
while (!xfc->disconnect && !freerdp_shall_disconnect(instance))
{
rcount = 0;
wcount = 0;
@ -1516,27 +1562,28 @@ DWORD xf_exit_code_from_disconnect_reason(DWORD reason)
if (reason == 0 || (reason >= XF_EXIT_PARSE_ARGUMENTS && reason <= XF_EXIT_CONN_FAILED))
return reason;
/* License error set */
else
if (reason >= 0x100 && reason <= 0x10A)
reason -= 0x100 + XF_EXIT_LICENSE_INTERNAL;
else if (reason >= 0x100 && reason <= 0x10A)
reason -= 0x100 + XF_EXIT_LICENSE_INTERNAL;
/* RDP protocol error set */
else
if (reason >= 0x10c9 && reason <= 0x1193)
reason = XF_EXIT_RDP;
else if (reason >= 0x10c9 && reason <= 0x1193)
reason = XF_EXIT_RDP;
/* There's no need to test protocol-independent codes: they match */
else
if (!(reason <= 0xB))
reason = XF_EXIT_UNKNOWN;
else if (!(reason <= 0xB))
reason = XF_EXIT_UNKNOWN;
return reason;
}
void xf_TerminateEventHandler(rdpContext *context, TerminateEventArgs *e)
void xf_TerminateEventHandler(rdpContext* context, TerminateEventArgs* e)
{
wMessageQueue *queue;
xfContext *xfc = (xfContext *) context;
wMessageQueue* queue;
xfContext* xfc = (xfContext*) context;
if (context->settings->AsyncInput)
{
queue = freerdp_get_message_queue(context->instance, FREERDP_INPUT_MESSAGE_QUEUE);
if (queue)
MessageQueue_PostQuit(queue, 0);
}
@ -1546,7 +1593,7 @@ void xf_TerminateEventHandler(rdpContext *context, TerminateEventArgs *e)
}
}
static void xf_ScalingFactorChangeEventHandler(rdpContext *context, ScalingFactorChangeEventArgs *e)
static void xf_ScalingFactorChangeEventHandler(rdpContext* context, ScalingFactorChangeEventArgs* e)
{
xfContext* xfc = (xfContext*) context;
@ -1589,7 +1636,7 @@ static void xfreerdp_client_global_uninit()
}
static int xfreerdp_client_start(rdpContext *context)
static int xfreerdp_client_start(rdpContext* context)
{
xfContext* xfc = (xfContext *) context;
rdpSettings* settings = context->settings;

View File

@ -24,8 +24,8 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <freerdp/locale/keyboard.h>
#include <freerdp/log.h>
#include <freerdp/locale/keyboard.h>
#include "xf_rail.h"
#include "xf_window.h"
@ -208,16 +208,16 @@ static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app)
}
else
{
xfWindow* xfw;
rdpWindow* window;
xfAppWindow* appWindow;
rdpRail* rail = ((rdpContext*) xfc)->rail;
window = window_list_get_by_extra_id(rail->list, (void*) event->xexpose.window);
if (window)
{
xfw = (xfWindow*) window->extra;
xf_UpdateWindowArea(xfc, xfw, x, y, w, h);
appWindow = (xfAppWindow*) window->extra;
xf_UpdateWindowArea(xfc, appWindow, x, y, w, h);
}
}
@ -265,7 +265,7 @@ BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window win
input->MouseEvent(input, PTR_FLAGS_MOVE, x, y);
if (xfc->fullscreen)
if (xfc->fullscreen && !app)
{
XSetInputFocus(xfc->display, xfc->window->handle, RevertToPointerRoot, CurrentTime);
}
@ -518,21 +518,25 @@ static BOOL xf_event_FocusIn(xfContext* xfc, XEvent* event, BOOL app)
xfc->focused = TRUE;
if (xfc->mouse_active && (!app))
if (xfc->mouse_active && !app)
XGrabKeyboard(xfc->display, xfc->window->handle, TRUE, GrabModeAsync, GrabModeAsync, CurrentTime);
if (app)
{
xf_rail_send_activate(xfc, event->xany.window, TRUE);
rdpWindow* window;
rdpRail* rail = ((rdpContext*) xfc)->rail;
window = window_list_get_by_extra_id(rail->list, (void*) event->xany.window);
/* Update the server with any window changes that occurred while the window was not focused. */
if (window)
xf_rail_adjust_position(xfc, window);
rdpWindow* window;
xfAppWindow* appWindow;
rdpRail* rail = ((rdpContext*) xfc)->rail;
xf_rail_send_activate(xfc, event->xany.window, TRUE);
window = window_list_get_by_extra_id(rail->list, (void*) event->xany.window);
/* Update the server with any window changes that occurred while the window was not focused. */
if (window)
{
appWindow = (xfAppWindow*) window->extra;
xf_rail_adjust_position(xfc, appWindow);
}
}
xf_keyboard_focus_in(xfc);
@ -617,15 +621,16 @@ static BOOL xf_event_EnterNotify(xfContext* xfc, XEvent* event, BOOL app)
{
/* keep track of which window has focus so that we can apply pointer updates */
xfWindow* xfw;
rdpWindow* window;
xfAppWindow* appWindow;
rdpRail* rail = ((rdpContext*) xfc)->rail;
window = window_list_get_by_extra_id(rail->list, (void*) event->xexpose.window);
if (window)
{
xfw = (xfWindow*) window->extra;
xfc->window = xfw;
appWindow = (xfAppWindow*) window->extra;
xfc->appWindow = appWindow;
}
}
@ -645,61 +650,62 @@ static BOOL xf_event_LeaveNotify(xfContext* xfc, XEvent* event, BOOL app)
static BOOL xf_event_ConfigureNotify(xfContext* xfc, XEvent* event, BOOL app)
{
rdpWindow* window;
rdpRail* rail = ((rdpContext*) xfc)->rail;
rdpWindow* window;
rdpRail* rail = ((rdpContext*) xfc)->rail;
if (!xfc->remote_app || !rail)
return TRUE;
if (!app || !rail)
return TRUE;
window = window_list_get_by_extra_id(rail->list, (void*) event->xconfigure.window);
window = window_list_get_by_extra_id(rail->list, (void*) event->xconfigure.window);
if (window)
{
xfWindow* xfw;
Window childWindow;
xfw = (xfWindow*) window->extra;
if (window)
{
Window childWindow;
xfAppWindow* appWindow;
/*
* ConfigureNotify coordinates are expressed relative to the window parent.
* Translate these to root window coordinates.
*/
XTranslateCoordinates(xfc->display, xfw->handle,
RootWindowOfScreen(xfc->screen),
0, 0, &xfw->left, &xfw->top, &childWindow);
xfw->width = event->xconfigure.width;
xfw->height = event->xconfigure.height;
xfw->right = xfw->left + xfw->width - 1;
xfw->bottom = xfw->top + xfw->height - 1;
appWindow = (xfAppWindow*) window->extra;
/*
* Additonal checks for not in a local move and not ignoring configure to send
* ConfigureNotify coordinates are expressed relative to the window parent.
* Translate these to root window coordinates.
*/
XTranslateCoordinates(xfc->display, appWindow->handle,
RootWindowOfScreen(xfc->screen),
0, 0, &appWindow->x, &appWindow->y, &childWindow);
appWindow->width = event->xconfigure.width;
appWindow->height = event->xconfigure.height;
/*
* Additional checks for not in a local move and not ignoring configure to send
* position update to server, also should the window not be focused then do not
* send to server yet(ie. resizing using window decoration).
* send to server yet (i.e. resizing using window decoration).
* The server will be updated when the window gets refocused.
*/
if (app && xfw->decorations)
if (appWindow->decorations)
{
/* moving resizing using window decoration */
xf_rail_adjust_position(xfc, window);
window->windowOffsetX = xfw->left;
xf_rail_adjust_position(xfc, appWindow);
window->windowOffsetX = appWindow->x;
window->visibleOffsetX = window->windowOffsetX;
window->windowOffsetY = xfw->top;
window->windowOffsetY = appWindow->y;
window->visibleOffsetY = window->windowOffsetY;
window->windowWidth = xfw->width;
window->windowHeight = xfw->height;
window->windowWidth = appWindow->width;
window->windowHeight = appWindow->height;
}
else
{
if (app && (!event->xconfigure.send_event || xfc->window->local_move.state == LMS_NOT_ACTIVE)
&& !xfw->rail_ignore_configure && xfc->focused)
xf_rail_adjust_position(xfc, window);
if ((!event->xconfigure.send_event || appWindow->local_move.state == LMS_NOT_ACTIVE)
&& !appWindow->rail_ignore_configure && xfc->focused)
xf_rail_adjust_position(xfc, appWindow);
}
}
}
return TRUE;
return TRUE;
}
static BOOL xf_event_MapNotify(xfContext* xfc, XEvent* event, BOOL app)
@ -732,8 +738,8 @@ static BOOL xf_event_MapNotify(xfContext* xfc, XEvent* event, BOOL app)
*/
//xf_rail_send_client_system_command(xfc, window->windowId, SC_RESTORE);
xfWindow* xfw = (xfWindow*) window->extra;
xfw->is_mapped = TRUE;
xfAppWindow* appWindow = (xfAppWindow*) window->extra;
appWindow->is_mapped = TRUE;
}
}
@ -758,8 +764,8 @@ static BOOL xf_event_UnmapNotify(xfContext* xfc, XEvent* event, BOOL app)
if (window)
{
xfWindow* xfw = (xfWindow*) window->extra;
xfw->is_mapped = FALSE;
xfAppWindow* appWindow = (xfAppWindow*) window->extra;
appWindow->is_mapped = FALSE;
}
}
@ -777,11 +783,14 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app)
if (app)
{
rdpWindow* window;
xfAppWindow* appWindow;
window = xf_rdpWindowFromWindow(xfc, event->xproperty.window);
if (!window)
return TRUE;
appWindow = (xfAppWindow*) window->extra;
if ((((Atom) event->xproperty.atom == xfc->_NET_WM_STATE) && (event->xproperty.state != PropertyDelete)) ||
(((Atom) event->xproperty.atom == xfc->WM_STATE) && (event->xproperty.state != PropertyDelete)))
@ -836,19 +845,19 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app)
}
if (maxVert && maxHorz && !minimized && (xfc->window->rail_state != WINDOW_SHOW_MAXIMIZED))
if (maxVert && maxHorz && !minimized && (appWindow->rail_state != WINDOW_SHOW_MAXIMIZED))
{
xfc->window->rail_state = WINDOW_SHOW_MAXIMIZED;
appWindow->rail_state = WINDOW_SHOW_MAXIMIZED;
xf_rail_send_client_system_command(xfc, window->windowId, SC_MAXIMIZE);
}
else if (minimized && (xfc->window->rail_state != WINDOW_SHOW_MINIMIZED))
else if (minimized && (appWindow->rail_state != WINDOW_SHOW_MINIMIZED))
{
xfc->window->rail_state = WINDOW_SHOW_MINIMIZED;
appWindow->rail_state = WINDOW_SHOW_MINIMIZED;
xf_rail_send_client_system_command(xfc, window->windowId, SC_MINIMIZE);
}
else if (!minimized && !maxVert && !maxHorz && (xfc->window->rail_state != WINDOW_SHOW))
else if (!minimized && !maxVert && !maxHorz && (appWindow->rail_state != WINDOW_SHOW))
{
xfc->window->rail_state = WINDOW_SHOW;
appWindow->rail_state = WINDOW_SHOW;
xf_rail_send_client_system_command(xfc, window->windowId, SC_RESTORE);
}
}
@ -857,21 +866,21 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app)
return TRUE;
}
static BOOL xf_event_suppress_events(xfContext* xfc, rdpWindow* window, XEvent*event)
static BOOL xf_event_suppress_events(xfContext* xfc, xfAppWindow* appWindow, XEvent* event)
{
if (!xfc->remote_app)
return FALSE;
switch (xfc->window->local_move.state)
switch (appWindow->local_move.state)
{
case LMS_NOT_ACTIVE:
/* No local move in progress, nothing to do */
/* Prevent Configure from happening during indeterminant state of Horz or Vert Max only */
if ( (event->type == ConfigureNotify) && xfc->window->rail_ignore_configure)
if ((event->type == ConfigureNotify) && appWindow->rail_ignore_configure)
{
xfc->window->rail_ignore_configure = FALSE;
appWindow->rail_ignore_configure = FALSE;
return TRUE;
}
@ -879,11 +888,11 @@ static BOOL xf_event_suppress_events(xfContext* xfc, rdpWindow* window, XEvent*e
case LMS_STARTING:
/* Local move initiated by RDP server, but we have not yet seen any updates from the X server */
switch(event->type)
switch (event->type)
{
case ConfigureNotify:
/* Starting to see move events from the X server. Local move is now in progress. */
xfc->window->local_move.state = LMS_ACTIVE;
appWindow->local_move.state = LMS_ACTIVE;
/* Allow these events to be processed during move to keep our state up to date. */
break;
@ -911,7 +920,7 @@ static BOOL xf_event_suppress_events(xfContext* xfc, rdpWindow* window, XEvent*e
case LMS_ACTIVE:
/* Local move is in progress */
switch(event->type)
switch (event->type)
{
case ConfigureNotify:
case VisibilityNotify:
@ -922,7 +931,7 @@ static BOOL xf_event_suppress_events(xfContext* xfc, rdpWindow* window, XEvent*e
break;
default:
/* Any other event terminates move */
xf_rail_end_local_move(xfc, window);
xf_rail_end_local_move(xfc, appWindow);
break;
}
break;
@ -950,9 +959,9 @@ BOOL xf_event_process(freerdp* instance, XEvent* event)
if (window)
{
/* Update "current" window for cursor change orders */
xfc->window = (xfWindow*) window->extra;
xfc->appWindow = (xfAppWindow*) window->extra;
if (xf_event_suppress_events(xfc, window, event))
if (xf_event_suppress_events(xfc, xfc->appWindow, event))
return TRUE;
}
}
@ -975,6 +984,7 @@ BOOL xf_event_process(freerdp* instance, XEvent* event)
case MotionNotify:
status = xf_event_MotionNotify(xfc, event, xfc->remote_app);
break;
case ButtonPress:
status = xf_event_ButtonPress(xfc, event, xfc->remote_app);
break;

View File

@ -283,10 +283,12 @@ static BOOL xf_keyboard_set_key_state(xfContext* xfc, BOOL on, int keysym)
return FALSE;
keysymMask = xf_keyboard_get_keymask(xfc, keysym);
if (!keysymMask)
{
return FALSE;
}
return XkbLockModifiers(xfc->display, XkbUseCoreKbd, keysymMask, on ? keysymMask : 0);
}
@ -321,7 +323,18 @@ void xf_keyboard_focus_in(xfContext* xfc)
{
input = xfc->instance->input;
syncFlags = xf_keyboard_get_toggle_keys_state(xfc);
XQueryPointer(xfc->display, xfc->window->handle, &wdummy, &wdummy, &mouseX, &mouseY, &dummy, &dummy, &state);
if (!xfc->remote_app)
{
XQueryPointer(xfc->display, xfc->window->handle, &wdummy, &wdummy,
&mouseX, &mouseY, &dummy, &dummy, &state);
}
else
{
XQueryPointer(xfc->display, DefaultRootWindow(xfc->display),
&wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
}
input->FocusInEvent(input, syncFlags, mouseX, mouseY);
}
}

View File

@ -68,7 +68,7 @@ void xf_rail_enable_remoteapp_mode(xfContext* xfc)
{
xfc->remote_app = TRUE;
xfc->drawable = DefaultRootWindow(xfc->display);
xf_DestroyWindow(xfc, xfc->window);
xf_DestroyDesktopWindow(xfc, xfc->window);
xfc->window = NULL;
}
}
@ -86,11 +86,10 @@ void xf_rail_invalidate_region(xfContext* xfc, REGION16* invalidRegion)
{
int index;
int count;
xfWindow* xfw = NULL;
RECTANGLE_16 updateRect;
RECTANGLE_16 windowRect;
ULONG_PTR* pKeys = NULL;
xfRailWindow* railWindow;
xfAppWindow* appWindow;
const RECTANGLE_16* extents;
REGION16 windowInvalidRegion;
@ -100,14 +99,14 @@ void xf_rail_invalidate_region(xfContext* xfc, REGION16* invalidRegion)
for (index = 0; index < count; index++)
{
railWindow = (xfRailWindow*) HashTable_GetItemValue(xfc->railWindows, (void*) pKeys[index]);
appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows, (void*) pKeys[index]);
if (railWindow)
if (appWindow)
{
windowRect.left = railWindow->x;
windowRect.top = railWindow->y;
windowRect.right = railWindow->x + railWindow->width;
windowRect.bottom = railWindow->y + railWindow->height;
windowRect.left = appWindow->x;
windowRect.top = appWindow->y;
windowRect.right = appWindow->x + appWindow->width;
windowRect.bottom = appWindow->y + appWindow->height;
region16_clear(&windowInvalidRegion);
region16_intersect_rect(&windowInvalidRegion, invalidRegion, &windowRect);
@ -116,14 +115,14 @@ void xf_rail_invalidate_region(xfContext* xfc, REGION16* invalidRegion)
{
extents = region16_extents(&windowInvalidRegion);
updateRect.left = extents->left - railWindow->x;
updateRect.top = extents->top - railWindow->y;
updateRect.right = extents->right - railWindow->x;
updateRect.bottom = extents->bottom - railWindow->y;
updateRect.left = extents->left - appWindow->x;
updateRect.top = extents->top - appWindow->y;
updateRect.right = extents->right - appWindow->x;
updateRect.bottom = extents->bottom - appWindow->y;
if (xfw)
if (appWindow)
{
xf_UpdateWindowArea(xfc, xfw, updateRect.left, updateRect.top,
xf_UpdateWindowArea(xfc, appWindow, updateRect.left, updateRect.top,
updateRect.right - updateRect.left,
updateRect.bottom - updateRect.top);
}
@ -137,8 +136,8 @@ void xf_rail_invalidate_region(xfContext* xfc, REGION16* invalidRegion)
void xf_rail_paint(xfContext* xfc, INT32 uleft, INT32 utop, UINT32 uright, UINT32 ubottom)
{
rdpRail* rail;
xfWindow* xfw;
rdpWindow* window;
xfAppWindow* appWindow;
BOOL intersect;
UINT32 iwidth, iheight;
INT32 ileft, itop;
@ -173,7 +172,7 @@ void xf_rail_paint(xfContext* xfc, INT32 uleft, INT32 utop, UINT32 uright, UINT3
while (window_list_has_next(rail->list))
{
window = window_list_get_next(rail->list);
xfw = (xfWindow*) window->extra;
appWindow = (xfAppWindow*) window->extra;
/* RDP can have zero width or height windows. X cannot, so we ignore these. */
@ -196,7 +195,7 @@ void xf_rail_paint(xfContext* xfc, INT32 uleft, INT32 utop, UINT32 uright, UINT3
if (intersect)
{
xf_UpdateWindowArea(xfc, xfw, ileft - wleft, itop - wtop, iwidth, iheight);
xf_UpdateWindowArea(xfc, appWindow, ileft - wleft, itop - wtop, iwidth, iheight);
}
}
}
@ -206,116 +205,128 @@ void xf_rail_paint(xfContext* xfc, INT32 uleft, INT32 utop, UINT32 uright, UINT3
static void xf_rail_CreateWindow(rdpRail* rail, rdpWindow* window)
{
xfContext* xfc;
xfWindow* xfw;
xfAppWindow* appWindow;
xfc = (xfContext*) rail->extra;
xf_rail_enable_remoteapp_mode(xfc);
xfw = xf_CreateWindow(xfc, window, window->windowOffsetX, window->windowOffsetY,
appWindow = xf_CreateWindow(xfc, window, window->windowOffsetX, window->windowOffsetY,
window->windowWidth, window->windowHeight, window->windowId);
xf_SetWindowStyle(xfc, xfw, window->style, window->extendedStyle);
xf_SetWindowText(xfc, xfw, window->title);
window->extra = (void*) xfw;
window->extraId = (void*) xfw->handle;
xf_SetWindowStyle(xfc, appWindow, window->style, window->extendedStyle);
xf_SetWindowText(xfc, appWindow, window->title);
window->extra = (void*) appWindow;
window->extraId = (void*) appWindow->handle;
}
static void xf_rail_MoveWindow(rdpRail* rail, rdpWindow* window)
{
xfContext* xfc;
xfWindow* xfw;
xfAppWindow* appWindow;
xfc = (xfContext*) rail->extra;
xfw = (xfWindow*) window->extra;
appWindow = (xfAppWindow*) window->extra;
/*
* 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
*/
if (xfw->rail_state == WINDOW_SHOW_MINIMIZED)
if (appWindow->rail_state == WINDOW_SHOW_MINIMIZED)
return;
/* Do nothing if window is already in the correct position */
if (xfw->left == window->visibleOffsetX &&
xfw->top == window->visibleOffsetY &&
xfw->width == window->windowWidth &&
xfw->height == window->windowHeight)
if (appWindow->x == window->visibleOffsetX &&
appWindow->y == window->visibleOffsetY &&
appWindow->width == window->windowWidth &&
appWindow->height == window->windowHeight)
{
/*
* Just ensure entire window area is updated to handle cases where we
* have drawn locally before getting new bitmap from the server
*/
xf_UpdateWindowArea(xfc, xfw, 0, 0, window->windowWidth, window->windowHeight);
xf_UpdateWindowArea(xfc, appWindow, 0, 0, window->windowWidth, window->windowHeight);
return;
}
xf_MoveWindow(xfc, xfw, window->visibleOffsetX, window->visibleOffsetY,
xf_MoveWindow(xfc, appWindow, window->visibleOffsetX, window->visibleOffsetY,
window->windowWidth, window->windowHeight);
}
static void xf_rail_ShowWindow(rdpRail* rail, rdpWindow* window, BYTE state)
{
xfContext* xfc;
xfWindow* xfw;
xfAppWindow* appWindow;
xfc = (xfContext*) rail->extra;
xfw = (xfWindow*) window->extra;
xf_ShowWindow(xfc, xfw, state);
appWindow = (xfAppWindow*) window->extra;
xf_ShowWindow(xfc, appWindow, state);
}
static void xf_rail_SetWindowText(rdpRail* rail, rdpWindow* window)
{
xfContext* xfc;
xfWindow* xfw;
xfAppWindow* appWindow;
xfc = (xfContext*) rail->extra;
xfw = (xfWindow*) window->extra;
xf_SetWindowText(xfc, xfw, window->title);
appWindow = (xfAppWindow*) window->extra;
xf_SetWindowText(xfc, appWindow, window->title);
}
static void xf_rail_SetWindowIcon(rdpRail* rail, rdpWindow* window, rdpIcon* icon)
{
xfContext* xfc;
xfWindow* xfw;
xfAppWindow* appWindow;
xfc = (xfContext*) rail->extra;
xfw = (xfWindow*) window->extra;
appWindow = (xfAppWindow*) window->extra;
icon->extra = freerdp_icon_convert(icon->entry->bitsColor, NULL, icon->entry->bitsMask,
icon->entry->width, icon->entry->height, icon->entry->bpp, rail->clrconv);
xf_SetWindowIcon(xfc, xfw, icon);
xf_SetWindowIcon(xfc, appWindow, icon);
}
static void xf_rail_SetWindowRects(rdpRail* rail, rdpWindow* window)
{
xfContext* xfc;
xfWindow* xfw;
xfc = (xfContext*) rail->extra;
xfw = (xfWindow*) window->extra;
xfAppWindow* appWindow;
xf_SetWindowRects(xfc, xfw, window->windowRects, window->numWindowRects);
xfc = (xfContext*) rail->extra;
appWindow = (xfAppWindow*) window->extra;
xf_SetWindowRects(xfc, appWindow, window->windowRects, window->numWindowRects);
}
static void xf_rail_SetWindowVisibilityRects(rdpRail* rail, rdpWindow* window)
{
xfWindow* xfw;
xfContext* xfc;
xfAppWindow* appWindow;
xfc = (xfContext*) rail->extra;
xfw = (xfWindow*) window->extra;
xf_SetWindowVisibilityRects(xfc, xfw, window->windowRects, window->numWindowRects);
appWindow = (xfAppWindow*) window->extra;
xf_SetWindowVisibilityRects(xfc, appWindow, window->windowRects, window->numWindowRects);
}
static void xf_rail_DestroyWindow(rdpRail* rail, rdpWindow* window)
{
xfWindow* xfw;
xfContext* xfc;
xfAppWindow* appWindow;
xfc = (xfContext*) rail->extra;
xfw = (xfWindow*) window->extra;
xf_DestroyWindow(xfc, xfw);
appWindow = (xfAppWindow*) window->extra;
xf_DestroyWindow(xfc, appWindow);
}
void xf_rail_DesktopNonMonitored(rdpRail* rail, rdpWindow* window)
{
xfContext* xfc;
xfc = (xfContext*) rail->extra;
xfContext* xfc = (xfContext*) rail->extra;
xf_rail_disable_remoteapp_mode(xfc);
}
@ -369,21 +380,21 @@ void xf_rail_send_client_system_command(xfContext* xfc, UINT32 windowId, UINT16
* send an update to the RDP server informing it of the new window position
* and size.
*/
void xf_rail_adjust_position(xfContext* xfc, rdpWindow* window)
void xf_rail_adjust_position(xfContext* xfc, xfAppWindow* appWindow)
{
xfWindow* xfw;
rdpWindow* window;
RAIL_WINDOW_MOVE_ORDER windowMove;
xfw = (xfWindow*) window->extra;
window = appWindow->window;
if (! xfw->is_mapped || xfw->local_move.state != LMS_NOT_ACTIVE)
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 */
if (xfw->left != window->visibleOffsetX ||
xfw->top != window->visibleOffsetY ||
xfw->width != window->windowWidth ||
xfw->height != window->windowHeight)
if (appWindow->x != window->visibleOffsetX ||
appWindow->y != window->visibleOffsetY ||
appWindow->width != window->windowWidth ||
appWindow->height != window->windowHeight)
{
/*
* Although the rail server can give negative window coordinates when updating windowOffsetX and windowOffsetY,
@ -409,28 +420,28 @@ void xf_rail_adjust_position(xfContext* xfc, rdpWindow* window)
* Calculate new offsets for the rail server window
* Negative offset correction + rail server window offset + (difference in visibleOffset and new window local offset)
*/
windowMove.left = offsetX + window->windowOffsetX + (xfw->left - window->visibleOffsetX);
windowMove.top = offsetY + window->windowOffsetY + (xfw->top - window->visibleOffsetY);
windowMove.right = windowMove.left + xfw->width;
windowMove.bottom = windowMove.top + xfw->height;
windowMove.left = offsetX + window->windowOffsetX + (appWindow->x - window->visibleOffsetX);
windowMove.top = offsetY + window->windowOffsetY + (appWindow->y - window->visibleOffsetY);
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, rdpWindow* window)
void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow)
{
int x, y;
int child_x;
int child_y;
xfWindow* xfw;
rdpWindow* window;
unsigned int mask;
Window root_window;
Window child_window;
RAIL_WINDOW_MOVE_ORDER window_move;
RAIL_WINDOW_MOVE_ORDER windowMove;
rdpInput* input = xfc->instance->input;
xfw = (xfWindow*) window->extra;
window = appWindow->window;
/*
* Although the rail server can give negative window coordinates when updating windowOffsetX and windowOffsetY,
@ -449,31 +460,30 @@ void xf_rail_end_local_move(xfContext* xfc, rdpWindow* window)
/*
* For keyboard moves send and explicit update to RDP server
*/
window_move.windowId = window->windowId;
windowMove.windowId = window->windowId;
/*
* Calculate new offsets for the rail server window
* Negative offset correction + rail server window offset + (difference in visibleOffset and new window local offset)
*/
window_move.left = offsetX + window->windowOffsetX + (xfw->left - window->visibleOffsetX);
window_move.top = offsetY + window->windowOffsetY + (xfw->top - window->visibleOffsetY);
window_move.right = window_move.left + xfw->width; /* In the update to RDP the position is one past the window */
window_move.bottom = window_move.top + xfw->height;
windowMove.left = offsetX + window->windowOffsetX + (appWindow->x - window->visibleOffsetX);
windowMove.top = offsetY + window->windowOffsetY + (appWindow->y - window->visibleOffsetY);
windowMove.right = windowMove.left + appWindow->width; /* In the update to RDP the position is one past the window */
windowMove.bottom = windowMove.top + appWindow->height;
xfc->rail->ClientWindowMove(xfc->rail, &window_move);
xfc->rail->ClientWindowMove(xfc->rail, &windowMove);
/*
* Simulate button up at new position to end the local move (per RDP spec)
*/
XQueryPointer(xfc->display, xfw->handle,
&root_window, &child_window,
&x, &y, &child_x, &child_y, &mask);
XQueryPointer(xfc->display, appWindow->handle,
&root_window, &child_window, &x, &y, &child_x, &child_y, &mask);
input->MouseEvent(input, PTR_FLAGS_BUTTON1, x, y);
/* only send the mouse coordinates if not a keyboard move or size */
if ((xfw->local_move.direction != _NET_WM_MOVERESIZE_MOVE_KEYBOARD) &&
(xfw->local_move.direction != _NET_WM_MOVERESIZE_SIZE_KEYBOARD))
if ((appWindow->local_move.direction != _NET_WM_MOVERESIZE_MOVE_KEYBOARD) &&
(appWindow->local_move.direction != _NET_WM_MOVERESIZE_SIZE_KEYBOARD))
{
input->MouseEvent(input, PTR_FLAGS_BUTTON1, x, y);
}
@ -483,11 +493,11 @@ void xf_rail_end_local_move(xfContext* xfc, rdpWindow* window)
* 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.
*/
window->windowOffsetX = offsetX + window->windowOffsetX + (xfw->left - window->visibleOffsetX);
window->windowOffsetY = offsetY + window->windowOffsetY + (xfw->top - window->visibleOffsetY);
window->windowWidth = xfw->width;
window->windowHeight = xfw->height;
xfw->local_move.state = LMS_TERMINATING;
window->windowOffsetX = offsetX + window->windowOffsetX + (appWindow->x - window->visibleOffsetX);
window->windowOffsetY = offsetY + window->windowOffsetY + (appWindow->y - window->visibleOffsetY);
window->windowWidth = appWindow->width;
window->windowHeight = appWindow->height;
appWindow->local_move.state = LMS_TERMINATING;
}
#if 0
@ -496,13 +506,13 @@ void xf_rail_end_local_move(xfContext* xfc, rdpWindow* window)
static void xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* windowState)
{
xfRailWindow* railWindow = NULL;
xfAppWindow* railWindow = NULL;
xfContext* xfc = (xfContext*) context;
UINT32 fieldFlags = orderInfo->fieldFlags;
if (fieldFlags & WINDOW_ORDER_STATE_NEW)
{
railWindow = (xfRailWindow*) calloc(1, sizeof(xfRailWindow));
railWindow = (xfAppWindow*) calloc(1, sizeof(xfAppWindow));
if (!railWindow)
return;
@ -541,7 +551,7 @@ static void xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
}
else
{
railWindow = (xfRailWindow*) HashTable_GetItemValue(xfc->railWindows,
railWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows,
(void*) (UINT_PTR) orderInfo->windowId);
}
@ -634,10 +644,10 @@ static void xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
static void xf_rail_window_delete(rdpContext* context, WINDOW_ORDER_INFO* orderInfo)
{
xfRailWindow* railWindow = NULL;
xfAppWindow* railWindow = NULL;
xfContext* xfc = (xfContext*) context;
railWindow = (xfRailWindow*) HashTable_GetItemValue(xfc->railWindows,
railWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows,
(void*) (UINT_PTR) orderInfo->windowId);
if (!railWindow)
@ -651,10 +661,10 @@ static void xf_rail_window_delete(rdpContext* context, WINDOW_ORDER_INFO* orderI
static void xf_rail_window_icon(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_ICON_ORDER* windowIcon)
{
BOOL bigIcon;
xfRailWindow* railWindow;
xfAppWindow* railWindow;
xfContext* xfc = (xfContext*) context;
railWindow = (xfRailWindow*) HashTable_GetItemValue(xfc->railWindows,
railWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows,
(void*) (UINT_PTR) orderInfo->windowId);
if (!railWindow)
@ -842,11 +852,11 @@ static int xf_rail_server_handshake_ex(RailClientContext* context, RAIL_HANDSHAK
static int xf_rail_server_local_move_size(RailClientContext* context, RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
{
rdpRail* rail;
xfWindow* window;
int x = 0, y = 0;
int direction = 0;
Window child_window;
rdpWindow* rail_window;
xfAppWindow* appWindow;
xfContext* xfc = (xfContext*) context->custom;
rail = ((rdpContext*) xfc)->rail;
@ -856,7 +866,7 @@ static int xf_rail_server_local_move_size(RailClientContext* context, RAIL_LOCAL
if (!rail_window)
return -1;
window = (xfWindow*) rail_window->extra;
appWindow = (xfAppWindow*) rail_window->extra;
switch (localMoveSize->moveSizeType)
{
@ -910,7 +920,7 @@ static int xf_rail_server_local_move_size(RailClientContext* context, RAIL_LOCAL
case RAIL_WMSZ_MOVE:
direction = _NET_WM_MOVERESIZE_MOVE;
XTranslateCoordinates(xfc->display, window->handle,
XTranslateCoordinates(xfc->display, appWindow->handle,
RootWindowOfScreen(xfc->screen),
localMoveSize->posX, localMoveSize->posY, &x, &y, &child_window);
break;
@ -934,11 +944,11 @@ static int xf_rail_server_local_move_size(RailClientContext* context, RAIL_LOCAL
if (localMoveSize->isMoveSizeStart)
{
xf_StartLocalMoveSize(xfc, window, direction, x, y);
xf_StartLocalMoveSize(xfc, appWindow, direction, x, y);
}
else
{
xf_EndLocalMoveSize(xfc, window);
xf_EndLocalMoveSize(xfc, appWindow);
}
return 1;
@ -947,7 +957,7 @@ static int xf_rail_server_local_move_size(RailClientContext* context, RAIL_LOCAL
static int xf_rail_server_min_max_info(RailClientContext* context, RAIL_MINMAXINFO_ORDER* minMaxInfo)
{
rdpRail* rail;
xfWindow* window;
xfAppWindow* appWindow;
rdpWindow* rail_window;
xfContext* xfc = (xfContext*) context->custom;
@ -958,9 +968,9 @@ static int xf_rail_server_min_max_info(RailClientContext* context, RAIL_MINMAXIN
if (!rail_window)
return -1;
window = (xfWindow*) rail_window->extra;
appWindow = (xfAppWindow*) rail_window->extra;
xf_SetWindowMinMaxInfo(xfc, window,
xf_SetWindowMinMaxInfo(xfc, appWindow,
minMaxInfo->maxWidth, minMaxInfo->maxHeight,
minMaxInfo->maxPosX, minMaxInfo->maxPosY,
minMaxInfo->minTrackWidth, minMaxInfo->minTrackHeight,

View File

@ -23,41 +23,13 @@
#include "xf_client.h"
#include "xfreerdp.h"
struct xf_rail_window
{
xfContext* xfc;
UINT32 id;
DWORD dwStyle;
DWORD dwExStyle;
int x;
int y;
int width;
int height;
char* title;
GC gc;
int shmid;
Window handle;
Window* xfwin;
BOOL fullscreen;
BOOL decorations;
BOOL is_mapped;
BOOL is_transient;
xfLocalMove local_move;
BYTE rail_state;
BOOL rail_ignore_configure;
};
typedef struct xf_rail_window xfRailWindow;
#include <freerdp/client/rail.h>
void xf_rail_paint(xfContext* xfc, INT32 uleft, INT32 utop, UINT32 uright, UINT32 ubottom);
void xf_rail_send_client_system_command(xfContext* xfc, UINT32 windowId, UINT16 command);
void xf_rail_send_activate(xfContext* xfc, Window xwindow, BOOL enabled);
void xf_rail_adjust_position(xfContext* xfc, rdpWindow* window);
void xf_rail_end_local_move(xfContext* xfc, rdpWindow* window);
void xf_rail_adjust_position(xfContext* xfc, xfAppWindow* appWindow);
void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow);
void xf_rail_enable_remoteapp_mode(xfContext* xfc);
void xf_rail_disable_remoteapp_mode(xfContext* xfc);

View File

@ -60,12 +60,6 @@
#define DEBUG_X11(fmt, ...) do { } while (0)
#endif
#ifdef WITH_DEBUG_X11_LOCAL_MOVESIZE
#define DEBUG_X11_LMS(fmt, ...) WLog_DBG(TAG, fmt, ## __VA_ARGS__)
#else
#define DEBUG_X11_LMS(fmt, ...) do { } while (0)
#endif
#include "FreeRDP_Icon_256px.h"
#define xf_icon_prop FreeRDP_Icon_256px_prop
@ -269,57 +263,7 @@ void xf_SetWindowUnlisted(xfContext* xfc, Window window)
XA_ATOM, 32, PropModeReplace, (BYTE*) &window_state, 2);
}
void xf_SetWindowStyle(xfContext* xfc, xfWindow* window, UINT32 style, UINT32 ex_style)
{
Atom window_type;
if (/*(ex_style & WS_EX_TOPMOST) ||*/ (ex_style & WS_EX_TOOLWINDOW))
{
/*
* Tooltips and menu items should be unmanaged windows
* (called "override redirect" in X windows parlance)
* If they are managed, there are issues with window focus that
* cause the windows to behave improperly. For example, a mouse
* press will dismiss a drop-down menu because the RDP server
* sees that as a focus out event from the window owning the
* dropdown.
*/
XSetWindowAttributes attrs;
attrs.override_redirect = True;
XChangeWindowAttributes(xfc->display, window->handle, CWOverrideRedirect, &attrs);
window->is_transient = TRUE;
xf_SetWindowUnlisted(xfc, window->handle);
window_type = xfc->_NET_WM_WINDOW_TYPE_POPUP;
}
/*
* TOPMOST window that is not a toolwindow is treated like a regular window(ie. task manager).
* Want to do this here, since the window may have type WS_POPUP
*/
else if (ex_style & WS_EX_TOPMOST)
{
window_type = xfc->_NET_WM_WINDOW_TYPE_NORMAL;
}
else if (style & WS_POPUP)
{
/* this includes dialogs, popups, etc, that need to be full-fledged windows */
window->is_transient = TRUE;
window_type = xfc->_NET_WM_WINDOW_TYPE_DIALOG;
xf_SetWindowUnlisted(xfc, window->handle);
}
else
{
XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_WINDOW_TYPE,
XA_ATOM, 32, PropModeReplace, (BYTE*) &window_type, 1);
}
}
void xf_SetWindowText(xfContext* xfc, xfWindow* window, char* name)
{
XStoreName(xfc->display, window->handle, name);
}
static void xf_SetWindowPID(xfContext* xfc, xfWindow* window, pid_t pid)
static void xf_SetWindowPID(xfContext* xfc, Window window, pid_t pid)
{
Atom am_wm_pid;
@ -328,14 +272,14 @@ static void xf_SetWindowPID(xfContext* xfc, xfWindow* window, pid_t pid)
am_wm_pid = XInternAtom(xfc->display, "_NET_WM_PID", False);
XChangeProperty(xfc->display, window->handle, am_wm_pid, XA_CARDINAL,
XChangeProperty(xfc->display, window, am_wm_pid, XA_CARDINAL,
32, PropModeReplace, (BYTE*) &pid, 1);
}
static const char* get_shm_id()
{
static char shm_id[64];
snprintf(shm_id, sizeof(shm_id), "com.freerdp.xfreerpd.tsmf_%016X", GetCurrentProcessId());
snprintf(shm_id, sizeof(shm_id), "com.freerdp.xfreerdp.tsmf_%016X", GetCurrentProcessId());
return shm_id;
}
@ -358,7 +302,6 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char *name, int width, int heig
window->height = height;
window->fullscreen = FALSE;
window->decorations = decorations;
window->local_move.state = LMS_NOT_ACTIVE;
window->is_mapped = FALSE;
window->is_transient = FALSE;
@ -410,7 +353,7 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char *name, int width, int heig
xf_ResizeDesktopWindow(xfc, window, width, height);
xf_SetWindowDecorations(xfc, window->handle, decorations);
xf_SetWindowPID(xfc, window, 0);
xf_SetWindowPID(xfc, window->handle, 0);
input_mask =
KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
@ -443,7 +386,7 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char *name, int width, int heig
while (xevent.type != VisibilityNotify);
/*
* The XCreateWindow call will start the window in the upper-left corner of our current
* monitor instead of the upper-left monitor for remote app mode(which uses all monitors).
* monitor instead of the upper-left monitor for remote app mode (which uses all monitors).
* This extra call after the window is mapped will position the login window correctly
*/
if (xfc->settings->RemoteApplicationMode)
@ -478,6 +421,87 @@ void xf_ResizeDesktopWindow(xfContext* xfc, xfWindow* window, int width, int hei
}
}
void xf_DestroyDesktopWindow(xfContext* xfc, xfWindow* window)
{
if (!window)
return;
if (xfc->window == window)
xfc->window = NULL;
if (window->gc)
XFreeGC(xfc->display, window->gc);
if (window->handle)
{
XUnmapWindow(xfc->display, window->handle);
XDestroyWindow(xfc->display, window->handle);
}
if (window->xfwin)
munmap(0, sizeof(*window->xfwin));
if (window->shmid >= 0)
close(window->shmid);
shm_unlink(get_shm_id());
window->xfwin = (Window*) -1;
window->shmid = -1;
free(window);
}
void xf_SetWindowStyle(xfContext* xfc, xfAppWindow* appWindow, UINT32 style, UINT32 ex_style)
{
Atom window_type;
if (/*(ex_style & WS_EX_TOPMOST) ||*/ (ex_style & WS_EX_TOOLWINDOW))
{
/*
* Tooltips and menu items should be unmanaged windows
* (called "override redirect" in X windows parlance)
* If they are managed, there are issues with window focus that
* cause the windows to behave improperly. For example, a mouse
* press will dismiss a drop-down menu because the RDP server
* sees that as a focus out event from the window owning the
* dropdown.
*/
XSetWindowAttributes attrs;
attrs.override_redirect = True;
XChangeWindowAttributes(xfc->display, appWindow->handle, CWOverrideRedirect, &attrs);
appWindow->is_transient = TRUE;
xf_SetWindowUnlisted(xfc, appWindow->handle);
window_type = xfc->_NET_WM_WINDOW_TYPE_POPUP;
}
/*
* TOPMOST window that is not a tool window is treated like a regular window (i.e. task manager).
* Want to do this here, since the window may have type WS_POPUP
*/
else if (ex_style & WS_EX_TOPMOST)
{
window_type = xfc->_NET_WM_WINDOW_TYPE_NORMAL;
}
else if (style & WS_POPUP)
{
/* this includes dialogs, popups, etc, that need to be full-fledged windows */
appWindow->is_transient = TRUE;
window_type = xfc->_NET_WM_WINDOW_TYPE_DIALOG;
xf_SetWindowUnlisted(xfc, appWindow->handle);
}
else
{
XChangeProperty(xfc->display, appWindow->handle, xfc->_NET_WM_WINDOW_TYPE,
XA_ATOM, 32, PropModeReplace, (BYTE*) &window_type, 1);
}
}
void xf_SetWindowText(xfContext* xfc, xfAppWindow* appWindow, char* name)
{
XStoreName(xfc->display, appWindow->handle, name);
}
void xf_FixWindowCoordinates(xfContext* xfc, int* x, int* y, int* width, int* height)
{
int vscreen_width;
@ -513,46 +537,48 @@ void xf_FixWindowCoordinates(xfContext* xfc, int* x, int* y, int* width, int* he
}
}
char rail_window_class[] = "RAIL:00000000";
xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int width, int height, UINT32 id)
xfAppWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int width, int height, UINT32 id)
{
XGCValues gcv;
int input_mask;
xfWindow* window;
xfAppWindow* appWindow;
XWMHints* InputModeHint;
XClassHint* class_hints;
window = (xfWindow*) calloc(1, sizeof(xfWindow));
appWindow = (xfAppWindow*) calloc(1, sizeof(xfAppWindow));
if (!appWindow)
return NULL;
xf_FixWindowCoordinates(xfc, &x, &y, &width, &height);
window->left = x;
window->top = y;
window->right = x + width - 1;
window->bottom = y + height - 1;
window->width = width;
window->height = height;
appWindow->x = x;
appWindow->y = y;
appWindow->width = width;
appWindow->height = height;
/*
* WS_EX_DECORATIONS is used by XRDP and instructs
* the client to use local window decorations
*/
window->decorations = (wnd->extendedStyle & WS_EX_DECORATIONS) ? TRUE : FALSE;
window->fullscreen = FALSE;
window->window = wnd;
window->local_move.state = LMS_NOT_ACTIVE;
window->is_mapped = FALSE;
window->is_transient = FALSE;
window->rail_state = 0;
window->rail_ignore_configure = FALSE;
appWindow->decorations = (wnd->extendedStyle & WS_EX_DECORATIONS) ? TRUE : FALSE;
appWindow->fullscreen = FALSE;
appWindow->window = wnd;
appWindow->local_move.state = LMS_NOT_ACTIVE;
appWindow->is_mapped = FALSE;
appWindow->is_transient = FALSE;
appWindow->rail_state = 0;
appWindow->rail_ignore_configure = FALSE;
window->handle = XCreateWindow(xfc->display, RootWindowOfScreen(xfc->screen),
x, y, window->width, window->height, 0, xfc->depth,
appWindow->handle = XCreateWindow(xfc->display, RootWindowOfScreen(xfc->screen),
x, y, appWindow->width, appWindow->height, 0, xfc->depth,
InputOutput, xfc->visual, 0, &xfc->attribs);
if (!appWindow->handle)
return NULL;
ZeroMemory(&gcv, sizeof(gcv));
window->gc = XCreateGC(xfc->display, window->handle, GCGraphicsExposures, &gcv);
appWindow->gc = XCreateGC(xfc->display, appWindow->handle, GCGraphicsExposures, &gcv);
class_hints = XAllocClassHint();
@ -566,13 +592,13 @@ xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int widt
}
else
{
class = malloc(sizeof(rail_window_class));
snprintf(class, sizeof(rail_window_class), "RAIL:%08X", id);
class = malloc(sizeof("RAIL:00000000"));
snprintf(class, sizeof("RAIL:00000000"), "RAIL:%08X", id);
class_hints->res_class = class;
}
class_hints->res_name = "RAIL";
XSetClassHint(xfc->display, window->handle, class_hints);
XSetClassHint(xfc->display, appWindow->handle, class_hints);
XFree(class_hints);
if (class)
@ -584,10 +610,10 @@ xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int widt
InputModeHint->flags = (1L << 0);
InputModeHint->input = True;
XSetWMHints(xfc->display, window->handle, InputModeHint);
XSetWMHints(xfc->display, appWindow->handle, InputModeHint);
XFree(InputModeHint);
XSetWMProtocols(xfc->display, window->handle, &(xfc->WM_DELETE_WINDOW), 1);
XSetWMProtocols(xfc->display, appWindow->handle, &(xfc->WM_DELETE_WINDOW), 1);
input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask |
ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
@ -598,23 +624,23 @@ xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int widt
SubstructureRedirectMask | FocusChangeMask | PropertyChangeMask |
ColormapChangeMask | OwnerGrabButtonMask;
XSelectInput(xfc->display, window->handle, input_mask);
XSelectInput(xfc->display, appWindow->handle, input_mask);
xf_SetWindowDecorations(xfc, window->handle, window->decorations);
xf_SetWindowStyle(xfc, window, wnd->style, wnd->extendedStyle);
xf_SetWindowPID(xfc, window, 0);
xf_ShowWindow(xfc, window, WINDOW_SHOW);
xf_SetWindowDecorations(xfc, appWindow->handle, appWindow->decorations);
xf_SetWindowStyle(xfc, appWindow, wnd->style, wnd->extendedStyle);
xf_SetWindowPID(xfc, appWindow->handle, 0);
xf_ShowWindow(xfc, appWindow, WINDOW_SHOW);
XClearWindow(xfc->display, window->handle);
XMapWindow(xfc->display, window->handle);
XClearWindow(xfc->display, appWindow->handle);
XMapWindow(xfc->display, appWindow->handle);
/* Move doesn't seem to work until window is mapped. */
xf_MoveWindow(xfc, window, x, y, width, height);
xf_MoveWindow(xfc, appWindow, x, y, width, height);
return window;
return appWindow;
}
void xf_SetWindowMinMaxInfo(xfContext* xfc, xfWindow* window,
void xf_SetWindowMinMaxInfo(xfContext* xfc, xfAppWindow* appWindow,
int maxWidth, int maxHeight, int maxPosX, int maxPosY,
int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight)
{
@ -630,28 +656,28 @@ void xf_SetWindowMinMaxInfo(xfContext* xfc, xfWindow* window,
size_hints->max_height = maxTrackHeight;
/* to speedup window drawing we need to select optimal value for sizing step. */
size_hints->width_inc = size_hints->height_inc = 1;
XSetWMNormalHints(xfc->display, window->handle, size_hints);
XSetWMNormalHints(xfc->display, appWindow->handle, size_hints);
XFree(size_hints);
}
}
void xf_StartLocalMoveSize(xfContext* xfc, xfWindow* window, int direction, int x, int y)
void xf_StartLocalMoveSize(xfContext* xfc, xfAppWindow* appWindow, int direction, int x, int y)
{
if (window->local_move.state != LMS_NOT_ACTIVE)
if (appWindow->local_move.state != LMS_NOT_ACTIVE)
return;
/*
* Save original mouse location relative to root. This will be needed
* to end local move to RDP server and/or X server
*/
window->local_move.root_x = x;
window->local_move.root_y = y;
window->local_move.state = LMS_STARTING;
window->local_move.direction = direction;
appWindow->local_move.root_x = x;
appWindow->local_move.root_y = y;
appWindow->local_move.state = LMS_STARTING;
appWindow->local_move.direction = direction;
XUngrabPointer(xfc->display, CurrentTime);
xf_SendClientEvent(xfc, window->handle,
xf_SendClientEvent(xfc, appWindow->handle,
xfc->_NET_WM_MOVERESIZE, /* request X window manager to initiate a local move */
5, /* 5 arguments to follow */
x, /* x relative to root window */
@ -661,12 +687,12 @@ void xf_StartLocalMoveSize(xfContext* xfc, xfWindow* window, int direction, int
1); /* 1 == application request per extended ICCM */
}
void xf_EndLocalMoveSize(xfContext* xfc, xfWindow* window)
void xf_EndLocalMoveSize(xfContext* xfc, xfAppWindow* appWindow)
{
if (window->local_move.state == LMS_NOT_ACTIVE)
if (appWindow->local_move.state == LMS_NOT_ACTIVE)
return;
if (window->local_move.state == LMS_STARTING)
if (appWindow->local_move.state == LMS_STARTING)
{
/*
* The move never was property started. This can happen due to race
@ -674,63 +700,61 @@ void xf_EndLocalMoveSize(xfContext* xfc, xfWindow* window)
* RDP server for local moves. We must cancel the X window manager move.
* Per ICCM, the X client can ask to cancel an active move.
*/
xf_SendClientEvent(xfc, window->handle,
xf_SendClientEvent(xfc, appWindow->handle,
xfc->_NET_WM_MOVERESIZE, /* request X window manager to abort a local move */
5, /* 5 arguments to follow */
window->local_move.root_x, /* x relative to root window */
window->local_move.root_y, /* y relative to root window */
appWindow->local_move.root_x, /* x relative to root window */
appWindow->local_move.root_y, /* y relative to root window */
_NET_WM_MOVERESIZE_CANCEL, /* extended ICCM direction flag */
1, /* simulated mouse button 1 */
1); /* 1 == application request per extended ICCM */
}
window->local_move.state = LMS_NOT_ACTIVE;
appWindow->local_move.state = LMS_NOT_ACTIVE;
}
void xf_MoveWindow(xfContext* xfc, xfWindow* window, int x, int y, int width, int height)
void xf_MoveWindow(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height)
{
BOOL resize = FALSE;
if ((width * height) < 1)
return;
if ((window->width != width) || (window->height != height))
if ((appWindow->width != width) || (appWindow->height != height))
resize = TRUE;
if (window->local_move.state == LMS_STARTING ||
window->local_move.state == LMS_ACTIVE)
if (appWindow->local_move.state == LMS_STARTING ||
appWindow->local_move.state == LMS_ACTIVE)
return;
window->left = x;
window->top = y;
window->right = x + width - 1;
window->bottom = y + height - 1;
window->width = width;
window->height = height;
appWindow->x = x;
appWindow->y = y;
appWindow->width = width;
appWindow->height = height;
if (resize)
XMoveResizeWindow(xfc->display, window->handle, x, y, width, height);
XMoveResizeWindow(xfc->display, appWindow->handle, x, y, width, height);
else
XMoveWindow(xfc->display, window->handle, x, y);
XMoveWindow(xfc->display, appWindow->handle, x, y);
xf_UpdateWindowArea(xfc, window, 0, 0, width, height);
xf_UpdateWindowArea(xfc, appWindow, 0, 0, width, height);
}
void xf_ShowWindow(xfContext* xfc, xfWindow* window, BYTE state)
void xf_ShowWindow(xfContext* xfc, xfAppWindow* appWindow, BYTE state)
{
switch (state)
{
case WINDOW_HIDE:
XWithdrawWindow(xfc->display, window->handle, xfc->screen_number);
XWithdrawWindow(xfc->display, appWindow->handle, xfc->screen_number);
break;
case WINDOW_SHOW_MINIMIZED:
XIconifyWindow(xfc->display, window->handle, xfc->screen_number);
XIconifyWindow(xfc->display, appWindow->handle, xfc->screen_number);
break;
case WINDOW_SHOW_MAXIMIZED:
/* Set the window as maximized */
xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, 1,
xf_SendClientEvent(xfc, appWindow->handle, xfc->_NET_WM_STATE, 4, 1,
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False),
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False), 0);
/*
@ -739,13 +763,13 @@ void xf_ShowWindow(xfContext* xfc, xfWindow* window, BYTE state)
* actually maximized on the server - an update of the new areas may not happen. So, we simply to do a full update of
* the entire window once the rail server notifies us that the window is now maximized.
*/
if (window->rail_state == WINDOW_SHOW_MAXIMIZED)
xf_UpdateWindowArea(xfc, window, 0, 0, window->window->windowWidth, window->window->windowHeight);
if (appWindow->rail_state == WINDOW_SHOW_MAXIMIZED)
xf_UpdateWindowArea(xfc, appWindow, 0, 0, appWindow->window->windowWidth, appWindow->window->windowHeight);
break;
case WINDOW_SHOW:
/* Ensure the window is not maximized */
xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, 0,
xf_SendClientEvent(xfc, appWindow->handle, xfc->_NET_WM_STATE, 4, 0,
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False),
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False), 0);
/*
@ -754,20 +778,20 @@ void xf_ShowWindow(xfContext* xfc, xfWindow* window, BYTE state)
* still being set - which causes a position adjustment to be sent back to the server
* thus causing the window to not return to its original size
*/
if (window->rail_state == WINDOW_SHOW_MAXIMIZED)
window->rail_ignore_configure = TRUE;
if (appWindow->rail_state == WINDOW_SHOW_MAXIMIZED)
appWindow->rail_ignore_configure = TRUE;
if (window->is_transient)
xf_SetWindowUnlisted(xfc, window->handle);
if (appWindow->is_transient)
xf_SetWindowUnlisted(xfc, appWindow->handle);
break;
}
/* Save the current rail state of this window */
window->rail_state = state;
appWindow->rail_state = state;
XFlush(xfc->display);
}
void xf_SetWindowIcon(xfContext* xfc, xfWindow* window, rdpIcon* icon)
void xf_SetWindowIcon(xfContext* xfc, xfAppWindow* appWindow, rdpIcon* icon)
{
int x, y;
int pixels;
@ -795,7 +819,7 @@ void xf_SetWindowIcon(xfContext* xfc, xfWindow* window, rdpIcon* icon)
}
}
XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_ICON, XA_CARDINAL, 32,
XChangeProperty(xfc->display, appWindow->handle, xfc->_NET_WM_ICON, XA_CARDINAL, 32,
PropModeReplace, (BYTE *) propdata, propsize);
XFlush(xfc->display);
@ -803,7 +827,7 @@ void xf_SetWindowIcon(xfContext* xfc, xfWindow* window, rdpIcon* icon)
free(propdata);
}
void xf_SetWindowRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, int nrects)
void xf_SetWindowRects(xfContext* xfc, xfAppWindow* appWindow, RECTANGLE_16* rects, int nrects)
{
int i;
XRectangle* xrects;
@ -811,7 +835,7 @@ void xf_SetWindowRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, in
if (nrects < 1)
return;
xrects = malloc(sizeof(XRectangle) * nrects);
xrects = (XRectangle*) calloc(nrects, sizeof(XRectangle));
for (i = 0; i < nrects; i++)
{
@ -822,17 +846,13 @@ void xf_SetWindowRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, in
}
#ifdef WITH_XEXT
/*
* This is currently unsupported with the new logic to handle window placement with VisibleOffset variables
*
* Marc: enabling it works, and is required for round corners.
*/
XShapeCombineRectangles(xfc->display, window->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
XShapeCombineRectangles(xfc->display, appWindow->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
#endif
free(xrects);
}
void xf_SetWindowVisibilityRects(xfContext* xfc, xfWindow* window, RECTANGLE_16 *rects, int nrects)
void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, RECTANGLE_16* rects, int nrects)
{
int i;
XRectangle* xrects;
@ -840,7 +860,7 @@ void xf_SetWindowVisibilityRects(xfContext* xfc, xfWindow* window, RECTANGLE_16
if (nrects < 1)
return;
xrects = malloc(sizeof(XRectangle) * nrects);
xrects = (XRectangle*) calloc(nrects, sizeof(XRectangle));
for (i = 0; i < nrects; i++)
{
@ -849,91 +869,71 @@ void xf_SetWindowVisibilityRects(xfContext* xfc, xfWindow* window, RECTANGLE_16
xrects[i].width = rects[i].right - rects[i].left;
xrects[i].height = rects[i].bottom - rects[i].top;
}
#ifdef WITH_XEXT
/*
* This is currently unsupported with the new logic to handle window placement with VisibleOffset variables
*
* Marc: enabling it works, and is required for round corners.
*/
XShapeCombineRectangles(xfc->display, window->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
XShapeCombineRectangles(xfc->display, appWindow->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
#endif
free(xrects);
}
void xf_UpdateWindowArea(xfContext* xfc, xfWindow* window, int x, int y, int width, int height)
void xf_UpdateWindowArea(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height)
{
int ax, ay;
rdpWindow* wnd;
wnd = window->window;
wnd = appWindow->window;
/* RemoteApp mode uses visibleOffset instead of windowOffset */
ax = x + wnd->visibleOffsetX;
ay = y + wnd->visibleOffsetY;
if (!xfc->remote_app)
{
ax = x + wnd->windowOffsetX;
ay = y + wnd->windowOffsetY;
if (ax + width > wnd->visibleOffsetX + wnd->windowWidth)
width = (wnd->visibleOffsetX + wnd->windowWidth - 1) - ax;
if (ay + height > wnd->visibleOffsetY + wnd->windowHeight)
height = (wnd->visibleOffsetY + wnd->windowHeight - 1) - ay;
if (ax + width > wnd->windowOffsetX + wnd->windowWidth)
width = (wnd->windowOffsetX + wnd->windowWidth - 1) - ax;
if (ay + height > wnd->windowOffsetY + wnd->windowHeight)
height = (wnd->windowOffsetY + wnd->windowHeight - 1) - ay;
}
else
{
ax = x + wnd->visibleOffsetX;
ay = y + wnd->visibleOffsetY;
if (ax + width > wnd->visibleOffsetX + wnd->windowWidth)
width = (wnd->visibleOffsetX + wnd->windowWidth - 1) - ax;
if (ay + height > wnd->visibleOffsetY + wnd->windowHeight)
height = (wnd->visibleOffsetY + wnd->windowHeight - 1) - ay;
}
WaitForSingleObject(xfc->mutex, INFINITE);
xf_lock_x11(xfc, TRUE);
if (xfc->settings->SoftwareGdi)
{
XPutImage(xfc->display, xfc->primary, window->gc, xfc->image,
ax, ay, ax, ay, width, height);
XPutImage(xfc->display, xfc->primary, appWindow->gc, xfc->image,
ax, ay, ax, ay, width, height);
}
XCopyArea(xfc->display, xfc->primary, window->handle, window->gc,
ax, ay, width, height, x, y);
XCopyArea(xfc->display, xfc->primary, appWindow->handle, appWindow->gc,
ax, ay, width, height, x, y);
XFlush(xfc->display);
ReleaseMutex(xfc->mutex);
xf_unlock_x11(xfc, TRUE);
}
void xf_DestroyWindow(xfContext* xfc, xfWindow* window)
void xf_DestroyWindow(xfContext* xfc, xfAppWindow* appWindow)
{
if (!window)
if (!appWindow)
return;
if (xfc->window == window)
xfc->window = NULL;
if (appWindow->gc)
XFreeGC(xfc->display, appWindow->gc);
if (window->gc)
XFreeGC(xfc->display, window->gc);
if (window->handle)
if (appWindow->handle)
{
XUnmapWindow(xfc->display, window->handle);
XDestroyWindow(xfc->display, window->handle);
XUnmapWindow(xfc->display, appWindow->handle);
XDestroyWindow(xfc->display, appWindow->handle);
}
if (window->xfwin)
munmap(0, sizeof(*window->xfwin));
if (appWindow->xfwin)
munmap(0, sizeof(*appWindow->xfwin));
if (window->shmid >= 0)
close(window->shmid);
if (appWindow->shmid >= 0)
close(appWindow->shmid);
shm_unlink(get_shm_id());
window->xfwin = (Window*) -1;
window->shmid = -1;
appWindow->xfwin = (Window*) -1;
appWindow->shmid = -1;
free(window);
free(appWindow);
}
rdpWindow* xf_rdpWindowFromWindow(xfContext* xfc, Window wnd)
@ -947,7 +947,7 @@ rdpWindow* xf_rdpWindowFromWindow(xfContext* xfc, Window wnd)
rail = ((rdpContext*) xfc)->rail;
if (rail)
return window_list_get_by_extra_id(rail->list, (void*)(long) wnd);
return window_list_get_by_extra_id(rail->list, (void*) (long) wnd);
}
}

View File

@ -24,6 +24,8 @@
#include <freerdp/freerdp.h>
typedef struct xf_app_window xfAppWindow;
typedef struct xf_localmove xfLocalMove;
typedef struct xf_window xfWindow;
@ -79,6 +81,26 @@ struct xf_window
BOOL decorations;
BOOL is_mapped;
BOOL is_transient;
};
struct xf_app_window
{
xfContext* xfc;
rdpWindow* window;
int x;
int y;
int width;
int height;
GC gc;
int shmid;
Window handle;
Window* xfwin;
BOOL fullscreen;
BOOL decorations;
BOOL is_mapped;
BOOL is_transient;
xfLocalMove local_move;
BYTE rail_state;
BOOL rail_ignore_configure;
@ -95,26 +117,27 @@ void xf_SetWindowUnlisted(xfContext* xfc, Window window);
xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int height, BOOL decorations);
void xf_ResizeDesktopWindow(xfContext* xfc, xfWindow* window, int width, int height);
void xf_DestroyDesktopWindow(xfContext* xfc, xfWindow* window);
BOOL xf_GetWindowProperty(xfContext* xfc, Window window, Atom property, int length,
unsigned long* nitems, unsigned long* bytes, BYTE** prop);
void xf_SendClientEvent(xfContext* xfc, Window window, Atom atom, unsigned int numArgs, ...);
xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int width, int height, UINT32 id);
void xf_SetWindowText(xfContext* xfc, xfWindow* window, char* name);
void xf_MoveWindow(xfContext* xfc, xfWindow* window, int x, int y, int width, int height);
void xf_ShowWindow(xfContext* xfc, xfWindow* window, BYTE state);
void xf_SetWindowIcon(xfContext* xfc, xfWindow* window, rdpIcon* icon);
void xf_SetWindowRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, int nrects);
void xf_SetWindowVisibilityRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, int nrects);
void xf_SetWindowStyle(xfContext* xfc, xfWindow* window, UINT32 style, UINT32 ex_style);
void xf_UpdateWindowArea(xfContext* xfc, xfWindow* window, int x, int y, int width, int height);
void xf_DestroyWindow(xfContext* xfc, xfWindow* window);
void xf_SetWindowMinMaxInfo(xfContext* xfc, xfWindow* window,
xfAppWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int width, int height, UINT32 id);
void xf_SetWindowText(xfContext* xfc, xfAppWindow* appWindow, char* name);
void xf_MoveWindow(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height);
void xf_ShowWindow(xfContext* xfc, xfAppWindow* appWindow, BYTE state);
void xf_SetWindowIcon(xfContext* xfc, xfAppWindow* appWindow, rdpIcon* icon);
void xf_SetWindowRects(xfContext* xfc, xfAppWindow* appWindow, RECTANGLE_16* rects, int nrects);
void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, RECTANGLE_16* rects, int nrects);
void xf_SetWindowStyle(xfContext* xfc, xfAppWindow* appWindow, UINT32 style, UINT32 ex_style);
void xf_UpdateWindowArea(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height);
void xf_DestroyWindow(xfContext* xfc, xfAppWindow* appWindow);
void xf_SetWindowMinMaxInfo(xfContext* xfc, xfAppWindow* appWindow,
int maxWidth, int maxHeight, int maxPosX, int maxPosY,
int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight);
void xf_StartLocalMoveSize(xfContext* xfc, xfWindow* window, int direction, int x, int y);
void xf_EndLocalMoveSize(xfContext* xfc, xfWindow* window);
void xf_StartLocalMoveSize(xfContext* xfc, xfAppWindow* appWindow, int direction, int x, int y);
void xf_EndLocalMoveSize(xfContext* xfc, xfAppWindow* appWindow);
rdpWindow* xf_rdpWindowFromWindow(xfContext* xfc, Window wnd);
#endif /* __XF_WINDOW_H */

View File

@ -106,6 +106,7 @@ struct xf_context
BOOL unobscured;
BOOL debug;
xfWindow* window;
xfAppWindow* appWindow;
xfPointer* pointer;
xfWorkArea workArea;
int current_desktop;