w32_common: show the cursor in the window border

When the cursor was in the window border, it could be hidden but it
wouldn't appear again, since mpv doesn't process mouse input there.

The code used ShowCursor, which is a horrid stateful API designed for
mouseless Win16 systems that incremented or decremented a global counter
to keep track of how many applications needed to display a special
cursor (like a busy cursor.) Replace that with a simple flag, handle
WM_SETCURSOR and use SetCursor(NULL) to hide the mouse cursor, but only
when the mouse is in the client area. DefWindowProc will set the correct
cursor on the border as long as it isn't hidden with ShowCursor.

PowerPoint also uses SetCursor(NULL) to hide the cursor when showing a
presentation, so it's probably safe.

See http://blogs.msdn.com/b/oldnewthing/archive/2009/12/17/9937972.aspx
This commit is contained in:
James Ross-Gowan 2013-07-14 22:57:39 +10:00 committed by wm4
parent 5f265d5930
commit d784759bc0
2 changed files with 22 additions and 6 deletions

View File

@ -221,6 +221,12 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
}
break;
}
case WM_SETCURSOR:
if (LOWORD(lParam) == HTCLIENT && !w32->cursor_visible) {
SetCursor(NULL);
return TRUE;
}
break;
case WM_MOUSEMOVE:
vo_mouse_movement(vo, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
@ -592,7 +598,7 @@ int vo_w32_init(struct vo *vo)
.lpfnWndProc = WndProc,
.hInstance = hInstance,
.hIcon = mplayerIcon,
.hCursor = LoadCursor(0, IDC_ARROW),
.hCursor = LoadCursor(NULL, IDC_ARROW),
.lpszClassName = classname,
.hIconSm = mplayerIcon,
};
@ -628,6 +634,7 @@ int vo_w32_init(struct vo *vo)
if (vo->opts->WinID >= 0)
EnableWindow(w32->window, 0);
w32->cursor_visible = true;
// we don't have proper event handling
vo->wakeup_period = 0.02;
@ -678,6 +685,12 @@ static void vo_w32_ontop(struct vo *vo)
reinit_window_state(vo);
}
static bool vo_w32_is_cursor_in_client(struct vo *vo)
{
DWORD pos = GetMessagePos();
return SendMessage(vo->w32->window, WM_NCHITTEST, 0, pos) == HTCLIENT;
}
int vo_w32_control(struct vo *vo, int *events, int request, void *arg)
{
struct vo_w32_state *w32 = vo->w32;
@ -700,10 +713,13 @@ int vo_w32_control(struct vo *vo, int *events, int request, void *arg)
w32_update_xinerama_info(vo);
return VO_TRUE;
case VOCTRL_SET_CURSOR_VISIBILITY:
if (*(bool *)arg) {
while (ShowCursor(1) < 0) { }
} else {
while (ShowCursor(0) >= 0) { }
w32->cursor_visible = *(bool *)arg;
if (vo_w32_is_cursor_in_client(vo)) {
if (w32->cursor_visible)
SetCursor(LoadCursor(NULL, IDC_ARROW));
else
SetCursor(NULL);
}
return VO_TRUE;
case VOCTRL_KILL_SCREENSAVER:
@ -737,7 +753,6 @@ void vo_w32_uninit(struct vo *vo)
mp_msg(MSGT_VO, MSGL_V, "vo: win32: uninit\n");
if (!w32)
return;
while (ShowCursor(1) < 0) { }
SetThreadExecutionState(ES_CONTINUOUS);
DestroyWindow(w32->window);
UnregisterClassW(classname, 0);

View File

@ -45,6 +45,7 @@ struct vo_w32_state {
uint32_t o_dheight;
bool disable_screensaver;
bool cursor_visible;
int event_flags;
int mon_cnt;
int mon_id;