Selaa lähdekoodia

Merge pull request #13437 from xsellier/bugfix/mouse-cursor-lag

Implement hardware cursor acceleration for Godot Engine 2.1
Rémi Verschelde 7 vuotta sitten
vanhempi
commit
3102dc17ee

+ 20 - 1
core/os/input.cpp

@@ -81,13 +81,32 @@ void Input::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("warp_mouse_pos", "to"), &Input::warp_mouse_pos);
 	ObjectTypeDB::bind_method(_MD("warp_mouse_pos", "to"), &Input::warp_mouse_pos);
 	ObjectTypeDB::bind_method(_MD("action_press", "action"), &Input::action_press);
 	ObjectTypeDB::bind_method(_MD("action_press", "action"), &Input::action_press);
 	ObjectTypeDB::bind_method(_MD("action_release", "action"), &Input::action_release);
 	ObjectTypeDB::bind_method(_MD("action_release", "action"), &Input::action_release);
-	ObjectTypeDB::bind_method(_MD("set_custom_mouse_cursor", "image:Texture", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(Vector2()));
+	ObjectTypeDB::bind_method(_MD("set_custom_mouse_cursor", "image:Texture", "shape", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(CURSOR_ARROW), DEFVAL(Vector2()));
 	ObjectTypeDB::bind_method(_MD("parse_input_event", "event"), &Input::parse_input_event);
 	ObjectTypeDB::bind_method(_MD("parse_input_event", "event"), &Input::parse_input_event);
 
 
 	BIND_CONSTANT(MOUSE_MODE_VISIBLE);
 	BIND_CONSTANT(MOUSE_MODE_VISIBLE);
 	BIND_CONSTANT(MOUSE_MODE_HIDDEN);
 	BIND_CONSTANT(MOUSE_MODE_HIDDEN);
 	BIND_CONSTANT(MOUSE_MODE_CAPTURED);
 	BIND_CONSTANT(MOUSE_MODE_CAPTURED);
 
 
+	// Those constants are used to change the mouse texture for given cursor shapes
+	BIND_CONSTANT(CURSOR_ARROW);
+	BIND_CONSTANT(CURSOR_IBEAM);
+	BIND_CONSTANT(CURSOR_POINTING_HAND);
+	BIND_CONSTANT(CURSOR_CROSS);
+	BIND_CONSTANT(CURSOR_WAIT);
+	BIND_CONSTANT(CURSOR_BUSY);
+	BIND_CONSTANT(CURSOR_DRAG);
+	BIND_CONSTANT(CURSOR_CAN_DROP);
+	BIND_CONSTANT(CURSOR_FORBIDDEN);
+	BIND_CONSTANT(CURSOR_VSIZE);
+	BIND_CONSTANT(CURSOR_HSIZE);
+	BIND_CONSTANT(CURSOR_BDIAGSIZE);
+	BIND_CONSTANT(CURSOR_FDIAGSIZE);
+	BIND_CONSTANT(CURSOR_MOVE);
+	BIND_CONSTANT(CURSOR_VSPLIT);
+	BIND_CONSTANT(CURSOR_HSPLIT);
+	BIND_CONSTANT(CURSOR_HELP);
+
 	ADD_SIGNAL(MethodInfo("joy_connection_changed", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "connected")));
 	ADD_SIGNAL(MethodInfo("joy_connection_changed", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "connected")));
 }
 }
 
 

+ 24 - 2
core/os/input.h

@@ -50,6 +50,28 @@ public:
 		MOUSE_MODE_CAPTURED
 		MOUSE_MODE_CAPTURED
 	};
 	};
 
 
+	#undef CursorShape
+	enum CursorShape {
+		CURSOR_ARROW,
+		CURSOR_IBEAM,
+		CURSOR_POINTING_HAND,
+		CURSOR_CROSS,
+		CURSOR_WAIT,
+		CURSOR_BUSY,
+		CURSOR_DRAG,
+		CURSOR_CAN_DROP,
+		CURSOR_FORBIDDEN,
+		CURSOR_VSIZE,
+		CURSOR_HSIZE,
+		CURSOR_BDIAGSIZE,
+		CURSOR_FDIAGSIZE,
+		CURSOR_MOVE,
+		CURSOR_VSPLIT,
+		CURSOR_HSPLIT,
+		CURSOR_HELP,
+		CURSOR_MAX
+	};
+
 	void set_mouse_mode(MouseMode p_mode);
 	void set_mouse_mode(MouseMode p_mode);
 	MouseMode get_mouse_mode() const;
 	MouseMode get_mouse_mode() const;
 
 
@@ -93,8 +115,7 @@ public:
 
 
 	virtual bool is_emulating_touchscreen() const = 0;
 	virtual bool is_emulating_touchscreen() const = 0;
 
 
-	virtual void set_custom_mouse_cursor(const RES &p_cursor, const Vector2 &p_hotspot = Vector2()) = 0;
-	virtual void set_mouse_in_window(bool p_in_window) = 0;
+	virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) = 0;
 
 
 	virtual String get_joy_button_string(int p_button) = 0;
 	virtual String get_joy_button_string(int p_button) = 0;
 	virtual String get_joy_axis_string(int p_axis) = 0;
 	virtual String get_joy_axis_string(int p_axis) = 0;
@@ -107,5 +128,6 @@ public:
 };
 };
 
 
 VARIANT_ENUM_CAST(Input::MouseMode);
 VARIANT_ENUM_CAST(Input::MouseMode);
+VARIANT_ENUM_CAST(Input::CursorShape);
 
 
 #endif // INPUT_H
 #endif // INPUT_H

+ 2 - 1
core/os/os.h

@@ -314,7 +314,8 @@ public:
 	virtual void hide_virtual_keyboard();
 	virtual void hide_virtual_keyboard();
 
 
 	virtual void set_cursor_shape(CursorShape p_shape) = 0;
 	virtual void set_cursor_shape(CursorShape p_shape) = 0;
-
+	virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape,  const Vector2 &p_hotspot) = 0;
+ 
 	virtual bool get_swap_ok_cancel() { return false; }
 	virtual bool get_swap_ok_cancel() { return false; }
 	virtual void dump_memory_to_file(const char *p_file);
 	virtual void dump_memory_to_file(const char *p_file);
 	virtual void dump_resources_to_file(const char *p_file);
 	virtual void dump_resources_to_file(const char *p_file);

+ 4 - 37
doc/base/classes.xml

@@ -16607,9 +16607,12 @@
 		<method name="set_custom_mouse_cursor">
 		<method name="set_custom_mouse_cursor">
 			<argument index="0" name="image" type="Texture">
 			<argument index="0" name="image" type="Texture">
 			</argument>
 			</argument>
-			<argument index="1" name="hotspot" type="Vector2" default="Vector2(0, 0)">
+			<argument index="1" name="hotspot" type="int" default="CURSOR_ARROW">
+			</argument>
+			<argument index="2" name="hotspot" type="Vector2" default="Vector2(0, 0)">
 			</argument>
 			</argument>
 			<description>
 			<description>
+				See enum CURSOR_* for the list of shapes.
 				Set a custom mouse cursor image, which is only visible inside the game window. The hotspot can also be specified.
 				Set a custom mouse cursor image, which is only visible inside the game window. The hotspot can also be specified.
 			</description>
 			</description>
 		</method>
 		</method>
@@ -46819,42 +46822,6 @@
 			<description>
 			<description>
 			</description>
 			</description>
 		</method>
 		</method>
-		<method name="cursor_set_pos">
-			<argument index="0" name="arg0" type="Vector2">
-			</argument>
-			<argument index="1" name="arg1" type="int">
-			</argument>
-			<description>
-			</description>
-		</method>
-		<method name="cursor_set_rotation">
-			<argument index="0" name="arg0" type="float">
-			</argument>
-			<argument index="1" name="arg1" type="int">
-			</argument>
-			<description>
-			</description>
-		</method>
-		<method name="cursor_set_texture">
-			<argument index="0" name="arg0" type="RID">
-			</argument>
-			<argument index="1" name="arg1" type="Vector2">
-			</argument>
-			<argument index="2" name="arg2" type="int">
-			</argument>
-			<argument index="3" name="arg3" type="Rect2">
-			</argument>
-			<description>
-			</description>
-		</method>
-		<method name="cursor_set_visible">
-			<argument index="0" name="arg0" type="bool">
-			</argument>
-			<argument index="1" name="arg1" type="int">
-			</argument>
-			<description>
-			</description>
-		</method>
 		<method name="draw">
 		<method name="draw">
 			<description>
 			<description>
 			</description>
 			</description>

+ 0 - 2
editor/editor_export_godot3.cpp

@@ -80,8 +80,6 @@ static const char *globals_renames[][2] = {
 	{ "display/custom_theme", "gui/theme/custom" },
 	{ "display/custom_theme", "gui/theme/custom" },
 	{ "display/custom_theme_font", "gui/theme/custom_font" },
 	{ "display/custom_theme_font", "gui/theme/custom_font" },
 	{ "display/swap_ok_cancel", "gui/common/swap_ok_cancel" },
 	{ "display/swap_ok_cancel", "gui/common/swap_ok_cancel" },
-	{ "display/custom_mouse_cursor", "display/mouse_cursor/custom_image" },
-	{ "display/custom_mouse_cursor_hotspot", "display/mouse_cursor/custom_hotspot" },
 	{ "display/tooltip_delay", "gui/timers/tooltip_delay_sec" },
 	{ "display/tooltip_delay", "gui/timers/tooltip_delay_sec" },
 	{ "display/text_edit_idle_detect_sec", "gui/timers/text_edit_idle_detect_sec" },
 	{ "display/text_edit_idle_detect_sec", "gui/timers/text_edit_idle_detect_sec" },
 	{ "display/stretch_mode", "display/stretch/mode" },
 	{ "display/stretch_mode", "display/stretch/mode" },

+ 1 - 12
editor/editor_import_export.cpp

@@ -930,17 +930,6 @@ Error EditorExportPlatform::export_project_files(EditorExportSaveFunction p_func
 			boot_splash = splash;
 			boot_splash = splash;
 		}
 		}
 	}
 	}
-	StringName custom_cursor;
-	{
-		String splash = Globals::get_singleton()->get("display/custom_mouse_cursor"); //avoid splash from being converted
-		splash = splash.strip_edges();
-		if (splash != String()) {
-			if (!splash.begins_with("res://"))
-				splash = "res://" + splash;
-			splash = splash.simplify_path();
-			custom_cursor = splash;
-		}
-	}
 
 
 	for (int i = 0; i < files.size(); i++) {
 	for (int i = 0; i < files.size(); i++) {
 
 
@@ -949,7 +938,7 @@ Error EditorExportPlatform::export_project_files(EditorExportSaveFunction p_func
 		String src = files[i];
 		String src = files[i];
 		Vector<uint8_t> buf;
 		Vector<uint8_t> buf;
 
 
-		if (src == boot_splash || src == custom_cursor)
+		if (src == boot_splash)
 			buf = get_exported_file_default(src); //bootsplash must be kept if used
 			buf = get_exported_file_default(src); //bootsplash must be kept if used
 		else
 		else
 			buf = get_exported_file(src);
 			buf = get_exported_file(src);

+ 4 - 31
main/input_default.cpp

@@ -415,9 +415,6 @@ void InputDefault::set_mouse_pos(const Point2 &p_posf) {
 
 
 	mouse_speed_track.update(p_posf - mouse_pos);
 	mouse_speed_track.update(p_posf - mouse_pos);
 	mouse_pos = p_posf;
 	mouse_pos = p_posf;
-	if (custom_cursor.is_valid()) {
-		VisualServer::get_singleton()->cursor_set_pos(get_mouse_pos());
-	}
 }
 }
 
 
 Point2 InputDefault::get_mouse_pos() const {
 Point2 InputDefault::get_mouse_pos() const {
@@ -497,37 +494,13 @@ bool InputDefault::is_emulating_touchscreen() const {
 	return emulate_touch;
 	return emulate_touch;
 }
 }
 
 
-void InputDefault::set_custom_mouse_cursor(const RES &p_cursor, const Vector2 &p_hotspot) {
-	if (custom_cursor == p_cursor)
+void InputDefault::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
+	if (custom_cursors[p_shape] == p_cursor)
 		return;
 		return;
 
 
-	custom_cursor = p_cursor;
-
-	if (p_cursor.is_null()) {
-		set_mouse_mode(MOUSE_MODE_VISIBLE);
-		VisualServer::get_singleton()->cursor_set_visible(false);
-	} else {
-		Ref<AtlasTexture> atex = custom_cursor;
-		Rect2 region = atex.is_valid() ? atex->get_region() : Rect2();
-		set_mouse_mode(MOUSE_MODE_HIDDEN);
-		VisualServer::get_singleton()->cursor_set_visible(true);
-		VisualServer::get_singleton()->cursor_set_texture(custom_cursor->get_rid(), p_hotspot, 0, region);
-		VisualServer::get_singleton()->cursor_set_pos(get_mouse_pos());
-	}
-}
+	custom_cursors[p_shape] = p_cursor;
 
 
-void InputDefault::set_mouse_in_window(bool p_in_window) {
-
-	if (custom_cursor.is_valid()) {
-
-		if (p_in_window) {
-			set_mouse_mode(MOUSE_MODE_HIDDEN);
-			VisualServer::get_singleton()->cursor_set_visible(true);
-		} else {
-			set_mouse_mode(MOUSE_MODE_VISIBLE);
-			VisualServer::get_singleton()->cursor_set_visible(false);
-		}
-	}
+	OS::get_singleton()->set_custom_mouse_cursor(p_cursor, (OS::CursorShape) p_shape, p_hotspot);
 }
 }
 
 
 // from github.com/gabomdq/SDL_GameControllerDB
 // from github.com/gabomdq/SDL_GameControllerDB

+ 2 - 3
main/input_default.h

@@ -105,7 +105,7 @@ class InputDefault : public Input {
 	SpeedTrack mouse_speed_track;
 	SpeedTrack mouse_speed_track;
 	Map<int, Joystick> joy_names;
 	Map<int, Joystick> joy_names;
 	int fallback_mapping;
 	int fallback_mapping;
-	RES custom_cursor;
+	RES custom_cursors[CURSOR_MAX] = { NULL };
 
 
 public:
 public:
 	enum HatMask {
 	enum HatMask {
@@ -214,8 +214,7 @@ public:
 	void set_emulate_touch(bool p_emulate);
 	void set_emulate_touch(bool p_emulate);
 	virtual bool is_emulating_touchscreen() const;
 	virtual bool is_emulating_touchscreen() const;
 
 
-	virtual void set_custom_mouse_cursor(const RES &p_cursor, const Vector2 &p_hotspot = Vector2());
-	virtual void set_mouse_in_window(bool p_in_window);
+	virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape = Input::CURSOR_ARROW, const Vector2 &p_hotspot = Vector2());
 
 
 	void parse_mapping(String p_mapping);
 	void parse_mapping(String p_mapping);
 	uint32_t joy_button(uint32_t p_last_id, int p_device, int p_button, bool p_pressed);
 	uint32_t joy_button(uint32_t p_last_id, int p_device, int p_button, bool p_pressed);

+ 0 - 14
main/main.cpp

@@ -953,20 +953,6 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
 	register_scene_types();
 	register_scene_types();
 	register_server_types();
 	register_server_types();
 
 
-	GLOBAL_DEF("display/custom_mouse_cursor", String());
-	GLOBAL_DEF("display/custom_mouse_cursor_hotspot", Vector2());
-	Globals::get_singleton()->set_custom_property_info("display/custom_mouse_cursor", PropertyInfo(Variant::STRING, "display/custom_mouse_cursor", PROPERTY_HINT_FILE, "*.png,*.webp"));
-
-	if (String(Globals::get_singleton()->get("display/custom_mouse_cursor")) != String()) {
-
-		//print_line("use custom cursor");
-		Ref<Texture> cursor = ResourceLoader::load(Globals::get_singleton()->get("display/custom_mouse_cursor"));
-		if (cursor.is_valid()) {
-			//	print_line("loaded ok");
-			Vector2 hotspot = Globals::get_singleton()->get("display/custom_mouse_cursor_hotspot");
-			Input::get_singleton()->set_custom_mouse_cursor(cursor, hotspot);
-		}
-	}
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 	EditorNode::register_editor_types();
 	EditorNode::register_editor_types();
 #endif
 #endif

+ 0 - 18
main/tests/test_containers.cpp

@@ -30,7 +30,6 @@
 #include "dvector.h"
 #include "dvector.h"
 #include "math_funcs.h"
 #include "math_funcs.h"
 #include "print_string.h"
 #include "print_string.h"
-#include "servers/visual/default_mouse_cursor.xpm"
 #include "set.h"
 #include "set.h"
 
 
 #include "image.h"
 #include "image.h"
@@ -51,23 +50,6 @@ MainLoop *test() {
 	}
 	}
 	*/
 	*/
 
 
-	{
-
-		//		static const int size = 16;
-		Image img;
-		img.create(default_mouse_cursor_xpm);
-
-		{
-			for (int i = 0; i < 8; i++) {
-
-				Image mipmap;
-				//img.make_mipmap(mipmap);
-				img = mipmap;
-				if (img.get_width() <= 4) break;
-			};
-		};
-	};
-
 #if 0
 #if 0
 	Set<int> set;
 	Set<int> set;
 
 

+ 5 - 1
platform/android/os_android.cpp

@@ -142,7 +142,6 @@ void OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int
 		visual_server = memnew(VisualServerWrapMT(visual_server, false));
 		visual_server = memnew(VisualServerWrapMT(visual_server, false));
 	};
 	};
 	visual_server->init();
 	visual_server->init();
-	visual_server->cursor_set_visible(false, 0);
 
 
 	AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
 	AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
 
 
@@ -325,6 +324,11 @@ void OS_Android::set_cursor_shape(CursorShape p_shape) {
 	//android really really really has no mouse.. how amazing..
 	//android really really really has no mouse.. how amazing..
 }
 }
 
 
+void OS_Android::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape,  const Vector2 &p_hotspot) {
+
+	// Since android has no mouse, we do not need to change its texture (how amazing !)
+}
+
 void OS_Android::main_loop_begin() {
 void OS_Android::main_loop_begin() {
 
 
 	if (main_loop)
 	if (main_loop)

+ 1 - 0
platform/android/os_android.h

@@ -203,6 +203,7 @@ public:
 
 
 	virtual bool can_draw() const;
 	virtual bool can_draw() const;
 
 
+	virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
 	virtual void set_cursor_shape(CursorShape p_shape);
 	virtual void set_cursor_shape(CursorShape p_shape);
 
 
 	void main_loop_begin();
 	void main_loop_begin();

+ 5 - 1
platform/bb10/os_bb10.cpp

@@ -136,7 +136,6 @@ void OSBB10::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
 
 
 	visual_server = memnew(VisualServerRaster(rasterizer));
 	visual_server = memnew(VisualServerRaster(rasterizer));
 	visual_server->init();
 	visual_server->init();
-	visual_server->cursor_set_visible(false, 0);
 
 
 	audio_driver = memnew(AudioDriverBB10);
 	audio_driver = memnew(AudioDriverBB10);
 	audio_driver->set_singleton();
 	audio_driver->set_singleton();
@@ -285,6 +284,11 @@ void OSBB10::set_cursor_shape(CursorShape p_shape) {
 	//android really really really has no mouse.. how amazing..
 	//android really really really has no mouse.. how amazing..
 }
 }
 
 
+void OSBB10::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape,  const Vector2 &p_hotspot) {
+
+	// Since BlackBerry 10 has no mouse, we do not need to change its texture (how amazing !)
+}
+
 void OSBB10::handle_screen_event(bps_event_t *event) {
 void OSBB10::handle_screen_event(bps_event_t *event) {
 
 
 	screen_event_t screen_event = screen_event_get_event(event);
 	screen_event_t screen_event = screen_event_get_event(event);

+ 1 - 0
platform/bb10/os_bb10.h

@@ -142,6 +142,7 @@ public:
 
 
 	virtual bool can_draw() const;
 	virtual bool can_draw() const;
 
 
+	virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
 	virtual void set_cursor_shape(CursorShape p_shape);
 	virtual void set_cursor_shape(CursorShape p_shape);
 
 
 	virtual bool has_touchscreen_ui_hint() const;
 	virtual bool has_touchscreen_ui_hint() const;

+ 4 - 0
platform/haiku/os_haiku.cpp

@@ -235,6 +235,10 @@ void OS_Haiku::set_cursor_shape(CursorShape p_shape) {
 	//ERR_PRINT("set_cursor_shape() NOT IMPLEMENTED");
 	//ERR_PRINT("set_cursor_shape() NOT IMPLEMENTED");
 }
 }
 
 
+void OS_Haiku::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape,  const Vector2 &p_hotspot) {
+	// TODO: implement set_custom_mouse_cursor()
+}
+
 int OS_Haiku::get_screen_count() const {
 int OS_Haiku::get_screen_count() const {
 	// TODO: implement get_screen_count()
 	// TODO: implement get_screen_count()
 	return 1;
 	return 1;

+ 2 - 1
platform/haiku/os_haiku.h

@@ -98,7 +98,8 @@ public:
 	virtual Point2 get_mouse_pos() const;
 	virtual Point2 get_mouse_pos() const;
 	virtual int get_mouse_button_state() const;
 	virtual int get_mouse_button_state() const;
 	virtual void set_cursor_shape(CursorShape p_shape);
 	virtual void set_cursor_shape(CursorShape p_shape);
-
+	virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
+ 
 	virtual int get_screen_count() const;
 	virtual int get_screen_count() const;
 	virtual int get_current_screen() const;
 	virtual int get_current_screen() const;
 	virtual void set_current_screen(int p_screen);
 	virtual void set_current_screen(int p_screen);

+ 4 - 1
platform/iphone/os_iphone.cpp

@@ -120,7 +120,6 @@ void OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p_
 	visual_server->init();
 	visual_server->init();
 
 
 	visual_server->init();
 	visual_server->init();
-	visual_server->cursor_set_visible(false, 0);
 
 
 	audio_driver = memnew(AudioDriverIphone);
 	audio_driver = memnew(AudioDriverIphone);
 	audio_driver->set_singleton();
 	audio_driver->set_singleton();
@@ -479,6 +478,10 @@ void OSIPhone::set_cursor_shape(CursorShape p_shape){
 
 
 };
 };
 
 
+void OSIPhone::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
+
+};
+
 String OSIPhone::get_data_dir() const {
 String OSIPhone::get_data_dir() const {
 
 
 	return data_dir;
 	return data_dir;

+ 1 - 0
platform/iphone/os_iphone.h

@@ -183,6 +183,7 @@ public:
 	virtual void hide_virtual_keyboard();
 	virtual void hide_virtual_keyboard();
 
 
 	virtual void set_cursor_shape(CursorShape p_shape);
 	virtual void set_cursor_shape(CursorShape p_shape);
+	virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
 
 
 	virtual Size2 get_window_size() const;
 	virtual Size2 get_window_size() const;
 
 

+ 4 - 1
platform/javascript/os_javascript.cpp

@@ -439,7 +439,6 @@ void OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, i
 
 
 	visual_server = memnew(VisualServerRaster(rasterizer));
 	visual_server = memnew(VisualServerRaster(rasterizer));
 	visual_server->init();
 	visual_server->init();
-	visual_server->cursor_set_visible(false, 0);
 
 
 	/*AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
 	/*AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
 
 
@@ -686,6 +685,10 @@ void OS_JavaScript::set_cursor_shape(CursorShape p_shape) {
 	//javascript really really really has no mouse.. how amazing..
 	//javascript really really really has no mouse.. how amazing..
 }
 }
 
 
+void OS_JavaScript::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
+
+}
+
 void OS_JavaScript::main_loop_begin() {
 void OS_JavaScript::main_loop_begin() {
 
 
 	if (main_loop)
 	if (main_loop)

+ 1 - 0
platform/javascript/os_javascript.h

@@ -138,6 +138,7 @@ public:
 	virtual bool can_draw() const;
 	virtual bool can_draw() const;
 
 
 	virtual void set_cursor_shape(CursorShape p_shape);
 	virtual void set_cursor_shape(CursorShape p_shape);
+	virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
 
 
 	void main_loop_begin();
 	void main_loop_begin();
 	bool main_loop_iterate();
 	bool main_loop_iterate();

+ 3 - 0
platform/osx/os_osx.h

@@ -49,6 +49,7 @@
 #include "servers/visual/visual_server_wrap_mt.h"
 #include "servers/visual/visual_server_wrap_mt.h"
 #include "servers/visual_server.h"
 #include "servers/visual_server.h"
 #include <ApplicationServices/ApplicationServices.h>
 #include <ApplicationServices/ApplicationServices.h>
+#include <AppKit/NSCursor.h>
 
 
 //bitch
 //bitch
 #undef CursorShape
 #undef CursorShape
@@ -102,6 +103,7 @@ public:
 	id context;
 	id context;
 
 
 	CursorShape cursor_shape;
 	CursorShape cursor_shape;
+	NSCursor *cursors[CURSOR_MAX] = { NULL };
 	MouseMode mouse_mode;
 	MouseMode mouse_mode;
 
 
 	String title;
 	String title;
@@ -149,6 +151,7 @@ public:
 	virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
 	virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
 
 
 	virtual void set_cursor_shape(CursorShape p_shape);
 	virtual void set_cursor_shape(CursorShape p_shape);
+	virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
 
 
 	virtual void set_mouse_show(bool p_show);
 	virtual void set_mouse_show(bool p_show);
 	virtual void set_mouse_grab(bool p_grab);
 	virtual void set_mouse_grab(bool p_grab);

+ 75 - 24
platform/osx/os_osx.mm

@@ -38,6 +38,7 @@
 #include "servers/physics/physics_server_sw.h"
 #include "servers/physics/physics_server_sw.h"
 #include "servers/visual/visual_server_raster.h"
 #include "servers/visual/visual_server_raster.h"
 #include "servers/visual/visual_server_wrap_mt.h"
 #include "servers/visual/visual_server_wrap_mt.h"
+#include "scene/resources/texture.h"
 
 
 #include <Carbon/Carbon.h>
 #include <Carbon/Carbon.h>
 #import <Cocoa/Cocoa.h>
 #import <Cocoa/Cocoa.h>
@@ -490,9 +491,6 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) {
 	if (OS_OSX::singleton->main_loop && OS_OSX::singleton->mouse_mode != OS::MOUSE_MODE_CAPTURED)
 	if (OS_OSX::singleton->main_loop && OS_OSX::singleton->mouse_mode != OS::MOUSE_MODE_CAPTURED)
 		OS_OSX::singleton->main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT);
 		OS_OSX::singleton->main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT);
 
 
-	if (OS_OSX::singleton->input)
-		OS_OSX::singleton->input->set_mouse_in_window(false);
-
 	//_glfwInputCursorEnter(window, GL_FALSE);
 	//_glfwInputCursorEnter(window, GL_FALSE);
 }
 }
 
 
@@ -505,7 +503,8 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) {
 		OS_OSX::singleton->main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
 		OS_OSX::singleton->main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
 
 
 	if (OS_OSX::singleton->input)
 	if (OS_OSX::singleton->input)
-		OS_OSX::singleton->input->set_mouse_in_window(true);
+		OS_OSX::singleton->cursor_shape = OS::CURSOR_MAX;
+		OS_OSX::singleton->set_cursor_shape(OS::CURSOR_ARROW);
 }
 }
 
 
 - (void)viewDidChangeBackingProperties {
 - (void)viewDidChangeBackingProperties {
@@ -1026,7 +1025,6 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
 	}
 	}
 
 
 	visual_server->init();
 	visual_server->init();
-	visual_server->cursor_set_visible(false, 0);
 
 
 	AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
 	AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
 
 
@@ -1167,30 +1165,83 @@ void OS_OSX::set_cursor_shape(CursorShape p_shape) {
 	if (cursor_shape == p_shape)
 	if (cursor_shape == p_shape)
 		return;
 		return;
 
 
-	switch (p_shape) {
-		case CURSOR_ARROW: [[NSCursor arrowCursor] set]; break;
-		case CURSOR_IBEAM: [[NSCursor IBeamCursor] set]; break;
-		case CURSOR_POINTING_HAND: [[NSCursor pointingHandCursor] set]; break;
-		case CURSOR_CROSS: [[NSCursor crosshairCursor] set]; break;
-		case CURSOR_WAIT: [[NSCursor arrowCursor] set]; break;
-		case CURSOR_BUSY: [[NSCursor arrowCursor] set]; break;
-		case CURSOR_DRAG: [[NSCursor closedHandCursor] set]; break;
-		case CURSOR_CAN_DROP: [[NSCursor openHandCursor] set]; break;
-		case CURSOR_FORBIDDEN: [[NSCursor arrowCursor] set]; break;
-		case CURSOR_VSIZE: [[NSCursor resizeUpDownCursor] set]; break;
-		case CURSOR_HSIZE: [[NSCursor resizeLeftRightCursor] set]; break;
-		case CURSOR_BDIAGSIZE: [[NSCursor arrowCursor] set]; break;
-		case CURSOR_FDIAGSIZE: [[NSCursor arrowCursor] set]; break;
-		case CURSOR_MOVE: [[NSCursor arrowCursor] set]; break;
-		case CURSOR_VSPLIT: [[NSCursor resizeUpDownCursor] set]; break;
-		case CURSOR_HSPLIT: [[NSCursor resizeLeftRightCursor] set]; break;
-		case CURSOR_HELP: [[NSCursor arrowCursor] set]; break;
-		default: {};
+	if (cursors[p_shape] != NULL) {
+		[cursors[p_shape] set];
+	} else {
+		switch (p_shape) {
+			case CURSOR_ARROW: [[NSCursor arrowCursor] set]; break;
+			case CURSOR_IBEAM: [[NSCursor IBeamCursor] set]; break;
+			case CURSOR_POINTING_HAND: [[NSCursor pointingHandCursor] set]; break;
+			case CURSOR_CROSS: [[NSCursor crosshairCursor] set]; break;
+			case CURSOR_WAIT: [[NSCursor arrowCursor] set]; break;
+			case CURSOR_BUSY: [[NSCursor arrowCursor] set]; break;
+			case CURSOR_DRAG: [[NSCursor closedHandCursor] set]; break;
+			case CURSOR_CAN_DROP: [[NSCursor openHandCursor] set]; break;
+			case CURSOR_FORBIDDEN: [[NSCursor arrowCursor] set]; break;
+			case CURSOR_VSIZE: [[NSCursor resizeUpDownCursor] set]; break;
+			case CURSOR_HSIZE: [[NSCursor resizeLeftRightCursor] set]; break;
+			case CURSOR_BDIAGSIZE: [[NSCursor arrowCursor] set]; break;
+			case CURSOR_FDIAGSIZE: [[NSCursor arrowCursor] set]; break;
+			case CURSOR_MOVE: [[NSCursor arrowCursor] set]; break;
+			case CURSOR_VSPLIT: [[NSCursor resizeUpDownCursor] set]; break;
+			case CURSOR_HSPLIT: [[NSCursor resizeLeftRightCursor] set]; break;
+			case CURSOR_HELP: [[NSCursor arrowCursor] set]; break;
+			default: {};
+		}
 	}
 	}
 
 
 	cursor_shape = p_shape;
 	cursor_shape = p_shape;
 }
 }
 
 
+void OS_OSX::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot){
+	if (p_cursor.is_valid()) {
+		Ref<ImageTexture> texture = p_cursor;
+		Image image = texture->get_data();
+
+		int image_size = 32 * 32;
+
+		ERR_FAIL_COND(texture->get_width() != 32 || texture->get_height() != 32);
+
+		NSBitmapImageRep *imgrep = [[[NSBitmapImageRep alloc]
+						initWithBitmapDataPlanes:NULL
+						pixelsWide:image.get_width()
+						pixelsHigh:image.get_height()
+						bitsPerSample:8
+						samplesPerPixel:4
+						hasAlpha:YES
+						isPlanar:NO
+						colorSpaceName:NSDeviceRGBColorSpace
+						bytesPerRow:image.get_width() * 4
+						bitsPerPixel:32] autorelease];
+		ERR_FAIL_COND(imgrep == nil);
+		uint8_t *pixels = [imgrep bitmapData];
+
+		int len = image.get_width() * image.get_height();
+		DVector<uint8_t> data = image.get_data();
+		DVector<uint8_t>::Read r = data.read();
+
+		/* Premultiply the alpha channel */
+		for (int i = 0; i < len; i++) {
+			uint8_t alpha = r[i * 4 + 3];
+			pixels[i * 4 + 0] = (uint8_t)(((uint16_t)r[i * 4 + 0] * alpha) / 255);
+			pixels[i * 4 + 1] = (uint8_t)(((uint16_t)r[i * 4 + 1] * alpha) / 255);
+			pixels[i * 4 + 2] = (uint8_t)(((uint16_t)r[i * 4 + 2] * alpha) / 255);
+			pixels[i * 4 + 3] = alpha;
+		}
+
+		NSImage * nsimage = [[[NSImage alloc] initWithSize: NSMakeSize(image.get_width(), image.get_height())] autorelease];
+		[nsimage addRepresentation: imgrep];
+		
+		NSCursor *cursor = [[NSCursor alloc] initWithImage: nsimage hotSpot: NSMakePoint(p_hotspot.x, p_hotspot.y)];
+
+		cursors[p_shape] = cursor;
+
+		if (p_shape == CURSOR_ARROW) {
+			[cursor set];
+		}
+	}
+}
+
 void OS_OSX::set_mouse_show(bool p_show) {
 void OS_OSX::set_mouse_show(bool p_show) {
 }
 }
 
 

+ 3 - 0
platform/server/os_server.cpp

@@ -198,6 +198,9 @@ void OS_Server::move_window_to_foreground() {
 void OS_Server::set_cursor_shape(CursorShape p_shape) {
 void OS_Server::set_cursor_shape(CursorShape p_shape) {
 }
 }
 
 
+void OS_Server::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
+}
+
 void OS_Server::run() {
 void OS_Server::run() {
 
 
 	force_quit = false;
 	force_quit = false;

+ 1 - 0
platform/server/os_server.h

@@ -89,6 +89,7 @@ public:
 	virtual String get_name();
 	virtual String get_name();
 
 
 	virtual void set_cursor_shape(CursorShape p_shape);
 	virtual void set_cursor_shape(CursorShape p_shape);
+	virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
 
 
 	virtual void set_mouse_show(bool p_show);
 	virtual void set_mouse_show(bool p_show);
 	virtual void set_mouse_grab(bool p_grab);
 	virtual void set_mouse_grab(bool p_grab);

+ 116 - 5
platform/windows/os_windows.cpp

@@ -42,6 +42,7 @@
 #include "servers/audio/audio_server_sw.h"
 #include "servers/audio/audio_server_sw.h"
 #include "servers/visual/visual_server_raster.h"
 #include "servers/visual/visual_server_raster.h"
 #include "servers/visual/visual_server_wrap_mt.h"
 #include "servers/visual/visual_server_wrap_mt.h"
+#include "scene/resources/texture.h"
 
 
 #include "globals.h"
 #include "globals.h"
 #include "io/marshalls.h"
 #include "io/marshalls.h"
@@ -359,8 +360,6 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 			outside = true;
 			outside = true;
 			if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED)
 			if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED)
 				main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT);
 				main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT);
-			if (input)
-				input->set_mouse_in_window(false);
 
 
 		} break;
 		} break;
 		case WM_MOUSEMOVE: {
 		case WM_MOUSEMOVE: {
@@ -370,8 +369,6 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 
 
 				if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED)
 				if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED)
 					main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
 					main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
-				if (input)
-					input->set_mouse_in_window(true);
 
 
 				CursorShape c = cursor_shape;
 				CursorShape c = cursor_shape;
 				cursor_shape = CURSOR_MAX;
 				cursor_shape = CURSOR_MAX;
@@ -1937,10 +1934,124 @@ void OS_Windows::set_cursor_shape(CursorShape p_shape) {
 		IDC_HELP
 		IDC_HELP
 	};
 	};
 
 
-	SetCursor(LoadCursor(hInstance, win_cursors[p_shape]));
+	if (cursors[p_shape] != NULL) {
+		SetCursor(cursors[p_shape]);
+	} else {
+		SetCursor(LoadCursor(hInstance, win_cursors[p_shape]));
+	}
+
 	cursor_shape = p_shape;
 	cursor_shape = p_shape;
 }
 }
 
 
+void OS_Windows::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot){
+	if (p_cursor.is_valid()) {
+		Ref<ImageTexture> texture = p_cursor;
+		Image image = texture->get_data();
+
+		UINT image_size = 32 * 32;
+		UINT size = sizeof(UINT) * image_size;
+
+		ERR_FAIL_COND(texture->get_width() != 32 || texture->get_height() != 32);
+
+		// Create the BITMAP with alpha channel
+		COLORREF *buffer = (COLORREF *)malloc(sizeof(COLORREF) * image_size);
+
+		for (UINT index = 0; index < image_size; index++) {
+			int column_index = floor(index / 32);
+			int row_index = index % 32;
+
+			Color pcColor = image.get_pixel(row_index, column_index);
+			*(buffer + index) = image.get_pixel(row_index, column_index).to_ARGB32();
+		}
+
+		// Using 4 channels, so 4 * 8 bits
+		HBITMAP bitmap = CreateBitmap(32, 32, 1, 4 * 8, buffer);
+		COLORREF clrTransparent = -1;
+
+		// Create the AND and XOR masks for the bitmap
+		HBITMAP hAndMask = NULL;
+		HBITMAP hXorMask = NULL;
+
+		GetMaskBitmaps(bitmap, clrTransparent, hAndMask, hXorMask);
+
+		if (NULL == hAndMask || NULL == hXorMask) {
+			return;
+		}
+
+		// Finally, create the icon
+		ICONINFO iconinfo = {0};
+		iconinfo.fIcon = FALSE;
+		iconinfo.xHotspot = p_hotspot.x;
+		iconinfo.yHotspot = p_hotspot.y;
+		iconinfo.hbmMask = hAndMask;
+		iconinfo.hbmColor = hXorMask;
+
+		cursors[p_shape] = CreateIconIndirect(&iconinfo);
+
+		if (p_shape == CURSOR_ARROW) {
+			SetCursor(cursors[p_shape]);
+		}
+
+		if (hAndMask != NULL) {
+			DeleteObject(hAndMask);
+		}
+
+		if (hXorMask != NULL) {
+		  DeleteObject(hXorMask);
+		}
+	}
+}
+
+void OS_Windows::GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap) {
+
+	// Get the system display DC
+	HDC hDC = GetDC(NULL);
+
+	// Create helper DC
+	HDC hMainDC = CreateCompatibleDC(hDC);
+	HDC hAndMaskDC = CreateCompatibleDC(hDC);
+	HDC hXorMaskDC = CreateCompatibleDC(hDC);
+
+	// Get the dimensions of the source bitmap
+	BITMAP bm;
+	GetObject(hSourceBitmap, sizeof(BITMAP), &bm);
+
+	// Create the mask bitmaps
+	hAndMaskBitmap = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight); // color
+	hXorMaskBitmap = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight); // color
+
+	// Release the system display DC
+	ReleaseDC(NULL, hDC);
+
+	// Select the bitmaps to helper DC
+	HBITMAP hOldMainBitmap = (HBITMAP)SelectObject(hMainDC, hSourceBitmap);
+	HBITMAP hOldAndMaskBitmap = (HBITMAP)SelectObject(hAndMaskDC, hAndMaskBitmap);
+	HBITMAP hOldXorMaskBitmap = (HBITMAP)SelectObject(hXorMaskDC, hXorMaskBitmap);
+
+	// Assign the monochrome AND mask bitmap pixels so that a pixels of the source bitmap
+	// with 'clrTransparent' will be white pixels of the monochrome bitmap
+	SetBkColor(hMainDC, clrTransparent);
+	BitBlt(hAndMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hMainDC, 0, 0, SRCCOPY);
+
+	// Assign the color XOR mask bitmap pixels so that a pixels of the source bitmap
+	// with 'clrTransparent' will be black and rest the pixels same as corresponding
+	// pixels of the source bitmap
+	SetBkColor(hXorMaskDC, RGB(0, 0, 0));
+	SetTextColor(hXorMaskDC, RGB(255, 255, 255));
+	BitBlt(hXorMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hAndMaskDC, 0, 0, SRCCOPY);
+	BitBlt(hXorMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hMainDC, 0,0, SRCAND);
+
+	// Deselect bitmaps from the helper DC
+	SelectObject(hMainDC, hOldMainBitmap);
+	SelectObject(hAndMaskDC, hOldAndMaskBitmap);
+	SelectObject(hXorMaskDC, hOldXorMaskBitmap);
+
+	// Delete the helper DC
+	DeleteDC(hXorMaskDC);
+	DeleteDC(hAndMaskDC);
+	DeleteDC(hMainDC);
+}
+
 Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) {
 Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) {
 
 
 	if (p_blocking && r_pipe) {
 	if (p_blocking && r_pipe) {

+ 3 - 0
platform/windows/os_windows.h

@@ -126,6 +126,7 @@ class OS_Windows : public OS {
 	bool force_quit;
 	bool force_quit;
 	uint32_t last_button_state;
 	uint32_t last_button_state;
 
 
+	HCURSOR cursors[CURSOR_MAX] = { NULL };
 	CursorShape cursor_shape;
 	CursorShape cursor_shape;
 
 
 	InputDefault *input;
 	InputDefault *input;
@@ -255,6 +256,8 @@ public:
 	virtual String get_clipboard() const;
 	virtual String get_clipboard() const;
 
 
 	void set_cursor_shape(CursorShape p_shape);
 	void set_cursor_shape(CursorShape p_shape);
+	void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
+	void GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap);
 	void set_icon(const Image &p_icon);
 	void set_icon(const Image &p_icon);
 
 
 	virtual String get_executable_path() const;
 	virtual String get_executable_path() const;

+ 7 - 0
platform/winrt/os_winrt.cpp

@@ -771,6 +771,13 @@ void OSWinrt::set_cursor_shape(CursorShape p_shape) {
 	cursor_shape = p_shape;
 	cursor_shape = p_shape;
 }
 }
 
 
+void OSWinrt::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape,  const Vector2 &p_hotspot) {
+
+	// FIXME:
+	// Not implemented, some work needs to be done for this one
+	// Might be a good source: https://stackoverflow.com/questions/43793745/set-custom-mouse-cursor-on-windows-10-universal-app-uwp
+}
+
 Error OSWinrt::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) {
 Error OSWinrt::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) {
 
 
 	return FAILED;
 	return FAILED;

+ 1 - 0
platform/winrt/os_winrt.h

@@ -236,6 +236,7 @@ public:
 	virtual String get_clipboard() const;
 	virtual String get_clipboard() const;
 
 
 	void set_cursor_shape(CursorShape p_shape);
 	void set_cursor_shape(CursorShape p_shape);
+	void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
 	void set_icon(const Image &p_icon);
 	void set_icon(const Image &p_icon);
 
 
 	virtual String get_executable_path() const;
 	virtual String get_executable_path() const;

+ 40 - 4
platform/x11/os_x11.cpp

@@ -42,6 +42,7 @@
 
 
 #include "X11/Xatom.h"
 #include "X11/Xatom.h"
 #include "X11/extensions/Xinerama.h"
 #include "X11/extensions/Xinerama.h"
+#include "scene/resources/texture.h"
 // ICCCM
 // ICCCM
 #define WM_NormalState 1L // window normal state
 #define WM_NormalState 1L // window normal state
 #define WM_IconicState 3L // window minimized
 #define WM_IconicState 3L // window minimized
@@ -1452,16 +1453,12 @@ void OS_X11::process_xevents() {
 
 
 				if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED)
 				if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED)
 					main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT);
 					main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT);
-				if (input)
-					input->set_mouse_in_window(false);
 
 
 			} break;
 			} break;
 			case EnterNotify: {
 			case EnterNotify: {
 
 
 				if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED)
 				if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED)
 					main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
 					main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
-				if (input)
-					input->set_mouse_in_window(true);
 			} break;
 			} break;
 			case FocusIn:
 			case FocusIn:
 				minimized = false;
 				minimized = false;
@@ -2038,6 +2035,45 @@ void OS_X11::set_cursor_shape(CursorShape p_shape) {
 	current_cursor = p_shape;
 	current_cursor = p_shape;
 }
 }
 
 
+void OS_X11::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
+
+	if (p_cursor.is_valid()) {
+		Ref<ImageTexture> texture = p_cursor;
+		Image image = texture->get_data();
+
+		ERR_FAIL_COND(texture->get_width() != 32 || texture->get_height() != 32);
+
+		// Create the cursor structure
+		XcursorImage *cursor_image = XcursorImageCreate(texture->get_width(), texture->get_height());
+		XcursorUInt image_size = 32 * 32;
+		XcursorDim size = sizeof(XcursorPixel) * image_size;
+
+		cursor_image->version = 1;
+		cursor_image->size = size;
+		cursor_image->xhot = p_hotspot.x;
+		cursor_image->yhot = p_hotspot.y;
+
+		// allocate memory to contain the whole file
+		cursor_image->pixels = (XcursorPixel *)malloc(size);
+
+		for (XcursorPixel index = 0; index < image_size; index++) {
+			int column_index = floor(index / 32);
+			int row_index = index % 32;
+
+			*(cursor_image->pixels + index) = image.get_pixel(row_index, column_index).to_ARGB32();
+		}
+
+		ERR_FAIL_COND(cursor_image->pixels == NULL);
+
+		// Save it for a further usage
+		cursors[p_shape] = XcursorImageLoadCursor(x11_display, cursor_image);
+
+		if (p_shape == CURSOR_ARROW) {
+			XDefineCursor(x11_display, x11_window, cursors[p_shape]);
+		}
+	}
+}
+
 void OS_X11::release_rendering_thread() {
 void OS_X11::release_rendering_thread() {
 
 
 	context_gl->release_current();
 	context_gl->release_current();

+ 1 - 0
platform/x11/os_x11.h

@@ -218,6 +218,7 @@ public:
 	virtual String get_name();
 	virtual String get_name();
 
 
 	virtual void set_cursor_shape(CursorShape p_shape);
 	virtual void set_cursor_shape(CursorShape p_shape);
+	virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
 
 
 	void set_mouse_mode(MouseMode p_mode);
 	void set_mouse_mode(MouseMode p_mode);
 	MouseMode get_mouse_mode() const;
 	MouseMode get_mouse_mode() const;

+ 0 - 23
servers/visual/default_mouse_cursor.xpm

@@ -1,23 +0,0 @@
-/* XPM */
-static const char * default_mouse_cursor_xpm[] = {
-"16 16 4 1",
-" 	c None",
-".	c #000000",
-"+	c #FF00FF",
-"@	c #FFFFFF",
-"...+++++++++++++",
-".@...+++++++++++",
-".@@@...+++++++++",
-".@@@@@....++++++",
-".@@@@@@@@...++++",
-".@@@@@@@@@@...++",
-".@@@@@@@@@@@@..+",
-".@@@@@@@@@@@@@..",
-".@@@@@@@@@@@@..+",
-".@@@@@@@@@@@..++",
-".@@@@@@@@@...+++",
-".@@@.....@@..+++",
-".....+++.@@@..++",
-"++++++++..@@@..+",
-"+++++++++..@@@.+",
-"++++++++++.....+"};

+ 0 - 57
servers/visual/visual_server_raster.cpp

@@ -28,7 +28,6 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 /*************************************************************************/
 #include "visual_server_raster.h"
 #include "visual_server_raster.h"
-#include "default_mouse_cursor.xpm"
 #include "globals.h"
 #include "globals.h"
 #include "io/marshalls.h"
 #include "io/marshalls.h"
 #include "os/os.h"
 #include "os/os.h"
@@ -4068,38 +4067,6 @@ void VisualServerRaster::canvas_item_material_set_shading_mode(RID p_material, C
 
 
 /******** CANVAS *********/
 /******** CANVAS *********/
 
 
-void VisualServerRaster::cursor_set_rotation(float p_rotation, int p_cursor) {
-	VS_CHANGED;
-	ERR_FAIL_INDEX(p_cursor, MAX_CURSORS);
-
-	cursors[p_cursor].rot = p_rotation;
-};
-
-void VisualServerRaster::cursor_set_texture(RID p_texture, const Point2 &p_center_offset, int p_cursor, const Rect2 &p_region) {
-	VS_CHANGED;
-	ERR_FAIL_INDEX(p_cursor, MAX_CURSORS);
-
-	cursors[p_cursor].texture = p_texture;
-	cursors[p_cursor].center = p_center_offset;
-	cursors[p_cursor].region = p_region;
-};
-
-void VisualServerRaster::cursor_set_visible(bool p_visible, int p_cursor) {
-	VS_CHANGED;
-	ERR_FAIL_INDEX(p_cursor, MAX_CURSORS);
-
-	cursors[p_cursor].visible = p_visible;
-};
-
-void VisualServerRaster::cursor_set_pos(const Point2 &p_pos, int p_cursor) {
-
-	ERR_FAIL_INDEX(p_cursor, MAX_CURSORS);
-	if (cursors[p_cursor].pos == p_pos)
-		return;
-	VS_CHANGED;
-	cursors[p_cursor].pos = p_pos;
-};
-
 void VisualServerRaster::black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) {
 void VisualServerRaster::black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) {
 
 
 	black_margin[MARGIN_LEFT] = p_left;
 	black_margin[MARGIN_LEFT] = p_left;
@@ -6925,24 +6892,6 @@ void VisualServerRaster::_draw_cursors_and_margins() {
 	rasterizer->canvas_begin();
 	rasterizer->canvas_begin();
 	rasterizer->canvas_begin_rect(Matrix32());
 	rasterizer->canvas_begin_rect(Matrix32());
 
 
-	for (int i = 0; i < MAX_CURSORS; i++) {
-
-		if (!cursors[i].visible) {
-
-			continue;
-		};
-
-		RID tex = cursors[i].texture ? cursors[i].texture : default_cursor_texture;
-		ERR_CONTINUE(!tex);
-		if (cursors[i].region.has_no_area()) {
-			Point2 size(texture_get_width(tex), texture_get_height(tex));
-			rasterizer->canvas_draw_rect(Rect2(cursors[i].pos - cursors[i].center, size), 0, Rect2(), tex, Color(1, 1, 1, 1));
-		} else {
-			Point2 size = cursors[i].region.size;
-			rasterizer->canvas_draw_rect(Rect2(cursors[i].pos - cursors[i].center, size), Rasterizer::CANVAS_RECT_REGION, cursors[i].region, tex, Color(1, 1, 1, 1));
-		}
-	};
-
 	if (black_image[MARGIN_LEFT].is_valid()) {
 	if (black_image[MARGIN_LEFT].is_valid()) {
 		Size2 sz(rasterizer->texture_get_width(black_image[MARGIN_LEFT]), rasterizer->texture_get_height(black_image[MARGIN_LEFT]));
 		Size2 sz(rasterizer->texture_get_width(black_image[MARGIN_LEFT]), rasterizer->texture_get_height(black_image[MARGIN_LEFT]));
 		rasterizer->canvas_draw_rect(Rect2(0, 0, black_margin[MARGIN_LEFT], window_h), 0, Rect2(0, 0, sz.x, sz.y), black_image[MARGIN_LEFT], Color(1, 1, 1));
 		rasterizer->canvas_draw_rect(Rect2(0, 0, black_margin[MARGIN_LEFT], window_h), 0, Rect2(0, 0, sz.x, sz.y), black_image[MARGIN_LEFT], Color(1, 1, 1));
@@ -7085,11 +7034,6 @@ void VisualServerRaster::init() {
 	for (int i = 0; i < 4; i++)
 	for (int i = 0; i < 4; i++)
 		black_margin[i] = 0;
 		black_margin[i] = 0;
 
 
-	Image img;
-	img.create(default_mouse_cursor_xpm);
-	//img.convert(Image::FORMAT_RGB);
-	default_cursor_texture = texture_create_from_image(img, 0);
-
 	aabb_random_points.resize(GLOBAL_DEF("render/aabb_random_points", 16));
 	aabb_random_points.resize(GLOBAL_DEF("render/aabb_random_points", 16));
 	for (int i = 0; i < aabb_random_points.size(); i++)
 	for (int i = 0; i < aabb_random_points.size(); i++)
 		aabb_random_points[i] = Vector3(Math::random(0, 1), Math::random(0, 1), Math::random(0, 1));
 		aabb_random_points[i] = Vector3(Math::random(0, 1), Math::random(0, 1), Math::random(0, 1));
@@ -7116,7 +7060,6 @@ void VisualServerRaster::_clean_up_owner(RID_OwnerBase *p_owner, String p_type)
 
 
 void VisualServerRaster::finish() {
 void VisualServerRaster::finish() {
 
 
-	free(default_cursor_texture);
 	if (test_cube.is_valid())
 	if (test_cube.is_valid())
 		free(test_cube);
 		free(test_cube);
 
 

+ 0 - 8
servers/visual/visual_server_raster.h

@@ -556,8 +556,6 @@ class VisualServerRaster : public VisualServer {
 
 
 	Rect2 canvas_clip;
 	Rect2 canvas_clip;
 	Color clear_color;
 	Color clear_color;
-	Cursor cursors[MAX_CURSORS];
-	RID default_cursor_texture;
 
 
 	static void *instance_pair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int);
 	static void *instance_pair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int);
 	static void instance_unpair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int, void *);
 	static void instance_unpair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int, void *);
@@ -1213,12 +1211,6 @@ public:
 	virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName &p_param) const;
 	virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName &p_param) const;
 	virtual void canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode);
 	virtual void canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode);
 
 
-	/* CURSOR */
-	virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0); // radians
-	virtual void cursor_set_texture(RID p_texture, const Point2 &p_center_offset, int p_cursor = 0, const Rect2 &p_region = Rect2());
-	virtual void cursor_set_visible(bool p_visible, int p_cursor = 0);
-	virtual void cursor_set_pos(const Point2 &p_pos, int p_cursor = 0);
-
 	/* BLACK BARS */
 	/* BLACK BARS */
 
 
 	virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom);
 	virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom);

+ 0 - 6
servers/visual/visual_server_wrap_mt.h

@@ -648,12 +648,6 @@ public:
 	FUNC2RC(Variant, canvas_item_material_get_shader_param, RID, const StringName &);
 	FUNC2RC(Variant, canvas_item_material_get_shader_param, RID, const StringName &);
 	FUNC2(canvas_item_material_set_shading_mode, RID, CanvasItemShadingMode);
 	FUNC2(canvas_item_material_set_shading_mode, RID, CanvasItemShadingMode);
 
 
-	/* CURSOR */
-	FUNC2(cursor_set_rotation, float, int); // radians
-	FUNC4(cursor_set_texture, RID, const Point2 &, int, const Rect2 &);
-	FUNC2(cursor_set_visible, bool, int);
-	FUNC2(cursor_set_pos, const Point2 &, int);
-
 	/* BLACK BARS */
 	/* BLACK BARS */
 
 
 	FUNC4(black_bars_set_margins, int, int, int, int);
 	FUNC4(black_bars_set_margins, int, int, int, int);

+ 0 - 5
servers/visual_server.cpp

@@ -522,11 +522,6 @@ void VisualServer::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("canvas_item_clear"), &VisualServer::canvas_item_clear);
 	ObjectTypeDB::bind_method(_MD("canvas_item_clear"), &VisualServer::canvas_item_clear);
 	ObjectTypeDB::bind_method(_MD("canvas_item_raise"), &VisualServer::canvas_item_raise);
 	ObjectTypeDB::bind_method(_MD("canvas_item_raise"), &VisualServer::canvas_item_raise);
 
 
-	ObjectTypeDB::bind_method(_MD("cursor_set_rotation"), &VisualServer::cursor_set_rotation);
-	ObjectTypeDB::bind_method(_MD("cursor_set_texture"), &VisualServer::cursor_set_texture);
-	ObjectTypeDB::bind_method(_MD("cursor_set_visible"), &VisualServer::cursor_set_visible);
-	ObjectTypeDB::bind_method(_MD("cursor_set_pos"), &VisualServer::cursor_set_pos);
-
 	ObjectTypeDB::bind_method(_MD("black_bars_set_margins", "left", "top", "right", "bottom"), &VisualServer::black_bars_set_margins);
 	ObjectTypeDB::bind_method(_MD("black_bars_set_margins", "left", "top", "right", "bottom"), &VisualServer::black_bars_set_margins);
 	ObjectTypeDB::bind_method(_MD("black_bars_set_images", "left", "top", "right", "bottom"), &VisualServer::black_bars_set_images);
 	ObjectTypeDB::bind_method(_MD("black_bars_set_images", "left", "top", "right", "bottom"), &VisualServer::black_bars_set_images);
 
 

+ 0 - 6
servers/visual_server.h

@@ -1068,12 +1068,6 @@ public:
 
 
 	virtual void canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode) = 0;
 	virtual void canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode) = 0;
 
 
-	/* CURSOR */
-	virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0) = 0; // radians
-	virtual void cursor_set_texture(RID p_texture, const Point2 &p_center_offset = Point2(0, 0), int p_cursor = 0, const Rect2 &p_region = Rect2()) = 0;
-	virtual void cursor_set_visible(bool p_visible, int p_cursor = 0) = 0;
-	virtual void cursor_set_pos(const Point2 &p_pos, int p_cursor = 0) = 0;
-
 	/* BLACK BARS */
 	/* BLACK BARS */
 
 
 	virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) = 0;
 	virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) = 0;