wip II
[sdk] / ecere / src / gui / Window.ec
index c9b922e..d05144e 100644 (file)
@@ -39,12 +39,17 @@ import "WindowList"
 import "i18n"
 
 // 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
+#ifdef HIGH_DPI
+define skinMenuHeight = 40;
+define statusBarHeight = 30;
+#else
 define skinMenuHeight = 25;
 define statusBarHeight = 18;
+#endif
 
 default extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown;
 
-public enum DialogResult { cancel, yes, no, ok };
+public enum DialogResult : int64 { cancel, yes, no, ok };
 
 public class MouseButtons
 {
@@ -498,7 +503,13 @@ private:
 
    Window()
    {
-      if(guiApp) guiApp.Initialize(true);
+      bool switchMode = true;
+#if defined(__ANDROID__)
+      switchMode = false;
+      fullRender = true;
+#endif
+      if(guiApp)
+         guiApp.Initialize(switchMode);
 
       if(guiApp && guiApp.currentSkin && ((subclass(Window))_class).pureVTbl)
       {
@@ -732,7 +743,7 @@ private:
       {
          int x = absPosition.x + clientStart.x;
          int y = absPosition.y + clientStart.y;
-         if(rootWindow.nativeDecorations)
+         if(rootWindow.nativeDecorations && rootWindow.windowHandle)
          {
             x -= rootWindow.clientStart.x;
             y -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
@@ -780,7 +791,7 @@ private:
       {
          int x = absPosition.x;
          int y = absPosition.y;
-         if(rootWindow.nativeDecorations)
+         if(rootWindow.nativeDecorations && rootWindow.windowHandle)
          {
             x -= rootWindow.clientStart.x;
             y -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
@@ -931,6 +942,7 @@ private:
    void ComputeAnchors(Anchor anchor, SizeAnchor sizeAnchor, int *ox, int *oy, int *ow, int *oh)
    {
       Window parent = this.parent ? this.parent : guiApp.desktop;
+      int xOffset = 0, yOffset = 0;
       int vpw = parent ? parent.clientSize.w : 0;
       int vph = parent ? parent.clientSize.h : 0;
       int pw = parent ? parent.clientSize.w : 0;
@@ -1025,12 +1037,46 @@ private:
       }
 
       // This is required to get proper initial decoration size using native decorations on Windows
-      if(nativeDecorations && guiApp && guiApp.interfaceDriver && !visible)
+#if defined(__WIN32__)
+      if(nativeDecorations && windowHandle && guiApp && guiApp.interfaceDriver && !visible)
          guiApp.interfaceDriver.PositionRootWindow(this, x, y, Max(1, size.w), Max(1, size.h), true, true);
+#endif
       GetDecorationsSize(&ew, &eh);
 
       if(anchor.left.type >= cascade && (state == normal /*|| state == Hidden*/))
       {
+         // Leave room for non client windows (eventually dockable panels)
+         Window win;
+         int loX = 0, loY = 0, hiX = pw, hiY = ph;
+         for(win = parent.children.first; win; win = win.next)
+         {
+            if(!win.isActiveClient && win.visible)
+            {
+               Size size = win.size;
+               Point pos = win.position;
+               int left = pos.x, top = pos.y;
+               int right = pos.x + size.w, bottom = pos.y + size.h;
+               if(win.size.w > win.size.h)
+               {
+                  if(bottom < ph / 4)
+                     loY = Max(loY, bottom);
+                  else if(top > ph - ph / 4)
+                     hiY = Min(hiY, top);
+               }
+               else
+               {
+                  if(right < pw / 4)
+                     loX = Max(loX, right);
+                  else if(left > pw - pw / 4)
+                     hiX = Min(hiX, left);
+               }
+            }
+         }
+         xOffset = loX;
+         yOffset = loY;
+         pw = hiX - loX;
+         ph = hiY - loY;
+
          if(parent.sbv && !parent.sbv.style.hidden) 
             pw += guiApp.currentSkin.VerticalSBW();
          if(parent.sbh && !parent.sbh.style.hidden)
@@ -1070,17 +1116,17 @@ private:
 
             if(positionID >= tilingSplit)
             {
-               x = pw * (tilingSplit / tilingH + (positionID - tilingSplit) / tilingLastH)/tilingW;
-               y = ph * ((positionID - tilingSplit) % tilingLastH) / tilingLastH;
-               x2 = pw * (tilingSplit/tilingH + (positionID - tilingSplit) / tilingLastH + 1)/tilingW;
-               y2 = ph * (((positionID - tilingSplit) % tilingLastH) + 1) / tilingLastH;
+               x = xOffset + pw * (tilingSplit / tilingH + (positionID - tilingSplit) / tilingLastH)/tilingW;
+               y = yOffset + ph * ((positionID - tilingSplit) % tilingLastH) / tilingLastH;
+               x2 = xOffset + pw * (tilingSplit/tilingH + (positionID - tilingSplit) / tilingLastH + 1)/tilingW;
+               y2 = yOffset + ph * (((positionID - tilingSplit) % tilingLastH) + 1) / tilingLastH;
             }
             else
             {
-               x = pw * (positionID / tilingH) / tilingW;
-               y = ph * (positionID % tilingH) / tilingH;
-               x2 = pw * (positionID / tilingH + 1) / tilingW;
-               y2 = ph * ((positionID % tilingH) + 1) / tilingH;
+               x = xOffset + pw * (positionID / tilingH) / tilingW;
+               y = yOffset + ph * (positionID % tilingH) / tilingH;
+               x2 = xOffset + pw * (positionID / tilingH + 1) / tilingW;
+               y2 = yOffset + ph * ((positionID % tilingH) + 1) / tilingH;
             }
             if(guiApp.textMode)
             {
@@ -1229,8 +1275,8 @@ private:
             cascadeH = (float)(ph - h) / (numCascade-1);
          }
 
-         x = (int)((positionID % numCascade) * cascadeW);
-         y = (int)((positionID % numCascade) * cascadeH);
+         x = (int)((positionID % numCascade) * cascadeW) + xOffset;
+         y = (int)((positionID % numCascade) * cascadeH) + yOffset;
       }
       else if(anchor.left.type < vTiled)
       {
@@ -1629,7 +1675,7 @@ private:
       SetPosition(x, y, w, h, true, modifyArea, updateScrollBars);
 
       clientResized = oldCW != clientSize.w || oldCH != clientSize.h || force;
-      if(clientResized && this == rootWindow && nativeDecorations)
+      if(clientResized && this == rootWindow && nativeDecorations && rootWindow.windowHandle)
          windowResized = true;
 
       if(display && rootWindow != this)
@@ -1699,14 +1745,17 @@ private:
                y -= guiApp.desktop.absPosition.y;
             }*/
             //guiApp.Log("Position %s\n", caption);
-            if(windowResized || windowMoved)
-               if(display && !display.flags.memBackBuffer && changeRootWindow)
-                  guiApp.interfaceDriver.PositionRootWindow(this, x, y, w, h, windowMoved, windowResized); //realResized);
+            if(windowHandle)
+            {
+               if(windowResized || windowMoved)
+                  if(display && !display.flags.memBackBuffer && changeRootWindow)
+                     guiApp.interfaceDriver.PositionRootWindow(this, x, y, w, h, windowMoved, windowResized); //realResized);
 
-            if(!guiApp.fullScreenMode && this != guiApp.desktop && (windowResized || windowMoved))
-               for(child = parent.children.first; child && child != this; child = child.next)
-                  if(child.rootWindow)
-                     guiApp.interfaceDriver.UpdateRootWindow(child.rootWindow);
+               if(!guiApp.fullScreenMode && this != guiApp.desktop && (windowResized || windowMoved))
+                  for(child = parent.children.first; child && child != this; child = child.next)
+                     if(child.rootWindow)
+                        guiApp.interfaceDriver.UpdateRootWindow(child.rootWindow);
+            }
 
             if(display)
             {
@@ -1720,7 +1769,7 @@ private:
                if(windowResized)
                {
                   // result = realResized ? display.Resize(size.w, size.h) : true;
-                  if(nativeDecorations)
+                  if(nativeDecorations && rootWindow.windowHandle)
                   {
                      int w = clientSize.w, h = clientSize.h;
                      if(hasMenuBar) h += skinMenuHeight;
@@ -1748,7 +1797,7 @@ private:
                   display.Unlock();
                }
             }
-            if(guiApp.driver && changeRootWindow)
+            if(guiApp.driver && changeRootWindow && windowHandle)
             {
                if(windowResized || windowMoved)
                   if(!display || display.flags.memBackBuffer)
@@ -1834,12 +1883,19 @@ private:
             }
             else
             {
+               int oldHRange = sbh ? sbh.range : 0;
+               int oldVRange = sbv ? sbv.range : 0;
                // Then start off with horizontal scrollbar range
                if(sbh)
                {
                   positionH = sbh.thumbPosition;
+
+                  /*
                   sbh.seen = cw;
                   sbh.total = rvw;
+                  */
+                  SBSetSeen(sbh, cw);
+                  SBSetTotal(sbh, rvw);
                   rangeH = sbh.range;
                   if(rangeH > 1)
                      ch -= guiApp.currentSkin.HorizontalSBH();
@@ -1849,8 +1905,12 @@ private:
                if(sbv)
                {
                   positionV = sbv.thumbPosition;
+                  /*
                   sbv.seen = ch;
                   sbv.total = rvh;
+                  */
+                  SBSetSeen(sbv, ch);
+                  SBSetTotal(sbv, rvh);
                   rangeV = sbv.range;
                   if(rangeV > 1)
                   {
@@ -1858,20 +1918,30 @@ private:
                      // Maybe we need to set the range on the horizontal scrollbar again
                      if(sbh)
                      {
+                        /*
                         sbh.seen = cw;
                         sbh.total = rvw;
-                        sbh.Action(setRange, positionH, 0);
+                        */
+                        SBSetSeen(sbh, cw);
+                        SBSetTotal(sbh, rvw);
+                        //sbh.Action(setRange, positionH, 0);
                         if(rangeH <= 1 && sbh.range > 1)
                         {
                            ch -= guiApp.currentSkin.HorizontalSBH();
+                           /*
                            sbv.seen = ch;
                            sbv.total = rvh;
+                           */
+                           SBSetSeen(sbv, ch);
+                           SBSetTotal(sbv, rvh);
                            rangeV = sbv.range;
-                           sbv.Action(setRange, positionV, 0);
+                           //sbv.Action(setRange, positionV, 0);
                         }
                         rangeH = sbh.range;
                      }
                   }
+                  if(sbh && sbh.range != oldHRange) sbh.Action(setRange, positionH, 0);
+                  if(sbv && sbv.range != oldVRange) sbv.Action(setRange, positionV, 0);
                }
 
                // Update the scrollbar visibility
@@ -2033,7 +2103,8 @@ private:
 
       if(sbh) // && !sbh.style.hidden
       {
-         sbh.Move(clientStart.x, clientStart.y + clientSize.h, clientSize.w,0);
+         if(!sbh.anchored)
+            sbh.Move(clientStart.x, clientStart.y + clientSize.h, clientSize.w,0);
          // Need to set the range again (should improve...) since the scrollbars didn't have
          // the right size when UpdateScrollArea set the range on it
          if(flag)
@@ -2044,7 +2115,8 @@ private:
       }
       if(sbv) // && !sbv.state.hidden
       {
-         sbv.Move(clientStart.x + clientSize.w, clientStart.y, 0, clientSize.h);
+         if(!sbv.anchored)
+            sbv.Move(clientStart.x + clientSize.w, clientStart.y, 0, clientSize.h);
          // Need to set the range again (should improve...) since the scrollbars didn't have
          // the right size when UpdateScrollArea set the range on it
          if(flag)
@@ -2163,14 +2235,11 @@ private:
       Window menuBarParent;
       for(menuBarParent = this; menuBarParent; menuBarParent = menuBarParent.parent)
       {
-         if(menuBarParent.menuBar) break;
-         if(menuBarParent.parent && /*menuBarParent != */!menuBarParent.parent.activeClient)
-         {
-            menuBarParent = null;
-            break;
-         }
+         if(menuBarParent.menuBar) return menuBarParent.menuBar;
+         if(menuBarParent && !menuBarParent.isActiveClient)
+            return null;
       }
-      return menuBarParent ? menuBarParent.menuBar : null;
+      return null;
    }
 
    void CreateSystemChildren(void)
@@ -2181,7 +2250,11 @@ private:
       Point scroll = this.scroll;
 
       if(state == maximized)
+      {
          parent = GetParentMenuBar();
+         if(!parent && nativeDecorations)
+            parent = rootWindow;
+      }
 
       if(parent)
       {
@@ -2371,11 +2444,16 @@ private:
       UpdateDecorations();
       if(parent)
       {
-         if(parent.rootWindow == parent && parent.activeClient == this) // Added this last check
+         if(parent.activeClient == this) // Added this last check
          {
-            char caption[2048];
-            parent.FigureCaption(caption);
-            guiApp.interfaceDriver.SetRootWindowCaption(parent, caption);
+            if(parent.rootWindow == parent)
+            {
+               char caption[2048];
+               parent.FigureCaption(caption);
+               guiApp.interfaceDriver.SetRootWindowCaption(parent, caption);
+            }
+            else
+               parent.UpdateCaption();
          }
          parent.UpdateDecorations();
       }
@@ -2645,7 +2723,7 @@ private:
       bool opaque = IsOpaque();
       Window child;
       int offsetX = absPosition.x - rootWindow.absPosition.x, offsetY = absPosition.y - rootWindow.absPosition.y;
-      if(rootWindow.nativeDecorations)
+      if(rootWindow.nativeDecorations && rootWindow.windowHandle)
       {
          offsetX -= rootWindow.clientStart.x;
          offsetY -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
@@ -2661,10 +2739,11 @@ private:
             if(!opaque)
             {
                // Adjust renderArea to the root window level
-               Extent * renderArea = &rootWindow.tempExtents[1];
+               Extent * renderArea = &rootWindow.tempExtents[3];
 
-               int offsetX = child.absPosition.x - rootWindow.absPosition.x, offsetY = child.absPosition.y - rootWindow.absPosition.y;
-               if(child.rootWindow.nativeDecorations)
+               int offsetX = child.absPosition.x - rootWindow.absPosition.x;
+               int offsetY = child.absPosition.y - rootWindow.absPosition.y;
+               if(child.rootWindow.nativeDecorations && rootWindow.windowHandle)
                {
                   offsetX -= child.rootWindow.clientStart.x;
                   offsetY -= child.rootWindow.clientStart.y - (child.rootWindow.hasMenuBar ? skinMenuHeight : 0);
@@ -2692,7 +2771,12 @@ private:
                */
 
                renderArea->Copy(child.dirtyArea /*childRenderArea*/);
+
+               // This intersection with child clip extent was missing and causing #708 (Installer components list scrolling bug):
+               renderArea->Intersection(child.clipExtent, rootWindow.tempExtents[0], rootWindow.tempExtents[1], rootWindow.tempExtents[2]);
+
                renderArea->Offset(offsetX, offsetY);
+
                dirtyExtent.Union(renderArea, rootWindow.tempExtents[0]);
                // overDirtyExtent.Union(renderArea);
                renderArea->Empty();
@@ -2718,7 +2802,7 @@ private:
       Extent * dirtyExtentWindow = &rootWindow.tempExtents[1];
       Window child;
       int offsetX = absPosition.x - rootWindow.absPosition.x, offsetY = absPosition.y - rootWindow.absPosition.y;
-      if(rootWindow.nativeDecorations)
+      if(rootWindow.nativeDecorations && rootWindow.windowHandle)
       {
          offsetX -= rootWindow.clientStart.x;
          offsetY -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
@@ -2915,7 +2999,7 @@ private:
       Window child;
       Window rootWindow = this.rootWindow;
       int offsetX = absPosition.x - rootWindow.absPosition.x, offsetY = absPosition.y - rootWindow.absPosition.y;
-      if(rootWindow.nativeDecorations)
+      if(rootWindow.nativeDecorations && rootWindow.windowHandle)
       {
          offsetX -= rootWindow.clientStart.x;
          offsetY -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
@@ -3165,7 +3249,12 @@ private:
             // If the window is disabled, stop looking in children (for acceptDisabled mode)
             if(!disabled)
             {
-               for(child = (last && last.parent == this) ? last.previous : children.last; child; child = child.prev)
+               bool isD = (last && last != this && last.IsDescendantOf(this)); //  Fix for WSMS (#844)
+               Window ancestor = null;
+               if(isD)
+                  for(ancestor = last; ancestor && ancestor.parent != this; ancestor = ancestor.parent);
+               // for(child = isD ? (last.previous == children.first ? null : last.previous) : children.last; child; child = child.prev)
+               for(child = isD ? (ancestor.previous == children.first ? null : ancestor) : children.last; child; child = child.prev)
                {
                   if(child != statusBar && child.rootWindow == rootWindow)
                   {
@@ -3176,7 +3265,8 @@ private:
                }
                if(clickThru)
                {
-                  for(child = (last && last.parent == this) ? last.previous : children.last; child; child = child.prev)
+                  //for(child = isD ? (last.previous == children.first ? null : last.previous) : children.last; child; child = child.prev)
+                  for(child = isD ? (ancestor.previous == children.first ? null : ancestor.previous) : children.last; child; child = child.prev)
                   {
                      if(child != statusBar && child.rootWindow == rootWindow)
                      {
@@ -3186,6 +3276,9 @@ private:
                      }
                   }
                }
+
+               if(last && last != this && this.IsDescendantOf(last)) // Fix for installer lockup
+                  result = null;
             }
          }
       }
@@ -3516,7 +3609,7 @@ private:
                   bool real = parent.activeChild != this;
 
                   // TEST THIS: New activateParent check here!!! CAUSED MENUS NOT GOING AWAY
-                  if(/*activateParent && */guiApp.interimWindow && 
+                  if(!style.inactive && /*activateParent && */guiApp.interimWindow && 
                      !IsDescendantOf(guiApp.interimWindow) && 
                      !IsSlaveOf(guiApp.interimWindow))
                   {
@@ -4025,6 +4118,8 @@ private:
                            return false;
                         }
                         delete activateWindow;
+                        // Trouble with clickThrough, siblings and activation (Fix for nicktick scrolling, siblings/activation endless loops, #844)
+                        activate = false;
                      }
                      mods->isActivate = true;
                   }
@@ -4158,7 +4253,7 @@ private:
                guiApp.prevWindow = null;
 
                // Eventually fix this not to include captured?
-               if(!prevWindow.OnMouseLeave(*mods))
+               if(!trueWindow.IsDescendantOf(prevWindow) && !prevWindow.OnMouseLeave(*mods))
                   result = false;
             }
             if(result && trueWindow && !trueWindow.destroyed/* && trueWindow == window*/)
@@ -4444,7 +4539,7 @@ private:
                      case tab: case shiftTab:
                      {
                         Window cycleParent = this;
-                        if(this == guiApp.interimWindow && !master.style.interim && !cycleParent.style.tabCycle)
+                        if(this == guiApp.interimWindow && master && !master.style.interim && !cycleParent.style.tabCycle && master.parent)
                            cycleParent = master.parent;
                         
                         if(!guiApp.windowCaptured && cycleParent.style.tabCycle)
@@ -4628,14 +4723,17 @@ private:
             Window hotKeyWindow = hotKey.window;
             Window parent = hotKeyWindow.parent;
             Window prevActiveWindow = activeChild;
+            // For when sys buttons are placed inside the menu bar
+            if(parent && parent._class == class(PopupMenu))
+               parent = parent.parent;
 
-            // 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] && hotKeyWindow != parent.sysButtons[1] )))
+            // Don't process non-visible buttons, but make an exception for the Alt-F4 with Native Decorations turned on; This handles alt+enter as well
+            if(hotKeyWindow.style.hidden && (!hotKeyWindow.style.nonClient || !parent || !parent.nativeDecorations || (hotKeyWindow != parent.sysButtons[2] && hotKeyWindow != parent.sysButtons[1])))
                continue;
 
             if(prevActiveWindow) incref prevActiveWindow;
             incref hotKeyWindow;
-            if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown && !hotKeyWindow.style.nonClient)
+            if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown && !hotKeyWindow.style.nonClient && !hotKeyWindow.inactive)
                if(!hotKeyWindow.ActivateEx(true, true, false, true, null, null))
                {
                   status = false;
@@ -4686,7 +4784,7 @@ private:
 
       // Setup relationship with outside world (bb root || !bb)
       if((!guiApp.fullScreenMode && parent == guiApp.desktop) || this == guiApp.desktop || 
-         (_displayDriver && dispDriver != parent.dispDriver))
+         (_displayDriver && parent.dispDriver && dispDriver != parent.dispDriver))
       {
          rootWindow = this;
          if(!tempExtents)
@@ -4718,7 +4816,7 @@ private:
       bool result = false;
       Window child;
 
-      if((!guiApp.fullScreenMode && parent == guiApp.desktop) || (guiApp.fullScreenMode && (this == guiApp.desktop || (_displayDriver && dispDriver != parent.dispDriver))))
+      if((!guiApp.fullScreenMode && parent == guiApp.desktop) || (guiApp.fullScreenMode && (this == guiApp.desktop || (_displayDriver && parent.dispDriver && dispDriver != parent.dispDriver))))
       {
          subclass(DisplayDriver) dDriver = (dispDriver && !formDesigner) ? dispDriver : GetDisplayDriver(guiApp.defaultDisplayDriver);
          DisplaySystem displaySystem = dDriver ? dDriver.displaySystem : null;
@@ -4746,7 +4844,8 @@ private:
                delete display;
             }
          }
-         guiApp.interfaceDriver.SetIcon(this, icon);
+         // Sometimes icon does not show up on Windows XP if we set here...
+         // guiApp.interfaceDriver.SetIcon(this, icon);
       }
       else if(this != guiApp.desktop)
       {
@@ -4786,11 +4885,6 @@ private:
       Window child;
       WindowState stateBackup = state;
 
-      /*
-      if(!rootWindow.created)
-         printf("");
-      */
-      
       if(((subclass(Window))_class).pureVTbl)
       {
          if(_vTbl == _class._vTbl)
@@ -4931,7 +5025,7 @@ private:
             }
             */
 
-            captionFont = guiApp.currentSkin.CaptionFont();
+            captionFont = guiApp.currentSkin ? guiApp.currentSkin.CaptionFont() : null;
             AddResource(captionFont);
 
             if(OnLoadGraphics())
@@ -5269,7 +5363,7 @@ private:
       return result;
    }
 
-   bool DestroyEx(int returnCode)
+   bool DestroyEx(int64 returnCode)
    {
       OldLink slave;
       Timer timer, nextTimer;
@@ -5385,6 +5479,8 @@ private:
          if(master.defaultControl == this)
             master.defaultControl = null;
       }
+      if(parent)
+         parent.OnChildAddedOrRemoved(this, true);
       if(parent && !parent.destroyed /*&&
          rootWindow && rootWindow.display && !rootWindow.destroyed*/)
       {
@@ -5635,7 +5731,7 @@ private:
       if(prevState != newState)
          lastState = prevState;
 
-      if(rootWindow != this || !nativeDecorations)
+      if(rootWindow != this || !nativeDecorations || !windowHandle)
       {
          if(style.isActiveClient && !style.hidden && prevState == minimized)
             parent.numIcons--;
@@ -5761,7 +5857,7 @@ private:
          if(child.cycle && !child.style.nonClient && child.style.isActiveClient && child.visible)
          {
             DataRow row = listBox.AddRow();
-            row.tag = (int)child;
+            row.tag = (int64)child;
             child.FigureCaption(caption);
             row.SetData(null, caption);
          }
@@ -5983,6 +6079,9 @@ public:
             (master && master != guiApp.desktop && !master.created))
             return false;
 
+         if(parent)
+            stopwatching(parent, font);
+
          if(!parent)
             property::parent = guiApp.desktop;
          if(!master) master = parent;
@@ -6135,7 +6234,13 @@ public:
                            Window slave = link.data;
                            next = link.next;
                            if(!slave.created && (slave.autoCreate || slave.wasCreated))
-                              slave.Create();
+                           {
+                              if(slave.Create())
+                                 // Things might have happened that invalidated 'next'...
+                                 // Start over the search for slaves to create.
+                                 // (Added this to fix crash with Stacker & Toolbar)
+                                 next = slaves.first;
+                           }
                         }
                      }
 
@@ -6153,9 +6258,12 @@ public:
                         if(state == minimized) parent.numIcons--;
                      }
 
+                     parent.OnChildAddedOrRemoved(this, false);
+
                      // Real set state & activate for proper display & activation
                      property::visible = visible;
                      //  SetState(state & 0x00000003, true, 0);
+                     guiApp.interfaceDriver.SetIcon(this, icon);
 
                      if(visible)
                      {
@@ -6337,7 +6445,7 @@ public:
       return result;
    }
 
-   bool Destroy(int code)
+   bool Destroy(int64 code)
    {
       //if(created)
       if(this)
@@ -6902,7 +7010,7 @@ public:
       }
    }
 
-   void SetText(char * format, ...)
+   private void _SetCaption(char * format, va_list args)
    {
       if(this)
       {
@@ -6910,22 +7018,34 @@ public:
          if(format)
          {
             char caption[MAX_F_STRING];
-            va_list args;
-            va_start(args, format);
-            vsprintf(caption, format, args);
-            va_end(args);
+            vsnprintf(caption, sizeof(caption), format, args);
+            caption[sizeof(caption)-1] = 0;
 
-            this.caption = new char[strlen(caption)+1];
-            if(this.caption)
-               strcpy(this.caption, caption);
+            this.caption = CopyString(caption);
          }
          if(created)
             UpdateCaption();
 
-         firewatchers text;
+         firewatchers caption;
       }
    }
 
+   /*deprecated*/ void SetText(char * format, ...)
+   {
+      va_list args;
+      va_start(args, format);
+      _SetCaption(format, args);
+      va_end(args);
+   }
+
+   void SetCaption(char * format, ...)
+   {
+      va_list args;
+      va_start(args, format);
+      _SetCaption(format, args);
+      va_end(args);
+   }
+
    bool Grab(Bitmap bitmap, Box box, bool decorations)
    {
       bool result = false;
@@ -7113,7 +7233,7 @@ public:
          else
             sprintf(message, $"Save changes to Untitled %d?", documentID);
 
-         dialogRes = MessageBox { master = master, type = yesNoCancel, text = parent.caption, contents = message }.Modal();
+         dialogRes = MessageBox { master = master, type = yesNoCancel, text = parent.caption ? parent.caption : rootWindow.caption, contents = message }.Modal();
 
          if(dialogRes == yes)
          {
@@ -7127,12 +7247,15 @@ public:
       if(result)
       {
          for(slave = slaves.first; slave; slave = slave.next)
-            if(!((Window)slave.data).CloseConfirmation(true))
+         {
+            Window w = slave.data;
+            if((w.parent == this || !w.IsDescendantOf(this)) && !w.CloseConfirmation(true))
             {
                // ((Window)slave.data).CloseConfirmation(true);
                result = false;
                break;
             }
+         }
       }
 
       if(result)
@@ -7436,7 +7559,7 @@ public:
    bool MenuWindowSelectWindow(MenuItem selection, Modifiers mods)
    {
       Window document;
-      int id = selection.id;
+      int64 id = selection.id;
       OldLink cycle = activeClient.cycle;
       int c = 0;
       //for(c = 0, cycle = activeChild.cycle; c<id; cycle = cycle.next, c++);
@@ -7669,10 +7792,16 @@ public:
    }
    virtual void ShowDecorations(Font captionFont, Surface surface, char * name, bool active, bool moving);
    virtual void PreShowDecorations(Font captionFont, Surface surface, char * name, bool active, bool moving);
-   virtual bool IsMouseMoving(int x, int y, int w, int h);
-   virtual bool IsMouseResizing(int x, int y, int w, int h, bool *resizeX, bool *resizeY, bool *resizeEndX, bool *resizeEndY);
+   virtual bool IsMouseMoving(int x, int y, int w, int h)
+   {
+      return false;
+   }
+   virtual bool IsMouseResizing(int x, int y, int w, int h, bool *resizeX, bool *resizeY, bool *resizeEndX, bool *resizeEndY)
+   {
+      return false;
+   }
    virtual void UpdateNonClient();
-   virtual void SetBox(Box box);
+   virtual void SetBox(Box box);    // This isn't used anywhere at this time
    virtual bool IsInside(int x, int y)
    {
       return box.IsPointInside({x, y});
@@ -7714,7 +7843,6 @@ public:
             if(parent)
             {
                parent.children.Remove(this);
-               parent.OnChildAddedOrRemoved(this, true);
 
                parent.Update(
                {
@@ -7755,6 +7883,12 @@ public:
                parent.childrenOrder.Delete(order);
             cycle = null;
             order = null;
+            // *** TODO: Added this here to solve crash on setting parent to null before destroying/destructing ***
+            //           Should something else be done?
+            if(parent && parent.activeChild == this)
+               parent.activeChild = null;
+            if(parent && parent.activeClient == this)
+               parent.activeClient = null;
 
             //if(created)
             {
@@ -7814,7 +7948,9 @@ public:
                {
                   if(!style.noCycle)
                      parent.childrenCycle.Insert(
-                        (parent.activeChild && parent.activeChild.cycle) ? parent.activeChild.cycle.prev : null, 
+                        // Note: changed to 'null' to fix broken tab cycling in WSMS custom reports
+                        //(parent.activeChild && parent.activeChild.cycle) ? parent.activeChild.cycle.prev : null, 
+                        null,
                         cycle = OldLink { data = this });
                   parent.childrenOrder.Insert(
                      (parent.activeChild && parent.activeChild.order) ? parent.activeChild.order.prev : parent.childrenOrder.last, 
@@ -7884,7 +8020,11 @@ public:
                   */
                }
                scrolledPos.x = MININT; // Prevent parent update
-               property::anchor = anchor;
+               {
+                  bool anchored = this.anchored;
+                  property::anchor = anchor;
+                  this.anchored = anchored;
+               }
                /*
                {
                   int x, y, w, h;
@@ -7898,6 +8038,8 @@ public:
 
             }
             // else parent = value;
+            if(oldParent)
+               oldParent.OnChildAddedOrRemoved(this, true);
          }
       }
       get { return parent; }
@@ -8017,7 +8159,7 @@ public:
       set
       {
          background.a = (byte)Min(Max((int)(value * 255), 0), 255);
-         drawBehind = background.a ? false : true;
+         drawBehind = (background.a == 255) ? false : true;
       }
       get { return background.a / 255.0f; }
    };
@@ -8182,7 +8324,9 @@ public:
                if(!style.noCycle)
                {
                   parent.childrenCycle.Insert(
-                     (parent.activeChild && parent.activeChild.cycle) ? parent.activeChild.cycle.prev : null, 
+                     // Note: changed to 'null' to fix broken tab cycling in WSMS custom reports
+                     //(parent.activeChild && parent.activeChild.cycle) ? parent.activeChild.cycle.prev : null, 
+                     null,
                      cycle = OldLink { data = this });
                }
                parent.childrenOrder.Insert(
@@ -9027,12 +9171,7 @@ public:
    property Point scroll
    {
       property_category $"Behavior"
-      set
-      {
-         // scroll = value;
-         // TESTING THIS IMPLEMENTATION:
-         SetScrollPosition(value.x, value.y);
-      }
+      set { SetScrollPosition(value.x, value.y); }
       get { value = scroll; }
    };
 
@@ -9043,6 +9182,14 @@ public:
       get { return (bool)modifyVirtArea; }
    };
 
+   property bool dontAutoScrollArea
+   {
+      property_category $"Behavior"
+      // Activating a child control out of view will automatically scroll to make it in view
+      set { noAutoScrollArea = value; }
+      get { return (bool)noAutoScrollArea; }
+   };
+
    property char * fileName
    {
       property_category $"Document"
@@ -9071,7 +9218,7 @@ public:
       get { return fileName; }
    };
 
-   property int id
+   property int64 id
    {
       property_category $"Data"
       set { id = value; }
@@ -9235,8 +9382,28 @@ public:
    {
       get { return (bool)nativeDecorations; }
       set { nativeDecorations = value; }
-#ifndef ECERE_VANILLA
-      isset { return (nativeDecorations && (rootWindow == this || (formDesigner && activeDesigner && parent == ((FormDesigner)activeDesigner.classDesigner).form.parent))) != style.fixed; }
+#if !defined(ECERE_VANILLA) && !defined(ECERE_NOTRUETYPE)
+      isset
+      {
+         //return (nativeDecorations && (rootWindow == this || (formDesigner && activeDesigner && ((FormDesigner)activeDesigner.classDesigner).form && parent == ((FormDesigner)activeDesigner.classDesigner).form.parent))) != style.fixed;
+         bool result = false;
+         if(nativeDecorations)
+         {
+            if(rootWindow == this)
+               result = true;
+            else
+            {
+               if(formDesigner && activeDesigner)
+               {
+                  FormDesigner cd = (FormDesigner)activeDesigner.classDesigner;
+                  Window form = cd ? cd.form : null;
+                  if(form && parent == form.parent)
+                     result = true;
+               }
+            }
+         }
+         return result != style.fixed;
+      }
 #endif
    };
    property bool manageDisplay { get { return (bool)manageDisplay; } set { manageDisplay = value; } };
@@ -9271,7 +9438,7 @@ private:
    Size scrollArea;        // Virtual Scroll area size
    Size reqScrollArea;     // Requested virtual area size
    Point scroll;           // Virtual area scrolling position
-   public ScrollBar sbh, sbv;        // Scrollbar window handles
+   ScrollBar sbh, sbv;        // Scrollbar window handles
    Cursor cursor;        // Mouse cursor used for this window
    WindowState state;
    PopupMenu menuBar;
@@ -9285,7 +9452,7 @@ private:
    int numPositions;
    Menu menu;
    ScrollFlags scrollFlags;// Window Scrollbar Flags
-   int id;                 // Control ID
+   int64 id;                 // Control ID
    int documentID;
    ColorAlpha background;  // Background color used to draw the window area
    Color foreground;
@@ -9565,127 +9732,141 @@ class WindowControllerInterface : ControllableWindow
 {
    bool OnKeyDown(Key key, unichar ch)
    {
-      bool result = ((int(*)())(void *)controller.OnKeyDown)((void *)controller.controlled, (void *)controller, key, ch);
+      bool result = ((bool(*)(Window, WindowController, Key, unichar))(void *)controller.OnKeyDown)((Window)controller.controlled, controller, key, ch);
       if(result)
-         result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown](controller.window, key, ch);
+         result = ((bool (*)(Window, Key, unichar))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown])(controller.window, key, ch);
       return result;
    }
 
    bool OnKeyUp(Key key, unichar ch)
    {
-      bool result = ((int(*)())(void *)controller.OnKeyUp)((void *)controller.controlled, (void *)controller, key, ch);
+      bool result = ((bool(*)(Window, WindowController, Key, unichar))(void *)controller.OnKeyUp)((Window)controller.controlled, controller, key, ch);
       if(result)
-         result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp](controller.window, key, ch);
+         result = ((bool(*)(Window, Key, unichar))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp])(controller.window, key, ch);
       return result;
    }
 
    bool OnKeyHit(Key key, unichar ch)
    {
-      bool result = ((int(*)())(void *)controller.OnKeyHit)((void *)controller.controlled, (void *)controller, key, ch);
+      bool result = ((bool(*)(Window, WindowController, Key, unichar))(void *)controller.OnKeyHit)((Window)controller.controlled, controller, key, ch);
       if(result)
-         result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit](controller.window, key, ch);
+         result = ((bool(*)(Window, Key, unichar))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit])(controller.window, key, ch);
       return result;
    }
 
    bool OnMouseMove(int x, int y, Modifiers mods)
    {
-      bool result = ((int(*)())(void *)controller.OnMouseMove)((void *)controller.controlled, (void *)controller, x, y, mods);
+      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnMouseMove)((Window)controller.controlled, controller, x, y, mods);
       if(result)
-         result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove](controller.window, x, y, mods);
+         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove])(controller.window, x, y, mods);
       return result;
    }
 
    bool OnLeftButtonDown(int x, int y, Modifiers mods)
    {
-      bool result = ((int(*)())(void *)controller.OnLeftButtonDown)((void *)controller.controlled, (void *)controller, x, y, mods);
+      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnLeftButtonDown)((Window)controller.controlled, controller, x, y, mods);
       if(result)
-         result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown](controller.window, x, y, mods);
+         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown])(controller.window, x, y, mods);
       return result;
    }
 
    bool OnLeftButtonUp(int x, int y, Modifiers mods)
    {
-      bool result = ((int(*)())(void *)controller.OnLeftButtonUp)((void *)controller.controlled, (void *)controller, x, y, mods);
+      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnLeftButtonUp)((Window)controller.controlled, controller, x, y, mods);
       if(result)
-         result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp](controller.window, x, y, mods);
+         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp])(controller.window, x, y, mods);
       return result;
    }
 
    bool OnLeftDoubleClick(int x, int y, Modifiers mods)
    {
-      bool result = ((int(*)())(void *)controller.OnLeftDoubleClick)((void *)controller.controlled, (void *)controller, x, y, mods);
+      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnLeftDoubleClick)((Window)controller.controlled, controller, x, y, mods);
       if(result)
-         result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick](controller.window, x, y, mods);
+         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick])(controller.window, x, y, mods);
       return result;
    }
 
    bool OnRightButtonDown(int x, int y, Modifiers mods)
    {
-      bool result = ((int(*)())(void *)controller.OnRightButtonDown)((void *)controller.controlled, (void *)controller, x, y, mods);
+      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnRightButtonDown)((Window)controller.controlled, controller, x, y, mods);
       if(result)
-         result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown](controller.window, x, y, mods);
+         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown])(controller.window, x, y, mods);
       return result;
    }
 
    bool OnRightButtonUp(int x, int y, Modifiers mods)
    {
-      bool result = ((int(*)())(void *)controller.OnRightButtonUp)((void *)controller.controlled, (void *)controller, x, y, mods);
+      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnRightButtonUp)((Window)controller.controlled, controller, x, y, mods);
       if(result)
-         result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp](controller.window, x, y, mods);
+         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp])(controller.window, x, y, mods);
       return result;
    }
 
    bool OnRightDoubleClick(int x, int y, Modifiers mods)
    {
-      bool result = ((int(*)())(void *)controller.OnRightDoubleClick)((void *)controller.controlled, (void *)controller, x, y, mods);
+      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnRightDoubleClick)((Window)controller.controlled, controller, x, y, mods);
       if(result)
-         result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick](controller.window, x, y, mods);
+         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick])(controller.window, x, y, mods);
       return result;
    }
 
    bool OnMiddleButtonDown(int x, int y, Modifiers mods)
    {
-      bool result = ((int(*)())(void *)controller.OnMiddleButtonDown)((void *)controller.controlled, (void *)controller, x, y, mods);
+      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnMiddleButtonDown)((Window)controller.controlled, controller, x, y, mods);
       if(result)
-         result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown](controller.window, x, y, mods);
+         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown])(controller.window, x, y, mods);
       return result;
    }
 
    bool OnMiddleButtonUp(int x, int y, Modifiers mods)
    {
-      bool result = ((int(*)())(void *)controller.OnMiddleButtonUp)((void *)controller.controlled, (void *)controller, x, y, mods);
+      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnMiddleButtonUp)((Window)controller.controlled, controller, x, y, mods);
       if(result)
-         result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp](controller.window, x, y, mods);
+         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp])(controller.window, x, y, mods);
       return result;
    }
 
    bool OnMiddleDoubleClick(int x, int y, Modifiers mods)
    {
-      bool result = ((int(*)())(void *)controller.OnMiddleDoubleClick)((void *)controller.controlled, (void *)controller, x, y, mods);
+      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnMiddleDoubleClick)((Window)controller.controlled, controller, x, y, mods);
       if(result)
-         result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick](controller.window, x, y, mods);
+         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick])(controller.window, x, y, mods);
       return result;
    }
 
    void OnResize(int width, int height)
    {
-      ((int(*)())(void *)controller.OnResize)((void *)controller.controlled, (void *)controller, width, height);
-      controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnResize](controller.window, width, height);
+      ((void(*)(Window, WindowController, int, int))(void *)controller.OnResize)((Window)controller.controlled, controller, width, height);
+      ((void(*)(Window, int, int))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnResize])(controller.window, width, height);
    }
 
    void OnRedraw(Surface surface)
    {
-      ((int(*)())(void *)controller.OnRedraw)((void *)controller.controlled, (void *)controller, surface);
-      controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRedraw](controller.window, surface);
+      ((void(*)(Window, WindowController, Surface))(void *)controller.OnRedraw)((Window)controller.controlled, controller, surface);
+      ((void(*)(Window, Surface))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRedraw])(controller.window, surface);
    }
 
    bool OnCreate()
    {
-      bool result = ((int(*)())(void *)controller.OnCreate)((void *)controller.controlled, (void *)controller);
+      bool result = ((bool(*)(Window, WindowController))(void *)controller.OnCreate)((Window)controller.controlled, controller);
       if(result)
-         result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnCreate](controller.window);
+         result = ((bool(*)(Window))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnCreate])(controller.window);
       return result;
    }
+
+   bool OnLoadGraphics()
+   {
+      bool result = ((bool(*)(Window, WindowController))(void *)controller.OnLoadGraphics)((Window)controller.controlled, controller);
+      if(result)
+         result = ((bool(*)(Window))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLoadGraphics])(controller.window);
+      return result;
+   }
+
+   void OnUnloadGraphics()
+   {
+      ((void(*)(Window, WindowController))(void *)controller.OnUnloadGraphics)((Window)controller.controlled, controller);
+      ((void(*)(Window))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnUnloadGraphics])(controller.window);
+   }
 }
 
 public class WindowController<class V>
@@ -9744,6 +9925,8 @@ public:
    virtual void V::OnResize(WindowController controller, int width, int height);
    virtual void V::OnRedraw(WindowController controller, Surface surface);
    virtual bool V::OnCreate(WindowController controller);
+   virtual bool V::OnLoadGraphics(WindowController controller);
+   virtual void V::OnUnloadGraphics(WindowController controller);
 
 private:
    int (** windowVTbl)();