From: Marc-André Moreau Date: Wed, 12 Nov 2014 03:27:33 +0000 (-0500) Subject: xfreerdp: separate app windows from desktop windows X-Git-Tag: 2.0.0-beta1+android10~743^2~38 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1225c6b5ceb3551b4181f69a0c5185a112c7b898;p=platform%2Fupstream%2Ffreerdp.git xfreerdp: separate app windows from desktop windows --- diff --git a/channels/tsmf/client/gstreamer/tsmf_X11.c b/channels/tsmf/client/gstreamer/tsmf_X11.c index d4cbcb4..e678f88 100644 --- a/channels/tsmf/client/gstreamer/tsmf_X11.c +++ b/channels/tsmf/client/gstreamer/tsmf_X11.c @@ -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; } diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index c34018d..4772f73 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -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->settings->WindowTitle); + } + else if (xfc->settings->ServerPort == 3389) { - windowTitle = _strdup(xfc->instance->settings->WindowTitle); + 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; diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c index ec1219f..ff9705f 100644 --- a/client/X11/xf_event.c +++ b/client/X11/xf_event.c @@ -24,8 +24,8 @@ #include #include -#include #include +#include #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. - */ + appWindow = (xfAppWindow*) window->extra; - XTranslateCoordinates(xfc->display, xfw->handle, - RootWindowOfScreen(xfc->screen), - 0, 0, &xfw->left, &xfw->top, &childWindow); + /* + * 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); - 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->width = event->xconfigure.width; + appWindow->height = event->xconfigure.height; /* - * Additonal checks for not in a local move and not ignoring configure to send + * 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; diff --git a/client/X11/xf_keyboard.c b/client/X11/xf_keyboard.c index f926132..0a15c1d 100644 --- a/client/X11/xf_keyboard.c +++ b/client/X11/xf_keyboard.c @@ -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); } } diff --git a/client/X11/xf_rail.c b/client/X11/xf_rail.c index ea4bcdc..b80f74c 100644 --- a/client/X11/xf_rail.c +++ b/client/X11/xf_rail.c @@ -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; + xfAppWindow* appWindow; + xfc = (xfContext*) rail->extra; - xfw = (xfWindow*) window->extra; + appWindow = (xfAppWindow*) window->extra; - xf_SetWindowRects(xfc, xfw, window->windowRects, window->numWindowRects); + 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, diff --git a/client/X11/xf_rail.h b/client/X11/xf_rail.h index 7b3b4a0..d7a47ea 100644 --- a/client/X11/xf_rail.h +++ b/client/X11/xf_rail.h @@ -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 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); diff --git a/client/X11/xf_window.c b/client/X11/xf_window.c index f456e01..fc54a2e 100644 --- a/client/X11/xf_window.c +++ b/client/X11/xf_window.c @@ -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; - - window->handle = XCreateWindow(xfc->display, RootWindowOfScreen(xfc->screen), - x, y, window->width, window->height, 0, xfc->depth, + 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; + + 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; - - /* RemoteApp mode uses visibleOffset instead of windowOffset */ + wnd = appWindow->window; - if (!xfc->remote_app) - { - ax = x + wnd->windowOffsetX; - ay = y + wnd->windowOffsetY; - - 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; + 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; - } + 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 (window->gc) - XFreeGC(xfc->display, window->gc); + if (appWindow->gc) + XFreeGC(xfc->display, appWindow->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); } } diff --git a/client/X11/xf_window.h b/client/X11/xf_window.h index add3662..fb93098 100644 --- a/client/X11/xf_window.h +++ b/client/X11/xf_window.h @@ -24,6 +24,8 @@ #include +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 */ diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index 6df2bb1..cda774e 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -106,6 +106,7 @@ struct xf_context BOOL unobscured; BOOL debug; xfWindow* window; + xfAppWindow* appWindow; xfPointer* pointer; xfWorkArea workArea; int current_desktop;