ecere: gui/Window: tweak to update normalAnchor and normalSizeAnchor for gui config.
[sdk] / ecere / src / gui / Window.ec
index 69289e2..e14b5d8 100644 (file)
@@ -25,6 +25,10 @@ import "EditBox"
 import "DataBox"
 import "ToolTip"
 
+#if defined(__WIN32__)
+import "Win32Interface"
+#endif
+
 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
 import "Desktop3D"
 #endif
@@ -568,6 +572,7 @@ private:
       OldLink slave;
       ResPtr ptr;
 
+#if !defined(__EMSCRIPTEN__)
       if(fileMonitor)
       {
          int i, lockCount = guiApp.lockMutex.lockCount;
@@ -577,6 +582,7 @@ private:
          for(i = 0; i < lockCount; i++)
             guiApp.lockMutex.Wait();
       }
+#endif
 
       if(parent)
       {
@@ -661,7 +667,9 @@ private:
       delete statusBar;
 
       OnDestroyed();
+#if !defined(__EMSCRIPTEN__)
       delete mutex;
+#endif
       delete icon;
 
       if(((subclass(Window))_class).pureVTbl)
@@ -698,6 +706,8 @@ private:
          tempExtents[3].Free(null);
          delete tempExtents;
       }
+
+      delete controller;
    }
 
 //#if !defined(ECERE_VANILLA)
@@ -765,13 +775,21 @@ private:
 
             if(rootWindow.is3D)
             {
-               x += rootWindow.parent.clientStart.x;
-               y += rootWindow.parent.clientStart.y;
+               int dx = rootWindow.parent.parent.clientStart.x;
+               int dy = rootWindow.parent.parent.clientStart.y;
+               if(!rootWindow.parent.nativeDecorations)
+               {
+                  dx += rootWindow.parent.clientStart.x;
+                  dy += rootWindow.parent.clientStart.y;
+               }
+               x += dx;
+               y += dy;
+
                /*
-               mox.left += rootWindow.parent.clientStart.x;
-               mox.top += rootWindow.parent.clientStart.y;
-               mox.right += rootWindow.parent.clientStart.x;
-               mox.bottom += rootWindow.parent.clientStart.y;
+               mox.left += dx;
+               mox.top += dy;
+               mox.right += dx;
+               mox.bottom += dy;
                */
             }
          }
@@ -812,13 +830,21 @@ private:
             y -= rootWindow.absPosition.y;
             if(rootWindow.is3D)
             {
-               x += rootWindow.parent.clientStart.x;
-               y += rootWindow.parent.clientStart.y;
+               int dx = rootWindow.parent.parent.clientStart.x;
+               int dy = rootWindow.parent.parent.clientStart.y;
+               if(!rootWindow.parent.nativeDecorations)
+               {
+                  dx += rootWindow.parent.clientStart.x;
+                  dy += rootWindow.parent.clientStart.y;
+               }
+               x += dx;
+               y += dy;
+
                /*
-               mox.left += rootWindow.parent.clientStart.x;
-               mox.top += rootWindow.parent.clientStart.y;
-               mox.right += rootWindow.parent.clientStart.x;
-               mox.bottom += rootWindow.parent.clientStart.y;
+               mox.left += dx;
+               mox.top += dy;
+               mox.right += dx;
+               mox.bottom += dy;
                */
             }
          }
@@ -1646,6 +1672,17 @@ private:
    public void ExternalPosition(int x, int y, int w, int h)
    {
       Position(x, y, w, h, false, true, true, true, false, false);
+      /* TO REVIEW: Redj's code trying to fix position saving -- TWEAK HERE
+      if(style.fixed)
+      {
+         if(state == normal)
+         {
+            normalAnchor = Anchor { left = x, top = y };
+            normalSizeAnchor = SizeAnchor { { w, h } };
+            anchored = false;
+         }
+      }
+      */ // -- TWEAK HERE
    }
 
    // (w, h): Full window size
@@ -1829,7 +1866,9 @@ private:
                   child.display.width = display.width;
                   child.display.height = display.height;
                   child.display.driverData = display.driverData;
+#if !defined(__EMSCRIPTEN__)
                   child.display.mutex = null;
+#endif
                }
             }
          }
@@ -3350,7 +3389,7 @@ private:
             if(rootWindow.active)
                guiApp.interfaceDriver.StopMoving(rootWindow);
          }
-         ReleaseCapture();
+         guiApp.windowCaptured.ReleaseCapture();
          guiApp.resizeX = guiApp.resizeY = guiApp.resizeEndX = guiApp.resizeEndY = false;
          guiApp.windowIsResizing = false;
       }
@@ -4355,6 +4394,11 @@ private:
                incref window;
                if(!MouseMethod(window, clientX, clientY, *mods))
                   result = false;
+
+#ifdef __ANDROID__
+               if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp)
+                  window.OnMouseLeave(*mods);
+#endif
                delete window;
             }
          }
@@ -5814,35 +5858,38 @@ private:
                break;
             case minimized:
             {
-               int maxIcons = parent.clientSize.w / MINIMIZED_WIDTH;
-               Window child;
-               int size = 256;
-               byte * idBuffer = new0 byte[size];
-               int c;
-               for(child = parent.children.first; child; child = child.next)
+               if(hasMinimize)
                {
-                  if(child != this && child.state == minimized)
+                  int maxIcons = parent.clientSize.w / MINIMIZED_WIDTH;
+                  Window child;
+                  int size = 256;
+                  byte * idBuffer = new0 byte[size];
+                  int c;
+                  for(child = parent.children.first; child; child = child.next)
                   {
-                     if(child.iconID > size - 2)
+                     if(child != this && child.state == minimized)
                      {
-                        idBuffer = renew0 idBuffer byte[size*2];
-                        memset(idBuffer + size, 0, size);
-                        size *= 2;
+                        if(child.iconID > size - 2)
+                        {
+                           idBuffer = renew0 idBuffer byte[size*2];
+                           memset(idBuffer + size, 0, size);
+                           size *= 2;
+                        }
+                        idBuffer[child.iconID] = (byte)bool::true;
                      }
-                     idBuffer[child.iconID] = (byte)bool::true;
                   }
-               }
-               for(c = 0; c<size; c++)
-                  if(!idBuffer[c])
-                     break;
-               iconID = c;
-               delete idBuffer;
-               if(style.isActiveClient && !style.hidden)
-                  parent.numIcons++;
+                  for(c = 0; c<size; c++)
+                     if(!idBuffer[c])
+                        break;
+                  iconID = c;
+                  delete idBuffer;
+                  if(style.isActiveClient && !style.hidden)
+                     parent.numIcons++;
 
-               stateAnchor = Anchor { left = (iconID % maxIcons) * MINIMIZED_WIDTH, bottom = (iconID / maxIcons) * (guiApp.textMode ? 16 : 24) };
-               stateSizeAnchor = SizeAnchor { size.w = MINIMIZED_WIDTH };
-               break;
+                  stateAnchor = Anchor { left = (iconID % maxIcons) * MINIMIZED_WIDTH, bottom = (iconID / maxIcons) * (guiApp.textMode ? 16 : 24) };
+                  stateSizeAnchor = SizeAnchor { size.w = MINIMIZED_WIDTH };
+                  break;
+               }
             }
          }
          // TOCHECK: Why was this here?
@@ -5850,13 +5897,15 @@ private:
          //position.y = (ty > 0) ? ty & 0xFFFFF : ty;
          ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
 
-         Position(x, y, w, h, true, true, true, true, false, true);
+         if(state != minimized || hasMinimize)
+            Position(x, y, w, h, true, true, true, true, false, true);
 
          if(!style.inactive && !style.interim && parent && this == parent.activeClient)
             parent.UpdateActiveDocument(null);
       }
 
-      CreateSystemChildren();
+      if(state != minimized || hasMinimize)
+         CreateSystemChildren();
       // ------------------------------------------------------
    }
 
@@ -5934,7 +5983,9 @@ private:
       {
          if(guiApp.fullScreenMode && guiApp.desktop.display)
          {
+#if !defined(__EMSCRIPTEN__)
             guiApp.desktop.mutex.Wait();
+#endif
             guiApp.desktop.display.Lock(true);
 
             Update(extent);
@@ -5958,12 +6009,16 @@ private:
             }
 
             guiApp.desktop.display.Unlock();
+#if !defined(__EMSCRIPTEN__)
             guiApp.desktop.mutex.Release();
+#endif
          }
          else
          {
             Window rootWindow = this.rootWindow;
+#if !defined(__EMSCRIPTEN__)
             rootWindow.mutex.Wait();
+#endif
             display.Lock(true);
 
             Update(extent);
@@ -5971,7 +6026,9 @@ private:
                guiApp.SignalEvent();
             else
             {
+#if !defined(__EMSCRIPTEN__)
                guiApp.waitMutex.Wait();
+#endif
                guiApp.interfaceDriver.Lock(rootWindow);
                if(!rootWindow.style.hidden && rootWindow.dirty)
                {
@@ -5983,10 +6040,14 @@ private:
                   rootWindow.dirty = false;
                }
                guiApp.interfaceDriver.Unlock(rootWindow);
+#if !defined(__EMSCRIPTEN__)
                guiApp.waitMutex.Release();
+#endif
             }
             display.Unlock();
+#if !defined(__EMSCRIPTEN__)
             rootWindow.mutex.Release();
+#endif
          }
       }
    }
@@ -6119,6 +6180,7 @@ private:
 
    void SetupFileMonitor()
    {
+#if !defined(__EMSCRIPTEN__)
       if(!fileMonitor)
       {
          fileMonitor = FileMonitor
@@ -6137,6 +6199,7 @@ private:
          };
          incref fileMonitor;
       }
+#endif
    }
 
 public:
@@ -6187,8 +6250,10 @@ public:
                }
          }
 
+#if !defined(__EMSCRIPTEN__)
          if(parent == guiApp.desktop && !mutex)
             mutex = Mutex {};
+#endif
 
          if(style.isDocument)
          {
@@ -6419,6 +6484,11 @@ public:
             Box realBox;
 
             // Testing this to avoid repetitve full update to take time...
+            if(rootWindow.fullRender)
+            {
+               rootWindow.dirty = true;
+               return;
+            }
             if(dirtyArea.count == 1)
             {
                BoxItem item = (BoxItem)ACCESS_ITEM(dirtyArea, dirtyArea.first);
@@ -7407,7 +7477,9 @@ public:
       SetupFileMonitor();
       if(fileName)
       {
+#if !defined(__EMSCRIPTEN__)
          fileMonitor.fileName = null;
+#endif
          saving = true;
 
          if(OnSaveFile(fileName))
@@ -7415,7 +7487,9 @@ public:
             //if(OnFileModified != Window::OnFileModified)
             {
                saving = false;
+#if !defined(__EMSCRIPTEN__)
                fileMonitor.fileName = fileName;
+#endif
             }
             return true;
          }
@@ -7450,7 +7524,9 @@ public:
             sprintf(filePath, "Untitled %d", documentID);
             fileDialog.filePath = filePath;
          }
+#if !defined(__EMSCRIPTEN__)
          fileMonitor.fileName = null;
+#endif
 
          fileDialog.type = save;
          fileDialog.text = $"Save As";
@@ -7487,11 +7563,13 @@ public:
                break;
             }
          }
+#if !defined(__EMSCRIPTEN__)
          //if(OnFileModified != Window::OnFileModified && fileName)
          {
             if(fileName)
                fileMonitor.fileName = fileName;
          }
+#endif
          delete fileDialog;
       }
       return (bool)result; // Actually returning result from Yes/NoCancel message box
@@ -7560,10 +7638,10 @@ public:
                         (*&child.normalAnchor).right.type = none;
                         (*&child.normalAnchor).bottom.type = none;
 
-                        child.normalSizeAnchor.isClientW = false;
-                        child.normalSizeAnchor.isClientH = false;
-                        child.normalSizeAnchor.size.w = w;
-                        child.normalSizeAnchor.size.h = h;
+                        (*&child.normalSizeAnchor).isClientW = false;
+                        (*&child.normalSizeAnchor).isClientH = false;
+                        (*&child.normalSizeAnchor).size.w = w;
+                        (*&child.normalSizeAnchor).size.h = h;
                         child.anchored = false;
                      }
 
@@ -7734,10 +7812,10 @@ public:
                         (*&child.normalAnchor).top = y;
                         (*&child.normalAnchor).right.type = none;
                         (*&child.normalAnchor).bottom.type = none;
-                        child.normalSizeAnchor.isClientW = false;
-                        child.normalSizeAnchor.isClientH = false;
-                        child.normalSizeAnchor.size.w = w;
-                        child.normalSizeAnchor.size.h = h;
+                        (*&child.normalSizeAnchor).isClientW = false;
+                        (*&child.normalSizeAnchor).isClientH = false;
+                        (*&child.normalSizeAnchor).size.w = w;
+                        (*&child.normalSizeAnchor).size.h = h;
                         child.anchored = false;
                      }
 
@@ -7799,10 +7877,10 @@ public:
                         (*&child.normalAnchor).top = y;
                         (*&child.normalAnchor).right.type = none;
                         (*&child.normalAnchor).bottom.type = none;
-                        child.normalSizeAnchor.isClientW = false;
-                        child.normalSizeAnchor.isClientH = false;
-                        child.normalSizeAnchor.size.w = w;
-                        child.normalSizeAnchor.size.h = h;
+                        (*&child.normalSizeAnchor).isClientW = false;
+                        (*&child.normalSizeAnchor).isClientH = false;
+                        (*&child.normalSizeAnchor).size.w = w;
+                        (*&child.normalSizeAnchor).size.h = h;
                         child.anchored = false;
                      }
 
@@ -8109,15 +8187,14 @@ public:
                firewatchers font;
 
 
-               if(value.rootWindow && value.rootWindow.display && rootWindow)
+               if(value.rootWindow && value.rootWindow.display && rootWindow && created)
                {
                   bool reloadGraphics = (oldParent.rootWindow == oldParent && value.rootWindow) || (!value.rootWindow && rootWindow == this) ||
                         (value.rootWindow.display && value.rootWindow.display.displaySystem != rootWindow.display.displaySystem);
 
                   if(reloadGraphics)
                      UnloadGraphics(false);
-                  if(created)
-                     SetupDisplay();
+                  SetupDisplay();
                   if(reloadGraphics)
                      LoadGraphics(false, false);
 
@@ -9322,8 +9399,10 @@ public:
             UpdateCaption();
 
          // if(style.isDocument)
+#if !defined(__EMSCRIPTEN__)
          if(!saving)
             fileMonitor.fileName = value;
+#endif
       }
       get { return fileName; }
    };
@@ -9362,7 +9441,13 @@ public:
    property bool showInTaskBar
    {
       property_category $"Window Style"
-      set { style.showInTaskBar = value; }
+      set
+      {
+         style.showInTaskBar = value;
+#if defined(__WIN32__)
+         Win32UpdateStyle(this);
+#endif
+      }
       get { return style.showInTaskBar; }
    };
    property FileDialog saveDialog { set { saveDialog = value; } };
@@ -9461,7 +9546,7 @@ public:
    property Point clientStart { get { value = clientStart; } };
    property Point absPosition { get { value = absPosition; } };
    property Anchor normalAnchor { get { value = normalAnchor; } };
-   // property Size normalSizeAnchor { get { value = normalSizeAnchor; } };
+   property SizeAnchor normalSizeAnchor { get { value = normalSizeAnchor; } };
    property bool active { get { return (bool)active; } };
    property bool created { get { return (bool)created; } };
    property bool destroyed { get { return (bool)destroyed; } };
@@ -9631,10 +9716,14 @@ private:
    int numIcons;
    int positionID;
 
+#if !defined(__EMSCRIPTEN__)
    Mutex mutex;
+#endif
    WindowState lastState;
 
+#if !defined(__EMSCRIPTEN__)
    FileMonitor fileMonitor;
+#endif
 
    FontResource setFont, systemFont;
    FontResource usedFont;
@@ -9844,25 +9933,37 @@ class WindowControllerInterface : ControllableWindow
 {
    bool OnKeyDown(Key key, unichar ch)
    {
-      bool result = ((bool(*)(Window, WindowController, Key, unichar))(void *)controller.OnKeyDown)((Window)controller.controlled, controller, key, ch);
+      bool result = controller.OnKeyDown ? ((bool(*)(Window, WindowController, Key, unichar))(void *)controller.OnKeyDown)((Window)controller.controlled, controller, key, ch) : true;
       if(result)
-         result = ((bool (*)(Window, Key, unichar))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown])(controller.window, key, ch);
+      {
+         bool (* onKeyDown)(Window, Key, unichar) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown];
+         if(onKeyDown)
+            result = onKeyDown(controller.window, key, ch);
+      }
       return result;
    }
 
    bool OnKeyUp(Key key, unichar ch)
    {
-      bool result = ((bool(*)(Window, WindowController, Key, unichar))(void *)controller.OnKeyUp)((Window)controller.controlled, controller, key, ch);
+      bool result = controller.OnKeyUp ? ((bool(*)(Window, WindowController, Key, unichar))(void *)controller.OnKeyUp)((Window)controller.controlled, controller, key, ch) : true;
       if(result)
-         result = ((bool(*)(Window, Key, unichar))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp])(controller.window, key, ch);
+      {
+         bool (* onKeyUp)(Window, Key, unichar) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp];
+         if(onKeyUp)
+            result = onKeyUp(controller.window, key, ch);
+      }
       return result;
    }
 
    bool OnKeyHit(Key key, unichar ch)
    {
-      bool result = ((bool(*)(Window, WindowController, Key, unichar))(void *)controller.OnKeyHit)((Window)controller.controlled, controller, key, ch);
+      bool result = controller.OnKeyHit ? ((bool(*)(Window, WindowController, Key, unichar))(void *)controller.OnKeyHit)((Window)controller.controlled, controller, key, ch) : true;
       if(result)
-         result = ((bool(*)(Window, Key, unichar))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit])(controller.window, key, ch);
+      {
+         bool (* onKeyHit)(Window, Key, unichar) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit];
+         if(onKeyHit)
+            result = onKeyHit(controller.window, key, ch);
+      }
       return result;
    }
 
@@ -9870,114 +9971,177 @@ class WindowControllerInterface : ControllableWindow
    {
       bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnMouseMove)((Window)controller.controlled, controller, x, y, mods);
       if(result)
-         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove])(controller.window, x, y, mods);
+      {
+         bool(* onMouseMove)(Window, int, int, Modifiers) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove];
+         if(onMouseMove)
+            result = onMouseMove(controller.window, x, y, mods);
+      }
       return result;
    }
 
    bool OnLeftButtonDown(int x, int y, Modifiers mods)
    {
-      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnLeftButtonDown)((Window)controller.controlled, controller, x, y, mods);
+      bool result = controller.OnLeftButtonDown ? ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnLeftButtonDown)((Window)controller.controlled, controller, x, y, mods) : true;
       if(result)
-         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown])(controller.window, x, y, mods);
+      {
+         bool(* onLeftButtonDown)(Window, int, int, Modifiers) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown];
+         if(onLeftButtonDown)
+            result = onLeftButtonDown(controller.window, x, y, mods);
+      }
       return result;
    }
 
    bool OnLeftButtonUp(int x, int y, Modifiers mods)
    {
-      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnLeftButtonUp)((Window)controller.controlled, controller, x, y, mods);
+      bool result = controller.OnLeftButtonUp ? ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnLeftButtonUp)((Window)controller.controlled, controller, x, y, mods) : true;
       if(result)
-         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp])(controller.window, x, y, mods);
+      {
+         bool(* onLeftButtonUp)(Window, int, int, Modifiers) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp];
+         if(onLeftButtonUp)
+            result = onLeftButtonUp(controller.window, x, y, mods);
+      }
       return result;
    }
 
    bool OnLeftDoubleClick(int x, int y, Modifiers mods)
    {
-      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnLeftDoubleClick)((Window)controller.controlled, controller, x, y, mods);
+      bool result = controller.OnLeftDoubleClick ? ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnLeftDoubleClick)((Window)controller.controlled, controller, x, y, mods) : true;
       if(result)
-         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick])(controller.window, x, y, mods);
+      {
+         bool(* onLeftDoubleClick)(Window, int, int, Modifiers) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick];
+         if(onLeftDoubleClick)
+            result = onLeftDoubleClick(controller.window, x, y, mods);
+      }
       return result;
    }
 
    bool OnRightButtonDown(int x, int y, Modifiers mods)
    {
-      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnRightButtonDown)((Window)controller.controlled, controller, x, y, mods);
+      bool result = controller.OnRightButtonDown ? ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnRightButtonDown)((Window)controller.controlled, controller, x, y, mods) : true;
       if(result)
-         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown])(controller.window, x, y, mods);
+      {
+         bool(* onRightButtonDown)(Window, int, int, Modifiers) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown];
+         if(onRightButtonDown)
+            result = onRightButtonDown(controller.window, x, y, mods);
+      }
       return result;
    }
 
    bool OnRightButtonUp(int x, int y, Modifiers mods)
    {
-      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnRightButtonUp)((Window)controller.controlled, controller, x, y, mods);
+      bool result = controller.OnRightButtonUp ? ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnRightButtonUp)((Window)controller.controlled, controller, x, y, mods) : true;
       if(result)
-         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp])(controller.window, x, y, mods);
+      {
+         bool(* onRightButtonUp)(Window, int, int, Modifiers) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp];
+         if(onRightButtonUp)
+            result = onRightButtonUp(controller.window, x, y, mods);
+      }
       return result;
    }
 
    bool OnRightDoubleClick(int x, int y, Modifiers mods)
    {
-      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnRightDoubleClick)((Window)controller.controlled, controller, x, y, mods);
+      bool result = controller.OnRightDoubleClick ? ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnRightDoubleClick)((Window)controller.controlled, controller, x, y, mods) : true;
       if(result)
-         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick])(controller.window, x, y, mods);
+      {
+         bool(* onRightDoubleClick)(Window, int, int, Modifiers) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick];
+         if(onRightDoubleClick)
+            result = onRightDoubleClick(controller.window, x, y, mods);
+      }
       return result;
    }
 
    bool OnMiddleButtonDown(int x, int y, Modifiers mods)
    {
-      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnMiddleButtonDown)((Window)controller.controlled, controller, x, y, mods);
+      bool result = controller.OnMiddleButtonDown ? ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnMiddleButtonDown)((Window)controller.controlled, controller, x, y, mods) : true;
       if(result)
-         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown])(controller.window, x, y, mods);
+      {
+         bool(* onMiddleButtonDown)(Window, int, int, Modifiers) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown];
+         if(onMiddleButtonDown)
+            result = onMiddleButtonDown(controller.window, x, y, mods);
+      }
       return result;
    }
 
    bool OnMiddleButtonUp(int x, int y, Modifiers mods)
    {
-      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnMiddleButtonUp)((Window)controller.controlled, controller, x, y, mods);
+      bool result = controller.OnMiddleButtonUp ? ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnMiddleButtonUp)((Window)controller.controlled, controller, x, y, mods) : true;
       if(result)
-         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp])(controller.window, x, y, mods);
+      {
+         bool(* onMiddleButtonUp)(Window, int, int, Modifiers) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp];
+         if(onMiddleButtonUp)
+            result = onMiddleButtonUp(controller.window, x, y, mods);
+      }
       return result;
    }
 
    bool OnMiddleDoubleClick(int x, int y, Modifiers mods)
    {
-      bool result = ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnMiddleDoubleClick)((Window)controller.controlled, controller, x, y, mods);
+      bool result = controller.OnMiddleDoubleClick ? ((bool(*)(Window, WindowController, int, int, Modifiers))(void *)controller.OnMiddleDoubleClick)((Window)controller.controlled, controller, x, y, mods) : true;
       if(result)
-         result = ((bool(*)(Window, int, int, Modifiers))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick])(controller.window, x, y, mods);
+      {
+         bool(* onMiddleDoubleClick)(Window, int, int, Modifiers) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick];
+         if(onMiddleDoubleClick)
+            onMiddleDoubleClick(controller.window, x, y, mods);
+      }
       return result;
    }
 
    void OnResize(int width, int 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);
+      if(controller.OnResize)
+         ((void(*)(Window, WindowController, int, int))(void *)controller.OnResize)((Window)controller.controlled, controller, width, height);
+      {
+         void(* onResize)(Window, int, int) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnResize];
+         if(onResize)
+            onResize(controller.window, width, height);
+      }
    }
 
    void OnRedraw(Surface 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);
+      if(controller.OnRedraw)
+         ((void(*)(Window, WindowController, Surface))(void *)controller.OnRedraw)((Window)controller.controlled, controller, surface);
+      {
+         void(* onRedraw)(Window, Surface) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRedraw];
+         if(onRedraw)
+            onRedraw(controller.window, surface);
+      }
    }
 
    bool OnCreate()
    {
-      bool result = ((bool(*)(Window, WindowController))(void *)controller.OnCreate)((Window)controller.controlled, controller);
+      bool result = controller.OnCreate ? ((bool(*)(Window, WindowController))(void *)controller.OnCreate)((Window)controller.controlled, controller) : true;
       if(result)
-         result = ((bool(*)(Window))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnCreate])(controller.window);
+      {
+         bool(* onCreate)(Window) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnCreate];
+         if(onCreate)
+            result = onCreate(controller.window);
+      }
       return result;
    }
 
    bool OnLoadGraphics()
    {
-      bool result = ((bool(*)(Window, WindowController))(void *)controller.OnLoadGraphics)((Window)controller.controlled, controller);
+      bool result = controller.OnLoadGraphics ? ((bool(*)(Window, WindowController))(void *)controller.OnLoadGraphics)((Window)controller.controlled, controller) : true;
       if(result)
-         result = ((bool(*)(Window))(void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLoadGraphics])(controller.window);
+      {
+         bool(* onLoadGraphics)(Window) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLoadGraphics];
+         if(onLoadGraphics)
+            result = 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);
+      if(controller.OnUnloadGraphics)
+         ((void(*)(Window, WindowController))(void *)controller.OnUnloadGraphics)((Window)controller.controlled, controller);
+      {
+         void(* onUnloadGraphics)(Window) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnUnloadGraphics];
+         if(onUnloadGraphics)
+            onUnloadGraphics(controller.window);
+      }
    }
 }
 
@@ -10003,7 +10167,7 @@ public:
                for(c = 0; c < size; c++)
                {
                   void * function = class(WindowControllerInterface)._vTbl[c];
-                  if(function != DefaultFunction)
+                  if(function && function != DefaultFunction)
                      value._vTbl[c] = function;
                   else
                      value._vTbl[c] = windowVTbl[c];