Fix cursor inheritance and busy cursor/global cursor, closes #15801

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@75690 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Paul Cornett
2014-01-23 18:27:13 +00:00
parent 7df4846118
commit 9f09241cd0
7 changed files with 117 additions and 95 deletions

View File

@@ -308,59 +308,18 @@ wxCursor::CloneGDIRefData(const wxGDIRefData * WXUNUSED(data)) const
// busy cursor routines
//-----------------------------------------------------------------------------
/* Current cursor, in order to hang on to
* cursor handle when setting the cursor globally */
wxCursor g_globalCursor;
static wxCursor gs_savedCursor;
static int gs_busyCount = 0;
const wxCursor &wxBusyCursor::GetStoredCursor()
void wxBeginBusyCursor(const wxCursor* cursor)
{
return gs_savedCursor;
}
const wxCursor wxBusyCursor::GetBusyCursor()
{
return wxCursor(wxCURSOR_WATCH);
}
static void UpdateCursors(GdkDisplay** display)
{
wxWindowList::const_iterator i = wxTopLevelWindows.begin();
for (size_t n = wxTopLevelWindows.size(); n--; ++i)
{
wxWindow* win = *i;
win->GTKUpdateCursor();
if (display && *display == NULL && win->m_widget)
*display = gtk_widget_get_display(win->m_widget);
}
if (gs_busyCount++ == 0)
wxSetCursor(*cursor);
}
void wxEndBusyCursor()
{
if (--gs_busyCount > 0)
return;
g_globalCursor = gs_savedCursor;
gs_savedCursor = wxNullCursor;
UpdateCursors(NULL);
}
void wxBeginBusyCursor(const wxCursor* cursor)
{
if (gs_busyCount++ > 0)
return;
wxASSERT_MSG( !gs_savedCursor.IsOk(),
wxT("forgot to call wxEndBusyCursor, will leak memory") );
gs_savedCursor = g_globalCursor;
g_globalCursor = *cursor;
GdkDisplay* display = NULL;
UpdateCursors(&display);
if (display)
gdk_display_flush(display);
if (gs_busyCount && --gs_busyCount == 0)
wxSetCursor(wxCursor());
}
bool wxIsBusy()
@@ -368,8 +327,94 @@ bool wxIsBusy()
return gs_busyCount > 0;
}
// Table holding non-default cursors to be restored when global cursor is unset
WX_DECLARE_HASH_MAP(GdkWindow*, GdkCursor*, wxPointerHash, wxPointerEqual, wxGdkWindowGdkCursorMapBase);
class wxGdkWindowGdkCursorMap: public wxGdkWindowGdkCursorMapBase
{
public:
~wxGdkWindowGdkCursorMap();
};
static wxGdkWindowGdkCursorMap* gs_windowCursorMap;
wxGdkWindowGdkCursorMap::~wxGdkWindowGdkCursorMap()
{
const_iterator i = begin();
for (size_t n = size(); n--; ++i)
{
#ifdef __WXGTK3__
g_object_unref(i->second);
#else
gdk_cursor_unref(i->second);
#endif
}
}
// Set cursor to default for window and all its children,
// recording non-default cursors in gs_windowCursorMap
static void clearCursors(GdkWindow* window)
{
GdkCursor* cursor = gdk_window_get_cursor(window);
if (cursor)
{
#ifdef __WXGTK3__
g_object_ref(cursor);
#else
gdk_cursor_ref(cursor);
#endif
(*gs_windowCursorMap)[window] = cursor;
gdk_window_set_cursor(window, NULL);
}
for (const GList* p = gdk_window_peek_children(window); p; p = p->next)
clearCursors(static_cast<GdkWindow*>(p->data));
}
// Restore non-default cursors
static void restoreCursors(GdkWindow* window)
{
wxGdkWindowGdkCursorMap::const_iterator i = gs_windowCursorMap->find(window);
if (i != gs_windowCursorMap->end())
gdk_window_set_cursor(window, i->second);
for (const GList* p = gdk_window_peek_children(window); p; p = p->next)
restoreCursors(static_cast<GdkWindow*>(p->data));
}
void wxSetCursor( const wxCursor& cursor )
{
g_globalCursor = cursor;
UpdateCursors(NULL);
GdkDisplay* display = NULL;
wxWindowList::const_iterator i = wxTopLevelWindows.begin();
for (size_t n = wxTopLevelWindows.size(); n--; ++i)
{
GtkWidget* widget = (*i)->m_widget;
GdkWindow* window;
if (widget && (window = gtk_widget_get_window(widget)))
{
// if setting global cursor
if (cursor.IsOk())
{
delete gs_windowCursorMap;
gs_windowCursorMap = new wxGdkWindowGdkCursorMap;
// clear all cursors, saving non-default ones for later
clearCursors(window);
// set global cursor
wxASSERT(gdk_window_get_cursor(window) == NULL);
gdk_window_set_cursor(window, cursor.GetCursor());
}
else
{
// remove global cursor
gdk_window_set_cursor(window, NULL);
if (gs_windowCursorMap)
{
// restore non-default cursors
restoreCursors(window);
delete gs_windowCursorMap;
gs_windowCursorMap = NULL;
}
}
if (display == NULL)
display = gdk_window_get_display(window);
}
}
if (display)
gdk_display_flush(display);
}