#include "wx/layout.h"
#include "wx/statusbr.h"
#include "wx/math.h"
+ #include "wx/module.h"
#endif
-#include "wx/module.h"
-
#if wxUSE_DRAG_AND_DROP
#include "wx/dnd.h"
#endif
#undef HAVE_XIM
#endif
-extern GtkContainerClass *pizza_parent_class;
-
//-----------------------------------------------------------------------------
// documentation on internals
//-----------------------------------------------------------------------------
extern bool g_blockEventsOnScroll;
extern wxCursor g_globalCursor;
-static GdkGC *g_eraseGC = NULL;
-
// mouse capture state: the window which has it and if the mouse is currently
// inside it
static wxWindowGTK *g_captureWindow = (wxWindowGTK*) NULL;
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;
}
}
{
DEBUG_MAIN_THREAD
- if (g_isIdle)
- wxapp_install_idle_handler();
+ // don't need to install idle handler, its done from "event" signal
// This callback gets called in drawing-idle time under
// GTK 2.0, so we don't need to defer anything to idle
GtkPizza *pizza = GTK_PIZZA( widget );
if (gdk_event->window != pizza->bin_window) return FALSE;
+
#if 0
if (win->GetName())
{
win->GtkSendPaintEvents();
-
// Let parent window draw window-less widgets
- (* GTK_WIDGET_CLASS (pizza_parent_class)->expose_event) (widget, gdk_event);
-
return FALSE;
}
}
{
DEBUG_MAIN_THREAD
- if (g_isIdle)
- wxapp_install_idle_handler();
+ // don't need to install idle handler, its done from "event" signal
if (!win->m_hasVMT)
return FALSE;
}
}
-
-
-
-
// win is a control: tab can be propagated up
if ( !ret &&
((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
}
- if (ret)
- {
- g_signal_stop_emission_by_name (widget, "key_press_event");
- return TRUE;
- }
-
- return FALSE;
+ return ret;
}
}
{
DEBUG_MAIN_THREAD
- if (g_isIdle)
- wxapp_install_idle_handler();
+ // don't need to install idle handler, its done from "event" signal
if (!win->m_hasVMT)
return FALSE;
return FALSE;
}
- if ( !win->GetEventHandler()->ProcessEvent( event ) )
- return FALSE;
-
- g_signal_stop_emission_by_name (widget, "key_release_event");
- return TRUE;
+ return win->GTKProcessEvent(event);
}
}
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() );
if (win->m_wxwindow)
{
GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
- xx += pizza->xoffset;
- yy += pizza->yoffset;
+ xx += gtk_pizza_get_xoffset( pizza );
+ yy += gtk_pizza_get_yoffset( pizza );
}
wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
// common event handlers helpers
// ----------------------------------------------------------------------------
+bool wxWindowGTK::GTKProcessEvent(wxEvent& event) const
+{
+ // nothing special at this level
+ return GetEventHandler()->ProcessEvent(event);
+}
+
int wxWindowGTK::GTKCallbackCommonPrologue(GdkEventAny *event) const
{
DEBUG_MAIN_THREAD
- if (g_isIdle)
- wxapp_install_idle_handler();
+ // don't need to install idle handler, its done from "event" signal
if (!m_hasVMT)
return FALSE;
event.SetEventObject( win );
event.SetId( win->GetId() );
- if (win->GetEventHandler()->ProcessEvent( event ))
+ if (win->GTKProcessEvent( event ))
{
- g_signal_stop_emission_by_name (widget, "button_press_event");
return TRUE;
}
win->GetId(),
win->ClientToScreen(event.GetPosition()));
evtCtx.SetEventObject(win);
- return win->GetEventHandler()->ProcessEvent(evtCtx);
+ return win->GTKProcessEvent(evtCtx);
}
return FALSE;
event.SetEventObject( win );
event.SetId( win->GetId() );
- if (win->GetEventHandler()->ProcessEvent( event ))
- {
- g_signal_stop_emission_by_name (widget, "button_release_event");
- return TRUE;
- }
-
- return FALSE;
+ return win->GTKProcessEvent(event);
}
//-----------------------------------------------------------------------------
: wxEVT_LEAVE_WINDOW);
InitMouseEvent(win, eventM, gdk_event);
eventM.SetEventObject(win);
- win->GetEventHandler()->ProcessEvent(eventM);
+ win->GTKProcessEvent(eventM);
}
}
else // no capture
if ( !g_captureWindow )
{
wxSetCursorEvent cevent( event.m_x, event.m_y );
- if (win->GetEventHandler()->ProcessEvent( cevent ))
+ if (win->GTKProcessEvent( cevent ))
{
- // Rewrite cursor handling here (away from idle).
+ win->SetCursor( cevent.GetCursor() );
}
}
- if (win->GetEventHandler()->ProcessEvent( event ))
- {
- g_signal_stop_emission_by_name (widget, "motion_notify_event");
- return TRUE;
- }
-
- return FALSE;
+ return win->GTKProcessEvent(event);
}
//-----------------------------------------------------------------------------
{
DEBUG_MAIN_THREAD
- if (g_isIdle)
- wxapp_install_idle_handler();
+ // don't need to install idle handler, its done from "event" signal
if (gdk_event->direction != GDK_SCROLL_UP &&
gdk_event->direction != GDK_SCROLL_DOWN)
event.SetId( win->GetId() );
event.SetTimestamp( gdk_event->time );
- return win->GetEventHandler()->ProcessEvent(event);
+ return win->GTKProcessEvent(event);
}
//-----------------------------------------------------------------------------
{
wxContextMenuEvent event(wxEVT_CONTEXT_MENU, win->GetId(), wxPoint(-1, -1));
event.SetEventObject(win);
- return win->GetEventHandler()->ProcessEvent(event);
+ return win->GTKProcessEvent(event);
}
//-----------------------------------------------------------------------------
{
DEBUG_MAIN_THREAD
- if (g_isIdle)
- wxapp_install_idle_handler();
+ // don't need to install idle handler, its done from "event" signal
if (win->m_imData)
gtk_im_context_focus_in(win->m_imData->context);
{
DEBUG_MAIN_THREAD
- if (g_isIdle)
- wxapp_install_idle_handler();
+ // don't need to install idle handler, its done from "event" signal
if (win->m_imData)
gtk_im_context_focus_out(win->m_imData->context);
wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
event.SetEventObject( win );
- (void)win->GetEventHandler()->ProcessEvent( event );
+ (void)win->GTKProcessEvent( event );
ret = TRUE;
}
if ( !g_captureWindow )
{
wxSetCursorEvent cevent( event.m_x, event.m_y );
- if (win->GetEventHandler()->ProcessEvent( cevent ))
+ if (win->GTKProcessEvent( cevent ))
{
- // Rewrite cursor handling here (away from idle).
+ win->SetCursor( cevent.GetCursor() );
}
}
- if (win->GetEventHandler()->ProcessEvent( event ))
- {
- g_signal_stop_emission_by_name (widget, "enter_notify_event");
- return TRUE;
- }
-
- return FALSE;
+ return win->GTKProcessEvent(event);
}
//-----------------------------------------------------------------------------
event.m_x = x + pt.x;
event.m_y = y + pt.y;
- if (win->GetEventHandler()->ProcessEvent( event ))
- {
- g_signal_stop_emission_by_name (widget, "leave_notify_event");
- return TRUE;
- }
-
- return FALSE;
+ return win->GTKProcessEvent(event);
}
//-----------------------------------------------------------------------------
event.SetEventObject(win);
win->m_blockValueChanged[dir] = true;
- win->GetEventHandler()->ProcessEvent(event);
+ win->GTKProcessEvent(event);
win->m_blockValueChanged[dir] = false;
}
}
{
DEBUG_MAIN_THREAD
- if (g_isIdle)
- wxapp_install_idle_handler();
+ // don't need to install idle handler, its done from "event" signal
g_blockEventsOnScroll = true;
win->m_mouseButtonDown = true;
win->ScrollDirFromRange(range));
wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBRELEASE, win->GetScrollPos(orient), orient);
event.SetEventObject(win);
- win->GetEventHandler()->ProcessEvent(event);
+ win->GTKProcessEvent(event);
}
}
wxWindowCreateEvent event( win );
event.SetEventObject( win );
- win->GetEventHandler()->ProcessEvent( event );
+ win->GTKProcessEvent( event );
}
//-----------------------------------------------------------------------------
static
void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
- GtkAllocation *WXUNUSED(alloc),
+ GtkAllocation *alloc,
wxWindow *win )
{
if (g_isIdle)
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
+
+ GTK_PIZZA(win->m_wxwindow)->m_width = win->GetClientSize().x;
+
win->m_oldClientWidth = client_width;
win->m_oldClientHeight = client_height;
{
wxSizeEvent event( win->GetSize(), win->GetId() );
event.SetEventObject( win );
- win->GetEventHandler()->ProcessEvent( event );
+ win->GTKProcessEvent( event );
}
}
/* the window might have been scrolled already, do we
have to adapt the position */
GtkPizza *pizza = GTK_PIZZA(parent->m_wxwindow);
- child->m_x += pizza->xoffset;
- child->m_y += pizza->yoffset;
+ child->m_x += gtk_pizza_get_xoffset( pizza );
+ child->m_y += gtk_pizza_get_yoffset( pizza );
gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
GTK_WIDGET(child->m_widget),
m_hasVMT = false;
m_needParent = true;
m_isBeingDeleted = false;
-
+
m_showOnIdle= false;
m_noExpose = false;
#ifndef __WXUNIVERSAL__
GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
-
+
if (HasFlag(wxRAISED_BORDER))
{
gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_OUT );
{
// 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
this);
}
#ifdef GTK_IS_FILE_CHOOSER_BUTTON
- else if (GTK_IS_FILE_CHOOSER_BUTTON(m_widget))
+ else if (!gtk_check_version(2,6,0) && GTK_IS_FILE_CHOOSER_BUTTON(m_widget))
{
// If we connect to the "size_request" signal of a GtkFileChooserButton
// then that control won't be sized properly when placed inside sizers
m_hasVMT = true;
+ SetLayoutDirection(wxLayout_Default);
+
// unless the window was created initially hidden (i.e. Hide() had been
// called before Create()), we should show it at GTK+ level as well
if ( IsShown() )
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 )
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;
// don't take the x,y values, they're wrong because toolbar sets them
GtkWidget *widget = GTK_WIDGET(m_widget);
gtk_widget_set_size_request (widget, m_width, m_height);
- if (GTK_WIDGET_VISIBLE (widget))
- gtk_widget_queue_resize (widget);
}
else
#endif
GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
{
- if (x != -1) m_x = x + pizza->xoffset;
- if (y != -1) m_y = y + pizza->yoffset;
+ if (x != -1) m_x = x + gtk_pizza_get_xoffset( pizza );
+ if (y != -1) m_y = y + gtk_pizza_get_yoffset( pizza );
}
else
{
- m_x = x + pizza->xoffset;
- m_y = y + pizza->yoffset;
+ m_x = x + gtk_pizza_get_xoffset( pizza );
+ m_y = y + gtk_pizza_get_yoffset( pizza );
}
int left_border = 0;
m_showOnIdle = false;
return true;
}
-
+
return false;
}
SetBackgroundStyle(GetBackgroundStyle());
m_needsStyleChange = false;
}
-
- // Update invalidated regions.
- GtkUpdate();
wxCursor cursor = m_cursor;
if (g_globalCursor.Ok()) cursor = g_globalCursor;
w -= dw;
h -= dh;
+ if (w < 0)
+ w = 0;
+ if (h < 0)
+ h = 0;
}
if (width) *width = w;
if (m_parent && m_parent->m_wxwindow)
{
GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
- dx = pizza->xoffset;
- dy = pizza->yoffset;
+ dx = gtk_pizza_get_xoffset( pizza );
+ 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);
+
+ ((wxWindowGTK*) this)->m_x = org_x;
+ ((wxWindowGTK*) this)->m_y = org_y;
+ }
}
if (x) (*x) = m_x - dx;
}
}
- 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;
}
}
}
- 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;
}
m_showOnIdle = true;
gtk_widget_hide( m_widget );
}
-
+
/* insert GTK representation */
(*(newParent->m_insertCallback))(newParent, this);
}
/* reverse: prevent GTK from deleting the widget arbitrarily */
gtk_widget_unref( m_widget );
+ SetLayoutDirection(wxLayout_Default);
+
return true;
}
wxapp_install_idle_handler();
}
+/* static */
+wxLayoutDirection wxWindowGTK::GTKGetLayout(GtkWidget *widget)
+{
+ return gtk_widget_get_direction(GTK_WIDGET(widget)) == GTK_TEXT_DIR_RTL
+ ? wxLayout_RightToLeft
+ : wxLayout_LeftToRight;
+}
+
+/* static */
+void wxWindowGTK::GTKSetLayout(GtkWidget *widget, wxLayoutDirection dir)
+{
+ wxASSERT_MSG( dir != wxLayout_Default, _T("invalid layout direction") );
+
+ gtk_widget_set_direction(GTK_WIDGET(widget),
+ dir == wxLayout_RightToLeft ? GTK_TEXT_DIR_RTL
+ : GTK_TEXT_DIR_LTR);
+}
+
+wxLayoutDirection wxWindowGTK::GetLayoutDirection() const
+{
+ return GTKGetLayout(m_widget);
+}
+
+void wxWindowGTK::SetLayoutDirection(wxLayoutDirection dir)
+{
+ if ( dir == wxLayout_Default )
+ {
+ const wxWindow *const parent = GetParent();
+ if ( parent )
+ {
+ // inherit layout from parent.
+ dir = parent->GetLayoutDirection();
+ }
+ else // no parent, use global default layout
+ {
+ dir = wxTheApp->GetLayoutDirection();
+ }
+ }
+
+ if ( dir == wxLayout_Default )
+ 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)
{
wxWindowBase::DoMoveInTabOrder(win, move);
bool wxWindowGTK::SetCursor( const wxCursor &cursor )
{
- wxCHECK_MSG( (m_widget != NULL), false, wxT("invalid window") );
-
- if (cursor == m_cursor)
- return false;
+ if ( !wxWindowBase::SetCursor(cursor.Ok() ? cursor : *wxSTANDARD_CURSOR) )
+ return false;
- if (g_isIdle)
- wxapp_install_idle_handler();
+ GTKUpdateCursor();
- return wxWindowBase::SetCursor( cursor.Ok() ? cursor : *wxSTANDARD_CURSOR );
+ return true;
}
void wxWindowGTK::GTKUpdateCursor()
const size_t count = windowsThis.size();
for ( size_t n = 0; n < count; n++ )
{
- gdk_window_set_cursor(windowsThis[n], cursor.GetCursor());
+ GdkWindow *win = windowsThis[n];
+ if ( !win )
+ {
+ wxFAIL_MSG(_T("NULL window returned by GTKGetWindow()?"));
+ continue;
+ }
+
+ gdk_window_set_cursor(win, cursor.GetCursor());
}
}
}
if (m_wxwindow)
{
if (!GTK_PIZZA(m_wxwindow)->bin_window) return;
-
+
GdkRectangle gdk_rect,
*p;
if (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 );
}
}
}
}
+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)
// Clip to paint region in wxClientDC
m_clipPaintRegion = true;
+ wxRegion maybe_rtl_region = m_updateRegion;
+
+#if 0
+ if (GetLayoutDirection() == wxLayout_RightToLeft)
+ {
+ maybe_rtl_region.Clear();
+
+ gint width;
+ gdk_window_get_geometry( GTK_PIZZA(m_wxwindow)->bin_window,
+ NULL, NULL, &width, NULL, NULL );
+
+ wxRegionIterator upd( m_updateRegion );
+ 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;
+ maybe_rtl_region.Union( rect );
+
+ ++upd;
+ }
+ }
+#endif
+
// widget to draw on
GtkPizza *pizza = GTK_PIZZA (m_wxwindow);
}
}
else
-
{
+ m_updateRegion = maybe_rtl_region;
+
wxWindowDC dc( (wxWindow*)this );
dc.SetClippingRegion( m_updateRegion );
GetEventHandler()->ProcessEvent(erase_event);
}
+ m_updateRegion = maybe_rtl_region;
+
wxNcPaintEvent nc_paint_event( GetId() );
nc_paint_event.SetEventObject( this );
GetEventHandler()->ProcessEvent( nc_paint_event );
{
gtk_grab_remove( (GtkWidget*) window->GetHandle() );
}
-
-// ----------------------------------------------------------------------------
-// wxWinModule
-// ----------------------------------------------------------------------------
-
-class wxWinModule : public wxModule
-{
-public:
- bool OnInit();
- void OnExit();
-
-private:
- DECLARE_DYNAMIC_CLASS(wxWinModule)
-};
-
-IMPLEMENT_DYNAMIC_CLASS(wxWinModule, wxModule)
-
-bool wxWinModule::OnInit()
-{
- // g_eraseGC = gdk_gc_new( gdk_get_default_root_window() );
- // gdk_gc_set_fill( g_eraseGC, GDK_SOLID );
-
- return true;
-}
-
-void wxWinModule::OnExit()
-{
- if (g_eraseGC)
- g_object_unref (g_eraseGC);
-}