Browse Source

Implemented method for setting the cursor position, with many warnings.

David Piuva 2 years ago
parent
commit
0437615866

+ 5 - 0
Source/DFPSR/api/guiAPI.cpp

@@ -168,6 +168,11 @@ bool dsr::window_getCursorVisibility(const Window& window) {
 	return window->backend->visibleCursor;
 	return window->backend->visibleCursor;
 }
 }
 
 
+void dsr::window_setCursorPosition(const Window& window, int x, int y) {
+	MUST_EXIST(window, window_setCursorPosition);
+	window->backend->setCursorPosition(x, y);
+}
+
 void dsr::window_setFullScreen(const Window& window, bool enabled) {
 void dsr::window_setFullScreen(const Window& window, bool enabled) {
 	MUST_EXIST(window, window_setFullScreen);
 	MUST_EXIST(window, window_setFullScreen);
 	window->setFullScreen(enabled);
 	window->setFullScreen(enabled);

+ 21 - 0
Source/DFPSR/api/guiAPI.h

@@ -131,6 +131,27 @@ namespace dsr {
 	bool window_setCursorVisibility(const Window& window, bool visible);
 	bool window_setCursorVisibility(const Window& window, bool visible);
 	// Returns true iff the cursor is allowed to be displayed over window.
 	// Returns true iff the cursor is allowed to be displayed over window.
 	bool window_getCursorVisibility(const Window& window);
 	bool window_getCursorVisibility(const Window& window);
+	// Tries move the cursor so that its active point is at (x, y) within window.
+	//   To get back the new cursor location and see if it worked, you must wait for the triggered mouse move event.
+	//   It is impossible to know if the operation succeeded while returning, due to absolute position input devices overwriting the side-effect.
+	// It is recommended to avoid this method if you can, but some games require capturing relative mouse movements.
+	//   If you use this then make sure to test it carefully on all targeted operating systems and both relative and absolute input devices.
+	// Pre-conditions:
+	//   0 <= x < width
+	//   0 <= y < height
+	//   Moving the mouse outside of the window's region may cause undefined behavior between platforms.
+	// WARNING!
+	//   Only set the cursor location if you know for sure that the cursor is controlled using relative input devices, such as a mouse or track-pad.
+	//   If an absolute input method is used, such as a stylus-pen, touch-screen or eye-tracker, the cursor will shake quickly.
+	//   The solution is to let the user select between modes for relative and absolute inputs.
+	//   You can for example let absolute input mode move the cursor freely within a dead zone and hover over edges
+	//   to rotate the camera itself, when pattern detection noticed a stylus pen being used instead of a mouse.
+	// WARNING!
+	//   On MS-Windows the cursor will always move, but on X11 the cursor must be within the window's region.
+	//   Only use this in full-screen mode to prevent getting stuck outside of the window.
+	// WARNING!
+	//   Due to potential race-conditions, you can not assume that the next mouse move event is generated by this call.
+	void window_setCursorPosition(const Window& window, int x, int y);
 
 
 // Full screen
 // Full screen
 	void window_setFullScreen(const Window& window, bool enabled);
 	void window_setFullScreen(const Window& window, bool enabled);

+ 1 - 0
Source/DFPSR/gui/BackendWindow.h

@@ -84,6 +84,7 @@ public:
 	// Cursor interface
 	// Cursor interface
 	bool visibleCursor = true; // Written to by setCursorVisibility on success.
 	bool visibleCursor = true; // Written to by setCursorVisibility on success.
 	virtual bool setCursorVisibility(bool visible) { return false; } // Returns true on success.
 	virtual bool setCursorVisibility(bool visible) { return false; } // Returns true on success.
+	virtual void setCursorPosition(int x, int y) {} // Does nothing unless implemented.
 public:
 public:
 	// Each callback declaration has a public variable and a public getter and setter
 	// Each callback declaration has a public variable and a public getter and setter
 	DECLARE_CALLBACK(closeEvent, emptyCallback);
 	DECLARE_CALLBACK(closeEvent, emptyCallback);

+ 9 - 0
Source/windowManagers/Win32Window.cpp

@@ -36,6 +36,9 @@ private:
 
 
 	// Called to change the cursor visibility and returning true on success
 	// Called to change the cursor visibility and returning true on success
 	bool setCursorVisibility(bool visible) override;
 	bool setCursorVisibility(bool visible) override;
+
+	// Place the cursor within the window
+	void setCursorPosition(int x, int y) override;
 private:
 private:
 	// Helper methods specific to calling XLib
 	// Helper methods specific to calling XLib
 	void updateTitle();
 	void updateTitle();
@@ -78,6 +81,12 @@ void Win32Window::updateTitle() {
 	}
 	}
 }
 }
 
 
+void Win32Window::setCursorPosition(int x, int y) {
+	POINT point; point.x = x; point.y = y;
+	ClientToScreen(this->hwnd, &point);
+	SetCursorPos(point.x, point.y);
+}
+
 bool Win32Window::setCursorVisibility(bool visible) {
 bool Win32Window::setCursorVisibility(bool visible) {
 	// Remember the cursor's visibility for anyone asking
 	// Remember the cursor's visibility for anyone asking
 	this->visibleCursor = visible;
 	this->visibleCursor = visible;

+ 9 - 0
Source/windowManagers/X11Window.cpp

@@ -59,6 +59,9 @@ private:
 	// Called to change the cursor visibility and returning true on success
 	// Called to change the cursor visibility and returning true on success
 	bool setCursorVisibility(bool visible) override;
 	bool setCursorVisibility(bool visible) override;
 
 
+	// Place the cursor within the window
+	void setCursorPosition(int x, int y) override;
+
 	// Color format
 	// Color format
 	dsr::PackOrderIndex packOrderIndex = dsr::PackOrderIndex::RGBA;
 	dsr::PackOrderIndex packOrderIndex = dsr::PackOrderIndex::RGBA;
 	dsr::PackOrderIndex getColorFormat_locked();
 	dsr::PackOrderIndex getColorFormat_locked();
@@ -94,6 +97,12 @@ public:
 	void showCanvas() override;
 	void showCanvas() override;
 };
 };
 
 
+void X11Window::setCursorPosition(int x, int y) {
+	windowLock.lock();
+		XWarpPointer(this->display, this->window, this->window, 0, 0, this->windowWidth, this->windowHeight, x, y);
+	windowLock.unlock();
+}
+
 bool X11Window::setCursorVisibility(bool visible) {
 bool X11Window::setCursorVisibility(bool visible) {
 	windowLock.lock();
 	windowLock.lock();
 		if (visible) {
 		if (visible) {