Kaynağa Gözat

Completely redone how I handle move/resize events. Now windows just specify non-client areas for move and resize and the rest is left to the OS.

Marko Pintera 12 yıl önce
ebeveyn
işleme
ce39033f5d
51 değiştirilmiş dosya ile 414 ekleme ve 536 silme
  1. 3 4
      BansheeEngine/Include/BsGUIArea.h
  2. 1 1
      BansheeEngine/Include/BsGUIButton.h
  3. 8 3
      BansheeEngine/Include/BsGUIElement.h
  4. 1 1
      BansheeEngine/Include/BsGUIInputBox.h
  5. 1 1
      BansheeEngine/Include/BsGUILabel.h
  6. 1 1
      BansheeEngine/Include/BsGUIScrollArea.h
  7. 1 1
      BansheeEngine/Include/BsGUIScrollBar.h
  8. 1 1
      BansheeEngine/Include/BsGUIScrollBarHandle.h
  9. 1 1
      BansheeEngine/Include/BsGUITexture.h
  10. 1 1
      BansheeEngine/Include/BsGUIToggle.h
  11. 1 1
      BansheeEngine/Include/BsGUIViewport.h
  12. 4 4
      BansheeEngine/Include/BsGUIWidget.h
  13. 1 4
      BansheeEngine/Include/BsGUIWindowFrame.h
  14. 2 2
      BansheeEngine/Source/BsGUIButton.cpp
  15. 9 4
      BansheeEngine/Source/BsGUIElement.cpp
  16. 2 2
      BansheeEngine/Source/BsGUIInputBox.cpp
  17. 2 2
      BansheeEngine/Source/BsGUILabel.cpp
  18. 1 1
      BansheeEngine/Source/BsGUIManager.cpp
  19. 2 2
      BansheeEngine/Source/BsGUIScrollArea.cpp
  20. 2 2
      BansheeEngine/Source/BsGUIScrollBar.cpp
  21. 3 3
      BansheeEngine/Source/BsGUIScrollBarHandle.cpp
  22. 2 2
      BansheeEngine/Source/BsGUITexture.cpp
  23. 2 2
      BansheeEngine/Source/BsGUIToggle.cpp
  24. 1 1
      BansheeEngine/Source/BsGUIViewport.cpp
  25. 2 2
      BansheeEngine/Source/BsGUIWidget.cpp
  26. 3 188
      BansheeEngine/Source/BsGUIWindowFrame.cpp
  27. 1 0
      CamelotClient/Include/BsEditorPrerequisites.h
  28. 2 1
      CamelotClient/Include/BsEditorWindowBase.h
  29. 2 0
      CamelotClient/Include/BsGUITabbedTitleBar.h
  30. 5 0
      CamelotClient/Include/BsGUIWindowFrameWidget.h
  31. 1 1
      CamelotClient/Include/BsGUIWindowMover.h
  32. 1 1
      CamelotClient/Source/BsEditorWindow.cpp
  33. 4 4
      CamelotClient/Source/BsEditorWindowBase.cpp
  34. 28 0
      CamelotClient/Source/BsGUITabbedTitleBar.cpp
  35. 59 0
      CamelotClient/Source/BsGUIWindowFrameWidget.cpp
  36. 3 12
      CamelotClient/Source/BsGUIWindowMover.cpp
  37. 0 20
      CamelotCore/Include/CmCoreThreadAccessor.h
  38. 3 0
      CamelotCore/Include/CmPlatformWndProc.h
  39. 0 12
      CamelotCore/Include/CmRenderWindow.h
  40. 112 0
      CamelotCore/Include/Win32/CmPlatformImpl.h
  41. 94 6
      CamelotCore/Source/CmPlatformWndProc.cpp
  42. 3 0
      CamelotCore/Source/CmRenderWindow.cpp
  43. 28 0
      CamelotCore/Source/Win32/CmPlatformImpl.cpp
  44. 0 6
      CamelotD3D11RenderSystem/Include/CmD3D11RenderWindow.h
  45. 0 64
      CamelotD3D11RenderSystem/Source/CmD3D11RenderWindow.cpp
  46. 0 6
      CamelotD3D9Renderer/Include/CmD3D9RenderWindow.h
  47. 0 65
      CamelotD3D9Renderer/Source/CmD3D9RenderWindow.cpp
  48. 0 6
      CamelotGLRenderer/Include/CmWin32Window.h
  49. 0 65
      CamelotGLRenderer/Source/CmWin32Window.cpp
  50. 10 28
      EditorWindowDock.txt
  51. 0 2
      TODO.txt

+ 3 - 4
BansheeEngine/Include/BsGUIArea.h

@@ -60,12 +60,12 @@ namespace BansheeEngine
 
 
 		void changeParentWidget(GUIWidget* widget);
 		void changeParentWidget(GUIWidget* widget);
 
 
-		CM::UINT32 x() const { return mLeft; }
-		CM::UINT32 y() const { return mTop; }
+		CM::INT32 x() const { return mLeft; }
+		CM::INT32 y() const { return mTop; }
 		CM::UINT32 width() const { return mWidth; }
 		CM::UINT32 width() const { return mWidth; }
 		CM::UINT32 height() const { return mHeight; }
 		CM::UINT32 height() const { return mHeight; }
 
 
-		void _update();
+		void _update();		
 	private:
 	private:
 		friend class GUIWidget;
 		friend class GUIWidget;
 
 
@@ -83,7 +83,6 @@ namespace BansheeEngine
 		GUIArea(GUIWidget* widget, CM::UINT32 x, CM::UINT32 y, CM::UINT16 depth);
 		GUIArea(GUIWidget* widget, CM::UINT32 x, CM::UINT32 y, CM::UINT16 depth);
 
 
 		bool isDirty() const;
 		bool isDirty() const;
-
 		void updateSizeBasedOnParent(CM::UINT32 parentWidth, CM::UINT32 parentHeight);
 		void updateSizeBasedOnParent(CM::UINT32 parentWidth, CM::UINT32 parentHeight);
 
 
 		static void destroyInternal(GUIArea* area);
 		static void destroyInternal(GUIArea* area);

+ 1 - 1
BansheeEngine/Include/BsGUIButton.h

@@ -48,7 +48,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @copydoc GUIElement::updateBounds()
 		 * @copydoc GUIElement::updateBounds()
 		 */
 		 */
-		virtual void updateBounds();
+		virtual void updateClippedBounds();
 
 
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalHeight() const;
 		virtual CM::UINT32 _getOptimalHeight() const;

+ 8 - 3
BansheeEngine/Include/BsGUIElement.h

@@ -74,6 +74,11 @@ namespace BansheeEngine
 		 */
 		 */
 		void updateRenderElements();
 		void updateRenderElements();
 
 
+		/**
+		 * @brief	Gets non-clipped bounds that were assigned to the element by the parent layout.
+		 */
+		CM::Rect getBounds() const;
+
 		virtual bool mouseEvent(const GUIMouseEvent& ev);
 		virtual bool mouseEvent(const GUIMouseEvent& ev);
 		virtual bool keyEvent(const GUIKeyEvent& ev);
 		virtual bool keyEvent(const GUIKeyEvent& ev);
 		virtual bool commandEvent(const GUICommandEvent& ev);
 		virtual bool commandEvent(const GUICommandEvent& ev);
@@ -100,7 +105,7 @@ namespace BansheeEngine
 		virtual CM::UINT32 _getRenderElementDepth(CM::UINT32 renderElementIdx) const { return _getDepth(); }
 		virtual CM::UINT32 _getRenderElementDepth(CM::UINT32 renderElementIdx) const { return _getDepth(); }
 		Type _getType() const { return GUIElementBase::Type::Element; }
 		Type _getType() const { return GUIElementBase::Type::Element; }
 
 
-		const CM::Rect& _getBounds() const { return mBounds; }
+		const CM::Rect& _getClippedBounds() const { return mClippedBounds; }
 		CM::UINT32 _getDepth() const { return mDepth; }
 		CM::UINT32 _getDepth() const { return mDepth; }
 		GUIWidget& _getParentWidget() const { return *mParent; }
 		GUIWidget& _getParentWidget() const { return *mParent; }
 		virtual bool _isInBounds(const CM::Int2 position) const;
 		virtual bool _isInBounds(const CM::Int2 position) const;
@@ -121,7 +126,7 @@ namespace BansheeEngine
 		const GUILayoutOptions& _getLayoutOptions() const { return mLayoutOptions; }
 		const GUILayoutOptions& _getLayoutOptions() const { return mLayoutOptions; }
 	protected:
 	protected:
 		virtual void updateRenderElementsInternal();
 		virtual void updateRenderElementsInternal();
-		virtual void updateBounds() = 0;
+		virtual void updateClippedBounds() = 0;
 
 
 		void setLayoutOptions(const GUILayoutOptions& layoutOptions);
 		void setLayoutOptions(const GUILayoutOptions& layoutOptions);
 		
 		
@@ -133,7 +138,7 @@ namespace BansheeEngine
 
 
 		GUIWidget* mParent;
 		GUIWidget* mParent;
 		GUILayoutOptions mLayoutOptions;
 		GUILayoutOptions mLayoutOptions;
-		CM::Rect mBounds;
+		CM::Rect mClippedBounds;
 
 
 		bool mAcceptsKeyboardFocus;
 		bool mAcceptsKeyboardFocus;
 		CM::UINT32 mDepth;
 		CM::UINT32 mDepth;

+ 1 - 1
BansheeEngine/Include/BsGUIInputBox.h

@@ -46,7 +46,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @copydoc GUIElement::updateBounds()
 		 * @copydoc GUIElement::updateBounds()
 		 */
 		 */
-		virtual void updateBounds();
+		virtual void updateClippedBounds();
 
 
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalHeight() const;
 		virtual CM::UINT32 _getOptimalHeight() const;

+ 1 - 1
BansheeEngine/Include/BsGUILabel.h

@@ -48,7 +48,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @copydoc GUIElement::updateBounds()
 		 * @copydoc GUIElement::updateBounds()
 		 */
 		 */
-		virtual void updateBounds();
+		virtual void updateClippedBounds();
 
 
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalHeight() const;
 		virtual CM::UINT32 _getOptimalHeight() const;

+ 1 - 1
BansheeEngine/Include/BsGUIScrollArea.h

@@ -47,7 +47,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @copydoc GUIElement::updateBounds()
 		 * @copydoc GUIElement::updateBounds()
 		 */
 		 */
-		virtual void updateBounds();
+		virtual void updateClippedBounds();
 
 
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalHeight() const;
 		virtual CM::UINT32 _getOptimalHeight() const;

+ 1 - 1
BansheeEngine/Include/BsGUIScrollBar.h

@@ -56,7 +56,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @copydoc GUIElement::updateBounds()
 		 * @copydoc GUIElement::updateBounds()
 		 */
 		 */
-		virtual void updateBounds();
+		virtual void updateClippedBounds();
 
 
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalHeight() const;
 		virtual CM::UINT32 _getOptimalHeight() const;

+ 1 - 1
BansheeEngine/Include/BsGUIScrollBarHandle.h

@@ -57,7 +57,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @copydoc GUIElement::updateBounds()
 		 * @copydoc GUIElement::updateBounds()
 		 */
 		 */
-		virtual void updateBounds();
+		virtual void updateClippedBounds();
 
 
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalHeight() const;
 		virtual CM::UINT32 _getOptimalHeight() const;

+ 1 - 1
BansheeEngine/Include/BsGUITexture.h

@@ -57,7 +57,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @copydoc GUIElement::updateBounds()
 		 * @copydoc GUIElement::updateBounds()
 		 */
 		 */
-		virtual void updateBounds();
+		virtual void updateClippedBounds();
 
 
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalHeight() const;
 		virtual CM::UINT32 _getOptimalHeight() const;

+ 1 - 1
BansheeEngine/Include/BsGUIToggle.h

@@ -59,7 +59,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @copydoc GUIElement::updateBounds()
 		 * @copydoc GUIElement::updateBounds()
 		 */
 		 */
-		virtual void updateBounds();
+		virtual void updateClippedBounds();
 
 
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalHeight() const;
 		virtual CM::UINT32 _getOptimalHeight() const;

+ 1 - 1
BansheeEngine/Include/BsGUIViewport.h

@@ -51,7 +51,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @copydoc GUIElement::updateBounds()
 		 * @copydoc GUIElement::updateBounds()
 		 */
 		 */
-		virtual void updateBounds();
+		virtual void updateClippedBounds();
 
 
 		/**
 		/**
 		 * @copydoc GUIElement::updateRenderElementsInternal()
 		 * @copydoc GUIElement::updateRenderElementsInternal()

+ 4 - 4
BansheeEngine/Include/BsGUIWidget.h

@@ -77,15 +77,15 @@ namespace BansheeEngine
 
 
 		void registerArea(GUIArea* area);
 		void registerArea(GUIArea* area);
 		void unregisterArea(GUIArea* area);
 		void unregisterArea(GUIArea* area);
-	private:
-		GUIWidget(const GUIWidget& other) { }
-
-		void updateBounds() const;
 
 
 		virtual void ownerWindowResized();
 		virtual void ownerWindowResized();
 		virtual void ownerWindowFocusChanged();
 		virtual void ownerWindowFocusChanged();
 
 
 		virtual void update();
 		virtual void update();
+	private:
+		GUIWidget(const GUIWidget& other) { }
+
+		void updateBounds() const;
 
 
 		CM::RenderWindow* mOwnerWindow;
 		CM::RenderWindow* mOwnerWindow;
 		CM::Viewport* mTarget;
 		CM::Viewport* mTarget;

+ 1 - 4
BansheeEngine/Include/BsGUIWindowFrame.h

@@ -47,7 +47,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @copydoc GUIElement::updateBounds()
 		 * @copydoc GUIElement::updateBounds()
 		 */
 		 */
-		virtual void updateBounds();
+		virtual void updateClippedBounds();
 
 
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalHeight() const;
 		virtual CM::UINT32 _getOptimalHeight() const;
@@ -56,10 +56,7 @@ namespace BansheeEngine
 	private:
 	private:
 		ImageSprite* mImageSprite;
 		ImageSprite* mImageSprite;
 		IMAGE_SPRITE_DESC mDesc;
 		IMAGE_SPRITE_DESC mDesc;
-		bool mResizeCursorSet;
 
 
 		GUIWindowFrame(GUIWidget& parent, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions);
 		GUIWindowFrame(GUIWidget& parent, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions);
-
-		virtual bool mouseEvent(const GUIMouseEvent& ev);
 	};
 	};
 }
 }

+ 2 - 2
BansheeEngine/Source/BsGUIButton.cpp

@@ -118,9 +118,9 @@ namespace BansheeEngine
 		GUIElement::updateRenderElementsInternal();
 		GUIElement::updateRenderElementsInternal();
 	}
 	}
 
 
-	void GUIButton::updateBounds()
+	void GUIButton::updateClippedBounds()
 	{
 	{
-		mBounds = mImageSprite->getBounds(mOffset, mClipRect);
+		mClippedBounds = mImageSprite->getBounds(mOffset, mClipRect);
 	}
 	}
 
 
 	UINT32 GUIButton::_getOptimalWidth() const
 	UINT32 GUIButton::_getOptimalWidth() const

+ 9 - 4
BansheeEngine/Source/BsGUIElement.cpp

@@ -32,7 +32,7 @@ namespace BansheeEngine
 
 
 	void GUIElement::updateRenderElementsInternal()
 	void GUIElement::updateRenderElementsInternal()
 	{
 	{
-		updateBounds();
+		updateClippedBounds();
 	}
 	}
 
 
 	void GUIElement::setLayoutOptions(const GUILayoutOptions& layoutOptions) 
 	void GUIElement::setLayoutOptions(const GUILayoutOptions& layoutOptions) 
@@ -87,7 +87,7 @@ namespace BansheeEngine
 			markMeshAsDirty();
 			markMeshAsDirty();
 
 
 			mOffset = offset;
 			mOffset = offset;
-			updateBounds();
+			updateClippedBounds();
 		}
 		}
 	}
 	}
 
 
@@ -114,7 +114,7 @@ namespace BansheeEngine
 			markMeshAsDirty();
 			markMeshAsDirty();
 
 
 			mClipRect = clipRect; 
 			mClipRect = clipRect; 
-			updateBounds();
+			updateClippedBounds();
 		}
 		}
 	}
 	}
 
 
@@ -134,9 +134,14 @@ namespace BansheeEngine
 		GUIElementBase::_changeParentWidget(widget);
 		GUIElementBase::_changeParentWidget(widget);
 	}
 	}
 
 
+	Rect GUIElement::getBounds() const
+	{
+		return Rect(mOffset.x, mOffset.y, mWidth, mHeight);
+	}
+
 	Rect GUIElement::getVisibleBounds() const
 	Rect GUIElement::getVisibleBounds() const
 	{
 	{
-		Rect bounds = _getBounds();
+		Rect bounds = _getClippedBounds();
 		
 		
 		bounds.x += mStyle->margins.left;
 		bounds.x += mStyle->margins.left;
 		bounds.y += mStyle->margins.top;
 		bounds.y += mStyle->margins.top;

+ 2 - 2
BansheeEngine/Source/BsGUIInputBox.cpp

@@ -137,9 +137,9 @@ namespace BansheeEngine
 		GUIElement::updateRenderElementsInternal();
 		GUIElement::updateRenderElementsInternal();
 	}
 	}
 
 
-	void GUIInputBox::updateBounds()
+	void GUIInputBox::updateClippedBounds()
 	{
 	{
-		mBounds = mImageSprite->getBounds(mOffset, mClipRect);
+		mClippedBounds = mImageSprite->getBounds(mOffset, mClipRect);
 	}
 	}
 
 
 	Sprite* GUIInputBox::renderElemToSprite(UINT32 renderElemIdx, UINT32& localRenderElemIdx) const
 	Sprite* GUIInputBox::renderElemToSprite(UINT32 renderElemIdx, UINT32& localRenderElemIdx) const

+ 2 - 2
BansheeEngine/Source/BsGUILabel.cpp

@@ -53,9 +53,9 @@ namespace BansheeEngine
 		GUIElement::updateRenderElementsInternal();
 		GUIElement::updateRenderElementsInternal();
 	}
 	}
 
 
-	void GUILabel::updateBounds()
+	void GUILabel::updateClippedBounds()
 	{
 	{
-		mBounds = mTextSprite->getBounds(mOffset, mClipRect);
+		mClippedBounds = mTextSprite->getBounds(mOffset, mClipRect);
 	}
 	}
 
 
 	UINT32 GUILabel::_getOptimalWidth() const
 	UINT32 GUILabel::_getOptimalWidth() const

+ 1 - 1
BansheeEngine/Source/BsGUIManager.cpp

@@ -299,7 +299,7 @@ namespace BansheeEngine
 				UINT32 renderElemIdx = elem.renderElement;
 				UINT32 renderElemIdx = elem.renderElement;
 				UINT32 elemDepth = guiElem->_getRenderElementDepth(renderElemIdx);
 				UINT32 elemDepth = guiElem->_getRenderElementDepth(renderElemIdx);
 
 
-				Rect tfrmedBounds = guiElem->_getBounds();
+				Rect tfrmedBounds = guiElem->_getClippedBounds();
 				tfrmedBounds.transform(guiElem->_getParentWidget().SO()->getWorldTfrm());
 				tfrmedBounds.transform(guiElem->_getParentWidget().SO()->getWorldTfrm());
 
 
 				const HMaterial& mat = guiElem->getMaterial(renderElemIdx);
 				const HMaterial& mat = guiElem->getMaterial(renderElemIdx);

+ 2 - 2
BansheeEngine/Source/BsGUIScrollArea.cpp

@@ -50,9 +50,9 @@ namespace BansheeEngine
 		GUIElement::updateRenderElementsInternal();
 		GUIElement::updateRenderElementsInternal();
 	}
 	}
 
 
-	void GUIScrollArea::updateBounds()
+	void GUIScrollArea::updateClippedBounds()
 	{
 	{
-		mBounds = Rect(0, 0, 0, 0); // We don't want any mouse input for this element. This is just a container.
+		mClippedBounds = Rect(0, 0, 0, 0); // We don't want any mouse input for this element. This is just a container.
 	}
 	}
 
 
 	UINT32 GUIScrollArea::_getOptimalWidth() const
 	UINT32 GUIScrollArea::_getOptimalWidth() const

+ 2 - 2
BansheeEngine/Source/BsGUIScrollBar.cpp

@@ -94,9 +94,9 @@ namespace BansheeEngine
 		GUIElement::updateRenderElementsInternal();
 		GUIElement::updateRenderElementsInternal();
 	}
 	}
 
 
-	void GUIScrollBar::updateBounds()
+	void GUIScrollBar::updateClippedBounds()
 	{
 	{
-		mBounds = Rect(0, 0, 0, 0); // We don't want any mouse input for this element. This is just a container.
+		mClippedBounds = Rect(0, 0, 0, 0); // We don't want any mouse input for this element. This is just a container.
 	}
 	}
 
 
 	UINT32 GUIScrollBar::_getOptimalWidth() const
 	UINT32 GUIScrollBar::_getOptimalWidth() const

+ 3 - 3
BansheeEngine/Source/BsGUIScrollBarHandle.cpp

@@ -121,12 +121,12 @@ namespace BansheeEngine
 		GUIElement::updateRenderElementsInternal();
 		GUIElement::updateRenderElementsInternal();
 	}
 	}
 
 
-	void GUIScrollBarHandle::updateBounds()
+	void GUIScrollBarHandle::updateClippedBounds()
 	{
 	{
-		mBounds = Rect(mOffset.x, mOffset.y, mWidth, mHeight);
+		mClippedBounds = Rect(mOffset.x, mOffset.y, mWidth, mHeight);
 
 
 		Rect localClipRect(mClipRect.x + mOffset.x, mClipRect.y + mOffset.y, mClipRect.width, mClipRect.height);
 		Rect localClipRect(mClipRect.x + mOffset.x, mClipRect.y + mOffset.y, mClipRect.width, mClipRect.height);
-		mBounds.clip(localClipRect);
+		mClippedBounds.clip(localClipRect);
 	}
 	}
 
 
 	UINT32 GUIScrollBarHandle::_getOptimalWidth() const
 	UINT32 GUIScrollBarHandle::_getOptimalWidth() const

+ 2 - 2
BansheeEngine/Source/BsGUITexture.cpp

@@ -162,9 +162,9 @@ namespace BansheeEngine
 		GUIElement::updateRenderElementsInternal();
 		GUIElement::updateRenderElementsInternal();
 	}
 	}
 
 
-	void GUITexture::updateBounds()
+	void GUITexture::updateClippedBounds()
 	{
 	{
-		mBounds = mImageSprite->getBounds(mOffset, mClipRect);
+		mClippedBounds = mImageSprite->getBounds(mOffset, mClipRect);
 	}
 	}
 
 
 	UINT32 GUITexture::_getOptimalWidth() const
 	UINT32 GUITexture::_getOptimalWidth() const

+ 2 - 2
BansheeEngine/Source/BsGUIToggle.cpp

@@ -243,9 +243,9 @@ namespace BansheeEngine
 		GUIElement::updateRenderElementsInternal();
 		GUIElement::updateRenderElementsInternal();
 	}
 	}
 
 
-	void GUIToggle::updateBounds()
+	void GUIToggle::updateClippedBounds()
 	{
 	{
-		mBounds = mImageSprite->getBounds(mOffset, mClipRect);
+		mClippedBounds = mImageSprite->getBounds(mOffset, mClipRect);
 	}
 	}
 
 
 	UINT32 GUIToggle::_getOptimalWidth() const
 	UINT32 GUIToggle::_getOptimalWidth() const

+ 1 - 1
BansheeEngine/Source/BsGUIViewport.cpp

@@ -75,7 +75,7 @@ namespace BansheeEngine
 		return 0;
 		return 0;
 	}
 	}
 
 
-	void GUIViewport::updateBounds()
+	void GUIViewport::updateClippedBounds()
 	{
 	{
 		Rect mBounds = Rect(0, 0, mWidth, mHeight);
 		Rect mBounds = Rect(0, 0, mWidth, mHeight);
 		mBounds.clip(mClipRect);
 		mBounds.clip(mClipRect);

+ 2 - 2
BansheeEngine/Source/BsGUIWidget.cpp

@@ -299,11 +299,11 @@ namespace BansheeEngine
 	void GUIWidget::updateBounds() const
 	void GUIWidget::updateBounds() const
 	{
 	{
 		if(mElements.size() > 0)
 		if(mElements.size() > 0)
-			mBounds = mElements[0]->_getBounds();
+			mBounds = mElements[0]->_getClippedBounds();
 
 
 		for(auto& elem : mElements)
 		for(auto& elem : mElements)
 		{
 		{
-			Rect elemBounds = elem->_getBounds();
+			Rect elemBounds = elem->_getClippedBounds();
 			mBounds.encapsulate(elemBounds);
 			mBounds.encapsulate(elemBounds);
 		}
 		}
 	}
 	}

+ 3 - 188
BansheeEngine/Source/BsGUIWindowFrame.cpp

@@ -14,83 +14,6 @@ using namespace CamelotFramework;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	enum class FrameSubArea
-	{
-		TopLeft, TopCenter, TopRight,
-		MiddleLeft, Middle, MiddleRight,
-		BottomLeft, BottomCenter, BottomRight,
-		None
-	};
-
-	FrameSubArea getFrameSubArea(const Int2& position, const Rect& bounds)
-	{
-		INT32 x0 = bounds.x;
-		INT32 x1 = bounds.x + 3;
-		INT32 x2 = bounds.x + bounds.width - 3;
-		INT32 x3 = bounds.x + bounds.width;
-
-		INT32 y0 = bounds.y;
-		INT32 y1 = bounds.y + 3;
-		INT32 y2 = bounds.y + bounds.height - 3;
-		INT32 y3 = bounds.y + bounds.height;
-
-		if(position.x >= x0 && position.x < x1 &&
-			position.y >= y0 && position.y < y1)
-		{
-			return FrameSubArea::TopLeft;
-		}
-
-		if(position.x >= x1 && position.x < x2 &&
-			position.y >= y0 && position.y < y1)
-		{
-			return FrameSubArea::TopCenter;
-		}
-
-		if(position.x >= x2 && position.x < x3 &&
-			position.y >= y0 && position.y < y1)
-		{
-			return FrameSubArea::TopRight;
-		}
-
-		if(position.x >= x0 && position.x < x1 &&
-			position.y >= y1 && position.y < y2)
-		{
-			return FrameSubArea::MiddleLeft;
-		}
-
-		if(position.x >= x1 && position.x < x2 &&
-			position.y >= y1 && position.y < y2)
-		{
-			return FrameSubArea::Middle;
-		}
-
-		if(position.x >= x2 && position.x < x3 &&
-			position.y >= y1 && position.y < y2)
-		{
-			return FrameSubArea::MiddleRight;
-		}
-
-		if(position.x >= x0 && position.x < x1 &&
-			position.y >= y2 && position.y < y3)
-		{
-			return FrameSubArea::BottomLeft;
-		}
-
-		if(position.x >= x1 && position.x < x2 &&
-			position.y >= y2 && position.y < y3)
-		{
-			return FrameSubArea::BottomCenter;
-		}
-
-		if(position.x >= x2 && position.x < x3 &&
-			position.y >= y2 && position.y < y3)
-		{
-			return FrameSubArea::BottomRight;
-		}
-
-		return FrameSubArea::None;
-	}
-
 	const String& GUIWindowFrame::getGUITypeName()
 	const String& GUIWindowFrame::getGUITypeName()
 	{
 	{
 		static String name = "WindowFrame";
 		static String name = "WindowFrame";
@@ -98,7 +21,7 @@ namespace BansheeEngine
 	}
 	}
 
 
 	GUIWindowFrame::GUIWindowFrame(GUIWidget& parent, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions)
 	GUIWindowFrame::GUIWindowFrame(GUIWidget& parent, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions)
-		:GUIElement(parent, style, layoutOptions, false), mResizeCursorSet(false)
+		:GUIElement(parent, style, layoutOptions, false)
 	{
 	{
 		mImageSprite = cm_new<ImageSprite, PoolAlloc>();
 		mImageSprite = cm_new<ImageSprite, PoolAlloc>();
 
 
@@ -167,9 +90,9 @@ namespace BansheeEngine
 		GUIElement::updateRenderElementsInternal();
 		GUIElement::updateRenderElementsInternal();
 	}
 	}
 
 
-	void GUIWindowFrame::updateBounds()
+	void GUIWindowFrame::updateClippedBounds()
 	{
 	{
-		mBounds = mImageSprite->getBounds(mOffset, mClipRect);
+		mClippedBounds = mImageSprite->getBounds(mOffset, mClipRect);
 	}
 	}
 
 
 	UINT32 GUIWindowFrame::_getOptimalWidth() const
 	UINT32 GUIWindowFrame::_getOptimalWidth() const
@@ -194,15 +117,6 @@ namespace BansheeEngine
 
 
 	bool GUIWindowFrame::_isInBounds(const CM::Int2 position) const
 	bool GUIWindowFrame::_isInBounds(const CM::Int2 position) const
 	{
 	{
-		Rect contentBounds = getVisibleBounds();
-
-		if(!contentBounds.contains(position))
-			return false;
-
-		FrameSubArea subArea = getFrameSubArea(position, contentBounds);
-		if(subArea != FrameSubArea::None && subArea != FrameSubArea::Middle)
-			return true;
-
 		return false;
 		return false;
 	}
 	}
 
 
@@ -221,103 +135,4 @@ namespace BansheeEngine
 
 
 		markContentAsDirty();
 		markContentAsDirty();
 	}
 	}
-
-	bool GUIWindowFrame::mouseEvent(const GUIMouseEvent& ev)
-	{
-		if(ev.getType() == GUIMouseEventType::MouseMove || ev.getType() == GUIMouseEventType::MouseDrag)
-		{
-			Rect contentBounds = getVisibleBounds();
-
-			FrameSubArea subArea = getFrameSubArea(ev.getPosition(), contentBounds);
-			if(subArea != FrameSubArea::None && subArea != FrameSubArea::Middle)
-			{
-				switch (subArea)
-				{
-				case BansheeEngine::FrameSubArea::TopLeft:
-					Platform::setCursor(CursorType::SizeNWSE);
-					break;
-				case BansheeEngine::FrameSubArea::TopCenter:
-					Platform::setCursor(CursorType::SizeNS);
-					break;
-				case BansheeEngine::FrameSubArea::TopRight:
-					Platform::setCursor(CursorType::SizeNESW);
-					break;
-				case BansheeEngine::FrameSubArea::MiddleLeft:
-					Platform::setCursor(CursorType::SizeWE);
-					break;
-				case BansheeEngine::FrameSubArea::MiddleRight:
-					Platform::setCursor(CursorType::SizeWE);
-					break;
-				case BansheeEngine::FrameSubArea::BottomLeft:
-					Platform::setCursor(CursorType::SizeNESW);
-					break;
-				case BansheeEngine::FrameSubArea::BottomCenter:
-					Platform::setCursor(CursorType::SizeNS);
-					break;
-				case BansheeEngine::FrameSubArea::BottomRight:
-					Platform::setCursor(CursorType::SizeNWSE);
-					break;
-				}
-
-				mResizeCursorSet = true;
-
-				return true;
-			}
-		}
-
-		if(ev.getType() == GUIMouseEventType::MouseDown)
-		{
-			Rect contentBounds = getVisibleBounds();
-
-			FrameSubArea subArea = getFrameSubArea(ev.getPosition(), contentBounds);
-			if(subArea != FrameSubArea::None && subArea != FrameSubArea::Middle)
-			{
-				RenderWindow* window = _getParentWidget().getOwnerWindow();
-				RenderWindowPtr windowPtr = std::static_pointer_cast<RenderWindow>(window->getThisPtr());
-
-				switch (subArea)
-				{
-				case BansheeEngine::FrameSubArea::TopLeft:
-					gMainCA().startResize(windowPtr, WindowResizeDirection::TopLeft);
-					break;
-				case BansheeEngine::FrameSubArea::TopCenter:
-					gMainCA().startResize(windowPtr, WindowResizeDirection::Top);
-					break;
-				case BansheeEngine::FrameSubArea::TopRight:
-					gMainCA().startResize(windowPtr, WindowResizeDirection::TopRight);
-					break;
-				case BansheeEngine::FrameSubArea::MiddleLeft:
-					gMainCA().startResize(windowPtr, WindowResizeDirection::Left);
-					break;
-				case BansheeEngine::FrameSubArea::MiddleRight:
-					gMainCA().startResize(windowPtr, WindowResizeDirection::Right);
-					break;
-				case BansheeEngine::FrameSubArea::BottomLeft:
-					gMainCA().startResize(windowPtr, WindowResizeDirection::BottomLeft);
-					break;
-				case BansheeEngine::FrameSubArea::BottomCenter:
-					gMainCA().startResize(windowPtr, WindowResizeDirection::Bottom);
-					break;
-				case BansheeEngine::FrameSubArea::BottomRight:
-					gMainCA().startResize(windowPtr, WindowResizeDirection::BottomRight);
-					break;
-				}
-
-				return true;
-			}
-		}
-
-		if(ev.getType() == GUIMouseEventType::MouseOut || ev.getType() == GUIMouseEventType::MouseDragEnd)
-		{
-			if(mResizeCursorSet)
-			{
-				Platform::setCursor(CursorType::Arrow);
-				mResizeCursorSet = false;
-
-				return true;
-			}
-		}
-
-		return false;
-	}
 }
 }

+ 1 - 0
CamelotClient/Include/BsEditorPrerequisites.h

@@ -15,6 +15,7 @@ namespace BansheeEditor
 	class EditorWindowManager;
 	class EditorWindowManager;
 	class DockManager;
 	class DockManager;
 	class MainEditorWindow;
 	class MainEditorWindow;
+	class WindowFrameWidget;
 
 
 	enum class DragAndDropType
 	enum class DragAndDropType
 	{
 	{

+ 2 - 1
CamelotClient/Include/BsEditorWindowBase.h

@@ -25,9 +25,11 @@ namespace BansheeEditor
 		EditorWindowBase();
 		EditorWindowBase();
 		EditorWindowBase(CM::RenderWindowPtr renderWindow);
 		EditorWindowBase(CM::RenderWindowPtr renderWindow);
 
 
+		CM::RenderWindowPtr mRenderWindow;
 		CM::HSceneObject mSceneObject;
 		CM::HSceneObject mSceneObject;
 		BS::HGUIWidget mGUI;
 		BS::HGUIWidget mGUI;
 		BS::HCamera mCamera;
 		BS::HCamera mCamera;
+		CM::GameObjectHandle<WindowFrameWidget> mWindowFrame;
 		bool mOwnsRenderWindow;
 		bool mOwnsRenderWindow;
 
 
 		void construct(CM::RenderWindowPtr renderWindow);
 		void construct(CM::RenderWindowPtr renderWindow);
@@ -35,7 +37,6 @@ namespace BansheeEditor
 		virtual void movedOrResized() { }
 		virtual void movedOrResized() { }
 	private:
 	private:
 		boost::signals::connection mMoveOrResizeConn;
 		boost::signals::connection mMoveOrResizeConn;
-		CM::RenderWindowPtr mRenderWindow;
 		
 		
 		void movedOrResized(CM::RenderWindow& renderWindow);
 		void movedOrResized(CM::RenderWindow& renderWindow);
 	};
 	};

+ 2 - 0
CamelotClient/Include/BsGUITabbedTitleBar.h

@@ -42,5 +42,7 @@ namespace BansheeEditor
 		void tabDraggedOn(CM::UINT32 tabIdx);
 		void tabDraggedOn(CM::UINT32 tabIdx);
 
 
 		CM::INT32 uniqueIdxToSeqIdx(CM::UINT32 uniqueIdx) const;
 		CM::INT32 uniqueIdxToSeqIdx(CM::UINT32 uniqueIdx) const;
+
+		void refreshNonClientAreas();
 	};
 	};
 }
 }

+ 5 - 0
CamelotClient/Include/BsGUIWindowFrameWidget.h

@@ -15,6 +15,8 @@ namespace BansheeEditor
 		virtual void initialize(CM::Viewport* target, CM::RenderWindow* ownerWindow);
 		virtual void initialize(CM::Viewport* target, CM::RenderWindow* ownerWindow);
 
 
 	protected:
 	protected:
+		static const CM::UINT32 RESIZE_BORDER_WIDTH;
+
 		BS::GUIArea* mWindowFrameArea;
 		BS::GUIArea* mWindowFrameArea;
 		BS::GUIWindowFrame* mWindowFrame;
 		BS::GUIWindowFrame* mWindowFrame;
 
 
@@ -22,5 +24,8 @@ namespace BansheeEditor
 
 
 		virtual bool _mouseEvent(BS::GUIElement* element, const BS::GUIMouseEvent& ev);
 		virtual bool _mouseEvent(BS::GUIElement* element, const BS::GUIMouseEvent& ev);
 		virtual void ownerWindowFocusChanged();
 		virtual void ownerWindowFocusChanged();
+		virtual void ownerWindowResized();
+
+		void refreshNonClientAreas() const;
 	};
 	};
 }
 }

+ 1 - 1
CamelotClient/Include/BsGUIWindowMover.h

@@ -50,7 +50,7 @@ namespace BansheeEditor
 		/**
 		/**
 		 * @copydoc GUIElement::updateBounds()
 		 * @copydoc GUIElement::updateBounds()
 		 */
 		 */
-		virtual void updateBounds();
+		virtual void updateClippedBounds();
 
 
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalWidth() const;
 		virtual CM::UINT32 _getOptimalHeight() const;
 		virtual CM::UINT32 _getOptimalHeight() const;

+ 1 - 1
CamelotClient/Source/BsEditorWindow.cpp

@@ -11,7 +11,7 @@ namespace BansheeEditor
 		:EditorWindowBase(), mWidgets(cm_new<EditorWidgetContainer>(mGUI.get()))
 		:EditorWindowBase(), mWidgets(cm_new<EditorWidgetContainer>(mGUI.get()))
 	{
 	{
 		updateSize();
 		updateSize();
-
+		
 		mWidgets->onWidgetClosed.connect(boost::bind(&EditorWindow::widgetRemoved, this));
 		mWidgets->onWidgetClosed.connect(boost::bind(&EditorWindow::widgetRemoved, this));
 		mWidgets->onWidgetHidden.connect(boost::bind(&EditorWindow::widgetHidden, this));
 		mWidgets->onWidgetHidden.connect(boost::bind(&EditorWindow::widgetHidden, this));
 	}
 	}

+ 4 - 4
CamelotClient/Source/BsEditorWindowBase.cpp

@@ -79,10 +79,10 @@ namespace BansheeEditor
 
 
 		mGUI->setSkin(&EngineGUI::instance().getSkin());
 		mGUI->setSkin(&EngineGUI::instance().getSkin());
 
 
-		GameObjectHandle<WindowFrameWidget> frame = mSceneObject->addComponent<WindowFrameWidget>();
-		frame->setSkin(&EngineGUI::instance().getSkin());
-		frame->initialize(mCamera->getViewport().get(), renderWindow.get());
-		frame->setDepth(129);
+		mWindowFrame = mSceneObject->addComponent<WindowFrameWidget>();
+		mWindowFrame->setSkin(&EngineGUI::instance().getSkin());
+		mWindowFrame->initialize(mCamera->getViewport().get(), renderWindow.get());
+		mWindowFrame->setDepth(129);
 
 
 		mMoveOrResizeConn = RenderWindowManager::instance().onMovedOrResized.connect(boost::bind(&EditorWindowBase::movedOrResized, this, _1));
 		mMoveOrResizeConn = RenderWindowManager::instance().onMovedOrResized.connect(boost::bind(&EditorWindowBase::movedOrResized, this, _1));
 	}
 	}

+ 28 - 0
CamelotClient/Source/BsGUITabbedTitleBar.cpp

@@ -9,6 +9,7 @@
 #include "BsEngineGUI.h"
 #include "BsEngineGUI.h"
 #include "BsGUIWidget.h"
 #include "BsGUIWidget.h"
 #include "CmMath.h"
 #include "CmMath.h"
+#include "CmPlatform.h"
 
 
 using namespace CamelotFramework;
 using namespace CamelotFramework;
 using namespace BansheeEngine;
 using namespace BansheeEngine;
@@ -42,6 +43,8 @@ namespace BansheeEditor
 		mMainLayout->addSpace(3);
 		mMainLayout->addSpace(3);
 		mMainLayout->addElement(mCloseBtn);
 		mMainLayout->addElement(mCloseBtn);
 		mMainArea->getLayout().addSpace(3);
 		mMainArea->getLayout().addSpace(3);
+
+		refreshNonClientAreas();
 	}
 	}
 
 
 	GUITabbedTitleBar::~GUITabbedTitleBar()
 	GUITabbedTitleBar::~GUITabbedTitleBar()
@@ -88,6 +91,8 @@ namespace BansheeEditor
 		mMainLayout->insertElement(idx * 2, newDragDropElement);
 		mMainLayout->insertElement(idx * 2, newDragDropElement);
 
 
 		mUniqueTabIdx++;
 		mUniqueTabIdx++;
+
+		refreshNonClientAreas();
 	}
 	}
 
 
 	void GUITabbedTitleBar::removeTab(UINT32 idx)
 	void GUITabbedTitleBar::removeTab(UINT32 idx)
@@ -102,18 +107,24 @@ namespace BansheeEditor
 
 
 		mTabButtons.erase(mTabButtons.begin() + idx);
 		mTabButtons.erase(mTabButtons.begin() + idx);
 		mDragDropElements.erase(mDragDropElements.begin() + idx);
 		mDragDropElements.erase(mDragDropElements.begin() + idx);
+
+		refreshNonClientAreas();
 	}
 	}
 
 
 	void GUITabbedTitleBar::setPosition(INT32 x, INT32 y)
 	void GUITabbedTitleBar::setPosition(INT32 x, INT32 y)
 	{
 	{
 		mMainArea->setPosition(x, y);
 		mMainArea->setPosition(x, y);
 		mBackgroundArea->setPosition(x, y);
 		mBackgroundArea->setPosition(x, y);
+
+		refreshNonClientAreas();
 	}
 	}
 
 
 	void GUITabbedTitleBar::setSize(UINT32 width, UINT32 height)
 	void GUITabbedTitleBar::setSize(UINT32 width, UINT32 height)
 	{
 	{
 		mMainArea->setSize(width, height);
 		mMainArea->setSize(width, height);
 		mBackgroundArea->setSize(width, height);
 		mBackgroundArea->setSize(width, height);
+
+		refreshNonClientAreas();
 	}
 	}
 
 
 	void GUITabbedTitleBar::tabToggled(CM::UINT32 tabIdx)
 	void GUITabbedTitleBar::tabToggled(CM::UINT32 tabIdx)
@@ -176,4 +187,21 @@ namespace BansheeEditor
 
 
 		return -1;
 		return -1;
 	}
 	}
+
+	void GUITabbedTitleBar::refreshNonClientAreas()
+	{
+		// If the size or contents of the area changed this frame the layout won't be updated yet,
+		// so force the update right away so we get correct element bounds
+		mMainArea->_update();
+
+		CM::Vector<CM::Rect>::type nonClientAreas;
+		for(auto& elem : mDragDropElements)
+		{
+			nonClientAreas.push_back(elem->getBounds());
+		}
+
+		nonClientAreas.push_back(mLastDropElement->getBounds());
+
+		Platform::setCaptionNonClientAreas(*mParentWidget->getOwnerWindow(), nonClientAreas);
+	}
 }
 }

+ 59 - 0
CamelotClient/Source/BsGUIWindowFrameWidget.cpp

@@ -7,12 +7,15 @@
 #include "BsGUIMouseEvent.h"
 #include "BsGUIMouseEvent.h"
 #include "CmRenderWindow.h"
 #include "CmRenderWindow.h"
 #include "CmMath.h"
 #include "CmMath.h"
+#include "CmPlatform.h"
 
 
 using namespace CamelotFramework;
 using namespace CamelotFramework;
 using namespace BansheeEngine;
 using namespace BansheeEngine;
 
 
 namespace BansheeEditor
 namespace BansheeEditor
 {
 {
+	const UINT32 WindowFrameWidget::RESIZE_BORDER_WIDTH = 3;
+
 	WindowFrameWidget::WindowFrameWidget(const HSceneObject& parent)
 	WindowFrameWidget::WindowFrameWidget(const HSceneObject& parent)
 		:GUIWidget(parent), mWindowFrameArea(nullptr)
 		:GUIWidget(parent), mWindowFrameArea(nullptr)
 	{
 	{
@@ -35,6 +38,8 @@ namespace BansheeEditor
 
 
 		mWindowFrame = GUIWindowFrame::create(*this, getSkin()->getStyle("WindowFrame"));
 		mWindowFrame = GUIWindowFrame::create(*this, getSkin()->getStyle("WindowFrame"));
 		mWindowFrameArea->getLayout().addElement(mWindowFrame);
 		mWindowFrameArea->getLayout().addElement(mWindowFrame);
+
+		refreshNonClientAreas();
 	}
 	}
 
 
 	void WindowFrameWidget::update()
 	void WindowFrameWidget::update()
@@ -50,5 +55,59 @@ namespace BansheeEditor
 	void WindowFrameWidget::ownerWindowFocusChanged()
 	void WindowFrameWidget::ownerWindowFocusChanged()
 	{
 	{
 		mWindowFrame->setFocused(getOwnerWindow()->hasFocus());
 		mWindowFrame->setFocused(getOwnerWindow()->hasFocus());
+
+		GUIWidget::ownerWindowFocusChanged();
+	}
+
+	void WindowFrameWidget::ownerWindowResized()
+	{
+		GUIWidget::ownerWindowResized();
+
+		refreshNonClientAreas();
+	}
+
+	void WindowFrameWidget::refreshNonClientAreas() const
+	{
+		INT32 x = mWindowFrameArea->x();
+		INT32 y = mWindowFrameArea->y();
+
+		UINT32 width = mWindowFrameArea->width();
+		UINT32 height = mWindowFrameArea->height();
+
+		CM::Vector<NonClientResizeArea>::type nonClientAreas(8);
+
+		nonClientAreas[0].type = NonClientAreaBorderType::TopLeft;
+		nonClientAreas[0].area = Rect(x, y, 
+			RESIZE_BORDER_WIDTH, RESIZE_BORDER_WIDTH);
+
+		nonClientAreas[1].type = NonClientAreaBorderType::Top;
+		nonClientAreas[1].area = Rect(x + RESIZE_BORDER_WIDTH, y, 
+			width - 2 * RESIZE_BORDER_WIDTH, RESIZE_BORDER_WIDTH);
+
+		nonClientAreas[2].type = NonClientAreaBorderType::TopRight;
+		nonClientAreas[2].area = Rect(x + width - RESIZE_BORDER_WIDTH, y, 
+			RESIZE_BORDER_WIDTH, RESIZE_BORDER_WIDTH);
+
+		nonClientAreas[3].type = NonClientAreaBorderType::Left;
+		nonClientAreas[3].area = Rect(x, y + RESIZE_BORDER_WIDTH, 
+			RESIZE_BORDER_WIDTH, height - 2 * RESIZE_BORDER_WIDTH);
+
+		nonClientAreas[4].type = NonClientAreaBorderType::Right;
+		nonClientAreas[4].area = Rect(x + width - RESIZE_BORDER_WIDTH, y + RESIZE_BORDER_WIDTH, 
+			RESIZE_BORDER_WIDTH, height - 2 * RESIZE_BORDER_WIDTH);
+
+		nonClientAreas[5].type = NonClientAreaBorderType::BottomLeft;
+		nonClientAreas[5].area = Rect(x, y + height - RESIZE_BORDER_WIDTH, 
+			RESIZE_BORDER_WIDTH, RESIZE_BORDER_WIDTH);
+
+		nonClientAreas[6].type = NonClientAreaBorderType::Bottom;
+		nonClientAreas[6].area = Rect(x + RESIZE_BORDER_WIDTH, y + height - RESIZE_BORDER_WIDTH, 
+			width - 2 * RESIZE_BORDER_WIDTH, RESIZE_BORDER_WIDTH);
+
+		nonClientAreas[7].type = NonClientAreaBorderType::BottomRight;
+		nonClientAreas[7].area = Rect(x + width - RESIZE_BORDER_WIDTH, y + height - RESIZE_BORDER_WIDTH, 
+			RESIZE_BORDER_WIDTH, RESIZE_BORDER_WIDTH);
+
+		Platform::setResizeNonClientAreas(*getOwnerWindow(), nonClientAreas);
 	}
 	}
 }
 }

+ 3 - 12
CamelotClient/Source/BsGUIWindowMover.cpp

@@ -89,9 +89,9 @@ namespace BansheeEditor
 		GUIElement::updateRenderElementsInternal();
 		GUIElement::updateRenderElementsInternal();
 	}
 	}
 
 
-	void GUIWindowMover::updateBounds()
+	void GUIWindowMover::updateClippedBounds()
 	{
 	{
-		mBounds = mImageSprite->getBounds(mOffset, mClipRect);
+		mClippedBounds = mImageSprite->getBounds(mOffset, mClipRect);
 	}
 	}
 
 
 	UINT32 GUIWindowMover::_getOptimalWidth() const
 	UINT32 GUIWindowMover::_getOptimalWidth() const
@@ -132,16 +132,7 @@ namespace BansheeEditor
 
 
 	bool GUIWindowMover::mouseEvent(const GUIMouseEvent& ev)
 	bool GUIWindowMover::mouseEvent(const GUIMouseEvent& ev)
 	{
 	{
-		if(ev.getType() == GUIMouseEventType::MouseDown)
-		{
-			RenderWindow* window = _getParentWidget().getOwnerWindow();
-			RenderWindowPtr windowPtr = std::static_pointer_cast<RenderWindow>(window->getThisPtr());
-
-			gMainCA().startMove(windowPtr);
-
-			return true;
-		}
-		else if(ev.getType() == GUIMouseEventType::MouseDragAndDropDropped)
+		if(ev.getType() == GUIMouseEventType::MouseDragAndDropDropped)
 		{
 		{
 			if(!onDraggedItemDropped.empty())
 			if(!onDraggedItemDropped.empty())
 				onDraggedItemDropped();
 				onDraggedItemDropped();

+ 0 - 20
CamelotCore/Include/CmCoreThreadAccessor.h

@@ -252,26 +252,6 @@ namespace CamelotFramework
 			mCommandQueue->queue(boost::bind(&RenderWindow::move, renderWindow.get(), left, top));
 			mCommandQueue->queue(boost::bind(&RenderWindow::move, renderWindow.get(), left, top));
 		}
 		}
 
 
-		void startResize(RenderWindowPtr& renderWindow, WindowResizeDirection direction)
-		{
-			mCommandQueue->queue(boost::bind(&RenderWindow::startResize, renderWindow.get(), direction));
-		}
-
-		void endResize(RenderWindowPtr& renderWindow)
-		{
-			mCommandQueue->queue(boost::bind(&RenderWindow::endResize, renderWindow.get()));
-		}
-
-		void startMove(RenderWindowPtr& renderWindow)
-		{
-			mCommandQueue->queue(boost::bind(&RenderWindow::startMove, renderWindow.get()));
-		}
-
-		void endMove(RenderWindowPtr& renderWindow)
-		{
-			mCommandQueue->queue(boost::bind(&RenderWindow::endMove, renderWindow.get()));
-		}
-
 		void hideWindow(RenderWindowPtr& renderWindow)
 		void hideWindow(RenderWindowPtr& renderWindow)
 		{
 		{
 			mCommandQueue->queue(boost::bind(&RenderWindow::setHidden, renderWindow.get(), true));
 			mCommandQueue->queue(boost::bind(&RenderWindow::setHidden, renderWindow.get(), true));

+ 3 - 0
CamelotCore/Include/CmPlatformWndProc.h

@@ -9,5 +9,8 @@ namespace CamelotFramework
 	{
 	{
 	public:
 	public:
 		static LRESULT CALLBACK _win32WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 		static LRESULT CALLBACK _win32WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+	private:
+		static LRESULT translateNonClientAreaType(NonClientAreaBorderType type);
 	};
 	};
 }
 }

+ 0 - 12
CamelotCore/Include/CmRenderWindow.h

@@ -39,12 +39,6 @@ namespace CamelotFramework
 		Fixed
 		Fixed
 	};
 	};
 
 
-	enum class WindowResizeDirection
-	{
-		Left, TopLeft, Top, TopRight,
-		Right, BottomRight, Bottom, BottomLeft
-	};
-
 	struct CM_EXPORT RENDER_WINDOW_DESC
 	struct CM_EXPORT RENDER_WINDOW_DESC
 	{
 	{
 		RENDER_WINDOW_DESC()
 		RENDER_WINDOW_DESC()
@@ -142,12 +136,6 @@ namespace CamelotFramework
 		virtual Int2 screenToWindowPos(const Int2& screenPos) const = 0;
 		virtual Int2 screenToWindowPos(const Int2& screenPos) const = 0;
 		virtual Int2 windowToScreenPos(const Int2& windowPos) const = 0;
 		virtual Int2 windowToScreenPos(const Int2& windowPos) const = 0;
 
 
-		virtual void startResize(WindowResizeDirection direction) = 0;
-		virtual void endResize() = 0;
-
-		virtual void startMove() = 0;
-		virtual void endMove() = 0;
-
 		virtual void destroy();
 		virtual void destroy();
 
 
 		static RenderWindowPtr create(RENDER_WINDOW_DESC& desc, RenderWindowPtr parentWindow = nullptr);
 		static RenderWindowPtr create(RENDER_WINDOW_DESC& desc, RenderWindowPtr parentWindow = nullptr);

+ 112 - 0
CamelotCore/Include/Win32/CmPlatformImpl.h

@@ -17,6 +17,30 @@ namespace CamelotFramework
 
 
 		Pimpl* data;
 		Pimpl* data;
 	};
 	};
+	
+	enum class NonClientAreaBorderType
+	{
+		TopLeft,
+		Top,
+		TopRight,
+		Left,
+		Right,
+		BottomLeft,
+		Bottom,
+		BottomRight	
+	};
+
+	struct CM_EXPORT NonClientResizeArea
+	{
+		NonClientAreaBorderType type;
+		Rect area;
+	};
+
+	struct CM_EXPORT WindowNonClientAreaData
+	{
+		Vector<NonClientResizeArea>::type resizeAreas;
+		Vector<Rect>::type moveAreas;
+	};
 
 
 	/**
 	/**
 	 * @brief	Provides access for version Windows operating system functions, including
 	 * @brief	Provides access for version Windows operating system functions, including
@@ -30,24 +54,109 @@ namespace CamelotFramework
 
 
 		/**
 		/**
 		 * @brief	Moves the cursor to the specified screen position.
 		 * @brief	Moves the cursor to the specified screen position.
+		 * 			
+		 * @note	Thread safe. 
 		 */
 		 */
 		static void setCursorPosition(const Int2& screenPos);
 		static void setCursorPosition(const Int2& screenPos);
 
 
+		/**
+		 * @brief	Capture mouse to this window so that we get mouse input even if the mouse leaves the window area.
+		 *
+		 * @note	Thread safe.
+		 */
 		static void captureMouse(const RenderWindow& window);
 		static void captureMouse(const RenderWindow& window);
+		/**
+		 * @brief	Releases the mouse capture set by "captureMouse"
+		 * 			
+		 * @note	Thread safe.
+		 */
 		static void releaseMouseCapture();
 		static void releaseMouseCapture();
 
 
+		/**
+		 * @brief	Limit cursor movement to the specified window.
+		 *
+		 * @note	Thread safe.
+		 */
 		static void clipCursorToWindow(const RenderWindow& window);
 		static void clipCursorToWindow(const RenderWindow& window);
+		/**
+		 * @brief	Clip cursor to specific area on the screen.
+		 *
+		 * @note	Thread safe.
+		 */
 		static void clipCursorToRect(const Rect& screenRect);
 		static void clipCursorToRect(const Rect& screenRect);
+		/**
+		 * @brief	Disables cursor clipping.
+		 * 			
+		 * @note	Thread safe.
+		 */
 		static void clipCursorDisable();
 		static void clipCursorDisable();
 
 
+		/**
+		 * @brief	Hides the cursor.
+		 * 			
+		 * @note	Thread safe.
+		 */
 		static void hideCursor();
 		static void hideCursor();
+		/**
+		 * @brief	Shows the cursor.
+		 * 			
+		 * @note	Thread safe.
+		 */
 		static void showCursor();
 		static void showCursor();
 
 
+		/**
+		 * @brief	Query if the cursor is hidden.
+		 *
+		 * @note	Thread safe.
+		 */
 		static bool isCursorHidden() { return mIsCursorHidden; }
 		static bool isCursorHidden() { return mIsCursorHidden; }
 		
 		
+		/**
+		 * @brief	Sets a cursor icon. Uses built-in platform cursor types.
+		 *
+		 * @note	Thread safe.
+		 */
 		static void setCursor(CursorType type);
 		static void setCursor(CursorType type);
+		/**
+		 * @brief	Sets a cursor using a custom image.
+		 *
+		 * @param 	pixelData	Cursor image data.
+		 * @param	hotSpot		Offset on the cursor image to where the actual input happens (e.g. tip of the Arrow cursor).
+		 * 						
+		 * @note	Thread safe.
+		 */
 		static void setCustomCursor(PixelData& pixelData, const Int2& hotSpot);
 		static void setCustomCursor(PixelData& pixelData, const Int2& hotSpot);
 
 
+		/**
+		 * @brief	Sets custom caption non client areas for the specified window. Using custom client
+		 * 			areas will override window move/drag operation and trigger when user interacts
+		 * 			with the custom area.
+		 * 			
+		 * @note	Thread safe.
+		 * 			All provided areas are relative to the specified window.
+		 * 			Mostly useful for frameless windows that don't have typical caption bar.
+		 */
+		static void setCaptionNonClientAreas(const RenderWindow& window, const Vector<Rect>::type& nonClientAreas);
+
+		/**
+		 * @brief	Sets custom non client areas for the specified window. Using custom client
+		 * 			areas will override window resize operation and trigger when user interacts
+		 * 			with the custom area.
+		 * 			
+		 * @note	Thread safe.
+		 * 			All provided areas are relative to the specified window.
+		 * 			Mostly useful for frameless windows that don't have typical border.
+		 */
+		static void setResizeNonClientAreas(const RenderWindow& window, const Vector<NonClientResizeArea>::type& nonClientAreas);
+
+		/**
+		 * @brief	Resets the non client areas for the specified windows and allows 
+		 * 			the platform to use the default values.
+		 * 			
+		 * @note	Thread safe.
+		 */
+		static void resetNonClientAreas(const RenderWindow& window);
+
 		/**
 		/**
 		 * @brief	Message pump. Processes OS messages and returns when it's free.
 		 * @brief	Message pump. Processes OS messages and returns when it's free.
 		 * 			
 		 * 			
@@ -68,6 +177,9 @@ namespace CamelotFramework
 		static bool mIsCursorHidden;
 		static bool mIsCursorHidden;
 		static NativeCursorData mCursor;
 		static NativeCursorData mCursor;
 		static bool mUsingCustomCursor;
 		static bool mUsingCustomCursor;
+		static Map<const RenderWindow*, WindowNonClientAreaData>::type mNonClientAreas;
+
+		CM_STATIC_MUTEX(mSync);
 
 
 		static void win32ShowCursor();
 		static void win32ShowCursor();
 		static void win32HideCursor();
 		static void win32HideCursor();

+ 94 - 6
CamelotCore/Source/CmPlatformWndProc.cpp

@@ -81,7 +81,37 @@ namespace CamelotFramework
 			if(isCursorHidden())
 			if(isCursorHidden())
 				win32HideCursor();
 				win32HideCursor();
 			else
 			else
+			{
+				switch (LOWORD(lParam))
+				{
+				case HTTOPLEFT:
+					SetCursor(LoadCursor(0, IDC_SIZENWSE));
+					return 0;
+				case HTTOP:
+					SetCursor(LoadCursor(0, IDC_SIZENS));
+					return 0;
+				case HTTOPRIGHT:
+					SetCursor(LoadCursor(0, IDC_SIZENESW));
+					return 0;
+				case HTLEFT:
+					SetCursor(LoadCursor(0, IDC_SIZEWE));
+					return 0;
+				case HTRIGHT:
+					SetCursor(LoadCursor(0, IDC_SIZEWE));
+					return 0;
+				case HTBOTTOMLEFT:
+					SetCursor(LoadCursor(0, IDC_SIZENESW));
+					return 0;
+				case HTBOTTOM:
+					SetCursor(LoadCursor(0, IDC_SIZENS));
+					return 0;
+				case HTBOTTOMRIGHT:
+					SetCursor(LoadCursor(0, IDC_SIZENWSE));
+					return 0;
+				}
+
 				win32ShowCursor();
 				win32ShowCursor();
+			}
 			return true;
 			return true;
 		case WM_GETMINMAXINFO:
 		case WM_GETMINMAXINFO:
 			// Prevent the window from going smaller than some minimu size
 			// Prevent the window from going smaller than some minimu size
@@ -95,13 +125,37 @@ namespace CamelotFramework
 
 
 				return 0;
 				return 0;
 			}
 			}
-		case WM_NCLBUTTONUP:
+		case WM_NCHITTEST:
 			{
 			{
-				break;
-			}
-		case WM_LBUTTONUP:
-			{
-				break;
+				auto iterFind = mNonClientAreas.find(win);
+				if(iterFind == mNonClientAreas.end())
+					break;
+
+				POINT mousePos;
+				mousePos.x = GET_X_LPARAM(lParam);
+				mousePos.y = GET_Y_LPARAM(lParam); 
+
+				ScreenToClient(hWnd, &mousePos);
+
+				Int2 mousePosInt;
+				mousePosInt.x = mousePos.x;
+				mousePosInt.y = mousePos.y;
+
+				Vector<NonClientResizeArea>::type& resizeAreasPerWindow = iterFind->second.resizeAreas;
+				for(auto area : resizeAreasPerWindow)
+				{
+					if(area.area.contains(mousePosInt))
+						return translateNonClientAreaType(area.type);
+				}
+
+				Vector<Rect>::type& moveAreasPerWindow = iterFind->second.moveAreas;
+				for(auto area : moveAreasPerWindow)
+				{
+					if(area.contains(mousePosInt))
+						return HTCAPTION;
+				}
+
+				return HTCLIENT;
 			}
 			}
 		case WM_MOUSEMOVE:
 		case WM_MOUSEMOVE:
 			{
 			{
@@ -192,4 +246,38 @@ namespace CamelotFramework
 
 
 		return DefWindowProc( hWnd, uMsg, wParam, lParam );
 		return DefWindowProc( hWnd, uMsg, wParam, lParam );
 	}
 	}
+
+	LRESULT PlatformWndProc::translateNonClientAreaType(NonClientAreaBorderType type)
+	{
+		LRESULT dir = HTCLIENT;
+		switch(type)
+		{
+		case NonClientAreaBorderType::Left:
+			dir = HTLEFT;
+			break;
+		case NonClientAreaBorderType::TopLeft:
+			dir = HTTOPLEFT;
+			break;
+		case NonClientAreaBorderType::Top:
+			dir = HTTOP;
+			break;
+		case NonClientAreaBorderType::TopRight:
+			dir = HTTOPRIGHT;
+			break;
+		case NonClientAreaBorderType::Right:
+			dir = HTRIGHT;
+			break;
+		case NonClientAreaBorderType::BottomRight:
+			dir = HTBOTTOMRIGHT;
+			break;
+		case NonClientAreaBorderType::Bottom:
+			dir = HTBOTTOM;
+			break;
+		case NonClientAreaBorderType::BottomLeft:
+			dir = HTBOTTOMLEFT;
+			break;
+		}
+
+		return dir;
+	}
 }
 }

+ 3 - 0
CamelotCore/Source/CmRenderWindow.cpp

@@ -29,6 +29,7 @@ THE SOFTWARE.
 #include "CmCoreThread.h"
 #include "CmCoreThread.h"
 #include "CmRenderWindowManager.h"
 #include "CmRenderWindowManager.h"
 #include "CmViewport.h"
 #include "CmViewport.h"
+#include "CmPlatform.h"
 
 
 namespace CamelotFramework 
 namespace CamelotFramework 
 {
 {
@@ -77,6 +78,8 @@ namespace CamelotFramework
 
 
 	void RenderWindow::destroy()
 	void RenderWindow::destroy()
 	{
 	{
+		Platform::resetNonClientAreas(*this);
+
 		RenderWindowManager::instance().windowDestroyed(this);
 		RenderWindowManager::instance().windowDestroyed(this);
 
 
 		RenderTarget::destroy();
 		RenderTarget::destroy();

+ 28 - 0
CamelotCore/Source/Win32/CmPlatformImpl.cpp

@@ -15,6 +15,10 @@ namespace CamelotFramework
 	boost::signal<void(RenderWindow*)> Platform::onWindowMovedOrResized;
 	boost::signal<void(RenderWindow*)> Platform::onWindowMovedOrResized;
 	boost::signal<void()> Platform::onMouseCaptureChanged;
 	boost::signal<void()> Platform::onMouseCaptureChanged;
 
 
+	Map<const RenderWindow*, WindowNonClientAreaData>::type Platform::mNonClientAreas;
+
+	CM_STATIC_MUTEX_CLASS_INSTANCE(mSync, Platform);
+
 	struct NativeCursorData::Pimpl
 	struct NativeCursorData::Pimpl
 	{
 	{
 		HCURSOR cursor;
 		HCURSOR cursor;
@@ -243,6 +247,30 @@ namespace CamelotFramework
 		PostMessage(hwnd, WM_SETCURSOR, WPARAM(hwnd), (LPARAM)MAKELONG(HTCLIENT, WM_MOUSEMOVE));
 		PostMessage(hwnd, WM_SETCURSOR, WPARAM(hwnd), (LPARAM)MAKELONG(HTCLIENT, WM_MOUSEMOVE));
 	}
 	}
 
 
+	void Platform::setCaptionNonClientAreas(const RenderWindow& window, const Vector<Rect>::type& nonClientAreas)
+	{
+		CM_LOCK_MUTEX(mSync);
+
+		mNonClientAreas[&window].moveAreas = nonClientAreas;
+	}
+
+	void Platform::setResizeNonClientAreas(const RenderWindow& window, const Vector<NonClientResizeArea>::type& nonClientAreas)
+	{
+		CM_LOCK_MUTEX(mSync);
+
+		mNonClientAreas[&window].resizeAreas = nonClientAreas;
+	}
+
+	void Platform::resetNonClientAreas(const RenderWindow& window)
+	{
+		CM_LOCK_MUTEX(mSync);
+
+		auto iterFind = mNonClientAreas.find(&window);
+
+		if(iterFind != end(mNonClientAreas))
+			mNonClientAreas.erase(iterFind);
+	}
+
 	void Platform::messagePump()
 	void Platform::messagePump()
 	{
 	{
 		MSG  msg;
 		MSG  msg;

+ 0 - 6
CamelotD3D11RenderSystem/Include/CmD3D11RenderWindow.h

@@ -75,12 +75,6 @@ namespace CamelotFramework
 		 */
 		 */
 		bool requiresTextureFlipping() const { return false; }
 		bool requiresTextureFlipping() const { return false; }
 
 
-		void startResize(WindowResizeDirection direction);
-		void endResize();
-
-		void startMove();
-		void endMove();
-
 		void _windowMovedOrResized();
 		void _windowMovedOrResized();
 
 
 		DXGI_SWAP_CHAIN_DESC* _getPresentationParameters(void) { return &mSwapChainDesc; }
 		DXGI_SWAP_CHAIN_DESC* _getPresentationParameters(void) { return &mSwapChainDesc; }

+ 0 - 64
CamelotD3D11RenderSystem/Source/CmD3D11RenderWindow.cpp

@@ -13,11 +13,6 @@
 
 
 namespace CamelotFramework
 namespace CamelotFramework
 {
 {
-	void HACK_SendLMBUpEvent()
-	{
-		gInput().simulateButtonUp(BC_MOUSE_LEFT);
-	}
-
 	D3D11RenderWindow::D3D11RenderWindow(const RENDER_WINDOW_DESC& desc,D3D11Device& device, IDXGIFactory* DXGIFactory)
 	D3D11RenderWindow::D3D11RenderWindow(const RENDER_WINDOW_DESC& desc,D3D11Device& device, IDXGIFactory* DXGIFactory)
 		: RenderWindow(desc)
 		: RenderWindow(desc)
 		, mDevice(device)
 		, mDevice(device)
@@ -551,65 +546,6 @@ namespace CamelotFramework
 		return Int2(pos.x, pos.y);
 		return Int2(pos.x, pos.y);
 	}
 	}
 
 
-
-	void D3D11RenderWindow::startResize(WindowResizeDirection direction)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		WPARAM dir = HTLEFT;
-		switch(direction)
-		{
-		case WindowResizeDirection::Left:
-			dir = HTLEFT;
-			break;
-		case WindowResizeDirection::TopLeft:
-			dir = HTTOPLEFT;
-			break;
-		case WindowResizeDirection::Top:
-			dir = HTTOP;
-			break;
-		case WindowResizeDirection::TopRight:
-			dir = HTTOPRIGHT;
-			break;
-		case WindowResizeDirection::Right:
-			dir = HTRIGHT;
-			break;
-		case WindowResizeDirection::BottomRight:
-			dir = HTBOTTOMRIGHT;
-			break;
-		case WindowResizeDirection::Bottom:
-			dir = HTBOTTOM;
-			break;
-		case WindowResizeDirection::BottomLeft:
-			dir = HTBOTTOMLEFT;
-			break;
-		}
-
-		SendMessage(mHWnd, WM_SYSCOMMAND, SC_SIZE + 8, 0 );
-		//SetCapture(mHWnd);
-		//SendMessage(mHWnd, WM_NCLBUTTONDOWN, dir, 0);
-		HACK_SendLMBUpEvent();
-		//ReleaseCapture();
-	}
-
-	void D3D11RenderWindow::endResize()
-	{
-
-	}
-
-	void D3D11RenderWindow::startMove()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		SendMessage(mHWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
-		HACK_SendLMBUpEvent();
-	}
-
-	void D3D11RenderWindow::endMove()
-	{
-
-	}
-
 	void D3D11RenderWindow::_windowMovedOrResized()
 	void D3D11RenderWindow::_windowMovedOrResized()
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;

+ 0 - 6
CamelotD3D9Renderer/Include/CmD3D9RenderWindow.h

@@ -108,12 +108,6 @@ namespace CamelotFramework
 		 */
 		 */
 		Int2 windowToScreenPos(const Int2& windowPos) const;
 		Int2 windowToScreenPos(const Int2& windowPos) const;
 
 
-		void startResize(WindowResizeDirection direction);
-		void endResize();
-
-		void startMove();
-		void endMove();
-
 		/**
 		/**
 		 * @copydoc RenderWindow::_windowMovedOrResized
 		 * @copydoc RenderWindow::_windowMovedOrResized
 		 */
 		 */

+ 0 - 65
CamelotD3D9Renderer/Source/CmD3D9RenderWindow.cpp

@@ -38,16 +38,6 @@ THE SOFTWARE.
 
 
 namespace CamelotFramework
 namespace CamelotFramework
 {
 {
-	// HACK: During the move/resize modal loop no mouse messages will be posted, which means we will
-	// never receive a "mouse up" event, even though user had to release the mouse to stop the loop. But our GUI system
-	// relies on mouse down being followed by mouse up otherwise things end start to break a bit. So here we simulate 
-	// the mouse release. 
-	// Note: This is possible because SendMessage won't return until user releases the mouse and modal loop is done.
-	void HACK_SendLMBUpEvent()
-	{
-		gInput().simulateButtonUp(BC_MOUSE_LEFT);
-	}
-
 	D3D9RenderWindow::D3D9RenderWindow(const RENDER_WINDOW_DESC& desc, HINSTANCE instance)
 	D3D9RenderWindow::D3D9RenderWindow(const RENDER_WINDOW_DESC& desc, HINSTANCE instance)
         : RenderWindow(desc), mInstance(instance), mIsDepthBuffered(true)  
         : RenderWindow(desc), mInstance(instance), mIsDepthBuffered(true)  
 	{
 	{
@@ -497,61 +487,6 @@ namespace CamelotFramework
 		mDevice->copyContentsToMemory(this, dst, buffer);
 		mDevice->copyContentsToMemory(this, dst, buffer);
 	}
 	}
 
 
-	void D3D9RenderWindow::startResize(WindowResizeDirection direction)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		WPARAM dir = HTLEFT;
-		switch(direction)
-		{
-		case WindowResizeDirection::Left:
-			dir = HTLEFT;
-			break;
-		case WindowResizeDirection::TopLeft:
-			dir = HTTOPLEFT;
-			break;
-		case WindowResizeDirection::Top:
-			dir = HTTOP;
-			break;
-		case WindowResizeDirection::TopRight:
-			dir = HTTOPRIGHT;
-			break;
-		case WindowResizeDirection::Right:
-			dir = HTRIGHT;
-			break;
-		case WindowResizeDirection::BottomRight:
-			dir = HTBOTTOMRIGHT;
-			break;
-		case WindowResizeDirection::Bottom:
-			dir = HTBOTTOM;
-			break;
-		case WindowResizeDirection::BottomLeft:
-			dir = HTBOTTOMLEFT;
-			break;
-		}
-
-		SendMessage(mHWnd, WM_NCLBUTTONDOWN, dir, 0);
-		HACK_SendLMBUpEvent();
-	}
-
-	void D3D9RenderWindow::endResize()
-	{
-
-	}
-
-	void D3D9RenderWindow::startMove()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		SendMessage(mHWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
-		HACK_SendLMBUpEvent();
-	}
-
-	void D3D9RenderWindow::endMove()
-	{
-
-	}
-
 	void D3D9RenderWindow::_windowMovedOrResized()
 	void D3D9RenderWindow::_windowMovedOrResized()
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;

+ 0 - 6
CamelotGLRenderer/Include/CmWin32Window.h

@@ -113,12 +113,6 @@ namespace CamelotFramework
 		 */
 		 */
 		void _windowMovedOrResized(void);
 		void _windowMovedOrResized(void);
 
 
-		void startResize(WindowResizeDirection direction);
-		void endResize();
-
-		void startMove();
-		void endMove();
-
 		HWND _getWindowHandle() const { return mHWnd; }
 		HWND _getWindowHandle() const { return mHWnd; }
 		HDC _getHDC() const { return mHDC; }
 		HDC _getHDC() const { return mHDC; }
 		
 		

+ 0 - 65
CamelotGLRenderer/Source/CmWin32Window.cpp

@@ -41,16 +41,6 @@ THE SOFTWARE.
 
 
 namespace CamelotFramework 
 namespace CamelotFramework 
 {
 {
-	// HACK: During the move/resize modal loop no mouse messages will be posted, which means we will
-	// never receive a "mouse up" event, even though user had to release the mouse to stop the loop. But our GUI system
-	// relies on mouse down being followed by mouse up otherwise things end start to break a bit. So here we simulate 
-	// the mouse release. 
-	// Note: This is possible because SendMessage won't return until user releases the mouse and modal loop is done.
-	void HACK_SendLMBUpEvent()
-	{
-		gInput().simulateButtonUp(BC_MOUSE_LEFT);
-	}
-
 	#define _MAX_CLASS_NAME_ 128
 	#define _MAX_CLASS_NAME_ 128
 
 
 	Win32Window::Win32Window(const RENDER_WINDOW_DESC& desc, Win32GLSupport &glsupport):
 	Win32Window::Win32Window(const RENDER_WINDOW_DESC& desc, Win32GLSupport &glsupport):
@@ -745,61 +735,6 @@ namespace CamelotFramework
 		}
 		}
 	}
 	}
 
 
-	void Win32Window::startResize(WindowResizeDirection direction)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		WPARAM dir = HTLEFT;
-		switch(direction)
-		{
-		case WindowResizeDirection::Left:
-			dir = HTLEFT;
-			break;
-		case WindowResizeDirection::TopLeft:
-			dir = HTTOPLEFT;
-			break;
-		case WindowResizeDirection::Top:
-			dir = HTTOP;
-			break;
-		case WindowResizeDirection::TopRight:
-			dir = HTTOPRIGHT;
-			break;
-		case WindowResizeDirection::Right:
-			dir = HTRIGHT;
-			break;
-		case WindowResizeDirection::BottomRight:
-			dir = HTBOTTOMRIGHT;
-			break;
-		case WindowResizeDirection::Bottom:
-			dir = HTBOTTOM;
-			break;
-		case WindowResizeDirection::BottomLeft:
-			dir = HTBOTTOMLEFT;
-			break;
-		}
-
-		SendMessage(mHWnd, WM_NCLBUTTONDOWN, dir, 0);
-		HACK_SendLMBUpEvent();
-	}
-
-	void Win32Window::endResize()
-	{
-
-	}
-
-	void Win32Window::startMove()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		SendMessage(mHWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
-		HACK_SendLMBUpEvent();
-	}
-
-	void Win32Window::endMove()
-	{
-
-	}
-
 	void Win32Window::_windowMovedOrResized()
 	void Win32Window::_windowMovedOrResized()
 	{
 	{
 		if (!mHWnd || IsIconic(mHWnd))
 		if (!mHWnd || IsIconic(mHWnd))

+ 10 - 28
EditorWindowDock.txt

@@ -1,44 +1,26 @@
 Add icons to drag and drop - There's a built-in windows icon for this. I think. Although solution that accepts custom cursors is probably better longterm. (Special class BuiltinCursors?)
 Add icons to drag and drop - There's a built-in windows icon for this. I think. Although solution that accepts custom cursors is probably better longterm. (Special class BuiltinCursors?)
+ - Drag and drop manager currently ignores the provided icon, but it should use it as a cursor
 
 
-end drag doesn't get called unless mouse is released over a window
- - Capture mouse on start drag (SetCapture, and release with ReleaseCapture)
- - End drag should be handled by GUIManager, but if it doesn't process it DragAndDrop manager should check if mouse was released, and
-   release capture and activate end drag callback
+Fix an issue where drag and dropping a window for the second times causes an exception
 
 
 Add highlight to WindowMover so I can know when I'm mousing over it with a dragged window in hand
 Add highlight to WindowMover so I can know when I'm mousing over it with a dragged window in hand
+Ensure that dropping a window onto a mover will actually dock it properly
 
 
-Reopening the window I can see the update takes a few frames. This shouldn't be the case.
+Change WindowMover to GUIToggle since move functionality has been removed from it.
 
 
-Drag and drop manager currently ignores the provided icon, but it should use it as a cursor
+Actually set up client areas for resize and move
+ - Figure out how to deal with Cursor change in WindowFrame and non-client areas (which will likely be done in a parent class)
+   - Possibly add two different types of client areas, for move and resize. Then I can keep resize in WindowFrame and keep move in TitleBar.
+
+Get rid of the GUIManager mouseUp hack when I ensure resize/move using non client areas work
 
 
 Prevent docking if available size is less than 20 pixels, otherwise there might be some weirdness
 Prevent docking if available size is less than 20 pixels, otherwise there might be some weirdness
 
 
 GUIViewport:
 GUIViewport:
- - MAJOR TODO - GUIViewport updateRenderElementsInternal only gets called when contents change, but viewport should update even if 
+ - TODO - GUIViewport updateRenderElementsInternal only gets called when contents change, but viewport should update even if 
     only its offset changes (normally that just marks the mesh as modified, which doesn't result in a call to updateRenderElementsInternal)
     only its offset changes (normally that just marks the mesh as modified, which doesn't result in a call to updateRenderElementsInternal)
 	- UPDATE: I don't use GUIViewport anymore
 	- UPDATE: I don't use GUIViewport anymore
 
 
-------------------------
-
-Get rid of resize hacks:
- - 	In CmWin32Window (and probably same for DX9 and DX11)
-	// HACK: During the move/resize modal loop no mouse messages will be posted, which means we will
-	// never receive a "mouse up" event, even though user had to release the mouse to stop the loop. But our GUI system
-	// relies on mouse down being followed by mouse up otherwise things end start to break a bit. So here we simulate 
-	// the mouse release. 
-	// Note: This is possible because SendMessage won't return until user releases the mouse and modal loop is done.
-	void HACK_SendLMBUpEvent()
-	{
-		gInput().simulateButtonUp(BC_MOUSE_LEFT);
-	}
- - Hack from GUIManager (related to resize and mouse up event)
-
-Also try to get rid of start/end move/resize
-
-Calling Set/Release capture on sim thread probably wont work. Create custom, and send messages instead
-Add Platform::onMouseCaptureLost
-
-
 ------------------------
 ------------------------
 
 
 Other things to remember:
 Other things to remember:

+ 0 - 2
TODO.txt

@@ -6,8 +6,6 @@ MAJOR ISSUE: writeSubresource/readSubresoure doesn't require a shared ptr to Gpu
   - When fixed, make sure I remove blocking calls after writeSubresource where they're not needed (GUIManager for example)
   - When fixed, make sure I remove blocking calls after writeSubresource where they're not needed (GUIManager for example)
 I call waitUntilLoaded too many times. Sometimes 5-6 times in a single function. Each of those calls will be extremely slow.
 I call waitUntilLoaded too many times. Sometimes 5-6 times in a single function. Each of those calls will be extremely slow.
 GUIWidget::updateMeshes leaks. If I leave the game running I can see memory continously going up
 GUIWidget::updateMeshes leaks. If I leave the game running I can see memory continously going up
- - Resizing from the top doesn't work
- - Resizing from the left actually resizes the right side
  - BansheeApplication should probably derive from Camlelot application. Right now user needs to know the difference between 
  - BansheeApplication should probably derive from Camlelot application. Right now user needs to know the difference between 
    gApplication and gBansheeApp, which is non-intuitive (e.g. retrieving a window can be done on gApplication, but running main loop can happen on both
    gApplication and gBansheeApp, which is non-intuitive (e.g. retrieving a window can be done on gApplication, but running main loop can happen on both