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 =
|
||||
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 = \
|
||||
-I$(top_srcdir) \
|
||||
-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/$(CLUTTER_WINSYS)/libclutter-$(CLUTTER_WINSYS).la \
|
||||
$(clutter_json_dep) \
|
||||
$(CLUTTER_WINSYS_BASE_LIB)
|
||||
$(CLUTTER_WINSYS_BASE_LIB) \
|
||||
$(win32_resources)
|
||||
|
||||
libclutter_@CLUTTER_WINSYS@_@CLUTTER_API_VERSION@_la_SOURCES = \
|
||||
$(source_c) \
|
||||
@ -219,6 +237,7 @@ libclutter_@CLUTTER_WINSYS@_@CLUTTER_API_VERSION@_la_LDFLAGS = \
|
||||
-export-dynamic \
|
||||
-export-symbols-regex "^(clutter|cogl|json).*" \
|
||||
-rpath $(libdir) \
|
||||
$(win32_resources_ldflag) \
|
||||
$(NULL)
|
||||
|
||||
lib_LTLIBRARIES = $(CLUTTER_WINSYS_LIB)
|
||||
|
@ -33,4 +33,4 @@ libclutter_win32_la_SOURCES = \
|
||||
|
||||
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 HINSTANCE clutter_hinst = NULL;
|
||||
|
||||
gboolean
|
||||
clutter_backend_win32_pre_parse (ClutterBackend *backend,
|
||||
GError **error)
|
||||
@ -67,6 +69,18 @@ clutter_backend_win32_init_events (ClutterBackend *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[] =
|
||||
{
|
||||
{
|
||||
@ -353,6 +367,7 @@ clutter_backend_win32_init (ClutterBackendWin32 *backend_win32)
|
||||
|
||||
backend_win32->gl_context = NULL;
|
||||
backend_win32->no_event_retrieval = FALSE;
|
||||
backend_win32->invisible_cursor = NULL;
|
||||
|
||||
/* FIXME: get from GetSystemMetric? */
|
||||
clutter_backend_set_double_click_time (backend, 250);
|
||||
@ -370,3 +385,13 @@ _clutter_backend_impl_get_type (void)
|
||||
{
|
||||
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;
|
||||
gboolean no_event_retrieval;
|
||||
|
||||
HCURSOR invisible_cursor;
|
||||
|
||||
GSource *event_source;
|
||||
};
|
||||
|
||||
@ -68,6 +70,8 @@ clutter_backend_win32_add_options (ClutterBackend *backend,
|
||||
ClutterFeatureFlags
|
||||
clutter_backend_win32_get_features (ClutterBackend *backend);
|
||||
|
||||
HCURSOR _clutter_backend_win32_get_invisible_cursor (ClutterBackend *backend);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_BACKEND_WIN32_H__ */
|
||||
|
@ -616,6 +616,20 @@ message_translate (ClutterBackend *backend,
|
||||
}
|
||||
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:
|
||||
/* ignore every other message */
|
||||
res = FALSE;
|
||||
|
@ -216,17 +216,51 @@ clutter_stage_win32_set_title (ClutterStageWindow *stage_window,
|
||||
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
|
||||
clutter_stage_win32_set_cursor_visible (ClutterStageWindow *stage_window,
|
||||
gboolean cursor_visible)
|
||||
{
|
||||
ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window);
|
||||
|
||||
if (stage_win32->is_cursor_visible != cursor_visible &&
|
||||
stage_win32->tracking_mouse)
|
||||
ShowCursor (cursor_visible);
|
||||
if (stage_win32->is_cursor_visible != 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
|
||||
|
@ -80,6 +80,8 @@ LRESULT CALLBACK _clutter_stage_win32_window_proc (HWND hwnd,
|
||||
void _clutter_stage_win32_get_min_max_info (ClutterStageWin32 *stage_win32,
|
||||
MINMAXINFO *min_max_info);
|
||||
|
||||
void _clutter_stage_win32_update_cursor (ClutterStageWin32 *stage_win32);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#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_LIBS="-lopengl32 -lgdi32 -lwinmm"
|
||||
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])]
|
||||
)
|
||||
|
||||
AM_CONDITIONAL(WINSYS_WIN32, [test "x$CLUTTER_WINSYS" = "xwin32"])
|
||||
|
||||
# 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])])
|
||||
AC_CHECK_HEADERS([$clutter_gl_header],
|
||||
|
Loading…
Reference in New Issue
Block a user