ecere/gui/XInterface; Win32Interface: Fixes to FlashWindow to flash owner instead
[sdk] / ecere / src / gui / drivers / Win32Interface.ec
index 89802c5..9239168 100644 (file)
@@ -6,8 +6,10 @@ import "instance"
 
 #if defined(__WIN32__)
 
+#undef WINVER
 #define WINVER 0x0500
-#define _WIN32_WINNT 0x0500
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
 
 #undef JOY_BUTTON1
 #undef JOY_BUTTON2
@@ -18,7 +20,11 @@ import "instance"
 #define Method _Method
 #define byte _byte
 #define int64 _int64
+#define String _String
+#define Mutex _Mutex
+#define Platform _Platform
 #include <windows.h>
+#include <wincon.h>
 #include <shellapi.h>
 
 
@@ -81,6 +87,9 @@ SetLayeredWindowAttributes(
 #undef Method
 #undef byte
 #undef int64
+#undef String
+#undef Mutex
+#undef Platform
 
 import "Window"
 
@@ -93,24 +102,28 @@ import "Window"
 static byte key2VK[256] =
 {
    0,VK_ESCAPE,'1','2','3','4','5','6','7','8','9','0',VK_MINUS,VK_EQUALS,VK_BACK,VK_TAB,
-   'Q','W','E','R','T','Y','U','I','O','P',VK_LBRACKET,VK_RBRACKET,VK_RETURN,VK_CONTROL,'A','S',
-   'D','F','G','H','J','K','L',VK_SEMI,VK_QUOTE,VK_TILDE,VK_SHIFT,VK_BACK_SLASH,'Z','X','C','V',
-   'B','N','M',VK_COMMA,VK_PERIOD,VK_DIVIDE,VK_SHIFT,VK_MULTIPLY,VK_LMENU,VK_SPACE,VK_CAPITAL,VK_F1,VK_F2,VK_F3,VK_F4,VK_F5,
+   'Q','W','E','R','T','Y','U','I','O','P',VK_LBRACKET,VK_RBRACKET,VK_RETURN,VK_LCONTROL,'A','S',
+   'D','F','G','H','J','K','L',VK_SEMI,VK_QUOTE,VK_TILDE,VK_LSHIFT,VK_BACK_SLASH,'Z','X','C','V',
+   'B','N','M',VK_COMMA,VK_PERIOD,VK_DIVIDE,VK_RSHIFT,VK_MULTIPLY,VK_LMENU,VK_SPACE,VK_CAPITAL,VK_F1,VK_F2,VK_F3,VK_F4,VK_F5,
    VK_F6,VK_F7,VK_F8,VK_F9,VK_F10,VK_NUMLOCK,VK_SCROLL,VK_NUMPAD7,VK_NUMPAD8,VK_NUMPAD9,VK_SUBTRACT,VK_NUMPAD4,VK_NUMPAD5,VK_NUMPAD6,VK_ADD,VK_NUMPAD1,
-   VK_NUMPAD2,VK_NUMPAD3,VK_NUMPAD0,VK_DELETE,0,0,0,0,0,0,0,0,0,0,0,0,
-   0,0,0,0,0,0,VK_HOME,VK_UP,VK_PRIOR,VK_LEFT,VK_RIGHT,VK_END,VK_DOWN,VK_NEXT,VK_INSERT,VK_DELETE,
-   0,0,0,VK_SHIFT,VK_MENU,VK_CONTROL
+   VK_NUMPAD2,VK_NUMPAD3,VK_NUMPAD0,VK_DELETE,0,0,0,VK_F11,VK_F12,0,0,0,0,0,0,0,
+   0,VK_RCONTROL,0,0,VK_RMENU,0,VK_HOME,VK_UP,VK_PRIOR,VK_LEFT,VK_RIGHT,VK_END,VK_DOWN,VK_NEXT,VK_INSERT,VK_DELETE
 };
-static char className[] = "ECERE Application";
+static const uint16 className[] = L"Ecere Application";
 static HINSTANCE hInstance;
 
+static WPARAM lastBits;
+static LPARAM lastRes;
+
 static DEVMODE devMode;
+#ifndef ECERE_NODINPUT
 static HWND acquiredWindow = null;
+#endif
 static HCURSOR systemCursors[SystemCursor];
 static bool fullScreenMode;
 static int desktopX = 0, desktopY = 0, desktopW = 0, desktopH = 0;
 static DWORD hiResTimer;
-static HWND topWindow;
+// static HWND topWindow;
 
 static HWND startBar;
 
@@ -158,30 +171,93 @@ static bool EnumerateMonitors(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMoni
    return monitor < 32;
 }
 
+static bool externalDisplayChange;
+
 static int taskBarState;
 static WINDOWPLACEMENT taskBarPlacement;
 static bool activateApp;
 
 static SystemCursor lastCursor = (SystemCursor)-1;
 
+static void SmartShowWindow(HWND windowHandle, WindowState state, bool doActivate)
+{
+   int showCmd;
+   if(state == maximized)
+      showCmd = doActivate ? SW_SHOWMAXIMIZED : SW_MAXIMIZE;
+   else if(state == minimized)
+      showCmd = SW_MINIMIZE;
+   else
+      showCmd = doActivate ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE;
+   ShowWindow(windowHandle, showCmd);
+}
+
+void AeroSnapPosition(Window window, int x, int y, int w, int h)
+{
+   int oldX = window.absPosition.x;
+
+   // To prevent having a window < minClientSize with Aero Snap, because we don't receive a WM_SIZING!
+   // The sensible implementation of this is in WM_SIZING
+   {
+      int gw = w, gh = h;
+      MinMaxValue ew, eh;
+      window.GetDecorationsSize(&ew, &eh);
+
+      gw -= ew;
+      gh -= eh;
+
+      gw = Max(gw, 1);
+      gh = Max(gh, 1);
+
+      gw = Max(gw, window.minSize.w);
+      gh = Max(gh, window.minSize.h);
+      gw = Min(gw, window.maxSize.w);
+      gh = Min(gh, window.maxSize.h);
+
+      if(!window.OnResizing(&gw, &gh))
+      {
+         gw = window.clientSize.w;
+         gh = window.clientSize.h;
+      }
+
+      gw = Max(gw, window.skinMinSize.w);
+      gh = Max(gh, window.skinMinSize.h);
+
+      gw += ew;
+      gh += eh;
+
+      if(w != gw || h != gh)
+      {
+         bool move = false;
+         // Adjust x position if we resized from top or bottom left corner
+         if(x != oldX)
+         {
+            x += w - gw;
+            move = true;
+         }
+         w = gw;
+         h = gh;
+         guiApp.interfaceDriver.PositionRootWindow(window, x, y, w, h, move, true);
+      }
+   }
+   window.ExternalPosition(x, y, w, h);
+}
+
 class Win32Interface : Interface
 {
    class_property(name) = "Win32";
-   
+
    void ::RepositionDesktop(bool updateChildren)
    {
       int c;
       static double lastTime = 0, time;
       int x = 0, y = 0;
-      int w, h;
-      static Size lastScreen;
-      static Point lastScreenPos;
-      static WINDOWPLACEMENT lastPlacement;
-      static int tryAgain;
+      int w = 0, h = 0;
+      //static Size lastScreen;
+      //static Point lastScreenPos;
       static double lastAutoHideCheck = 0;
       int newTaskBarState = taskBarState;
-      HMONITOR primaryMonitor;
-            
+      HMONITOR primaryMonitor = 0;
+
       time = GetTime();
       if(time - lastTime < 0.1) return;
       lastTime = time;
@@ -190,7 +266,7 @@ class Win32Interface : Interface
       if(time - lastAutoHideCheck > 1)
       {
          APPBARDATA appBarData = { 0 };
-         newTaskBarState = SHAppBarMessage(ABM_GETSTATE, &appBarData);
+         newTaskBarState = (int)SHAppBarMessage(ABM_GETSTATE, &appBarData);
          lastAutoHideCheck = time;
       }
 
@@ -210,7 +286,7 @@ class Win32Interface : Interface
       memcpy(lastMonitorAreas, monitorAreas, sizeof(monitorAreas));
 
       guiApp.virtualScreen =
-      { 
+      {
          GetSystemMetrics(SM_CXVIRTUALSCREEN),
          GetSystemMetrics(SM_CYVIRTUALSCREEN)
       };
@@ -270,7 +346,7 @@ class Win32Interface : Interface
                }
             }
          }
-   
+
         if(c < monitor ||
          placement.rcNormalPosition.left != taskBarPlacement.rcNormalPosition.left ||
          placement.rcNormalPosition.top != taskBarPlacement.rcNormalPosition.top ||
@@ -288,8 +364,8 @@ class Win32Interface : Interface
             guiApp.SetDesktopPosition(x, y, w, h, updateChildren);
          }
 
-         lastScreen = guiApp.virtualScreen;
-         lastScreenPos = guiApp.virtualScreenPos;
+         //lastScreen = guiApp.virtualScreen;
+         //lastScreenPos = guiApp.virtualScreenPos;
       }
    }
 
@@ -304,7 +380,7 @@ class Win32Interface : Interface
       Key key;
       // UNICODE FIX
       bool frenchShift = (ch < 0x10000) ? (((VkKeyScan((uint16)ch) >> 8) & 6) == 6) : false;
-      
+
       if(msg == WM_CHAR || msg == WM_DEADCHAR)
       {
          wParam = 0;
@@ -327,28 +403,34 @@ class Win32Interface : Interface
          code = key;
       }
 
-      if(key != leftShift && key != rightShift && ::GetKeyState(VK_SHIFT) & 0x80000)
-         code.shift = true;
-      if(key != leftControl && key != rightControl && ::GetKeyState(VK_CONTROL) & 0x80000 && !frenchShift)
-         code.ctrl = true;
-      if(key != leftAlt && key != rightAlt && ::GetKeyState(VK_MENU) & 0x80000 && !frenchShift)
-         code.alt = true;
-      
       if(msg == WM_MOUSEWHEEL)
       {
+         if(::GetAsyncKeyState(VK_SHIFT) & 0x80000)
+            code.shift = true;
+         if(::GetAsyncKeyState(VK_CONTROL) & 0x80000)
+            code.ctrl = true;
+         if(::GetAsyncKeyState(VK_MENU) & 0x80000)
+            code.alt = true;
+
          result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit, code, 0);
       }
       else
       {
+         if(key != leftShift && key != rightShift && ::GetKeyState(VK_SHIFT) & 0x80000)
+            code.shift = true;
+         if(key != leftControl && key != rightControl && ::GetKeyState(VK_CONTROL) & 0x80000 && !frenchShift)
+            code.ctrl = true;
+         if(key != leftAlt && key != rightAlt && ::GetKeyState(VK_MENU) & 0x80000 && !frenchShift)
+            code.alt = true;
          /*
          byte ch = Interface::TranslateKeykey, code.shift);
          if(::GetKeyState(VK_CAPITAL))
             ch = toupper(ch);
          */
-         
+
          if(msg == WM_KEYUP || msg == WM_SYSKEYUP)
          {
-            result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp, code, ch); 
+            result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp, code, ch);
          }
          else
          {
@@ -369,14 +451,18 @@ class Win32Interface : Interface
                result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit, code,ch);
          }
       }
-               
+
       return result;
    }
 
    // --- Window procedure ---
    DWORD CALLBACK ::ApplicationWindow(HWND windowHandle, UINT msg, WPARAM wParam, LPARAM lParam)
    {
+#ifdef _WIN64
+      Window window = (Window)GetWindowLongPtr(windowHandle, GWLP_USERDATA);
+#else
       Window window = (Window)GetWindowLong(windowHandle, GWL_USERDATA);
+#endif
       static Point lastPos;
       if(window)
       {
@@ -397,7 +483,7 @@ class Win32Interface : Interface
                   if(wParam)
                   {
                      Window modalRoot = window.FindModal();
-                     
+
                      HWND modalWindow = modalRoot ? modalRoot.windowHandle : null;
 
                      FLASHWINFO flashInfo = { 0 };
@@ -416,33 +502,37 @@ class Win32Interface : Interface
                   {
                      HWND foreground;
                      DWORD id;
-                     uint windowLong;
+                     void * windowLong;
                      foreground = GetForegroundWindow();
                      if(foreground == windowHandle && lParam)
                         foreground = (HWND)lParam;
 
                      GetWindowThreadProcessId(foreground, &id);
 
-                     windowLong = GetWindowLong(foreground, GWL_WNDPROC);
+#ifdef _WIN64
+                     windowLong = (void*)GetWindowLongPtr(foreground, GWLP_WNDPROC);
+#else
+                     windowLong = (void*)GetWindowLong(foreground, GWL_WNDPROC);
+#endif
 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
                      // The != ApplicationWindow check is for not recognizing the Console window as an Ecere Window
                      // That check causes a problem with the OpenGL driver which seems to popup a window of a different class
                      if(window.displaySystem && window.displaySystem.driver == class(OpenGLDisplayDriver))
-                        windowLong = (uint)ApplicationWindow;
+                        windowLong = (void *)ApplicationWindow;
 #endif
-                     if(id != GetCurrentProcessId() || windowLong != (LPARAM)ApplicationWindow)
+                     if(id != GetCurrentProcessId() || windowLong != (void *)ApplicationWindow)
                         window.ExternalActivate(false, true, window, null);
                      // DefWindowProc for WM_NCACTIVATE draws the decorations, make sure it's drawn in the right state
-                     return DefWindowProc(windowHandle, msg, window.active, lParam);
+                     return (uint)DefWindowProc(windowHandle, msg, window.active, lParam);
                   }
                }
                if(activateApp)
                {
                   for(window = guiApp.desktop.firstChild; window; window = window.next)
                      SetWindowPos(window.windowHandle, window.style.stayOnTop ? HWND_TOPMOST : HWND_TOP, 0,0,0,0,
-                        SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOSIZE); //|SWP_NOREDRAW); 
+                        SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOSIZE); //|SWP_NOREDRAW);
                   activateApp = false;
-                } 
+               }
 
                return (uint)DefWindowProc(windowHandle, msg, window ? window.active : wParam, lParam);
             }
@@ -475,22 +565,22 @@ class Win32Interface : Interface
                   }
                   else
                   {
-                     Window window;
-                     
+                     //Window window;
+
                      if(wParam && !guiApp.desktop.active /*&& lParam != GetCurrentThreadID()*/)
                      {
                         activateApp = true;
                         /*
                         for(window = guiApp.desktop.firstChild; window; window = window.next)
                            SetWindowPos(window.windowHandle, window.style.stayOnTop ? HWND_TOPMOST : HWND_TOP, 0,0,0,0,
-                              SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOSIZE); //|SWP_NOREDRAW); 
-                        */ 
+                              SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOSIZE); //|SWP_NOREDRAW);
+                        */
                      }
-                     guiApp.SetAppFocus(wParam);
+                     guiApp.SetAppFocus((bool)wParam);
                   }
                }
-               else 
-                  guiApp.SetAppFocus(wParam);
+               else
+                  guiApp.SetAppFocus((bool)wParam);
                break;
             case WM_PAINT:
             {
@@ -509,20 +599,20 @@ class Win32Interface : Interface
                   BoxItem item = window.dirtyArea.count ? (BoxItem)ACCESS_ITEM(window.dirtyArea, window.dirtyArea.first) : null;
 
                   BeginPaint(windowHandle, &ps);
-                  
+
                   // Prevent flickering if we're going to update anyways
                   /*
-                  printf("   Paint message (%d, %d)-(%d, %d)\n", 
+                  printf("   Paint message (%d, %d)-(%d, %d)\n",
                      item ? item.box.left : 0,
                      item ? item.box.top : 0,
                      item ? item.box.right : 0,
                      item ? item.box.bottom : 0);
                   */
-                  // Causes redraw bug...      
+                  // Causes redraw bug...
                   if(!window.manageDisplay || !item ||
-                     item.box.left > 0 || 
+                     item.box.left > 0 ||
                      item.box.top > 0 ||
-                     item.box.right < window.size.w - 1 || 
+                     item.box.right < window.size.w - 1 ||
                      item.box.bottom < window.size.h - 1)
                   {
                      Box box { ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right-1, ps.rcPaint.bottom-1 };
@@ -536,35 +626,44 @@ class Win32Interface : Interface
             }
             case WM_DISPLAYCHANGE:
             {
-               static int lastBits = 0;
-               static int lastRes = 0;
-               if(lastBits != wParam || lastRes != lParam)
+               if(!guiApp.fullScreenMode && (lastBits != wParam || lastRes != lParam))
                {
+                  RECT rect;
+                  HWND foregroundWindow = GetForegroundWindow();
+                  int w = LOWORD(lParam);
+                  int h = HIWORD(lParam);
+
+                  GetWindowRect(foregroundWindow, &rect);
+                  if(rect.right == w && rect.bottom == h)
+                     break;
+
                   lastBits = wParam;
                   lastRes = lParam;
-               
+
+                  externalDisplayChange = true;
                   if(guiApp.desktop.DisplayModeChanged())
                   {
                      char caption[2048];
                      if(!window.style.hidden)
-                        ShowWindow(windowHandle, SW_SHOWNOACTIVATE /*SW_SHOWNORMAL*/);
+                        SmartShowWindow(window.windowHandle, (window.nativeDecorations && window.state == maximized) ? maximized : normal, false);
                      window.FigureCaption(caption);
                      SetRootWindowCaption(window, caption);
                   }
+                  externalDisplayChange = false;
                }
                break;
             }
             // Keyboard Messages
             case WM_SYSKEYDOWN:
             case WM_KEYDOWN:
-            case WM_SYSKEYUP: 
+            case WM_SYSKEYUP:
             case WM_KEYUP:
-            case WM_CHAR: 
-            //case WM_DEADCHAR: 
+            case WM_CHAR:
+            //case WM_DEADCHAR:
             {
                MSG charMsg;
-               DWORD min, max;
-               
+               DWORD min = 0, max = 0;
+
                if(msg != WM_CHAR && window.composing)
                   break;
 
@@ -572,7 +671,7 @@ class Win32Interface : Interface
                {
                   case WM_SYSKEYDOWN: min = max = WM_SYSCHAR; break;
                   case WM_KEYDOWN: min = max = WM_CHAR; break;
-                  case WM_SYSKEYUP: min = WM_SYSCHAR;  max = WM_SYSDEADCHAR; break;
+                  case WM_SYSKEYUP: min = WM_SYSCHAR; max = WM_SYSDEADCHAR; break;
                   case WM_KEYUP: min = WM_CHAR; max = WM_DEADCHAR; break;
                }
 
@@ -582,12 +681,20 @@ class Win32Interface : Interface
                incref window;
                if(msg == WM_CHAR || msg == WM_DEADCHAR || PeekMessage(&charMsg, windowHandle, min, max, PM_REMOVE))
                {
-                  ch = (msg == WM_CHAR || msg == WM_DEADCHAR) ? wParam : (unichar)charMsg.wParam;
+                  ch = (msg == WM_CHAR || msg == WM_DEADCHAR) ? (unichar)wParam : (unichar)charMsg.wParam;
+                  // TOCHECK: What is this for again? Fixing some obscure activation status?
+                  // -- I believe this was somehow allowing 'unmaximizing', but was causing problems
+                  // as there was no way to prevent AltEnter from doing so (e.g. when it is used for a node property)
+                  // Worked around by fixing ProcessHotKeys to properly check for sysButtons in parent.parent when sys buttons
+                  // are placed inside a menu bar for a document
+                  /*
                   if(msg == WM_SYSKEYDOWN && ch == 13)
                   {
-                     ShowWindow(window.windowHandle, SW_SHOWNORMAL);
+                     ShowWindow(window.windowHandle, window.state == maximized ? SW_MAXIMIZE : SW_SHOWNORMAL);
+                     // This last line been commented out for a long time:
                      // window.ExternalActivate(true, true, window, null);
                   }
+                  */
                   if(msg == WM_SYSKEYUP || msg == WM_KEYUP)
                   {
                      if(!ProcessKeyMessage(window, WM_KEYDOWN, 0x40000000, 0, ch))
@@ -650,7 +757,7 @@ class Win32Interface : Interface
                      font.lfOutPrecision = OUT_DEFAULT_PRECIS;
                      font.lfClipPrecision = CLIP_DEFAULT_PRECIS;
                      font.lfQuality = DEFAULT_QUALITY;
-                     font.lfPitchAndFamily = (byte)DEFAULT_PITCH|FF_DONTCARE; // TODO: Fix compiler 0 | 0 to produce byte, not int
+                     font.lfPitchAndFamily = (byte)(DEFAULT_PITCH|FF_DONTCARE); // TODO: Fix compiler 0 | 0 to produce byte, not int
                      UTF8toUTF16Buffer(res.faceName, font.lfFaceName, LF_FACESIZE);
 
                      ImmSetCompositionFont(ctx, &font);
@@ -692,7 +799,7 @@ class Win32Interface : Interface
                   return HTCLIENT;
 
             // Mouse Messages
-            case WM_LBUTTONUP:  
+            case WM_LBUTTONUP:
             case WM_RBUTTONUP:
             case WM_MBUTTONUP:
             case WM_LBUTTONDOWN:
@@ -704,7 +811,7 @@ class Win32Interface : Interface
             case WM_MOUSEMOVE:
                x = window.absPosition.x;
                y = window.absPosition.y;
-            /*case WM_NCLBUTTONUP:  
+            /*case WM_NCLBUTTONUP:
             case WM_NCRBUTTONUP:
             case WM_NCMBUTTONUP:
             case WM_NCLBUTTONDOWN:
@@ -712,16 +819,16 @@ class Win32Interface : Interface
             case WM_NCRBUTTONDOWN:
             case WM_NCRBUTTONDBLCLK:
             case WM_NCMBUTTONDOWN:
-            case WM_NCMBUTTONDBLCLK:
-            case WM_NCMOUSEMOVE:*/
+            case WM_NCMBUTTONDBLCLK:*/
+            case WM_NCMOUSEMOVE:
             {
                Modifiers code = 0;
                bool consequential = false;
+
                x += (short)LOWORD(lParam);
                y += (short)HIWORD(lParam);
 
-               if(window.nativeDecorations)
+               if(window.nativeDecorations && msg != WM_NCMOUSEMOVE)
                {
                   x += window.clientStart.x;
                   y += window.clientStart.y - (window.hasMenuBar ? skinMenuHeight : 0);
@@ -733,7 +840,7 @@ class Win32Interface : Interface
                if(wParam & MK_LBUTTON) code.left = true;
                if(wParam & MK_MBUTTON) code.middle = true;
                if(wParam & MK_RBUTTON) code.right = true;
-               
+
                if(msg == WM_MOUSEMOVE)
                {
                   if(lastPos.x == x && lastPos.y == y)
@@ -745,7 +852,7 @@ class Win32Interface : Interface
                incref window;
                switch(msg)
                {
-                  //case WM_NCMOUSEMOVE:
+                  case WM_NCMOUSEMOVE:
                   case WM_MOUSEMOVE:
                      window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove, x,y,&code, consequential, false);
                      break;
@@ -755,8 +862,8 @@ class Win32Interface : Interface
                         break;
                   //case WM_NCLBUTTONDOWN:
                   case WM_LBUTTONDOWN:
-                     window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown,x,y,&code, false, 
-                                             (msg == WM_LBUTTONDBLCLK) ? false: true);
+                     window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown,x,y,&code, false,
+                                             /*(msg == WM_LBUTTONDBLCLK) ? false: */true);
                      break;
                   //case WM_NCLBUTTONUP:
                   case WM_LBUTTONUP:      window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp, x,y,&code, false, false);break;
@@ -766,7 +873,7 @@ class Win32Interface : Interface
                         break;
                   //case WM_NCMBUTTONDOWN:
                   case WM_MBUTTONDOWN:
-                     window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown, x,y,&code, false, 
+                     window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown, x,y,&code, false,
                                              (msg == WM_LBUTTONDBLCLK) ? false: true);
                      break;
                   //case WM_NCMBUTTONUP:
@@ -779,7 +886,7 @@ class Win32Interface : Interface
                         break;
                   //case WM_NCRBUTTONDOWN:
                   case WM_RBUTTONDOWN:
-                     window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown, x,y,&code, false, 
+                     window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown, x,y,&code, false,
                                              (msg == WM_LBUTTONDBLCLK) ? false: true);
                      break;
                   //case WM_NCRBUTTONUP:
@@ -788,6 +895,8 @@ class Win32Interface : Interface
                      break;
                }
                delete window;
+               if(msg == WM_NCMOUSEMOVE)
+                  return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
                break;
             }
             case WM_SETCURSOR:
@@ -816,51 +925,92 @@ class Win32Interface : Interface
             }
             case WM_MOVE:
             {
-               int x, y;
+               int x, y, w, h;
                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);
+
+               x = rcWindow.left - desktopX;
+               y = rcWindow.top  - desktopY;
+               w = rcWindow.right - rcWindow.left;
+               h = rcWindow.bottom - rcWindow.top;
+
+               AeroSnapPosition(window, x, y, w, h);
                break;
             }
+            /*case WM_MOVING:
+               break;*/
+            case WM_SIZING:
+            {
+               RECT * rect = (RECT *)lParam;
+               MinMaxValue ew, eh;
+               int w, h;
+
+               window.GetDecorationsSize(&ew, &eh);
+
+               w = rect->right - rect->left;
+               h = rect->bottom - rect->top;
+
+               w -= ew;
+               h -= eh;
+
+               w = Max(w, 1);
+               h = Max(h, 1);
+
+               w = Max(w, window.minSize.w);
+               h = Max(h, window.minSize.h);
+               w = Min(w, window.maxSize.w);
+               h = Min(h, window.maxSize.h);
+
+               if(!window.OnResizing(&w, &h))
+               {
+                  w = window.clientSize.w;
+                  h = window.clientSize.h;
+               }
+
+               w = Max(w, window.skinMinSize.w);
+               h = Max(h, window.skinMinSize.h);
+
+               w += ew;
+               h += eh;
+
+               if(wParam == WMSZ_BOTTOMLEFT || wParam == WMSZ_LEFT || wParam == WMSZ_TOPLEFT)
+                  rect->left = rect->right - w;
+               else
+                  rect->right = rect->left + w;
+
+               if(wParam == WMSZ_TOPLEFT || wParam == WMSZ_TOP || wParam == WMSZ_TOPRIGHT)
+                  rect->top = rect->bottom - h;
+               else
+                  rect->bottom = rect->top + h;
+
+               return 1;
+            }
             case WM_SIZE:
             {
                if(window.nativeDecorations)
                {
-                  int w = LOWORD(lParam);
-                  int h = HIWORD(lParam);
-                  int x, y;
-                  WINDOWPLACEMENT placement = { 0 };
+                  int x, y, w, h;
                   RECT rcWindow;
                   GetWindowRect(windowHandle, &rcWindow);
 
-                  placement.length = sizeof(WINDOWPLACEMENT);
-
-                  GetWindowPlacement(windowHandle, &placement);
-                  if((placement.showCmd == SW_SHOWMAXIMIZED || placement.showCmd == SW_MAXIMIZE) && window.state != maximized)
+                  if(wParam == SIZE_MAXIMIZED && window.state != maximized)
                      window.state = maximized;
-                  else if(placement.showCmd == SW_SHOWMINIMIZED && window.state != minimized)
+                  else if(wParam == SIZE_MINIMIZED && window.state != minimized)
                      window.state = minimized;
-                  else if(placement.showCmd == SW_SHOWNORMAL && window.state != normal && window.visible)
+                  else if(wParam == SIZE_RESTORED && window.state != normal && window.visible)
                      window.state = normal;
 
-                  x = rcWindow.left;
-                  y = rcWindow.top;
+                  x = rcWindow.left - desktopX;
+                  y = rcWindow.top  - desktopY;
                   w = rcWindow.right - rcWindow.left;
                   h = rcWindow.bottom - rcWindow.top;
-                  window.ExternalPosition(x, y, w, h);
-                  window.UpdateDisplay();
+
+                  AeroSnapPosition(window, x, y, w, h);
+                  if(!guiApp.modeSwitching)
+                     window.UpdateVisual(null);
                }
                else
                   return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
@@ -891,15 +1041,15 @@ class Win32Interface : Interface
 
    bool CALLBACK ::JoystickAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, void * context )
    {
-      DIPROPRANGE diprg; 
+      DIPROPRANGE diprg;
       IDirectInputDevice2 * curJoy = (IDirectInputDevice2 *)context;
 
-      diprg.diph.dwSize       = sizeof(DIPROPRANGE); 
-      diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); 
-      diprg.diph.dwHow        = DIPH_BYOFFSET; 
+      diprg.diph.dwSize       = sizeof(DIPROPRANGE);
+      diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+      diprg.diph.dwHow        = DIPH_BYOFFSET;
       diprg.diph.dwObj        = pdidoi->dwOfs;
-      diprg.lMin              = -128; 
-      diprg.lMax              = 127; 
+      diprg.lMin              = -128;
+      diprg.lMax              = 127;
       if(curJoy->lpVtbl->SetProperty(curJoy, DIPROP_RANGE, &diprg.diph))
          return DIENUM_STOP;
       return DIENUM_CONTINUE;
@@ -909,7 +1059,7 @@ class Win32Interface : Interface
    void ::TerminateDirectInput()
    {
       int j;
-      if (directMouse) 
+      if (directMouse)
       {
          directMouse->lpVtbl->Unacquire(directMouse);
          directMouse->lpVtbl->Release(directMouse);
@@ -918,7 +1068,7 @@ class Win32Interface : Interface
    #ifndef ECERE_NOJOYSTICK
       for(j=0; j<numJoysticks; j++)
       {
-         if (directJoysticks[j]) 
+         if (directJoysticks[j])
          {
             directJoysticks[j]->lpVtbl->Unacquire(directJoysticks[j]);
             directJoysticks[j]->lpVtbl->Release(directJoysticks[j]);
@@ -927,7 +1077,7 @@ class Win32Interface : Interface
       }
       numJoysticks = 0;
    #endif
-      if(dInput) 
+      if(dInput)
       {
          dInput->lpVtbl->Release(dInput);
          dInput = null;
@@ -964,7 +1114,7 @@ class Win32Interface : Interface
                dInput->lpVtbl->EnumDevices(dInput, DIDEVTYPE_JOYSTICK, JoystickCallback, null, DIEDFL_ATTACHEDONLY );
                for(j=0; j<NUMJOY; j++)
                   if(directJoysticks[j])
-                     if(!directJoysticks[j]->lpVtbl->SetDataFormat(directJoysticks[j], &c_dfDIJoystick )) 
+                     if(!directJoysticks[j]->lpVtbl->SetDataFormat(directJoysticks[j], &c_dfDIJoystick ))
                         directJoysticks[j]->lpVtbl->EnumObjects(directJoysticks[j], JoystickAxesCallback, directJoysticks[j], DIDFT_AXIS );
    #endif
                result = true;
@@ -976,8 +1126,6 @@ class Win32Interface : Interface
 
    void ::AcquireDirectInput(HWND windowHandle, bool state)
    {
-      POINT oldPosition;
-
       if((state && !acquiredWindow) || (!state && acquiredWindow == windowHandle))
       {
          int j;
@@ -988,7 +1136,7 @@ class Win32Interface : Interface
                directMouse->lpVtbl->SetCooperativeLevel(directMouse, /*fullScreenMode ? */windowHandle /*: HWND_DESKTOP*/, DISCL_EXCLUSIVE|DISCL_FOREGROUND);
                directMouse->lpVtbl->Acquire(directMouse);
             }
-            else 
+            else
                directMouse->lpVtbl->Unacquire(directMouse);
          }
    #ifndef ECERE_NOJOYSTICK
@@ -1026,7 +1174,11 @@ class Win32Interface : Interface
       /// DRIVER IMPLEMENTATION /////////////
    ****************************************************************************/
 
+#ifdef _WIN64
+   void CALLBACK ::TimerProc(UINT uTimerID, UINT uMsg, uint64 dwUser, uint64 dw1, uint64 dw2)
+#else
    void CALLBACK ::TimerProc(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
+#endif
    {
       guiApp.SignalEvent();
    }
@@ -1034,15 +1186,21 @@ class Win32Interface : Interface
    // --- User Interface System ---
    bool Initialize()
    {
-      WNDCLASS wcl = 
-      { 
-         CS_DBLCLKS, ApplicationWindow, 0L, 0L, 0, 
-         LoadIcon(null, IDI_APPLICATION), 
+      WNDCLASS wcl =
+      {
+         CS_DBLCLKS, ApplicationWindow, 0L, 0L, 0,
+         LoadIcon(null, IDI_APPLICATION),
          null,
          null,
          null,
          className
       };
+      HDC hdc = GetDC(0);
+      lastRes = MAKELPARAM(GetSystemMetrics(SM_CYSCREEN), GetSystemMetrics(SM_CXSCREEN));
+      lastBits = (WPARAM)GetDeviceCaps(hdc, BITSPIXEL);
+      ReleaseDC(0, hdc);
+
+      AttachConsole(-1);
       wcl.hInstance = hInstance = GetModuleHandle(null);
       RegisterClass(&wcl);
 
@@ -1075,7 +1233,7 @@ class Win32Interface : Interface
          1000.0 / 500.0,
          TimerProc,0,TIME_PERIODIC);
          */
-      
+
    /*
       topWindow = CreateWindowEx(0, className, "",WS_POPUP,0,0,1,1,HWND_DESKTOP,
          null, hInstance, null);
@@ -1096,7 +1254,7 @@ class Win32Interface : Interface
       if(hiResTimer) timeKillEvent(hiResTimer);
       if(hertz)
          hiResTimer = timeSetEvent(1000 / hertz, 1000 / hertz, TimerProc, 0, TIME_PERIODIC);
-   }  
+   }
 
    bool ProcessInput(bool processAll)
    {
@@ -1132,11 +1290,11 @@ class Win32Interface : Interface
 
    }
 
-   char ** GraphicsDrivers(int * numDrivers)
+   const char ** GraphicsDrivers(int * numDrivers)
    {
-      static char *graphicsDrivers[] = { "GDI", "DirectDraw", "OpenGL", "Direct3D", "Direct3D8", "Direct3D9" };
+      static const char *graphicsDrivers[] = { "GDI", "DirectDraw", "OpenGL", "Direct3D", "Direct3D8", "Direct3D9" };
       *numDrivers = sizeof(graphicsDrivers) / sizeof(char *);
-      return (char **)graphicsDrivers;
+      return (const char **)graphicsDrivers;
    }
 
    void GetCurrentMode(bool * fullScreen, Resolution * resolution, PixelFormat * colorDepth, int * refreshRate)
@@ -1217,73 +1375,65 @@ class Win32Interface : Interface
       {
          windowHandle = CreateWindowEx(0, className, text,
                         WS_POPUP,
-                        0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN), 
-                        HWND_DESKTOP, 
+                        0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),
+                        HWND_DESKTOP,
                         null, hInstance, null);
          ShowWindow(windowHandle, SW_SHOWNORMAL);
       }
       else if(window.systemParent)
-         windowHandle = CreateWindowEx(0, className, text, 
+         windowHandle = CreateWindowEx(0, className, text,
          WS_CHILD,0,0,1,1, window.systemParent, null, hInstance, null);
       else
       {
          DWORD style = 0;
          DWORD exStyle = 0;
          HWND parentWindow = null; //HWND_DESKTOP; // we get different behaviors with desktop...
+         Window master = window.master, rootWindow = (master && master != guiApp.desktop) ? master.rootWindow : null;
          if(window.style.stayOnTop)
             exStyle |= WS_EX_TOPMOST;
 
-         // exStyle |= WS_EX_TOOLWINDOW;
-
-         if(window.master.rootWindow && window.master.rootWindow != guiApp.desktop && (window.style.modal || window.style.interim))
-         {
-            Window master = window.master;
-            Window rootWindow = window.master.rootWindow;
-
+         if(rootWindow && (window._isModal || window.style.interim))
             parentWindow = rootWindow.is3D ? rootWindow.parent.windowHandle : rootWindow.windowHandle;
 
-            // parentWindow = window.master.rootWindow.is3D ? window.master.rootWindow.parent.windowHandle : window.master.rootWindow.windowHandle;
-         }
-            
          if(window.alphaBlend)
          // if(window.background.a < 255) //&& window.style & ES_REDRAW) Not needed anymore?
             exStyle |= WS_EX_LAYERED; // | WS_EX_TRANSPARENT;
 
-         if(window.style.showInTaskBar)
+         // Toolwindow will disappear if they don't have AppWindow set
+         if(window.style.showInTaskBar || (!parentWindow && window.style.thin))
          {
             exStyle |= WS_EX_APPWINDOW;
             parentWindow = null;
-            style |= WS_SYSMENU;
          }
-         else if(window.master.rootWindow && window.master.rootWindow != guiApp.desktop)
-         {
+
+         if(window.style.thin)
             exStyle |= WS_EX_TOOLWINDOW;
-            //exStyle |=  WS_EX_APPWINDOW;
-            style |= WS_SYSMENU;
-         }
-         else
-         {
-            // exStyle |= WS_EX_APPWINDOW;
-            style |= WS_SYSMENU;
-         }
-         /*else if(parentWindow)
-            exStyle |= WS_EX_TOOLWINDOW;*/
-         /*if(window.interim)
-            parentWindow = window.master.rootWindow.windowHandle;*/
 
          if(window.windowHandle)
             windowHandle = window.windowHandle;
          else
          {
             if(window.nativeDecorations)
-               style |= WS_OVERLAPPEDWINDOW;
+            {
+               BorderBits borderStyle = window.borderStyle; // FIXME!
+               style = WS_OVERLAPPED;
+               if(borderStyle.fixed)
+                  style |= WS_CAPTION;
+               if(window.hasClose)
+                  style |= WS_SYSMENU;
+               if(borderStyle.sizable)
+                  style |= WS_THICKFRAME;
+               if(window.hasMinimize)
+                  style |= WS_MINIMIZEBOX;
+               if(window.hasMaximize)
+                  style |= WS_MAXIMIZEBOX;
+            }
             windowHandle = CreateWindowEx(
                exStyle,
                className, text,
-               style | (window.systemParent ? WS_CHILD : 
+               style | (window.systemParent ? WS_CHILD :
                (WS_POPUP | (window.style.hasMinimize ? WS_MINIMIZEBOX : 0))),
                   0,0,1,1, parentWindow, null, hInstance, null);
-               
    #if 0
             if(exStyle & WS_EX_LAYERED)
                SetLayeredWindowAttributes(windowHandle, 0, 255 /*A(window.background)*/, LWA_ALPHA);
@@ -1291,34 +1441,53 @@ class Win32Interface : Interface
          }
       }
       delete text;
+#ifdef _WIN64
+      SetWindowLongPtr(windowHandle, GWLP_USERDATA, (int64)window);
+#else
       SetWindowLong(windowHandle, GWL_USERDATA, (DWORD)window);
+#endif
 
       return windowHandle;
    }
 
    void DestroyRootWindow(Window window)
    {
-      HICON oldIcon = (HICON)SendMessage(window.windowHandle, WM_GETICON, ICON_BIG, 0);
+      HICON oldIcon;
+      int c, lockCount = guiApp.lockMutex.lockCount;
+      for(c = 0; c < lockCount; c++)
+         guiApp.lockMutex.Release();
+
+      oldIcon = (HICON)SendMessage(window.windowHandle, WM_GETICON, ICON_BIG, 0);
+#ifdef _WIN64
+      if(oldIcon && oldIcon != (HICON)GetClassLongPtr(window.windowHandle, GCLP_HICON))
+#else
       if(oldIcon && oldIcon != (HICON)GetClassLong(window.windowHandle, GCL_HICON))
-      {
+#endif
          DestroyIcon(oldIcon);
-      }
 
-      // TO FIX LOCK UP PROBLEMS...  WOULD NEED TO UNLOCK ALL RECURSIONS ((GuiApplication)__thisModule.application).Unlock();
        ShowWindow(window.windowHandle, SW_HIDE);
-      // TO FIX LOCK UP PROBLEMS...  WOULD NEED TO LOCK ALL RECURSIONS((GuiApplication)__thisModule.application).Lock();
 
+#ifdef _WIN64
+      SetWindowLongPtr(window.windowHandle, GWLP_USERDATA, (int64)null);
+#else
       SetWindowLong(window.windowHandle, GWL_USERDATA, 0);
+#endif
       DestroyWindow(window.windowHandle);
+
+      for(c = 0; c < lockCount; c++)
+         guiApp.lockMutex.Wait();
+
       window.windowHandle = null;
    }
 
    // -- Window manipulation ---
 
-   void SetRootWindowCaption(Window window, char * name)
+   void SetRootWindowCaption(Window window, const char * name)
    {
       uint16 * text = UTF8toUTF16(name, null);
+      guiApp.Unlock();
       SetWindowText(window.windowHandle, text);
+      guiApp.Lock();
       delete text;
    }
 
@@ -1342,7 +1511,7 @@ class Win32Interface : Interface
          flags &=~SWP_NOMOVE;
          flags |= SWP_NOSIZE;
       }*/
-      if(!window.nativeDecorations || window.state != maximized || !window.visible)
+      if(!window.nativeDecorations || window.state != maximized || !window.visible || guiApp.modeSwitching)
          SetWindowPos(window.windowHandle, null, x, y, w, h, flags);
    }
 
@@ -1354,7 +1523,6 @@ class Win32Interface : Interface
 
    void SetRootWindowColor(Window window)
    {
-      DWORD style = GetWindowLong(window.windowHandle, GWL_EXSTYLE);
       if(window.alphaBlend && window.display.pixelFormat == pixelFormat888)
       {
          /*if(A(window.background) == 255)
@@ -1365,12 +1533,13 @@ class Win32Interface : Interface
          else*/
          {
 #ifndef ECERE_NOBLENDING
+            DWORD style = GetWindowLong(window.windowHandle, GWL_EXSTYLE);
             if((style & WS_EX_LAYERED) != WS_EX_LAYERED)
                SetWindowLong(window.windowHandle, GWL_EXSTYLE, style | WS_EX_LAYERED);
 #endif
             // SetLayeredWindowAttributes(window.windowHandle, 0, 255 /*Max(A(window.background),1)*/, LWA_ALPHA);
          }
-      }  
+      }
    }
 
    void OffsetWindow(Window window, int * x, int * y)
@@ -1393,17 +1562,19 @@ class Win32Interface : Interface
    {
       if(visible)
       {
+         WindowState curState = window.state;
+         *&window.state = state;
          switch(state)
          {
             case maximized:
             case normal:
-               ShowWindow(window.windowHandle, (window.creationActivation == activate && !guiApp.modeSwitching) ? 
-                  ((window.nativeDecorations && state == maximized) ? SW_MAXIMIZE : SW_SHOWNORMAL) : SW_SHOWNOACTIVATE);
+               SmartShowWindow(window.windowHandle, window.nativeDecorations ? state : normal, (window.active || window.creationActivation == activate) && !externalDisplayChange);
                break;
             case minimized:
                ShowWindow(window.windowHandle, SW_MINIMIZE);
                break;
          }
+         *&window.state = curState;
       }
       else
       {
@@ -1413,18 +1584,25 @@ class Win32Interface : Interface
 
    void ActivateRootWindow(Window window)
    {
-      if(!guiApp.modeSwitching)
+      if(!externalDisplayChange)
          SetForegroundWindow(window.windowHandle);
    }
 
    void FlashRootWindow(Window window)
    {
+      HWND hwnd = window.windowHandle;
       FLASHWINFO flashInfo = { 0 };
+      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;
+
       flashInfo.cbSize = sizeof(FLASHWINFO);
-      flashInfo.hwnd = window.windowHandle;
+      flashInfo.hwnd = hwnd;
       flashInfo.uCount = 1;
       flashInfo.dwFlags = FLASHW_TRAY; // FLASHW_ALL;
+      guiApp.Unlock();
       FlashWindowEx((void *)&flashInfo);
+      guiApp.Lock();
    }
 
    // --- Mouse-based window movement ---
@@ -1438,7 +1616,8 @@ class Win32Interface : Interface
       {
          SetWindowPos(window.windowHandle, HWND_TOPMOST, 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
          mouse_event(MOUSEEVENTF_LEFTDOWN, x, y, 0, 0);
-         SetWindowPos(window.windowHandle, HWND_NOTOPMOST, 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
+         if(!window.stayOnTop)
+            SetWindowPos(window.windowHandle, HWND_NOTOPMOST, 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
       }
    }
 
@@ -1478,7 +1657,7 @@ class Win32Interface : Interface
 
    // -- Mouse cursor ---
 
-   void SetMouseCursor(SystemCursor cursor)
+   void SetMouseCursor(Window window, SystemCursor cursor)
    {
       if(lastCursor != cursor)
       {
@@ -1492,7 +1671,7 @@ class Win32Interface : Interface
    void SetCaret(int x, int y, int size)
    {
 
-   }  
+   }
 
    // --- Clipboard manipulation ---
 
@@ -1518,7 +1697,7 @@ class Win32Interface : Interface
       bool result = false;
       if(clipBoard.text)
       {
-         uint wordCount;
+         int wordCount;
          uint16 * u16text = UTF8toUTF16(clipBoard.text, &wordCount);
          wordCount++;
          clipBoard.handle = GlobalAlloc(GHND | GMEM_DDESHARE, wordCount * 2);
@@ -1552,7 +1731,7 @@ class Win32Interface : Interface
       bool result = false;
        if(OpenClipboard(null))
        {
-         if(clipBoard.handle = GetClipboardData(CF_UNICODETEXT))
+         if((clipBoard.handle = GetClipboardData(CF_UNICODETEXT)))
          {
             uint16 * u16text = GlobalLock(clipBoard.handle);
             if(u16text)
@@ -1615,6 +1794,15 @@ class Win32Interface : Interface
 
       if(x)*x = dims.lX;
       if(y)*y = dims.lY;
+      if(dims.lZ)
+      {
+#ifdef _WIN64
+         Window window = (Window)GetWindowLongPtr(acquiredWindow, GWLP_USERDATA);
+#else
+         Window window = (Window)GetWindowLong(acquiredWindow, GWL_USERDATA);
+#endif
+         ProcessKeyMessage(window, WM_MOUSEWHEEL, ((uint16)(short)dims.lZ) << 16, 0, 0);
+      }
       if(buttons)
       {
          *buttons = MouseButtons {
@@ -1623,7 +1811,7 @@ class Win32Interface : Interface
              middle = (dims.rgbButtons[2] & 0x80) ? true : false };
       }
    #endif
-      
+
       return result;
    }
 
@@ -1635,9 +1823,9 @@ class Win32Interface : Interface
       {
          DIJOYSTATE dijs = {0};
    #ifndef ECERE_NOJOYSTICK
-         if(acquiredWindow && device < numJoysticks) 
+         if(acquiredWindow && device < numJoysticks)
          {
-            if(directJoysticks[device]) 
+            if(directJoysticks[device])
             {
                directJoysticks[device]->lpVtbl->Poll(directJoysticks[device]);
                if(directJoysticks[device]->lpVtbl->GetDeviceState(directJoysticks[device], sizeof(DIJOYSTATE), &dijs ))
@@ -1652,7 +1840,7 @@ class Win32Interface : Interface
          joystick.rx = dijs.lRx;
          joystick.ry = dijs.lRy;
          joystick.rz = dijs.lRz;
-         joystick.buttons = 
+         joystick.buttons =
               ((dijs.rgbButtons[0] & 0x80) ? JOY_BUTTON1 : 0)
             | ((dijs.rgbButtons[1] & 0x80) ? JOY_BUTTON2 : 0)
             | ((dijs.rgbButtons[2] & 0x80) ? JOY_BUTTON3 : 0)
@@ -1665,18 +1853,25 @@ class Win32Interface : Interface
    bool GetKeyState(Key key)
    {
       bool keyState = false;
-      if(key < 256)
+      if(key < 256 || key == alt || key == shift || key == control)
       {
-         if(key2VK[key])
-            keyState = GetAsyncKeyState(key2VK[key]);
-         keyState = (keyState & 0x80000) ? true : false;
+         uint ks = 0;
+         if(key == alt)
+            ks = GetAsyncKeyState(VK_MENU);
+         else if(key == control)
+            ks = GetAsyncKeyState(VK_CONTROL);
+         else if(key == shift)
+            ks = GetAsyncKeyState(VK_SHIFT);
+         else if(key2VK[key])
+            ks = GetAsyncKeyState(key2VK[key]);
+         keyState = (ks & 0x80000) ? true : false;
       }
       else if(key == capsState)
-         keyState = ::GetKeyState(VK_CAPITAL) & 0x00000001;
+         keyState = (::GetKeyState(VK_CAPITAL) & 0x00000001) != 0;
       else if(key == numState)
-         keyState = ::GetKeyState(VK_NUMLOCK) & 0x00000001;
+         keyState = (::GetKeyState(VK_NUMLOCK) & 0x00000001) != 0;
       else if(key == scrollState)
-         keyState = ::GetKeyState(VK_SCROLL) & 0x00000001;
+         keyState = (::GetKeyState(VK_SCROLL) & 0x00000001) != 0;
       return keyState;
    }
 
@@ -1685,6 +1880,20 @@ class Win32Interface : Interface
       HICON icon = null;
       HICON oldIcon = (HICON)SendMessage(window.windowHandle, WM_GETICON, ICON_BIG, 0);
 
+      // Dialogs Inherit master's icon if none set
+      if(!window.style.showInTaskBar && window.hasClose)
+      {
+         Window master = window.master;
+         while(master && !resource)
+         {
+            Window rootWindow = (master && master != guiApp.desktop) ? master.rootWindow : null;
+            if(rootWindow && rootWindow.icon)
+               resource = rootWindow.icon;
+            else
+               master = master.master;
+         }
+      }
+
       // WARNING -- putting this here as it is right after CreateRootWindow
       // Take out Layered flag if we're not in 24 bit
       {
@@ -1698,7 +1907,11 @@ class Win32Interface : Interface
          }
       }
 
+#ifdef _WIN64
+      if(oldIcon && oldIcon != (HICON)GetClassLongPtr(window.windowHandle, GCLP_HICON))
+#else
       if(oldIcon && oldIcon != (HICON)GetClassLong(window.windowHandle, GCL_HICON))
+#endif
       {
          DestroyIcon(oldIcon);
       }
@@ -1709,14 +1922,10 @@ class Win32Interface : Interface
          if(bitmap.Load(resource.fileName, null, null))
          {
             Bitmap and { };
-            int y, x;
             PixelFormat format = window.display.pixelFormat;
-            //int bits = 8<<GetColorDepthShifts(format);
-            int bits;
+            int bits = GetDepthBits(format);
             bool blend;
-            
-            bits = GetDepthBits(format);
-                        
+
             bitmap.Convert(null, pixelFormat888, null);
             and.Allocate(null, (bitmap.width+7/8), bitmap.height, 0, pixelFormat8, false);
 
@@ -1754,7 +1963,7 @@ class Win32Interface : Interface
             }
             if(bits == 15) { bits = 16; format = pixelFormat565; };
             bitmap.Convert(null, format, null);
-            
+
             icon = CreateIcon(hInstance, bitmap.width, bitmap.height, 1, (byte)bits, and.picture, bitmap.picture);
             delete and;
          }
@@ -1776,7 +1985,7 @@ class Win32Interface : Interface
          GetMonitorInfo(monitor, &info);
          // box = { info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom };
          box = { info.rcMonitor.left, info.rcMonitor.top, info.rcMonitor.right-1, info.rcMonitor.bottom-1 };
-         
+
          if(taskBarMonitor == monitor)
          {
             if(taskBarPlacement.rcNormalPosition.top <= box.top && taskBarPlacement.rcNormalPosition.bottom >= box.bottom)
@@ -1813,7 +2022,7 @@ class Win32Interface : Interface
          box.top -= desktopY;
          box.right -= desktopX;
          box.bottom -= desktopY;
-      }      
+      }
    }
 }