Different fix for cursor inheritance and busy cursor/global cursor.

Previous work was not compatible with GTK < 2.18 and did not properly handle some cases
see #15801


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@75807 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Paul Cornett
2014-02-06 04:43:46 +00:00
parent 5e6d30aa0b
commit 0dfeb74e78
5 changed files with 106 additions and 112 deletions

View File

@@ -283,7 +283,10 @@ void wxCursor::InitFromImage( const wxImage & image )
GdkCursor *wxCursor::GetCursor() const
{
return M_CURSORDATA->m_cursor;
GdkCursor* cursor = NULL;
if (m_refData)
cursor = M_CURSORDATA->m_cursor;
return cursor;
}
wxGDIRefData *wxCursor::CreateGDIRefData() const
@@ -308,108 +311,43 @@ wxCursor::CloneGDIRefData(const wxGDIRefData * WXUNUSED(data)) const
// busy cursor routines
//-----------------------------------------------------------------------------
wxCursor g_globalCursor;
wxCursor g_busyCursor;
static wxCursor gs_storedCursor;
static int gs_busyCount = 0;
void wxBeginBusyCursor(const wxCursor* cursor)
const wxCursor& wxBusyCursor::GetStoredCursor()
{
if (gs_busyCount++ == 0)
wxSetCursor(*cursor);
return gs_storedCursor;
}
void wxEndBusyCursor()
const wxCursor wxBusyCursor::GetBusyCursor()
{
if (gs_busyCount && --gs_busyCount == 0)
wxSetCursor(wxCursor());
return g_busyCursor;
}
bool wxIsBusy()
static void UpdateCursors(wxWindow* win, bool isBusyOrGlobalCursor)
{
return gs_busyCount > 0;
win->GTKUpdateCursor(isBusyOrGlobalCursor);
const wxWindowList& children = win->GetChildren();
wxWindowList::const_iterator i = children.begin();
for (size_t n = children.size(); n--; ++i)
UpdateCursors(*i, isBusyOrGlobalCursor);
}
// 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 )
static void SetGlobalCursor(const wxCursor& cursor)
{
GdkCursor* gdk_cursor = cursor.GetCursor();
GdkDisplay* display = NULL;
wxWindowList::const_iterator i = wxTopLevelWindows.begin();
for (size_t n = wxTopLevelWindows.size(); n--; ++i)
{
GtkWidget* widget = (*i)->m_widget;
wxWindow* win = *i;
GdkWindow* window;
if (widget && (window = gtk_widget_get_window(widget)))
if (win->m_widget && (window = gtk_widget_get_window(win->m_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
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;
}
}
gdk_window_set_cursor(window, gdk_cursor);
UpdateCursors(win, gdk_cursor != NULL);
if (display == NULL)
display = gdk_window_get_display(window);
}
@@ -417,3 +355,35 @@ void wxSetCursor( const wxCursor& cursor )
if (display)
gdk_display_flush(display);
}
void wxBeginBusyCursor(const wxCursor* cursor)
{
if (gs_busyCount++ == 0)
{
g_busyCursor = *cursor;
gs_storedCursor = g_globalCursor;
SetGlobalCursor(*cursor);
}
}
void wxEndBusyCursor()
{
if (gs_busyCount && --gs_busyCount == 0)
{
g_globalCursor = gs_storedCursor;
gs_storedCursor =
g_busyCursor = wxCursor();
SetGlobalCursor(g_globalCursor);
}
}
bool wxIsBusy()
{
return gs_busyCount > 0;
}
void wxSetCursor( const wxCursor& cursor )
{
g_globalCursor = cursor;
SetGlobalCursor(cursor);
}