namespace gui::drivers;
import "instance"
-#if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
+#if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D) && !defined(ECERE_NOGL)
import "OpenGLDisplayDriver"
#endif
#include <linux/joystick.h>
#endif
#include <sys/param.h>
-#ifdef BSD
#include <stdlib.h>
-#else
-#include <malloc.h>
-#endif
#include <unistd.h>
+#include <sys/select.h>
//#include <stdio.h>
//#include <stdlib.h>
#include <X11/Xutil.h>
#include <X11/XKBlib.h>
#include <X11/keysym.h>
-#include <sys/fcntl.h>
+#include <fcntl.h>
+#if !defined(ECERE_NO3D) && !defined(ECERE_NOGL)
#include <GL/glx.h>
+#endif
#include <X11/extensions/Xrender.h>
#include <X11/extensions/XShm.h>
_net_wm_window_type_desktop, _net_wm_window_type_dialog, _net_wm_window_type_dock, _net_wm_window_type_dropdown_menu,
_net_wm_window_type_menu, _net_wm_window_type_normal, _net_wm_window_type_popup_menu, _net_wm_window_type_splash,
_net_wm_window_type_toolbar, _net_wm_window_type_utility, _net_workarea, _net_frame_extents, _net_request_frame_extents,
- _net_wm_state_maximized_vert, _net_wm_state_maximized_horz, app_selection
+ _net_wm_state_maximized_vert, _net_wm_state_maximized_horz, _net_wm_state_modal, app_selection
};
static Atom atoms[AtomIdents];
"_NET_REQUEST_FRAME_EXTENTS", // _net_request_frame_extents
"_NET_WM_STATE_MAXIMIZED_VERT", // _net_wm_state_maximized_vert
"_NET_WM_STATE_MAXIMIZED_HORZ", // _net_wm_state_maximized_horz
+ "_NET_WM_STATE_MODAL", // _net_wm_state_modal
"APP_SELECTION"
};
+/*
+_NET_WM_STATE_STICKY, ATOM
+_NET_WM_STATE_MAXIMIZED_VERT, ATOM
+_NET_WM_STATE_MAXIMIZED_HORZ, ATOM
+_NET_WM_STATE_SHADED, ATOM
+_NET_WM_STATE_SKIP_TASKBAR, ATOM
+_NET_WM_STATE_SKIP_PAGER, ATOM
+_NET_WM_STATE_HIDDEN, ATOM
+_NET_WM_STATE_FULLSCREEN, ATOM
+_NET_WM_STATE_ABOVE, ATOM
+_NET_WM_STATE_BELOW, ATOM
+_NET_WM_STATE_DEMANDS_ATTENTION, ATOM
+*/
static bool autoRepeatDetectable;
static bool setICPosition;
XWindowData windowData = window.windowData;
if(windowData)
{
- box = windowData.decor;
+ if(window.state == maximized)
+ box = { 0, 0, 0, 0 };
+ else
+ box = windowData.decor;
return true;
}
return false;
}
return null;
}
-/*
-_NET_WM_STATE_MODAL, ATOM
-_NET_WM_STATE_STICKY, ATOM
-_NET_WM_STATE_MAXIMIZED_VERT, ATOM
-_NET_WM_STATE_MAXIMIZED_HORZ, ATOM
-_NET_WM_STATE_SHADED, ATOM
-_NET_WM_STATE_SKIP_TASKBAR, ATOM
-_NET_WM_STATE_SKIP_PAGER, ATOM
-_NET_WM_STATE_HIDDEN, ATOM
-_NET_WM_STATE_FULLSCREEN, ATOM
-_NET_WM_STATE_ABOVE, ATOM
-_NET_WM_STATE_BELOW, ATOM
-_NET_WM_STATE_DEMANDS_ATTENTION, ATOM
-*/
-
static void RepositionDesktop(bool updateChildren)
{
int format;
unsigned long len, fill;
Atom type;
+ static double lastTime = 0, time;
+
+ time = GetTime();
+ if(desktopW && desktopH && time - lastTime < 1.5) return;
+ lastTime = time;
w = XDisplayWidth(xGlobalDisplay, DefaultScreen(xGlobalDisplay));
h = XDisplayHeight(xGlobalDisplay, DefaultScreen(xGlobalDisplay));
if(data)
{
int desktops = 0;
- desktops = *(long *)data;
+ desktops = (int)*(long *)data;
//printf("_NET_NUMBER_OF_DESKTOPS is %d\n", desktops);
if(data)
{
- current = *(long *)data;
+ current = (int)*(long *)data;
XFree(data);
data = null;
{
workareas = (long *)data;
- x = workareas[current * 4];
- y = workareas[current * 4 + 1];
- w = workareas[current * 4 + 2];
- h = workareas[current * 4 + 3];
+ x = (int)workareas[current * 4];
+ y = (int)workareas[current * 4 + 1];
+ w = (int)workareas[current * 4 + 2];
+ h = (int)workareas[current * 4 + 3];
//printf("_NET_WORKAREA is x = %d, y = %d, w = %d, h = %d\n", x, y, w, h);
+ XFree(data);
+ data = null;
}
// printf("Work Area width: %d, height %d\n", w, h);
}
*/
if(!buf)
- buf = malloc(bufsize);
+ buf = malloc((uint)bufsize);
if(windowData && windowData.ic)
{
- buflength = XmbLookupString(windowData.ic, event, buf, bufsize, &keysym, &status);
+ buflength = XmbLookupString(windowData.ic, event, buf, (int)bufsize, &keysym, &status);
if (status == XBufferOverflow)
{
- buf = realloc(buf, (bufsize = buflength));
- buflength = XmbLookupString(windowData.ic, event, buf, bufsize, &keysym, &status);
+ buf = realloc(buf, (uint)(bufsize = buflength));
+ buflength = XmbLookupString(windowData.ic, event, buf, (int)bufsize, &keysym, &status);
}
if(status != XLookupKeySym && status != XLookupBoth && release == 1)
keysym = XLookupKeysym(event, 0);
#ifdef __APPLE__
case XK_Help: key = insert; break;
#endif
- // case XK_Break:
+ case XK_Break: key = Key { pauseBreak, ctrl = true }; break;
#ifdef __APPLE__
case XK_Mode_switch: key = leftAlt; break;
#endif
int numBytes;
ch = UTF8GetChar(buf + c, &numBytes);
if(ch == 127) ch = 0;
- if(!numBytes) c = buflength;
result = window.KeyMessage((c == 0) ?
__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown : __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit,
(c == 0) ? code : 0, ch);
c += numBytes;
+ if(!numBytes) c = buflength;
}
}
else
int numBytes;
ch = UTF8GetChar(buf + c, &numBytes);
if(ch == 127) ch = 0;
- if(!numBytes) c = buflength;
result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit, code, ch);
c += numBytes;
+ if(!numBytes) c = buflength;
}
else
result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit, code, ch);
static Bool ConfigureNotifyChecker(void *display, XConfigureEvent *event, char * data)
{
- return ((!data || (event->window == (int) data)) && event->type == ConfigureNotify;
+ return ((!data || (event->window == (X11Window) data)) && event->type == ConfigureNotify;
}
+static enum FrameExtentSupport { unknown, working, broken };
+
+static FrameExtentSupport frameExtentSupported;
+static Time frameExtentRequest;
+static X11Window frameExtentWindow;
+
static uint timerDelay = MAXINT;
#define RESOLUTION (18.2 * 100)
static uint XTimerThread(Thread thread)
if(FD_ISSET(s, &readSet))
gotAnXEvent = true;
}
+ if(frameExtentSupported == unknown && frameExtentRequest && GetTime() - frameExtentRequest > 1)
+ {
+ XPropertyEvent event = { 0 };
+ event.type = PropertyNotify;
+ event.state = PropertyNewValue;
+ event.atom = atoms[_net_frame_extents];
+ event.display = xGlobalDisplay;
+ event.serial = 0;
+ event.window = frameExtentWindow;
+ event.send_event = 1;
+
+ frameExtentSupported = broken;
+
+ XSendEvent(xGlobalDisplay, frameExtentWindow, bool::false,
+ PropertyChangeMask, (union _XEvent *)&event);
+ }
xMutex.Release();
guiApp.SignalEvent();
xSemaphore.Wait();
#include <sys/ipc.h>
#include <sys/shm.h>
-#include <sys/signal.h>
+#include <signal.h>
#include <locale.h>
#endif
xTerminate = false;
xGlobalDisplay = XOpenDisplay(null);
+ frameExtentSupported = unknown;
joystickFD[0] = open("/dev/js0", O_RDONLY);
joystickFD[1] = open("/dev/js1", O_RDONLY);
{
XVisualInfo vinfo;
XVisualInfo *vinfo_ret;
- long numitems;
+ int numitems = 0;
vinfo.visualid = XVisualIDFromVisual(xSystemVisual);
vinfo_ret = XGetVisualInfo(xGlobalDisplay, VisualIDMask, &vinfo, &numitems);
event->x_root, event->y_root, &keyFlags, false, false);
delete window;
//*if(xGlobalDisplay) XLockDisplay(xGlobalDisplay);
- lastTime = event->time;
+ lastTime = (uint)event->time;
}
break;
}
}
case FocusIn:
{
- XFocusChangeEvent *event = (XFocusChangeEvent *) thisEvent;
- Window modalRoot = window.FindModal();
- XWindowData windowData;
- activeWindow = (X11Window)window.windowHandle;
-
- if(window.parent && window == window.parent.activeChild) break;
- incref window;
- //if(window.creationActivation == activate)
- {
- if(modalRoot)
- modalRoot.ExternalActivate(true, true, window, null); // lastActive);
- else
- window.ExternalActivate(true, true, window, null); // lastActive);
- }
- windowData = modalRoot ? modalRoot.windowData : window.windowData;
- if(windowData && windowData.ic)
+ if(activeWindow != (X11Window)window.windowHandle)
{
- // XSetICValues(ic, XNClientWindow, window.windowHandle, XNFocusWindow, window.windowHandle, 0);
- XSetICFocus(windowData.ic);
+ XFocusChangeEvent *event = (XFocusChangeEvent *) thisEvent;
+ Window modalRoot = window.FindModal();
+ XWindowData windowData;
+
+ activeWindow = (X11Window)window.windowHandle;
+
+ if(window.parent && window == window.parent.activeChild) break;
+ incref window;
+ //if(window.creationActivation == activate)
+ {
+ if(modalRoot)
+ modalRoot.ExternalActivate(true, true, window, null); // lastActive);
+ else
+ window.ExternalActivate(true, true, window, null); // lastActive);
+ }
+ windowData = modalRoot ? modalRoot.windowData : window.windowData;
+ if(windowData && windowData.ic)
+ {
+ // XSetICValues(ic, XNClientWindow, window.windowHandle, XNFocusWindow, window.windowHandle, 0);
+ XSetICFocus(windowData.ic);
+ }
+ //delete lastActive;
+ //lastActive = window;
+ //incref lastActive;
+ delete window;
}
- //delete lastActive;
- //lastActive = window;
- //incref lastActive;
- delete window;
break;
}
case FocusOut:
//if(event->send_event)
{
X11Window rootChild;
- long rootX, rootY;
+ int rootX, rootY;
XTranslateCoordinates(xGlobalDisplay, event->window,
RootWindow(xGlobalDisplay, DefaultScreen(xGlobalDisplay)), 0, 0,
&rootX, &rootY, &rootChild);
x -= desktopX;
y -= desktopY;
- if(window.nativeDecorations)
+ if(window.nativeDecorations && window.state != maximized)
{
x -= windowData.decor.left;
y -= windowData.decor.top;
h += window.size.h - window.clientSize.h;
*/
}
- window.ExternalPosition(x, y, w, h);
+ window.Position(x, y, w, h, true, true, true, true, false, false);
}
break;
}
bool laterFocus;
activeWindow = (X11Window)window.windowHandle;
- timeStamp = event->data.l[1];
+ timeStamp = (int)event->data.l[1];
windowData = window.windowData;
laterFocus = windowData.laterFocus;
&fill, &data) == Success && data)
{
long *extents = (long *)data;
+ bool change = extents[0] != windowData.decor.left ||
+ extents[1] != windowData.decor.right ||
+ extents[2] != windowData.decor.top ||
+ extents[3] != windowData.decor.bottom;
+
bool hadFrameExtents = windowData.gotFrameExtents;
- windowData.decor =
- {
- left = extents[0], right = extents[1],
- top = extents[2], bottom = extents[3]
- };
- windowData.gotFrameExtents = true;
+ Box oldDecor = windowData.decor;
+
+ frameExtentSupported = working;
+ frameExtentWindow = 0;
+ frameExtentRequest = 0;
+
+ if(!hadFrameExtents || extents[0] || extents[1] || extents[2] || extents[3])
{
- int x, y, w, h;
- window.ComputeAnchors(
- window.normalAnchor,
- window.normalSizeAnchor,
- &x, &y, &w, &h);
- if(!hadFrameExtents) // || window.state == normal)
+ windowData.decor =
+ {
+ left = (int)extents[0], right = (int)extents[1],
+ top = (int)extents[2], bottom = (int)extents[3]
+ };
+ windowData.gotFrameExtents = true;
+ if(change && ((Window)window).clientSize.w > 0)
{
- bool isMaximized = window.state == maximized;
- window.Position(x, y, w, h, true, true, true, true, false, true);
- UpdateRootWindow(window);
+ int x = window.position.x, y = window.position.y, w = window.size.w, h = window.size.h;
+ if(!hadFrameExtents && window.state != maximized)
+ {
+ window.ComputeAnchors(
+ window.normalAnchor,
+ window.normalSizeAnchor,
+ &x, &y, &w, &h);
+ }
+ else
+ {
+ x += windowData.decor.left - oldDecor.left;
+ y += windowData.decor.top - oldDecor.top;
+
+ w += windowData.decor.left - oldDecor.left + windowData.decor.right - oldDecor.right;
+ h += windowData.decor.top - oldDecor.top + windowData.decor.bottom - oldDecor.bottom;
+ }
+
+ if(window.state != maximized)
+ {
+ window.Position(x, y, w, h, true, true, true, true, false, !hadFrameExtents && window.state != maximized);
+ UpdateRootWindow(window);
+ }
}
}
-
XFree(data);
}
else
attributes.override_redirect = window.interim ? True : False;
attributes.event_mask = EVENT_MASK;
//printf("%s\n", guiApp.defaultDisplayDriver);
-#if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
+#if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D) && !defined(ECERE_NOGL)
if(window.dispDriver == class(OpenGLDisplayDriver) || !strcmp(guiApp.defaultDisplayDriver, "OpenGL"))
{
int samples;
0,0,1,1,0, depth, InputOutput, visual ? visual : CopyFromParent,
CWEventMask | CWOverrideRedirect | (visual ? (CWColormap | CWBorderPixel) : 0), &attributes);
- if(parentWindow && window.interim)
+ if(parentWindow && (window.interim || window.isModal))
{
//printf("Setting WM_TRANSIENT_FOR of %s to %s\n", window._class.name, window.master.rootWindow._class.name);
XSetTransientForHint(xGlobalDisplay, windowHandle, parentWindow);
//XFlush(xGlobalDisplay);
//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);
+ }
}
{
XUngrabPointer(xGlobalDisplay, CurrentTime);
}
- if(window.nativeDecorations)
+ if(window.nativeDecorations && frameExtentSupported != broken)
{
- // Maximize / Restore the window
+ // Request decoration frame extents
XClientMessageEvent event = { 0 };
event.type = ClientMessage;
event.message_type = atoms[_net_request_frame_extents];
event.send_event = 1;
window.windowHandle = (void *)windowHandle;
event.format = 32;
+
+ if(frameExtentSupported == unknown && !frameExtentRequest)
+ {
+ frameExtentRequest = GetTime();
+ frameExtentWindow = windowHandle;
+ }
+
XSendEvent(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), bool::false,
SubstructureRedirectMask | SubstructureNotifyMask, (union _XEvent *)&event);
}
+ else
+ ((XWindowData)window.windowData).gotFrameExtents = true;
return (void *)windowHandle;
}
//Logf("Position root window %s\n", window.name);
if(window.windowHandle && (!window.parent || !window.parent.display))
{
-#if defined(__APPLE__) || defined(__FreeBSD__)
bool visible = window.visible;
- if(window.visible)
- {
+ if(window.visible && window.created)
XMapWindow(xGlobalDisplay, (X11Window)window.windowHandle);
- WaitForViewableWindow(window);
- }
-#endif
if(window.state == minimized) return;
if(window.nativeDecorations)
{
XWindowData windowData = window.windowData;
-#if !defined(__APPLE__) && !defined(__FreeBSD__)
- // TODO: How to handle frame extents not supported?
- if(!windowData.gotFrameExtents || window.state == maximized) return;
-#endif
- w -= window.size.w - window.clientSize.w;
- h -= window.size.h - window.clientSize.h;
+
+ // 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;
+
+ x -= windowData.decor.left;
+ y -= windowData.decor.top;
+
+ w -= windowData.decor.left + windowData.decor.right;
+ 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))
+ {
+ w -= 40;
+ h -= 40;
+ }
}
+
+ x += desktopX;
+ y += desktopY;
+
if(move && resize)
- XMoveResizeWindow(xGlobalDisplay, (X11Window)window.windowHandle, x + desktopX, y + desktopY, w, h);
+ XMoveResizeWindow(xGlobalDisplay, (X11Window)window.windowHandle, x, y, w, h);
else if(move)
- XMoveWindow(xGlobalDisplay, (X11Window)window.windowHandle, x + desktopX, y + desktopY);
+ XMoveWindow(xGlobalDisplay, (X11Window)window.windowHandle, x, y);
else if(resize)
XResizeWindow(xGlobalDisplay, (X11Window)window.windowHandle, w, h);
#if defined(__APPLE__)
if(visible)
{
XMapWindow(xGlobalDisplay, (X11Window)window.windowHandle);
-#if defined(__APPLE__) || defined(__FreeBSD__)
WaitForViewableWindow(window);
-#endif
if(window.creationActivation == activate && state != minimized)
ActivateRootWindow(window);
{
if(!window.nativeDecorations || (!((XWindowData)window.windowData).gotFrameExtents && window.state == maximized)) //((XWindowData)window.windowData).gotFrameExtents && (!window.nativeDecorations || window.state == state))
{
+ int x = window.position.x;
+ int y = window.position.y;
+ int w = window.size.w;
+ int h = window.size.h;
+
+ if(window.nativeDecorations)
+ {
+ XWindowData windowData = window.windowData;
+ x -= windowData.decor.left;
+ y -= windowData.decor.top;
+
+ w -= windowData.decor.left + windowData.decor.right;
+ h -= windowData.decor.top + windowData.decor.bottom;
+ }
+ x += desktopX;
+ y += desktopY;
+
// With native decorations, we do it the first time
// or the WM (Gnome) is sticking it to the top/right!
XMoveResizeWindow(xGlobalDisplay,
(X11Window)window.windowHandle,
- window.position.x + desktopX,
- window.position.y + desktopY,
- window.nativeDecorations ? window.clientSize.w : window.size.w,
- window.nativeDecorations ? window.clientSize.h : window.size.h);
+ x, y, w, h);
UpdateRootWindow(window);
}
if(window.nativeDecorations)
{
XSelectionEvent * selection = (XSelectionEvent *) &e;
//printf("Got a SelectionNotify with %d (%s)\n", selection->_property, XGetAtomName(xGlobalDisplay, selection->_property));
- byte *data;
+ byte *data = null;
unsigned long len, size = 0, dummy;
Atom type;
int format;
XGetWindowProperty(xGlobalDisplay, (X11Window) rootWindow.windowHandle, selection->_property ? selection->_property : atom, 0, 0, False, AnyPropertyType, &type, &format, &len, &size, &data);
+ if(data)
+ {
+ XFree(data);
+ data = null;
+ }
if(size > 0)
{
if(XGetWindowProperty(xGlobalDisplay, (X11Window) rootWindow.windowHandle, selection->_property ? selection->_property : atom, 0, size, False,