ecere: Fixes for proper Native Decorations support on Windows
authorJerome St-Louis <jerome@ecere.com>
Sun, 14 Aug 2011 06:24:50 +0000 (02:24 -0400)
committerJerome St-Louis <jerome@ecere.com>
Sun, 14 Aug 2011 06:24:50 +0000 (02:24 -0400)
ecere/src/gui/Window.ec
ecere/src/gui/controls/EditBox.ec
ecere/src/gui/drivers/Win32Interface.ec
ecere/src/gui/skins/WindowsSkin.ec
ide/src/ide.ec

index c053244..6af42f0 100644 (file)
@@ -36,6 +36,9 @@ import "FileDialog"
 import "MessageBox"
 import "WindowList"
 
+// Had to define this here for native decorations support, because the menu bar is part of total decoration's size, but not part of the system decorations
+define skinMenuHeight = 25;
+
 default extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown;
 
 public enum DialogResult { cancel, yes, no, ok };
@@ -705,7 +708,7 @@ private:
       mox.top    -= clientStart.y;
       mox.right  -= clientStart.x;
       mox.bottom -= clientStart.y;
-      
+
       mox.Clip(clientArea);
       // mox.ClipOffset(against, scrolledPos.x, scrolledPos.y);
 
@@ -713,6 +716,11 @@ private:
       {
          int x = absPosition.x + clientStart.x;
          int y = absPosition.y + clientStart.y;
+         if(rootWindow.nativeDecorations)
+         {
+            x -= rootWindow.clientStart.x;
+            y -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
+         }
          if(!guiApp.fullScreenMode || is3D)
          {
             x -= rootWindow.absPosition.x;
@@ -730,6 +738,7 @@ private:
                */
             }
          }
+
          surface = display.GetSurface(x, y, mox);
          /*if(surface)
          {
@@ -755,11 +764,15 @@ private:
       {
          int x = absPosition.x;
          int y = absPosition.y;
+         if(rootWindow.nativeDecorations)
+         {
+            x -= rootWindow.clientStart.x;
+            y -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
+         }
          if(!guiApp.fullScreenMode || is3D)
          {
             x -= rootWindow.absPosition.x;
-            y -= rootWindow.absPosition.y; 
-
+            y -= rootWindow.absPosition.y;
             if(rootWindow.is3D)
             {
                x += rootWindow.parent.clientStart.x;
@@ -772,6 +785,7 @@ private:
                */
             }
          }
+
          surface = display.GetSurface(x, y, mox);
          /*if(surface)
          {
@@ -2567,7 +2581,13 @@ private:
    {
       bool opaque = IsOpaque();
       Window child;
-      int offsetX = absPosition.x - rootWindow.absPosition.x, offsetY = absPosition.y - rootWindow.absPosition.y; 
+      int offsetX = absPosition.x - rootWindow.absPosition.x, offsetY = absPosition.y - rootWindow.absPosition.y;
+      if(rootWindow.nativeDecorations)
+      {
+         offsetX -= rootWindow.clientStart.x;
+         offsetY -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
+      }
+
 
       for(child = children.last; child; child = child.prev)
       {
@@ -2577,9 +2597,16 @@ private:
          {
             if(!opaque)
             {
-               int offsetX = child.absPosition.x - rootWindow.absPosition.x, offsetY = child.absPosition.y - rootWindow.absPosition.y; 
                // Adjust renderArea to the root window level
                Extent * renderArea = &rootWindow.tempExtents[1];
+
+               int offsetX = child.absPosition.x - rootWindow.absPosition.x, offsetY = child.absPosition.y - rootWindow.absPosition.y;
+               if(child.rootWindow.nativeDecorations)
+               {
+                  offsetX -= child.rootWindow.clientStart.x;
+                  offsetY -= child.rootWindow.clientStart.y - (child.rootWindow.hasMenuBar ? skinMenuHeight : 0);
+               }
+
                /*
                Extent childRenderArea;
                
@@ -2627,7 +2654,12 @@ private:
       bool opaque = IsOpaque();
       Extent * dirtyExtentWindow = &rootWindow.tempExtents[1];
       Window child;
-      int offsetX = absPosition.x - rootWindow.absPosition.x, offsetY = absPosition.y - rootWindow.absPosition.y; 
+      int offsetX = absPosition.x - rootWindow.absPosition.x, offsetY = absPosition.y - rootWindow.absPosition.y;
+      if(rootWindow.nativeDecorations)
+      {
+         offsetX -= rootWindow.clientStart.x;
+         offsetY -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
+      }
 
 #if 0
       for(child = children.last; child; child = child.prev)
@@ -2640,7 +2672,7 @@ private:
          {
             if(!opaque)
             {
-               int offsetX = child.absPosition.x - rootWindow.absPosition.x, offsetY = child.absPosition.y - rootWindow.absPosition.y; 
+               int offsetX = child.absPosition.x - rootWindow.absPosition.x, offsetY = child.absPosition.y - rootWindow.absPosition.y;
                // Adjust renderArea to the root window level
                Extent renderArea;
                renderArea.Copy(child.dirtyArea);
@@ -2820,6 +2852,11 @@ private:
       Window child;
       Window rootWindow = this.rootWindow;
       int offsetX = absPosition.x - rootWindow.absPosition.x, offsetY = absPosition.y - rootWindow.absPosition.y;
+      if(rootWindow.nativeDecorations)
+      {
+         offsetX -= rootWindow.clientStart.x;
+         offsetY -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
+      }
 
       if(rootWindow.fullRender)
       {
@@ -4499,11 +4536,16 @@ private:
 
       for(hotKey = hotKeys.first; hotKey; hotKey = hotKey.next)
          if((hotKey.key == key || (method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp && hotKey.key.code == key.code)) &&
-            !hotKey.window.disabled && !hotKey.window.style.hidden && (hotKey.window.style.nonClient || state != minimized))
+            !hotKey.window.disabled && (hotKey.window.style.nonClient || state != minimized))
          {
             Window hotKeyWindow = hotKey.window;
+            Window parent = hotKeyWindow.parent;
             Window prevActiveWindow = activeChild;
 
+            // Don't process non-visible buttons, but make an exception for the Alt-F4 with Native Decorations turned on
+            if(hotKeyWindow.style.hidden && (!hotKeyWindow.style.nonClient || !parent || !parent.nativeDecorations || hotKeyWindow != parent.sysButtons[2]))
+               continue;
+
             if(prevActiveWindow) incref prevActiveWindow;
             incref hotKeyWindow;
             if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown && !hotKeyWindow.style.nonClient)
@@ -5495,6 +5537,9 @@ private:
       WindowState prevState = state;
 
       state = newState;
+      if(nativeDecorations)
+         return;
+
       if(prevState != newState)
          lastState = prevState;
       if(style.isActiveClient && !style.hidden && prevState == minimized)
@@ -5545,11 +5590,9 @@ private:
             break;
          }
       }
-
       // TOCHECK: Why was this here?
       //position.x = (tx > 0) ? tx & 0xFFFFF : tx;
       //position.y = (ty > 0) ? ty & 0xFFFFF : ty;
-
       ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
 
       Position(x, y, w, h, true, true, true, true, false, true);
@@ -6371,7 +6414,7 @@ public:
       
             SetStateEx(newState, activate);
 
-            if(rootWindow == this)
+            if(rootWindow == this && !rootWindow.nativeDecorations)
             {
                int x = position.x, y = position.y;
                /*if(style.interim)
index 7cec3ea..ed0244f 100644 (file)
@@ -3013,7 +3013,9 @@ private:
    bool OnMiddleButtonDown(int x, int y, Modifiers mods)
    {
       if(style.readOnly) return true;
-      Paste();
+      // We really shouldn't be pasting here, Unix middle button paste is for the selection (not the clipboard), good for the terminal
+      // Middle button already serves as a dragger as well.
+      // Paste();
       return true;
    }
 
index 5225ddc..89802c5 100644 (file)
@@ -416,8 +416,6 @@ class Win32Interface : Interface
                   {
                      HWND foreground;
                      DWORD id;
-
-                     uint returnValue = (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
                      uint windowLong;
                      foreground = GetForegroundWindow();
                      if(foreground == windowHandle && lParam)
@@ -434,7 +432,8 @@ class Win32Interface : Interface
 #endif
                      if(id != GetCurrentProcessId() || windowLong != (LPARAM)ApplicationWindow)
                         window.ExternalActivate(false, true, window, null);
-                     return returnValue;
+                     // DefWindowProc for WM_NCACTIVATE draws the decorations, make sure it's drawn in the right state
+                     return DefWindowProc(windowHandle, msg, window.active, lParam);
                   }
                }
                if(activateApp)
@@ -445,7 +444,7 @@ class Win32Interface : Interface
                   activateApp = false;
                 } 
 
-               return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
+               return (uint)DefWindowProc(windowHandle, msg, window ? window.active : wParam, lParam);
             }
             case WM_ACTIVATEAPP:
                if(!guiApp.IsModeSwitching())
@@ -722,6 +721,12 @@ class Win32Interface : Interface
                x += (short)LOWORD(lParam);
                y += (short)HIWORD(lParam);
 
+               if(window.nativeDecorations)
+               {
+                  x += window.clientStart.x;
+                  y += window.clientStart.y - (window.hasMenuBar ? skinMenuHeight : 0);
+               }
+
                if(::GetKeyState(VK_SHIFT) & 0x80000)   code.shift = true;
                if(::GetKeyState(VK_CONTROL) & 0x80000) code.ctrl = true;
                if(::GetKeyState(VK_MENU) & 0x80000)    code.alt = true;
@@ -796,11 +801,39 @@ class Win32Interface : Interface
                SetCursor((lastCursor == (SystemCursor)-1) ? null : systemCursors[lastCursor]);
                return 0;
             }
+            case WM_EXITMENULOOP:
+            case WM_EXITSIZEMOVE:
+               // We had some DirectInput stuff in here
+               break;
+            case WM_ENTERMENULOOP:
+            case WM_ENTERSIZEMOVE:
+               // We had some DirectInput stuff in here
+               break;
             case WM_CLOSE:
             {
                window.Destroy(0);
                return 0;
             }
+            case WM_MOVE:
+            {
+               int x, y;
+               WINDOWPLACEMENT placement = { 0 };
+               RECT rcWindow;
+               placement.length = sizeof(WINDOWPLACEMENT);
+               GetWindowRect(windowHandle, &rcWindow);
+               GetWindowPlacement(windowHandle, &placement);
+               x = rcWindow.left;
+               y = rcWindow.top;
+               if((placement.showCmd == SW_SHOWMAXIMIZED || placement.showCmd == SW_MAXIMIZE) && window.state != maximized)
+                  window.state = maximized;
+               else if(placement.showCmd == SW_SHOWMINIMIZED && window.state != minimized)
+                  window.state = minimized;
+               else if(placement.showCmd == SW_SHOWNORMAL && window.state != normal && window.visible)
+                  window.state = normal;
+
+               window.ExternalPosition(x, y, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top);
+               break;
+            }
             case WM_SIZE:
             {
                if(window.nativeDecorations)
@@ -809,13 +842,25 @@ class Win32Interface : Interface
                   int h = HIWORD(lParam);
                   int x, y;
                   WINDOWPLACEMENT placement = { 0 };
+                  RECT rcWindow;
+                  GetWindowRect(windowHandle, &rcWindow);
+
                   placement.length = sizeof(WINDOWPLACEMENT);
 
                   GetWindowPlacement(windowHandle, &placement);
-                  x = placement.rcNormalPosition.left;
-                  y = placement.rcNormalPosition.top;
-
+                  if((placement.showCmd == SW_SHOWMAXIMIZED || placement.showCmd == SW_MAXIMIZE) && window.state != maximized)
+                     window.state = maximized;
+                  else if(placement.showCmd == SW_SHOWMINIMIZED && window.state != minimized)
+                     window.state = minimized;
+                  else if(placement.showCmd == SW_SHOWNORMAL && window.state != normal && window.visible)
+                     window.state = normal;
+
+                  x = rcWindow.left;
+                  y = rcWindow.top;
+                  w = rcWindow.right - rcWindow.left;
+                  h = rcWindow.bottom - rcWindow.top;
                   window.ExternalPosition(x, y, w, h);
+                  window.UpdateDisplay();
                }
                else
                   return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
@@ -1223,6 +1268,8 @@ class Win32Interface : Interface
          }
          /*else if(parentWindow)
             exStyle |= WS_EX_TOOLWINDOW;*/
+         /*if(window.interim)
+            parentWindow = window.master.rootWindow.windowHandle;*/
 
          if(window.windowHandle)
             windowHandle = window.windowHandle;
@@ -1295,7 +1342,8 @@ class Win32Interface : Interface
          flags &=~SWP_NOMOVE;
          flags |= SWP_NOSIZE;
       }*/
-      SetWindowPos(window.windowHandle, null, x, y, w, h, flags);
+      if(!window.nativeDecorations || window.state != maximized || !window.visible)
+         SetWindowPos(window.windowHandle, null, x, y, w, h, flags);
    }
 
    void OrderRootWindow(Window window, bool topMost)
@@ -1349,28 +1397,8 @@ class Win32Interface : Interface
          {
             case maximized:
             case normal:
-               /*SetWindowPos(window.windowHandle, null, 0,0,0,0, 
-                  SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOZORDER);*/
-               // ShowWindow(window.windowHandle, SW_SHOWNA);
-               ShowWindow(window.windowHandle, (window.creationActivation == activate && !guiApp.modeSwitching) ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE);
-
-               if(window.nativeDecorations)
-               {
-                  int w, h;
-                  int x, y;
-                  RECT rect;
-                  WINDOWPLACEMENT placement = { 0 };
-                  placement.length = sizeof(WINDOWPLACEMENT);
-
-                  GetClientRect(window.windowHandle, &rect);
-                  GetWindowPlacement(window.windowHandle, &placement);
-                  x = placement.rcNormalPosition.left;
-                  y = placement.rcNormalPosition.top;
-                  w = rect.right+1;
-                  h = rect.bottom+1;
-
-                  window.ExternalPosition(x, y, w, h);
-               }
+               ShowWindow(window.windowHandle, (window.creationActivation == activate && !guiApp.modeSwitching) ? 
+                  ((window.nativeDecorations && state == maximized) ? SW_MAXIMIZE : SW_SHOWNORMAL) : SW_SHOWNOACTIVATE);
                break;
             case minimized:
                ShowWindow(window.windowHandle, SW_MINIMIZE);
@@ -1379,59 +1407,14 @@ class Win32Interface : Interface
       }
       else
       {
-         /*
-         SetWindowPos(window.windowHandle, null, 0,0,0,0, 
-            SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_HIDEWINDOW|SWP_NOZORDER);
-            */
          ShowWindow(window.windowHandle, SW_HIDE);
       }
    }
 
    void ActivateRootWindow(Window window)
    {
-      //MSG msg;
-      //HWND windowHandle = window.windowHandle;
-      //SetActiveWindow(topWindow);
-      //while(windowHandle != HWND_DESKTOP)
-     // {
-         // SetActiveWindow(windowHandle);
-         /*
-         SetWindowPos(window.windowHandle, window.style.stayOnTop ? HWND_TOPMOST : HWND_TOP, 
-            0,0,0,0,
-            SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOSIZE|SWP_NOREDRAW);
-         */
-         //SetFocus(windowHandle);
-
-         // windowHandle = GetParent(windowHandle);
-         /*
-         SetWindowPos(window.windowHandle, window.style.stayOnTop ? HWND_TOPMOST : HWND_TOP, 
-            0,0,0,0, SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOSIZE|SWP_NOREDRAW);*/
-   //   }
-   //   if(!window.isForegroundWindow)
-           //SetActiveWindow(window.windowHandle);
-/*
-      HWND windowHandle = window.windowHandle;
-      while(windowHandle != HWND_DESKTOP)
-      {
-         SetActiveWindow(windowHandle);
-         windowHandle = GetParent(windowHandle);
-      }
-*/
-      //SetActiveWindow(window.windowHandle);
       if(!guiApp.modeSwitching)
          SetForegroundWindow(window.windowHandle);
-      // UpdateWindow(window.windowHandle);
-      /*
-      SetWindowPos(window.windowHandle, window.style.stayOnTop ? HWND_TOPMOST : HWND_TOP, 
-         0,0,0,0, SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOSIZE|SWP_NOREDRAW|SWP_NOACTIVATE);
-         */
-      /*
-      while(PeekMessage(&msg,window.windowHandle,WM_NCACTIVATE,WM_NCACTIVATE,PM_REMOVE))
-      {
-         TranslateMessage(&msg);
-         DispatchMessage(&msg);
-      }*/
-
    }
 
    void FlashRootWindow(Window window)
@@ -1755,7 +1738,7 @@ class Win32Interface : Interface
                      c++;
                      m++;
                   }
-                  and.picture[b++] = mask;
+                  picture[b++] = mask;
                }
                c = 0;
                while(c < size)
index f4a0214..1890dfc 100644 (file)
@@ -1,5 +1,10 @@
 namespace gui::skins;
 
+#define WIN32_LEAN_AND_MEAN
+#define Method _Method
+#include <windows.h>
+#undef Method
+
 import "Window"
 
 #define BORDER       4
@@ -17,7 +22,6 @@ import "Window"
 #define SB_WIDTH  16
 #define SB_HEIGHT 16
 
-#define MENU_HEIGHT     25
 #define STATUS_HEIGHT   18
 
 #define GRADIENT_SMOOTHNESS 1.0f
@@ -145,14 +149,32 @@ public class WindowsSkin_Window : Window
 
       if(hasMenuBar && state != minimized)
       {
-         *h += MENU_HEIGHT;
+         *h += skinMenuHeight;
       }
       if(statusBar && state != minimized)
       {
          *h += STATUS_HEIGHT;
       }
 
-      if(nativeDecorations) return;
+      if(nativeDecorations && rootWindow == this)
+      {
+#if defined(WIN32)
+         RECT rcClient, rcWindow;
+         GetClientRect(windowHandle, &rcClient);
+         GetWindowRect(windowHandle, &rcWindow);
+         if(state == maximized)
+         {
+            *w += (rcWindow.right  - rcWindow.left) - rcClient.right;
+            *h += (rcWindow.bottom - rcWindow.top) - rcClient.bottom;
+         }
+         else
+         {
+            *w += (rcWindow.right - rcWindow.left) - rcClient.right;
+            *h += (rcWindow.bottom - rcWindow.top) - rcClient.bottom;
+         }
+#endif
+         return;
+      }
       if((((BorderBits)borderStyle).deep || ((BorderBits)borderStyle).bevel) && state != minimized)
       {
          *w += 4;
@@ -182,7 +204,7 @@ public class WindowsSkin_Window : Window
    void SetWindowMinimum(MinMaxValue * mw, MinMaxValue * mh)
    {
       bool isNormal = (state == normal);
-      if(nativeDecorations) return;
+      if(nativeDecorations && rootWindow == this) return;
       if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
       {
          *mw = MIN_WIDTH;
@@ -216,12 +238,23 @@ public class WindowsSkin_Window : Window
 
       if(hasMenuBar)
       {
-         *y += MENU_HEIGHT;
+         *y += skinMenuHeight;
       }
 
       GetDecorationsSize(&aw, &ah);
 
-      if(!nativeDecorations)
+      if(nativeDecorations && rootWindow == this)
+      {
+#if defined(WIN32)
+         RECT rcWindow;
+         POINT client00 = { 0, 0 };
+         ClientToScreen(windowHandle, &client00);
+         GetWindowRect(windowHandle, &rcWindow);
+         *x += client00.x - rcWindow.left;
+         *y += client00.y - rcWindow.top;
+#endif
+      }
+      else
       {
          // Compute client area start
          if(((BorderBits)borderStyle).deep || ((BorderBits)borderStyle).bevel)
@@ -266,7 +299,7 @@ public class WindowsSkin_Window : Window
       bool isNormal = (state == normal);
       int top = 0, border = 0, bottom = 0;
 
-      if(nativeDecorations) return;
+      if(nativeDecorations && rootWindow == this) return;
 
       if(state == minimized)
          top = border = bottom = DEAD_BORDER;
@@ -365,7 +398,7 @@ public class WindowsSkin_Window : Window
    {
       bool isNormal = (state == normal);
       bool result = false;
-      if(nativeDecorations) return false;
+      if(nativeDecorations && rootWindow == this) return false;
 
       if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
       {
@@ -390,7 +423,7 @@ public class WindowsSkin_Window : Window
       bool result = false;
 
       *resizeX = *resizeY = *resizeEndX = *resizeEndY = false;
-      if(nativeDecorations) return false;
+      if(nativeDecorations && rootWindow == this) return false;
 
       if(((BorderBits)borderStyle).sizable && (state == normal))
       {
@@ -428,7 +461,7 @@ public class WindowsSkin_Window : Window
       int top = 0, border = 0;
       int insideBorder = 0;
 
-      if(!nativeDecorations
+      if(!nativeDecorations && rootWindow == this)
       {
          if(state == minimized)
             top = border = DEAD_BORDER;
@@ -466,7 +499,7 @@ public class WindowsSkin_Window : Window
             menuBar.visible = false;
          else
             menuBar.visible = true;
-         menuBar.Move(clientStart.x, clientStart.y - MENU_HEIGHT, size.w - insideBorder * 2, MENU_HEIGHT);
+         menuBar.Move(clientStart.x, clientStart.y - skinMenuHeight, size.w - insideBorder * 2, skinMenuHeight);
       }
       if(statusBar)
       {
@@ -475,11 +508,19 @@ public class WindowsSkin_Window : Window
          else
          {
             statusBar.visible = true;
-            statusBar.anchor = { left = clientStart.x, bottom = border };
-            statusBar.size.w = size.w - insideBorder * 2;
+            if(nativeDecorations && rootWindow == this)
+            {
+               statusBar.anchor = { left = clientStart.x, bottom = (int)(size.h - clientSize.h - clientStart.y - STATUS_HEIGHT ) };
+               statusBar.size.w = size.w - insideBorder * 2;
+            }
+            else
+            {
+               statusBar.anchor = { left = clientStart.x, bottom = border };
+               statusBar.size.w = size.w - insideBorder * 2;
+            }
          }
       }
-      if(!nativeDecorations)
+      if(!nativeDecorations && rootWindow == this)
       {
          if(sysButtons[0])
          {
index b7d21ce..a639233 100644 (file)
@@ -199,7 +199,10 @@ void DrawLineMarginIcon(Surface surface, BitmapResource resource, int line, int
 
 class IDE : Window
 {
-   //nativeDecorations = true;
+#if defined(__WIN32__)
+   // Native decorations on Windows works pretty well now! Let's get them going good on X and make it the default there as well.
+   nativeDecorations = true;
+#endif
    icon = { ":icon.png" };
    text = titleECEREIDE;
    background = Color { 85, 85, 85 };