X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a31bb9442581e64799025a86153a0af9aec5317c..4913272f9cdead94a6d1470e51d6fb14946b50e0:/src/gtk/window.cpp diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index ab595ed612..a4edb3bbd8 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -17,37 +17,24 @@ #include "wx/window.h" #ifndef WX_PRECOMP - #include "wx/intl.h" #include "wx/log.h" #include "wx/app.h" - #include "wx/utils.h" #include "wx/frame.h" #include "wx/dcclient.h" #include "wx/menu.h" - #include "wx/dialog.h" #include "wx/settings.h" #include "wx/msgdlg.h" #include "wx/textctrl.h" + #include "wx/radiobut.h" #include "wx/toolbar.h" #include "wx/combobox.h" #include "wx/layout.h" - #include "wx/statusbr.h" #include "wx/math.h" - #include "wx/module.h" #endif -#if wxUSE_DRAG_AND_DROP - #include "wx/dnd.h" -#endif - -#if wxUSE_TOOLTIPS - #include "wx/tooltip.h" -#endif - -#if wxUSE_CARET - #include "wx/caret.h" -#endif // wxUSE_CARET - +#include "wx/dnd.h" +#include "wx/tooltip.h" +#include "wx/caret.h" #include "wx/fontutil.h" #ifdef __WXDEBUG__ @@ -59,27 +46,16 @@ // FIXME: Due to a hack we use GtkCombo in here, which is deprecated since gtk2.3.0 #include #if defined(GTK_DISABLE_DEPRECATED) && GTK_CHECK_VERSION(2,3,0) -#undef GTK_DISABLE_DEPRECATED + #undef GTK_DISABLE_DEPRECATED + #include + #define GTK_DISABLE_DEPRECATED #endif #include "wx/gtk/private.h" -#include +#include "wx/gtk/win_gtk.h" #include #include -#include -#include - -#include "wx/gtk/win_gtk.h" - -#include - -#ifdef HAVE_XIM - #undef HAVE_XIM -#endif - -extern GtkContainerClass *pizza_parent_class; - //----------------------------------------------------------------------------- // documentation on internals //----------------------------------------------------------------------------- @@ -340,14 +316,6 @@ static void draw_frame( GtkWidget *widget, wxWindowGTK *win ) if (!win->m_hasVMT) return; - int dw = 0; - int dh = 0; - - if (win->m_hasScrolling) - { - GetScrollbarWidth(widget, dw, dh); - } - int dx = 0; int dy = 0; if (GTK_WIDGET_NO_WINDOW (widget)) @@ -356,6 +324,27 @@ static void draw_frame( GtkWidget *widget, wxWindowGTK *win ) dy += widget->allocation.y; } + int x = dx; + int y = dy; + + int dw = 0; + int dh = 0; + if (win->m_hasScrolling) + { + GetScrollbarWidth(widget, dw, dh); + + if (win->GetLayoutDirection() == wxLayout_RightToLeft) + { + // This is actually wrong for old GTK+ version + // which do not display the scrollbar on the + // left side in RTL + x += dw; + } + } + + int w = widget->allocation.width-dw; + int h = widget->allocation.height-dh; + if (win->HasFlag(wxRAISED_BORDER)) { gtk_paint_shadow (widget->style, @@ -363,8 +352,7 @@ static void draw_frame( GtkWidget *widget, wxWindowGTK *win ) GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, NULL, NULL, // FIXME: No clipping? - dx, dy, - widget->allocation.width-dw, widget->allocation.height-dh ); + x, y, w, h ); return; } @@ -375,8 +363,7 @@ static void draw_frame( GtkWidget *widget, wxWindowGTK *win ) GTK_STATE_NORMAL, GTK_SHADOW_IN, NULL, NULL, NULL, // FIXME: No clipping? - dx, dy, - widget->allocation.width-dw, widget->allocation.height-dh ); + x, y, w, h ); return; } @@ -385,9 +372,7 @@ static void draw_frame( GtkWidget *widget, wxWindowGTK *win ) GdkGC *gc; gc = gdk_gc_new( widget->window ); gdk_gc_set_foreground( gc, &widget->style->black ); - gdk_draw_rectangle( widget->window, gc, FALSE, - dx, dy, - widget->allocation.width-dw-1, widget->allocation.height-dh-1 ); + gdk_draw_rectangle( widget->window, gc, FALSE, x, y, w-1, h-1 ); g_object_unref (gc); return; } @@ -404,13 +389,9 @@ gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindowGTK *win ) { - if (gdk_event->count > 0) return FALSE; - - draw_frame( widget, win ); - - (* GTK_WIDGET_CLASS (pizza_parent_class)->expose_event) (widget, gdk_event); - - return TRUE; + if (gdk_event->count == 0) + draw_frame(widget, win); + return false; } } @@ -486,6 +467,7 @@ gtk_window_expose_callback( GtkWidget *widget, GtkPizza *pizza = GTK_PIZZA( widget ); if (gdk_event->window != pizza->bin_window) return FALSE; + #if 0 if (win->GetName()) { @@ -515,10 +497,7 @@ gtk_window_expose_callback( GtkWidget *widget, win->GtkSendPaintEvents(); - // Let parent window draw window-less widgets - (* GTK_WIDGET_CLASS (pizza_parent_class)->expose_event) (widget, gdk_event); - return FALSE; } } @@ -1282,6 +1261,13 @@ template void InitMouseEvent(wxWindowGTK *win, wxPoint pt = win->GetClientAreaOrigin(); event.m_x = (wxCoord)gdk_event->x - pt.x; event.m_y = (wxCoord)gdk_event->y - pt.y; + + if ((win->m_wxwindow) && (win->GetLayoutDirection() == wxLayout_RightToLeft)) + { + // origin in the upper right corner + int window_width = gtk_pizza_get_rtl_offset( GTK_PIZZA(win->m_wxwindow) ); + event.m_x = window_width - event.m_x; + } event.SetEventObject( win ); event.SetId( win->GetId() ); @@ -1819,11 +1805,6 @@ gtk_window_focus_in_callback( GtkWidget *widget, wxLogTrace(TRACE_FOCUS, _T("%s: focus in"), win->GetName().c_str()); -#ifdef HAVE_XIM - if (win->m_ic) - gdk_im_begin(win->m_ic, win->m_wxwindow->window); -#endif - #if wxUSE_CARET // caret needs to be informed about focus change wxCaret *caret = win->GetCaret(); @@ -1880,11 +1861,6 @@ gtk_window_focus_out_callback( GtkWidget *widget, g_focusWindow = (wxWindowGTK *)NULL; -#ifdef HAVE_XIM - if (win->m_ic) - gdk_im_end(); -#endif - #if wxUSE_CARET // caret needs to be informed about focus change wxCaret *caret = win->GetCaret(); @@ -2012,7 +1988,7 @@ gtk_scrollbar_value_changed(GtkRange* range, wxWindow* win) wxWindowGTK::ScrollDir dir = win->ScrollDirFromRange(range); // generate the corresponding wx event - const int orient = win->OrientFromScrollDir(dir); + const int orient = wxWindow::OrientFromScrollDir(dir); wxScrollWinEvent event(eventType, win->GetScrollPos(orient), orient); event.SetEventObject(win); @@ -2050,7 +2026,7 @@ gtk_scrollbar_event_after(GtkRange* range, GdkEvent* event, wxWindow* win) { g_signal_handlers_block_by_func(range, (void*)gtk_scrollbar_event_after, win); - const int orient = win->OrientFromScrollDir( + const int orient = wxWindow::OrientFromScrollDir( win->ScrollDirFromRange(range)); wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBRELEASE, win->GetScrollPos(orient), orient); event.SetEventObject(win); @@ -2115,7 +2091,7 @@ gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win ) static void gtk_window_size_callback( GtkWidget *WXUNUSED(widget), - GtkAllocation *WXUNUSED(alloc), + GtkAllocation *alloc, wxWindow *win ) { if (g_isIdle) @@ -2127,6 +2103,17 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget), if ((client_width == win->m_oldClientWidth) && (client_height == win->m_oldClientHeight)) return; +#if 0 + wxPrintf( wxT("size_allocate ") ); + if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) + wxPrintf( win->GetClassInfo()->GetClassName() ); + wxPrintf( wxT(" %d %d %d %d\n"), + alloc->x, + alloc->y, + alloc->width, + alloc->height ); +#endif + win->m_oldClientWidth = client_width; win->m_oldClientHeight = client_height; @@ -2138,129 +2125,6 @@ void gtk_window_size_callback( GtkWidget *WXUNUSED(widget), } } - -#ifdef HAVE_XIM - #define WXUNUSED_UNLESS_XIM(param) param -#else - #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param) -#endif - -/* Resize XIM window */ -static -void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget), - GtkAllocation* WXUNUSED_UNLESS_XIM(alloc), - wxWindowGTK* WXUNUSED_UNLESS_XIM(win) ) -{ - if (g_isIdle) - wxapp_install_idle_handler(); - -#ifdef HAVE_XIM - if (!win->m_ic) - return; - - if (gdk_ic_get_style (win->m_ic) & GDK_IM_PREEDIT_POSITION) - { - gint width, height; - - gdk_drawable_get_size (widget->window, &width, &height); - win->m_icattr->preedit_area.width = width; - win->m_icattr->preedit_area.height = height; - gdk_ic_set_attr (win->m_ic, win->m_icattr, GDK_IC_PREEDIT_AREA); - } -#endif // HAVE_XIM -} - -//----------------------------------------------------------------------------- -// "realize" from m_wxwindow -//----------------------------------------------------------------------------- - -/* Initialize XIM support */ - -static void -gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget), - wxWindowGTK * WXUNUSED_UNLESS_XIM(win) ) -{ - if (g_isIdle) - wxapp_install_idle_handler(); - -#ifdef HAVE_XIM - if (win->m_ic) return; - if (!widget) return; - if (!gdk_im_ready()) return; - - win->m_icattr = gdk_ic_attr_new(); - if (!win->m_icattr) return; - - gint width, height; - GdkEventMask mask; - GdkColormap *colormap; - GdkICAttr *attr = win->m_icattr; - unsigned attrmask = GDK_IC_ALL_REQ; - GdkIMStyle style; - GdkIMStyle supported_style = (GdkIMStyle) - (GDK_IM_PREEDIT_NONE | - GDK_IM_PREEDIT_NOTHING | - GDK_IM_PREEDIT_POSITION | - GDK_IM_STATUS_NONE | - GDK_IM_STATUS_NOTHING); - - if (widget->style && widget->style->font->type != GDK_FONT_FONTSET) - supported_style = (GdkIMStyle)(supported_style & ~GDK_IM_PREEDIT_POSITION); - - attr->style = style = gdk_im_decide_style (supported_style); - attr->client_window = widget->window; - - if ((colormap = gtk_widget_get_colormap (widget)) != - gtk_widget_get_default_colormap ()) - { - attrmask |= GDK_IC_PREEDIT_COLORMAP; - attr->preedit_colormap = colormap; - } - - attrmask |= GDK_IC_PREEDIT_FOREGROUND; - attrmask |= GDK_IC_PREEDIT_BACKGROUND; - attr->preedit_foreground = widget->style->fg[GTK_STATE_NORMAL]; - attr->preedit_background = widget->style->base[GTK_STATE_NORMAL]; - - switch (style & GDK_IM_PREEDIT_MASK) - { - case GDK_IM_PREEDIT_POSITION: - if (widget->style && widget->style->font->type != GDK_FONT_FONTSET) - { - g_warning ("over-the-spot style requires fontset"); - break; - } - - gdk_drawable_get_size (widget->window, &width, &height); - - attrmask |= GDK_IC_PREEDIT_POSITION_REQ; - attr->spot_location.x = 0; - attr->spot_location.y = height; - attr->preedit_area.x = 0; - attr->preedit_area.y = 0; - attr->preedit_area.width = width; - attr->preedit_area.height = height; - attr->preedit_fontset = widget->style->font; - - break; - } - - win->m_ic = gdk_ic_new (attr, (GdkICAttributesType)attrmask); - - if (win->m_ic == NULL) - g_warning ("Can't create input context."); - else - { - mask = gdk_window_get_events (widget->window); - mask = (GdkEventMask)(mask | gdk_ic_get_events (win->m_ic)); - gdk_window_set_events (widget->window, mask); - - if (GTK_WIDGET_HAS_FOCUS(widget)) - gdk_im_begin (win->m_ic, widget->window); - } -#endif // HAVE_XIM -} - } // extern "C" // ---------------------------------------------------------------------------- @@ -2448,12 +2312,14 @@ bool wxWindowGTK::Create( wxWindow *parent, m_scrollBar[ScrollDir_Horz] = GTK_RANGE(scrolledWindow->hscrollbar); m_scrollBar[ScrollDir_Vert] = GTK_RANGE(scrolledWindow->vscrollbar); + if (GetLayoutDirection() == wxLayout_RightToLeft) + gtk_range_set_inverted( m_scrollBar[ScrollDir_Horz], TRUE ); m_wxwindow = gtk_pizza_new(); #ifndef __WXUNIVERSAL__ GtkPizza *pizza = GTK_PIZZA(m_wxwindow); - + if (HasFlag(wxRAISED_BORDER)) { gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_OUT ); @@ -2540,13 +2406,6 @@ wxWindowGTK::~wxWindowGTK() if (m_widget) Show( false ); -#ifdef HAVE_XIM - if (m_ic) - gdk_ic_destroy (m_ic); - if (m_icattr) - gdk_ic_attr_destroy (m_icattr); -#endif - // delete before the widgets to avoid a crash on solaris delete m_imData; @@ -2588,12 +2447,11 @@ void wxWindowGTK::PostCreation() { // these get reported to wxWidgets -> wxPaintEvent - gtk_pizza_set_external( GTK_PIZZA(m_wxwindow), TRUE ); - g_signal_connect (m_wxwindow, "expose_event", G_CALLBACK (gtk_window_expose_callback), this); - gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), HasFlag( wxFULL_REPAINT_ON_RESIZE ) ); + if (GetLayoutDirection() == wxLayout_LeftToRight) + gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), HasFlag( wxFULL_REPAINT_ON_RESIZE ) ); } // Create input method handler @@ -2649,14 +2507,6 @@ void wxWindowGTK::PostCreation() // Catch native resize events g_signal_connect (m_wxwindow, "size_allocate", G_CALLBACK (gtk_window_size_callback), this); - - // Initialize XIM support - g_signal_connect (m_wxwindow, "realize", - G_CALLBACK (gtk_wxwindow_realized_callback), this); - - // And resize XIM window - g_signal_connect (m_wxwindow, "size_allocate", - G_CALLBACK (gtk_wxwindow_size_callback), this); } if (GTK_IS_COMBO(m_widget)) @@ -2732,7 +2582,9 @@ bool wxWindowGTK::Destroy() void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height) { + // inform the parent to perform the move gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow), m_widget, x, y, width, height ); + } void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags ) @@ -2740,10 +2592,6 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") ); wxASSERT_MSG( (m_parent != NULL), wxT("wxWindowGTK::SetSize requires parent.\n") ); -/* - printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height ); -*/ - if (m_resizing) return; /* I don't like recursions */ m_resizing = true; @@ -2999,9 +2847,7 @@ void wxWindowGTK::DoGetClientSize( int *width, int *height ) const int dh = 0; if (m_hasScrolling) - { GetScrollbarWidth(m_widget, dw, dh); - } #ifndef __WXUNIVERSAL__ if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER)) @@ -3043,6 +2889,28 @@ void wxWindowGTK::DoGetPosition( int *x, int *y ) const dy = gtk_pizza_get_yoffset( pizza ); } + if (m_x == -1 && m_y == -1) + { + GdkWindow *source = (GdkWindow *) NULL; + if (m_wxwindow) + source = GTK_PIZZA(m_wxwindow)->bin_window; + else + source = m_widget->window; + + if (source) + { + int org_x = 0; + int org_y = 0; + gdk_window_get_origin( source, &org_x, &org_y ); + + if (GetParent()) + GetParent()->ScreenToClient(&org_x, &org_y); + + wx_const_cast(wxWindowGTK*, this)->m_x = org_x; + wx_const_cast(wxWindowGTK*, this)->m_y = org_y; + } + } + if (x) (*x) = m_x - dx; if (y) (*y) = m_y - dy; } @@ -3072,7 +2940,15 @@ void wxWindowGTK::DoClientToScreen( int *x, int *y ) const } } - if (x) *x += org_x; + + if (x) + { + if (GetLayoutDirection() == wxLayout_RightToLeft) + *x = (GetClientSize().x - *x) + org_x; + else + *x += org_x; + } + if (y) *y += org_y; } @@ -3101,7 +2977,13 @@ void wxWindowGTK::DoScreenToClient( int *x, int *y ) const } } - if (x) *x -= org_x; + if (x) + { + if (GetLayoutDirection() == wxLayout_RightToLeft) + *x = (GetClientSize().x - *x) - org_x; + else + *x -= org_x; + } if (y) *y -= org_y; } @@ -3319,6 +3201,12 @@ void wxWindowGTK::SetFocus() { if (GTK_IS_CONTAINER(m_widget)) { + if (IsKindOf(CLASSINFO(wxRadioButton))) + { + gtk_widget_grab_focus (m_widget); + return; + } + gtk_widget_child_focus( m_widget, GTK_DIR_TAB_FORWARD ); } else @@ -3477,6 +3365,18 @@ void wxWindowGTK::SetLayoutDirection(wxLayoutDirection dir) return; GTKSetLayout(m_widget, dir); + + if (m_wxwindow) + GTKSetLayout(m_wxwindow, dir); +} + +wxCoord +wxWindowGTK::AdjustForLayoutDirection(wxCoord x, + wxCoord WXUNUSED(width), + wxCoord WXUNUSED(widthTotal)) const +{ + // We now mirrors the coordinates of RTL windows in GtkPizza + return x; } void wxWindowGTK::DoMoveInTabOrder(wxWindow *win, MoveKind move) @@ -3705,13 +3605,16 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect ) gdk_rect.y = rect->y; gdk_rect.width = rect->width; gdk_rect.height = rect->height; + if (GetLayoutDirection() == wxLayout_RightToLeft) + gdk_rect.x = GetClientSize().x - gdk_rect.x - gdk_rect.width; + p = &gdk_rect; } else // invalidate everything { p = NULL; } - + gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow)->bin_window, p, TRUE ); } } @@ -3745,6 +3648,20 @@ void wxWindowGTK::GtkUpdate() } } +bool wxWindowGTK::DoIsExposed( int x, int y ) const +{ + return m_updateRegion.Contains(x, y) != wxOutRegion; +} + + +bool wxWindowGTK::DoIsExposed( int x, int y, int w, int h ) const +{ + if (GetLayoutDirection() == wxLayout_RightToLeft) + return m_updateRegion.Contains(x-w, y, w, h) != wxOutRegion; + else + return m_updateRegion.Contains(x, y, w, h) != wxOutRegion; +} + void wxWindowGTK::GtkSendPaintEvents() { if (!m_wxwindow) @@ -3756,6 +3673,33 @@ void wxWindowGTK::GtkSendPaintEvents() // Clip to paint region in wxClientDC m_clipPaintRegion = true; + m_nativeUpdateRegion = m_updateRegion; + + if (GetLayoutDirection() == wxLayout_RightToLeft) + { + // Transform m_updateRegion under RTL + m_updateRegion.Clear(); + + gint width; + gdk_window_get_geometry( GTK_PIZZA(m_wxwindow)->bin_window, + NULL, NULL, &width, NULL, NULL ); + + wxRegionIterator upd( m_nativeUpdateRegion ); + while (upd) + { + wxRect rect; + rect.x = upd.GetX(); + rect.y = upd.GetY(); + rect.width = upd.GetWidth(); + rect.height = upd.GetHeight(); + + rect.x = width - rect.x - rect.width; + m_updateRegion.Union( rect ); + + ++upd; + } + } + // widget to draw on GtkPizza *pizza = GTK_PIZZA (m_wxwindow); @@ -3768,7 +3712,7 @@ void wxWindowGTK::GtkSendPaintEvents() if (GTK_WIDGET_MAPPED(parent->m_widget)) { - wxRegionIterator upd( m_updateRegion ); + wxRegionIterator upd( m_nativeUpdateRegion ); while (upd) { GdkRectangle rect; @@ -3791,7 +3735,6 @@ void wxWindowGTK::GtkSendPaintEvents() } } else - { wxWindowDC dc( (wxWindow*)this ); dc.SetClippingRegion( m_updateRegion ); @@ -3813,6 +3756,7 @@ void wxWindowGTK::GtkSendPaintEvents() m_clipPaintRegion = false; m_updateRegion.Clear(); + m_nativeUpdateRegion.Clear(); } void wxWindowGTK::SetDoubleBuffered( bool on ) @@ -3823,6 +3767,11 @@ void wxWindowGTK::SetDoubleBuffered( bool on ) gtk_widget_set_double_buffered( m_wxwindow, on ); } +bool wxWindowGTK::IsDoubleBuffered() const +{ + return GTK_WIDGET_DOUBLE_BUFFERED( m_wxwindow ); +} + void wxWindowGTK::ClearBackground() { wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); @@ -4186,8 +4135,8 @@ void wxWindowGTK::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh)) pos = max; if (pos < 0) pos = 0; - m_scrollPos[dir] = - adj->value = pos; + m_scrollPos[dir] = adj->value = pos; + // If a "value_changed" signal emission is not already in progress if (!m_blockValueChanged[dir]) { @@ -4240,7 +4189,9 @@ wxEventType wxWindowGTK::GetScrollEventType(GtkRange* range) const int barIndex = range == m_scrollBar[1]; GtkAdjustment* adj = range->adjustment; + const int value = int(adj->value + 0.5); + // save previous position const double oldPos = m_scrollPos[barIndex]; // update current position @@ -4286,7 +4237,10 @@ void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) ) m_clipPaintRegion = true; - gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy ); + if (GetLayoutDirection() == wxLayout_RightToLeft) + gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), dx, -dy ); + else + gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy ); m_clipPaintRegion = false; }