ecere/gui/drivers/XInterface: (#992) Setting pointer position implementation
[sdk] / ecere / src / gui / drivers / XInterface.ec
index e7e9135..c392eb1 100644 (file)
@@ -33,6 +33,10 @@ default:
 #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>
@@ -48,6 +52,7 @@ default:
 #include <X11/extensions/Xrender.h>
 #include <X11/extensions/XShm.h>
 
+#undef Bool
 #undef Picture
 #undef Window
 #undef Cursor
@@ -106,7 +111,8 @@ 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, _net_wm_state_modal, app_selection, _net_supported
+   _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
 };
 
 static Atom atoms[AtomIdents];
@@ -153,20 +159,16 @@ static const char *atomNames[AtomIdents] = {
    "_NET_WM_STATE_MAXIMIZED_HORZ", // _net_wm_state_maximized_horz
    "_NET_WM_STATE_MODAL", // _net_wm_state_modal
    "APP_SELECTION",
-   "_NET_SUPPORTED"
+   "_NET_SUPPORTED",
+   "_NET_WM_STATE_SKIP_TASKBAR",
+   "_NET_WM_STATE_FULLSCREEN",
+   "_NET_WM_STATE_ABOVE"
 };
 /*
 _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;
@@ -240,7 +242,7 @@ static void SetNETWMState(X11Window windowHandle, bool throughRoot, NETWMStateAc
 
 }
 
-static Time timeStamp;
+static X11Time timeStamp;
 
 class XWindowData : struct
 {
@@ -251,6 +253,7 @@ public:
    // Decorations Size
    Box decor;
    bool gotFrameExtents;
+   bool currentlyVisible;
 };
 
 bool XGetBorderWidths(Window window, Box box)
@@ -397,11 +400,39 @@ static void RepositionDesktop(bool updateChildren)
 
    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;
+      }
    }
 }
 
@@ -779,7 +810,16 @@ static bool ProcessKeyMessage(Window window, uint keyCode, int release, XKeyEven
    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));
+      }
       code.alt = true;
+   }
 
 #ifdef __APPLE__
    if(key != leftAlt && key != rightAlt && event->state & (1<<13))
@@ -862,12 +902,12 @@ static uint E_CALL XEventThread(void * data)
 }
 */
 
-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;
 }
 
-static Bool ConfigureNotifyChecker(void *display, XConfigureEvent *event, char * data)
+static X11Bool ConfigureNotifyChecker(void *display, XConfigureEvent *event, char * data)
 {
    return (!data || (event->window == (X11Window) data)) && event->type == ConfigureNotify;
 }
@@ -1022,9 +1062,9 @@ static void WaitForViewableWindow(Window window)
    }
 }
 
-static bool RequestFrameExtents(Window window)
+static bool RequestFrameExtents(X11Window windowHandle)
 {
-   if(window.nativeDecorations && frameExtentSupported != broken)
+   if(frameExtentSupported != broken)
    {
       // Request decoration frame extents
       XClientMessageEvent event = { 0 };
@@ -1032,15 +1072,14 @@ static bool RequestFrameExtents(Window window)
       event.message_type = atoms[_net_request_frame_extents];
       event.display = xGlobalDisplay;
       event.serial = 0;
-      event.window = (X11Window)window.windowHandle;
+      event.window = windowHandle;
       event.send_event = 1;
-      window.windowHandle = (void *)window.windowHandle;
       event.format = 32;
 
       if(frameExtentSupported == unknown && !frameExtentRequest)
       {
          frameExtentRequest = GetTime();
-         frameExtentWindow = (X11Window)window.windowHandle;
+         frameExtentWindow = windowHandle;
       }
 
       XSendEvent(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), bool::false,
@@ -1241,6 +1280,7 @@ class XInterface : Interface
 #endif
       xTerminate = false;
       xGlobalDisplay = XOpenDisplay(null);
+      // XSynchronize(xGlobalDisplay, True);
       frameExtentSupported = unknown;
 
       joystickFD[0] = open("/dev/js0", O_RDONLY);
@@ -1362,12 +1402,6 @@ class XInterface : Interface
                }
             }
 
-            {
-               Atom protocols[2] = { atoms[wm_delete_window], atoms[wm_take_focus] };
-
-               XSetWMProtocols(xGlobalDisplay, DefaultRootWindow(xGlobalDisplay), protocols, 2);
-            }
-
             /*
             if(atomsSupported[_net_workarea])
                printf("Warning: _NET_WORKAREA extension not supported\n");
@@ -1535,6 +1569,7 @@ class XInterface : Interface
                {
                   XKeyEvent * event = (XKeyEvent *) thisEvent;
                   incref window;
+                  timeStamp = event->time;
                   if(!window.active)
                   {
                      Window modalRoot = window.FindModal();
@@ -1568,6 +1603,7 @@ class XInterface : Interface
                   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))
@@ -1608,14 +1644,15 @@ class XInterface : Interface
                   uint button, buttonDouble, whichButton;
                   uint buttonMask;
                   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(!atomsSupported[_net_active_window] && !window.isRemote)
+                     if(!fullScreenMode)
                      {
-                        XRaiseWindow(xGlobalDisplay, (X11Window)window.windowHandle);
-                        XSetInputFocus(xGlobalDisplay, (X11Window)window.windowHandle, RevertToPointerRoot, CurrentTime);
+                        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;
@@ -1703,6 +1740,7 @@ class XInterface : Interface
                      button = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp;
                      buttonMask = Button2Mask;
                   }
+                  timeStamp = event->time;
                   if(!(event->state & buttonMask)) break;
                   if(event->state & ShiftMask)     keyFlags.shift = true;
                   if(event->state & ControlMask)   keyFlags.ctrl = true;
@@ -1734,6 +1772,7 @@ class XInterface : Interface
                   // 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;
@@ -1756,15 +1795,10 @@ class XInterface : Interface
                {
                   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;
                }
@@ -1810,6 +1844,18 @@ class XInterface : Interface
                }
                case FocusIn:
                {
+                  guiApp.SetAppFocus(true);
+
+                  if(fullScreenMode)
+                  {
+                     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);
+                        (xGlobalDisplay, (X11Window)window.windowHandle, RevertToParent, timeStamp);
+                     XInterface::UpdateRootWindow(window);
+                     break;
+                  }
+
                   if(activeWindow != (X11Window)window.windowHandle)
                   {
                      XFocusChangeEvent *event = (XFocusChangeEvent *) thisEvent;
@@ -1842,6 +1888,18 @@ class XInterface : Interface
                }
                case FocusOut:
                {
+                  if((X11Window)window.windowHandle == activeWindow)
+                     guiApp.SetAppFocus(false);
+
+                  if(fullScreenMode)
+                  {
+                     SetNETWMState((X11Window)window.windowHandle, true, remove, atoms[_net_wm_state_fullscreen], 0);
+                     XUngrabKeyboard(xGlobalDisplay, CurrentTime);
+                     // -- This XIconifyWindow causes trouble on Gnome Classic
+                     XIconifyWindow(xGlobalDisplay, (X11Window)window.windowHandle, DefaultScreen(xGlobalDisplay));
+                     break;
+                  }
+
 #ifdef _DEBUG
                   //printf("Processing a FocusOut Event for %s (%x)\n", window._class.name, window);
 #endif
@@ -1921,7 +1979,7 @@ class XInterface : Interface
 #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
@@ -1946,6 +2004,7 @@ class XInterface : Interface
                {
                   XConfigureEvent * event = (XConfigureEvent *) thisEvent;
                   bool unmaximized = 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)
 
@@ -2003,9 +2062,9 @@ class XInterface : Interface
                   {
                      bool offset = false;
                      int x, y, w, h;
-                     if(unmaximized)
+                     if(unmaximized && window.nativeDecorations)
                      {
-                        if(window.nativeDecorations && RequestFrameExtents(window))
+                        if(window.nativeDecorations && RequestFrameExtents((X11Window)window.windowHandle))
                            WaitForFrameExtents(window);
 
                         // Ensure we set the normal size anchor when un-maximizing
@@ -2024,11 +2083,13 @@ class XInterface : Interface
                            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;
-                              offset = true;
                            }
                         }
 
@@ -2082,9 +2143,19 @@ class XInterface : Interface
                      Window modalRoot;
                      XWindowData windowData;
                      bool laterFocus;
-                     activeWindow = (X11Window)window.windowHandle;
 
-                     timeStamp = (int)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;
@@ -2105,7 +2176,7 @@ class XInterface : Interface
                            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
@@ -2141,10 +2212,10 @@ class XInterface : Interface
                                  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
@@ -2152,7 +2223,9 @@ class XInterface : Interface
 #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");
@@ -2160,7 +2233,9 @@ class XInterface : Interface
                            }
                            else
                            {
-                              XSetInputFocus(xGlobalDisplay, (X11Window)window.windowHandle, RevertToPointerRoot, (uint)timeStamp);
+                              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)
                               {
@@ -2182,7 +2257,7 @@ class XInterface : Interface
                {
                   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)
                   {
                      if(!GetFrameExtents(window, true))
@@ -2389,9 +2464,50 @@ class XInterface : Interface
 
       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...
@@ -2457,18 +2573,33 @@ class XInterface : Interface
             }
 
             {
-               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);
 
-                  XChangeProperty(xGlobalDisplay, windowHandle, atoms[_net_wm_window_type], XA_ATOM, 32,
-                     PropModeReplace, (unsigned char*)&hints, parentWindow ? 2 : 1);
                {
                   XWMHints xwmHints;
                   xwmHints.flags = InputHint;
@@ -2481,7 +2612,6 @@ class XInterface : Interface
                }
 
                // Set Normal hints for minimum/maximum size
-               if(true)
                {
                   XSizeHints hints = { 0 };
                   hints.min_width = minW;
@@ -2565,10 +2695,10 @@ class XInterface : Interface
             {
                (window.nativeDecorations ? 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 || ((BorderBits)window.borderStyle).fixed) ? MWM_FUNC_MOVE : 0) |
+               (fullScreenMode || ((BorderBits)window.borderStyle).sizable ? MWM_FUNC_RESIZE : 0),
                 0, 0, 0
             };
             XChangeProperty(xGlobalDisplay, windowHandle, atoms[_motif_wm_hints], atoms[_motif_wm_hints], 32,
@@ -2585,16 +2715,12 @@ class XInterface : Interface
          }
       }
 
-      /*
       {
-         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 };
 
@@ -2609,8 +2735,13 @@ class XInterface : Interface
          XUngrabPointer(xGlobalDisplay, CurrentTime);
       }
 
-      if(!window.nativeDecorations || !RequestFrameExtents(window))
+      if(!fullScreenMode && !window.nativeDecorations || !RequestFrameExtents(windowHandle))
          ((XWindowData)window.windowData).gotFrameExtents = true;
+      if(fullScreenMode)
+      {
+         XMapWindow(xGlobalDisplay, windowHandle);
+         XGrabKeyboard(xGlobalDisplay, windowHandle, False,  GrabModeAsync, GrabModeAsync, CurrentTime);
+      }
       return (void *)windowHandle;
    }
 
@@ -2697,7 +2828,7 @@ class XInterface : Interface
          x += desktopX;
          y += desktopY;
 
-         if(!atomsSupported[_net_wm_state] || window.state != maximized)
+         if(!fullScreenMode && (!atomsSupported[_net_wm_state] || window.state != maximized))
          {
             if(move && resize)
                XMoveResizeWindow(xGlobalDisplay, (X11Window)window.windowHandle, x, y, w, h);
@@ -2710,16 +2841,14 @@ class XInterface : Interface
             if(window.style.fixed && !window.style.sizable)
             {
                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|PPosition|PSize;
+               hints.flags |= PMinSize|PMaxSize;
                XSetWMNormalHints(xGlobalDisplay, (X11Window)window.windowHandle, &hints);
             }
          }
-#if defined(__APPLE__)
-//         if(window.created && !visible)
-  //          XUnmapWindow(xGlobalDisplay, (X11Window)window.windowHandle);
-#endif
       }
    }
 
@@ -2767,13 +2896,29 @@ class XInterface : Interface
          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);
-            WaitForViewableWindow(window);
-            if(window.creationActivation == activate && state != minimized)
-               ActivateRootWindow(window);
+            if(!windowData.currentlyVisible)
+            {
+               XMapWindow(xGlobalDisplay, (X11Window)window.windowHandle);
+               windowData.currentlyVisible = true;
+               WaitForViewableWindow(window);
+               if(window.creationActivation == activate && 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])
             {
@@ -2798,9 +2943,10 @@ class XInterface : Interface
                */
 
                // 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)
             {
                //((XWindowData)window.windowData).gotFrameExtents && (!window.nativeDecorations || window.state == state))
                if(!atomsSupported[_net_wm_state] || (!((XWindowData)window.windowData).gotFrameExtents && window.state == maximized))
@@ -2834,7 +2980,7 @@ class XInterface : Interface
                if(atomsSupported[_net_wm_state])
                {
                   // Maximize / Restore the window
-                  SetNETWMState((X11Window)window.windowHandle, true, state == maximized ? add: remove,
+                  SetNETWMState((X11Window)window.windowHandle, true, state == maximized ? add : remove,
                      atoms[_net_wm_state_maximized_vert], atoms[_net_wm_state_maximized_horz]);
                   if(state == maximized)
                   {
@@ -2847,7 +2993,10 @@ class XInterface : Interface
             }
          }
          else
+         {
             XUnmapWindow(xGlobalDisplay, (X11Window)window.windowHandle);
+            windowData.currentlyVisible = false;
+         }
          //XFlush(xGlobalDisplay);
       }
    }
@@ -2864,10 +3013,15 @@ class XInterface : Interface
       {
          if(!window.style.hidden && window.created)
          {
+            XWindowData windowData = window.windowData;
             //printf("Activate root window %s\n", window._class.name);
+            if(!windowData.currentlyVisible)
+            {
+               XMapWindow(xGlobalDisplay, (X11Window)window.windowHandle);
+               WaitForViewableWindow(window);
+               windowData.currentlyVisible = true;
+            }
             XRaiseWindow(xGlobalDisplay, (X11Window)window.windowHandle);
-            XMapWindow(xGlobalDisplay, (X11Window)window.windowHandle);
-            WaitForViewableWindow(window);
             if(atomsSupported[_net_active_window])
             {
                XClientMessageEvent event = { 0 };
@@ -2878,14 +3032,9 @@ class XInterface : Interface
                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;
+               event.data.l[1] = 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);
@@ -2893,11 +3042,11 @@ class XInterface : Interface
 
                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);
          }
       }
    }
@@ -2931,7 +3080,7 @@ class XInterface : Interface
 
    void SetMousePosition(int x, int y)
    {
-
+      XWarpPointer(xGlobalDisplay, None, DefaultRootWindow(xGlobalDisplay), 0, 0, 0, 0, x, y);
    }
 
    void SetMouseRange(Window window, Box box)
@@ -3009,7 +3158,7 @@ class XInterface : Interface
    {
       if(window.rootWindow.windowHandle)
          XDefineCursor(xGlobalDisplay, (X11Window) window.rootWindow.windowHandle,
-            cursor == -1 ? (X11Cursor)0 : systemCursors[(SystemCursor)cursor]);
+            cursor == -1 ? nullCursor : systemCursors[(SystemCursor)cursor]);
    }
 
    // --- Caret ---