X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/20123d495814b8b8543bf43fbd63aa7ec21e5d78..bb86baea10afec3a7e4860c17b20edd485c628d6:/src/gtk/window.cpp diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index 75df72073f..9c1a4fecb3 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -7,11 +7,6 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// - -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "window.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -138,7 +133,7 @@ extern GtkContainerClass *pizza_parent_class; All windows must have a widget, with which they interact with other under- lying GTK widgets. It is this widget, e.g. that has to be resized etc and - thw wxWindow class has a member variable called m_widget which holds a + the wxWindow class has a member variable called m_widget which holds a pointer to this widget. When the window class represents a GTK native widget, this is (in most cases) the only GTK widget the class manages. E.g. the wxStaticText class handles only a GtkLabel widget a pointer to which you @@ -178,27 +173,27 @@ extern GtkContainerClass *pizza_parent_class; III) - Singularily the most broken code in GTK is the code that is supposes to + Singularily the most broken code in GTK is the code that is supposed to inform subwindows (child windows) about new positions. Very often, duplicate events are sent without changes in size or position, equally often no events are sent at all (All this is due to a bug in the GtkContainer code which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores GTK's own system and it simply waits for size events for toplevel windows and then iterates down the respective size events to all window. This has - the disadvantage, that windows might get size events before the GTK widget + the disadvantage that windows might get size events before the GTK widget actually has the reported size. This doesn't normally pose any problem, but - the OpenGl drawing routines rely on correct behaviour. Therefore, I have + the OpenGL drawing routines rely on correct behaviour. Therefore, I have added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas, i.e. the wxGLCanvas will emit a size event, when (and not before) the X11 - window that is used for OpenGl output really has that size (as reported by + window that is used for OpenGL output really has that size (as reported by GTK). IV) If someone at some point of time feels the immense desire to have a look at, - change or attempt to optimse the Refresh() logic, this person will need an - intimate understanding of what a "draw" and what an "expose" events are and - what there are used for, in particular when used in connection with GTK's + change or attempt to optimise the Refresh() logic, this person will need an + intimate understanding of what "draw" and "expose" events are and what + they are used for, in particular when used in connection with GTK's own windowless widgets. Beware. V) @@ -210,7 +205,7 @@ extern GtkContainerClass *pizza_parent_class; and ending with the youngest generation (speaking of parent and 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 + point to the GdkWindow of the parent widget (-> "window-less widget") and that the two obviously have very different meanings. */ @@ -244,7 +239,9 @@ wxWindowGTK *g_delayedFocus = (wxWindowGTK*) NULL; // hack: we need something to pass to gtk_menu_popup, so we store the time of // the last click here +#ifndef __WXGTK20__ static guint32 gs_timeLastClick = 0; +#endif extern bool g_mainThreadLocked; @@ -563,7 +560,7 @@ static int gtk_window_expose_callback( GtkWidget *widget, win->GtkSendPaintEvents(); - // Let parent window draw window less widgets + // Let parent window draw window-less widgets (* GTK_WIDGET_CLASS (pizza_parent_class)->expose_event) (widget, gdk_event); #else // This gets called immediately after an expose event @@ -1064,7 +1061,7 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event, } // we want to always get the same key code when the same key is - // pressed regardless of the state of the modifies, i.e. on a + // pressed regardless of the state of the modifiers, i.e. on a // standard US keyboard pressing '5' or '%' ('5' key with // Shift) should result in the same key code in OnKeyDown(): // '5' (although OnChar() will get either '5' or '%'). @@ -1238,7 +1235,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, const char* string = gdk_event->string; #endif - // Implement OnCharHook by checking ancesteror top level windows + // Implement OnCharHook by checking ancestor top level windows wxWindow *parent = win; while (parent && !parent->IsTopLevel()) parent = parent->GetParent(); @@ -1316,7 +1313,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, event.m_keyCode = key_code; - // Implement OnCharHook by checking ancesteror top level windows + // Implement OnCharHook by checking ancestor top level windows wxWindow *parent = win; while (parent && !parent->IsTopLevel()) parent = parent->GetParent(); @@ -1341,7 +1338,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, // win is a control: tab can be propagated up if ( !ret && ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) && -// VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may +// VZ: testing for wxTE_PROCESS_TAB shouldn't be done here - the control may // have this style, yet choose not to process this particular TAB in which // case TAB must still work as a navigational character // JS: enabling again to make consistent with other platforms @@ -1393,9 +1390,9 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, if ( btnCancel ) { - wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL); - event.SetEventObject(btnCancel); - ret = btnCancel->GetEventHandler()->ProcessEvent(event); + wxCommandEvent eventClick(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL); + eventClick.SetEventObject(btnCancel); + ret = btnCancel->GetEventHandler()->ProcessEvent(eventClick); } } @@ -1491,7 +1488,7 @@ static gint gtk_window_key_release_callback( GtkWidget *widget, wxKeyEvent event( wxEVT_KEY_UP ); if ( !wxTranslateGTKKeyEventToWx(event, win, gdk_event) ) { - // unknown key pressed, ignore (the event would be useless anyhow + // unknown key pressed, ignore (the event would be useless anyhow) return FALSE; } @@ -1678,7 +1675,7 @@ static gint gtk_window_button_press_callback( GtkWidget *widget, */ } - // GDK sends surplus button down event + // GDK sends surplus button down events // before a double click event. We // need to filter these out. if (gdk_event->type == GDK_BUTTON_PRESS) @@ -1794,19 +1791,19 @@ static gint gtk_window_button_press_callback( GtkWidget *widget, AdjustEventButtonState(event); - // wxListBox actually get mouse events from the item, so we need to give it + // wxListBox actually gets mouse events from the item, so we need to give it // a chance to correct this win->FixUpMouseEvent(widget, event.m_x, event.m_y); - // find the correct window to send the event too: it may be a different one - // from the one which got it at GTK+ level because some control don't have + // find the correct window to send the event to: it may be a different one + // from the one which got it at GTK+ level because some controls don't have // their own X window and thus cannot get any events. if ( !g_captureWindow ) win = FindWindowForMouseEvent(win, event.m_x, event.m_y); +#ifndef __WXGTK20__ gs_timeLastClick = gdk_event->time; -#ifndef __WXGTK20__ if (event_type == wxEVT_LEFT_DCLICK) { // GTK 1.2 crashes when intercepting double @@ -1818,7 +1815,7 @@ static gint gtk_window_button_press_callback( GtkWidget *widget, return FALSE; } } -#endif +#endif // !__WXGTK20__ if (win->GetEventHandler()->ProcessEvent( event )) { @@ -1963,11 +1960,11 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget, // the mouse changed window g_captureWindowHasMouse = hasMouse; - wxMouseEvent event(g_captureWindowHasMouse ? wxEVT_ENTER_WINDOW - : wxEVT_LEAVE_WINDOW); - InitMouseEvent(win, event, gdk_event); - event.SetEventObject(win); - win->GetEventHandler()->ProcessEvent(event); + wxMouseEvent eventM(g_captureWindowHasMouse ? wxEVT_ENTER_WINDOW + : wxEVT_LEAVE_WINDOW); + InitMouseEvent(win, eventM, gdk_event); + eventM.SetEventObject(win); + win->GetEventHandler()->ProcessEvent(eventM); } } else // no capture @@ -2883,11 +2880,22 @@ wxWindowGTK::~wxWindowGTK() m_isBeingDeleted = true; m_hasVMT = false; + // destroy children before destroying this window itself + DestroyChildren(); + + // unhook focus handlers to prevent stray events being + // propagated to this (soon to be) dead object + if (m_focusWidget != NULL) + { + gtk_signal_disconnect_by_func( GTK_OBJECT(m_focusWidget), + (GtkSignalFunc) gtk_window_focus_in_callback, (gpointer) this ); + gtk_signal_disconnect_by_func( GTK_OBJECT(m_focusWidget), + (GtkSignalFunc) gtk_window_focus_out_callback, (gpointer) this ); + } + if (m_widget) Show( false ); - DestroyChildren(); - #ifdef HAVE_XIM if (m_ic) gdk_ic_destroy (m_ic); @@ -2895,6 +2903,11 @@ wxWindowGTK::~wxWindowGTK() gdk_ic_attr_destroy (m_icattr); #endif +#ifdef __WXGTK20__ + // delete before the widgets to avoid a crash on solaris + delete m_imData; +#endif + if (m_wxwindow) { gtk_widget_destroy( m_wxwindow ); @@ -2906,10 +2919,6 @@ wxWindowGTK::~wxWindowGTK() gtk_widget_destroy( m_widget ); m_widget = (GtkWidget*) NULL; } - -#ifdef __WXGTK20__ - delete m_imData; -#endif } bool wxWindowGTK::PreCreation( wxWindowGTK *parent, const wxPoint &pos, const wxSize &size ) @@ -4021,7 +4030,7 @@ void wxWindowGTK::Update() GtkUpdate(); // when we call Update() we really want to update the window immediately on - // screen, even if itmeans flushing the entire queue and hence slowing down + // screen, even if it means flushing the entire queue and hence slowing down // everything -- but it should still be done, it's just that Update() should // be called very rarely gdk_flush(); @@ -4151,8 +4160,7 @@ void wxWindowGTK::GtkSendPaintEvents() m_clipPaintRegion = false; -#ifndef __WXUNIVERSAL__ -#ifndef __WXGTK20__ +#if !defined(__WXUNIVERSAL__) && !defined(__WXGTK20__) // The following code will result in all window-less widgets // being redrawn because the wxWidgets class is allowed to // paint over the window-less widgets. @@ -4173,6 +4181,7 @@ void wxWindowGTK::GtkSendPaintEvents() gdk_event.type = GDK_EXPOSE; gdk_event.window = pizza->bin_window; gdk_event.count = 0; + gdk_event.send_event = TRUE; wxRegionIterator upd( m_updateRegion ); while (upd) @@ -4192,8 +4201,7 @@ void wxWindowGTK::GtkSendPaintEvents() } } } -#endif -#endif +#endif // native GTK 1 m_updateRegion.Clear(); } @@ -4280,12 +4288,10 @@ PangoContext *wxWindowGTK::GtkGetPangoDefaultContext() return gtk_widget_get_pango_context( m_widget ); } +// MR: Returns the same as GtkGetPangoDefaultContext until the symbol can be removed in 2.7.x PangoContext *wxWindowGTK::GtkGetPangoX11Context() { - if (!m_x11Context) - m_x11Context = pango_x_get_context( gdk_display ); - - return m_x11Context; + return gtk_widget_get_pango_context( m_widget ); } #endif @@ -4472,7 +4478,7 @@ bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y ) // NOTE: if you change this code, you need to update // the same code in taskbar.cpp as well. This - // is ugly code duplication, I know, + // is ugly code duplication, I know. SetInvokingWindow( menu, this ); @@ -4699,55 +4705,38 @@ void wxWindowGTK::SetScrollbar( int orient, int pos, int thumbVisible, gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" ); } +void wxWindowGTK::GtkUpdateScrollbar(int orient) +{ + GtkAdjustment *adj = orient == wxHORIZONTAL ? m_hAdjust : m_vAdjust; + GtkSignalFunc fn = orient == wxHORIZONTAL + ? (GtkSignalFunc)gtk_window_hscroll_callback + : (GtkSignalFunc)gtk_window_vscroll_callback; + + gtk_signal_disconnect_by_func(GTK_OBJECT(adj), fn, (gpointer)this); + gtk_signal_emit_by_name(GTK_OBJECT(adj), "value_changed"); + gtk_signal_connect(GTK_OBJECT(adj), "value_changed", fn, (gpointer)this); +} + void wxWindowGTK::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) ) { wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); - wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") ); - if (orient == wxHORIZONTAL) - { - float fpos = (float)pos; - if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size; - if (fpos < 0.0) fpos = 0.0; - m_oldHorizontalPos = fpos; + GtkAdjustment *adj = orient == wxHORIZONTAL ? m_hAdjust : m_vAdjust; - if (fabs(fpos-m_hAdjust->value) < 0.2) return; - m_hAdjust->value = fpos; - } - else - { - float fpos = (float)pos; - if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size; - if (fpos < 0.0) fpos = 0.0; - m_oldVerticalPos = fpos; + float fpos = (float)pos; + if (fpos > adj->upper - adj->page_size) + fpos = adj->upper - adj->page_size; + if (fpos < 0.0) + fpos = 0.0; + *(orient == wxHORIZONTAL ? &m_oldHorizontalPos : &m_oldVerticalPos) = fpos; - if (fabs(fpos-m_vAdjust->value) < 0.2) return; - m_vAdjust->value = fpos; - } + if (fabs(fpos-adj->value) < 0.2) + return; + adj->value = fpos; - if (m_wxwindow->window) + if ( m_wxwindow->window ) { - if (orient == wxHORIZONTAL) - { - gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust), - (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this ); - - gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" ); - - gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed", - (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this ); - } - else - { - gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust), - (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this ); - - gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" ); - - gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed", - (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this ); - } } } @@ -4825,6 +4814,11 @@ void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) ) m_clipPaintRegion = false; } +void wxWindowGTK::SetWindowStyleFlag( long style ) +{ + // Updates the internal variable. NB: Now m_windowStyle bits carry the _new_ style values already + wxWindowBase::SetWindowStyleFlag(style); +} // Find the wxWindow at the current mouse position, also returning the mouse // position.