From f3d1830eb4da5176f175b1426cf638a0933fae6c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 11 Nov 2014 17:49:29 -0500 Subject: [PATCH] xfreerdp: partially migrate RAIL to callback interface --- client/X11/xf_client.c | 194 ++++++++++------------ client/X11/xf_rail.c | 442 +++++++++++++++++++++++++++---------------------- client/X11/xf_rail.h | 19 ++- client/X11/xfreerdp.h | 2 + 4 files changed, 351 insertions(+), 306 deletions(-) diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 22b3b48..6d81d80 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -116,15 +116,15 @@ void xf_transform_window(xfContext *xfc) XSizeHints *size_hints = NULL; hints_atom = XInternAtom(xfc->display, "WM_SIZE_HINTS", 1); ret = XGetWMSizeHints(xfc->display, xfc->window->handle, size_hints, &supplied, hints_atom); - if(ret == 0) + if (ret == 0) size_hints = XAllocSizeHints(); w = (xfc->originalWidth * xfc->settings->ScalingFactor) + xfc->offset_x; h = (xfc->originalHeight * xfc->settings->ScalingFactor) + xfc->offset_y; - if(w < 1) + if (w < 1) w = 1; - if(h < 1) + if (h < 1) h = 1; - if(size_hints) + if (size_hints) { size_hints->flags |= PMinSize | PMaxSize; size_hints->min_width = size_hints->max_width = w; @@ -157,9 +157,9 @@ 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 ((w != 0) && (h != 0)) { - if(scale == TRUE) + if (scale == TRUE) { xr.x = x * xfc->settings->ScalingFactor; xr.y = y * xfc->settings->ScalingFactor; @@ -413,7 +413,7 @@ void xf_hw_desktop_resize(rdpContext *context) xfc->primary = XCreatePixmap(xfc->display, xfc->drawable, xfc->width, xfc->height, xfc->depth); - if(same) + if (same) xfc->drawing = xfc->primary; } } @@ -449,12 +449,12 @@ BOOL xf_process_x_events(freerdp *instance) xf_lock_x11(xfc, FALSE); pending_status = XPending(xfc->display); xf_unlock_x11(xfc, FALSE); - if(pending_status) + if (pending_status) { ZeroMemory(&xevent, sizeof(xevent)); XNextEvent(xfc->display, &xevent); status = xf_event_process(instance, &xevent); - if(!status) + if (!status) return status; } } @@ -469,7 +469,7 @@ void xf_create_window(xfContext *xfc) ZeroMemory(&xevent, sizeof(xevent)); width = xfc->width; height = xfc->height; - if(!xfc->remote_app) + if (!xfc->remote_app) { xfc->attribs.background_pixel = BlackPixelOfScreen(xfc->screen); xfc->attribs.border_pixel = WhitePixelOfScreen(xfc->screen); @@ -478,12 +478,12 @@ 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->instance->settings->WindowTitle) { windowTitle = _strdup(xfc->instance->settings->WindowTitle); } else - if(xfc->instance->settings->ServerPort == 3389) + if (xfc->instance->settings->ServerPort == 3389) { windowTitle = malloc(1 + sizeof("FreeRDP: ") + strlen(xfc->instance->settings->ServerHostname)); sprintf(windowTitle, "FreeRDP: %s", xfc->instance->settings->ServerHostname); @@ -495,7 +495,7 @@ void xf_create_window(xfContext *xfc) } xfc->window = xf_CreateDesktopWindow(xfc, windowTitle, width, height, xfc->settings->Decorations); free(windowTitle); - if(xfc->fullscreen) + 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); @@ -574,26 +574,26 @@ void xf_encomsp_uninit(xfContext* xfc, EncomspClientContext* encomsp) void xf_lock_x11(xfContext *xfc, BOOL display) { - if(!xfc->UseXThreads) + if (!xfc->UseXThreads) { WaitForSingleObject(xfc->mutex, INFINITE); } else { - if(display) + if (display) XLockDisplay(xfc->display); } } void xf_unlock_x11(xfContext *xfc, BOOL display) { - if(!xfc->UseXThreads) + if (!xfc->UseXThreads) { ReleaseMutex(xfc->mutex); } else { - if(display) + if (display) XUnlockDisplay(xfc->display); } } @@ -654,7 +654,7 @@ BOOL xf_get_pixmap_info(xfContext *xfc) for (i = 0; i < vi_count; i++) { vi = vis + i; - if(vi->visual == window_attributes.visual) + if (vi->visual == window_attributes.visual) { xfc->visual = vi->visual; break; @@ -691,7 +691,7 @@ int xf_error_handler(Display *d, XErrorEvent *ev) int do_abort = TRUE; XGetErrorText(d, ev->error_code, buf, sizeof(buf)); WLog_ERR(TAG, "%s", buf); - if(do_abort) + if (do_abort) abort(); _def_error_handler(d, ev); return FALSE; @@ -714,7 +714,7 @@ static void xf_post_disconnect(freerdp *instance) assert(NULL != instance); assert(NULL != xfc); assert(NULL != instance->settings); - if(xfc->mutex) + if (xfc->mutex) { WaitForSingleObject(xfc->mutex, INFINITE); CloseHandle(xfc->mutex); @@ -797,7 +797,7 @@ BOOL xf_pre_connect(freerdp* instance) if (xfc->UseXThreads) { - if(!XInitThreads()) + if (!XInitThreads()) { WLog_WARN(TAG, "XInitThreads() failure"); xfc->UseXThreads = FALSE; @@ -1041,7 +1041,7 @@ 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) + if (freerdp_passphrase_read("Password: ", *password, password_size, instance->settings->CredentialsFromStdin) == NULL) return FALSE; return TRUE; } @@ -1070,20 +1070,20 @@ BOOL xf_verify_certificate(freerdp *instance, char *subject, char *issuer, char { WLog_INFO(TAG, "Do you trust the above certificate? (Y/N) "); answer = fgetc(stdin); - if(feof(stdin)) + if (feof(stdin)) { WLog_INFO(TAG, "Error: Could not read answer from stdin."); - if(instance->settings->CredentialsFromStdin) + if (instance->settings->CredentialsFromStdin) WLog_INFO(TAG, " - Run without parameter \"--from-stdin\" to set trust."); WLog_INFO(TAG, ""); return FALSE; } - if(answer == 'y' || answer == 'Y') + if (answer == 'y' || answer == 'Y') { return TRUE; } else - if(answer == 'n' || answer == 'N') + if (answer == 'n' || answer == 'N') { break; } @@ -1099,30 +1099,6 @@ int xf_logon_error_info(freerdp *instance, UINT32 data, UINT32 type) return 1; } -void xf_process_channel_event(rdpChannels* channels, freerdp* instance) -{ - xfContext* xfc; - wMessage* event; - xfc = (xfContext*) instance->context; - - event = freerdp_channels_pop_event(channels); - - if (event) - { - switch(GetMessageClass(event->id)) - { - case RailChannel_Class: - xf_process_rail_event(xfc, channels, event); - break; - - default: - break; - } - - freerdp_event_free(event); - } -} - void xf_window_free(xfContext *xfc) { rdpContext* context = (rdpContext*) xfc; @@ -1227,7 +1203,7 @@ void* xf_input_thread(void *arg) process_status = xf_event_process(instance, &xevent); xf_unlock_x11(xfc, FALSE); - if(!process_status) + if (!process_status) break; } } @@ -1261,8 +1237,6 @@ void* xf_channels_thread(void *arg) if (!status) break; - - xf_process_channel_event(channels, instance); } ExitThread(0); @@ -1275,11 +1249,11 @@ BOOL xf_auto_reconnect(freerdp *instance) UINT32 num_retries = 0; UINT32 max_retries = instance->settings->AutoReconnectMaxRetries; /* Only auto reconnect on network disconnects. */ - if(freerdp_error_info(instance) != 0) + if (freerdp_error_info(instance) != 0) return FALSE; /* A network disconnect was detected */ WLog_INFO(TAG, "Network disconnect!"); - if(!instance->settings->AutoReconnectionEnabled) + if (!instance->settings->AutoReconnectionEnabled) { /* No auto-reconnect - just quit */ return FALSE; @@ -1288,13 +1262,13 @@ BOOL xf_auto_reconnect(freerdp *instance) for(;;) { /* Quit retrying if max retries has been exceeded */ - if(num_retries++ >= max_retries) + 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)) + if (freerdp_reconnect(instance)) { xfc->disconnect = FALSE; return TRUE; @@ -1349,15 +1323,15 @@ void* xf_thread(void *param) xfc = (xfContext *) instance->context; assert(NULL != xfc); /* Connection succeeded. --authonly ? */ - if(instance->settings->AuthenticationOnly) + if (instance->settings->AuthenticationOnly) { freerdp_disconnect(instance); WLog_ERR(TAG, "Authentication only, exit status %d", !status); ExitThread(exit_code); } - if(!status) + if (!status) { - if(xfc->mutex) + if (xfc->mutex) { WaitForSingleObject(xfc->mutex, INFINITE); CloseHandle(xfc->mutex); @@ -1373,11 +1347,11 @@ void* xf_thread(void *param) async_channels = settings->AsyncChannels; async_transport = settings->AsyncTransport; - if(async_input) + if (async_input) { input_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_input_thread, instance, 0, NULL); } - if(async_channels) + if (async_channels) { channels_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_channels_thread, instance, 0, NULL); } @@ -1390,32 +1364,35 @@ void* xf_thread(void *param) * when a initial sync request is send to sync the keyboard inidcators * sending the sync event twice fixed this problem */ - if(freerdp_focus_required(instance)) + if (freerdp_focus_required(instance)) { xf_keyboard_focus_in(xfc); xf_keyboard_focus_in(xfc); } - if(!async_transport) + + if (!async_transport) { - if(freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) + if (!freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount)) { WLog_ERR(TAG, "Failed to get FreeRDP file descriptor"); exit_code = XF_EXIT_CONN_FAILED; break; } } - if(!async_channels) + + if (!async_channels) { - if(freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != TRUE) + if (!freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount)) { WLog_ERR(TAG, "Failed to get channel manager file descriptor"); exit_code = XF_EXIT_CONN_FAILED; break; } } - if(!async_input) + + if (!async_input) { - if(xf_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) + if (!xf_get_fds(instance, rfds, &rcount, wfds, &wcount)) { WLog_ERR(TAG, "Failed to get xfreerdp file descriptor"); exit_code = XF_EXIT_CONN_FAILED; @@ -1428,58 +1405,67 @@ void* xf_thread(void *param) fd_input_event = GetEventFileDescriptor(input_event); rfds[rcount++] = (void *)(long) fd_input_event; } + max_fds = 0; FD_ZERO(&rfds_set); FD_ZERO(&wfds_set); - for(i = 0; i < rcount; i++) + + for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); - if(fds > max_fds) + + if (fds > max_fds) max_fds = fds; + FD_SET(fds, &rfds_set); } - if(max_fds == 0) + + if (max_fds == 0) break; + timeout.tv_sec = 1; timeout.tv_usec = 0; select_status = select(max_fds + 1, &rfds_set, NULL, NULL, &timeout); - if(select_status == 0) + + if (select_status == 0) { continue; /* select timeout */ } - else - if(select_status == -1) + else if (select_status == -1) + { + /* these are not really errors */ + if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || + (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { - /* these are not really errors */ - if(!((errno == EAGAIN) || (errno == EWOULDBLOCK) || - (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ - { - WLog_ERR(TAG, "xfreerdp_run: select failed"); - break; - } + WLog_ERR(TAG, "xfreerdp_run: select failed"); + break; } - if(!async_transport) + } + + if (!async_transport) { - if(freerdp_check_fds(instance) != TRUE) + if (!freerdp_check_fds(instance)) { - if(xf_auto_reconnect(instance)) + if (xf_auto_reconnect(instance)) continue; + WLog_ERR(TAG, "Failed to check FreeRDP file descriptor"); break; } } - if(!async_channels) + + if (!async_channels) { - if(freerdp_channels_check_fds(channels, instance) != TRUE) + if (!freerdp_channels_check_fds(channels, instance)) { WLog_ERR(TAG, "Failed to check channel manager file descriptor"); break; } - xf_process_channel_event(channels, instance); } - if(!async_input) + + if (!async_input) { - if(xf_process_x_events(instance) != TRUE) + if (!xf_process_x_events(instance)) { WLog_INFO(TAG, "Closed from X11"); break; @@ -1487,9 +1473,9 @@ void* xf_thread(void *param) } else { - if(WaitForSingleObject(input_event, 0) == WAIT_OBJECT_0) + if (WaitForSingleObject(input_event, 0) == WAIT_OBJECT_0) { - if(!freerdp_message_queue_process_pending_messages(instance, FREERDP_INPUT_MESSAGE_QUEUE)) + if (!freerdp_message_queue_process_pending_messages(instance, FREERDP_INPUT_MESSAGE_QUEUE)) { WLog_INFO(TAG, "User Disconnect"); xfc->disconnect = TRUE; @@ -1502,42 +1488,46 @@ void* xf_thread(void *param) * that the threads should quit. */ freerdp_channels_close(channels, instance); - if(async_input) + if (async_input) { wMessageQueue *input_queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE); MessageQueue_PostQuit(input_queue, 0); WaitForSingleObject(input_thread, INFINITE); CloseHandle(input_thread); } - if(async_channels) + + if (async_channels) { WaitForSingleObject(channels_thread, INFINITE); CloseHandle(channels_thread); } - if(!exit_code) + + if (!exit_code) exit_code = freerdp_error_info(instance); + freerdp_channels_free(channels); freerdp_disconnect(instance); gdi_free(instance); + ExitThread(exit_code); return NULL; } DWORD xf_exit_code_from_disconnect_reason(DWORD reason) { - if(reason == 0 || (reason >= XF_EXIT_PARSE_ARGUMENTS && reason <= XF_EXIT_CONN_FAILED)) + if (reason == 0 || (reason >= XF_EXIT_PARSE_ARGUMENTS && reason <= XF_EXIT_CONN_FAILED)) return reason; /* License error set */ else - if(reason >= 0x100 && reason <= 0x10A) + if (reason >= 0x100 && reason <= 0x10A) reason -= 0x100 + XF_EXIT_LICENSE_INTERNAL; /* RDP protocol error set */ else - if(reason >= 0x10c9 && reason <= 0x1193) + if (reason >= 0x10c9 && reason <= 0x1193) reason = XF_EXIT_RDP; /* There's no need to test protocol-independent codes: they match */ else - if(!(reason <= 0xB)) + if (!(reason <= 0xB)) reason = XF_EXIT_UNKNOWN; return reason; } @@ -1546,10 +1536,10 @@ void xf_TerminateEventHandler(rdpContext *context, TerminateEventArgs *e) { wMessageQueue *queue; xfContext *xfc = (xfContext *) context; - if(context->settings->AsyncInput) + if (context->settings->AsyncInput) { queue = freerdp_get_message_queue(context->instance, FREERDP_INPUT_MESSAGE_QUEUE); - if(queue) + if (queue) MessageQueue_PostQuit(queue, 0); } else @@ -1624,7 +1614,7 @@ static int xfreerdp_client_stop(rdpContext* context) { wMessageQueue *queue; queue = freerdp_get_message_queue(context->instance, FREERDP_INPUT_MESSAGE_QUEUE); - if(queue) + if (queue) MessageQueue_PostQuit(queue, 0); } else diff --git a/client/X11/xf_rail.c b/client/X11/xf_rail.c index 0da4945..f8c5d40 100644 --- a/client/X11/xf_rail.c +++ b/client/X11/xf_rail.c @@ -36,12 +36,6 @@ #define TAG CLIENT_TAG("x11") -#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 - const char* error_code_names[] = { "RAIL_EXEC_S_OK", @@ -185,9 +179,8 @@ static void xf_rail_MoveWindow(rdpRail* rail, rdpWindow* window) return; } - xf_MoveWindow(xfc, xfw, - window->visibleOffsetX, window->visibleOffsetY, - window->windowWidth, window->windowHeight); + xf_MoveWindow(xfc, xfw, window->visibleOffsetX, window->visibleOffsetY, + window->windowWidth, window->windowHeight); } static void xf_rail_ShowWindow(rdpRail* rail, rdpWindow* window, BYTE state) @@ -362,14 +355,6 @@ void xf_rail_adjust_position(xfContext* xfc, rdpWindow* window) window_move.right = window_move.left + xfw->width; window_move.bottom = window_move.top + xfw->height; - DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%u h=%u" - " RDP=0x%X rc={l=%d t=%d} w=%d h=%d", - (UINT32) xfw->handle, window_move.left, window_move.top, - window_move.right, window_move.bottom, xfw->width, xfw->height, - window->windowId, - window->windowOffsetX, window->windowOffsetY, - window->windowWidth, window->windowHeight); - xf_send_rail_client_event(channels, RailChannel_ClientWindowMove, &window_move); } } @@ -389,10 +374,6 @@ void xf_rail_end_local_move(xfContext* xfc, rdpWindow* window) xfw = (xfWindow*) window->extra; channels = ((rdpContext*) xfc)->channels; - DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d", - (UINT32) xfw->handle, - xfw->left, xfw->top, xfw->right, xfw->bottom, - xfw->width, xfw->height); /* * Although the rail server can give negative window coordinates when updating windowOffsetX and windowOffsetY, * we can only send unsigned integers to the rail server. Therefore, we always bring negative coordinates up to 0 when @@ -433,7 +414,6 @@ void xf_rail_end_local_move(xfContext* xfc, rdpWindow* window) (xfw->local_move.direction != _NET_WM_MOVERESIZE_SIZE_KEYBOARD)) { input->MouseEvent(input, PTR_FLAGS_BUTTON1, x, y); - DEBUG_X11_LMS("Mouse coordinates. x= %i, y= %i", x, y); } /* @@ -448,236 +428,285 @@ void xf_rail_end_local_move(xfContext* xfc, rdpWindow* window) xfw->local_move.state = LMS_TERMINATING; } -void xf_process_rail_get_sysparams_event(xfContext* xfc, rdpChannels* channels, wMessage* event) -{ - RAIL_SYSPARAM_ORDER* sysparam; - sysparam = (RAIL_SYSPARAM_ORDER*) event->wParam; - sysparam->workArea.left = xfc->workArea.x; - sysparam->workArea.top = xfc->workArea.y; - sysparam->workArea.right = xfc->workArea.x + xfc->workArea.width; - sysparam->workArea.bottom = xfc->workArea.y + xfc->workArea.height; - sysparam->taskbarPos.left = 0; - sysparam->taskbarPos.top = 0; - sysparam->taskbarPos.right = 0; - sysparam->taskbarPos.bottom = 0; - sysparam->dragFullWindows = FALSE; - xf_send_rail_client_event(channels, RailChannel_ClientSystemParam, sysparam); +void xf_rail_invalidate_region(xfContext* xfc, REGION16* invalidRegion) +{ + int index; + int count; + RECTANGLE_16 updateRect; + RECTANGLE_16 windowRect; + ULONG_PTR* pKeys = NULL; + xfRailWindow* railWindow; + const RECTANGLE_16* extents; + REGION16 windowInvalidRegion; + + region16_init(&windowInvalidRegion); + + count = HashTable_GetKeys(xfc->railWindows, &pKeys); + + for (index = 0; index < count; index++) + { + railWindow = (xfRailWindow*) HashTable_GetItemValue(xfc->railWindows, (void*) pKeys[index]); + + if (railWindow) + { + windowRect.left = railWindow->x; + windowRect.top = railWindow->y; + windowRect.right = railWindow->x + railWindow->width; + windowRect.bottom = railWindow->y + railWindow->height; + + region16_clear(&windowInvalidRegion); + region16_intersect_rect(&windowInvalidRegion, invalidRegion, &windowRect); + + if (!region16_is_empty(&windowInvalidRegion)) + { + 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; + + //InvalidateRect(railWindow->hWnd, &updateRect, FALSE); + } + } + } + + region16_uninit(&windowInvalidRegion); } -void xf_process_rail_exec_result_event(xfContext* xfc, rdpChannels* channels, wMessage* event) +/* RemoteApp Virtual Channel Extension */ + +static int xf_rail_server_execute_result(RailClientContext* context, RAIL_EXEC_RESULT_ORDER* execResult) { - RAIL_EXEC_RESULT_ORDER* exec_result; - exec_result = (RAIL_EXEC_RESULT_ORDER*) event->wParam; + xfContext* xfc = (xfContext*) context->custom; - if (exec_result->execResult != RAIL_EXEC_S_OK) + if (execResult->execResult != RAIL_EXEC_S_OK) { WLog_ERR(TAG, "RAIL exec error: execResult=%s NtError=0x%X\n", - error_code_names[exec_result->execResult], exec_result->rawResult); - xfc->disconnect = True; + error_code_names[execResult->execResult], execResult->rawResult); + xfc->disconnect = TRUE; } else { xf_rail_enable_remoteapp_mode(xfc); } + + return 1; } -void xf_process_rail_server_sysparam_event(xfContext* xfc, rdpChannels* channels, wMessage* event) +static int xf_rail_server_system_param(RailClientContext* context, RAIL_SYSPARAM_ORDER* sysparam) { - RAIL_SYSPARAM_ORDER* sysparam = (RAIL_SYSPARAM_ORDER*) event->wParam; - - switch (sysparam->param) - { - case SPI_SET_SCREEN_SAVE_ACTIVE: - break; - - case SPI_SET_SCREEN_SAVE_SECURE: - break; - } + return 1; } -void xf_process_rail_server_minmaxinfo_event(xfContext* xfc, rdpChannels* channels, wMessage* event) +static int xf_rail_server_handshake(RailClientContext* context, RAIL_HANDSHAKE_ORDER* handshake) { - rdpRail* rail; - rdpWindow* rail_window = NULL; - RAIL_MINMAXINFO_ORDER* minmax = (RAIL_MINMAXINFO_ORDER*) event->wParam; - rail = ((rdpContext*) xfc)->rail; - rail_window = window_list_get_by_id(rail->list, minmax->windowId); + RAIL_EXEC_ORDER exec; + RAIL_SYSPARAM_ORDER sysparam; + RAIL_HANDSHAKE_ORDER clientHandshake; + RAIL_CLIENT_STATUS_ORDER clientStatus; + xfContext* xfc = (xfContext*) context->custom; + rdpSettings* settings = xfc->settings; + + clientHandshake.buildNumber = 0x00001DB0; + context->ClientHandshake(context, &clientHandshake); + + ZeroMemory(&clientStatus, sizeof(RAIL_CLIENT_STATUS_ORDER)); + clientStatus.flags = RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE; + context->ClientInformation(context, &clientStatus); - if (rail_window) + if (settings->RemoteAppLanguageBarSupported) { - xfWindow* window = NULL; - window = (xfWindow*) rail_window->extra; - - DEBUG_X11_LMS("windowId=0x%X maxWidth=%d maxHeight=%d maxPosX=%d maxPosY=%d " - "minTrackWidth=%d minTrackHeight=%d maxTrackWidth=%d maxTrackHeight=%d", - minmax->windowId, minmax->maxWidth, minmax->maxHeight, - (INT16)minmax->maxPosX, (INT16)minmax->maxPosY, - minmax->minTrackWidth, minmax->minTrackHeight, - minmax->maxTrackWidth, minmax->maxTrackHeight); - - xf_SetWindowMinMaxInfo(xfc, window, minmax->maxWidth, minmax->maxHeight, minmax->maxPosX, minmax->maxPosY, - minmax->minTrackWidth, minmax->minTrackHeight, minmax->maxTrackWidth, minmax->maxTrackHeight); + RAIL_LANGBAR_INFO_ORDER langBarInfo; + langBarInfo.languageBarStatus = 0x00000008; /* TF_SFT_HIDDEN */ + context->ClientLanguageBarInfo(context, &langBarInfo); } -} -void xf_process_rail_server_localmovesize_event(xfContext* xfc, rdpChannels* channels, wMessage* event) -{ - int x = 0, y = 0; - rdpRail* rail; - int direction = 0; - Window child_window; - rdpWindow* rail_window = NULL; - RAIL_LOCALMOVESIZE_ORDER* movesize = (RAIL_LOCALMOVESIZE_ORDER*) event->wParam; - rail = ((rdpContext*) xfc)->rail; - rail_window = window_list_get_by_id(rail->list, movesize->windowId); + ZeroMemory(&sysparam, sizeof(RAIL_SYSPARAM_ORDER)); - if (rail_window) - { - xfWindow* xfw = NULL; - xfw = (xfWindow*) rail_window->extra; + sysparam.params = 0; - DEBUG_X11_LMS("windowId=0x%X isMoveSizeStart=%d moveSizeType=%s PosX=%d PosY=%d", - movesize->windowId, movesize->isMoveSizeStart, - movetype_names[movesize->moveSizeType], (INT16) movesize->posX, (INT16) movesize->posY); + sysparam.params |= SPI_MASK_SET_HIGH_CONTRAST; + sysparam.highContrast.colorScheme.string = NULL; + sysparam.highContrast.colorScheme.length = 0; + sysparam.highContrast.flags = 0x7E; - switch (movesize->moveSizeType) - { - case RAIL_WMSZ_LEFT: - direction = _NET_WM_MOVERESIZE_SIZE_LEFT; - x = movesize->posX; - y = movesize->posY; - break; - - case RAIL_WMSZ_RIGHT: - direction = _NET_WM_MOVERESIZE_SIZE_RIGHT; - x = movesize->posX; - y = movesize->posY; - break; - - case RAIL_WMSZ_TOP: - direction = _NET_WM_MOVERESIZE_SIZE_TOP; - x = movesize->posX; - y = movesize->posY; - break; - - case RAIL_WMSZ_TOPLEFT: - direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT; - x = movesize->posX; - y = movesize->posY; - break; - - case RAIL_WMSZ_TOPRIGHT: - direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT; - x = movesize->posX; - y = movesize->posY; - break; - - case RAIL_WMSZ_BOTTOM: - direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM; - x = movesize->posX; - y = movesize->posY; - break; - - case RAIL_WMSZ_BOTTOMLEFT: - direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT; - x = movesize->posX; - y = movesize->posY; - break; - - case RAIL_WMSZ_BOTTOMRIGHT: - direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT; - x = movesize->posX; - y = movesize->posY; - break; - - case RAIL_WMSZ_MOVE: - direction = _NET_WM_MOVERESIZE_MOVE; - XTranslateCoordinates(xfc->display, xfw->handle, - RootWindowOfScreen(xfc->screen), - movesize->posX, movesize->posY, &x, &y, &child_window); - break; - - case RAIL_WMSZ_KEYMOVE: - direction = _NET_WM_MOVERESIZE_MOVE_KEYBOARD; - x = movesize->posX; - y = movesize->posY; - /* FIXME: local keyboard moves not working */ - return; - - case RAIL_WMSZ_KEYSIZE: - direction = _NET_WM_MOVERESIZE_SIZE_KEYBOARD; - x = movesize->posX; - y = movesize->posY; - /* FIXME: local keyboard moves not working */ - return; - } + sysparam.params |= SPI_MASK_SET_MOUSE_BUTTON_SWAP; + sysparam.mouseButtonSwap = FALSE; - if (movesize->isMoveSizeStart) - { - xf_StartLocalMoveSize(xfc, xfw, direction, x, y); - } - else - { - xf_EndLocalMoveSize(xfc, xfw); - } - } -} + sysparam.params |= SPI_MASK_SET_KEYBOARD_PREF; + sysparam.keyboardPref = FALSE; -void xf_process_rail_appid_resp_event(xfContext* xfc, rdpChannels* channels, wMessage* event) -{ - RAIL_GET_APPID_RESP_ORDER* appid_resp = - (RAIL_GET_APPID_RESP_ORDER*) event->wParam; + sysparam.params |= SPI_MASK_SET_DRAG_FULL_WINDOWS; + sysparam.dragFullWindows = FALSE; + + sysparam.params |= SPI_MASK_SET_KEYBOARD_CUES; + sysparam.keyboardCues = FALSE; + + sysparam.params |= SPI_MASK_SET_WORK_AREA; + sysparam.workArea.left = 0; + sysparam.workArea.top = 0; + sysparam.workArea.right = settings->DesktopWidth; + sysparam.workArea.bottom = settings->DesktopHeight; + + sysparam.dragFullWindows = FALSE; + + context->ClientSystemParam(context, &sysparam); + + ZeroMemory(&exec, sizeof(RAIL_EXEC_ORDER)); - WLog_ERR(TAG, "Server Application ID Response PDU: windowId=0x%X " - "applicationId=(length=%d dump)\n", - appid_resp->windowId, 512); + exec.RemoteApplicationProgram = settings->RemoteApplicationProgram; + exec.RemoteApplicationWorkingDir = settings->ShellWorkingDirectory; + exec.RemoteApplicationArguments = settings->RemoteApplicationCmdLine; - winpr_HexDump(TAG, WLOG_ERROR, (BYTE*) &appid_resp->applicationId, 512); + context->ClientExecute(context, &exec); + + return 1; } -void xf_process_rail_langbarinfo_event(xfContext* xfc, rdpChannels* channels, wMessage* event) +static int xf_rail_server_handshake_ex(RailClientContext* context, RAIL_HANDSHAKE_EX_ORDER* handshakeEx) { - RAIL_LANGBAR_INFO_ORDER* langbar = (RAIL_LANGBAR_INFO_ORDER*) event->wParam; - - WLog_ERR(TAG, "Language Bar Information PDU: languageBarStatus=0x%X\n", - langbar->languageBarStatus); + return 1; } -void xf_process_rail_event(xfContext* xfc, rdpChannels* channels, wMessage* event) +static int xf_rail_server_local_move_size(RailClientContext* context, RAIL_LOCALMOVESIZE_ORDER* localMoveSize) { - switch (GetMessageType(event->id)) + rdpRail* rail; + xfWindow* window; + int x = 0, y = 0; + int direction = 0; + Window child_window; + rdpWindow* rail_window; + xfContext* xfc = (xfContext*) context->custom; + + rail = ((rdpContext*) xfc)->rail; + + rail_window = window_list_get_by_id(rail->list, localMoveSize->windowId); + + if (!rail_window) + return -1; + + window = (xfWindow*) rail_window->extra; + + switch (localMoveSize->moveSizeType) { - case RailChannel_GetSystemParam: - xf_process_rail_get_sysparams_event(xfc, channels, event); + case RAIL_WMSZ_LEFT: + direction = _NET_WM_MOVERESIZE_SIZE_LEFT; + x = localMoveSize->posX; + y = localMoveSize->posY; + break; + + case RAIL_WMSZ_RIGHT: + direction = _NET_WM_MOVERESIZE_SIZE_RIGHT; + x = localMoveSize->posX; + y = localMoveSize->posY; break; - case RailChannel_ServerExecuteResult: - xf_process_rail_exec_result_event(xfc, channels, event); + case RAIL_WMSZ_TOP: + direction = _NET_WM_MOVERESIZE_SIZE_TOP; + x = localMoveSize->posX; + y = localMoveSize->posY; break; - case RailChannel_ServerSystemParam: - xf_process_rail_server_sysparam_event(xfc, channels, event); + case RAIL_WMSZ_TOPLEFT: + direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT; + x = localMoveSize->posX; + y = localMoveSize->posY; break; - case RailChannel_ServerMinMaxInfo: - xf_process_rail_server_minmaxinfo_event(xfc, channels, event); + case RAIL_WMSZ_TOPRIGHT: + direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT; + x = localMoveSize->posX; + y = localMoveSize->posY; break; - case RailChannel_ServerLocalMoveSize: - xf_process_rail_server_localmovesize_event(xfc, channels, event); + case RAIL_WMSZ_BOTTOM: + direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM; + x = localMoveSize->posX; + y = localMoveSize->posY; break; - case RailChannel_ServerGetAppIdResponse: - xf_process_rail_appid_resp_event(xfc, channels, event); + case RAIL_WMSZ_BOTTOMLEFT: + direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT; + x = localMoveSize->posX; + y = localMoveSize->posY; break; - case RailChannel_ServerLanguageBarInfo: - xf_process_rail_langbarinfo_event(xfc, channels, event); + case RAIL_WMSZ_BOTTOMRIGHT: + direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT; + x = localMoveSize->posX; + y = localMoveSize->posY; break; - default: + case RAIL_WMSZ_MOVE: + direction = _NET_WM_MOVERESIZE_MOVE; + XTranslateCoordinates(xfc->display, window->handle, + RootWindowOfScreen(xfc->screen), + localMoveSize->posX, localMoveSize->posY, &x, &y, &child_window); break; + + case RAIL_WMSZ_KEYMOVE: + direction = _NET_WM_MOVERESIZE_MOVE_KEYBOARD; + x = localMoveSize->posX; + y = localMoveSize->posY; + /* FIXME: local keyboard moves not working */ + return 1; + break; + + case RAIL_WMSZ_KEYSIZE: + direction = _NET_WM_MOVERESIZE_SIZE_KEYBOARD; + x = localMoveSize->posX; + y = localMoveSize->posY; + /* FIXME: local keyboard moves not working */ + return 1; + break; + } + + if (localMoveSize->isMoveSizeStart) + { + xf_StartLocalMoveSize(xfc, window, direction, x, y); } + else + { + xf_EndLocalMoveSize(xfc, window); + } + + return 1; +} + +static int xf_rail_server_min_max_info(RailClientContext* context, RAIL_MINMAXINFO_ORDER* minMaxInfo) +{ + rdpRail* rail; + xfWindow* window; + rdpWindow* rail_window; + xfContext* xfc = (xfContext*) context->custom; + + rail = ((rdpContext*) xfc)->rail; + + rail_window = window_list_get_by_id(rail->list, minMaxInfo->windowId); + + if (!rail_window) + return -1; + + window = (xfWindow*) rail_window->extra; + + xf_SetWindowMinMaxInfo(xfc, window, + minMaxInfo->maxWidth, minMaxInfo->maxHeight, + minMaxInfo->maxPosX, minMaxInfo->maxPosY, + minMaxInfo->minTrackWidth, minMaxInfo->minTrackHeight, + minMaxInfo->maxTrackWidth, minMaxInfo->maxTrackHeight); + + return 1; +} + +static int xf_rail_server_language_bar_info(RailClientContext* context, RAIL_LANGBAR_INFO_ORDER* langBarInfo) +{ + return 1; +} + +static int xf_rail_server_get_appid_response(RailClientContext* context, RAIL_GET_APPID_RESP_ORDER* getAppIdResp) +{ + return 1; } int xf_rail_init(xfContext* xfc, RailClientContext* rail) @@ -691,9 +720,18 @@ int xf_rail_init(xfContext* xfc, RailClientContext* rail) xf_rail_register_callbacks(xfc, context->rail); - if (0) + if (1) { rail->custom = (void*) xfc; + + rail->ServerExecuteResult = xf_rail_server_execute_result; + rail->ServerSystemParam = xf_rail_server_system_param; + rail->ServerHandshake = xf_rail_server_handshake; + rail->ServerHandshakeEx = xf_rail_server_handshake_ex; + rail->ServerLocalMoveSize = xf_rail_server_local_move_size; + rail->ServerMinMaxInfo = xf_rail_server_min_max_info; + rail->ServerLanguageBarInfo = xf_rail_server_language_bar_info; + rail->ServerGetAppIdResponse = xf_rail_server_get_appid_response; } return 1; diff --git a/client/X11/xf_rail.h b/client/X11/xf_rail.h index b2371a8..04d3b40 100644 --- a/client/X11/xf_rail.h +++ b/client/X11/xf_rail.h @@ -23,6 +23,23 @@ #include "xf_client.h" #include "xfreerdp.h" +struct xf_rail_window +{ + xfContext* wfc; + + HWND hWnd; + + DWORD dwStyle; + DWORD dwExStyle; + + int x; + int y; + int width; + int height; + char* title; +}; +typedef struct xf_rail_window xfRailWindow; + #include void xf_rail_paint(xfContext* xfc, rdpRail* rail, INT32 uleft, INT32 utop, UINT32 uright, UINT32 ubottom); @@ -33,8 +50,6 @@ void xf_rail_end_local_move(xfContext* xfc, rdpWindow* window); void xf_rail_enable_remoteapp_mode(xfContext* xfc); void xf_rail_disable_remoteapp_mode(xfContext* xfc); -void xf_process_rail_event(xfContext* xfc, rdpChannels* channels, wMessage* event); - int xf_rail_init(xfContext* xfc, RailClientContext* rail); int xf_rail_uninit(xfContext* xfc, RailClientContext* rail); diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index db4a2d6..6df2bb1 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -190,7 +190,9 @@ struct xf_context RdpeiClientContext* rdpei; RdpgfxClientContext* gfx; EncomspClientContext* encomsp; + RailClientContext* rail; + wHashTable* railWindows; BOOL xkbAvailable; }; -- 2.7.4