Applied patch, fixes #12090: wxGTK cursor handling revamp

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64404 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robert Roebling
2010-05-26 17:37:55 +00:00
parent 443fbbf7ae
commit c2246a3881
8 changed files with 55 additions and 123 deletions

View File

@@ -217,8 +217,6 @@ private:
// For wxTE_AUTO_URL
void OnUrlMouseEvent(wxMouseEvent&);
GdkCursor *m_gdkHandCursor;
GdkCursor *m_gdkXTermCursor;
DECLARE_EVENT_TABLE()
DECLARE_DYNAMIC_CLASS(wxTextCtrl)

View File

@@ -279,6 +279,10 @@ public:
// find the direction of the given scrollbar (must be one of ours)
ScrollDir ScrollDirFromRange(GtkRange *range) const;
// set the current cursor for all GdkWindows making part of this widget
// (see GTKGetWindow)
void GTKUpdateCursor(bool update_self = true, bool recurse = true);
// extra (wxGTK-specific) flags
bool m_noExpose:1; // wxGLCanvas has its own redrawing
bool m_nativeSizeEvent:1; // wxGLCanvas sends wxSizeEvent upon "alloc_size"
@@ -357,12 +361,6 @@ protected:
// sets the border of a given GtkScrolledWindow from a wx style
static void GTKScrolledWindowSetBorder(GtkWidget* w, int style);
// set the current cursor for all GdkWindows making part of this widget
// (see GTKGetWindow)
//
// should be called from OnInternalIdle() if it's overridden
void GTKUpdateCursor();
// Connect the given function to the specified signal on m_widget.
//
// This is just a wrapper for g_signal_connect() and returns the handler id

View File

@@ -323,11 +323,6 @@ void wxControl::OnInternalIdle()
if ( GTKShowFromOnIdle() )
return;
if ( GTK_WIDGET_REALIZED(m_widget) )
{
GTKUpdateCursor();
}
if ( wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen() )
UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
}

View File

@@ -374,7 +374,7 @@ const wxCursor wxBusyCursor::GetBusyCursor()
return wxCursor(wxCURSOR_WATCH);
}
static void InternalIdle(const wxWindowList& list, GdkDisplay*& display)
static void UpdateCursors(const wxWindowList& list, GdkDisplay*& display)
{
wxWindowList::const_iterator i = list.begin();
for (size_t n = list.size(); n--; ++i)
@@ -382,8 +382,8 @@ static void InternalIdle(const wxWindowList& list, GdkDisplay*& display)
wxWindow* win = *i;
if (display == NULL && win->m_widget && win->m_widget->window)
display = gdk_drawable_get_display(win->m_widget->window);
win->OnInternalIdle();
InternalIdle(win->GetChildren(), display);
win->GTKUpdateCursor(true, false);
UpdateCursors(win->GetChildren(), display);
}
}
@@ -395,7 +395,7 @@ void wxEndBusyCursor()
g_globalCursor = gs_savedCursor;
gs_savedCursor = wxNullCursor;
GdkDisplay* unused = NULL;
InternalIdle(wxTopLevelWindows, unused);
UpdateCursors(wxTopLevelWindows, unused);
}
void wxBeginBusyCursor(const wxCursor* cursor)
@@ -409,7 +409,7 @@ void wxBeginBusyCursor(const wxCursor* cursor)
gs_savedCursor = g_globalCursor;
g_globalCursor = *cursor;
GdkDisplay* display = NULL;
InternalIdle(wxTopLevelWindows, display);
UpdateCursors(wxTopLevelWindows, display);
if (display)
gdk_display_flush(display);
}
@@ -422,5 +422,6 @@ bool wxIsBusy()
void wxSetCursor( const wxCursor& cursor )
{
g_globalCursor = cursor;
wxTheApp->WakeUpIdle();
GdkDisplay* unused = NULL;
UpdateCursors(wxTopLevelWindows, unused);
}

View File

@@ -281,6 +281,7 @@ gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event,
gdk_window_set_cursor( widget->window, gdk_cursor_new( GDK_BOTTOM_RIGHT_CORNER ) );
else
gdk_window_set_cursor( widget->window, NULL );
win->GTKUpdateCursor(false);
}
return TRUE;
}

View File

@@ -622,16 +622,10 @@ void wxTextCtrl::Init()
m_text = NULL;
m_showPositionOnThaw = NULL;
m_gdkHandCursor = NULL;
m_gdkXTermCursor = NULL;
}
wxTextCtrl::~wxTextCtrl()
{
if(m_gdkHandCursor)
gdk_cursor_unref(m_gdkHandCursor);
if(m_gdkXTermCursor)
gdk_cursor_unref(m_gdkXTermCursor);
}
wxTextCtrl::wxTextCtrl( wxWindow *parent,
@@ -763,8 +757,6 @@ bool wxTextCtrl::Create( wxWindow *parent,
if (style & wxTE_AUTO_URL)
{
GtkTextIter start, end;
m_gdkHandCursor = gdk_cursor_new(GDK_HAND2);
m_gdkXTermCursor = gdk_cursor_new(GDK_XTERM);
// We create our wxUrl tag here for slight efficiency gain - we
// don't have to check for the tag existance in callbacks,
@@ -1873,13 +1865,11 @@ void wxTextCtrl::OnUrlMouseEvent(wxMouseEvent& event)
gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(m_text), &end, x, y);
if (!gtk_text_iter_has_tag(&end, tag))
{
gdk_window_set_cursor(gtk_text_view_get_window(GTK_TEXT_VIEW(m_text),
GTK_TEXT_WINDOW_TEXT), m_gdkXTermCursor);
SetCursor(wxCursor(wxCURSOR_IBEAM));
return;
}
gdk_window_set_cursor(gtk_text_view_get_window(GTK_TEXT_VIEW(m_text),
GTK_TEXT_WINDOW_TEXT), m_gdkHandCursor);
SetCursor(wxCursor(wxCURSOR_HAND));
start = end;
if(!gtk_text_iter_begins_tag(&start, tag))

View File

@@ -733,45 +733,6 @@ void wxToolBar::OnInternalIdle()
// Check if we have to show window now
if (GTKShowFromOnIdle()) return;
wxCursor cursor = m_cursor;
if (g_globalCursor.Ok()) cursor = g_globalCursor;
if (cursor.Ok())
{
/* I now set the cursor the anew in every OnInternalIdle call
as setting the cursor in a parent window also effects the
windows above so that checking for the current cursor is
not possible. */
if (HasFlag(wxTB_DOCKABLE) && (m_widget->window))
{
/* if the toolbar is dockable, then m_widget stands for the
GtkHandleBox widget, which uses its own window so that we
can set the cursor for it. if the toolbar is not dockable,
m_widget comes from m_toolbar which uses its parent's
window ("windowless windows") and thus we cannot set the
cursor. */
gdk_window_set_cursor( m_widget->window, cursor.GetCursor() );
}
wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
while ( node )
{
wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
node = node->GetNext();
if (tool->m_item)
{
GdkWindow* window = GTK_WIDGET(tool->m_item)->window;
if ( window )
{
gdk_window_set_cursor( window, cursor.GetCursor() );
}
}
}
}
if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen())
UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
}

View File

@@ -183,14 +183,12 @@
Cursors, too, have been a constant source of pleasure. The main difficulty
is that a GdkWindow inherits a cursor if the programmer sets a new cursor
for the parent. To prevent this from doing too much harm, I use idle time
to set the cursor over and over again, starting from the toplevel windows
and ending with the youngest generation (speaking of parent and child windows).
for the parent. To prevent this from doing too much harm, SetCursor calls
GTKUpdateCursor, which will recursively re-set the cursors of all child windows.
Also don't forget that cursors (like much else) are connected to GdkWindows,
not GtkWidgets and that the "window" field of a GtkWidget might very well
point to the GdkWindow of the parent widget (-> "window-less widget") and
that the two obviously have very different meanings.
*/
//-----------------------------------------------------------------------------
@@ -2565,38 +2563,6 @@ void wxWindowGTK::OnInternalIdle()
m_needsStyleChange = false;
}
wxCursor cursor = m_cursor;
if (g_globalCursor.Ok()) cursor = g_globalCursor;
if (cursor.Ok())
{
/* I now set the cursor anew in every OnInternalIdle call
as setting the cursor in a parent window also effects the
windows above so that checking for the current cursor is
not possible. */
if (m_wxwindow && (m_wxwindow != m_widget))
{
GdkWindow* window = GTKGetDrawingWindow();
if (window)
gdk_window_set_cursor( window, cursor.GetCursor() );
if (!g_globalCursor.Ok())
cursor = *wxSTANDARD_CURSOR;
window = m_widget->window;
if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
gdk_window_set_cursor( window, cursor.GetCursor() );
}
else if ( m_widget )
{
GdkWindow *window = m_widget->window;
if ( window && !GTK_WIDGET_NO_WINDOW(m_widget) )
gdk_window_set_cursor( window, cursor.GetCursor() );
}
}
if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen())
UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
}
@@ -3429,17 +3395,19 @@ bool wxWindowGTK::SetCursor( const wxCursor &cursor )
return true;
}
void wxWindowGTK::GTKUpdateCursor()
void wxWindowGTK::GTKUpdateCursor(bool update_self /*=true*/, bool recurse /*=true*/)
{
if (update_self)
{
wxCursor cursor(g_globalCursor.Ok() ? g_globalCursor : GetCursor());
if ( cursor.Ok() )
{
wxArrayGdkWindows windowsThis;
GdkWindow * const winThis = GTKGetWindow(windowsThis);
if ( winThis )
if (m_wxwindow && (m_wxwindow != m_widget))
{
gdk_window_set_cursor(winThis, cursor.GetCursor());
}
wxArrayGdkWindows windowsThis;
GdkWindow* window = GTKGetDrawingWindow();
if (window)
gdk_window_set_cursor( window, cursor.GetCursor() );
else
{
const size_t count = windowsThis.size();
@@ -3451,10 +3419,30 @@ void wxWindowGTK::GTKUpdateCursor()
wxFAIL_MSG(wxT("NULL window returned by GTKGetWindow()?"));
continue;
}
gdk_window_set_cursor(win, cursor.GetCursor());
}
}
window = m_widget->window;
if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
gdk_window_set_cursor( window, cursor.GetCursor() );
}
else if ( m_widget )
{
GdkWindow *window = m_widget->window;
if ( window && !GTK_WIDGET_NO_WINDOW(m_widget) )
gdk_window_set_cursor( window, cursor.GetCursor() );
}
}
}
if (recurse)
{
for (wxWindowList::iterator it = GetChildren().begin(); it != GetChildren().end(); ++it)
{
(*it)->GTKUpdateCursor( true );
}
}
}