ecere/gui/drivers/XInterface: Removed position and size flags when setting min/max...
[sdk] / ecere / src / gui / drivers / XInterface.ec
index fbaa1e2..3bb7145 100644 (file)
@@ -240,7 +240,7 @@ static void SetNETWMState(X11Window windowHandle, bool throughRoot, NETWMStateAc
 
 }
 
-static Time timeStamp;
+static X11Time timeStamp;
 
 class XWindowData : struct
 {
@@ -1022,9 +1022,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,20 +1032,21 @@ 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,
          SubstructureRedirectMask | SubstructureNotifyMask, (union _XEvent *)&event);
+      return true;
    }
+   return false;
 }
 
 static bool GetFrameExtents(Window window, bool update)
@@ -1239,6 +1240,7 @@ class XInterface : Interface
 #endif
       xTerminate = false;
       xGlobalDisplay = XOpenDisplay(null);
+      // XSynchronize(xGlobalDisplay, True);
       frameExtentSupported = unknown;
 
       joystickFD[0] = open("/dev/js0", O_RDONLY);
@@ -1533,6 +1535,7 @@ class XInterface : Interface
                {
                   XKeyEvent * event = (XKeyEvent *) thisEvent;
                   incref window;
+                  timeStamp = event->time;
                   if(!window.active)
                   {
                      Window modalRoot = window.FindModal();
@@ -1566,6 +1569,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))
@@ -1606,15 +1610,13 @@ 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)
-                     {
                         XRaiseWindow(xGlobalDisplay, (X11Window)window.windowHandle);
-                        XSetInputFocus(xGlobalDisplay, (X11Window)window.windowHandle, RevertToPointerRoot, CurrentTime);
-                     }
+                     XSetInputFocus(xGlobalDisplay, (X11Window)window.windowHandle, RevertToPointerRoot, CurrentTime);
                      button = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown;
                      buttonDouble = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick;
                      whichButton = 0;
@@ -1701,6 +1703,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;
@@ -1732,6 +1735,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;
@@ -1754,15 +1758,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;
                }
@@ -1999,13 +1998,14 @@ class XInterface : Interface
                      }
                   }
                   {
+                     bool offset = false;
                      int x, y, w, h;
-                     if(unmaximized)
+                     if(unmaximized && window.nativeDecorations)
                      {
-                        // Ensure we set the normal size anchor when un-maximizing
-                        if(window.nativeDecorations && RequestFrameExtents(window))
+                        if(window.nativeDecorations && RequestFrameExtents((X11Window)window.windowHandle))
                            WaitForFrameExtents(window);
-                        x = window.position.x, y = window.position.y, w = window.size.w, h = window.size.h;
+
+                        // Ensure we set the normal size anchor when un-maximizing
                         window.ComputeAnchors(window.normalAnchor, window.normalSizeAnchor, &x, &y, &w, &h);
                      }
                      else
@@ -2021,8 +2021,14 @@ class XInterface : Interface
                            XTranslateCoordinates(xGlobalDisplay, event->window,
                               RootWindow(xGlobalDisplay, DefaultScreen(xGlobalDisplay)), 0, 0,
                               &rootX, &rootY, &rootChild);
-                           x = rootX;
-                           y = rootY;
+
+                           if(x != rootX || y != rootY)
+                           {
+                              /*if(event->send_event)
+                                 offset = true;*/
+                              x = rootX;
+                              y = rootY;
+                           }
                         }
 
                         x -= desktopX;
@@ -2034,6 +2040,7 @@ class XInterface : Interface
                            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);
@@ -2043,23 +2050,20 @@ class XInterface : Interface
                         }
                      }
 
-                     // Break the anchors for moveable/resizable windows
-                     if(window.style.fixed && window.state == normal)
-                     {
-                        window.normalAnchor = Anchor { left = x, top = y };
-                        window.normalSizeAnchor = SizeAnchor { { w, h } };
-                        window.anchored = false;
-                     }
+                     window.Position(x, y, w, h, true, true, true, true, false, unmaximized);
 
                      // Break the anchors for moveable/resizable windows
-                     if(window.style.fixed && window.state == normal)
+                     // 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)
                      {
-                        window.normalAnchor = Anchor { left = x, top = y };
-                        window.normalSizeAnchor = SizeAnchor { { w, h } };
-                        window.anchored = false;
+                        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.Position(x, y, w, h, true, true, true, true, false, unmaximized);
                   }
                   break;
                }
@@ -2079,7 +2083,7 @@ class XInterface : Interface
                      bool laterFocus;
                      activeWindow = (X11Window)window.windowHandle;
 
-                     timeStamp = (int)event->data.l[1];
+                     timeStamp = (X11Time)event->data.l[1];
 
                      windowData = window.windowData;
                      laterFocus = windowData.laterFocus;
@@ -2136,10 +2140,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
@@ -2147,7 +2151,7 @@ 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, RevertToPointerRoot, timeStamp);
 
                                  //XFlush(xGlobalDisplay);
                                  //printf("Done.\n");
@@ -2155,7 +2159,7 @@ class XInterface : Interface
                            }
                            else
                            {
-                              XSetInputFocus(xGlobalDisplay, (X11Window)window.windowHandle, RevertToPointerRoot, (uint)timeStamp);
+                              XSetInputFocus(xGlobalDisplay, (X11Window)window.windowHandle, RevertToPointerRoot, timeStamp);
                               window.ExternalActivate(true, true, window, null); // lastActive);
                               if(windowData && windowData.ic)
                               {
@@ -2405,6 +2409,18 @@ class XInterface : Interface
             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;
@@ -2440,18 +2456,32 @@ class XInterface : Interface
             }
 
             {
-               Atom hints[2] =
+               Atom hints[4];
+               int count;
+               if(parentWindow && window.interim)
+               {
+                  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)
                {
-                  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_normal];
+
+                  // 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;
@@ -2464,17 +2494,12 @@ class XInterface : Interface
                }
 
                // Set Normal hints for minimum/maximum size
-               if(true) //window.minSize.w || window.minSize.h || window.maxSize.w < MAXINT || window.maxSize.h < MAXINT)
                {
                   XSizeHints hints = { 0 };
-                  MinMaxValue mw, mh;
-                  window.SetWindowMinimum(&mw, &mh);
-                  if(window.minSize.w || window.minSize.h)
-                  {
-                     hints.min_width = Max(window.minSize.w, mw);
-                     hints.min_height = Max(window.minSize.h, mh);
-                     hints.flags |= PMinSize;
-                  }
+                  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;
@@ -2596,8 +2621,9 @@ class XInterface : Interface
          XUngrabPointer(xGlobalDisplay, CurrentTime);
       }
 
-      if(!window.nativeDecorations || !RequestFrameExtents(window))
+      if(!window.nativeDecorations || !RequestFrameExtents(windowHandle))
          ((XWindowData)window.windowData).gotFrameExtents = true;
+
       return (void *)windowHandle;
    }
 
@@ -2692,11 +2718,18 @@ class XInterface : Interface
                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)
+            {
+               XSizeHints hints = { 0 };
+               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 defined(__APPLE__)
-//         if(window.created && !visible)
-  //          XUnmapWindow(xGlobalDisplay, (X11Window)window.windowHandle);
-#endif
       }
    }
 
@@ -2855,14 +2888,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);
@@ -2920,7 +2948,7 @@ class XInterface : Interface
       {
          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)
@@ -2984,8 +3012,9 @@ class XInterface : Interface
 
    void SetMouseCursor(Window window, int cursor)
    {
-      XDefineCursor(xGlobalDisplay, (X11Window) window.rootWindow.windowHandle,
-         cursor == -1 ? (X11Cursor)0 : systemCursors[(SystemCursor)cursor]);
+      if(window.rootWindow.windowHandle)
+         XDefineCursor(xGlobalDisplay, (X11Window) window.rootWindow.windowHandle,
+            cursor == -1 ? (X11Cursor)0 : systemCursors[(SystemCursor)cursor]);
    }
 
    // --- Caret ---