X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d1f2ac459a122eec2fa2317765b5c30909fca750..b720b24da89b6b60dbabde36f2a995357e3b1497:/src/gtk/window.cpp diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index a566c9ebdb..c12e2fad49 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -54,6 +54,7 @@ #endif #include +#include #include "wx/gtk/private.h" #include @@ -518,7 +519,7 @@ static int gtk_window_expose_callback( GtkWidget *widget, gdk_event->area.height ); // Actual redrawing takes place in idle time. - win->GtkUpdate(); + // win->GtkUpdate(); #ifdef __WXGTK20__ @@ -611,20 +612,12 @@ static void gtk_window_draw_callback( GtkWidget *widget, (char *)"base", 0, 0, -1, -1); } - - - if (!(GTK_WIDGET_APP_PAINTABLE (widget)) && - (pizza->clear_on_draw)) - { - gdk_window_clear_area( pizza->bin_window, - rect->x, rect->y, rect->width, rect->height); - } #endif + win->m_clearRegion.Union( rect->x, rect->y, rect->width, rect->height ); win->GetUpdateRegion().Union( rect->x, rect->y, rect->width, rect->height ); - // Actual redrawing takes place in idle time. - + // Update immediately, not in idle time. win->GtkUpdate(); #ifndef __WXUNIVERSAL__ @@ -953,7 +946,7 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event, KeySym keysym = gdk_event->keyval; - wxLogTrace(TRACE_KEYS, _T("Key %s event: keysym = %d"), + wxLogTrace(TRACE_KEYS, _T("Key %s event: keysym = %ld"), event.GetEventType() == wxEVT_KEY_UP ? _T("release") : _T("press"), keysym); @@ -1023,7 +1016,7 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event, } } - wxLogTrace(TRACE_KEYS, _T("\t-> wxKeyCode %d"), key_code); + wxLogTrace(TRACE_KEYS, _T("\t-> wxKeyCode %ld"), key_code); // sending unknown key events doesn't really make sense if ( !key_code ) @@ -1066,6 +1059,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, if (g_blockEventsOnDrag) return FALSE; + wxKeyEvent event( wxEVT_KEY_DOWN ); if ( !wxTranslateGTKKeyEventToWx(event, win, gdk_event) ) { @@ -1073,6 +1067,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, return FALSE; } + // Emit KEY_DOWN event bool ret = win->GetEventHandler()->ProcessEvent( event ); #if wxUSE_ACCEL @@ -1095,10 +1090,11 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, } #endif // wxUSE_ACCEL - /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x - will only be sent if it is not in an accelerator table. */ - if ( !ret ) + // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x + // will only be sent if it is not in an accelerator table. + if (!ret) { + // Find key code for EVT_CHAR and EVT_CHAR_HOOK events KeySym keysym = gdk_event->keyval; long key_code = wxTranslateKeySymToWXKey(keysym, TRUE /* isChar */); if ( !key_code ) @@ -1118,16 +1114,27 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, { wxLogTrace(TRACE_KEYS, _T("Char event: %ld"), key_code); - // reuse the same event object, just change its type and use the - // translated keycode instead of the raw one - event.SetEventType(wxEVT_CHAR); event.m_keyCode = key_code; + + // Implement OnCharHook by checking ancesteror top level windows + wxWindow *parent = win; + while (parent && !parent->IsTopLevel()) + parent = parent->GetParent(); + if (parent) + { + event.SetEventType( wxEVT_CHAR_HOOK ); + ret = parent->GetEventHandler()->ProcessEvent( event ); + } - ret = win->GetEventHandler()->ProcessEvent( event ); + if (!ret) + { + event.SetEventType(wxEVT_CHAR); + ret = win->GetEventHandler()->ProcessEvent( event ); + } } } - /* win is a control: tab can be propagated up */ + // 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 @@ -1140,15 +1147,15 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, { wxNavigationKeyEvent new_event; new_event.SetEventObject( win->GetParent() ); - /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */ + // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB new_event.SetDirection( (gdk_event->keyval == GDK_Tab) ); - /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */ + // CTRL-TAB changes the (parent) window, i.e. switch notebook page new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) ); new_event.SetCurrentFocus( win ); ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event ); } - /* generate wxID_CANCEL if has been pressed (typically in dialogs) */ + // generate wxID_CANCEL if has been pressed (typically in dialogs) if ( !ret && (gdk_event->keyval == GDK_Escape) ) { @@ -1157,9 +1164,9 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, ret = win->GetEventHandler()->ProcessEvent( new_event ); } - /* Doesn't work. */ -#if 0 // (GTK_MINOR_VERSION > 0) - /* Pressing F10 will activate the menu bar of the top frame. */ + // Doesn't work. +#if 0 + // Pressing F10 will activate the menu bar of the top frame if ( (!ret) && (gdk_event->keyval == GDK_F10) ) { @@ -1192,7 +1199,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" ); return TRUE; } - + return FALSE; } @@ -1238,21 +1245,30 @@ static gint gtk_window_key_release_callback( GtkWidget *widget, // ---------------------------------------------------------------------------- // init wxMouseEvent with the info from gdk_event -#define InitMouseEvent(win, event, gdk_event) \ - { \ - event.SetTimestamp( gdk_event->time ); \ - event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \ - event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \ - event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \ - event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \ - event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \ - event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \ - event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \ -\ - wxPoint pt = win->GetClientAreaOrigin(); \ - event.m_x = (wxCoord)gdk_event->x - pt.x; \ - event.m_y = (wxCoord)gdk_event->y - pt.y; \ - } +// +// NB: this has to be a macro as gdk_event type is different for different +// events we're used with +#define InitMouseEvent(/* wxWindowGTK * */ win, \ + /* wxMouseEvent& */ event, \ + /* GdkEventXXX * */ gdk_event) \ +{ \ + event.SetTimestamp( gdk_event->time ); \ + event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \ + event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \ + event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \ + event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \ + event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \ + event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \ + event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \ + \ + wxPoint pt = win->GetClientAreaOrigin(); \ + event.m_x = (wxCoord)gdk_event->x - pt.x; \ + event.m_y = (wxCoord)gdk_event->y - pt.y; \ + \ + event.SetEventObject( win ); \ + event.SetId( win->GetId() ); \ + event.SetTimestamp( gdk_event->time ); \ +} \ static void AdjustEventButtonState(wxMouseEvent& event) { @@ -1290,11 +1306,14 @@ static void AdjustEventButtonState(wxMouseEvent& event) static wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y) { + wxCoord xx = x; + wxCoord yy = y; + if (win->m_wxwindow) { GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow); - x += pizza->xoffset; - y += pizza->yoffset; + xx += pizza->xoffset; + yy += pizza->yoffset; } wxNode *node = win->GetChildren().First(); @@ -1315,13 +1334,13 @@ wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y) int yy2 = child->m_x + child->m_height; // left - if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) || + if (((xx >= xx1) && (xx <= xx1+10) && (yy >= yy1) && (yy <= yy2)) || // right - ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) || + ((xx >= xx2-10) && (xx <= xx2) && (yy >= yy1) && (yy <= yy2)) || // top - ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) || + ((xx >= xx1) && (xx <= xx2) && (yy >= yy1) && (yy <= yy1+10)) || // bottom - ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2))) + ((xx >= xx1) && (xx <= xx2) && (yy >= yy2-1) && (yy <= yy2))) { win = child; x -= child->m_x; @@ -1333,10 +1352,10 @@ wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y) else { if ((child->m_wxwindow == (GtkWidget*) NULL) && - (child->m_x <= x) && - (child->m_y <= y) && - (child->m_x+child->m_width >= x) && - (child->m_y+child->m_height >= y)) + (child->m_x <= xx) && + (child->m_y <= yy) && + (child->m_x+child->m_width >= xx) && + (child->m_y+child->m_height >= yy)) { win = child; x -= child->m_x; @@ -1436,8 +1455,6 @@ static gint gtk_window_button_press_callback( GtkWidget *widget, if ( !g_captureWindow ) win = FindWindowForMouseEvent(win, event.m_x, event.m_y); - event.SetEventObject( win ); - gs_timeLastClick = gdk_event->time; /* @@ -1501,8 +1518,6 @@ static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButto if ( !g_captureWindow ) win = FindWindowForMouseEvent(win, event.m_x, event.m_y); - event.SetEventObject( win ); - if (win->GetEventHandler()->ProcessEvent( event )) { gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" ); @@ -1573,8 +1588,6 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget, win = FindWindowForMouseEvent(win, event.m_x, event.m_y); } - event.SetEventObject( win ); - if (win->GetEventHandler()->ProcessEvent( event )) { gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" ); @@ -1713,7 +1726,7 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk // always) and makes using Mahogany quite annoying #if 0 wxASSERT_MSG( wxGetTopLevelParent(win) == g_activeFrame, - wxT("unfocusing window that hasn't gained focus properly") ) + wxT("unfocusing window that hasn't gained focus properly") ); #endif // 0 g_activeFrameLostFocus = TRUE; @@ -1767,7 +1780,10 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk // "enter_notify_event" //----------------------------------------------------------------------------- -static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindowGTK *win ) +static +gint gtk_window_enter_callback( GtkWidget *widget, + GdkEventCrossing *gdk_event, + wxWindowGTK *win ) { DEBUG_MAIN_THREAD @@ -1779,16 +1795,13 @@ static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_ if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE; - wxMouseEvent event( wxEVT_ENTER_WINDOW ); - event.SetTimestamp( gdk_event->time ); - event.SetEventObject( win ); - int x = 0; int y = 0; GdkModifierType state = (GdkModifierType)0; gdk_window_get_pointer( widget->window, &x, &y, &state ); + wxMouseEvent event( wxEVT_ENTER_WINDOW ); InitMouseEvent(win, event, gdk_event); wxPoint pt = win->GetClientAreaOrigin(); event.m_x = x + pt.x; @@ -1993,6 +2006,22 @@ wxWindow *wxWindowBase::FindFocus() return (wxWindow *)g_focusWindow; } +//----------------------------------------------------------------------------- +// "destroy" event +//----------------------------------------------------------------------------- + +// VZ: Robert commented the code using out so it generates warnings: should +// be either fixed or removed completely +#if 0 + +static void gtk_window_destroy_callback( GtkWidget* widget, wxWindow *win ) +{ + wxWindowDestroyEvent event(win); + win->GetEventHandler()->ProcessEvent(event); +} + +#endif // 0 + //----------------------------------------------------------------------------- // "realize" from m_widget //----------------------------------------------------------------------------- @@ -2263,8 +2292,6 @@ void wxWindowGTK::Init() m_insertCallback = (wxInsertChildFunction) NULL; - m_isRadioButton = FALSE; - m_isFrame = FALSE; m_acceptsFocus = FALSE; m_hasFocus = FALSE; @@ -2469,17 +2496,17 @@ bool wxWindowGTK::PreCreation( wxWindowGTK *parent, const wxPoint &pos, const w { wxCHECK_MSG( !m_needParent || parent, FALSE, wxT("Need complete parent.") ); - /* this turns -1 into 20 so that a minimal window is - visible even although -1,-1 has been given as the - size of the window. the same trick is used in other - ports and should make debugging easier */ - m_width = WidthDefault(size.x); + // This turns -1 into 30 so that a minimal window is + // visible even although -1,-1 has been given as the + // size of the window. the same trick is used in other + // ports and should make debugging easier. + m_width = WidthDefault(size.x) ; m_height = HeightDefault(size.y); m_x = (int)pos.x; m_y = (int)pos.y; - /* some reasonable defaults */ + // some reasonable defaults if (!parent) { if (m_x == -1) @@ -2609,6 +2636,11 @@ void wxWindowGTK::ConnectWidget( GtkWidget *widget ) gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event", GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this ); + + // This keeps crashing on me. RR. + // + // gtk_signal_connect( GTK_OBJECT(widget), "destroy", + // GTK_SIGNAL_FUNC(gtk_window_destroy_callback), (gpointer)this ); } bool wxWindowGTK::Destroy() @@ -2660,16 +2692,14 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags { if (x != -1) m_x = x + pizza->xoffset; if (y != -1) m_y = y + pizza->yoffset; - if (width != -1) m_width = width; - if (height != -1) m_height = height; } else { m_x = x + pizza->xoffset; m_y = y + pizza->yoffset; - m_width = width; - m_height = height; } + if (width != -1) m_width = width; + if (height != -1) m_height = height; if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH) { @@ -3110,7 +3140,7 @@ void wxWindowGTK::GetTextExtent( const wxString& string, wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") ); GdkFont *font = fontToUse.GetInternalFont( 1.0 ); - if (x) (*x) = gdk_string_width( font, string.mbc_str() ); + if (x) (*x) = gdk_string_width( font, wxGTK_CONV( string ) ); if (y) (*y) = font->ascent + font->descent; if (descent) (*descent) = font->descent; if (externalLeading) (*externalLeading) = 0; // ?? @@ -3277,11 +3307,12 @@ void wxWindowGTK::WarpPointer( int x, int y ) gdk_window_warp_pointer( window, x, y ); } + void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect ) { if (!m_widget) return; if (!m_widget->window) return; - + #ifndef __WXGTK20__ if (g_isIdle) wxapp_install_idle_handler(); @@ -3381,7 +3412,8 @@ void wxWindowGTK::GtkSendPaintEvents() // Clip to paint region in wxClientDC m_clipPaintRegion = TRUE; - + +#ifndef __WXGTK20__ if (GetThemeEnabled()) { // find ancestor from which to steal background @@ -3413,16 +3445,23 @@ void wxWindowGTK::GtkSendPaintEvents() } } else - // if (!m_clearRegion.IsEmpty()) // always send an erase event +#endif +#ifdef __WXGTK20__ + if (!m_clearRegion.IsEmpty()) // Always send an erase event under GTK 1.2 +#endif { wxWindowDC dc( (wxWindow*)this ); - dc.SetClippingRegion( m_clearRegion ); + if (m_clearRegion.IsEmpty()) + dc.SetClippingRegion( m_updateRegion ); + else + dc.SetClippingRegion( m_clearRegion ); wxEraseEvent erase_event( GetId(), &dc ); erase_event.SetEventObject( this ); if (!GetEventHandler()->ProcessEvent(erase_event)) { +#ifndef __WXGTK20__ if (!g_eraseGC) { g_eraseGC = gdk_gc_new( pizza->bin_window ); @@ -3437,6 +3476,7 @@ void wxWindowGTK::GtkSendPaintEvents() upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() ); upd ++; } +#endif } m_clearRegion.Clear(); } @@ -4121,7 +4161,7 @@ void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) ) wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") ); - + // No scrolling requested. if ((dx == 0) && (dy == 0)) return;