static X11Window activeWindow;
static X11Cursor systemCursors[SystemCursor];
+static enum NETWMStateAction { remove = 0, add = 1, toggle = 2 };
+
static enum AtomIdents
{
clipboard, multiple, targets, utf8_string, wm_delete_window, wm_hints, wm_name, wm_protocols, wm_state, wm_take_focus, wm_transient_for,
Visual * xSystemVisual;
bool xSharedMemory;
+static void SetNETWMState(X11Window windowHandle, bool throughRoot, NETWMStateAction action, Atom atom1, Atom atom2)
+{
+ if(atomsSupported[_net_wm_state])
+ {
+ int format;
+ unsigned long count, fill;
+ Atom type;
+ char * data = null;
+ uint state = WithdrawnState;
+
+ /*if(XGetWindowProperty(xGlobalDisplay, windowHandle, atoms[wm_state], 0, 3, False,
+ atoms[wm_state], &type, &format, &count, &fill, &data) == Success && count)
+ {
+ state = *(uint *)data;
+ XFree(data);
+ } */
+ if(!throughRoot) //state == WithdrawnState)
+ {
+ // We need to handle modifying these ourselves for withdrawn windows...
+ if(action == add)
+ {
+ Atom values[2] = { atom1, atom2 };
+ XChangeProperty(xGlobalDisplay, windowHandle, atoms[_net_wm_state], XA_ATOM,
+ 32, PropModeAppend, (byte *)values, atom2 ? 2 : 1);
+ }
+ else if(XGetWindowProperty(xGlobalDisplay, windowHandle, atoms[_net_wm_state], 0, 32, False,
+ XA_ATOM, &type, &format, &count, &fill, &data) == Success)
+ {
+ Atom * values = (Atom *) data;
+ int i;
+ for (i = 0; i < count; i++)
+ {
+ if(values[i] == atom1 || (atom2 && values[i] == atom2))
+ {
+ if(i < count - 1)
+ memmove(values + i, values + i + 1, sizeof(Atom) * (count - i - 1));
+ count--;
+ i--;
+ }
+ }
+ XChangeProperty(xGlobalDisplay, windowHandle, atoms[_net_wm_state], XA_ATOM, 32, PropModeReplace, (byte *)values, (int)count);
+ XFree(data);
+ }
+ }
+ else
+ {
+ XClientMessageEvent event = { 0 };
+ event.type = ClientMessage;
+ event.message_type = atoms[_net_wm_state];
+ event.display = xGlobalDisplay;
+ event.serial = 0;
+ event.window = windowHandle;
+ event.send_event = 1;
+ event.format = 32;
+ event.data.l[0] = action;
+ event.data.l[1] = atom1;
+ event.data.l[2] = atom2;
+ XSendEvent(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), bool::false,
+ SubstructureRedirectMask | SubstructureNotifyMask, (union _XEvent *)&event);
+ }
+ }
+
+}
+
static Time timeStamp;
class XWindowData : struct
XInterface::UpdateRootWindow(window);
}
}
+ result = true;
}
XFree(data);
- result = true;
}
return result;
}
+static bool WaitForFrameExtents(Window window)
+{
+ int attempts = 0;
+ //XFlush(xGlobalDisplay);
+ while(attempts++ < 10)
+ {
+ if(GetFrameExtents(window, false)) return true;
+ Sleep(1.0 / RESOLUTION);
+ }
+ return false;
+}
+
/****************************************************************************
/// DRIVER IMPLEMENTATION /////////////
****************************************************************************/
case ConfigureNotify:
{
XConfigureEvent * event = (XConfigureEvent *) thisEvent;
+ bool unmaximized = false;
while(XCheckIfEvent(xGlobalDisplay, (XEvent *)thisEvent, (void *)ConfigureNotifyChecker, (void *)window.windowHandle));
//if(event->x - desktopX != window.position.x || event->y - desktopY != window.position.y || event->width != window.size.w || event->height != window.size.h)
- if(window.nativeDecorations)
+ if(atomsSupported[_net_wm_state]) //window.nativeDecorations)
{
int format;
unsigned long len, fill;
}
}
{
- int x = event->x;
- int y = event->y;
- int w = event->width, h = event->height;
-
- //if(event->send_event)
+ int x, y, w, h;
+ if(unmaximized)
{
- X11Window rootChild;
- int rootX, rootY;
- XTranslateCoordinates(xGlobalDisplay, event->window,
- RootWindow(xGlobalDisplay, DefaultScreen(xGlobalDisplay)), 0, 0,
- &rootX, &rootY, &rootChild);
- x = rootX;
- y = rootY;
+ // Ensure we set the normal size anchor when un-maximizing
+ if(window.nativeDecorations && RequestFrameExtents(window))
+ WaitForFrameExtents(window);
+ x = window.position.x, y = window.position.y, w = window.size.w, h = window.size.h;
+ window.ComputeAnchors(window.normalAnchor, window.normalSizeAnchor, &x, &y, &w, &h);
}
+ else
+ {
+ x = event->x;
+ y = event->y;
+ w = event->width, h = event->height;
+
+ //if(event->send_event)
+ {
+ X11Window rootChild;
+ int rootX, rootY;
+ XTranslateCoordinates(xGlobalDisplay, event->window,
+ RootWindow(xGlobalDisplay, DefaultScreen(xGlobalDisplay)), 0, 0,
+ &rootX, &rootY, &rootChild);
+ x = rootX;
+ y = rootY;
+ }
- x -= desktopX;
- y -= desktopY;
+ x -= desktopX;
+ y -= desktopY;
- if(window.nativeDecorations && window.state != maximized)
+ if(window.nativeDecorations && window.state != maximized)
+ {
+ x -= windowData.decor.left;
+ y -= windowData.decor.top;
+ w += windowData.decor.left + windowData.decor.right;
+ h += windowData.decor.top + windowData.decor.bottom;
+ /*
+ x -= window.clientStart.x;
+ y -= window.clientStart.y - (window.hasMenuBar ? skinMenuHeight : 0);
+ w += window.size.w - window.clientSize.w;
+ h += window.size.h - window.clientSize.h;
+ */
+ }
+ }
+
+ // Break the anchors for moveable/resizable windows
+ if(window.style.fixed && window.state == normal)
{
- x -= windowData.decor.left;
- y -= windowData.decor.top;
- w += windowData.decor.left + windowData.decor.right;
- h += windowData.decor.top + windowData.decor.bottom;
- /*
- x -= window.clientStart.x;
- y -= window.clientStart.y - (window.hasMenuBar ? skinMenuHeight : 0);
- w += window.size.w - window.clientSize.w;
- h += window.size.h - window.clientSize.h;
- */
+ window.normalAnchor = Anchor { left = x, top = y };
+ window.normalSizeAnchor = SizeAnchor { { w, h } };
+ window.anchored = false;
}
// Break the anchors for moveable/resizable windows
window.anchored = false;
}
- window.Position(x, y, w, h, true, true, true, true, false, false);
+ window.Position(x, y, w, h, true, true, true, true, false, unmaximized);
}
break;
}
else
{
X11Window parentWindow = (X11Window)null;
- int x = window.position.x, y = window.position.y;
+ int x = window.position.x + desktopX, y = window.position.y + desktopY;
int w = window.state == normal ? Max(1, window.size.w) : Max(1, window.normalSizeAnchor.size.w);
int h = window.state == normal ? Max(1, window.size.h) : Max(1, window.normalSizeAnchor.size.h);
+ if(!window.nativeDecorations && window.state != normal)
+ {
+ w += window.size.w - window.clientSize.w;
+ h += window.size.h - window.clientSize.h;
+ }
if(window.master.rootWindow && window.master.rootWindow != guiApp.desktop && (window._isModal || window.style.interim))
{
//printf("Done.\n");
//XChangeProperty(xGlobalDisplay, windowHandle, atoms[wm_transient_for], XA_WINDOW, 32, PropModeReplace, (unsigned char*)&parentWindow, 1);
if(window.isModal)
- {
- Atom hints[1] = { atoms[_net_wm_state_modal] };
- XChangeProperty(xGlobalDisplay, windowHandle, atoms[_net_wm_state], XA_ATOM, 32, PropModeReplace, (unsigned char*)&hints, 1);
- }
+ SetNETWMState(windowHandle, false, add, atoms[_net_wm_state_modal], 0);
}
{
// Was commenting this out was part of #700/#795 fix, but this causes jumping of e.g. About box after getting frame extents PropertyNotify
// && window.state != maximized -- required for Cinnamon on Mint 14/15
- if(!windowData.gotFrameExtents && window.state != maximized) return;
+ if(!windowData.gotFrameExtents && window.state != maximized)
+ {
+ if(WaitForFrameExtents(window))
+ {
+ x += windowData.decor.left;
+ y += windowData.decor.top ;
+
+ w += windowData.decor.left + windowData.decor.right;
+ h += windowData.decor.top + windowData.decor.bottom;
+ }
+ }
x -= windowData.decor.left;
y -= windowData.decor.top;
h -= windowData.decor.top + windowData.decor.bottom;
// Tweak for first unmaximize on Unity on Ubuntu 11.10
- if(window.state == maximized && (desktopX + w > desktopW || desktopY + h > desktopH))
+ /*if(window.state == maximized && (desktopX + w > desktopW || desktopY + h > desktopH))
{
w -= 40;
h -= 40;
- }
+ }*/
}
x += desktopX;
y += desktopY;
- if(move && resize)
- XMoveResizeWindow(xGlobalDisplay, (X11Window)window.windowHandle, x, y, w, h);
- else if(move)
- XMoveWindow(xGlobalDisplay, (X11Window)window.windowHandle, x, y);
- else if(resize)
- XResizeWindow(xGlobalDisplay, (X11Window)window.windowHandle, w, h);
+ if(!atomsSupported[_net_wm_state] || window.state != maximized)
+ {
+ if(move && resize)
+ XMoveResizeWindow(xGlobalDisplay, (X11Window)window.windowHandle, x, y, w, h);
+ else if(move)
+ XMoveWindow(xGlobalDisplay, (X11Window)window.windowHandle, x, y);
+ else if(resize)
+ XResizeWindow(xGlobalDisplay, (X11Window)window.windowHandle, w, h);
+ }
#if defined(__APPLE__)
// if(window.created && !visible)
// XUnmapWindow(xGlobalDisplay, (X11Window)window.windowHandle);
if(state == minimized && atomsSupported[_net_wm_state])
{
uint iconic = IconicState;
- /*
- XChangeProperty(xGlobalDisplay, window.windowHandle, atoms[_net_wm_state], XA_ATOM, 32,
- PropModeReplace, (unsigned char*)&atoms[_net_wm_state_hidden], 1);
- */
+
+ // SetNETWMState(window.windowHandle, true, add, atoms[_net_wm_state_hidden], null);
/*
XChangeProperty(xGlobalDisplay, window.windowHandle, atoms[wm_state], XA_CARDINAL, 32,
PropModeReplace, &iconic, 1);
/*
XClientMessageEvent event = { 0 };
event.type = ClientMessage;
- event.message_type = atoms[_net_wm_state];
- event.display = xGlobalDisplay;
- event.serial = 0;
- event.window = window.windowHandle;
- event.send_event = 1;
- event.format = 32;
- event.data.l[0] = 2; // 1;
- event.data.l[1] = atoms[_net_wm_state_hidden];
- XSendEvent(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), bool::false, SubstructureRedirectMask | SubstructureNotifyMask, &event);
- */
- /*
- XClientMessageEvent event = { 0 };
- event.type = ClientMessage;
event.message_type = atoms[wm_state];
event.display = xGlobalDisplay;
event.window = window.windowHandle;
}
else
{
- if(!atomsSupported[_net_wm_state] || !window.nativeDecorations || (!((XWindowData)window.windowData).gotFrameExtents && window.state == maximized)) //((XWindowData)window.windowData).gotFrameExtents && (!window.nativeDecorations || window.state == state))
+ //((XWindowData)window.windowData).gotFrameExtents && (!window.nativeDecorations || window.state == state))
+ if(!atomsSupported[_net_wm_state] || (!((XWindowData)window.windowData).gotFrameExtents && window.state == maximized))
{
- // With native decorations, we do it the first time
- // or the WM (Gnome) is sticking it to the top/right!
+ // Running this block avoids the initial IDE maximized->unmaximized flicker
+ //if(window.state != maximized || !atomsSupported[_net_wm_state] || window.nativeDecorations)
{
int x = window.position.x;
int y = window.position.y;
if(atomsSupported[_net_wm_state])
{
// Maximize / Restore the window
- XClientMessageEvent event = { 0 };
- event.type = ClientMessage;
- event.message_type = atoms[_net_wm_state];
- event.display = xGlobalDisplay;
- event.serial = 0;
- event.window = (X11Window)window.windowHandle;
- event.send_event = 1;
- event.format = 32;
- event.data.l[0] = (state == maximized) ? 1 : 0;
- event.data.l[1] = atoms[_net_wm_state_maximized_vert];
- event.data.l[2] = atoms[_net_wm_state_maximized_horz];
- XSendEvent(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), bool::false,
- SubstructureRedirectMask | SubstructureNotifyMask, (union _XEvent *)&event);
+ SetNETWMState((X11Window)window.windowHandle, true, state == maximized ? add: remove,
+ atoms[_net_wm_state_maximized_vert], atoms[_net_wm_state_maximized_horz]);
+ if(state == maximized)
+ {
+ // Prevent the code in ConfigureNotify to think the window has been unmaximized
+ // if the Window Manager hasn't set the hints yet.
+ XFlush(xGlobalDisplay);
+ Sleep(0.01);
+ }
}
}
}
void FlashRootWindow(Window window)
{
- XClientMessageEvent event = { 0 };
// printf("Attempting to flash root window\n");
- event.type = ClientMessage;
- event.message_type = atoms[_net_wm_state];
- event.display = xGlobalDisplay;
- event.serial = 0;
- event.window = (X11Window)window.windowHandle;
- event.send_event = 1;
- event.format = 32;
- event.data.l[0] = 1;
- event.data.l[1] = atoms[_net_wm_state_demands_attention];
- XSendEvent(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), bool::false, SubstructureRedirectMask | SubstructureNotifyMask, (union _XEvent *)&event);
+ SetNETWMState((X11Window)window.windowHandle, true, add, atoms[_net_wm_state_demands_attention], 0);
}
void ActivateRootWindow(Window window)