#319 OS cursor support 4.x-dev

Mon, 17 May 2021 20:56:17 +0300

author
cemkalyoncu
date
Mon, 17 May 2021 20:56:17 +0300
branch
4.x-dev
changeset 1679
ba8492d69168
parent 1678
ca3c4cddb613
child 1680
7bf7ffcbda96

#319 OS cursor support

Source/Gorgon/Graphics/Pointer.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/Graphics/Pointer.h file | annotate | diff | comparison | revisions
Source/Gorgon/Resource/Pointer.h file | annotate | diff | comparison | revisions
Source/Gorgon/Window.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/Window.h file | annotate | diff | comparison | revisions
Source/Gorgon/WindowManager.h file | annotate | diff | comparison | revisions
Source/Gorgon/WindowManager/DWM/DWM.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/WindowManager/DWM/Window.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/WindowManager/X11/Window.cpp file | annotate | diff | comparison | revisions
Testing/Source/Manual/Window.cpp file | annotate | diff | comparison | revisions
--- a/Source/Gorgon/Graphics/Pointer.cpp	Sat May 15 20:18:29 2021 +0200
+++ b/Source/Gorgon/Graphics/Pointer.cpp	Mon May 17 20:56:17 2021 +0300
@@ -20,32 +20,47 @@
     
     void PointerStack::Add(PointerType type, const Drawable &image, Geometry::Point hotspot) {
         auto ptr = new DrawablePointer(image, hotspot);
+        ptr->SetType(type);
         
         Add(type, *ptr);
         pointers[(int)type].owned = true;
     }
 
     PointerStack::Token PointerStack::Set(PointerType type) {
-        ASSERT((int)type>(int)PointerType::None && (int)type<=(int)PointerType::Drag, "Invalid pointer type");
+        ASSERT((int)type>(int)PointerType::None && (int)type<(int)PointerType::Max, "Invalid pointer type");
        
         if(!pointers[(int)type].ptr) return Token();
         
         stack.Add(lastind, pointers[(int)type].ptr);
         
+        PointerChanged();
+        
         return Token(this, lastind++);
     }
     
     PointerStack::Token PointerStack::Set(const Pointer &pointer) {
         stack.Add(lastind, pointer);
         
+        PointerChanged();
+        
         return Token(this, lastind++);
     }
     
     void PointerStack::Reset(Token &token) {
         if(token.parent != this) return;
         
+        long curid = -1;
+        
+        if(stack.GetSize() > 0) {
+            curid = stack.Last().Current().first;
+        }
+        
         stack.Remove(token.ind);
         
+        if(stack.GetSize() == 0 || stack.Last().Current().first != curid) {
+            PointerChanged();
+        }
+        
         token.parent = nullptr;
         token.ind = 0;
     }
@@ -55,7 +70,7 @@
             return stack.Last().Current().second;
         }
         else {
-            for(int i=(int)PointerType::Arrow; i<=(int)PointerType::Drag; i++) {
+            for(int i=(int)PointerType::Arrow; i<(int)PointerType::Max; i++) {
                 if(pointers[i].ptr)
                     return *pointers[i].ptr;
             }
@@ -69,7 +84,7 @@
             return true;
         }
         else {
-            for(int i=(int)PointerType::Arrow; i<=(int)PointerType::Drag; i++) {
+            for(int i=(int)PointerType::Arrow; i<(int)PointerType::Max; i++) {
                 if(pointers[i].ptr)
                     return true;
             }
@@ -78,4 +93,13 @@
         return false;
     }
     
+    PointerType PointerStack::GetCurrentType() const {
+        if(IsValid()) {
+            return Current().GetType();
+        }
+        else {
+            return PointerType::None;
+        }
+    }
+    
 } }
--- a/Source/Gorgon/Graphics/Pointer.h	Sat May 15 20:18:29 2021 +0200
+++ b/Source/Gorgon/Graphics/Pointer.h	Mon May 17 20:56:17 2021 +0300
@@ -10,249 +10,349 @@
 
 namespace Gorgon { namespace Graphics {
 
+    ///Pointer types
+    enum class PointerType {
+        ///No pointer is selected or using default. Do not use this value
+        None,
+        
+        ///Arrow / Pointer
+        Arrow,
+        
+        ///Wait / Hourglass
+        Wait,
+        
+        ///Processing, pointer and wait combined
+        Processing,
+        
+        ///No / Not allowed
+        No,
+        
+        ///Text / Beam pointer
+        Text,
+        
+        ///A pointer for links
+        Link,
+        
+        ///Cursor icon that offers to move an item
+        Move,
+        
+        ///Drag / Closed hand pointer
+        Drag,
+        
+        ///Scaling from left side
+        ScaleLeft,
+        
+        ///Scaling from the right side
+        ScaleRight,
+        
+        ///Scaling from top side
+        ScaleTop,
+        
+        ///Scaling from bottom side
+        ScaleBottom,
+        
+        ///Scaling from top left corner
+        ScaleTopLeft,
+        
+        ///Scaling from top right corner
+        ScaleTopRight,
+        
+        ///Scaling from bottom left corner
+        ScaleBottomLeft,
+        
+        ///Scaling from bottom right corner
+        ScaleBottomRight,
+        
+        ///Cross hair to select a point
+        Cross,
+        
+        /// A cursor denotes a help text
+        Help,
+        
+        ///Straight upward pointing arrow, can be used for alternative objects
+        Straight,
+        
+        ///Do not use this value
+        Max
+    };
+        
     /**
-     * Represents a pointer. When drawn, pointer should move the image so that the hotspot
-     * will be on the given point. If desired, ownership of the image can be transferred
-     * to the pointer.
-     */
-	class Pointer : virtual public Drawable {
-	public:
+    * Represents a pointer. When drawn, pointer should move the image so that the hotspot
+    * will be on the given point. If desired, ownership of the image can be transferred
+    * to the pointer.
+    */
+    class Pointer : virtual public Drawable {
+    public:
 
-		virtual ~Pointer() {
-		}
+        virtual ~Pointer() {
+        }
+        
+        /// Returns the type of the pointer
+        PointerType GetType() const {
+            return type;
+        }
+        
+        /// Sets the type of the pointer. Pointer type can be used to determine the type while 
+        /// adding to the stack. If operating system pointers are used, this value is used determine
+        /// which pointer to show.
+        void SetType(PointerType value) {
+            type = value;
+        }
         
     protected:
-	};
+        PointerType type = PointerType::Arrow;
+    };
+
+    /// This class turns a drawable into a pointer
+    class DrawablePointer : public Pointer {
+    public:
+        DrawablePointer() = default;
 
-	/// This class turns a drawable into a pointer
-	class DrawablePointer : public Pointer {
-	public:
-		DrawablePointer() = default;
-
-		/// Initializes a pointer. Ownership of the drawable is not transferred. Use Assume function 
-		/// after invoking default constructor to transfer ownership.
-		DrawablePointer(const Drawable &image, int x, int y) : DrawablePointer(image, {x, y}) {}
+        /// Initializes a pointer. Ownership of the drawable is not transferred. Use Assume function 
+        /// after invoking default constructor to transfer ownership.
+        DrawablePointer(const Drawable &image, int x, int y, PointerType type = PointerType::Arrow) : 
+            DrawablePointer(image, {x, y}) 
+        {
+            SetType(type);
+        }
 
-		/// Initializes a pointer. Ownership of the drawable is not transferred. Use Assume function 
-		/// after invoking default constructor to transfer ownership.
-		DrawablePointer(const Drawable &image, Geometry::Point hotspot) :
-			image(&image), hotspot(hotspot) {}
+        /// Initializes a pointer. Ownership of the drawable is not transferred. Use Assume function 
+        /// after invoking default constructor to transfer ownership.
+        DrawablePointer(const Drawable &image, Geometry::Point hotspot, PointerType type = PointerType::Arrow) :
+            image(&image), hotspot(hotspot) 
+        {
+            SetType(type);
+        }
 
-		/// Initializes a pointer. Ownership of the drawable is not transferred. Use Assume function 
-		/// after invoking default constructor to transfer ownership.
-		DrawablePointer(const AssumeOwnershipTag &tag, const Drawable &image, int x, int y) : DrawablePointer(tag, image, {x, y}) {}
-
-		/// Initializes a pointer. Ownership of the drawable is not transferred. Use Assume function 
-		/// after invoking default constructor to transfer ownership.
-		DrawablePointer(const AssumeOwnershipTag &, const Drawable &image, Geometry::Point hotspot) :
-			image(&image), hotspot(hotspot) { owner = true; }
+        /// Initializes a pointer. Ownership of the drawable is not transferred. Use Assume function 
+        /// after invoking default constructor to transfer ownership.
+        DrawablePointer(const AssumeOwnershipTag &tag, const Drawable &image, int x, int y, PointerType type = PointerType::Arrow) : 
+            DrawablePointer(tag, image, {x, y}) 
+        {
+            SetType(type);
+        }
 
-		DrawablePointer(const DrawablePointer &other) = delete;
+        /// Initializes a pointer. Ownership of the drawable is not transferred. Use Assume function 
+        /// after invoking default constructor to transfer ownership.
+        DrawablePointer(const AssumeOwnershipTag &, const Drawable &image, Geometry::Point hotspot, PointerType type = PointerType::Arrow) :
+            image(&image), hotspot(hotspot) 
+        { 
+            owner = true; 
+            SetType(type);
+        }
 
-		DrawablePointer(DrawablePointer &&other) :
-			image(other.image), hotspot(other.hotspot), owner(other.owner) {
-			other.image = nullptr;
-			other.owner = false;
-		}
+        DrawablePointer(const DrawablePointer &other) = delete;
 
-		DrawablePointer &operator =(const DrawablePointer &) = delete;
+        DrawablePointer(DrawablePointer &&other) :
+            image(other.image), hotspot(other.hotspot), owner(other.owner) {
+            other.image = nullptr;
+            other.owner = false;
+        }
+
+        DrawablePointer &operator =(const DrawablePointer &) = delete;
 
-		DrawablePointer &operator =(DrawablePointer &&other) {
-			RemoveImage();
-			image   = other.image;
-			owner   = other.owner;
-			hotspot = other.hotspot;
-
-			other.image = nullptr;
-			other.owner = false;
+        DrawablePointer &operator =(DrawablePointer &&other) {
+            RemoveImage();
+            image   = other.image;
+            owner   = other.owner;
+            hotspot = other.hotspot;
+            type    = other.type;
 
-			return *this;
-		}
+            other.image = nullptr;
+            other.owner = false;
+
+            return *this;
+        }
 
-		//Pointer(Resource::Pointer &pointer);
+        //Pointer(Resource::Pointer &pointer);
 
-		~DrawablePointer() {
-			RemoveImage();
-		}
+        ~DrawablePointer() {
+            RemoveImage();
+        }
 
 
-		/// Returns if the pointer has an image
-		bool HasImage() const {
-			return image != nullptr;
-		}
+        /// Returns if the pointer has an image
+        bool HasImage() const {
+            return image != nullptr;
+        }
 
-		/// Returns the image contained in this pointer. You should check HasImage
-		/// before accessing to the image
-		const Drawable &GetImage() const {
-			ASSERT(image, "Pointer image is not set");
+        /// Returns the image contained in this pointer. You should check HasImage
+        /// before accessing to the image
+        const Drawable &GetImage() const {
+            ASSERT(image, "Pointer image is not set");
 
-			return *image;
-		}
+            return *image;
+        }
 
-		/// Changes the image of this pointer 
-		void SetImage(const Drawable &value) {
-			RemoveImage();
+        /// Changes the image of this pointer 
+        void SetImage(const Drawable &value) {
+            RemoveImage();
 
-			image = &value;
-		}
+            image = &value;
+        }
 
-		/// Changes the image of the pointer by assuming the ownership of the given
-		/// image
-		void Assume(const Drawable &value) {
-			RemoveImage();
+        /// Changes the image of the pointer by assuming the ownership of the given
+        /// image
+        void Assume(const Drawable &value) {
+            RemoveImage();
 
-			image = &value;
-			owner = true;
-		}
+            image = &value;
+            owner = true;
+        }
 
-		/// Changes the image of the pointer by assuming the ownership of the given
-		/// image
-		void Assume(const Drawable &value, Geometry::Point hotspot) {
-			RemoveImage();
+        /// Changes the image of the pointer by assuming the ownership of the given
+        /// image
+        void Assume(const Drawable &value, Geometry::Point hotspot) {
+            RemoveImage();
 
-			image = &value;
-			owner = true;
-			this->hotspot = hotspot;
-		}
+            image = &value;
+            owner = true;
+            this->hotspot = hotspot;
+        }
 
-		/// Changes the image of the pointer by assuming the ownership of the given
-		/// image
-		void Assume(const Drawable &value, int x, int y) {
-			RemoveImage();
+        /// Changes the image of the pointer by assuming the ownership of the given
+        /// image
+        void Assume(const Drawable &value, int x, int y) {
+            RemoveImage();
 
-			image = &value;
-			owner = true;
-			this->hotspot = {x, y};
-		}
+            image = &value;
+            owner = true;
+            this->hotspot = {x, y};
+        }
 
-		/// Removes the image from the pointer
-		void RemoveImage() {
-			if(owner) {
-				delete image;
-				owner = false;
-			}
+        /// Removes the image from the pointer
+        void RemoveImage() {
+            if(owner) {
+                delete image;
+                owner = false;
+            }
 
-			image = nullptr;
-		}
+            image = nullptr;
+        }
 
-		/// Releases the ownership of the drawable and removes it from the pointer
-		const Drawable &Release() {
-			auto img = image;
+        /// Releases the ownership of the drawable and removes it from the pointer
+        const Drawable &Release() {
+            auto img = image;
 
-			owner = false;
-			image = nullptr;
+            owner = false;
+            image = nullptr;
 
-			return *img;
-		}
+            return *img;
+        }
 
 
-	protected:
-		void draw(Gorgon::Graphics::TextureTarget &target, const Geometry::Pointf &p, Gorgon::Graphics::RGBAf color) const override {
-			if(!image) return;
+    protected:
+        void draw(Gorgon::Graphics::TextureTarget &target, const Geometry::Pointf &p, Gorgon::Graphics::RGBAf color) const override {
+            if(!image) return;
 
-			image->Draw(target, p-hotspot, color);
-		}
+            image->Draw(target, p-hotspot, color);
+        }
 
-	private:
-		const Drawable *image = nullptr;
-		Geometry::Point hotspot ={0, 0};
+    private:
+        const Drawable *image = nullptr;
+        Geometry::Point hotspot ={0, 0};
 
-		bool owner = false;
-	};
+        bool owner = false;
+    };
+
+    template<class A_>
+    class basic_PointerProvider;
 
-	template<class A_>
-	class basic_PointerProvider;
+    /// Represents animated pointer.
+    template<class A_>
+    class basic_AnimatedPointer : public virtual Pointer, public virtual A_::AnimationType {
+    public:
+        basic_AnimatedPointer(const basic_PointerProvider<A_> &parent, typename A_::AnimationType &anim) :
+            A_::AnimationType(parent, false), anim(&anim), parent(parent)
+        { 
+            SetType(parent.GetType());
+        }
 
-	/// Represents animated pointer.
-	template<class A_>
-	class basic_AnimatedPointer : public virtual Pointer, public virtual A_::AnimationType {
-	public:
-		basic_AnimatedPointer(const basic_PointerProvider<A_> &parent, typename A_::AnimationType &anim) :
-			A_::AnimationType(parent, false), anim(&anim), parent(parent)
-		{ }
+        basic_AnimatedPointer(const basic_AnimatedPointer &) = delete;
 
-		basic_AnimatedPointer(const basic_AnimatedPointer &) = delete;
-
-		basic_AnimatedPointer(basic_AnimatedPointer &&other) : A_::AnimationType(other.parent, false), anim(other.anim), parent(other.parent) {
-			other.anim = nullptr;
-		}
+        basic_AnimatedPointer(basic_AnimatedPointer &&other) : A_::AnimationType(other.parent, false), anim(other.anim), parent(other.parent) {
+            SetType(other.GetType());
+            other.anim = nullptr;
+        }
 
-		~basic_AnimatedPointer() {
-			if(anim)
-				anim->DeleteAnimation();
-		}
+        ~basic_AnimatedPointer() {
+            if(anim)
+                anim->DeleteAnimation();
+        }
 
-		void SetController(Gorgon::Animation::ControllerBase &controller) override {
-			ASSERT(anim, "Trying to use a moved out pointer");
+        void SetController(Gorgon::Animation::ControllerBase &controller) override {
+            ASSERT(anim, "Trying to use a moved out pointer");
 
-			anim->SetController(controller);
-		}
-		
-		bool HasController() const override {
-			ASSERT(anim, "Trying to use a moved out pointer");
+            anim->SetController(controller);
+        }
+        
+        bool HasController() const override {
+            ASSERT(anim, "Trying to use a moved out pointer");
 
-			return anim->HasController();
-		}
+            return anim->HasController();
+        }
 
-		Gorgon::Animation::ControllerBase &GetController() const {
-			ASSERT(anim, "Trying to use a moved out pointer");
+        Gorgon::Animation::ControllerBase &GetController() const override {
+            ASSERT(anim, "Trying to use a moved out pointer");
 
-			return anim->GetController();
-		}
+            return anim->GetController();
+        }
 
-		void RemoveController() const {
-			ASSERT(anim, "Trying to use a moved out pointer");
+        void RemoveController() override {
+            ASSERT(anim, "Trying to use a moved out pointer");
 
-			anim->RemoveController();
-		}
+            anim->RemoveController();
+        }
 
-	protected:
-		void draw(Gorgon::Graphics::TextureTarget &target, const Geometry::Pointf &p, Gorgon::Graphics::RGBAf color) const override;
+    protected:
+        using A_::AnimationType::draw;
+        
+        void draw(Gorgon::Graphics::TextureTarget &target, const Geometry::Pointf &p, Gorgon::Graphics::RGBAf color) const override;
 
-		const basic_PointerProvider<A_> &parent;
-		typename A_::AnimationType *anim;
-	};
+        typename A_::AnimationType *anim;
+        const basic_PointerProvider<A_> &parent;
+    };
     
     /// This class stores information that allows an animated pointer to be created.
-	template<class A_>
+    template<class A_>
     class basic_PointerProvider : public A_ {
     public:
-		using AnimationType = basic_AnimatedPointer<A_>;
+        using AnimationType = basic_AnimatedPointer<A_>;
 
-		explicit basic_PointerProvider(Geometry::Point hotspot = {0,0}) :
+        explicit basic_PointerProvider(Geometry::Point hotspot = {0,0}) :
         hotspot(hotspot) {
         }
         
         /// Move constructor
-		basic_PointerProvider(basic_PointerProvider &&other) :
+        basic_PointerProvider(basic_PointerProvider &&other) :
         hotspot(other.hotspot), owned(other.owned) {
             other.owned = false;
         }
         
-		basic_PointerProvider(const basic_PointerProvider &) = delete;
+        basic_PointerProvider(const basic_PointerProvider &) = delete;
         
         virtual ~basic_PointerProvider() {
         }
 
-		/// Creates a pointer from this provider
-		AnimationType CreatePointer(Gorgon::Animation::Timer &timer) const {
-			return AnimationType(*this, A_::CreateAnimation(timer));
-		}
+        /// Creates a pointer from this provider
+        AnimationType CreatePointer(Gorgon::Animation::Timer &timer) const {
+            return AnimationType(*this, A_::CreateAnimation(timer));
+        }
 
-		/// Creates a pointer from this provider, just a rename for CreateAnimation
-		AnimationType CreatePointer(bool create = true) const {
-			return AnimationType(*this, A_::CreateAnimation(create));
-		}
+        /// Creates a pointer from this provider, just a rename for CreateAnimation
+        AnimationType CreatePointer(bool create = true) const {
+            return AnimationType(*this, A_::CreateAnimation(create));
+        }
 
-		/// Creates a pointer from this provider
-		AnimationType &CreateAnimation(Gorgon::Animation::ControllerBase &timer) const override {
-			return *new basic_AnimatedPointer<A_>(*this, A_::CreateAnimation(timer));
-		}
+        /// Creates a pointer from this provider
+        AnimationType &CreateAnimation(Gorgon::Animation::ControllerBase &timer) const override {
+            return *new basic_AnimatedPointer<A_>(*this, A_::CreateAnimation(timer));
+        }
 
-		/// Creates a pointer from this provider
-		AnimationType &CreateAnimation(bool create = true) const override {
-			return *new basic_AnimatedPointer<A_>(*this, A_::CreateAnimation(create));
-		}
+        /// Creates a pointer from this provider
+        AnimationType &CreateAnimation(bool create = true) const override {
+            return *new basic_AnimatedPointer<A_>(*this, A_::CreateAnimation(create));
+        }
 
         /// Returns the hotspot of the provider
         Geometry::Point GetHotspot() const {
@@ -264,7 +364,21 @@
             hotspot = value;
         }
         
-    protected:        
+        /// Returns the type of the pointer
+        PointerType GetType() const {
+            return type;
+        }
+        
+        /// Sets the type of the pointer. Pointer type can be used to determine the type while 
+        /// adding to the stack. If operating system pointers are used, this value is used determine
+        /// which pointer to show.
+        void SetType(PointerType value) {
+            type = value;
+        }
+        
+    protected:
+        PointerType type = PointerType::Arrow;
+
         /// Hotspot will be transferred to newly created pointers
         Geometry::Point hotspot;
         
@@ -272,40 +386,16 @@
         bool owned;
     };
 
-	using PointerProvider = basic_PointerProvider<AnimationProvider>;
-	using BitmapPointerProvider = basic_PointerProvider<BitmapAnimationProvider>;
-	using ConstBitmapPointerProvider = basic_PointerProvider<ConstBitmapAnimationProvider>;
+    using PointerProvider = basic_PointerProvider<AnimationProvider>;
+    using BitmapPointerProvider = basic_PointerProvider<BitmapAnimationProvider>;
+    using ConstBitmapPointerProvider = basic_PointerProvider<ConstBitmapAnimationProvider>;
 
-    ///Pointer types
-    enum class PointerType {
-        ///No pointer is selected or using default
-        None=0,
-        
-        ///Arrow / Pointer
-        Arrow=1,
-        
-        ///Wait / Hourglass
-        Wait=2,
-        
-        ///No / Not allowed
-        No=3,
-        
-        ///Text / Beam pointer
-        Text=4,
-        
-        ///Hand pointer
-        Hand=5,
-        
-        ///Drag / Closed hand pointer
-        Drag=6
-    };
-        
 
     /**
-     * This class manages a pointer stack that allows multiple pointers to be
-     * registered and switched. These pointers are pushed to the stack and can
-     * be reset, setting the pointer to the previous state. 
-     */
+    * This class manages a pointer stack that allows multiple pointers to be
+    * registered and switched. These pointers are pushed to the stack and can
+    * be reset, setting the pointer to the previous state. 
+    */
     class PointerStack {
     public:
         
@@ -324,13 +414,11 @@
             }
             
             ~Token() {
-                if(parent)
-                    parent->Reset(*this);
+                Revert();
             }
             
             Token &operator =(Token &&tok) {
-                if(parent)
-                    parent->Reset(*this);
+                Revert();
                 
                 parent = tok.parent;
                 ind = tok.ind;
@@ -341,6 +429,14 @@
                 return *this;
             }
             
+            void Revert() {
+                if(parent)
+                    parent->Reset(*this);
+                
+                parent = nullptr;
+                ind = 0;
+            }
+            
             /// Checks if the token is null
             bool IsNull() const { return parent == nullptr; }
             
@@ -357,38 +453,41 @@
             int ind = 0;
         };
 
-		PointerStack() = default;
+        PointerStack() = default;
 
-		PointerStack(const PointerStack &) = delete;
+        PointerStack(const PointerStack &) = delete;
 
-		PointerStack(PointerStack &&other) {
-			Swap(other);
-		}
+        PointerStack(PointerStack &&other) {
+            Swap(other);
+        }
 
-		void Swap(PointerStack &other) {
-			using std::swap;
+        void Swap(PointerStack &other) {
+            using std::swap;
 
-			swap(lastind, other.lastind);
-			swap(stack, other.stack);
-			swap(pointers, other.pointers);
-		}
+            swap(lastind, other.lastind);
+            swap(stack, other.stack);
+            swap(pointers, other.pointers);
+        }
 
-		~PointerStack() {
-			for(auto &w : pointers) {
-				if(w.owned)
-					delete w.ptr;
-			}
-		}
+        ~PointerStack() {
+            for(auto &w : pointers) {
+                if(w.owned)
+                    delete w.ptr;
+            }
+        }
 
         /// Adds the given pointer to the stack. Ownership of the pointer will not
         /// be transferred. If the given pointer type exists old one will be overridden.
         /// If the old pointer is managed by this stack then it will be deleted.
-		void Add(PointerType type, const Pointer &pointer);
+        void Add(PointerType type, const Pointer &pointer);
 
-		/// Move variant that maps to assume
-		void Add(PointerType type, const Pointer &&pointer) {
-			Assume(type, pointer);
-		}
+        /// Adds the given pointer to the stack. Ownership of the pointer will not
+        /// be transferred. If the given pointer type exists old one will be overridden.
+        /// If the old pointer is managed by this stack then it will be deleted. Type that
+        /// is set in the pointer is used to refer to this pointer.
+        void Add(const Pointer &pointer) {
+            Add(pointer.GetType(), pointer);
+        }
 
         /// Adds the given pointer to the stack. Ownership of the pointer will be
         /// transferred. If the given pointer type exists old one will be overridden.
@@ -399,9 +498,9 @@
         /// bound to the life time of the stack. If the given pointer type exists
         /// old one will be overridden. If the old pointer is managed by this stack
         /// then it will be deleted.
-		void Add(PointerType type, const Drawable &image, Geometry::Point hotspot);
+        void Add(PointerType type, const Drawable &image, Geometry::Point hotspot);
 
-		void Add(PointerType type, const Drawable &&image, Geometry::Point hotspot) = delete;
+        void Add(PointerType type, const Drawable &&image, Geometry::Point hotspot) = delete;
 
         /// Checks if the given pointer exists
         bool Exists(PointerType type) {
@@ -410,10 +509,12 @@
             return pointers[(int)type].ptr != nullptr;
         }
         
+        PointerType GetCurrentType() const;
+        
         /// Set the current pointer to the given type. This would return a token to
         /// be used to reset this operation. The token should be stored in a variable
         /// otherwise the pointer would be reset immediately.
-		Token Set(PointerType type);
+        Token Set(PointerType type);
         
         /// Sets the current pointer in the stack to the given pointer. This pointer
         /// will not be added to the list. The token should be stored in a variable
@@ -433,6 +534,9 @@
         /// one registered or pushed pointer
         bool IsValid() const;
         
+        /// This event is fired if the pointer at the top is changed.
+        Event<PointerStack> PointerChanged = Event<PointerStack>{this};
+        
     private:
         struct Wrapper {
             const Pointer *ptr = nullptr;
@@ -443,15 +547,15 @@
         
         Containers::Hashmap<int, const Pointer> stack;
         
-        std::array<Wrapper, (int)PointerType::Drag+1> pointers = {};
+        std::array<Wrapper, (int)PointerType::Max> pointers = {};
     };
     
 
-	template<class A_>
-	void basic_AnimatedPointer<A_>::draw(Gorgon::Graphics::TextureTarget &target, const Geometry::Pointf &p, Gorgon::Graphics::RGBAf color) const {
-		ASSERT(anim, "Try to use a moved out pointer");
+    template<class A_>
+    void basic_AnimatedPointer<A_>::draw(Gorgon::Graphics::TextureTarget &target, const Geometry::Pointf &p, Gorgon::Graphics::RGBAf color) const {
+        ASSERT(anim, "Try to use a moved out pointer");
 
-		anim->Draw(target, p-parent.GetHotspot(), color);
-	}
+        anim->Draw(target, p-parent.GetHotspot(), color);
+    }
 
 } }
--- a/Source/Gorgon/Resource/Pointer.h	Sat May 15 20:18:29 2021 +0200
+++ b/Source/Gorgon/Resource/Pointer.h	Mon May 17 20:56:17 2021 +0300
@@ -25,18 +25,19 @@
     class Pointer : public AnimationStorage, public Graphics::BitmapPointerProvider {
     public:
         Pointer(Graphics::Bitmap &bmp, Geometry::Point hotspot, Graphics::PointerType type) : 
-        Graphics::BitmapPointerProvider(hotspot), type(type) {
+        Graphics::BitmapPointerProvider(hotspot) {
             Add(bmp);
+            SetType(type);
         }
 
         Pointer(Graphics::BitmapAnimationProvider &&anim, Geometry::Point hotspot, Graphics::PointerType type) :
-        Graphics::BitmapPointerProvider(hotspot), type(type) {
+        Graphics::BitmapPointerProvider(hotspot) {
             dynamic_cast<Graphics::BitmapAnimationProvider&>(*this) = std::move(anim);
+            SetType(type);
         }
         
-        explicit Pointer(Graphics::PointerType type = Graphics::PointerType::None) : 
-        type(type) { 
-            
+        explicit Pointer(Graphics::PointerType type = Graphics::PointerType::None) { 
+            SetType(type);
         }
         
         Pointer(const Pointer &) = delete;
@@ -45,16 +46,6 @@
         
         GID::Type GetGID() const override { return GID::Pointer; }
         
-        /// Returns the type of the pointer
-        Graphics::PointerType GetType() const {
-            return type;
-        }
-        
-        /// Sets the type of the pointer
-        void SetType(Graphics::PointerType value) {
-            type = value;
-        }
-        
         void Prepare() override;
         
         /// Moves the pointer provider out of resource system. Use Prepare and Discard before calling this function to
@@ -68,8 +59,6 @@
 		static Pointer *LoadLegacy(std::weak_ptr<File> file, std::shared_ptr<Reader> reader, unsigned long size) { Utils::NotImplemented(); }
         
     protected:
-        Graphics::PointerType type = Graphics::PointerType::Arrow;
-
 		virtual Graphics::RectangularAnimationStorage animmoveout() override;
 
         virtual ~Pointer() { }
--- a/Source/Gorgon/Window.cpp	Sat May 15 20:18:29 2021 +0200
+++ b/Source/Gorgon/Window.cpp	Mon May 17 20:56:17 2021 +0300
@@ -277,6 +277,8 @@
         
         pointerlayer = new Graphics::Layer;
         Layer::Add(*pointerlayer);
+        
+        Pointers.PointerChanged.Register(*this, &Window::UpdatePointer);
     }
 
     void Window::SetBackground(const Graphics::Bitmap &value) {
@@ -356,4 +358,7 @@
             over = MouseHandler{};
     }
 
+    void Window::UpdatePointer() {
+        WindowManager::SetPointer(*this, Pointers.GetCurrentType());
+    }
 }
--- a/Source/Gorgon/Window.h	Sat May 15 20:18:29 2021 +0200
+++ b/Source/Gorgon/Window.h	Mon May 17 20:56:17 2021 +0300
@@ -376,6 +376,9 @@
         using Layer::Remove;
         virtual void Remove(Layer &layer) override;
         
+        /// Updates current mouse pointer if OS pointer is shown. This is called automatically.
+        void UpdatePointer();
+        
         /// Returns the minimum size required to fit any window inside.
         static Geometry::Size GetMinimumRequiredSize();
         
--- a/Source/Gorgon/WindowManager.h	Sat May 15 20:18:29 2021 +0200
+++ b/Source/Gorgon/WindowManager.h	Mon May 17 20:56:17 2021 +0300
@@ -10,6 +10,8 @@
 #include "Event.h"
 #include "Containers/Image.h"
 #include "Resource/GID.h"
+#include "Graphics/Pointer.h"
+
 
 namespace Gorgon {
 	
@@ -228,5 +230,9 @@
 		/// Changes the clipboard to the given image. Depending on size of the image, this operation might not work 
 		/// on X11 for now.
 		void SetClipboardBitmap(Containers::Image img, bool append = false);
+        
+        /// Changes the OS pointer to the requested type. If target OS does not supported the requested
+        /// type, a similar pointer will be displayed.
+        void SetPointer(Window &wind, Graphics::PointerType type);
 	}
 }
--- a/Source/Gorgon/WindowManager/DWM/DWM.cpp	Sat May 15 20:18:29 2021 +0200
+++ b/Source/Gorgon/WindowManager/DWM/DWM.cpp	Mon May 17 20:56:17 2021 +0300
@@ -142,6 +142,5 @@
             
 			delete data;
 		}
-
 	}
 }
--- a/Source/Gorgon/WindowManager/DWM/Window.cpp	Sat May 15 20:18:29 2021 +0200
+++ b/Source/Gorgon/WindowManager/DWM/Window.cpp	Mon May 17 20:56:17 2021 +0300
@@ -546,4 +546,75 @@
 		}
 	}
 
-}
+namespace WindowManager {
+    
+    void SetPointer(Window &wind, Graphics::PointerType type) { 
+        HINSTANCE instance=GetModuleHandle(NULL);
+        LPCSTR cursor;
+        
+        switch(type) {
+        case Graphics::PointerType::Wait:
+            cursor = IDC_WAIT;
+            break;
+        case Graphics::PointerType::Processing:
+            cursor = IDC_APPSTARTING;
+            break;
+        case Graphics::PointerType::No:
+            cursor = IDC_NO;
+            break;
+        case Graphics::PointerType::Text:
+            cursor = IDC_IBEAM;
+            break;
+        case Graphics::PointerType::Link:
+            cursor = IDC_HAND;
+            break;
+        case Graphics::PointerType::Move:
+            cursor = IDC_HAND;
+            break;
+        case Graphics::PointerType::Drag:
+            cursor = IDC_SIZEALL;
+            break;
+        case Graphics::PointerType::ScaleLeft:
+            cursor = IDC_SIZEWE;
+            break;
+        case Graphics::PointerType::ScaleTop:
+            cursor = IDC_SIZENS;
+            break;
+        case Graphics::PointerType::ScaleRight:
+            cursor = IDC_SIZEWE;
+            break;
+        case Graphics::PointerType::ScaleBottom:
+            cursor = IDC_SIZENS;
+            break;
+        case Graphics::PointerType::ScaleTopLeft:
+            cursor = IDC_SIZENWSE;
+            break;
+        case Graphics::PointerType::ScaleTopRight:
+            cursor = IDC_SIZENESW;
+            break;
+        case Graphics::PointerType::ScaleBottomLeft:
+            cursor = IDC_SIZENESW;
+            break;
+        case Graphics::PointerType::ScaleBottomRight:
+            cursor = IDC_SIZENWSE;
+            break;
+        case Graphics::PointerType::Cross:
+            cursor = IDC_CROSS;
+            break;
+        case Graphics::PointerType::Help:
+            cursor = IDC_HELP;
+            break;
+        case Graphics::PointerType::Straight:
+            cursor = IDC_UPARROW;
+            break;
+        default:
+            cursor = IDC_ARROW;
+            break;
+        }
+        
+        LoadCursorW(instance, cursor);
+        SetCursor(c);
+    }
+    
+    
+} }
--- a/Source/Gorgon/WindowManager/X11/Window.cpp	Sat May 15 20:18:29 2021 +0200
+++ b/Source/Gorgon/WindowManager/X11/Window.cpp	Mon May 17 20:56:17 2021 +0300
@@ -6,7 +6,7 @@
 #include "../../Graphics/Layer.h"
 #include "../../Encoding/URI.h"
 #include "X11Keysym.h"
-
+#include <X11/cursorfont.h>
 
 namespace Gorgon { namespace WindowManager {
 
@@ -788,5 +788,80 @@
                     break;
             }
         }
-    }   
-}
+    }
+
+namespace WindowManager {
+    void SetPointer(Window &wind, Graphics::PointerType type) {
+        int cursor;
+        static std::map<Graphics::PointerType, Cursor> cursors;
+        
+        if(!cursors.count(type)) {
+            switch(type) {
+            case Graphics::PointerType::Wait:
+                cursor = XC_watch;
+                break;
+            case Graphics::PointerType::Processing:
+                cursor = XC_watch;
+                break;
+            case Graphics::PointerType::No:
+                cursor = XC_X_cursor;
+                break;
+            case Graphics::PointerType::Text:
+                cursor = XC_xterm;
+                break;
+            case Graphics::PointerType::Link:
+                cursor = XC_hand1;
+                break;
+            case Graphics::PointerType::Move:
+                cursor = XC_plus;
+                break;
+            case Graphics::PointerType::Drag:
+                cursor = XC_fleur;
+                break;
+            case Graphics::PointerType::ScaleLeft:
+                cursor = XC_left_side;
+                break;
+            case Graphics::PointerType::ScaleTop:
+                cursor = XC_top_side;
+                break;
+            case Graphics::PointerType::ScaleRight:
+                cursor = XC_right_side;
+                break;
+            case Graphics::PointerType::ScaleBottom:
+                cursor = XC_bottom_side;
+                break;
+            case Graphics::PointerType::ScaleTopLeft:
+                cursor = XC_top_left_corner;
+                break;
+            case Graphics::PointerType::ScaleTopRight:
+                cursor = XC_top_right_corner;
+                break;
+            case Graphics::PointerType::ScaleBottomLeft:
+                cursor = XC_bottom_left_corner;
+                break;
+            case Graphics::PointerType::ScaleBottomRight:
+                cursor = XC_bottom_right_corner;
+                break;
+            case Graphics::PointerType::Cross:
+                cursor = XC_crosshair;
+                break;
+            case Graphics::PointerType::Help:
+                cursor = XC_question_arrow;
+                break;
+            case Graphics::PointerType::Straight:
+                cursor = XC_center_ptr;
+                break;
+            default:
+                cursor = XC_arrow;
+                break;
+            }
+            
+            Cursor c;
+            c = XCreateFontCursor(WindowManager::display, cursor); 
+            cursors[type] = c;
+        }
+
+        XDefineCursor(WindowManager::display, internal::getdata(wind)->handle, cursors[type]);
+    }
+    
+} }
--- a/Testing/Source/Manual/Window.cpp	Sat May 15 20:18:29 2021 +0200
+++ b/Testing/Source/Manual/Window.cpp	Mon May 17 20:56:17 2021 +0300
@@ -112,10 +112,18 @@
     Graphics::DrawablePointer pointer1(cursor1, 8,15);
     
     cursor2.Prepare();
-    Graphics::DrawablePointer pointer2(cursor2, 8,8);
+    Graphics::DrawablePointer pointer2(cursor2, 8,8, Gorgon::Graphics::PointerType::Wait);
     
     cursor3.Prepare();
-    Graphics::DrawablePointer pointer3(cursor3, 1,8);
+    Graphics::DrawablePointer pointer3(cursor3, 1,8, Gorgon::Graphics::PointerType::Text);
+    
+    Resource::File fsave;
+    auto ptrsave = new Resource::Pointer;
+    
+    ptrsave->Add(cursor1);
+    ptrsave->SetType(Graphics::PointerType::Arrow);
+    fsave.Root().Add(ptrsave);
+    fsave.Save("ptrtest.gor");
     
     Resource::File f;
     f.LoadFile("ptrtest.gor");
@@ -127,14 +135,6 @@
     wind.Pointers.Add(Graphics::PointerType::Wait, pointer2);
     wind.Pointers.Add(Graphics::PointerType::Text, pointer3);
     
-    /*Resource::File f;
-    auto ptr = new Resource::Pointer;
-    
-    ptr->Add(cursor1);
-    ptr->SetType(Graphics::PointerType::Arrow);
-    f.Root().Add(ptr);
-    f.Save("ptrtest.gor");*/
-    
 
 	
 	//img = Graphics::Bitmap({200, 200}, Graphics::ColorMode::Alpha);

mercurial