ecere/gui/XInterface: Reduced likelyhood of stealing focus
[sdk] / ecere / src / gui / drivers / XInterface.ec
index 9f82a0c..ccfb10e 100644 (file)
@@ -22,6 +22,16 @@ 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>
@@ -857,7 +867,8 @@ static bool ProcessKeyMessage(Window window, uint keyCode, int release, XKeyEven
    {
       int numBytes;
 
-      if(code < KeyCode::enumSize) keyStates[code] = false;
+      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);
@@ -868,7 +879,8 @@ static bool ProcessKeyMessage(Window window, uint keyCode, int release, XKeyEven
       int c;
       if(release == 0)
       {
-         if(code < KeyCode::enumSize) keyStates[code] = true;
+         if(key < KeyCode::enumSize)
+            keyStates[key] = true;
 
          if(windowData.ic && buflength)
          {
@@ -1993,7 +2005,7 @@ class XInterface : Interface
 
                      if(window.parent && window == window.parent.activeChild) break;
                      incref window;
-                     //if(window.creationActivation == activate)
+                     //if(window.creationActivation == activate && guiApp.desktop.active)
                      {
                         if(modalRoot)
                            modalRoot.ExternalActivate(true, true, window, null); // lastActive);
@@ -2885,7 +2897,12 @@ class XInterface : Interface
       if(window.windowHandle && (!window.parent || !window.parent.display))
       {
          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);
+         }
          if(window.state == minimized && atomsSupported[_net_wm_state]) return;
 
          if(window.nativeDecorations)
@@ -2924,7 +2941,7 @@ class XInterface : Interface
          x += desktopX;
          y += desktopY;
 
-         if(!fullScreenMode && (!atomsSupported[_net_wm_state] || window.state != maximized))
+         if(!fullScreenMode && (!atomsSupported[_net_wm_state] || (window.state != maximized || !window.visible)))
          {
             if(move && resize)
                XMoveResizeWindow(xGlobalDisplay, (X11Window)window.windowHandle, x, y, w, h);
@@ -2934,7 +2951,7 @@ class XInterface : Interface
                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)
+            if(window.style.fixed && !window.style.sizable && window.state != maximized)
             {
                XSizeHints hints = { 0 };
                long supplied;
@@ -2987,6 +3004,8 @@ class XInterface : Interface
 
    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;
@@ -2998,10 +3017,13 @@ class XInterface : Interface
          {
             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);
                windowData.currentlyVisible = true;
                WaitForViewableWindow(window);
-               if(window.creationActivation == activate && state != minimized)
+               if(window.creationActivation == activate && guiApp.desktop.active && state != minimized)
                   ActivateRootWindow(window);
             }
 
@@ -3076,8 +3098,10 @@ class XInterface : Interface
                if(atomsSupported[_net_wm_state])
                {
                   // Maximize / Restore the window
-                  SetNETWMState((X11Window)window.windowHandle, true, state == maximized ? add : remove,
-                     atoms[_net_wm_state_maximized_vert], atoms[_net_wm_state_maximized_horz]);
+                  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
@@ -3095,12 +3119,18 @@ class XInterface : Interface
          }
          //XFlush(xGlobalDisplay);
       }
+      *&window.state = curState;
    }
 
    void FlashRootWindow(Window window)
    {
+      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");
-      SetNETWMState((X11Window)window.windowHandle, true, add, atoms[_net_wm_state_demands_attention], 0);
+      SetNETWMState((X11Window)hwnd, true, add, atoms[_net_wm_state_demands_attention], 0);
    }
 
    void ActivateRootWindow(Window window)
@@ -3113,6 +3143,9 @@ class XInterface : Interface
             //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;
@@ -3479,7 +3512,16 @@ class XInterface : Interface
          return (bool)state;
       }
       else
-         return keyStates[key.code];
+      {
+         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)