static void xf_rail_MoveWindow(rdpRail* rail, rdpWindow* window) { xfContext* xfc; xfWindow* xfw; xfc = (xfContext*) rail->extra; xfw = (xfWindow*) 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) 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) { /* * 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); return; } xf_MoveWindow(xfc, xfw, window->visibleOffsetX, window->visibleOffsetY, window->windowWidth, window->windowHeight); }
void xf_rail_MoveWindow(rdpRail* rail, rdpWindow* window) { xfInfo* xfi; xfWindow* xfw; xfi = (xfInfo*) rail->extra; xfw = (xfWindow*) window->extra; xf_MoveWindow((xfInfo*) rail->extra, xfw, window->windowOffsetX, window->windowOffsetY, window->windowWidth, window->windowHeight); }
void xf_rail_MoveWindow(rdpRail* rail, rdpWindow* window) { xfInfo* xfi; xfWindow* xfw; xfi = (xfInfo*) rail->extra; xfw = (xfWindow*) window->extra; // Do nothing if window is already in the correct position if (xfw->left == window->windowOffsetX && xfw->top == window->windowOffsetY && xfw->width == window->windowWidth && xfw->height == window->windowHeight) { return; } xf_MoveWindow((xfInfo*) rail->extra, xfw, window->windowOffsetX, window->windowOffsetY, window->windowWidth, window->windowHeight); }
static BOOL xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* windowState) { xfAppWindow* appWindow = NULL; xfContext* xfc = (xfContext*) context; UINT32 fieldFlags = orderInfo->fieldFlags; if (fieldFlags & WINDOW_ORDER_STATE_NEW) { appWindow = (xfAppWindow*) calloc(1, sizeof(xfAppWindow)); if (!appWindow) return FALSE; appWindow->xfc = xfc; appWindow->windowId = orderInfo->windowId; appWindow->dwStyle = windowState->style; appWindow->dwExStyle = windowState->extendedStyle; appWindow->x = appWindow->windowOffsetX = windowState->windowOffsetX; appWindow->y = appWindow->windowOffsetY = windowState->windowOffsetY; appWindow->width = appWindow->windowWidth = windowState->windowWidth; appWindow->height = appWindow->windowHeight = windowState->windowHeight; appWindow->localWindowOffsetCorrX = 0; appWindow->localWindowOffsetCorrY = 0; if (fieldFlags & WINDOW_ORDER_FIELD_TITLE) { char* title = NULL; ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string, windowState->titleInfo.length / 2, &title, 0, NULL, NULL); appWindow->title = title; } else { appWindow->title = _strdup("RdpRailWindow"); } if (!appWindow->title) { free(appWindow); return FALSE; } HashTable_Add(xfc->railWindows, (void*) (UINT_PTR) orderInfo->windowId, (void*) appWindow); xf_AppWindowInit(xfc, appWindow); return TRUE; } else { appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows, (void*) (UINT_PTR) orderInfo->windowId); } if (!appWindow) return FALSE; /* Update Parameters */ if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) || (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)) { if (fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) { appWindow->windowOffsetX = windowState->windowOffsetX; appWindow->windowOffsetY = windowState->windowOffsetY; /* * The rail server can give negative window coordinates when updating windowOffsetX and windowOffsetY, * but we can only send unsigned integers to the rail server. Therefore, we maintain a local offset. */ if (appWindow->windowOffsetX < 0) appWindow->localWindowOffsetCorrX = 0 - appWindow->windowOffsetX; else appWindow->localWindowOffsetCorrX = 0; if (appWindow->windowOffsetY < 0) appWindow->localWindowOffsetCorrY = 0 - appWindow->windowOffsetY; else appWindow->localWindowOffsetCorrY = 0; } if (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) { appWindow->windowWidth = windowState->windowWidth; appWindow->windowHeight = windowState->windowHeight; } } if (fieldFlags & WINDOW_ORDER_FIELD_OWNER) { appWindow->ownerWindowId = windowState->ownerWindowId; } if (fieldFlags & WINDOW_ORDER_FIELD_STYLE) { appWindow->dwStyle = windowState->style; appWindow->dwExStyle = windowState->extendedStyle; } if (fieldFlags & WINDOW_ORDER_FIELD_SHOW) { appWindow->showState = windowState->showState; } if (fieldFlags & WINDOW_ORDER_FIELD_TITLE) { char* title = NULL; ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string, windowState->titleInfo.length / 2, &title, 0, NULL, NULL); free(appWindow->title); appWindow->title = title; } if (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) { appWindow->clientOffsetX = windowState->clientOffsetX; appWindow->clientOffsetY = windowState->clientOffsetY; } if (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) { appWindow->clientAreaWidth = windowState->clientAreaWidth; appWindow->clientAreaHeight = windowState->clientAreaHeight; } if (fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) { appWindow->windowClientDeltaX = windowState->windowClientDeltaX; appWindow->windowClientDeltaY = windowState->windowClientDeltaY; } if (fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) { if (appWindow->windowRects) { free(appWindow->windowRects); appWindow->windowRects = NULL; } appWindow->numWindowRects = windowState->numWindowRects; if (appWindow->numWindowRects) { appWindow->windowRects = (RECTANGLE_16*) calloc(appWindow->numWindowRects, sizeof(RECTANGLE_16)); if (!appWindow->windowRects) return FALSE; CopyMemory(appWindow->windowRects, windowState->windowRects, appWindow->numWindowRects * sizeof(RECTANGLE_16)); } } if (fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) { appWindow->visibleOffsetX = windowState->visibleOffsetX; appWindow->visibleOffsetY = windowState->visibleOffsetY; } if (fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) { if (appWindow->visibilityRects) { free(appWindow->visibilityRects); appWindow->visibilityRects = NULL; } appWindow->numVisibilityRects = windowState->numVisibilityRects; if (appWindow->numVisibilityRects) { appWindow->visibilityRects = (RECTANGLE_16*) calloc(appWindow->numVisibilityRects, sizeof(RECTANGLE_16)); if (!appWindow->visibilityRects) return FALSE; CopyMemory(appWindow->visibilityRects, windowState->visibilityRects, appWindow->numVisibilityRects * sizeof(RECTANGLE_16)); } } /* Update Window */ if (fieldFlags & WINDOW_ORDER_FIELD_STYLE) { } if (fieldFlags & WINDOW_ORDER_FIELD_SHOW) { xf_ShowWindow(xfc, appWindow, appWindow->showState); } if (fieldFlags & WINDOW_ORDER_FIELD_TITLE) { if (appWindow->title) xf_SetWindowText(xfc, appWindow, appWindow->title); } if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) || (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)) { /* * 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 (appWindow->rail_state == WINDOW_SHOW_MINIMIZED) return TRUE; /* Do nothing if window is already in the correct position */ if (appWindow->x == (appWindow->windowOffsetX - appWindow->localWindowOffsetCorrX) && appWindow->y == (appWindow->windowOffsetY - appWindow->localWindowOffsetCorrY) && appWindow->width == appWindow->windowWidth && appWindow->height == appWindow->windowHeight) { xf_UpdateWindowArea(xfc, appWindow, 0, 0, appWindow->windowWidth, appWindow->windowHeight); return TRUE; } xf_MoveWindow(xfc, appWindow, appWindow->windowOffsetX - appWindow->localWindowOffsetCorrX, appWindow->windowOffsetY - appWindow->localWindowOffsetCorrY, appWindow->windowWidth, appWindow->windowHeight); } if (fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) { xf_SetWindowRects(xfc, appWindow, appWindow->windowRects, appWindow->numWindowRects); } if (fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) { xf_SetWindowVisibilityRects(xfc, appWindow, appWindow->visibilityRects, appWindow->numVisibilityRects); } return TRUE; }
static BOOL xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* windowState) { xfAppWindow* appWindow = NULL; xfContext* xfc = (xfContext*) context; UINT32 fieldFlags = orderInfo->fieldFlags; BOOL position_or_size_updated = FALSE; if (fieldFlags & WINDOW_ORDER_STATE_NEW) { appWindow = (xfAppWindow*) calloc(1, sizeof(xfAppWindow)); if (!appWindow) return FALSE; appWindow->xfc = xfc; appWindow->windowId = orderInfo->windowId; appWindow->dwStyle = windowState->style; appWindow->dwExStyle = windowState->extendedStyle; appWindow->x = appWindow->windowOffsetX = windowState->windowOffsetX; appWindow->y = appWindow->windowOffsetY = windowState->windowOffsetY; appWindow->width = appWindow->windowWidth = windowState->windowWidth; appWindow->height = appWindow->windowHeight = windowState->windowHeight; /* Ensure window always gets a window title */ if (fieldFlags & WINDOW_ORDER_FIELD_TITLE) { char* title = NULL; if (windowState->titleInfo.length == 0) { if (!(title = _strdup(""))) { WLog_ERR(TAG, "failed to duplicate empty window title string"); /* error handled below */ } } else if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string, windowState->titleInfo.length / 2, &title, 0, NULL, NULL) < 1) { WLog_ERR(TAG, "failed to convert window title"); /* error handled below */ } appWindow->title = title; } else { if (!(appWindow->title = _strdup("RdpRailWindow"))) WLog_ERR(TAG, "failed to duplicate default window title string"); } if (!appWindow->title) { free(appWindow); return FALSE; } HashTable_Add(xfc->railWindows, (void*)(UINT_PTR) orderInfo->windowId, (void*) appWindow); xf_AppWindowInit(xfc, appWindow); } else { appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows, (void*)(UINT_PTR) orderInfo->windowId); } if (!appWindow) return FALSE; /* Keep track of any position/size update so that we can force a refresh of the window */ if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) || (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) || (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) || (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) || (fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) || (fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) || (fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)) { position_or_size_updated = TRUE; } /* Update Parameters */ if (fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) { appWindow->windowOffsetX = windowState->windowOffsetX; appWindow->windowOffsetY = windowState->windowOffsetY; } if (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) { appWindow->windowWidth = windowState->windowWidth; appWindow->windowHeight = windowState->windowHeight; } if (fieldFlags & WINDOW_ORDER_FIELD_OWNER) { appWindow->ownerWindowId = windowState->ownerWindowId; } if (fieldFlags & WINDOW_ORDER_FIELD_STYLE) { appWindow->dwStyle = windowState->style; appWindow->dwExStyle = windowState->extendedStyle; } if (fieldFlags & WINDOW_ORDER_FIELD_SHOW) { appWindow->showState = windowState->showState; } if (fieldFlags & WINDOW_ORDER_FIELD_TITLE) { char* title = NULL; if (windowState->titleInfo.length == 0) { if (!(title = _strdup(""))) { WLog_ERR(TAG, "failed to duplicate empty window title string"); return FALSE; } } else if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string, windowState->titleInfo.length / 2, &title, 0, NULL, NULL) < 1) { WLog_ERR(TAG, "failed to convert window title"); return FALSE; } free(appWindow->title); appWindow->title = title; } if (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) { appWindow->clientOffsetX = windowState->clientOffsetX; appWindow->clientOffsetY = windowState->clientOffsetY; } if (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) { appWindow->clientAreaWidth = windowState->clientAreaWidth; appWindow->clientAreaHeight = windowState->clientAreaHeight; } if (fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) { appWindow->windowClientDeltaX = windowState->windowClientDeltaX; appWindow->windowClientDeltaY = windowState->windowClientDeltaY; } if (fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) { if (appWindow->windowRects) { free(appWindow->windowRects); appWindow->windowRects = NULL; } appWindow->numWindowRects = windowState->numWindowRects; if (appWindow->numWindowRects) { appWindow->windowRects = (RECTANGLE_16*) calloc(appWindow->numWindowRects, sizeof(RECTANGLE_16)); if (!appWindow->windowRects) return FALSE; CopyMemory(appWindow->windowRects, windowState->windowRects, appWindow->numWindowRects * sizeof(RECTANGLE_16)); } } if (fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) { appWindow->visibleOffsetX = windowState->visibleOffsetX; appWindow->visibleOffsetY = windowState->visibleOffsetY; } if (fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) { if (appWindow->visibilityRects) { free(appWindow->visibilityRects); appWindow->visibilityRects = NULL; } appWindow->numVisibilityRects = windowState->numVisibilityRects; if (appWindow->numVisibilityRects) { appWindow->visibilityRects = (RECTANGLE_16*) calloc( appWindow->numVisibilityRects, sizeof(RECTANGLE_16)); if (!appWindow->visibilityRects) return FALSE; CopyMemory(appWindow->visibilityRects, windowState->visibilityRects, appWindow->numVisibilityRects * sizeof(RECTANGLE_16)); } } /* Update Window */ if (fieldFlags & WINDOW_ORDER_FIELD_STYLE) { } if (fieldFlags & WINDOW_ORDER_FIELD_SHOW) { xf_ShowWindow(xfc, appWindow, appWindow->showState); } if (fieldFlags & WINDOW_ORDER_FIELD_TITLE) { if (appWindow->title) xf_SetWindowText(xfc, appWindow, appWindow->title); } if (position_or_size_updated) { UINT32 visibilityRectsOffsetX = (appWindow->visibleOffsetX - (appWindow->clientOffsetX - appWindow->windowClientDeltaX)); UINT32 visibilityRectsOffsetY = (appWindow->visibleOffsetY - (appWindow->clientOffsetY - appWindow->windowClientDeltaY)); /* * 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 (appWindow->rail_state != WINDOW_SHOW_MINIMIZED) { /* Redraw window area if already in the correct position */ if (appWindow->x == appWindow->windowOffsetX && appWindow->y == appWindow->windowOffsetY && appWindow->width == appWindow->windowWidth && appWindow->height == appWindow->windowHeight) { xf_UpdateWindowArea(xfc, appWindow, 0, 0, appWindow->windowWidth, appWindow->windowHeight); } else { xf_MoveWindow(xfc, appWindow, appWindow->windowOffsetX, appWindow->windowOffsetY, appWindow->windowWidth, appWindow->windowHeight); } xf_SetWindowVisibilityRects(xfc, appWindow, visibilityRectsOffsetX, visibilityRectsOffsetY, appWindow->visibilityRects, appWindow->numVisibilityRects); } } /* We should only be using the visibility rects for shaping the window */ /*if (fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) { xf_SetWindowRects(xfc, appWindow, appWindow->windowRects, appWindow->numWindowRects); }*/ return TRUE; }
int xf_AppWindowInit(xfContext* xfc, xfAppWindow* appWindow) { XGCValues gcv; int input_mask; XWMHints* InputModeHint; XClassHint* class_hints; xf_FixWindowCoordinates(xfc, &appWindow->x, &appWindow->y, &appWindow->width, &appWindow->height); appWindow->decorations = FALSE; appWindow->fullscreen = FALSE; 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), appWindow->x, appWindow->y, appWindow->width, appWindow->height, 0, xfc->depth, InputOutput, xfc->visual, 0, &xfc->attribs); if (!appWindow->handle) return -1; ZeroMemory(&gcv, sizeof(gcv)); appWindow->gc = XCreateGC(xfc->display, appWindow->handle, GCGraphicsExposures, &gcv); class_hints = XAllocClassHint(); if (class_hints) { char* class = NULL; if (xfc->context.settings->WmClass) { class_hints->res_class = xfc->context.settings->WmClass; } else { class = malloc(sizeof("RAIL:00000000")); sprintf_s(class, sizeof("RAIL:00000000"), "RAIL:%08"PRIX32"", appWindow->windowId); class_hints->res_class = class; } class_hints->res_name = "RAIL"; XSetClassHint(xfc->display, appWindow->handle, class_hints); XFree(class_hints); free(class); } /* Set the input mode hint for the WM */ InputModeHint = XAllocWMHints(); InputModeHint->flags = (1L << 0); InputModeHint->input = True; XSetWMHints(xfc->display, appWindow->handle, InputModeHint); XFree(InputModeHint); XSetWMProtocols(xfc->display, appWindow->handle, &(xfc->WM_DELETE_WINDOW), 1); input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | Button1MotionMask | Button2MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask | ButtonMotionMask | KeymapStateMask | ExposureMask | VisibilityChangeMask | StructureNotifyMask | SubstructureNotifyMask | SubstructureRedirectMask | FocusChangeMask | PropertyChangeMask | ColormapChangeMask | OwnerGrabButtonMask; XSelectInput(xfc->display, appWindow->handle, input_mask); xf_SetWindowDecorations(xfc, appWindow->handle, appWindow->decorations); xf_SetWindowStyle(xfc, appWindow, appWindow->dwStyle, appWindow->dwExStyle); xf_SetWindowPID(xfc, appWindow->handle, 0); xf_ShowWindow(xfc, appWindow, WINDOW_SHOW); XClearWindow(xfc->display, appWindow->handle); XMapWindow(xfc->display, appWindow->handle); /* Move doesn't seem to work until window is mapped. */ xf_MoveWindow(xfc, appWindow, appWindow->x, appWindow->y, appWindow->width, appWindow->height); xf_SetWindowText(xfc, appWindow, appWindow->title); return 1; }