#include <X11/Xlib.h>
#include <X11/Xutil.h>
+#include <X11/Xatom.h>
#ifdef WITH_XRENDER
#include <X11/extensions/Xrender.h>
return 0;
}
+static Atom get_supported_atom(xfContext* xfc, const char* atomName)
+{
+ unsigned long i;
+ const Atom atom = XInternAtom(xfc->display, atomName, False);
+
+ for (i = 0; i < xfc->supportedAtomCount; i++)
+ {
+ if (xfc->supportedAtoms[i] == atom)
+ return atom;
+ }
+
+ return None;
+}
static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
{
xfContext* xfc = (xfContext*) instance->context;
goto fail_create_mutex;
}
+ xfc->xfds = ConnectionNumber(xfc->display);
+ xfc->screen_number = DefaultScreen(xfc->display);
+ xfc->screen = ScreenOfDisplay(xfc->display, xfc->screen_number);
+ xfc->depth = DefaultDepthOfScreen(xfc->screen);
+ xfc->big_endian = (ImageByteOrder(xfc->display) == MSBFirst);
+ xfc->invert = TRUE;
+ xfc->complex_regions = TRUE;
+ xfc->_NET_SUPPORTED = XInternAtom(xfc->display, "_NET_SUPPORTED", True);
+ xfc->_NET_SUPPORTING_WM_CHECK = XInternAtom(xfc->display, "_NET_SUPPORTING_WM_CHECK", True);
+
+ if ((xfc->_NET_SUPPORTED != None) && (xfc->_NET_SUPPORTING_WM_CHECK != None))
+ {
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems, after;
+ unsigned char* data = NULL;
+ int status = XGetWindowProperty(xfc->display, RootWindowOfScreen(xfc->screen),
+ xfc->_NET_SUPPORTED, 0, 1024, False, XA_ATOM,
+ &actual_type, &actual_format, &nitems, &after, &data);
+
+ if ((status == Success) && (actual_type == XA_ATOM) && (actual_format == 32))
+ {
+ xfc->supportedAtomCount = nitems;
+ xfc->supportedAtoms = calloc(nitems, sizeof(Atom));
+ memcpy(xfc->supportedAtoms, data, nitems * sizeof(Atom));
+ }
+
+ if (data)
+ XFree(data);
+ }
xfc->_NET_WM_ICON = XInternAtom(xfc->display, "_NET_WM_ICON", False);
xfc->_MOTIF_WM_HINTS = XInternAtom(xfc->display, "_MOTIF_WM_HINTS", False);
xfc->_NET_CURRENT_DESKTOP = XInternAtom(xfc->display, "_NET_CURRENT_DESKTOP",
False);
xfc->_NET_WORKAREA = XInternAtom(xfc->display, "_NET_WORKAREA", False);
- xfc->_NET_WM_STATE = XInternAtom(xfc->display, "_NET_WM_STATE", False);
- xfc->_NET_WM_STATE_FULLSCREEN = XInternAtom(xfc->display,
- "_NET_WM_STATE_FULLSCREEN", False);
+ xfc->_NET_WM_STATE = get_supported_atom(xfc, "_NET_WM_STATE");
+ xfc->_NET_WM_STATE_FULLSCREEN = get_supported_atom(xfc, "_NET_WM_STATE_FULLSCREEN");
xfc->_NET_WM_STATE_MAXIMIZED_HORZ = XInternAtom(xfc->display,
"_NET_WM_STATE_MAXIMIZED_HORZ", False);
xfc->_NET_WM_STATE_MAXIMIZED_VERT = XInternAtom(xfc->display,
"_NET_WM_STATE_MAXIMIZED_VERT", False);
- xfc->_NET_WM_FULLSCREEN_MONITORS = XInternAtom(xfc->display,
- "_NET_WM_FULLSCREEN_MONITORS", False);
+ xfc->_NET_WM_FULLSCREEN_MONITORS = get_supported_atom(xfc, "_NET_WM_FULLSCREEN_MONITORS");
xfc->_NET_WM_NAME = XInternAtom(xfc->display, "_NET_WM_NAME", False);
xfc->_NET_WM_PID = XInternAtom(xfc->display, "_NET_WM_PID", False);
xfc->_NET_WM_WINDOW_TYPE = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE",
xfc->WM_PROTOCOLS = XInternAtom(xfc->display, "WM_PROTOCOLS", False);
xfc->WM_DELETE_WINDOW = XInternAtom(xfc->display, "WM_DELETE_WINDOW", False);
xfc->WM_STATE = XInternAtom(xfc->display, "WM_STATE", False);
- xfc->xfds = ConnectionNumber(xfc->display);
- xfc->screen_number = DefaultScreen(xfc->display);
- xfc->screen = ScreenOfDisplay(xfc->display, xfc->screen_number);
- xfc->depth = DefaultDepthOfScreen(xfc->screen);
- xfc->big_endian = (ImageByteOrder(xfc->display) == MSBFirst);
- xfc->invert = TRUE;
- xfc->complex_regions = TRUE;
xfc->x11event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, xfc->xfds,
WINPR_FD_READ);
free(xfc->vscreen.monitors);
xfc->vscreen.monitors = NULL;
}
+
+ free(xfc->supportedAtoms);
}
int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
}
/* Determine the x,y starting location for the fullscreen window */
- if (fullscreen && xfc->context.settings->MonitorCount)
+ if (fullscreen)
{
/* Initialize startX and startY with reasonable values */
startX = xfc->context.settings->MonitorDefArray[0].x;
/* Lastly apply any monitor shift(translation from remote to local coordinate system)
* to startX and startY values
*/
- startX = startX + xfc->context.settings->MonitorLocalShiftX;
- startY = startY + xfc->context.settings->MonitorLocalShiftY;
+ startX += xfc->context.settings->MonitorLocalShiftX;
+ startY += xfc->context.settings->MonitorLocalShiftY;
+ }
+ if (xfc->_NET_WM_FULLSCREEN_MONITORS != None)
+ {
/* Set monitor bounds */
if (settings->MonitorCount > 1)
{
xfc->fullscreenMonitors.right,
1);
}
- }
- xf_ResizeDesktopWindow(xfc, window, width, height);
+ 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);
- }
+ 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);
+ /* 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)
+ if (!fullscreen)
+ {
+ /* leave full screen: move the window after removing NET_WM_STATE_FULLSCREEN */
+ XMoveWindow(xfc->display, window->handle, startX, startY);
+ }
+ }
+ else
{
- /* leave full screen: move the window after removing NET_WM_STATE_FULLSCREEN */
- XMoveWindow(xfc->display, window->handle, startX, startY);
+ 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;
+ 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;
+ }
}
}
return FALSE;
status = XGetWindowProperty(xfc->display, window,
- property, 0, length, FALSE, AnyPropertyType,
+ property, 0, length, False, AnyPropertyType,
&actual_type, &actual_format, nitems, bytes, prop);
if (status != Success)
int height)
{
XSizeHints* size_hints;
- rdpSettings *settings = xfc->context.settings;
+ rdpSettings* settings = xfc->context.settings;
if (!xfc || !window)
return;
size_hints->max_width = size_hints->max_height = 16384;
XSetWMNormalHints(xfc->display, window->handle, size_hints);
XResizeWindow(xfc->display, window->handle, width, height);
-
#ifdef WITH_XRENDER
+
if (!settings->SmartSizing)
#endif
{
}
static void xf_FixWindowCoordinates(xfContext* xfc, int* x, int* y, int* width,
- int* height)
+ int* height)
{
int vscreen_width;
int vscreen_height;