mirror of
https://github.com/brl/mutter.git
synced 2024-11-29 11:30:45 -05:00
win32: Use an invisible cursor when cursor-visible is FALSE
The win32 backend now handles the WM_SETCURSOR message and sets a fully transparent cursor if the cursor-visible property has been cleared on the stage. The icon is stored in the library via a resource file. The instance handle for the DLL is needed to load the resource so there is now a DllMain function to grab the handle.
This commit is contained in:
parent
4db89759a0
commit
14a28620ae
@ -20,6 +20,23 @@ DISTCLEANFILES =
|
|||||||
EXTRA_DIST =
|
EXTRA_DIST =
|
||||||
BUILT_SOURCES =
|
BUILT_SOURCES =
|
||||||
|
|
||||||
|
if WINSYS_WIN32
|
||||||
|
|
||||||
|
# Ideally this resources stuff would go in win32/ but libtool doesn't
|
||||||
|
# seem to pass on the -Wl argument when linking a convenience library
|
||||||
|
# so we need to do it here as part of linking the dll. libtool also
|
||||||
|
# won't let you link against the .o directly because it wants you to
|
||||||
|
# link against libtool objects for dynamic libraries.
|
||||||
|
.rc.o :
|
||||||
|
$(WINDRES) -I$(srcdir)/win32 $< $@
|
||||||
|
|
||||||
|
win32/resources.o : $(srcdir)/win32/invisible-cursor.cur
|
||||||
|
|
||||||
|
win32_resources = win32/resources.o
|
||||||
|
win32_resources_ldflag = -Wl,win32/resources.o
|
||||||
|
|
||||||
|
endif # WINSYS_WIN32
|
||||||
|
|
||||||
INCLUDES = \
|
INCLUDES = \
|
||||||
-I$(top_srcdir) \
|
-I$(top_srcdir) \
|
||||||
-I$(top_srcdir)/clutter/cogl \
|
-I$(top_srcdir)/clutter/cogl \
|
||||||
@ -205,7 +222,8 @@ libclutter_@CLUTTER_WINSYS@_@CLUTTER_API_VERSION@_la_DEPENDENCIES = \
|
|||||||
$(top_builddir)/clutter/cogl/pango/libcoglpango.la \
|
$(top_builddir)/clutter/cogl/pango/libcoglpango.la \
|
||||||
$(top_builddir)/clutter/$(CLUTTER_WINSYS)/libclutter-$(CLUTTER_WINSYS).la \
|
$(top_builddir)/clutter/$(CLUTTER_WINSYS)/libclutter-$(CLUTTER_WINSYS).la \
|
||||||
$(clutter_json_dep) \
|
$(clutter_json_dep) \
|
||||||
$(CLUTTER_WINSYS_BASE_LIB)
|
$(CLUTTER_WINSYS_BASE_LIB) \
|
||||||
|
$(win32_resources)
|
||||||
|
|
||||||
libclutter_@CLUTTER_WINSYS@_@CLUTTER_API_VERSION@_la_SOURCES = \
|
libclutter_@CLUTTER_WINSYS@_@CLUTTER_API_VERSION@_la_SOURCES = \
|
||||||
$(source_c) \
|
$(source_c) \
|
||||||
@ -219,6 +237,7 @@ libclutter_@CLUTTER_WINSYS@_@CLUTTER_API_VERSION@_la_LDFLAGS = \
|
|||||||
-export-dynamic \
|
-export-dynamic \
|
||||||
-export-symbols-regex "^(clutter|cogl|json).*" \
|
-export-symbols-regex "^(clutter|cogl|json).*" \
|
||||||
-rpath $(libdir) \
|
-rpath $(libdir) \
|
||||||
|
$(win32_resources_ldflag) \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
lib_LTLIBRARIES = $(CLUTTER_WINSYS_LIB)
|
lib_LTLIBRARIES = $(CLUTTER_WINSYS_LIB)
|
||||||
|
@ -33,4 +33,4 @@ libclutter_win32_la_SOURCES = \
|
|||||||
|
|
||||||
CLEANFILES = clutter-win32-$(CLUTTER_API_VERSION).pc
|
CLEANFILES = clutter-win32-$(CLUTTER_API_VERSION).pc
|
||||||
|
|
||||||
EXTRA_DIST = clutter-win32.pc.in
|
EXTRA_DIST = clutter-win32.pc.in resources.rc invisible-cursor.cur
|
||||||
|
@ -47,6 +47,8 @@ static ClutterBackendWin32 *backend_singleton = NULL;
|
|||||||
|
|
||||||
static gchar *clutter_vblank_name = NULL;
|
static gchar *clutter_vblank_name = NULL;
|
||||||
|
|
||||||
|
static HINSTANCE clutter_hinst = NULL;
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
clutter_backend_win32_pre_parse (ClutterBackend *backend,
|
clutter_backend_win32_pre_parse (ClutterBackend *backend,
|
||||||
GError **error)
|
GError **error)
|
||||||
@ -67,6 +69,18 @@ clutter_backend_win32_init_events (ClutterBackend *backend)
|
|||||||
_clutter_backend_win32_events_init (backend);
|
_clutter_backend_win32_events_init (backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HCURSOR
|
||||||
|
_clutter_backend_win32_get_invisible_cursor (ClutterBackend *backend)
|
||||||
|
{
|
||||||
|
ClutterBackendWin32 *backend_win32 = CLUTTER_BACKEND_WIN32 (backend);
|
||||||
|
|
||||||
|
if (backend_win32->invisible_cursor == NULL)
|
||||||
|
backend_win32->invisible_cursor =
|
||||||
|
LoadCursor (clutter_hinst, MAKEINTRESOURCE (42));
|
||||||
|
|
||||||
|
return backend_win32->invisible_cursor;
|
||||||
|
}
|
||||||
|
|
||||||
static const GOptionEntry entries[] =
|
static const GOptionEntry entries[] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@ -353,6 +367,7 @@ clutter_backend_win32_init (ClutterBackendWin32 *backend_win32)
|
|||||||
|
|
||||||
backend_win32->gl_context = NULL;
|
backend_win32->gl_context = NULL;
|
||||||
backend_win32->no_event_retrieval = FALSE;
|
backend_win32->no_event_retrieval = FALSE;
|
||||||
|
backend_win32->invisible_cursor = NULL;
|
||||||
|
|
||||||
/* FIXME: get from GetSystemMetric? */
|
/* FIXME: get from GetSystemMetric? */
|
||||||
clutter_backend_set_double_click_time (backend, 250);
|
clutter_backend_set_double_click_time (backend, 250);
|
||||||
@ -370,3 +385,13 @@ _clutter_backend_impl_get_type (void)
|
|||||||
{
|
{
|
||||||
return clutter_backend_win32_get_type ();
|
return clutter_backend_win32_get_type ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI
|
||||||
|
DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved)
|
||||||
|
{
|
||||||
|
if (reason == DLL_PROCESS_ATTACH)
|
||||||
|
/* Store the module handle so that we can use it to load resources */
|
||||||
|
clutter_hinst = hinst;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
@ -48,6 +48,8 @@ struct _ClutterBackendWin32
|
|||||||
HGLRC gl_context;
|
HGLRC gl_context;
|
||||||
gboolean no_event_retrieval;
|
gboolean no_event_retrieval;
|
||||||
|
|
||||||
|
HCURSOR invisible_cursor;
|
||||||
|
|
||||||
GSource *event_source;
|
GSource *event_source;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -68,6 +70,8 @@ clutter_backend_win32_add_options (ClutterBackend *backend,
|
|||||||
ClutterFeatureFlags
|
ClutterFeatureFlags
|
||||||
clutter_backend_win32_get_features (ClutterBackend *backend);
|
clutter_backend_win32_get_features (ClutterBackend *backend);
|
||||||
|
|
||||||
|
HCURSOR _clutter_backend_win32_get_invisible_cursor (ClutterBackend *backend);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_BACKEND_WIN32_H__ */
|
#endif /* __CLUTTER_BACKEND_WIN32_H__ */
|
||||||
|
@ -616,6 +616,20 @@ message_translate (ClutterBackend *backend,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WM_SETCURSOR:
|
||||||
|
/* If the cursor is in the window's client area and the stage's
|
||||||
|
cursor should be invisible then we'll set a blank cursor
|
||||||
|
instead */
|
||||||
|
if (LOWORD (msg->lParam) == HTCLIENT && !stage_win32->is_cursor_visible)
|
||||||
|
{
|
||||||
|
if (call_def_window_proc)
|
||||||
|
*call_def_window_proc = FALSE;
|
||||||
|
_clutter_stage_win32_update_cursor (stage_win32);
|
||||||
|
}
|
||||||
|
|
||||||
|
res = FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* ignore every other message */
|
/* ignore every other message */
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
|
@ -216,17 +216,51 @@ clutter_stage_win32_set_title (ClutterStageWindow *stage_window,
|
|||||||
SetWindowTextW (stage_win32->hwnd, stage_win32->wtitle);
|
SetWindowTextW (stage_win32->hwnd, stage_win32->wtitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_stage_win32_update_cursor (ClutterStageWin32 *stage_win32)
|
||||||
|
{
|
||||||
|
HCURSOR cursor;
|
||||||
|
|
||||||
|
if (stage_win32->is_cursor_visible)
|
||||||
|
cursor = (HCURSOR) GetClassLongPtrW (stage_win32->hwnd, GCL_HCURSOR);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ClutterBackend *backend = clutter_get_default_backend ();
|
||||||
|
/* The documentation implies that we can just use
|
||||||
|
SetCursor(NULL) to get rid of the cursor but apparently this
|
||||||
|
doesn't work very well so instead we create an invisible
|
||||||
|
cursor */
|
||||||
|
cursor = _clutter_backend_win32_get_invisible_cursor (backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetCursor (cursor);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_stage_win32_set_cursor_visible (ClutterStageWindow *stage_window,
|
clutter_stage_win32_set_cursor_visible (ClutterStageWindow *stage_window,
|
||||||
gboolean cursor_visible)
|
gboolean cursor_visible)
|
||||||
{
|
{
|
||||||
ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window);
|
ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window);
|
||||||
|
|
||||||
if (stage_win32->is_cursor_visible != cursor_visible &&
|
if (stage_win32->is_cursor_visible != cursor_visible)
|
||||||
stage_win32->tracking_mouse)
|
{
|
||||||
ShowCursor (cursor_visible);
|
POINT cursor_pos;
|
||||||
|
RECT client_rect;
|
||||||
|
|
||||||
stage_win32->is_cursor_visible = cursor_visible;
|
stage_win32->is_cursor_visible = cursor_visible;
|
||||||
|
|
||||||
|
/* If the cursor is already over the client area of the window
|
||||||
|
then we need to update it immediately */
|
||||||
|
GetCursorPos (&cursor_pos);
|
||||||
|
if (WindowFromPoint (cursor_pos) == stage_win32->hwnd &&
|
||||||
|
ScreenToClient (stage_win32->hwnd, &cursor_pos) &&
|
||||||
|
GetClientRect (stage_win32->hwnd, &client_rect) &&
|
||||||
|
cursor_pos.x >= client_rect.left &&
|
||||||
|
cursor_pos.y >= client_rect.top &&
|
||||||
|
cursor_pos.x < client_rect.right &&
|
||||||
|
cursor_pos.y < client_rect.bottom)
|
||||||
|
_clutter_stage_win32_update_cursor (stage_win32);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static LONG
|
static LONG
|
||||||
|
@ -80,6 +80,8 @@ LRESULT CALLBACK _clutter_stage_win32_window_proc (HWND hwnd,
|
|||||||
void _clutter_stage_win32_get_min_max_info (ClutterStageWin32 *stage_win32,
|
void _clutter_stage_win32_get_min_max_info (ClutterStageWin32 *stage_win32,
|
||||||
MINMAXINFO *min_max_info);
|
MINMAXINFO *min_max_info);
|
||||||
|
|
||||||
|
void _clutter_stage_win32_update_cursor (ClutterStageWin32 *stage_win32);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_STAGE_H__ */
|
#endif /* __CLUTTER_STAGE_H__ */
|
||||||
|
BIN
clutter/win32/invisible-cursor.cur
Normal file
BIN
clutter/win32/invisible-cursor.cur
Normal file
Binary file not shown.
After Width: | Height: | Size: 86 B |
1
clutter/win32/resources.rc
Normal file
1
clutter/win32/resources.rc
Normal file
@ -0,0 +1 @@
|
|||||||
|
42 CURSOR "invisible-cursor.cur"
|
@ -364,11 +364,18 @@ AS_CASE([$CLUTTER_WINSYS],
|
|||||||
WIN32_CFLAGS="-D_WIN32_WINNT=0x0500"
|
WIN32_CFLAGS="-D_WIN32_WINNT=0x0500"
|
||||||
WIN32_LIBS="-lopengl32 -lgdi32 -lwinmm"
|
WIN32_LIBS="-lopengl32 -lgdi32 -lwinmm"
|
||||||
CLUTTER_LT_LDFLAGS="$CLUTTER_LT_LDFLAGS -no-undefined"
|
CLUTTER_LT_LDFLAGS="$CLUTTER_LT_LDFLAGS -no-undefined"
|
||||||
|
|
||||||
|
AC_CHECK_TOOL(WINDRES, windres, no)
|
||||||
|
if test "$WINDRES" = no; then
|
||||||
|
AC_MSG_ERROR([*** windres is required])
|
||||||
|
fi
|
||||||
],
|
],
|
||||||
|
|
||||||
[AC_MSG_ERROR([Invalid backend for Clutter: use glx, sdl, osx, win32, eglx, eglnative or fruity])]
|
[AC_MSG_ERROR([Invalid backend for Clutter: use glx, sdl, osx, win32, eglx, eglnative or fruity])]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
AM_CONDITIONAL(WINSYS_WIN32, [test "x$CLUTTER_WINSYS" = "xwin32"])
|
||||||
|
|
||||||
# at this point we must have a GL header to check
|
# at this point we must have a GL header to check
|
||||||
AS_IF([test "x$clutter_gl_header" = "x"], [AC_MSG_ERROR([Internal error: no GL header set])])
|
AS_IF([test "x$clutter_gl_header" = "x"], [AC_MSG_ERROR([Internal error: no GL header set])])
|
||||||
AC_CHECK_HEADERS([$clutter_gl_header],
|
AC_CHECK_HEADERS([$clutter_gl_header],
|
||||||
|
Loading…
Reference in New Issue
Block a user