namespace gui::drivers;
import "instance"
-#if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
+#if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D) && !defined(ECERE_NOGL) && !defined(__ODROID__)
import "OpenGLDisplayDriver"
#endif
-#if (defined(__unix__) || defined(__APPLE__)) && !defined(ECERE_MINIGLX)
+#if (defined(__unix__) || defined(__APPLE__)) && !defined(ECERE_MINIGLX) && !defined(__EMSCRIPTEN__)
#undef __BLOCKS__
default:
#include <unistd.h>
#include <sys/select.h>
+#if defined(__APPLE__)
+#define set _set
+#include <mach/mach.h>
+#include <mach/task.h>
+#include <mach/semaphore.h>
+#undef set
+#else
+#include <semaphore.h>
+#endif
+
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
#define Time X11Time
#define KeyCode X11KeyCode
#define Picture X11Picture
+#define Bool X11Bool
+
+#define _XTYPEDEF_BOOL
+typedef int X11Bool;
#include <X11/Xatom.h>
#include <X11/Xlib.h>
+#if !defined(__EMSCRIPTEN__)
#include <X11/Xresource.h>
+#endif
#include <X11/Xutil.h>
#include <X11/XKBlib.h>
#include <X11/keysym.h>
+#include <X11/cursorfont.h>
#include <fcntl.h>
-#if !defined(ECERE_NO3D)
+#if !defined(ECERE_NO3D) && !defined(ECERE_NOGL) //&& !defined(__ODROID__)
+#if defined(__EMSCRIPTEN__)
+#include <GL/glfw.h>
+#else
#include <GL/glx.h>
#endif
+#endif
+#if !defined(__EMSCRIPTEN__)
#include <X11/extensions/Xrender.h>
+#endif
#include <X11/extensions/XShm.h>
+#undef Bool
#undef Picture
#undef Window
#undef Cursor
static X11Window capturedWindow = None;
static Window restrictedWindow = null;
static bool gotAnXEvent = false;
-static XEvent xEvent;
+//static XEvent xEvent;
static int joystickFD[4];
static X11Window activeWindow;
+static X11Cursor systemCursors[SystemCursor];
+
+static Window acquiredInputWindow;
+static Point acquireStart;
+static Point lastMouse;
+static MouseButtons buttonsState;
+
+static bool keyStates[KeyCode];
+
+static enum NETWMStateAction { remove = 0, add = 1, toggle = 2 };
static enum AtomIdents
{
_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, _net_supported,
+ _net_wm_state_skip_taskbar, _net_wm_state_fullscreen, _net_wm_state_above, capsLock, numLock, scrollLock
};
static Atom atoms[AtomIdents];
+static bool atomsSupported[AtomIdents];
static const char *atomNames[AtomIdents] = {
"CLIPBOARD", //clipboard
"_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
- "APP_SELECTION"
+ "_NET_WM_STATE_MODAL", // _net_wm_state_modal
+ "APP_SELECTION",
+ "_NET_SUPPORTED",
+ "_NET_WM_STATE_SKIP_TASKBAR",
+ "_NET_WM_STATE_FULLSCREEN",
+ "_NET_WM_STATE_ABOVE",
+ "Caps Lock",
+ "Num Lock",
+ "Scroll Lock"
};
+/*
+_NET_WM_STATE_STICKY, ATOM
+_NET_WM_STATE_SHADED, ATOM
+_NET_WM_STATE_SKIP_PAGER, ATOM
+_NET_WM_STATE_BELOW, ATOM
+*/
static bool autoRepeatDetectable;
static bool setICPosition;
Visual * xSystemVisual;
bool xSharedMemory;
-static Time timeStamp;
+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;
+ byte * 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 X11Time timeStamp;
class XWindowData : struct
{
// Decorations Size
Box decor;
bool gotFrameExtents;
+ bool currentlyVisible;
};
bool XGetBorderWidths(Window window, Box box)
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;
XVisualInfo vinfo;
XVisualInfo *vinfo_ret;
int numitems;
-
+
vinfo._class = TrueColor;
vinfo_ret = XGetVisualInfo(dpy, VisualClassMask, &vinfo, &numitems);
if(numitems)
return vinfo.visual;
}
}
- }
+ }
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 w, h;
Screen * x_screen = XDefaultScreenOfDisplay(xGlobalDisplay);
X11Window x_root;
- int current = 0;
- char *data = null;
+ int current = 0;
+ byte *data = null;
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));
x_root = XRootWindowOfScreen(x_screen);
-
- if(atoms[_net_number_of_desktops] != None)
+
+ if(atomsSupported[_net_number_of_desktops])
{
if(XGetWindowProperty(xGlobalDisplay, x_root, atoms[_net_number_of_desktops], 0, 1, False,
XA_CARDINAL, &type, &format, &len, &fill,
{
printf("cant get xa desktops property\n");
}
-
+
if(data)
{
+ /*
int desktops = 0;
- desktops = *(long *)data;
-
- //printf("_NET_NUMBER_OF_DESKTOPS is %d\n", desktops);
+ desktops = (int)*(long *)data;
+ printf("_NET_NUMBER_OF_DESKTOPS is %d\n", desktops);
+ */
XFree(data);
data = null;
}
}
-
- if(atoms[_net_current_desktop] != None)
- {
+
+ if(atomsSupported[_net_current_desktop])
+ {
if(XGetWindowProperty(xGlobalDisplay, x_root, atoms[_net_current_desktop], 0, 1, False,
XA_CARDINAL, &type, &format, &len, &fill,
&data) != Success)
{
printf("cant get xa current property\n");
}
-
+
if(data)
{
- current = *(long *)data;
+ current = (int)*(long *)data;
XFree(data);
data = null;
//printf("_NET_CURRENT_DESKTOP is %d\n", current);
}
- }
- if(atoms[_net_workarea] != None)
+ }
+ if(atomsSupported[_net_workarea])
{
long *workareas;
{
//printf("warning\n");
}
-
+
/*
if(type == None || format == 0)
printf("warning\n");
if(fill)
printf("warning\n");
-
+
if(len % 4)
printf("warning\n");
*/
-
+
if(data)
{
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(desktopX != x || desktopY != y || desktopW != w || desktopH != h)
{
- guiApp.SetDesktopPosition(x, y, w, h, updateChildren);
- desktopX = x;
- desktopY = y;
- desktopW = w;
- desktopH = h;
+ bool skip = false;
+ // Don't change the desktop area if another fullscreen application is running
+ // (Attemps to solve the debugging IDE being re-activated while switching debugged app between fullscreen/windowed on Cinnamon)
+ if(XGetWindowProperty(xGlobalDisplay, x_root, atoms[_net_active_window], 0, 32,
+ False, AnyPropertyType, &type, &format, &len,
+ &fill, &data) == Success && data)
+ {
+ X11Window active = *(long *)data;
+ XFree(data);
+ if(XGetWindowProperty(xGlobalDisplay, active, atoms[_net_wm_state], 0, 32, False,
+ XA_ATOM, &type, &format, &len, &fill, &data) == Success)
+ {
+ Atom * values = (Atom *) data;
+ int i;
+ for (i = 0; i < len; i++)
+ {
+ if(values[i] == atoms[_net_wm_state_fullscreen])
+ {
+ skip = true;
+ break;
+ }
+ }
+ XFree(data);
+ }
+ }
+ if(w && h && !skip)
+ {
+ guiApp.SetDesktopPosition(x, y, w, h, updateChildren);
+ desktopX = x;
+ desktopY = y;
+ desktopW = w;
+ desktopH = h;
+ }
}
}
Key code;
unichar ch = 0;
KeySym keysym = NoSymbol;
- Status status;
int buflength = 0;
static long bufsize = 16;
static char *buf = NULL;
/*
key = key - 8;
//Logf("Got 0x%x (%d)\n", key, key);
-
+
switch(key)
{
case KEYCODE_HOME: key = home; break;
case KEYCODE_DEL: key = del; break;
case KEYCODE_SLASH: key = keyPadSlash; break;
}
-
+
ch = (byte)Interface::TranslateKey(key, event->state & ShiftMask);
*/
/*
*/
if(!buf)
- buf = malloc(bufsize);
- if(windowData && windowData.ic)
- {
- buflength = XmbLookupString(windowData.ic, event, buf, bufsize, &keysym, &status);
- if (status == XBufferOverflow)
+ buf = malloc((uint)bufsize);
+
+ // TOCHECK: X*LookupString man page says we shouldn't invoke it for non KeyPress events
+ if(windowData && windowData.ic) // && event->type == KeyPress)
+ {
+ Status status;
+#ifdef X_HAVE_UTF8_STRING
+ #define LookupString Xutf8LookupString
+#else
+ #define LookupString XmbLookupString
+#endif
+ buflength = LookupString(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 = LookupString(windowData.ic, event, buf, (int)bufsize, &keysym, &status);
}
if(status != XLookupKeySym && status != XLookupBoth && release == 1)
keysym = XLookupKeysym(event, 0);
// case XK_Begin:
// case XK_Select:
- // case XK_Print:
+ // case XK_Print:
// case XK_Execute:
case XK_Insert: key = insert; break;
// case XK_Undo:
// case XK_script_switch:
case XK_Num_Lock: key = numLock; break;
- // case XK_KP_Space:
+ // case XK_KP_Space:
// case XK_KP_Tab:
case XK_KP_Enter: key = keyPadEnter; break;
// case XK_KP_F1:
case XK_KP_Add: key = keyPadPlus; break;
case XK_KP_Separator:key = keyPadDelete; break;
case XK_KP_Subtract: key = keyPadMinus; break;
- // case XK_KP_Decimal:
+ // case XK_KP_Decimal:
case XK_KP_Divide: key = keyPadSlash; break;
case XK_KP_0: key = keyPad0; break;
case XK_Control_L: key = leftControl; break;
case XK_Control_R: key = rightControl; break;
case XK_Caps_Lock: key = capsLock; break;
- // case XK_Shift_Lock:
+ // case XK_Shift_Lock:
// case XK_Meta_L:
// case XK_Meta_R:
case XK_Alt_L: key = leftAlt; break;
}
if(!windowData.ic)
{
- ch = (byte)Interface::TranslateKey(key, event->state & ShiftMask);
+ ch = (byte)Interface::TranslateKey(key, (event->state & ShiftMask) != 0);
// 127 is delete, we don't treat that as a character (Use (SmartKey)key == del)
if(ch == 128 || ch == 127) ch = 0;
}
if(key != leftControl && key != rightControl && event->state & ControlMask)
code.ctrl = true;
if(key != leftAlt && key != rightAlt && event->state & Mod1Mask)
+ {
+ if(fullScreenMode && key == tab)
+ {
+ XUngrabKeyboard(xGlobalDisplay, CurrentTime);
+ guiApp.SetAppFocus(false);
+ SetNETWMState((X11Window)window.windowHandle, true, remove, atoms[_net_wm_state_fullscreen], 0);
+ XIconifyWindow(xGlobalDisplay, (X11Window)window.windowHandle, DefaultScreen(xGlobalDisplay));
+ if(acquiredInputWindow)
+ XInterface::SetMousePosition(guiApp.acquiredMouseX, guiApp.acquiredMouseY);
+ }
code.alt = true;
+ }
#ifdef __APPLE__
if(key != leftAlt && key != rightAlt && event->state & (1<<13))
code.alt = true;
/*buflength = 0;
ch = 0;*/
- }
+ }
#endif
// Logf("Key Message: %s, keysym: 0x%x, key: %d state: %d, ch: %c\n", release ? ((release == 2) ? "REPEAT" : "KeyRelease") : "KeyPress", keysym, key, event->state, (byte)ch);
if(release == 1)
{
int numBytes;
+
+ if(key < KeyCode::enumSize)
+ keyStates[key] = false;
if(windowData && windowData.ic) ch = buflength ? UTF8GetChar(buf, &numBytes) : 0;
if(ch == 127) ch = 0;
// printf("Release! %d %d %d\n", keysym, code, ch);
int c;
if(release == 0)
{
+ if(key < KeyCode::enumSize)
+ keyStates[key] = true;
+
if(windowData.ic && buflength)
{
for(c = 0; c<buflength;)
int numBytes;
ch = UTF8GetChar(buf + c, &numBytes);
if(ch == 127) ch = 0;
- if(!numBytes) c = buflength;
- result = window.KeyMessage((c == 0) ?
+ 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);
- }
+ }
}
delete window;
-
+
return result;
}
/*
}
*/
-static Bool EventChecker(void *display, XEvent *event, char * data)
+static X11Bool EventChecker(void *display, XEvent *event, char * data)
{
- return (!data || (event->type == (int) data)) && event->type != NoExpose && event->type != GraphicsExpose;
+ return (!data || (event->type == (int)(intptr_t) data)) && event->type != NoExpose && event->type != GraphicsExpose;
}
-static Bool ConfigureNotifyChecker(void *display, XConfigureEvent *event, char * data)
+static X11Bool 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 X11Bool FocusInChecker(void *display, XFocusChangeEvent *event, char * data)
+{
+ X11Bool result = False;
+ if(event->type == FocusIn)
+ {
+ Window window = null;
+ // --- This deadlocks and I think Xorg should fix this.
+ // XFindContext(xGlobalDisplay, event->window, windowContext, (XPointer *) &window);
+ if((X11Window)guiApp.desktop.windowHandle == event->window)
+ window = guiApp.desktop;
+ else
+ {
+ for(window = guiApp.desktop.firstChild; window; window = window.next)
+ if((X11Window)window.windowHandle == event->window)
+ break;
+ }
+ if(window)
+ result = True;
+ }
+ return result;
}
+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)
//bool waitSemaphore = false;
fd_set readSet, writeSet, exceptSet;
struct timeval tv = { (timerDelay == MAXINT) ? 0 : (timerDelay / 1000000), (timerDelay == MAXINT) ? (int)(1000000 / 18.2) : (timerDelay % 1000000) };
-
+
if(xTerminate) break;
FD_ZERO(&readSet);
FD_ZERO(&writeSet);
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();
+ guiApp.SignalEvent();
xSemaphore.Wait();
#if 0
char buffer[1024];
if(xGlobalDisplay)
XGetErrorText(xGlobalDisplay, event->error_code, buffer, sizeof(buffer));
+#ifdef _DEBUG
Logf("X Error: %s\n", buffer);
+#endif
return 0;
}
//int attempts = 0;
//Logf("Wait for viewable %s\n", window.name);
XFlush(xGlobalDisplay);
- //while(attempts++ < 40)
+ //while(attempts++ < 40)
while(true)
{
XWindowAttributes attributes = { 0 };
- int result;
if(!XGetWindowAttributes(xGlobalDisplay, (X11Window)window.windowHandle, &attributes))
break;
if(attributes.map_state == IsViewable)
}
}
+static bool RequestFrameExtents(X11Window windowHandle)
+{
+ if(frameExtentSupported != broken)
+ {
+ // Request decoration frame extents
+ XClientMessageEvent event = { 0 };
+ event.type = ClientMessage;
+ event.message_type = atoms[_net_request_frame_extents];
+ event.display = xGlobalDisplay;
+ event.serial = 0;
+ event.window = windowHandle;
+ event.send_event = 1;
+ event.format = 32;
+
+ if(frameExtentSupported == unknown && !frameExtentRequest)
+ {
+ frameExtentRequest = GetTime();
+ frameExtentWindow = windowHandle;
+ }
+
+ XSendEvent(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), bool::false,
+ SubstructureRedirectMask | SubstructureNotifyMask, (union _XEvent *)&event);
+ return true;
+ }
+ return false;
+}
+
+static bool GetFrameExtents(Window window, bool update)
+{
+ XWindowData windowData = window.windowData;
+ bool result = false;
+ int format;
+ unsigned long len, fill;
+ Atom type;
+ byte * data = null;
+
+ if(XGetWindowProperty(xGlobalDisplay, (X11Window)window.windowHandle,
+ atoms[_net_frame_extents], 0, 4,
+ False, XA_CARDINAL, &type, &format, &len,
+ &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;
+ Box oldDecor = windowData.decor;
+
+ frameExtentSupported = working;
+ frameExtentWindow = 0;
+ frameExtentRequest = 0;
+
+ if(!hadFrameExtents || extents[0] || extents[1] || extents[2] || extents[3])
+ {
+ windowData.decor =
+ {
+ left = (int)extents[0], right = (int)extents[1],
+ top = (int)extents[2], bottom = (int)extents[3]
+ };
+ windowData.gotFrameExtents = true;
+ if(update && change && ((Window)window).clientSize.w > 0)
+ {
+ 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);
+ XInterface::UpdateRootWindow(window);
+ }
+ }
+ result = true;
+ }
+ XFree(data);
+ }
+ return result;
+}
+
+static bool WaitForFrameExtents(Window window, bool update)
+{
+ int attempts = 0;
+ //XFlush(xGlobalDisplay);
+ while(attempts++ < 40)
+ {
+ if(GetFrameExtents(window, update)) return true;
+ Sleep(1.0 / RESOLUTION);
+ }
+ return false;
+}
+
/****************************************************************************
/// DRIVER IMPLEMENTATION /////////////
****************************************************************************/
{
bool terminate;
uint delay;
-
+
void Stop()
{
if(started)
Wait();
}
}
-
+
uint Main()
{
while(!terminate)
}
/*
struct shmid_ds info;
- int maxid = shmctl (0, SHM_INFO, &info);
+ int maxid = shmctl (0, SHM_INFO, &info);
int pid = getpgrp();
int thisPid = getpid();
//if(thisPid == pid)
if(maxid >= 0)
{
int id;
- for(id = 0; id <= maxid; id++)
+ for(id = 0; id <= maxid; id++)
{
- struct shmid_ds shmseg;
+ struct shmid_ds shmseg;
int shmid;
- if((shmid = shmctl(id, SHM_STAT, &shmseg)) >= 0)
+ if((shmid = shmctl(id, SHM_STAT, &shmseg)) >= 0)
{
if(shmseg.shm_cpid == pid || shmseg.shm_cpid == thisPid)
{
guiApp.desktop.Destroy(0);*/
}
+static void X11UpdateState(Window window, bool * unmaximized)
+{
+ if(atomsSupported[_net_wm_state]) //window.nativeDecorations)
+ {
+ int format;
+ unsigned long len, fill;
+ Atom type;
+ byte * data = null;
+ if(XGetWindowProperty(xGlobalDisplay, (X11Window)window.systemHandle, atoms[_net_wm_state], 0, 32, False,
+ XA_ATOM, &type, &format, &len, &fill, &data) == Success)
+ {
+ bool maxVert = false, maxHorz = false, isMinimized = false;
+ Atom * hints = (Atom *)data;
+ int c;
+ for(c = 0; c < len && hints[c]; c++)
+ {
+ if(hints[c] == atoms[_net_wm_state_maximized_vert])
+ maxVert = true;
+ else if(hints[c] == atoms[_net_wm_state_maximized_horz])
+ maxHorz = true;
+ else if(hints[c] == atoms[_net_wm_state_hidden])
+ isMinimized = true;
+ }
+ XFree(data);
+
+ if(maxVert && maxHorz)
+ {
+ if(window.state != maximized)
+ {
+ *&window.state = maximized;
+ if(!window.nativeDecorations)
+ window.CreateSystemChildren();
+ }
+ }
+ else if(isMinimized)
+ {
+ if(window.state != minimized)
+ {
+ *&window.state = minimized;
+ if(!window.nativeDecorations)
+ window.CreateSystemChildren();
+ }
+ }
+ else if(window.state != normal)
+ {
+ if(unmaximized && window.state == maximized)
+ *unmaximized = true;
+ *&window.state = normal;
+ if(!window.nativeDecorations)
+ window.CreateSystemChildren();
+ }
+ }
+ }
+}
+
class XInterface : Interface
{
class_property(name) = "X";
xTerminate = false;
xGlobalDisplay = XOpenDisplay(null);
- joystickFD[0] = open("/dev/js0", O_RDONLY);
+#if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__)
+ if(xGlobalDisplay)
+ XLockDisplay(xGlobalDisplay);
+#endif
+
+ // XSynchronize(xGlobalDisplay, True);
+ frameExtentSupported = unknown;
+
+ joystickFD[0] = open("/dev/js0", O_RDONLY);
joystickFD[1] = open("/dev/js1", O_RDONLY);
joystickFD[2] = open("/dev/js2", O_RDONLY);
joystickFD[3] = open("/dev/js3", O_RDONLY);
-
+
if(xGlobalDisplay)
{
XWindowAttributes attributes = { 0 };
+
+ systemCursors[iBeam] = XCreateFontCursor(xGlobalDisplay, XC_xterm);
+ systemCursors[cross] = XCreateFontCursor(xGlobalDisplay, XC_tcross);
+ systemCursors[moving] = XCreateFontCursor(xGlobalDisplay, XC_fleur);
+ systemCursors[sizeNESW] = XCreateFontCursor(xGlobalDisplay, XC_bottom_left_corner);
+ systemCursors[sizeNS] = XCreateFontCursor(xGlobalDisplay, XC_sb_v_double_arrow);
+ systemCursors[sizeNWSE] = XCreateFontCursor(xGlobalDisplay, XC_bottom_right_corner);
+ systemCursors[sizeWE] = XCreateFontCursor(xGlobalDisplay, XC_sb_h_double_arrow);
+ systemCursors[hand] = XCreateFontCursor(xGlobalDisplay, XC_hand2);
+ systemCursors[arrow] = XCreateFontCursor(xGlobalDisplay, XC_left_ptr);
+
XGetWindowAttributes(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), &attributes);
xSystemDepth = attributes.depth;
xSystemVisual = attributes.visual;
{
XVisualInfo vinfo;
XVisualInfo *vinfo_ret;
- long numitems;
-
+ int numitems = 0;
+
vinfo.visualid = XVisualIDFromVisual(xSystemVisual);
vinfo_ret = XGetVisualInfo(xGlobalDisplay, VisualIDMask, &vinfo, &numitems);
if(numitems)
else
printf("Could not get a 555 visual\n");
*/
- }
+ }
break;
}
}
// printf("Got a depth of %d\n", xSystemDepth);
- {
+ {
int major, minor, pixmaps;
xSharedMemory = XShmQueryExtension(xGlobalDisplay) && XShmQueryVersion(xGlobalDisplay, &major, &minor, &pixmaps) && pixmaps;
- }
+ }
// printf("Opening IM\n");
im = XOpenIM(xGlobalDisplay, null, null, null);
Pixmap mask = XCreatePixmap(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), 1, 1, 1);
XSetWindowAttributes attributes = { 0 };
- XkbSetDetectableAutoRepeat(xGlobalDisplay, True, &autoRepeatDetectable);
+ XkbSetDetectableAutoRepeat(xGlobalDisplay, True, (int *)&autoRepeatDetectable);
XInternAtoms(xGlobalDisplay, (char**)atomNames, AtomIdents::enumSize, False, atoms);
-
+
+ // Check which atoms are supported by the WM
{
- Atom protocols[2] = { atoms[wm_delete_window], atoms[wm_take_focus] };
+ int format;
+ unsigned long count, fill;
+ Atom type;
+ Atom * data;
- XSetWMProtocols(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), protocols, 2);
+ if(XGetWindowProperty(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), atoms[_net_supported],
+ 0, 10000, False, XA_ATOM, &type, &format, &count, &fill, (void *)&data) == Success)
+ {
+ int i;
+ for (i = 0; i < count; i++)
+ {
+ AtomIdents j;
+ for(j = 0; j < AtomIdents::enumSize; j++)
+ {
+ if(atoms[j] == data[i])
+ {
+ atomsSupported[j] = true;
+ break;
+ }
+ }
+ }
+ XFree(data);
+ }
}
/*
- if(atoms[_net_workarea] == None)
+ if(atomsSupported[_net_workarea])
printf("Warning: _NET_WORKAREA extension not supported\n");
*/
/*
XIMStyles *IMcando;
- XIMStyle clientCanDo;
+ XIMStyle clientCanDo;
XIMStyle styleWeWillUse = null;
int i;
XVaNestedList arglist;
XIMPreeditPosition | XIMStatusArea |
XIMPreeditArea | XIMStatusArea |
XIMPreeditNothing | XIMStatusNothing;
-
+
for(i=0; i<IMcando->count_styles; i++)
{
XIMStyle tmpStyle;
XSetICFocus(ic);
*/
}
-
+
xMutex.Wait();
timerThread = Thread { };
incref timerThread;
timerThread.Create();
return true;
- }
+ }
}
return false;
}
void Terminate()
{
- XEvent e = { 0 };
+ //XEvent e = { 0 };
xTerminate = true;
// WHY WAS THIS COMMENTED HERE?
delete timerThread;
hiResTimer.Stop();
+ XFreeCursor(xGlobalDisplay, systemCursors[iBeam]);
+ XFreeCursor(xGlobalDisplay, systemCursors[cross]);
+ XFreeCursor(xGlobalDisplay, systemCursors[moving]);
+ XFreeCursor(xGlobalDisplay, systemCursors[sizeNESW]);
+ XFreeCursor(xGlobalDisplay, systemCursors[sizeNS]);
+ XFreeCursor(xGlobalDisplay, systemCursors[sizeNWSE]);
+ XFreeCursor(xGlobalDisplay, systemCursors[sizeWE]);
+ XFreeCursor(xGlobalDisplay, systemCursors[hand]);
+ XFreeCursor(xGlobalDisplay, systemCursors[arrow]);
+
//XPutBackEvent(xGlobalDisplay, &e);
// xThread.Wait();
// delete xThread;
case KeyPress:
{
XKeyEvent * event = (XKeyEvent *) thisEvent;
+ incref window;
+ timeStamp = event->time;
+ if(!window.active)
+ {
+ Window modalRoot = window.FindModal();
+ XWindowData windowData;
+
+ activeWindow = (X11Window)window.windowHandle;
+
+ if(!window.parent || window != window.parent.activeChild)
+ {
+ if(modalRoot)
+ modalRoot.ExternalActivate(true, true, window, null);
+ 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, NULL);
+ XSetICFocus(windowData.ic);
+ }
+ }
+ }
//*XUnlockDisplay(xGlobalDisplay);
ProcessKeyMessage(window, event->keycode, (event->keycode == lastKeyCode) ? 2 : 0, event);
//*if(xGlobalDisplay) XLockDisplay(xGlobalDisplay);
lastKeyCode = event->keycode;
+ delete window;
break;
}
case KeyRelease:
XKeyEvent * event = (XKeyEvent *) thisEvent;
XEvent nextEvent;
lastKeyCode = 0;
+ timeStamp = event->time;
if(!autoRepeatDetectable && XCheckIfEvent(xGlobalDisplay, (XEvent *)&nextEvent, EventChecker, (void *)KeyPress))
{
if(im && XFilterEvent(&nextEvent, None))
static Point lastPos[3];
Modifiers keyFlags = 0;
- bool doubleClick;
- uint button, buttonDouble, whichButton;
- uint buttonMask;
+ bool doubleClick = false;
+ uint button = 0, buttonDouble = 0, whichButton;
+ uint buttonMask = 0;
int x = event->x_root, y = event->y_root;
-
+ timeStamp = event->time;
if(event->button == Button1)
{
+ // Force a raise on click here to deal with confused active state preventing to bring the window up
+ if(!fullScreenMode)
+ {
+ if(!atomsSupported[_net_active_window] && !window.isRemote)
+ XRaiseWindow(xGlobalDisplay, (X11Window)window.windowHandle);
+ XSetInputFocus(xGlobalDisplay, (X11Window)window.windowHandle, RevertToParent, CurrentTime);
+ }
button = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown;
buttonDouble = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick;
whichButton = 0;
buttonMask = Button1Mask;
keyFlags.left = true;
+ buttonsState.left = true;
}
else if(event->button == Button3)
{
whichButton = 2;
buttonMask = Button3Mask;
keyFlags.right = true;
+ buttonsState.right = true;
}
- else
+ else if(event->button == Button2)
{
button = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown;
buttonDouble = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick;
whichButton = 1;
buttonMask = Button2Mask;
keyFlags.middle = true;
+ buttonsState.middle = true;
}
if(event->state & buttonMask)
break;
- doubleClick = event->time - lastTime[whichButton] < DBLCLICK_DELAY &&
- window == lastWindow[whichButton] &&
- Abs(event->x_root - lastPos[whichButton].x) < DBLCLICK_DELTA &&
- Abs(event->y_root - lastPos[whichButton].y) < DBLCLICK_DELTA;
- lastTime[whichButton] = doubleClick ? 0 : event->time;
- lastWindow[whichButton] = window;
- lastPos[whichButton].x = event->x_root;
- lastPos[whichButton].y = event->y_root;
+ if(buttonMask)
+ {
+ doubleClick = event->time - lastTime[whichButton] < DBLCLICK_DELAY &&
+ window == lastWindow[whichButton] &&
+ Abs(event->x_root - lastPos[whichButton].x) < DBLCLICK_DELTA &&
+ Abs(event->y_root - lastPos[whichButton].y) < DBLCLICK_DELTA;
+ lastTime[whichButton] = doubleClick ? 0 : event->time;
+ lastWindow[whichButton] = window;
+ lastPos[whichButton].x = event->x_root;
+ lastPos[whichButton].y = event->y_root;
+ }
if(event->state & ShiftMask) keyFlags.shift = true;
if(event->state & ControlMask) keyFlags.ctrl = true;
incref window;
if(event->button == Button4 || event->button == Button5)
{
- window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit, (event->button == Button4) ? wheelUp : wheelDown, 0);
+ window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit, { modifiers = keyFlags, code = (event->button == Button4) ? wheelUp : wheelDown }, 0);
}
- else
+ else if(button)
{
if(doubleClick)
{
{
button = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp;
buttonMask = Button1Mask;
+ buttonsState.left = false;
}
else if(event->button == Button3)
{
button = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp;
buttonMask = Button3Mask;
+ buttonsState.right = false;
}
else
{
button = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp;
buttonMask = Button2Mask;
+ buttonsState.middle = false;
}
+ timeStamp = event->time;
if(!(event->state & buttonMask)) break;
if(event->state & ShiftMask) keyFlags.shift = true;
if(event->state & ControlMask) keyFlags.ctrl = true;
break;
}
case MotionNotify:
- {
- static uint lastTime = 0;
+ {
+ //static uint lastTime = 0;
XMotionEvent * event = (XMotionEvent *) thisEvent;
while(XCheckIfEvent(xGlobalDisplay, (XEvent *)thisEvent, EventChecker, (void *)MotionNotify));
// if(event->time - lastTime > 15)
{
Modifiers keyFlags = 0;
+ timeStamp = event->time;
// int x = event->x_root, y = event->y_root;
if(event->state & ShiftMask) keyFlags.shift = true;
if(event->state & Button3Mask) keyFlags.right = true;
//*XUnlockDisplay(xGlobalDisplay);
incref window;
+ if(window == acquiredInputWindow)
+ {
+ lastMouse.x = event->x_root;
+ lastMouse.y = event->y_root;
+ }
window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove,
event->x_root, event->y_root, &keyFlags, false, false);
delete window;
//*if(xGlobalDisplay) XLockDisplay(xGlobalDisplay);
- lastTime = event->time;
+ //lastTime = (uint)event->time;
}
break;
}
{
XExposeEvent * event = (XExposeEvent *) thisEvent;
Box box;
- box.left = event->x - window.clientStart.x;
- box.top = event->y - window.clientStart.y;
+ box.left = event->x;
+ box.top = event->y;
box.right = box.left + event->width - 1;
box.bottom = box.top + event->height - 1;
- window.Update(box);
- box.left += window.clientStart.x;
- box.top += window.clientStart.y;
- box.right += window.clientStart.x;
- box.bottom += window.clientStart.y;
window.UpdateDirty(box);
break;
}
case SelectionRequest:
{
- XSelectionRequestEvent *req = (XSelectionRequestEvent *) thisEvent;
- XEvent respond;
- if(req->target == atoms[targets] && clipBoardData)
+ XSelectionRequestEvent *req = (XSelectionRequestEvent *) thisEvent;
+ XEvent respond;
+ if(req->target == atoms[targets] && clipBoardData)
{
Atom * supportedTargets = new Atom[4];
supportedTargets[0] = atoms[targets];
supportedTargets[2] = XA_STRING;
supportedTargets[3] = atoms[utf8_string];
XChangeProperty(xGlobalDisplay,req->requestor, req->_property,
- XA_ATOM,32,PropModeReplace, (byte *) supportedTargets, 4*sizeof(Atom));
+ XA_ATOM,32,PropModeReplace, (byte *) supportedTargets, 4*sizeof(Atom));
respond.xselection._property = req->_property;
delete supportedTargets;
}
else if((req->target == XA_STRING || req->target == atoms[utf8_string]) && clipBoardData)
- {
+ {
Atom _property = (req->_property == None) ? req->target : req->_property;
- XChangeProperty(xGlobalDisplay,req->requestor, _property,
- req->target/*req->_property*/,8,PropModeReplace, (byte *) clipBoardData, strlen(clipBoardData));
- respond.xselection._property = _property;
- }
+ XChangeProperty(xGlobalDisplay,req->requestor, _property,
+ req->target/*req->_property*/,8,PropModeReplace, (byte *) clipBoardData, strlen(clipBoardData));
+ respond.xselection._property = _property;
+ }
else
- respond.xselection._property = None;
-
+ respond.xselection._property = None;
+
respond.xselection.type = SelectionNotify;
- respond.xselection.display = req->display;
- respond.xselection.requestor = req->requestor;
- respond.xselection.selection =req->selection;
- respond.xselection.target = req->target;
- respond.xselection.time = CurrentTime;
- XSendEvent(xGlobalDisplay, req->requestor,0,0,&respond);
+ respond.xselection.display = req->display;
+ respond.xselection.requestor = req->requestor;
+ respond.xselection.selection =req->selection;
+ respond.xselection.target = req->target;
+ respond.xselection.time = CurrentTime;
+ XSendEvent(xGlobalDisplay, req->requestor,0,0,&respond);
break;
}
case SelectionClear:
}
case FocusIn:
{
- XFocusChangeEvent *event = (XFocusChangeEvent *) thisEvent;
- Window modalRoot = window.FindModal();
- XWindowData windowData;
- activeWindow = (X11Window)window.windowHandle;
+ lastMouse = acquireStart;
- if(window.parent && window == window.parent.activeChild) break;
- incref window;
- //if(window.creationActivation == activate)
+ guiApp.SetAppFocus(true);
+
+ X11UpdateState(window, null);
+
+ if(fullScreenMode)
{
- 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(acquiredInputWindow)
+ {
+ GetMousePosition(&guiApp.acquiredMouseX, &guiApp.acquiredMouseY);
+ lastMouse = { window.size.w/2, window.size.h/2 };
+ SetMousePosition(lastMouse.x, lastMouse.y);
+ }
+ XRaiseWindow(xGlobalDisplay, (X11Window)window.windowHandle);
+ SetNETWMState((X11Window)window.windowHandle, true, add, atoms[_net_wm_state_fullscreen], 0);
+ XGrabKeyboard(xGlobalDisplay, (X11Window)window.windowHandle, False, GrabModeAsync, GrabModeAsync, CurrentTime);
+ XSetInputFocus(xGlobalDisplay, (X11Window)window.windowHandle, RevertToParent, timeStamp);
+ XInterface::UpdateRootWindow(window);
+ break;
+ }
+
+ if(activeWindow != (X11Window)window.windowHandle)
{
- // XSetICValues(ic, XNClientWindow, window.windowHandle, XNFocusWindow, window.windowHandle, 0);
- XSetICFocus(windowData.ic);
+ Window modalRoot = window.FindModal();
+ XWindowData windowData;
+
+ activeWindow = (X11Window)window.windowHandle;
+
+ if(window.parent && window == window.parent.activeChild) break;
+ incref window;
+ //if(window.creationActivation == activate && guiApp.desktop.active)
+ {
+ 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, NULL);
+ XSetICFocus(windowData.ic);
+ }
+ //delete lastActive;
+ //lastActive = window;
+ //incref lastActive;
+ delete window;
}
- //delete lastActive;
- //lastActive = window;
- //incref lastActive;
- delete window;
break;
}
case FocusOut:
//printf("Processing a FocusOut Event for %s (%x)\n", window._class.name, window);
#endif
+ /*
if(XCheckTypedWindowEvent(xGlobalDisplay, thisEvent->window, FocusIn, (XEvent *)thisEvent))
{
break;
}
+ */
+
+ if(XCheckIfEvent(xGlobalDisplay, (XEvent *)thisEvent, (void *)FocusInChecker, null))
+ {
+ if(!fullScreenMode)
+ XPutBackEvent(xGlobalDisplay, (XEvent *)thisEvent);
+ break;
+ }
+
+
+ if(fullScreenMode || (X11Window)window.windowHandle == activeWindow)
+ guiApp.SetAppFocus(false);
+
+ if(fullScreenMode)
+ {
+ //XUngrabKeyboard(xGlobalDisplay, CurrentTime);
+ //SetNETWMState((X11Window)window.windowHandle, true, remove, atoms[_net_wm_state_fullscreen], 0);
+ //XIconifyWindow(xGlobalDisplay, (X11Window)window.windowHandle, DefaultScreen(xGlobalDisplay));
+ break;
+ }
+
if(thisEvent->window == activeWindow)
activeWindow = (X11Window)null;
#if 0
if(XCheckTypedWindowEvent(xGlobalDisplay, thisEvent->window, FocusOut, (XEvent *)thisEvent))
{
XFocusChangeEvent *event = (XFocusChangeEvent *) thisEvent;
-
+
XFindContext(xGlobalDisplay, thisEvent->window, windowContext, (XPointer *) &window);
if(window)
{
{
XWindowData windowData;
XFindContext(xGlobalDisplay, thisEvent->window, windowContext, (XPointer *) &window);
-
+
if(window)
{
XFocusChangeEvent *event = (XFocusChangeEvent *) thisEvent;
else
#endif
{
- XFocusChangeEvent *event = (XFocusChangeEvent *) thisEvent;
- if(window != window.parent.activeChild && window != guiApp.interimWindow) break;
+ if(window.parent && window != window.parent.activeChild && window != guiApp.interimWindow) break;
incref window;
#ifdef _DEBUG
{
XCheckTypedEvent(xGlobalDisplay, /*thisEvent->window, */ButtonPress, (XEvent *)thisEvent);
}
-
+
//delete lastActive;
/*
lastActive = window;
case ConfigureNotify:
{
XConfigureEvent * event = (XConfigureEvent *) thisEvent;
+ bool unmaximized = false;
+ bool um = false;
+ if(!window.visible || fullScreenMode) break;
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)
-
- // TODO: Support _NET_REQUEST_FRAME_EXTENTS message / _NET_FRAME_EXTENTS property for decoration size awareness
- if(window.nativeDecorations)
+ X11UpdateState(window, &um);
+ unmaximized = false;
{
- int format;
- unsigned long len, fill;
- Atom type;
- char * data = null;
- if(XGetWindowProperty(xGlobalDisplay, (X11Window)window.systemHandle, atoms[_net_wm_state], 0, 32, False,
- XA_ATOM, &type, &format, &len, &fill, &data) == Success)
+ bool offset = false;
+ int x, y, w, h;
+ if(unmaximized && window.nativeDecorations && ((BorderBits)window.borderStyle).fixed)
{
- bool maxVert = false, maxHorz = false, isMinimized = false;
- Atom * hints = (Atom *)data;
- int c;
- for(c = 0; c < len && hints[c]; c++)
- {
- if(hints[c] == atoms[_net_wm_state_maximized_vert])
- maxVert = true;
- else if(hints[c] == atoms[_net_wm_state_maximized_horz])
- maxHorz = true;
- else if(hints[c] == atoms[_net_wm_state_hidden])
- isMinimized = true;
- }
- XFree(data);
+ if(window.nativeDecorations && RequestFrameExtents((X11Window)window.windowHandle))
+ WaitForFrameExtents(window, false);
+
+ // Ensure we set the normal size anchor when un-maximizing
+ window.ComputeAnchors(window.normalAnchor, window.normalSizeAnchor, &x, &y, &w, &h);
+ }
+ else
+ {
+ x = event->x;
+ y = event->y;
+ w = event->width, h = event->height;
- if(maxVert && maxHorz)
+ //if(event->send_event)
{
- if(window.state != maximized)
- *&window.state = maximized;
+ X11Window rootChild;
+ int rootX, rootY;
+ XTranslateCoordinates(xGlobalDisplay, event->window,
+ RootWindow(xGlobalDisplay, DefaultScreen(xGlobalDisplay)), 0, 0,
+ &rootX, &rootY, &rootChild);
+
+ if(x != rootX || y != rootY)
+ {
+ if(!event->send_event)
+ {
+ // offset = true;
+ x = rootX;
+ y = rootY;
+ }
+ }
}
- else if(isMinimized)
+
+ x -= desktopX;
+ y -= desktopY;
+
+ if(window.nativeDecorations && window.state != maximized && ((BorderBits)window.borderStyle).fixed)
{
- if(window.state != minimized)
- *&window.state = minimized;
+ x -= windowData.decor.left;
+ y -= windowData.decor.top;
+ w += windowData.decor.left + windowData.decor.right;
+ h += windowData.decor.top + windowData.decor.bottom;
}
- else if(window.state != normal)
- *&window.state = normal;
- }
- }
- {
- int x = event->x;
- int y = event->y;
- int w = event->width, h = event->height;
-
- //if(event->send_event)
- {
- X11Window rootChild;
- long rootX, rootY;
- XTranslateCoordinates(xGlobalDisplay, event->window,
- RootWindow(xGlobalDisplay, DefaultScreen(xGlobalDisplay)), 0, 0,
- &rootX, &rootY, &rootChild);
- x = rootX;
- y = rootY;
}
- x -= desktopX;
- y -= desktopY;
+ window.Position(x, y, w, h, um, true, true, true, false, unmaximized);
- if(window.nativeDecorations)
+ // Break the anchors for moveable/resizable windows
+ // Avoid doing this if the translation wasn't in sync as it will cause the window to move around
+ if(!unmaximized && !offset && 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 + windowData.decor.left,
+ top = y + windowData.decor.top
+ };
+ window.normalSizeAnchor =
+ SizeAnchor { { window.clientSize.w, window.clientSize.h }, isClientW = true, isClientH = true };
}
- window.ExternalPosition(x, y, w, h);
}
break;
}
Window modalRoot;
XWindowData windowData;
bool laterFocus;
- activeWindow = (X11Window)window.windowHandle;
- timeStamp = event->data.l[1];
-
+ if(fullScreenMode)
+ {
+ XRaiseWindow(xGlobalDisplay, (X11Window)window.windowHandle);
+ XSetInputFocus(xGlobalDisplay, (X11Window)window.windowHandle, RevertToParent, timeStamp);
+ XGrabKeyboard(xGlobalDisplay, (X11Window)window.windowHandle, False, GrabModeAsync, GrabModeAsync, CurrentTime);
+ guiApp.SetAppFocus(true);
+ break;
+ }
+
+ //activeWindow = (X11Window)window.windowHandle;
+
+ timeStamp = (X11Time)event->data.l[1];
+
windowData = window.windowData;
laterFocus = windowData.laterFocus;
windowData.laterFocus = true;
if(guiApp.interimWindow && guiApp.interimWindow.created && window != guiApp.interimWindow) break; //window == window.parent.activeChild) break;
// if(window == window.parent.activeChild) break;
incref window;
-
+
{
XEvent checkEvent;
//XFlush(xGlobalDisplay);
XFocusChangeEvent *event = (XFocusChangeEvent *) &checkEvent;
Window window;
XFindContext(xGlobalDisplay, event->window, windowContext, (XPointer *) &window);
- if(window != window.parent.activeChild) break;
+ if(window.parent && window != window.parent.activeChild) break;
incref window;
#ifdef _DEBUG
}
}
+ lastMouse = acquireStart;
modalRoot = window.FindModal();
windowData = modalRoot ? modalRoot.windowData : window.windowData;
if(windowData)
{
XRaiseWindow(xGlobalDisplay, (X11Window)modalRoot.windowHandle);
WaitForViewableWindow(modalRoot);
- if(atoms[_net_active_window])
+ if(atomsSupported[_net_active_window])
{
XClientMessageEvent event = { 0 };
event.type = ClientMessage;
event.window = (X11Window)modalRoot.windowHandle;
event.send_event = 1;
event.format = 32;
- event.data.l[0] = 0;
+ event.data.l[0] = /*0*/ 1;
+ event.data.l[1] = timeStamp;
+ event.data.l[2] = activeWindow;
/*
- event.data.l[0] = 1;
- event.data.l[1] = atoms[_net_wm_user_time];
event.data.l[2] = activeWindow; //guiApp.desktop.activeChild.windowHandle;
*/
#ifdef _DEBUG
#endif
XSendEvent(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), bool::false, SubstructureRedirectMask | SubstructureNotifyMask, (union _XEvent *)&event);
- XSetInputFocus(xGlobalDisplay, (X11Window)modalRoot.windowHandle, RevertToPointerRoot, (uint)timeStamp);
+ XSetInputFocus(xGlobalDisplay, (X11Window)modalRoot.windowHandle, RevertToParent, timeStamp);
+ guiApp.SetAppFocus(true);
+ activeWindow = (X11Window)window.windowHandle;
//XFlush(xGlobalDisplay);
//printf("Done.\n");
}
else
{
- XSetInputFocus(xGlobalDisplay, (X11Window)window.windowHandle, RevertToPointerRoot, (uint)timeStamp);
- window.ExternalActivate(true, true, window, null); // lastActive);
+ XSetInputFocus(xGlobalDisplay, (X11Window)window.windowHandle, RevertToParent, timeStamp);
+ guiApp.SetAppFocus(true);
+ activeWindow = (X11Window)window.windowHandle;
+ window.ExternalActivate(true, true, window, null); // lastActive);
if(windowData && windowData.ic)
{
- // XSetICValues(ic, XNClientWindow, window.windowHandle, XNFocusWindow, window.windowHandle, 0);
+ // XSetICValues(ic, XNClientWindow, window.windowHandle, XNFocusWindow, window.windowHandle, NULL);
//XSetICFocus(windowData.ic);
}
}
{
XWindowData windowData = window.windowData;
XPropertyEvent * event = (XPropertyEvent *) thisEvent;
- if(event->atom == atoms[_net_frame_extents] &&
+ if(!fullScreenMode && event->atom == atoms[_net_frame_extents] &&
event->state == PropertyNewValue && windowData)
{
- int format;
- unsigned long len, fill;
- Atom type;
- char * data = null;
-
- if(XGetWindowProperty(xGlobalDisplay, (X11Window)window.windowHandle,
- atoms[_net_frame_extents], 0, 4,
- False, XA_CARDINAL, &type, &format, &len,
- &fill, &data) == Success && data)
- {
- long *extents = (long *)data;
- bool hadFrameExtents = windowData.gotFrameExtents;
- windowData.decor =
- {
- left = extents[0], right = extents[1],
- top = extents[2], bottom = extents[3]
- };
- windowData.gotFrameExtents = true;
- {
- int x, y, w, h;
- window.ComputeAnchors(
- window.normalAnchor,
- window.normalSizeAnchor,
- &x, &y, &w, &h);
- if(!hadFrameExtents) // || window.state == normal)
- {
- bool isMaximized = window.state == maximized;
- window.Position(x, y, w, h, true, true, true, true, false, true);
- UpdateRootWindow(window);
- }
- }
-
- XFree(data);
- }
- else
+ if(!GetFrameExtents(window, true))
windowData.gotFrameExtents = true; // Unsupported?
}
break;
//*XUnlockDisplay(xGlobalDisplay);
}
- char ** GraphicsDrivers(int * numDrivers)
+ const char ** GraphicsDrivers(int * numDrivers)
{
- static char *graphicsDrivers[] = { "X", "OpenGL" };
+ static const char *graphicsDrivers[] = { "X", "OpenGL" };
*numDrivers = sizeof(graphicsDrivers) / sizeof(char *);
- return (char **)graphicsDrivers;
+ return (const char **)graphicsDrivers;
}
void GetCurrentMode(bool * fullScreen, int * resolution, int * colorDepth, int * refreshRate)
}
else
{
- static bool firstTime = true;
- firstTime = false;
+ //static bool firstTime = true;
+ //firstTime = false;
desktopX = desktopY = desktopW = desktopH = 0;
RepositionDesktop(false);
XIC ic = null;
unsigned long mask = EVENT_MASK;
- attributes.override_redirect = window.interim ? True : False;
+ // Old WM (e.g. TWM), use built-in decorations
+ if(!atomsSupported[_net_wm_state])
+ window.nativeDecorations = false;
+ attributes.override_redirect = (window.interim || (!atomsSupported[_net_wm_state] && !window.nativeDecorations)) ? 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) && !defined(__ODROID__)
if(window.dispDriver == class(OpenGLDisplayDriver) || !strcmp(guiApp.defaultDisplayDriver, "OpenGL"))
{
int samples;
GLX_BLUE_SIZE, 1
};
int numAttribs = 14;
-
+
GLXFBConfig *fbconfigs = null, fbconfig;
int numfbconfigs;
int i;
}
if(!visualInfo)
{
- int attrList[] =
+ int attrList[] =
+ {
+ GLX_USE_GL, GLX_DEPTH_SIZE, 1,
+ GLX_RGBA,
+ GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ None
+ };
+ visualInfo = glXChooseVisual(xGlobalDisplay, DefaultScreen(xGlobalDisplay), attrList);
+ }
+#elif defined(__ODROID__)
+ if(!visualInfo)
+ {
+ // System visual not working on ODROID?
+ int attrList[] =
{
GLX_USE_GL, GLX_DEPTH_SIZE, 1,
- GLX_RGBA,
+ GLX_RGBA,
GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1,
- GLX_DOUBLEBUFFER,
+ GLX_DOUBLEBUFFER,
None
};
visualInfo = glXChooseVisual(xGlobalDisplay, DefaultScreen(xGlobalDisplay), attrList);
if(fullScreenMode)
{
- windowHandle = XCreateWindow(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay),
- 0,0,guiApp.desktop.size.w,guiApp.desktop.size.h,0, depth, InputOutput, visual ? visual : CopyFromParent,
- CWEventMask | (visual ? (CWColormap | CWBorderPixel) : 0)/*| CWOverrideRedirect*/, &attributes);
+ windowHandle = XCreateWindow(xGlobalDisplay,
+ DefaultRootWindow(xGlobalDisplay),
+ 0,0,
+ XDisplayWidth(xGlobalDisplay, DefaultScreen(xGlobalDisplay)),
+ XDisplayHeight(xGlobalDisplay, DefaultScreen(xGlobalDisplay)),
+ 0, depth, InputOutput, visual ? visual : CopyFromParent,
+ CWEventMask | (visual ? (CWColormap | CWBorderPixel) : 0) | CWOverrideRedirect,
+ &attributes);
+
+ {
+ XSizeHints hints = { 0 };
+ XSetWMNormalHints(xGlobalDisplay, windowHandle, &hints);
+ }
+
+ {
+ String caption = window.caption;
+ XChangeProperty(xGlobalDisplay, windowHandle, atoms[_net_wm_name],
+ atoms[utf8_string], 8, PropModeReplace, (byte *)window.caption, caption ? strlen(caption) : 0);
+ XChangeProperty(xGlobalDisplay, windowHandle, atoms[wm_name],
+ atoms[utf8_string], 8, PropModeReplace, (byte *)window.caption, caption ? strlen(caption) : 0);
+ }
+
+ SetNETWMState((X11Window)windowHandle, false, add, atoms[_net_wm_state_fullscreen], 0);
+ //SetNETWMState((X11Window)windowHandle, false, add, atoms[_net_wm_state_above], 0);
+ {
+ Atom hints[4];
+ int count;
+
+ hints[0] = atoms[_net_wm_window_type_normal];
+ count = 1;
+ XChangeProperty(xGlobalDisplay, windowHandle, atoms[_net_wm_window_type], XA_ATOM, 32,
+ PropModeReplace, (unsigned char*)&hints, count);
+ }
+
+ {
+ XWMHints xwmHints;
+ xwmHints.flags = InputHint;
+ xwmHints.input = 0;
+ XSetWMHints(xGlobalDisplay, windowHandle, &xwmHints);
+ }
+ {
+ Atom protocols[2] = { atoms[wm_delete_window], atoms[wm_take_focus] };
+ XSetWMProtocols(xGlobalDisplay, windowHandle, protocols, 2);
+ }
}
/*
Unsupported for now...
else
{
X11Window parentWindow = (X11Window)null;
+ 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);
+ MinMaxValue smw = 0, smh = 0;
+ MinMaxValue minW = window.minSize.w, minH = window.minSize.h;
+ window.OnResizing((int *)&minW, (int *)&minH);
+
+ // To fix jumping message boxes on Cinnamon:
+ if(window.state == normal && (minW > window.minSize.w || minH > window.minSize.w))
+ window.ComputeAnchors(window.normalAnchor, window.normalSizeAnchor, &x, &y, &w, &h);
+
+ window.SetWindowMinimum(&smw, &smh);
+ minW = Max(minW, smw);
+ minH = Max(minH, smh);
+
+ 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))
{
if(window.style.showInTaskBar)
parentWindow = (X11Window)null;
- windowHandle = XCreateWindow(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay),
- 0,0,1,1,0, depth, InputOutput, visual ? visual : CopyFromParent,
+ windowHandle = XCreateWindow(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay),
+ x, y, w, h,
+ 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)
+ SetNETWMState(windowHandle, false, add, atoms[_net_wm_state_modal], 0);
}
{
- Atom hints[2] =
+ Atom hints[4];
+ int count;
+ if(parentWindow && window.interim)
{
- parentWindow ? atoms[_net_wm_window_type_menu] : atoms[_net_wm_window_type_normal],
- parentWindow ? atoms[_net_wm_window_type_popup_menu] : 0
+ hints[0] = atoms[_net_wm_window_type_dropdown_menu];
+ hints[1] = atoms[_net_wm_window_type_popup_menu];
+ hints[2] = atoms[_net_wm_window_type_menu];
+ count = 3;
+ }
+ else if(parentWindow)
+ {
+ hints[0] = atoms[_net_wm_window_type_normal];
+ SetNETWMState(windowHandle, false, add, atoms[_net_wm_state_skip_taskbar], 0);
+
+ // Some WMs won't show a close button if dialog is set
+ // Additionally, this casues jumping of all dialog windows on Cinnamon
+ //hints[0] = atoms[_net_wm_window_type_dialog];
+ count = 1;
+ }
+ else
+ {
+ hints[0] = atoms[_net_wm_window_type_normal];
+ count = 1;
};
-#if defined(__APPLE__) || defined(__FreeBSD__)
- // Don't set this on non-interim windows for OS X...
- if(parentWindow && window.interim)
-#endif
+ XChangeProperty(xGlobalDisplay, windowHandle, atoms[_net_wm_window_type], XA_ATOM, 32,
+ PropModeReplace, (unsigned char*)&hints, count);
+
+ if(window.stayOnTop)
+ SetNETWMState((X11Window)windowHandle, false, add, atoms[_net_wm_state_above], 0);
- XChangeProperty(xGlobalDisplay, windowHandle, atoms[_net_wm_window_type], XA_ATOM, 32,
- PropModeReplace, (unsigned char*)&hints, parentWindow ? 2 : 1);
{
XWMHints xwmHints;
xwmHints.flags = InputHint;
Atom protocols[2] = { atoms[wm_delete_window], atoms[wm_take_focus] };
XSetWMProtocols(xGlobalDisplay, windowHandle, protocols, 2);
}
+
+ // Set Normal hints for minimum/maximum size
+ {
+ XSizeHints hints = { 0 };
+ hints.min_width = minW;
+ hints.min_height = minH;
+ hints.flags |= PMinSize;
+
+ if(window.maxSize.w < MAXINT || window.minSize.h < MAXINT)
+ {
+ hints.max_width = window.maxSize.w;
+ hints.max_height = window.maxSize.h;
+ hints.flags |= PMaxSize;
+ }
+ hints.x = x;
+ hints.y = y;
+ hints.flags |= PPosition;
+
+ hints.width = w;
+ hints.height = h;
+ hints.flags |= PSize;
+
+ XSetWMNormalHints(xGlobalDisplay, windowHandle, &hints);
+ }
}
}
}
int num_missing_charsets = 0;
char *default_string;
XFontSet fontset;
- XRectangle area = { 0, 0, 400, 400 };
+ //XRectangle area = { 0, 0, 400, 400 };
XVaNestedList argList;
// sprintf(fontString, "-*-%s-*-r-*-*-*-%d-*-*-*-*-*-*", "Helvetica" /*window.font.faceName*/, (int)(window.font.size * 20));
fontset = XCreateFontSet(xGlobalDisplay, fontString, &missing_charsets, &num_missing_charsets, &default_string);
argList = XVaCreateNestedList(0,
- XNSpotLocation, &cursor_location,
+ XNSpotLocation, &cursor_location,
//XNArea, &area,
XNFontSet, fontset,/*
XNForeground,
}
if(ic)
{
- XGetICValues(ic, XNFilterEvents, &mask, NULL);
- mask |= EVENT_MASK;
+ XGetICValues(ic, XNFilterEvents, &mask, NULL);
+ mask |= EVENT_MASK;
}
/*
XSelectInput(xGlobalDisplay, windowHandle, mask);
*/
{
- if ( atoms[_motif_wm_hints] != None )
+ if ( atoms[_motif_wm_hints] != None )
{
+ BorderBits borderBits = (BorderBits)window.borderStyle;
+ bool hasTitleBar = borderBits.fixed;
MWM_Hints hints
{
- (window.nativeDecorations ? 0 : MWM_HINTS_DECORATIONS)|MWM_HINTS_FUNCTIONS,
+ ((window.nativeDecorations && hasTitleBar) ? 0 : MWM_HINTS_DECORATIONS)|MWM_HINTS_FUNCTIONS,
(window.hasClose ? MWM_FUNC_CLOSE : 0) |
- (window.hasMaximize ? MWM_FUNC_MAXIMIZE : 0) |
- (window.hasMinimize ? MWM_FUNC_MINIMIZE : 0) |
- ((window.moveable || ((BorderBits)window.borderStyle).fixed) ? MWM_FUNC_MOVE : 0) |
- (((BorderBits)window.borderStyle).sizable ? MWM_FUNC_RESIZE : 0),
+ (fullScreenMode || window.hasMaximize ? MWM_FUNC_MAXIMIZE : 0) |
+ (fullScreenMode || window.hasMinimize ? MWM_FUNC_MINIMIZE : 0) |
+ ((fullScreenMode || window.moveable || hasTitleBar) ? MWM_FUNC_MOVE : 0) |
+ (fullScreenMode || borderBits.sizable ? MWM_FUNC_RESIZE : 0),
0, 0, 0
};
XChangeProperty(xGlobalDisplay, windowHandle, atoms[_motif_wm_hints], atoms[_motif_wm_hints], 32,
PropModeReplace, (unsigned char*)&hints, 5);
}
- if(atoms[_net_wm_pid] != None)
+
+ // *** We set this for ourselves, so don't check atomsSupported !!! ***
+ if(atoms[_net_wm_pid])
{
int pid = getpid();
- // printf("Setting _NET_WM_PID to %d\n", pid);
+ // printf("Setting _NET_WM_PID to %d\n", pid);
XChangeProperty(xGlobalDisplay, windowHandle, atoms[_net_wm_pid], XA_CARDINAL, 32,
- PropModeReplace, (unsigned char*)&pid, 1);
+ PropModeReplace, (unsigned char*)&pid, 1);
}
}
-
- /*
+
{
- Atom protocolsAtom = XInternAtom(xGlobalDisplay, "WM_PROTOCOLS", False);
- if ( protocolsAtom != None )
- {
- MWM_Hints hints = { MWM_HINTS_DECORATIONS|MWM_HINTS_FUNCTIONS, 0, 0, 0, 0 };
- XChangeProperty(xGlobalDisplay, windowHandle, atoms[_motif_wm_hints], atoms[_motif_wm_hints], 32,
- PropModeReplace, (unsigned char*)&hints, sizeof(hints)/4);
- }
- }*/
+ XWMHints wmHints = { 0 };
+ wmHints.input = True;
+ XSetWMHints(xGlobalDisplay, windowHandle, &wmHints);
+ }
+
// XFlush(xGlobalDisplay);
window.windowData = XWindowData { visualInfo, ic };
-
+
XSaveContext(xGlobalDisplay, windowHandle, windowContext, (XPointer)window);
XSelectInput(xGlobalDisplay, windowHandle, mask);
XUngrabPointer(xGlobalDisplay, CurrentTime);
}
- if(window.nativeDecorations)
+ if(fullScreenMode || !window.nativeDecorations || !((BorderBits)window.borderStyle).fixed || !RequestFrameExtents(windowHandle))
+ ((XWindowData)window.windowData).gotFrameExtents = true;
+
+ window.windowHandle = (void *)windowHandle;
+ if(window.state != maximized)
+ WaitForFrameExtents(window, true);
+
+ //GetFrameExtents(window, true);
+
+ if(fullScreenMode)
{
- // Maximize / Restore the window
- XClientMessageEvent event = { 0 };
- event.type = ClientMessage;
- event.message_type = atoms[_net_request_frame_extents];
- event.display = xGlobalDisplay;
- event.serial = 0;
- event.window = (X11Window)windowHandle;
- event.send_event = 1;
- window.windowHandle = (void *)windowHandle;
- event.format = 32;
- XSendEvent(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), bool::false,
- SubstructureRedirectMask | SubstructureNotifyMask, (union _XEvent *)&event);
+ XMapWindow(xGlobalDisplay, windowHandle);
+ XGrabKeyboard(xGlobalDisplay, windowHandle, False, GrabModeAsync, GrabModeAsync, CurrentTime);
}
return (void *)windowHandle;
}
void DestroyRootWindow(Window window)
{
XEvent event;
+ if(window == acquiredInputWindow)
+ delete acquiredInputWindow;
- XDeleteContext(xGlobalDisplay, (XID)window, windowContext);
+ XDeleteContext(xGlobalDisplay, (XID)window, windowContext);
XSaveContext(xGlobalDisplay, (X11Window)window.windowHandle, windowContext, null);
XDestroyWindow(xGlobalDisplay, (X11Window)window.windowHandle);
XSync(xGlobalDisplay, 0);
// -- Window manipulation ---
- void SetRootWindowCaption(Window window, char * name)
+ void SetRootWindowCaption(Window window, const char * name)
{
if(window.windowHandle)
{
atoms[utf8_string], 8, PropModeReplace, (byte *)name, name ? strlen(name) : 0);
XChangeProperty(xGlobalDisplay, (X11Window)window.windowHandle, atoms[wm_name],
atoms[utf8_string], 8, PropModeReplace, (byte *)name, name ? strlen(name) : 0);
- }
+ }
}
void PositionRootWindow(Window window, int x, int y, int w, int h, bool move, bool resize)
//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)
{
+ long t = (window.creationActivation == activate && guiApp.desktop.active) ? (int)timeStamp : 0;
+ XChangeProperty(xGlobalDisplay, (X11Window)window.windowHandle, atoms[_net_wm_user_time],
+ XA_CARDINAL,32,PropModeReplace, (byte *)&t, 1);
XMapWindow(xGlobalDisplay, (X11Window)window.windowHandle);
- WaitForViewableWindow(window);
}
-#endif
- if(window.state == minimized) return;
+ if(window.state == minimized && atomsSupported[_net_wm_state]) 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)
+ {
+ if(WaitForFrameExtents(window, false))
+ {
+ 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;
+
+ 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(!fullScreenMode && (!atomsSupported[_net_wm_state] || (window.state != maximized || !window.visible)))
+ {
+ 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);
+
+ // Reset min/max for fixed size windows on WMs not looking at MWM_FUNC_RESIZE (e.g. Cinnamon)
+ if(window.style.fixed && !window.style.sizable && window.state != maximized)
+ {
+ XSizeHints hints = { 0 };
+ long supplied;
+ XGetWMNormalHints(xGlobalDisplay, (X11Window)window.windowHandle, &hints, &supplied);
+ hints.min_width = hints.max_width = w;
+ hints.min_height = hints.max_height = h;
+ hints.flags |= PMinSize|PMaxSize;
+ XSetWMNormalHints(xGlobalDisplay, (X11Window)window.windowHandle, &hints);
+ }
}
- if(move && resize)
- XMoveResizeWindow(xGlobalDisplay, (X11Window)window.windowHandle, x + desktopX, y + desktopY, w, h);
- else if(move)
- XMoveWindow(xGlobalDisplay, (X11Window)window.windowHandle, x + desktopX, y + desktopY);
- else if(resize)
- XResizeWindow(xGlobalDisplay, (X11Window)window.windowHandle, w, h);
-#if defined(__APPLE__)
-// if(window.created && !visible)
- // XUnmapWindow(xGlobalDisplay, (X11Window)window.windowHandle);
-#endif
}
}
void OrderRootWindow(Window window, bool topMost)
{
-
+ SetNETWMState((X11Window)window.windowHandle, false, topMost ? add : remove, atoms[_net_wm_state_above], 0);
}
void SetRootWindowColor(Window window)
}
}
-
void SetRootWindowState(Window window, WindowState state, bool visible)
{
+ WindowState curState = window.state;
+ *&window.state = state;
+ // Old WM (e.g. TWM), use built-in decorations
+ if(!atomsSupported[_net_wm_state])
+ window.nativeDecorations = false;
if(!window.parent || !window.parent.display)
{
+ XWindowData windowData = window.windowData;
//Logf("Set root window state %d %s\n", state, window.name);
if(visible)
{
- XMapWindow(xGlobalDisplay, (X11Window)window.windowHandle);
-#if defined(__APPLE__) || defined(__FreeBSD__)
- WaitForViewableWindow(window);
-#endif
- if(window.creationActivation == activate && state != minimized)
- ActivateRootWindow(window);
-
- if(state == minimized)
+ if(!windowData.currentlyVisible)
{
- uint iconic = IconicState;
- /*
- XChangeProperty(xGlobalDisplay, window.windowHandle, atoms[_net_wm_state], XA_ATOM, 32,
- PropModeReplace, (unsigned char*)&atoms[_net_wm_state_hidden], 1);
- */
+ long t = (window.creationActivation == activate && guiApp.desktop.active) ? timeStamp : 0;
+ XChangeProperty(xGlobalDisplay, (X11Window)window.windowHandle, atoms[_net_wm_user_time],
+ XA_CARDINAL,32,PropModeReplace, (byte *)&t, 1);
+ XMapWindow(xGlobalDisplay, (X11Window)window.windowHandle);
+ windowData.currentlyVisible = true;
+ WaitForViewableWindow(window);
+ if(window.creationActivation == activate && guiApp.desktop.active && state != minimized)
+ ActivateRootWindow(window);
+ }
+
+ if(fullScreenMode && state != minimized)
+ {
+ int w = XDisplayWidth(xGlobalDisplay, DefaultScreen(xGlobalDisplay));
+ int h = XDisplayHeight(xGlobalDisplay, DefaultScreen(xGlobalDisplay));
+ SetNETWMState((X11Window)window.windowHandle, true, add, atoms[_net_wm_state_fullscreen], 0);
+ XMoveResizeWindow(xGlobalDisplay, (X11Window)window.windowHandle, 0, 0, w, h);
+
+ guiApp.SetDesktopPosition(0, 0, w, h, true);
+ window.Position(0, 0, w, h, true, true, true, true, false, false);
+ }
+
+ if(state == minimized && atomsSupported[_net_wm_state])
+ {
+ //uint iconic = IconicState;
+
+ // 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;
*/
// printf("Attempting to minimize %s\n", window._class.name);
- XIconifyWindow(xGlobalDisplay, (X11Window)window.windowHandle, DefaultScreen(xGlobalDisplay));
+ if(!fullScreenMode)
+ XIconifyWindow(xGlobalDisplay, (X11Window)window.windowHandle, DefaultScreen(xGlobalDisplay));
}
- else
+ else if(!fullScreenMode)
{
- if(!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!
- 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);
+ // 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;
+ 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;
+
+ XMoveResizeWindow(xGlobalDisplay,
+ (X11Window)window.windowHandle,
+ x, y, w, h);
+ }
UpdateRootWindow(window);
}
- if(window.nativeDecorations)
+ 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);
+ if(curState != state)
+ 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);
+ }
}
}
}
else
+ {
XUnmapWindow(xGlobalDisplay, (X11Window)window.windowHandle);
+ windowData.currentlyVisible = false;
+ }
//XFlush(xGlobalDisplay);
}
+ *&window.state = curState;
}
void FlashRootWindow(Window window)
{
- XClientMessageEvent event = { 0 };
+ void * hwnd = window.windowHandle;
+ Window master = window.master, rootWindow = (master && master != guiApp.desktop) ? master.rootWindow : null;
+ if(!window.style.showInTaskBar && rootWindow && (window._isModal || window.style.interim))
+ hwnd = rootWindow.windowHandle;
+
// 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)hwnd, true, add, atoms[_net_wm_state_demands_attention], 0);
}
void ActivateRootWindow(Window window)
{
if(!window.style.hidden && window.created)
{
+ XWindowData windowData = window.windowData;
//printf("Activate root window %s\n", window._class.name);
+ if(!windowData.currentlyVisible)
+ {
+ long t = (window.creationActivation == activate && guiApp.desktop.active) ? timeStamp : 0;
+ XChangeProperty(xGlobalDisplay, (X11Window)window.windowHandle, atoms[_net_wm_user_time],
+ XA_CARDINAL,32,PropModeReplace, (byte *)&t, 1);
+ XMapWindow(xGlobalDisplay, (X11Window)window.windowHandle);
+ WaitForViewableWindow(window);
+ windowData.currentlyVisible = true;
+ }
XRaiseWindow(xGlobalDisplay, (X11Window)window.windowHandle);
- XMapWindow(xGlobalDisplay, (X11Window)window.windowHandle);
- WaitForViewableWindow(window);
- if(atoms[_net_active_window])
+ if(atomsSupported[_net_active_window])
{
XClientMessageEvent event = { 0 };
event.type = ClientMessage;
event.window = (X11Window)window.windowHandle;
event.send_event = 1;
event.format = 32;
- event.data.l[0] = 0;
-
- //event.data.l[0] = 2;
- //event.data.l[1] = timeStamp;
-
-
- //event.data.l[1] = atoms[_net_wm_user_time];
- //event.data.l[2] = activeWindow; //guiApp.desktop.activeChild.windowHandle;
-
+ event.data.l[0] = /*0*/ 1;
+ // WMs will complain about using CurrentTime here, but when ActivateRootWindow() is called we really need to take over,
+ // otherwise a debugged application stays on top of the IDE when we hit a breakpoint (there was no user interaction with the IDE,
+ // but it really should be activated)
+ event.data.l[1] = CurrentTime; //timeStamp;
+ event.data.l[2] = activeWindow; //guiApp.desktop.activeChild.windowHandle;
+
#ifdef _DEBUG
//printf("(ActivateRootWindow) Setting _NET_ACTIVE_WINDOW for %s (%x)\n", window._class.name, window);
#endif
-
+
XSendEvent(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), bool::false, SubstructureRedirectMask | SubstructureNotifyMask, (union _XEvent *)&event);
//#if defined(__APPLE__)
- XSetInputFocus(xGlobalDisplay, (X11Window)window.windowHandle, RevertToPointerRoot, CurrentTime);
+ XSetInputFocus(xGlobalDisplay, (X11Window)window.windowHandle, RevertToParent, CurrentTime);
//#endif
}
else
- XSetInputFocus(xGlobalDisplay, (X11Window)window.windowHandle, RevertToPointerRoot, CurrentTime);
+ XSetInputFocus(xGlobalDisplay, (X11Window)window.windowHandle, RevertToParent, CurrentTime);
}
}
}
unsigned int state;
((GuiApplication)__thisModule.application).Lock();
//XLockDisplay(xGlobalDisplay);
- XQueryPointer(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), &childWindow,
+ XQueryPointer(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), &childWindow,
&rootWindow, x, y, &mx, &my, &state);
//XUnlockDisplay(xGlobalDisplay);
((GuiApplication)__thisModule.application).Unlock();
void SetMousePosition(int x, int y)
{
-
+ XWarpPointer(xGlobalDisplay, None, DefaultRootWindow(xGlobalDisplay), 0, 0, 0, 0, x, y);
+ XFlush(xGlobalDisplay);
}
void SetMouseRange(Window window, Box box)
{
((GuiApplication)__thisModule.application).Lock();
//XLockDisplay(xGlobalDisplay);
- if(box && box.left > 0 && box.top > 0 &&
+ if(box && box.left > 0 && box.top > 0 &&
box.right < guiApp.desktop.clientSize.w - 1 && box.bottom < guiApp.desktop.clientSize.h - 1)
{
if(!window.parent || !window.parent.display)
{
- XMoveResizeWindow(xGlobalDisplay, confineWindow, box.left + desktopX, box.top + desktopY,
+ XMoveResizeWindow(xGlobalDisplay, confineWindow, box.left /*+ desktopX*/, box.top /*+ desktopY*/,
box.right - box.left + 1, box.bottom - box.top + 1);
-
+
if(!restrictedWindow)
XMapWindow(xGlobalDisplay, confineWindow);
}
else
XUngrabPointer(xGlobalDisplay, CurrentTime);
-
+
if(restrictedWindow)
XUnmapWindow(xGlobalDisplay, confineWindow);
else if(capturedWindow != None)
{
if(restrictedWindow)
- XGrabPointer(xGlobalDisplay, (X11Window) restrictedWindow.rootWindow.windowHandle, False,
+ XGrabPointer(xGlobalDisplay, (X11Window) restrictedWindow.rootWindow.windowHandle, False,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask, GrabModeAsync,
GrabModeAsync, confineWindow, fullScreenMode ? nullCursor : None, CurrentTime);
else
// -- Mouse cursor ---
- void SetMouseCursor(int cursor)
+ void SetMouseCursor(Window window, int cursor)
{
- //*XLockDisplay(xGlobalDisplay);
- if(cursor == -1)
- {
- XDefineCursor(xGlobalDisplay, (X11Window) guiApp.desktop.windowHandle, nullCursor);
- }
- //*XUnlockDisplay(xGlobalDisplay);
+ if(window.rootWindow.windowHandle)
+ XDefineCursor(xGlobalDisplay, (X11Window) window.rootWindow.windowHandle,
+ (acquiredInputWindow || cursor == -1) ? nullCursor : systemCursors[(SystemCursor)cursor]);
}
// --- Caret ---
(short)(caretOwner.caretPos.y - caretOwner.scroll.y + caretOwner.absPosition.y - window.absPosition.y)
};
XVaNestedList argList = XVaCreateNestedList(0, XNSpotLocation, &cursor_location, NULL);
- XSetICValues(windowData.ic, XNPreeditAttributes, argList, 0);
+ XSetICValues(windowData.ic, XNPreeditAttributes, argList, NULL);
}
}
- }
+ }
void ClearClipboard()
{
if(clipBoardData)
{
delete clipBoardData;
- XSetSelectionOwner(xGlobalDisplay, atoms[clipboard], None, CurrentTime);
+ XSetSelectionOwner(xGlobalDisplay, atoms[clipboard], None, CurrentTime);
}
//*XUnlockDisplay(xGlobalDisplay);
}
{
bool result = false;
if((clipBoard.text = new0 byte[size]))
- result = true;
+ result = true;
return result;
}
if(clipBoard.text)
{
Window rootWindow = guiApp.desktop;
- if(!fullScreenMode)
+ if(!fullScreenMode)
{
- for(rootWindow = rootWindow.children.first;
- rootWindow && !rootWindow.windowHandle;
+ for(rootWindow = rootWindow.children.first;
+ rootWindow && !rootWindow.windowHandle;
rootWindow = rootWindow.next);
}
if(clipBoardData)
delete clipBoardData;
else if(rootWindow)
- XSetSelectionOwner(xGlobalDisplay, atoms[clipboard],
+ XSetSelectionOwner(xGlobalDisplay, atoms[clipboard],
(X11Window) rootWindow.windowHandle, CurrentTime);
clipBoardData = clipBoard.text;
clipBoard.text = null;
Window rootWindow = guiApp.desktop;
if(!fullScreenMode)
{
- for(rootWindow = rootWindow.children.first;
- rootWindow && !rootWindow.windowHandle;
+ for(rootWindow = rootWindow.children.first;
+ rootWindow && !rootWindow.windowHandle;
rootWindow = rootWindow.next);
}
if(rootWindow)
{
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,
AnyPropertyType, &type,&format,&len, &dummy, &data) == Success)
{
clipBoard.text = new char[size+1];
- strncpy(clipBoard.text, data, size);
+ strncpy(clipBoard.text, (char *)data, size);
clipBoard.text[size] = '\0';
XFree(data);
result = true;
bool AcquireInput(Window window, bool state)
{
- return false;
+ if(state && window)
+ {
+ GetMousePosition(&acquireStart.x, &acquireStart.y);
+ lastMouse = acquireStart;
+ acquiredInputWindow = window;
+ incref acquiredInputWindow;
+ }
+ else if(acquiredInputWindow)
+ delete acquiredInputWindow;
+ return true;
}
bool GetMouseState(MouseButtons * buttons, int * x, int * y)
{
bool result = false;
- if(x) *x = 0;
- if(y) *y = 0;
+ if(acquiredInputWindow && guiApp.desktop.active)
+ {
+ if(x) *x = lastMouse.x - acquireStart.x;
+ if(y) *y = lastMouse.y - acquireStart.y;
+ *buttons = buttonsState;
+ SetMousePosition(acquireStart.x, acquireStart.y);
+ lastMouse = acquireStart;
+ result = true;
+ }
+ else
+ {
+ if(x) *x = 0;
+ if(y) *y = 0;
+ if(buttons) *buttons = 0;
+ }
return result;
}
bool GetJoystickState(int device, Joystick joystick)
{
bool result = false;
- #if defined(__linux__)
+ #if defined(__linux__)
if(joystick && device < 4)
{
struct JS_DATA_TYPE js = { 0 };
result = true;
}
}
- #endif
+ #endif
return result;
}
bool GetKeyState(Key key)
{
- int keyState = 0;
- return keyState;
+ if(key == capsState || key == numState || key == scrollState)
+ {
+ Atom atom = None;
+ X11Bool state = 0;
+ int idx = 0;
+ switch(key)
+ {
+ case capsState: atom = atoms[capsLock]; idx = 0; break;
+ case numState: atom = atoms[numLock]; idx = 1; break;
+ case scrollState: atom = atoms[scrollLock]; idx = 2; break;
+ }
+ /*XkbGetIndicatorState(xGlobalDisplay, XkbUseCoreKbd, &state);
+ state = (state & (1 << idx)) ? 1 : 0;*/
+ XkbGetNamedIndicator(xGlobalDisplay, /*XkbUseCoreKbd,*/ atom, &idx, &state, NULL, NULL);
+ return (bool)state;
+ }
+ else
+ {
+ if(key == alt)
+ return keyStates[leftAlt] || keyStates[rightAlt];
+ else if(key == shift)
+ return keyStates[leftShift] || keyStates[rightShift];
+ else if(key == control)
+ return keyStates[leftControl] || keyStates[rightControl];
+ else
+ return keyStates[key.code];
+ }
}
void SetTimerResolution(uint hertz)
hiResTimer.Create();
}
*/
- }
+ }
bool SetIcon(Window window, BitmapResource resource)
{
else
memcpy(icon + 2, bitmap.picture, bitmap.width * bitmap.height * sizeof(uint32));
XChangeProperty(xGlobalDisplay, (X11Window)window.windowHandle, atoms[_net_wm_icon],
- XA_CARDINAL,32,PropModeReplace, (byte *)icon, 2+bitmap.width*bitmap.height);
- delete icon;
+ XA_CARDINAL,32,PropModeReplace, (byte *)icon, 2+bitmap.width*bitmap.height);
+ delete icon;
}
delete bitmap;
}
}
}
-default dllexport void * __attribute__((stdcall)) IS_XGetDisplay()
+default dllexport void * IS_XGetDisplay()
{
return xGlobalDisplay;
}
-default dllexport void * __attribute__((stdcall)) IS_XGetWindow(Window window)
+default dllexport void * IS_XGetWindow(Window window)
{
return window.windowHandle ? window.windowHandle : window.rootWindow.windowHandle;
}