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:
@@ -332,7 +332,7 @@ public:
|
|||||||
|
|
||||||
// set the current cursor for all GdkWindows making part of this widget
|
// set the current cursor for all GdkWindows making part of this widget
|
||||||
// (see GTKGetWindow)
|
// (see GTKGetWindow)
|
||||||
void GTKUpdateCursor(bool update_self = true, bool recurse = true);
|
void GTKUpdateCursor();
|
||||||
|
|
||||||
// extra (wxGTK-specific) flags
|
// extra (wxGTK-specific) flags
|
||||||
bool m_noExpose:1; // wxGLCanvas has its own redrawing
|
bool m_noExpose:1; // wxGLCanvas has its own redrawing
|
||||||
|
@@ -308,59 +308,18 @@ wxCursor::CloneGDIRefData(const wxGDIRefData * WXUNUSED(data)) const
|
|||||||
// busy cursor routines
|
// 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;
|
static int gs_busyCount = 0;
|
||||||
|
|
||||||
const wxCursor &wxBusyCursor::GetStoredCursor()
|
void wxBeginBusyCursor(const wxCursor* cursor)
|
||||||
{
|
{
|
||||||
return gs_savedCursor;
|
if (gs_busyCount++ == 0)
|
||||||
}
|
wxSetCursor(*cursor);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxEndBusyCursor()
|
void wxEndBusyCursor()
|
||||||
{
|
{
|
||||||
if (--gs_busyCount > 0)
|
if (gs_busyCount && --gs_busyCount == 0)
|
||||||
return;
|
wxSetCursor(wxCursor());
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxIsBusy()
|
bool wxIsBusy()
|
||||||
@@ -368,8 +327,94 @@ bool wxIsBusy()
|
|||||||
return gs_busyCount > 0;
|
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 )
|
void wxSetCursor( const wxCursor& cursor )
|
||||||
{
|
{
|
||||||
g_globalCursor = cursor;
|
GdkDisplay* display = NULL;
|
||||||
UpdateCursors(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);
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,6 @@
|
|||||||
#include "wx/dialog.h"
|
#include "wx/dialog.h"
|
||||||
|
|
||||||
#ifndef WX_PRECOMP
|
#ifndef WX_PRECOMP
|
||||||
#include "wx/cursor.h"
|
|
||||||
#endif // WX_PRECOMP
|
#endif // WX_PRECOMP
|
||||||
|
|
||||||
#include "wx/evtloop.h"
|
#include "wx/evtloop.h"
|
||||||
@@ -148,8 +147,6 @@ int wxDialog::ShowModal()
|
|||||||
GTK_WINDOW(parent->m_widget) );
|
GTK_WINDOW(parent->m_widget) );
|
||||||
}
|
}
|
||||||
|
|
||||||
wxBusyCursorSuspender cs; // temporarily suppress the busy cursor
|
|
||||||
|
|
||||||
#if GTK_CHECK_VERSION(2,10,0)
|
#if GTK_CHECK_VERSION(2,10,0)
|
||||||
unsigned sigId = 0;
|
unsigned sigId = 0;
|
||||||
gulong hookId = 0;
|
gulong hookId = 0;
|
||||||
|
@@ -304,7 +304,6 @@ gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event,
|
|||||||
gdk_window_set_cursor(gtk_widget_get_window(widget), gdk_cursor_new(GDK_BOTTOM_RIGHT_CORNER));
|
gdk_window_set_cursor(gtk_widget_get_window(widget), gdk_cursor_new(GDK_BOTTOM_RIGHT_CORNER));
|
||||||
else
|
else
|
||||||
gdk_window_set_cursor(gtk_widget_get_window(widget), NULL);
|
gdk_window_set_cursor(gtk_widget_get_window(widget), NULL);
|
||||||
win->GTKUpdateCursor(false);
|
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@@ -823,8 +823,6 @@ bool wxTextCtrl::Create( wxWindow *parent,
|
|||||||
|
|
||||||
GTKConnectClipboardSignals(m_text);
|
GTKConnectClipboardSignals(m_text);
|
||||||
|
|
||||||
m_cursor = wxCursor( wxCURSOR_IBEAM );
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1329,7 +1327,6 @@ bool wxTextCtrl::Enable( bool enable )
|
|||||||
}
|
}
|
||||||
|
|
||||||
gtk_widget_set_sensitive( m_text, enable );
|
gtk_widget_set_sensitive( m_text, enable );
|
||||||
SetCursor(enable ? wxCursor(wxCURSOR_IBEAM) : wxCursor());
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1989,7 +1986,7 @@ void wxTextCtrl::OnUrlMouseEvent(wxMouseEvent& event)
|
|||||||
gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(m_text), &end, x, y);
|
gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(m_text), &end, x, y);
|
||||||
if (!gtk_text_iter_has_tag(&end, tag))
|
if (!gtk_text_iter_has_tag(&end, tag))
|
||||||
{
|
{
|
||||||
SetCursor(wxCursor(wxCURSOR_IBEAM));
|
SetCursor(wxCursor());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
// data
|
// data
|
||||||
extern bool g_blockEventsOnDrag;
|
extern bool g_blockEventsOnDrag;
|
||||||
extern wxCursor g_globalCursor;
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxToolBarTool
|
// wxToolBarTool
|
||||||
|
@@ -197,7 +197,6 @@ typedef guint KeySym;
|
|||||||
bool g_blockEventsOnDrag;
|
bool g_blockEventsOnDrag;
|
||||||
// Don't allow mouse event propagation during scroll
|
// Don't allow mouse event propagation during scroll
|
||||||
bool g_blockEventsOnScroll;
|
bool g_blockEventsOnScroll;
|
||||||
extern wxCursor g_globalCursor;
|
|
||||||
|
|
||||||
// mouse capture state: the window which has it and if the mouse is currently
|
// mouse capture state: the window which has it and if the mouse is currently
|
||||||
// inside it
|
// inside it
|
||||||
@@ -2068,7 +2067,7 @@ void wxWindowGTK::GTKHandleRealized()
|
|||||||
event.SetEventObject( this );
|
event.SetEventObject( this );
|
||||||
GTKProcessEvent( event );
|
GTKProcessEvent( event );
|
||||||
|
|
||||||
GTKUpdateCursor(true, false);
|
GTKUpdateCursor();
|
||||||
|
|
||||||
if (m_wxwindow && IsTopLevel())
|
if (m_wxwindow && IsTopLevel())
|
||||||
{
|
{
|
||||||
@@ -2259,8 +2258,6 @@ void wxWindowGTK::Init()
|
|||||||
|
|
||||||
m_clipPaintRegion = false;
|
m_clipPaintRegion = false;
|
||||||
|
|
||||||
m_cursor = *wxSTANDARD_CURSOR;
|
|
||||||
|
|
||||||
m_imContext = NULL;
|
m_imContext = NULL;
|
||||||
m_imKeyEvent = NULL;
|
m_imKeyEvent = NULL;
|
||||||
|
|
||||||
@@ -3663,7 +3660,7 @@ void wxWindowGTK::Lower()
|
|||||||
|
|
||||||
bool wxWindowGTK::SetCursor( const wxCursor &cursor )
|
bool wxWindowGTK::SetCursor( const wxCursor &cursor )
|
||||||
{
|
{
|
||||||
if ( !wxWindowBase::SetCursor(cursor.IsOk() ? cursor : *wxSTANDARD_CURSOR) )
|
if (!wxWindowBase::SetCursor(cursor))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
GTKUpdateCursor();
|
GTKUpdateCursor();
|
||||||
@@ -3671,38 +3668,30 @@ bool wxWindowGTK::SetCursor( const wxCursor &cursor )
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxWindowGTK::GTKUpdateCursor(bool update_self /*=true*/, bool recurse /*=true*/)
|
void wxWindowGTK::GTKUpdateCursor()
|
||||||
{
|
{
|
||||||
if (update_self)
|
if (m_widget == NULL ||
|
||||||
|
!gtk_widget_get_realized(m_widget) ||
|
||||||
|
(m_wxwindow == NULL && !gtk_widget_get_has_window(m_widget)))
|
||||||
{
|
{
|
||||||
wxCursor cursor(g_globalCursor.IsOk() ? g_globalCursor : GetCursor());
|
return;
|
||||||
if ( cursor.IsOk() )
|
|
||||||
{
|
|
||||||
wxArrayGdkWindows windowsThis;
|
|
||||||
GdkWindow* window = GTKGetWindow(windowsThis);
|
|
||||||
if (window)
|
|
||||||
gdk_window_set_cursor( window, cursor.GetCursor() );
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const size_t count = windowsThis.size();
|
|
||||||
for ( size_t n = 0; n < count; n++ )
|
|
||||||
{
|
|
||||||
GdkWindow *win = windowsThis[n];
|
|
||||||
// It can be zero if the window has not been realized yet.
|
|
||||||
if ( win )
|
|
||||||
{
|
|
||||||
gdk_window_set_cursor(win, cursor.GetCursor());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recurse)
|
GdkCursor* cursor = NULL;
|
||||||
|
if (m_cursor.IsOk())
|
||||||
|
cursor = m_cursor.GetCursor();
|
||||||
|
|
||||||
|
wxArrayGdkWindows windows;
|
||||||
|
GdkWindow* window = GTKGetWindow(windows);
|
||||||
|
if (window)
|
||||||
|
gdk_window_set_cursor(window, cursor);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
for (wxWindowList::iterator it = GetChildren().begin(); it != GetChildren().end(); ++it)
|
for (size_t i = windows.size(); i--;)
|
||||||
{
|
{
|
||||||
(*it)->GTKUpdateCursor( true );
|
window = windows[i];
|
||||||
|
if (window)
|
||||||
|
gdk_window_set_cursor(window, cursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4474,10 +4463,6 @@ void wxWindowGTK::DoCaptureMouse()
|
|||||||
|
|
||||||
wxCHECK_RET( window, wxT("CaptureMouse() failed") );
|
wxCHECK_RET( window, wxT("CaptureMouse() failed") );
|
||||||
|
|
||||||
const wxCursor* cursor = &m_cursor;
|
|
||||||
if (!cursor->IsOk())
|
|
||||||
cursor = wxSTANDARD_CURSOR;
|
|
||||||
|
|
||||||
const GdkEventMask mask = GdkEventMask(
|
const GdkEventMask mask = GdkEventMask(
|
||||||
GDK_BUTTON_PRESS_MASK |
|
GDK_BUTTON_PRESS_MASK |
|
||||||
GDK_BUTTON_RELEASE_MASK |
|
GDK_BUTTON_RELEASE_MASK |
|
||||||
@@ -4489,12 +4474,12 @@ void wxWindowGTK::DoCaptureMouse()
|
|||||||
GdkDevice* device = gdk_device_manager_get_client_pointer(manager);
|
GdkDevice* device = gdk_device_manager_get_client_pointer(manager);
|
||||||
gdk_device_grab(
|
gdk_device_grab(
|
||||||
device, window, GDK_OWNERSHIP_NONE, false, mask,
|
device, window, GDK_OWNERSHIP_NONE, false, mask,
|
||||||
cursor->GetCursor(), unsigned(GDK_CURRENT_TIME));
|
NULL, unsigned(GDK_CURRENT_TIME));
|
||||||
#else
|
#else
|
||||||
gdk_pointer_grab( window, FALSE,
|
gdk_pointer_grab( window, FALSE,
|
||||||
mask,
|
mask,
|
||||||
NULL,
|
NULL,
|
||||||
cursor->GetCursor(),
|
NULL,
|
||||||
(guint32)GDK_CURRENT_TIME );
|
(guint32)GDK_CURRENT_TIME );
|
||||||
#endif
|
#endif
|
||||||
g_captureWindow = this;
|
g_captureWindow = this;
|
||||||
|
Reference in New Issue
Block a user