BOOL xf_GetWorkArea(xfContext* xfc) { long* plong; BOOL status; unsigned long nitems; unsigned long bytes; unsigned char* prop; status = xf_GetCurrentDesktop(xfc); if (!status) return FALSE; status = xf_GetWindowProperty(xfc, DefaultRootWindow(xfc->display), xfc->_NET_WORKAREA, 32 * 4, &nitems, &bytes, &prop); if (!status) return FALSE; if ((xfc->current_desktop * 4 + 3) >= (INT64)nitems) { free(prop); return FALSE; } plong = (long*) prop; xfc->workArea.x = plong[xfc->current_desktop * 4 + 0]; xfc->workArea.y = plong[xfc->current_desktop * 4 + 1]; xfc->workArea.width = plong[xfc->current_desktop * 4 + 2]; xfc->workArea.height = plong[xfc->current_desktop * 4 + 3]; free(prop); return TRUE; }
boolean xf_GetWorkArea(xfInfo* xfi) { long* plong; boolean status; unsigned long nitems; unsigned long bytes; unsigned char* prop; status = xf_GetWindowProperty(xfi, DefaultRootWindow(xfi->display), xfi->_NET_WORKAREA, 32 * 4, &nitems, &bytes, &prop); if (status != True) return False; status = xf_GetCurrentDesktop(xfi); if (status != True) return False; plong = (long*) prop; xfi->workArea.x = plong[xfi->current_desktop * 4 + 0]; xfi->workArea.y = plong[xfi->current_desktop * 4 + 1]; xfi->workArea.width = plong[xfi->current_desktop * 4 + 2]; xfi->workArea.height = plong[xfi->current_desktop * 4 + 3]; xfree(prop); return True; }
BOOL xf_GetCurrentDesktop(xfContext* xfc) { BOOL status; unsigned long nitems; unsigned long bytes; unsigned char* prop; status = xf_GetWindowProperty(xfc, DefaultRootWindow(xfc->display), xfc->_NET_CURRENT_DESKTOP, 1, &nitems, &bytes, &prop); if (!status) return FALSE; xfc->current_desktop = (int) * prop; free(prop); return TRUE; }
boolean xf_GetCurrentDesktop(xfInfo* xfi) { boolean status; unsigned long nitems; unsigned long bytes; unsigned char* prop; status = xf_GetWindowProperty(xfi, DefaultRootWindow(xfi->display), xfi->_NET_CURRENT_DESKTOP, 1, &nitems, &bytes, &prop); if (status != True) return False; xfi->current_desktop = (int) *prop; xfree(prop); return True; }
static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app) { /* * This section handles sending the appropriate commands to the rail server * when the window has been minimized, maximized, restored locally * ie. not using the buttons on the rail window itself */ if (app) { xfAppWindow* appWindow; appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); if (!appWindow) return TRUE; if ((((Atom) event->xproperty.atom == xfc->_NET_WM_STATE) && (event->xproperty.state != PropertyDelete)) || (((Atom) event->xproperty.atom == xfc->WM_STATE) && (event->xproperty.state != PropertyDelete))) { int i; BOOL status; BOOL maxVert = FALSE; BOOL maxHorz = FALSE; BOOL minimized = FALSE; unsigned long nitems; unsigned long bytes; unsigned char* prop; if ((Atom) event->xproperty.atom == xfc->_NET_WM_STATE) { status = xf_GetWindowProperty(xfc, event->xproperty.window, xfc->_NET_WM_STATE, 12, &nitems, &bytes, &prop); if (status) { for (i = 0; i < nitems; i++) { if ((Atom)((UINT16**) prop)[i] == XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False)) { maxVert = TRUE; } if ((Atom)((UINT16**) prop)[i] == XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False)) { maxHorz = TRUE; } } XFree(prop); } } if ((Atom) event->xproperty.atom == xfc->WM_STATE) { status = xf_GetWindowProperty(xfc, event->xproperty.window, xfc->WM_STATE, 1, &nitems, &bytes, &prop); if (status) { /* If the window is in the iconic state */ if (((UINT32) *prop == 3)) minimized = TRUE; else minimized = FALSE; XFree(prop); } } if (maxVert && maxHorz && !minimized && (appWindow->rail_state != WINDOW_SHOW_MAXIMIZED)) { appWindow->rail_state = WINDOW_SHOW_MAXIMIZED; xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_MAXIMIZE); } else if (minimized && (appWindow->rail_state != WINDOW_SHOW_MINIMIZED)) { appWindow->rail_state = WINDOW_SHOW_MINIMIZED; xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_MINIMIZE); } else if (!minimized && !maxVert && !maxHorz && (appWindow->rail_state != WINDOW_SHOW)) { appWindow->rail_state = WINDOW_SHOW; xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_RESTORE); } } } return TRUE; }
static BOOL xf_event_PropertyNotify(xfInfo* xfi, XEvent* event, BOOL app) { /* * This section handles sending the appropriate commands to the rail server * when the window has been minimized, maximized, restored locally * ie. not using the buttons on the rail window itself */ if (app) { rdpWindow* window; window = xf_rdpWindowFromWindow(xfi, event->xproperty.window); if (window == NULL) return TRUE; if ((((Atom) event->xproperty.atom == xfi->_NET_WM_STATE) && (event->xproperty.state != PropertyDelete)) || (((Atom) event->xproperty.atom == xfi->WM_STATE) && (event->xproperty.state != PropertyDelete))) { int i; BOOL status; BOOL maxVert = FALSE; BOOL maxHorz = FALSE; BOOL minimized = FALSE; unsigned long nitems; unsigned long bytes; unsigned char* prop; if ((Atom) event->xproperty.atom == xfi->_NET_WM_STATE) { status = xf_GetWindowProperty(xfi, event->xproperty.window, xfi->_NET_WM_STATE, 12, &nitems, &bytes, &prop); if (!status) { DEBUG_X11_LMS("No return _NET_WM_STATE, window is not maximized"); } for (i = 0; i < nitems; i++) { if ((Atom) ((UINT16**) prop)[i] == XInternAtom(xfi->display, "_NET_WM_STATE_MAXIMIZED_VERT", False)) { maxVert = TRUE; } if ((Atom) ((UINT16**) prop)[i] == XInternAtom(xfi->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False)) { maxHorz = TRUE; } } XFree(prop); } if ((Atom) event->xproperty.atom == xfi->WM_STATE) { status = xf_GetWindowProperty(xfi, event->xproperty.window, xfi->WM_STATE, 1, &nitems, &bytes, &prop); if (!status) { DEBUG_X11_LMS("No return WM_STATE, window is not minimized"); } else { /* If the window is in the iconic state */ if (((UINT32) *prop == 3)) minimized = TRUE; else minimized = FALSE; XFree(prop); } } if (maxVert && maxHorz && !minimized && (xfi->window->rail_state != WINDOW_SHOW_MAXIMIZED)) { DEBUG_X11_LMS("Send SC_MAXIMIZE command to rail server."); xfi->window->rail_state = WINDOW_SHOW_MAXIMIZED; xf_rail_send_client_system_command(xfi, window->windowId, SC_MAXIMIZE); } else if (minimized && (xfi->window->rail_state != WINDOW_SHOW_MINIMIZED)) { DEBUG_X11_LMS("Send SC_MINIMIZE command to rail server."); xfi->window->rail_state = WINDOW_SHOW_MINIMIZED; xf_rail_send_client_system_command(xfi, window->windowId, SC_MINIMIZE); } else if (!minimized && !maxVert && !maxHorz && (xfi->window->rail_state != WINDOW_SHOW)) { DEBUG_X11_LMS("Send SC_RESTORE command to rail server"); xfi->window->rail_state = WINDOW_SHOW; xf_rail_send_client_system_command(xfi, window->windowId, SC_RESTORE); } } } else { if (xf_cliprdr_process_property_notify(xfi, event)) return TRUE; } return TRUE; }
void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen) { UINT32 i; rdpSettings* settings = xfc->context.settings; int startX, startY; UINT32 width = window->width; UINT32 height = window->height; /* xfc->decorations is set by caller depending on settings and whether it is fullscreen or not */ window->decorations = xfc->decorations; /* show/hide decorations (e.g. title bar) as guided by xfc->decorations */ xf_SetWindowDecorations(xfc, window->handle, window->decorations); DEBUG_X11(TAG, "X window decoration set to %d", (int)window->decorations); xf_floatbar_toggle_fullscreen(xfc->window->floatbar, fullscreen); if (fullscreen) { xfc->savedWidth = xfc->window->width; xfc->savedHeight = xfc->window->height; xfc->savedPosX = xfc->window->left; xfc->savedPosY = xfc->window->top; startX = (settings->DesktopPosX != UINT32_MAX) ? settings->DesktopPosX : 0; startY = (settings->DesktopPosY != UINT32_MAX) ? settings->DesktopPosY : 0; } else { width = xfc->savedWidth; height = xfc->savedHeight; startX = xfc->savedPosX; startY = xfc->savedPosY; } /* Determine the x,y starting location for the fullscreen window */ if (fullscreen) { /* Initialize startX and startY with reasonable values */ startX = xfc->context.settings->MonitorDefArray[0].x; startY = xfc->context.settings->MonitorDefArray[0].y; /* Search all monitors to find the lowest startX and startY values */ for (i = 0; i < xfc->context.settings->MonitorCount; i++) { startX = MIN(startX, xfc->context.settings->MonitorDefArray[i].x); startY = MIN(startY, xfc->context.settings->MonitorDefArray[i].y); } /* Lastly apply any monitor shift(translation from remote to local coordinate system) * to startX and startY values */ startX += xfc->context.settings->MonitorLocalShiftX; startY += xfc->context.settings->MonitorLocalShiftY; } /* It is safe to proceed with simply toogling _NET_WM_STATE_FULLSCREEN window state on the following conditions: - The window manager supports multiple monitor full screen - The user requested to use a single monitor to render the remote desktop */ if (xfc->_NET_WM_FULLSCREEN_MONITORS != None || settings->MonitorCount == 1) { xf_ResizeDesktopWindow(xfc, window, width, height); if (fullscreen) { /* enter full screen: move the window before adding NET_WM_STATE_FULLSCREEN */ XMoveWindow(xfc->display, window->handle, startX, startY); } /* Set the fullscreen state */ xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, fullscreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE, xfc->_NET_WM_STATE_FULLSCREEN, 0, 0); if (!fullscreen) { /* leave full screen: move the window after removing NET_WM_STATE_FULLSCREEN */ XMoveWindow(xfc->display, window->handle, startX, startY); } /* Set monitor bounds */ if (settings->MonitorCount > 1) { xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_FULLSCREEN_MONITORS, 5, xfc->fullscreenMonitors.top, xfc->fullscreenMonitors.bottom, xfc->fullscreenMonitors.left, xfc->fullscreenMonitors.right, 1); } } else { if (fullscreen) { xf_SetWindowDecorations(xfc, window->handle, FALSE); if (xfc->fullscreenMonitors.top) { xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, _NET_WM_STATE_ADD, xfc->fullscreenMonitors.top, 0, 0); } else { XSetWindowAttributes xswa; xswa.override_redirect = True; XChangeWindowAttributes(xfc->display, window->handle, CWOverrideRedirect, &xswa); XRaiseWindow(xfc->display, window->handle); xswa.override_redirect = False; XChangeWindowAttributes(xfc->display, window->handle, CWOverrideRedirect, &xswa); } /* if window is in maximized state, save and remove */ if (xfc->_NET_WM_STATE_MAXIMIZED_VERT != None) { BYTE state; unsigned long nitems; unsigned long bytes; BYTE* prop; if (xf_GetWindowProperty(xfc, window->handle, xfc->_NET_WM_STATE, 255, &nitems, &bytes, &prop)) { state = 0; while (nitems-- > 0) { if (((Atom*) prop)[nitems] == xfc->_NET_WM_STATE_MAXIMIZED_VERT) state |= 0x01; if (((Atom*) prop)[nitems] == xfc->_NET_WM_STATE_MAXIMIZED_HORZ) state |= 0x02; } if (state) { xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, _NET_WM_STATE_REMOVE, xfc->_NET_WM_STATE_MAXIMIZED_VERT, 0, 0); xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, _NET_WM_STATE_REMOVE, xfc->_NET_WM_STATE_MAXIMIZED_HORZ, 0, 0); xfc->savedMaximizedState = state; } XFree(prop); } } width = xfc->vscreen.area.right - xfc->vscreen.area.left + 1; height = xfc->vscreen.area.bottom - xfc->vscreen.area.top + 1; DEBUG_X11("X window move and resize %dx%d@%dx%d", startX, startY, width, height); xf_ResizeDesktopWindow(xfc, window, width, height); XMoveWindow(xfc->display, window->handle, startX, startY); } else { xf_SetWindowDecorations(xfc, window->handle, window->decorations); xf_ResizeDesktopWindow(xfc, window, width, height); XMoveWindow(xfc->display, window->handle, startX, startY); if (xfc->fullscreenMonitors.top) { xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, _NET_WM_STATE_REMOVE, xfc->fullscreenMonitors.top, 0, 0); } /* restore maximized state, if the window was maximized before setting fullscreen */ if (xfc->savedMaximizedState & 0x01) { xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, _NET_WM_STATE_ADD, xfc->_NET_WM_STATE_MAXIMIZED_VERT, 0, 0); } if (xfc->savedMaximizedState & 0x02) { xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, _NET_WM_STATE_ADD, xfc->_NET_WM_STATE_MAXIMIZED_HORZ, 0, 0); } xfc->savedMaximizedState = 0; } } }