(svn r4075) - Feature: Undraw the mouse when it leaves the window and Draw it again when it enters. Added both for WIN32 and SDL. Since Win95 has troubles with TrackMouseEvent(), this function was just simply rewritten which was the easiest. Based on a patch by DmitryKo.
authorDarkvater
Fri, 24 Mar 2006 00:42:35 +0000
changeset 3312 593789444b01
parent 3311 56c1c502ff6d
child 3313 767d77394c61
(svn r4075) - Feature: Undraw the mouse when it leaves the window and Draw it again when it enters. Added both for WIN32 and SDL. Since Win95 has troubles with TrackMouseEvent(), this function was just simply rewritten which was the easiest. Based on a patch by DmitryKo.
gfx.c
gfx.h
openttd.c
video/sdl_v.c
video/win32_v.c
--- a/gfx.c	Thu Mar 23 23:54:43 2006 +0000
+++ b/gfx.c	Fri Mar 24 00:42:35 2006 +0000
@@ -1654,6 +1654,9 @@
 	int w;
 	int h;
 
+	/* Redraw mouse cursor but only when it's inside the window */
+	if (!_cursor.in_window) return;
+
 	// Don't draw the mouse cursor if it's already drawn
 	if (_cursor.visible) {
 		if (!_cursor.dirty) return;
--- a/gfx.h	Thu Mar 23 23:54:43 2006 +0000
+++ b/gfx.h	Fri Mar 24 00:42:35 2006 +0000
@@ -21,17 +21,18 @@
 
 
 typedef struct CursorVars {
-	Point pos, size, offs, delta;
-	Point draw_pos, draw_size;
-	CursorID sprite;
+	Point pos, size, offs, delta; ///< position, size, offset from top-left, and movement
+	Point draw_pos, draw_size;    ///< position and size bounding-box for drawing
+	CursorID sprite; ///< current image of cursor
 
-	int wheel; // mouse wheel movement
-	const CursorID *animate_list, *animate_cur;
-	uint animate_timeout;
+	int wheel;       ///< mouse wheel movement
+	const CursorID *animate_list, *animate_cur; ///< in case of animated cursor, list of frames
+	uint animate_timeout;                       ///< current frame in list of animated cursor
 
-	bool visible;
-	bool dirty;
-	bool fix_at;
+	bool visible;    ///< cursor is visible
+	bool dirty;      ///< the rect occupied by the mouse is dirty (redraw)
+	bool fix_at;     ///< mouse is moving, but cursor is not (used for scrolling)
+	bool in_window;  ///< mouse inside this window, determines drawing logic
 } CursorVars;
 
 
--- a/openttd.c	Thu Mar 23 23:54:43 2006 +0000
+++ b/openttd.c	Fri Mar 24 00:42:35 2006 +0000
@@ -450,6 +450,7 @@
 
 	// initialize the ingame console
 	IConsoleInit();
+	_cursor.in_window = true;
 	InitializeGUI();
 	IConsoleCmdExec("exec scripts/autoexec.scr 0");
 
--- a/video/sdl_v.c	Thu Mar 23 23:54:43 2006 +0000
+++ b/video/sdl_v.c	Fri Mar 24 00:42:35 2006 +0000
@@ -345,6 +345,15 @@
 		}
 		break;
 
+	case SDL_ACTIVEEVENT:
+		if (ev.active.gain == 1) // mouse entered the window, enable cursor
+			_cursor.in_window = true;
+		else if (ev.active.gain == 0) {
+			UndrawMouseCursor(); // mouse left the window, undraw cursor
+			_cursor.in_window = false;
+		}
+		break;
+
 	case SDL_QUIT:
 		// do not ask to quit on the main screen
 		if (_game_mode != GM_MENU) {
--- a/video/win32_v.c	Thu Mar 23 23:54:43 2006 +0000
+++ b/video/win32_v.c	Fri Mar 24 00:42:35 2006 +0000
@@ -184,9 +184,40 @@
 }
 #endif
 
+/* Windows 95 will not have a WM_MOUSELEAVE message, so define it if
+ * needed. There is no such event as WM_MOUSEENTER, we just made this up :) */
+#define WM_MOUSEENTER WM_USER + 1
+#if !defined(WM_MOUSELEAVE)
+#define WM_MOUSELEAVE 0x02A3
+#endif
+#define TID_POLLMOUSE 1
+#define MOUSE_POLL_DELAY 75
+
+static void CALLBACK TrackMouseTimerProc(HWND hwnd, UINT msg, UINT event, DWORD time)
+{
+	RECT rc;
+	POINT pt;
+
+	/* Get the rectangle of our window and translate it to screen coordinates.
+	 * Compare this with the current screen coordinates of the mouse and if it
+	 * falls outside of the area or our window we have left the window. */
+	GetClientRect(hwnd, &rc);
+	MapWindowPoints(hwnd, HWND_DESKTOP, (LPPOINT)&rc, 2);
+	GetCursorPos(&pt);
+
+	if (!PtInRect(&rc, pt) || (WindowFromPoint(pt) != hwnd)) {
+		KillTimer(hwnd, event);
+		PostMessage(hwnd, WM_MOUSELEAVE, 0, 0L);
+	}
+}
+
 static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
 	switch (msg) {
+	case WM_CREATE:
+		SetTimer(hwnd, TID_POLLMOUSE, MOUSE_POLL_DELAY, (TIMERPROC)TrackMouseTimerProc);
+		break;
+
 	case WM_PAINT: {
 		PAINTSTRUCT ps;
 		HDC dc,dc2;
@@ -259,11 +290,33 @@
 		_right_button_down = false;
 		return 0;
 
+	case WM_MOUSEENTER:
+		printf("enter\n");
+		_cursor.in_window = true;
+		DrawMouseCursor();
+		break;
+
+	case WM_MOUSELEAVE:
+		printf("enter\n");
+		UndrawMouseCursor();
+		_cursor.in_window = false;
+		break;
+
 	case WM_MOUSEMOVE: {
 		int x = (int16)LOWORD(lParam);
 		int y = (int16)HIWORD(lParam);
 		POINT pt;
 
+		/* If the mouse was not in the window and it has moved it means it has
+		 * come into the window, so send a WM_MOUSEENTER message. Also start
+		 * tracking the mouse for exiting the window */
+		if (!_cursor.in_window) {
+			_cursor.in_window = true;
+			SetTimer(hwnd, TID_POLLMOUSE, MOUSE_POLL_DELAY, (TIMERPROC)TrackMouseTimerProc);
+
+			if (hwnd != GetCapture()) PostMessage(hwnd, WM_MOUSEENTER, 0, 0L);
+		}
+
 		if (_wnd.double_size) {
 			x /= 2;
 			y /= 2;