X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2f7baaeccf143a4606c463bd50b1bd995fd3d18a..b3ee9f4d2efa4a5088b4c84eb8a0ba712fa7e7fb:/src/gtk/window.cpp diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index e8dc9150eb..2fe5fc38ba 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -43,6 +43,7 @@ #include "wx/gtk/private/gtk2-compat.h" #include "wx/gtk/private/event.h" #include "wx/gtk/private/win_gtk.h" +#include "wx/private/textmeasure.h" using namespace wxGTKImpl; #ifdef GDK_WINDOWING_X11 @@ -226,6 +227,17 @@ int g_lastButtonNumber = 0; // the trace mask used for the focus debugging messages #define TRACE_FOCUS wxT("focus") +// A handy function to run from under gdb to show information about the given +// GtkWidget. Right now it only shows its type, we could enhance it to show +// more information later but this is already pretty useful. +const char* wxDumpGtkWidget(GtkWidget* w) +{ + static wxString s; + s.Printf("GtkWidget %p, type \"%s\"", w, G_OBJECT_TYPE_NAME(w)); + + return s.c_str(); +} + //----------------------------------------------------------------------------- // "expose_event"/"draw" from m_wxwindow //----------------------------------------------------------------------------- @@ -666,6 +678,16 @@ static void wxFillOtherKeyEventFields(wxKeyEvent& event, event.m_altDown = (gdk_event->state & GDK_MOD1_MASK) != 0; event.m_metaDown = (gdk_event->state & GDK_META_MASK) != 0; + // At least with current Linux systems, MOD5 corresponds to AltGr key and + // we represent it, for consistency with Windows, which really allows to + // use Ctrl+Alt as a replacement for AltGr if this key is not present, as a + // combination of these two modifiers. + if ( gdk_event->state & GDK_MOD5_MASK ) + { + event.m_controlDown = + event.m_altDown = true; + } + // Normally we take the state of modifiers directly from the low level GDK // event but unfortunately GDK uses a different convention from MSW for the // key events corresponding to the modifier keys themselves: in it, when @@ -929,8 +951,6 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget), GdkEventKey *gdk_event, wxWindow *win ) { - if (!win->m_hasVMT) - return FALSE; if (g_blockEventsOnDrag) return FALSE; @@ -1012,10 +1032,9 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget), // will only be sent if it is not in an accelerator table. if (!ret) { - long key_code; KeySym keysym = gdk_event->keyval; // Find key code for EVT_CHAR and EVT_CHAR_HOOK events - key_code = wxTranslateKeySymToWXKey(keysym, true /* isChar */); + long key_code = wxTranslateKeySymToWXKey(keysym, true /* isChar */); if ( !key_code ) { if ( wxIsAsciiKeysym(keysym) ) @@ -1037,6 +1056,9 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget), wxLogTrace(TRACE_KEYS, wxT("Char event: %ld"), key_code); eventChar.m_keyCode = key_code; +#if wxUSE_UNICODE + eventChar.m_uniChar = gdk_keyval_to_unicode(key_code); +#endif // wxUSE_UNICODE AdjustCharEventKeyCodes(eventChar); @@ -1101,9 +1123,6 @@ gtk_window_key_release_callback( GtkWidget * WXUNUSED(widget), GdkEventKey *gdk_event, wxWindowGTK *win ) { - if (!win->m_hasVMT) - return FALSE; - if (g_blockEventsOnDrag) return FALSE; @@ -1253,13 +1272,11 @@ bool wxWindowGTK::GTKProcessEvent(wxEvent& event) const bool wxWindowGTK::GTKShouldIgnoreEvent() const { - return !m_hasVMT || g_blockEventsOnDrag; + return g_blockEventsOnDrag; } int wxWindowGTK::GTKCallbackCommonPrologue(GdkEventAny *event) const { - if (!m_hasVMT) - return FALSE; if (g_blockEventsOnDrag) return TRUE; if (g_blockEventsOnScroll) @@ -1515,8 +1532,11 @@ gtk_window_motion_notify_callback( GtkWidget * WXUNUSED(widget), { int x = 0; int y = 0; - GdkModifierType state; - gdk_window_get_pointer(gdk_event->window, &x, &y, &state); +#ifdef __WXGTK3__ + gdk_window_get_device_position(gdk_event->window, gdk_event->device, &x, &y, NULL); +#else + gdk_window_get_pointer(gdk_event->window, &x, &y, NULL); +#endif gdk_event->x = x; gdk_event->y = y; } @@ -1529,7 +1549,12 @@ gtk_window_motion_notify_callback( GtkWidget * WXUNUSED(widget), if ( g_captureWindow ) { // synthesise a mouse enter or leave event if needed - GdkWindow *winUnderMouse = gdk_window_at_pointer(NULL, NULL); + GdkWindow* winUnderMouse = +#ifdef __WXGTK3__ + gdk_device_get_window_at_position(gdk_event->device, NULL, NULL); +#else + gdk_window_at_pointer(NULL, NULL); +#endif // This seems to be necessary and actually been added to // GDK itself in version 2.0.X gdk_flush(); @@ -1624,7 +1649,10 @@ window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win) case GDK_SCROLL_LEFT: event.m_wheelRotation = -120; break; - +#if GTK_CHECK_VERSION(3,4,0) + case GDK_SCROLL_SMOOTH: + // TODO +#endif default: return false; // Unknown/unhandled direction } @@ -1641,6 +1669,11 @@ window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win) case GDK_SCROLL_RIGHT: event.m_wheelAxis = wxMOUSE_WHEEL_HORIZONTAL; break; +#if GTK_CHECK_VERSION(3,4,0) + case GDK_SCROLL_SMOOTH: + // TODO + break; +#endif } if (win->GTKProcessEvent(event)) @@ -1725,7 +1758,7 @@ wx_window_focus_callback(GtkWidget *widget, //----------------------------------------------------------------------------- static gboolean -gtk_window_enter_callback( GtkWidget *widget, +gtk_window_enter_callback( GtkWidget*, GdkEventCrossing *gdk_event, wxWindowGTK *win ) { @@ -1734,17 +1767,8 @@ gtk_window_enter_callback( GtkWidget *widget, // Event was emitted after a grab if (gdk_event->mode != GDK_CROSSING_NORMAL) return FALSE; - int x = 0; - int y = 0; - GdkModifierType state = (GdkModifierType)0; - - gdk_window_get_pointer(gtk_widget_get_window(widget), &x, &y, &state); - wxMouseEvent event( wxEVT_ENTER_WINDOW ); InitMouseEvent(win, event, gdk_event); - wxPoint pt = win->GetClientAreaOrigin(); - event.m_x = x + pt.x; - event.m_y = y + pt.y; if ( !g_captureWindow ) { @@ -1763,7 +1787,7 @@ gtk_window_enter_callback( GtkWidget *widget, //----------------------------------------------------------------------------- static gboolean -gtk_window_leave_callback( GtkWidget *widget, +gtk_window_leave_callback( GtkWidget*, GdkEventCrossing *gdk_event, wxWindowGTK *win ) { @@ -1773,13 +1797,6 @@ gtk_window_leave_callback( GtkWidget *widget, if (gdk_event->mode != GDK_CROSSING_NORMAL) return FALSE; wxMouseEvent event( wxEVT_LEAVE_WINDOW ); - - int x = 0; - int y = 0; - GdkModifierType state = (GdkModifierType)0; - - gdk_window_get_pointer(gtk_widget_get_window(widget), &x, &y, &state); - InitMouseEvent(win, event, gdk_event); return win->GTKProcessEvent(event); @@ -1958,22 +1975,21 @@ static void style_updated(GtkWidget*, GtkStyle*, wxWindow* win) } //----------------------------------------------------------------------------- -// "unrealize" from m_wxwindow +// "unrealize" //----------------------------------------------------------------------------- static void unrealize(GtkWidget*, wxWindow* win) { - if (win->m_imData) - gtk_im_context_set_client_window(win->m_imData->context, NULL); - - g_signal_handlers_disconnect_by_func( - win->m_wxwindow, (void*)style_updated, win); + win->GTKHandleUnrealize(); } } // extern "C" void wxWindowGTK::GTKHandleRealized() { + if (IsFrozen()) + DoFreeze(); + if (m_imData) { gtk_im_context_set_client_window @@ -2036,6 +2052,23 @@ void wxWindowGTK::GTKHandleRealized() } } +void wxWindowGTK::GTKHandleUnrealize() +{ + // unrealizing a frozen window seems to have some lingering effect + // preventing updates to the affected area + if (IsFrozen()) + DoThaw(); + + if (m_wxwindow) + { + if (m_imData) + gtk_im_context_set_client_window(m_imData->context, NULL); + + g_signal_handlers_disconnect_by_func( + m_wxwindow, (void*)style_updated, this); + } +} + // ---------------------------------------------------------------------------- // this wxWindowBase function is implemented here (in platform-specific file) // because it is static and so couldn't be made virtual @@ -2089,7 +2122,7 @@ bool wxGetKeyState(wxKeyCode WXUNUSED(key)) } #endif // __WINDOWS__ -static void GetMouseState(int& x, int& y, GdkModifierType& mask) +static GdkDisplay* GetDisplay() { wxWindow* tlw = NULL; if (!wxTopLevelWindows.empty()) @@ -2099,7 +2132,7 @@ static void GetMouseState(int& x, int& y, GdkModifierType& mask) display = gtk_widget_get_display(tlw->m_widget); else display = gdk_display_get_default(); - gdk_display_get_pointer(display, NULL, &x, &y, &mask); + return display; } wxMouseState wxGetMouseState() @@ -2110,7 +2143,17 @@ wxMouseState wxGetMouseState() gint y; GdkModifierType mask; - GetMouseState(x, y, mask); + GdkDisplay* display = GetDisplay(); +#ifdef __WXGTK3__ + GdkDeviceManager* manager = gdk_display_get_device_manager(display); + GdkDevice* device = gdk_device_manager_get_client_pointer(manager); + GdkScreen* screen; + gdk_device_get_position(device, &screen, &x, &y); + GdkWindow* window = gdk_screen_get_root_window(screen); + gdk_device_get_state(device, window, NULL, &mask); +#else + gdk_display_get_pointer(display, NULL, &x, &y, &mask); +#endif ms.SetX(x); ms.SetY(y); @@ -2152,14 +2195,13 @@ void wxWindowGTK::Init() m_width = 0; m_height = 0; - m_hasVMT = false; - m_showOnIdle = false; m_noExpose = false; m_nativeSizeEvent = false; #ifdef __WXGTK3__ m_paintContext = NULL; + m_styleProvider = NULL; #endif m_isScrolling = false; @@ -2228,14 +2270,20 @@ void wxWindowGTK::GTKCreateScrolledWindowWith(GtkWidget* view) } } - if (HasFlag(wxALWAYS_SHOW_SB)) - { - gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS ); - } - else - { - gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); - } + // If wx[HV]SCROLL is not given, the corresponding scrollbar is not shown + // at all. Otherwise it may be shown only on demand (default) or always, if + // the wxALWAYS_SHOW_SB is specified. + GtkPolicyType horzPolicy = HasFlag(wxHSCROLL) + ? HasFlag(wxALWAYS_SHOW_SB) + ? GTK_POLICY_ALWAYS + : GTK_POLICY_AUTOMATIC + : GTK_POLICY_NEVER; + GtkPolicyType vertPolicy = HasFlag(wxVSCROLL) + ? HasFlag(wxALWAYS_SHOW_SB) + ? GTK_POLICY_ALWAYS + : GTK_POLICY_AUTOMATIC + : GTK_POLICY_NEVER; + gtk_scrolled_window_set_policy( scrolledWindow, horzPolicy, vertPolicy ); m_scrollBar[ScrollDir_Horz] = GTK_RANGE(gtk_scrolled_window_get_hscrollbar(scrolledWindow)); m_scrollBar[ScrollDir_Vert] = GTK_RANGE(gtk_scrolled_window_get_vscrollbar(scrolledWindow)); @@ -2320,6 +2368,12 @@ bool wxWindowGTK::Create( wxWindow *parent, return true; } +void wxWindowGTK::GTKDisconnect(void* instance) +{ + g_signal_handlers_disconnect_matched(instance, + GSignalMatchType(G_SIGNAL_MATCH_DATA), 0, 0, NULL, NULL, this); +} + wxWindowGTK::~wxWindowGTK() { SendDestroyEvent(); @@ -2332,22 +2386,28 @@ wxWindowGTK::~wxWindowGTK() if ( gs_deferredFocusOut == this ) gs_deferredFocusOut = NULL; - m_hasVMT = false; - - // destroy children before destroying this window itself - DestroyChildren(); + // Unlike the above cases, which can happen in normal circumstances, a + // window shouldn't be destroyed while it still has capture, so even though + // we still reset the global pointer to avoid leaving it dangling and + // crashing afterwards, also complain about it. + if ( g_captureWindow == this ) + { + wxFAIL_MSG( wxS("Destroying window with mouse capture") ); + g_captureWindow = NULL; + } - // unhook focus handlers to prevent stray events being - // propagated to this (soon to be) dead object - if (m_focusWidget != NULL) + if (m_wxwindow) { - g_signal_handlers_disconnect_by_func (m_focusWidget, - (gpointer) gtk_window_focus_in_callback, - this); - g_signal_handlers_disconnect_by_func (m_focusWidget, - (gpointer) gtk_window_focus_out_callback, - this); + GTKDisconnect(m_wxwindow); + GtkWidget* parent = gtk_widget_get_parent(m_wxwindow); + if (parent) + GTKDisconnect(parent); } + if (m_widget && m_widget != m_wxwindow) + GTKDisconnect(m_widget); + + // destroy children before destroying this window itself + DestroyChildren(); if (m_widget) Show( false ); @@ -2359,8 +2419,13 @@ wxWindowGTK::~wxWindowGTK() // avoid problem with GTK+ 2.18 where a frozen window causes the whole // TLW to be frozen, and if the window is then destroyed, nothing ever // gets painted again - if (IsFrozen()) - DoThaw(); + while (IsFrozen()) + Thaw(); + +#ifdef __WXGTK3__ + if (m_styleProvider) + g_object_unref(m_styleProvider); +#endif if (m_widget) { @@ -2441,7 +2506,6 @@ void wxWindowGTK::PostCreation() g_signal_connect (m_imData->context, "commit", G_CALLBACK (gtk_wxwindow_commit_cb), this); - g_signal_connect(m_wxwindow, "unrealize", G_CALLBACK(unrealize), this); } // focus handling @@ -2486,13 +2550,14 @@ void wxWindowGTK::PostCreation() // was in fact realized already. if ( gtk_widget_get_realized(connect_widget) ) { - gtk_window_realized_callback(connect_widget, this); + GTKHandleRealized(); } else { g_signal_connect (connect_widget, "realize", G_CALLBACK (gtk_window_realized_callback), this); } + g_signal_connect(connect_widget, "unrealize", G_CALLBACK(unrealize), this); if (!IsTopLevel()) { @@ -2525,8 +2590,6 @@ void wxWindowGTK::PostCreation() InheritAttributes(); - m_hasVMT = true; - SetLayoutDirection(wxLayout_Default); // unless the window was created initially hidden (i.e. Hide() had been @@ -2571,13 +2634,6 @@ void wxWindowGTK::ConnectWidget( GtkWidget *widget ) G_CALLBACK (gtk_window_leave_callback), this); } -bool wxWindowGTK::Destroy() -{ - m_hasVMT = false; - - return wxWindowBase::Destroy(); -} - static GSList* gs_queueResizeList; extern "C" { @@ -2781,8 +2837,8 @@ void wxWindowGTK::DoGetClientSize( int *width, int *height ) const gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(m_widget), &policy[ScrollDir_Horz], &policy[ScrollDir_Vert]); - const int scrollbar_spacing = - GTK_SCROLLED_WINDOW_GET_CLASS(m_widget)->scrollbar_spacing; + int scrollbar_spacing; + gtk_widget_style_get(m_widget, "scrollbar-spacing", &scrollbar_spacing, NULL); for ( int i = 0; i < ScrollDir_Max; i++ ) { @@ -3062,52 +3118,18 @@ void wxWindowGTK::DoGetTextExtent( const wxString& string, int *externalLeading, const wxFont *theFont ) const { - wxFont fontToUse = theFont ? *theFont : GetFont(); + // ensure we work with a valid font + wxFont fontToUse; + if ( !theFont || !theFont->IsOk() ) + fontToUse = GetFont(); + else + fontToUse = *theFont; wxCHECK_RET( fontToUse.IsOk(), wxT("invalid font") ); - if (string.empty()) - { - if (x) (*x) = 0; - if (y) (*y) = 0; - return; - } - - PangoContext *context = NULL; - if (m_widget) - context = gtk_widget_get_pango_context( m_widget ); - - if (!context) - { - if (x) (*x) = 0; - if (y) (*y) = 0; - return; - } - - PangoFontDescription *desc = fontToUse.GetNativeFontInfo()->description; - PangoLayout *layout = pango_layout_new(context); - pango_layout_set_font_description(layout, desc); - { - const wxCharBuffer data = wxGTK_CONV( string ); - if ( data ) - pango_layout_set_text(layout, data, strlen(data)); - } - - PangoRectangle rect; - pango_layout_get_extents(layout, NULL, &rect); - - if (x) (*x) = (wxCoord) PANGO_PIXELS(rect.width); - if (y) (*y) = (wxCoord) PANGO_PIXELS(rect.height); - if (descent) - { - PangoLayoutIter *iter = pango_layout_get_iter(layout); - int baseline = pango_layout_iter_get_baseline(iter); - pango_layout_iter_free(iter); - *descent = *y - PANGO_PIXELS(baseline); - } - if (externalLeading) (*externalLeading) = 0; // ?? - - g_object_unref (layout); + const wxWindow* win = static_cast(this); + wxTextMeasure txm(win, &fontToUse); + txm.GetTextExtent(string, x, y, descent, externalLeading); } void wxWindowGTK::GTKDisableFocusOutEvent() @@ -4026,16 +4048,8 @@ PangoContext *wxWindowGTK::GTKGetPangoDefaultContext() } #ifndef __WXGTK3__ -GtkRcStyle *wxWindowGTK::GTKCreateWidgetStyle(bool forceStyle) +GtkRcStyle* wxWindowGTK::GTKCreateWidgetStyle() { - // do we need to apply any changes at all? - if ( !forceStyle && - !m_font.IsOk() && - !m_foregroundColour.IsOk() && !m_backgroundColour.IsOk() ) - { - return NULL; - } - GtkRcStyle *style = gtk_rc_style_new(); if ( m_font.IsOk() ) @@ -4096,18 +4110,35 @@ GtkRcStyle *wxWindowGTK::GTKCreateWidgetStyle(bool forceStyle) } #endif // !__WXGTK3__ -void wxWindowGTK::GTKApplyWidgetStyle(bool WXUNUSED_IN_GTK3(forceStyle)) +void wxWindowGTK::GTKApplyWidgetStyle(bool forceStyle) { + if (forceStyle || m_font.IsOk() || + m_foregroundColour.IsOk() || m_backgroundColour.IsOk()) + { #ifdef __WXGTK3__ - DoApplyWidgetStyle(NULL); + if (m_backgroundColour.IsOk()) + { + // create a GtkStyleProvider to override "background-image" + if (m_styleProvider == NULL) + m_styleProvider = GTK_STYLE_PROVIDER(gtk_css_provider_new()); + const char css[] = + "*{background-image:-gtk-gradient(linear,0 0,0 1," + "from(rgba(%u,%u,%u,%g)),to(rgba(%u,%u,%u,%g)))}"; + char buf[sizeof(css) + 20]; + const unsigned r = m_backgroundColour.Red(); + const unsigned g = m_backgroundColour.Green(); + const unsigned b = m_backgroundColour.Blue(); + const double a = m_backgroundColour.Alpha() / 255.0; + g_snprintf(buf, sizeof(buf), css, r, g, b, a, r, g, b, a); + gtk_css_provider_load_from_data(GTK_CSS_PROVIDER(m_styleProvider), buf, -1, NULL); + } + DoApplyWidgetStyle(NULL); #else - GtkRcStyle *style = GTKCreateWidgetStyle(forceStyle); - if ( style ) - { + GtkRcStyle* style = GTKCreateWidgetStyle(); DoApplyWidgetStyle(style); g_object_unref(style); - } #endif + } // Style change may affect GTK+'s size calculation: InvalidateBestSize(); @@ -4145,6 +4176,25 @@ void wxWindowGTK::GTKApplyStyle(GtkWidget* widget, GtkRcStyle* WXUNUSED_IN_GTK3( gtk_widget_override_font(widget, pfd); gtk_widget_override_color(widget, GTK_STATE_FLAG_NORMAL, m_foregroundColour); gtk_widget_override_background_color(widget, GTK_STATE_FLAG_NORMAL, m_backgroundColour); + + // setting background color has no effect with some themes when the widget style + // has a "background-image" property, so we need to override that as well + + GtkStyleContext* context = gtk_widget_get_style_context(widget); + if (m_styleProvider) + gtk_style_context_remove_provider(context, m_styleProvider); + cairo_pattern_t* pattern = NULL; + if (m_backgroundColour.IsOk()) + { + gtk_style_context_get(context, + GTK_STATE_FLAG_NORMAL, "background-image", &pattern, NULL); + } + if (pattern) + { + cairo_pattern_destroy(pattern); + gtk_style_context_add_provider(context, + m_styleProvider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + } #else gtk_widget_modify_style(widget, style); #endif @@ -4257,7 +4307,11 @@ void wxPopupMenuPositionCallback( GtkMenu *menu, { // ensure that the menu appears entirely on screen GtkRequisition req; +#ifdef __WXGTK3__ + gtk_widget_get_preferred_size(GTK_WIDGET(menu), &req, NULL); +#else gtk_widget_get_child_requisition(GTK_WIDGET(menu), &req); +#endif wxSize sizeScreen = wxGetDisplaySize(); wxPoint *pos = (wxPoint*)user_data; @@ -4383,15 +4437,25 @@ void wxWindowGTK::DoCaptureMouse() if (!cursor->IsOk()) cursor = wxSTANDARD_CURSOR; + const GdkEventMask mask = GdkEventMask( + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_POINTER_MOTION_HINT_MASK | + GDK_POINTER_MOTION_MASK); +#ifdef __WXGTK3__ + GdkDisplay* display = gdk_window_get_display(window); + GdkDeviceManager* manager = gdk_display_get_device_manager(display); + GdkDevice* device = gdk_device_manager_get_client_pointer(manager); + gdk_device_grab( + device, window, GDK_OWNERSHIP_NONE, false, mask, + cursor->GetCursor(), unsigned(GDK_CURRENT_TIME)); +#else gdk_pointer_grab( window, FALSE, - (GdkEventMask) - (GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_HINT_MASK | - GDK_POINTER_MOTION_MASK), + mask, NULL, cursor->GetCursor(), (guint32)GDK_CURRENT_TIME ); +#endif g_captureWindow = this; g_captureWindowHasMouse = true; } @@ -4413,7 +4477,14 @@ void wxWindowGTK::DoReleaseMouse() if (!window) return; +#ifdef __WXGTK3__ + GdkDisplay* display = gdk_window_get_display(window); + GdkDeviceManager* manager = gdk_display_get_device_manager(display); + GdkDevice* device = gdk_device_manager_get_client_pointer(manager); + gdk_device_ungrab(device, unsigned(GDK_CURRENT_TIME)); +#else gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME ); +#endif } void wxWindowGTK::GTKReleaseMouseAndNotify() @@ -4532,7 +4603,7 @@ wxEventType wxWindowGTK::GTKGetScrollEventType(GtkRange* range) // update current position m_scrollPos[barIndex] = value; // If event should be ignored, or integral position has not changed - if (!m_hasVMT || g_blockEventsOnDrag || wxRound(value) == wxRound(oldPos)) + if (g_blockEventsOnDrag || wxRound(value) == wxRound(oldPos)) { return wxEVT_NULL; } @@ -4636,12 +4707,23 @@ wxWindow* wxFindWindowAtPointer(wxPoint& pt) } // Get the current mouse position. +void wxGetMousePosition(int* x, int* y) +{ + GdkDisplay* display = GetDisplay(); +#ifdef __WXGTK3__ + GdkDeviceManager* manager = gdk_display_get_device_manager(display); + GdkDevice* device = gdk_device_manager_get_client_pointer(manager); + gdk_device_get_position(device, NULL, x, y); +#else + gdk_display_get_pointer(display, NULL, x, y, NULL); +#endif +} + wxPoint wxGetMousePosition() { - int x, y; - GdkModifierType unused; - GetMouseState(x, y, unused); - return wxPoint(x, y); + wxPoint pt; + wxGetMousePosition(&pt.x, &pt.y); + return pt; } GdkWindow* wxWindowGTK::GTKGetDrawingWindow() const @@ -4656,91 +4738,38 @@ GdkWindow* wxWindowGTK::GTKGetDrawingWindow() const // freeze/thaw // ---------------------------------------------------------------------------- -extern "C" -{ - -// this is called if we attempted to freeze unrealized widget when it finally -// is realized (and so can be frozen): -static void wx_frozen_widget_realize(GtkWidget* w, wxWindowGTK* win) +void wxWindowGTK::GTKFreezeWidget(GtkWidget* widget) { - wxASSERT( w && gtk_widget_get_has_window(w) ); - wxASSERT( gtk_widget_get_realized(w) ); - - g_signal_handlers_disconnect_by_func - ( - w, - (void*)wx_frozen_widget_realize, - win - ); - - GdkWindow* window; - if (w == win->m_wxwindow) - window = win->GTKGetDrawingWindow(); - else - window = gtk_widget_get_window(w); - gdk_window_freeze_updates(window); -} - -} // extern "C" - -void wxWindowGTK::GTKFreezeWidget(GtkWidget *w) -{ - if ( !w || !gtk_widget_get_has_window(w) ) - return; // window-less widget, cannot be frozen - - GdkWindow* window = gtk_widget_get_window(w); - if (window == NULL) + if (widget && gtk_widget_get_has_window(widget)) { - // we can't thaw unrealized widgets because they don't have GdkWindow, - // so set it up to be done immediately after realization: - g_signal_connect_after - ( - w, - "realize", - G_CALLBACK(wx_frozen_widget_realize), - this - ); - return; + GdkWindow* window = gtk_widget_get_window(widget); + if (window) + gdk_window_freeze_updates(window); } - - if (w == m_wxwindow) - window = GTKGetDrawingWindow(); - gdk_window_freeze_updates(window); } -void wxWindowGTK::GTKThawWidget(GtkWidget *w) +void wxWindowGTK::GTKThawWidget(GtkWidget* widget) { - if ( !w || !gtk_widget_get_has_window(w) ) - return; // window-less widget, cannot be frozen - - GdkWindow* window = gtk_widget_get_window(w); - if (window == NULL) + if (widget && gtk_widget_get_has_window(widget)) { - // the widget wasn't realized yet, no need to thaw - g_signal_handlers_disconnect_by_func - ( - w, - (void*)wx_frozen_widget_realize, - this - ); - return; + GdkWindow* window = gtk_widget_get_window(widget); + if (window) + gdk_window_thaw_updates(window); } - - if (w == m_wxwindow) - window = GTKGetDrawingWindow(); - gdk_window_thaw_updates(window); } void wxWindowGTK::DoFreeze() { - GTKFreezeWidget(m_widget); - if ( m_wxwindow && m_widget != m_wxwindow ) - GTKFreezeWidget(m_wxwindow); + GtkWidget* widget = m_wxwindow; + if (widget == NULL) + widget = m_widget; + GTKFreezeWidget(widget); } void wxWindowGTK::DoThaw() { - GTKThawWidget(m_widget); - if ( m_wxwindow && m_widget != m_wxwindow ) - GTKThawWidget(m_wxwindow); + GtkWidget* widget = m_wxwindow; + if (widget == NULL) + widget = m_widget; + GTKThawWidget(widget); }