mirror of https://github.com/FreeRDP/FreeRDP
Fullscreen without _NET_WM_FULLSCREEN_MONITORS
Some window managers do not support _NET_WM_FULLSCREEN_MONITORS. In that case multimonitor fullscreen does not properly work, so add a path resizing the window over all screens instead. Based on @erbth pull request, adding proper X11 atom checks.
This commit is contained in:
parent
80a49f46dc
commit
1628045f67
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#ifdef WITH_XRENDER
|
||||
#include <X11/extensions/Xrender.h>
|
||||
|
@ -1738,6 +1739,19 @@ static int xfreerdp_client_stop(rdpContext* context)
|
|||
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;
|
||||
|
@ -1792,20 +1806,48 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* 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",
|
||||
|
@ -1832,13 +1874,6 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
|
|||
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);
|
||||
|
||||
|
@ -1915,6 +1950,8 @@ static void xfreerdp_client_free(freerdp* instance, rdpContext* context)
|
|||
free(xfc->vscreen.monitors);
|
||||
xfc->vscreen.monitors = NULL;
|
||||
}
|
||||
|
||||
free(xfc->supportedAtoms);
|
||||
}
|
||||
|
||||
int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
|
||||
|
|
|
@ -174,7 +174,7 @@ void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen)
|
|||
}
|
||||
|
||||
/* 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;
|
||||
|
@ -190,9 +190,12 @@ void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen)
|
|||
/* 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)
|
||||
{
|
||||
|
@ -203,25 +206,119 @@ void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen)
|
|||
xfc->fullscreenMonitors.right,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
xf_ResizeDesktopWindow(xfc, window, width, height);
|
||||
|
||||
if (fullscreen)
|
||||
else
|
||||
{
|
||||
/* enter full screen: move the window before adding NET_WM_STATE_FULLSCREEN */
|
||||
XMoveWindow(xfc->display, window->handle, startX, startY);
|
||||
}
|
||||
if (fullscreen)
|
||||
{
|
||||
xf_SetWindowDecorations(xfc, window->handle, FALSE);
|
||||
|
||||
/* 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 (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 (!fullscreen)
|
||||
{
|
||||
/* leave full screen: move the window after removing NET_WM_STATE_FULLSCREEN */
|
||||
XMoveWindow(xfc->display, window->handle, startX, startY);
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,7 +336,7 @@ BOOL xf_GetWindowProperty(xfContext* xfc, Window window, Atom property,
|
|||
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)
|
||||
|
@ -480,7 +577,7 @@ void xf_ResizeDesktopWindow(xfContext* xfc, xfWindow* window, int width,
|
|||
int height)
|
||||
{
|
||||
XSizeHints* size_hints;
|
||||
rdpSettings *settings = xfc->context.settings;
|
||||
rdpSettings* settings = xfc->context.settings;
|
||||
|
||||
if (!xfc || !window)
|
||||
return;
|
||||
|
@ -494,8 +591,8 @@ void xf_ResizeDesktopWindow(xfContext* xfc, xfWindow* window, int width,
|
|||
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
|
||||
{
|
||||
|
@ -595,7 +692,7 @@ void xf_SetWindowText(xfContext* xfc, xfAppWindow* appWindow, const char* name)
|
|||
}
|
||||
|
||||
static void xf_FixWindowCoordinates(xfContext* xfc, int* x, int* y, int* width,
|
||||
int* height)
|
||||
int* height)
|
||||
{
|
||||
int vscreen_width;
|
||||
int vscreen_height;
|
||||
|
|
|
@ -173,6 +173,9 @@ struct xf_context
|
|||
VIRTUAL_SCREEN vscreen;
|
||||
void* xv_context;
|
||||
|
||||
Atom* supportedAtoms;
|
||||
unsigned long supportedAtomCount;
|
||||
|
||||
Atom UTF8_STRING;
|
||||
|
||||
Atom _NET_WM_ICON;
|
||||
|
@ -180,6 +183,9 @@ struct xf_context
|
|||
Atom _NET_CURRENT_DESKTOP;
|
||||
Atom _NET_WORKAREA;
|
||||
|
||||
Atom _NET_SUPPORTED;
|
||||
ATOM _NET_SUPPORTING_WM_CHECK;
|
||||
|
||||
Atom _NET_WM_STATE;
|
||||
Atom _NET_WM_STATE_FULLSCREEN;
|
||||
Atom _NET_WM_STATE_MAXIMIZED_HORZ;
|
||||
|
@ -213,8 +219,8 @@ struct xf_context
|
|||
RdpeiClientContext* rdpei;
|
||||
RdpgfxClientContext* gfx;
|
||||
EncomspClientContext* encomsp;
|
||||
xfDispContext *xfDisp;
|
||||
DispClientContext *disp;
|
||||
xfDispContext* xfDisp;
|
||||
DispClientContext* disp;
|
||||
|
||||
RailClientContext* rail;
|
||||
wHashTable* railWindows;
|
||||
|
@ -224,6 +230,7 @@ struct xf_context
|
|||
|
||||
/* value to be sent over wire for each logical client mouse button */
|
||||
int button_map[NUM_BUTTONS_MAPPED];
|
||||
BYTE savedMaximizedState;
|
||||
};
|
||||
|
||||
BOOL xf_create_window(xfContext* xfc);
|
||||
|
|
Loading…
Reference in New Issue