#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
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;
{
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);
{
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 );
}
- // generate wxID_CANCEL if <esc> has been pressed (typically in dialogs)
- if ( !ret &&
- (gdk_event->keyval == GDK_Escape) )
- {
- // however only do it if we have a Cancel button in the dialog,
- // otherwise the user code may get confused by the events from a
- // nonexistent button and, worse, a wxButton might get button event
- // from another button which is not really expected
- wxWindow *winForCancel = win,
- *btnCancel = NULL;
- while ( winForCancel )
- {
- btnCancel = winForCancel->FindWindow(wxID_CANCEL);
- if ( btnCancel )
- {
- // found a cancel button
- break;
- }
-
- if ( winForCancel->IsTopLevel() )
- {
- // no need to look further
- break;
- }
-
- // maybe our parent has a cancel button?
- winForCancel = winForCancel->GetParent();
- }
-
- if ( btnCancel )
- {
- wxCommandEvent eventClick(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
- eventClick.SetEventObject(btnCancel);
- ret = btnCancel->GetEventHandler()->ProcessEvent(eventClick);
- }
- }
-
- 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();
return win;
}
+// ----------------------------------------------------------------------------
+// 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
+
+ // don't need to install idle handler, its done from "event" signal
+
+ if (!m_hasVMT)
+ return FALSE;
+ if (g_blockEventsOnDrag)
+ return TRUE;
+ if (g_blockEventsOnScroll)
+ return TRUE;
+
+ if (!GTKIsOwnWindow(event->window))
+ return FALSE;
+
+ return -1;
+}
+
+// overloads for all GDK event types we use here: we need to have this as
+// GdkEventXXX can't be implicitly cast to GdkEventAny even if it, in fact,
+// derives from it in the sense that the structs have the same layout
+#define wxDEFINE_COMMON_PROLOGUE_OVERLOAD(T) \
+ static int wxGtkCallbackCommonPrologue(T *event, wxWindowGTK *win) \
+ { \
+ return win->GTKCallbackCommonPrologue((GdkEventAny *)event); \
+ }
+
+wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventButton)
+wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventMotion)
+wxDEFINE_COMMON_PROLOGUE_OVERLOAD(GdkEventCrossing)
+
+#undef wxDEFINE_COMMON_PROLOGUE_OVERLOAD
+
+#define wxCOMMON_CALLBACK_PROLOGUE(event, win) \
+ const int rc = wxGtkCallbackCommonPrologue(event, win); \
+ if ( rc != -1 ) \
+ return rc
+
+// send the wxChildFocusEvent and wxFocusEvent, common code of
+// gtk_window_focus_in_callback() and SetFocus()
+static bool DoSendFocusEvents(wxWindow *win)
+{
+ // Notify the parent keeping track of focus for the kbd navigation
+ // purposes that we got it.
+ wxChildFocusEvent eventChildFocus(win);
+ (void)win->GetEventHandler()->ProcessEvent(eventChildFocus);
+
+ wxFocusEvent eventFocus(wxEVT_SET_FOCUS, win->GetId());
+ eventFocus.SetEventObject(win);
+
+ return win->GetEventHandler()->ProcessEvent(eventFocus);
+}
+
+// all event handlers must have C linkage as they're called from GTK+ C code
+extern "C"
+{
+
//-----------------------------------------------------------------------------
// "button_press_event"
//-----------------------------------------------------------------------------
-extern "C" {
static gboolean
gtk_window_button_press_callback( GtkWidget *widget,
GdkEventButton *gdk_event,
wxWindowGTK *win )
{
- DEBUG_MAIN_THREAD
-
- if (g_isIdle)
- wxapp_install_idle_handler();
-
-/*
- wxPrintf( wxT("1) OnButtonPress from ") );
- if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
- wxPrintf( win->GetClassInfo()->GetClassName() );
- wxPrintf( wxT(".\n") );
-*/
- if (!win->m_hasVMT) return FALSE;
- if (g_blockEventsOnDrag) return TRUE;
- if (g_blockEventsOnScroll) return TRUE;
-
- if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
+ wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win);
if (win->m_wxwindow && (g_focusWindow != win) && win->AcceptsFocus())
{
gtk_widget_grab_focus( win->m_wxwindow );
-/*
- wxPrintf( wxT("GrabFocus from ") );
- if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
- wxPrintf( win->GetClassInfo()->GetClassName() );
- wxPrintf( wxT(".\n") );
-*/
}
// GDK sends surplus button down events
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;
}
-}
//-----------------------------------------------------------------------------
// "button_release_event"
//-----------------------------------------------------------------------------
-extern "C" {
static gboolean
gtk_window_button_release_callback( GtkWidget *widget,
GdkEventButton *gdk_event,
wxWindowGTK *win )
{
- DEBUG_MAIN_THREAD
-
- if (g_isIdle)
- wxapp_install_idle_handler();
-
- if (!win->m_hasVMT) return FALSE;
- if (g_blockEventsOnDrag) return FALSE;
- if (g_blockEventsOnScroll) return FALSE;
-
- if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
+ wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win);
wxEventType event_type = wxEVT_NULL;
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);
}
//-----------------------------------------------------------------------------
// "motion_notify_event"
//-----------------------------------------------------------------------------
-extern "C" {
static gboolean
gtk_window_motion_notify_callback( GtkWidget *widget,
GdkEventMotion *gdk_event,
wxWindowGTK *win )
{
- DEBUG_MAIN_THREAD
-
- if (g_isIdle)
- wxapp_install_idle_handler();
-
- if (!win->m_hasVMT) return FALSE;
- if (g_blockEventsOnDrag) return FALSE;
- if (g_blockEventsOnScroll) return FALSE;
-
- if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
+ wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win);
if (gdk_event->is_hint)
{
gdk_event->y = y;
}
-/*
- printf( "OnMotion from " );
- if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
- printf( win->GetClassInfo()->GetClassName() );
- printf( ".\n" );
-*/
-
wxMouseEvent event( wxEVT_MOTION );
InitMouseEvent(win, event, gdk_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);
}
//-----------------------------------------------------------------------------
// "scroll_event", (mouse wheel event)
//-----------------------------------------------------------------------------
-extern "C" {
static gboolean
window_scroll_event(GtkWidget*, GdkEventScroll* gdk_event, wxWindow* win)
{
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);
}
//-----------------------------------------------------------------------------
// "popup-menu"
//-----------------------------------------------------------------------------
-extern "C" {
+
static gboolean wxgtk_window_popup_menu_callback(GtkWidget*, wxWindowGTK* win)
{
- wxContextMenuEvent event(
- wxEVT_CONTEXT_MENU,
- win->GetId(),
- wxPoint(-1, -1));
+ wxContextMenuEvent event(wxEVT_CONTEXT_MENU, win->GetId(), wxPoint(-1, -1));
event.SetEventObject(win);
- return win->GetEventHandler()->ProcessEvent(event);
-}
+ return win->GTKProcessEvent(event);
}
//-----------------------------------------------------------------------------
// "focus_in_event"
//-----------------------------------------------------------------------------
-// send the wxChildFocusEvent and wxFocusEvent, common code of
-// gtk_window_focus_in_callback() and SetFocus()
-static bool DoSendFocusEvents(wxWindow *win)
-{
- // Notify the parent keeping track of focus for the kbd navigation
- // purposes that we got it.
- wxChildFocusEvent eventChildFocus(win);
- (void)win->GetEventHandler()->ProcessEvent(eventChildFocus);
-
- wxFocusEvent eventFocus(wxEVT_SET_FOCUS, win->GetId());
- eventFocus.SetEventObject(win);
-
- return win->GetEventHandler()->ProcessEvent(eventFocus);
-}
-
-extern "C" {
static gboolean
gtk_window_focus_in_callback( GtkWidget *widget,
GdkEventFocus *WXUNUSED(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);
return FALSE;
}
-}
//-----------------------------------------------------------------------------
// "focus_out_event"
//-----------------------------------------------------------------------------
-extern "C" {
static gboolean
gtk_window_focus_out_callback( GtkWidget *widget,
GdkEventFocus *gdk_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_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;
}
return FALSE;
}
-}
//-----------------------------------------------------------------------------
// "enter_notify_event"
//-----------------------------------------------------------------------------
-extern "C" {
static gboolean
gtk_window_enter_callback( GtkWidget *widget,
GdkEventCrossing *gdk_event,
wxWindowGTK *win )
{
- DEBUG_MAIN_THREAD
-
- if (g_isIdle)
- wxapp_install_idle_handler();
-
- if (!win->m_hasVMT) return FALSE;
- if (g_blockEventsOnDrag) return FALSE;
+ wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win);
// Event was emitted after a grab
if (gdk_event->mode != GDK_CROSSING_NORMAL) return FALSE;
- if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
-
int x = 0;
int y = 0;
GdkModifierType state = (GdkModifierType)0;
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);
}
//-----------------------------------------------------------------------------
// "leave_notify_event"
//-----------------------------------------------------------------------------
-extern "C" {
static gboolean
gtk_window_leave_callback( GtkWidget *widget,
GdkEventCrossing *gdk_event,
wxWindowGTK *win )
{
- DEBUG_MAIN_THREAD
-
- if (g_isIdle)
- wxapp_install_idle_handler();
-
- if (!win->m_hasVMT) return FALSE;
- if (g_blockEventsOnDrag) return FALSE;
+ wxCOMMON_CALLBACK_PROLOGUE(gdk_event, win);
// Event was emitted after an ungrab
if (gdk_event->mode != GDK_CROSSING_NORMAL) return FALSE;
- if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
-
wxMouseEvent event( wxEVT_LEAVE_WINDOW );
event.SetTimestamp( gdk_event->time );
event.SetEventObject( win );
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);
}
//-----------------------------------------------------------------------------
// "value_changed" from scrollbar
//-----------------------------------------------------------------------------
-extern "C" {
static void
gtk_scrollbar_value_changed(GtkRange* range, wxWindow* win)
{
{
// Convert scroll event type to scrollwin event type
eventType += wxEVT_SCROLLWIN_TOP - wxEVT_SCROLL_TOP;
- const int orient = range == win->m_scrollBar[0] ? wxHORIZONTAL : wxVERTICAL;
- const int i = orient == wxVERTICAL;
+
+ // find the scrollbar which generated the event
+ wxWindowGTK::ScrollDir dir = win->ScrollDirFromRange(range);
+
+ // generate the corresponding wx event
+ const int orient = win->OrientFromScrollDir(dir);
wxScrollWinEvent event(eventType, win->GetScrollPos(orient), orient);
event.SetEventObject(win);
- win->m_blockValueChanged[i] = true;
- win->GetEventHandler()->ProcessEvent(event);
- win->m_blockValueChanged[i] = false;
+
+ win->m_blockValueChanged[dir] = true;
+ win->GTKProcessEvent(event);
+ win->m_blockValueChanged[dir] = false;
}
}
-}
//-----------------------------------------------------------------------------
// "button_press_event" from scrollbar
//-----------------------------------------------------------------------------
-extern "C" {
static gboolean
gtk_scrollbar_button_press_event(GtkRange*, GdkEventButton*, wxWindow* win)
{
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;
return false;
}
-}
//-----------------------------------------------------------------------------
// "event_after" from scrollbar
//-----------------------------------------------------------------------------
-extern "C" {
static void
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 = range == win->m_scrollBar[0] ? wxHORIZONTAL : wxVERTICAL;
+ const int orient = win->OrientFromScrollDir(
+ win->ScrollDirFromRange(range));
wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBRELEASE, win->GetScrollPos(orient), orient);
event.SetEventObject(win);
- win->GetEventHandler()->ProcessEvent(event);
+ win->GTKProcessEvent(event);
}
}
-}
//-----------------------------------------------------------------------------
// "button_release_event" from scrollbar
//-----------------------------------------------------------------------------
-extern "C" {
static gboolean
gtk_scrollbar_button_release_event(GtkRange* range, GdkEventButton*, wxWindow* win)
{
return false;
}
-}
-
-// ----------------------------------------------------------------------------
-// this wxWindowBase function is implemented here (in platform-specific file)
-// because it is static and so couldn't be made virtual
-// ----------------------------------------------------------------------------
-
-wxWindow *wxWindowBase::DoFindFocus()
-{
- // the cast is necessary when we compile in wxUniversal mode
- return (wxWindow *)g_focusWindow;
-}
//-----------------------------------------------------------------------------
// "realize" from m_widget
/* We cannot set colours and fonts before the widget has
been realized, so we do this directly after realization. */
-extern "C" {
static void
gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win )
{
wxWindowCreateEvent event( win );
event.SetEventObject( win );
- win->GetEventHandler()->ProcessEvent( event );
-}
+ win->GTKProcessEvent( event );
}
//-----------------------------------------------------------------------------
// "size_allocate"
//-----------------------------------------------------------------------------
-extern "C" {
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 = alloc->width;
+
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 );
}
}
-}
#ifdef HAVE_XIM
#endif
/* Resize XIM window */
-
-extern "C" {
static
void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget),
GtkAllocation* WXUNUSED_UNLESS_XIM(alloc),
}
#endif // HAVE_XIM
}
-}
//-----------------------------------------------------------------------------
// "realize" from m_wxwindow
/* Initialize XIM support */
-extern "C" {
static void
gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
wxWindowGTK * WXUNUSED_UNLESS_XIM(win) )
}
#endif // HAVE_XIM
}
+
+} // extern "C"
+
+// ----------------------------------------------------------------------------
+// this wxWindowBase function is implemented here (in platform-specific file)
+// because it is static and so couldn't be made virtual
+// ----------------------------------------------------------------------------
+
+wxWindow *wxWindowBase::DoFindFocus()
+{
+ // the cast is necessary when we compile in wxUniversal mode
+ return (wxWindow *)g_focusWindow;
}
//-----------------------------------------------------------------------------
/* 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_needParent = true;
m_isBeingDeleted = false;
+ m_showOnIdle= false;
+
m_noExpose = false;
m_nativeSizeEvent = false;
m_mouseButtonDown = false;
m_blockScrollEvent = false;
- m_scrollBar[0] =
- m_scrollBar[1] = NULL;
- m_scrollPos[0] =
- m_scrollPos[1] = 0;
- m_blockValueChanged[0] =
- m_blockValueChanged[1] = false;
+ // initialize scrolling stuff
+ for ( int dir = 0; dir < ScrollDir_Max; dir++ )
+ {
+ m_scrollBar[dir] = NULL;
+ m_scrollPos[dir] = 0;
+ m_blockValueChanged[dir] = false;
+ }
m_oldClientWidth =
m_oldClientHeight = 0;
gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
- m_scrollBar[0] = GTK_RANGE(scrolledWindow->hscrollbar);
- m_scrollBar[1] = GTK_RANGE(scrolledWindow->vscrollbar);
+ m_scrollBar[ScrollDir_Horz] = GTK_RANGE(scrolledWindow->hscrollbar);
+ m_scrollBar[ScrollDir_Vert] = GTK_RANGE(scrolledWindow->vscrollbar);
m_wxwindow = gtk_pizza_new();
GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
m_acceptsFocus = true;
- // these handlers block mouse events to any window during scrolling such as
- // motion events and prevent GTK and wxWidgets from fighting over where the
- // slider should be
- g_signal_connect(m_scrollBar[0], "button_press_event",
- G_CALLBACK(gtk_scrollbar_button_press_event), this);
- g_signal_connect(m_scrollBar[1], "button_press_event",
- G_CALLBACK(gtk_scrollbar_button_press_event), this);
- g_signal_connect(m_scrollBar[0], "button_release_event",
- G_CALLBACK(gtk_scrollbar_button_release_event), this);
- g_signal_connect(m_scrollBar[1], "button_release_event",
- G_CALLBACK(gtk_scrollbar_button_release_event), this);
- gulong handler_id;
- handler_id = g_signal_connect(
- m_scrollBar[0], "event_after", G_CALLBACK(gtk_scrollbar_event_after), this);
- g_signal_handler_block(m_scrollBar[0], handler_id);
- handler_id = g_signal_connect(
- m_scrollBar[1], "event_after", G_CALLBACK(gtk_scrollbar_event_after), this);
- g_signal_handler_block(m_scrollBar[1], handler_id);
-
- // these handlers get notified when scrollbar slider moves
-
- g_signal_connect(m_scrollBar[0], "value_changed",
- G_CALLBACK(gtk_scrollbar_value_changed), this);
- g_signal_connect(m_scrollBar[1], "value_changed",
- G_CALLBACK(gtk_scrollbar_value_changed), this);
+ // connect various scroll-related events
+ for ( int dir = 0; dir < ScrollDir_Max; dir++ )
+ {
+ // these handlers block mouse events to any window during scrolling
+ // such as motion events and prevent GTK and wxWidgets from fighting
+ // over where the slider should be
+ g_signal_connect(m_scrollBar[dir], "button_press_event",
+ G_CALLBACK(gtk_scrollbar_button_press_event), this);
+ g_signal_connect(m_scrollBar[dir], "button_release_event",
+ G_CALLBACK(gtk_scrollbar_button_release_event), this);
+
+ gulong handler_id = g_signal_connect(m_scrollBar[dir], "event_after",
+ G_CALLBACK(gtk_scrollbar_event_after), this);
+ g_signal_handler_block(m_scrollBar[dir], handler_id);
+
+ // these handlers get notified when scrollbar slider moves
+ g_signal_connect(m_scrollBar[dir], "value_changed",
+ G_CALLBACK(gtk_scrollbar_value_changed), this);
+ }
gtk_widget_show( m_wxwindow );
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 )
// 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_resizing = false;
}
+bool wxWindowGTK::GtkShowFromOnIdle()
+{
+ if (IsShown() && m_showOnIdle && !GTK_WIDGET_VISIBLE (m_widget))
+ {
+ GtkAllocation alloc;
+ alloc.x = m_x;
+ alloc.y = m_y;
+ alloc.width = m_width;
+ alloc.height = m_height;
+ gtk_widget_size_allocate( m_widget, &alloc );
+ gtk_widget_show( m_widget );
+ wxShowEvent eventShow(GetId(), true);
+ eventShow.SetEventObject(this);
+ GetEventHandler()->ProcessEvent(eventShow);
+ m_showOnIdle = false;
+ return true;
+ }
+
+ return false;
+}
+
void wxWindowGTK::OnInternalIdle()
{
+ // Check if we have to show window now
+ if (GtkShowFromOnIdle()) return;
+
if ( m_dirtyTabOrder )
{
m_dirtyTabOrder = false;
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 (x) (*x) = m_x - dx;
}
if (show)
- gtk_widget_show( m_widget );
+ {
+ if (!m_showOnIdle)
+ {
+ gtk_widget_show( m_widget );
+ wxShowEvent eventShow(GetId(), show);
+ eventShow.SetEventObject(this);
+ GetEventHandler()->ProcessEvent(eventShow);
+ }
+ }
else
+ {
gtk_widget_hide( m_widget );
-
- wxShowEvent eventShow(GetId(), show);
- eventShow.SetEventObject(this);
-
- GetEventHandler()->ProcessEvent(eventShow);
+ wxShowEvent eventShow(GetId(), show);
+ eventShow.SetEventObject(this);
+ GetEventHandler()->ProcessEvent(eventShow);
+ }
return true;
}
g_object_unref (layout);
}
+bool wxWindowGTK::GTKSetDelayedFocusIfNeeded()
+{
+ if ( g_delayedFocus == this )
+ {
+ if ( GTK_WIDGET_REALIZED(m_widget) )
+ {
+ gtk_widget_grab_focus(m_widget);
+ g_delayedFocus = NULL;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
void wxWindowGTK::SetFocus()
{
wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
if (newParent)
{
+ if (GTK_WIDGET_VISIBLE (newParent->m_widget))
+ {
+ 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 ( !wxWindowBase::SetCursor(cursor.Ok() ? cursor : *wxSTANDARD_CURSOR) )
+ return false;
- if (cursor == m_cursor)
- return false;
+ GTKUpdateCursor();
- if (g_isIdle)
- wxapp_install_idle_handler();
+ return true;
+}
- if (cursor == wxNullCursor)
- return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR );
- else
- return wxWindowBase::SetCursor( cursor );
+void wxWindowGTK::GTKUpdateCursor()
+{
+ wxCursor cursor(g_globalCursor.Ok() ? g_globalCursor : GetCursor());
+ if ( cursor.Ok() )
+ {
+ wxArrayGdkWindows windowsThis;
+ GdkWindow * const winThis = GTKGetWindow(windowsThis);
+ if ( winThis )
+ {
+ gdk_window_set_cursor(winThis, cursor.GetCursor());
+ }
+ else
+ {
+ const size_t count = windowsThis.size();
+ for ( size_t n = 0; n < count; n++ )
+ {
+ GdkWindow *win = windowsThis[n];
+ if ( !win )
+ {
+ wxFAIL_MSG(_T("NULL window returned by GTKGetWindow()?"));
+ continue;
+ }
+
+ gdk_window_set_cursor(win, cursor.GetCursor());
+ }
+ }
+ }
}
void wxWindowGTK::WarpPointer( int x, int y )
gdk_window_warp_pointer( window, x, y );
}
-bool wxWindowGTK::ScrollLines(int lines)
+wxWindowGTK::ScrollDir wxWindowGTK::ScrollDirFromRange(GtkRange *range) const
{
- bool changed = false;
- GtkRange* range = m_scrollBar[1];
- if (range != NULL)
+ // find the scrollbar which generated the event
+ for ( int dir = 0; dir < ScrollDir_Max; dir++ )
{
- GtkAdjustment* adj = range->adjustment;
- const int pos = int(adj->value + 0.5);
- gtk_range_set_value(range, pos + lines*adj->step_increment);
- changed = pos != int(adj->value + 0.5);
+ if ( range == m_scrollBar[dir] )
+ return (ScrollDir)dir;
}
- return changed;
+
+ wxFAIL_MSG( _T("event from unknown scrollbar received") );
+
+ return ScrollDir_Max;
}
-bool wxWindowGTK::ScrollPages(int pages)
+bool wxWindowGTK::DoScrollByUnits(ScrollDir dir, ScrollUnit unit, int units)
{
bool changed = false;
- GtkRange* range = m_scrollBar[1];
- if (range != NULL)
+ GtkRange* range = m_scrollBar[dir];
+ if ( range && units )
{
GtkAdjustment* adj = range->adjustment;
- const int pos = int(adj->value + 0.5);
- gtk_range_set_value(range, pos + pages*adj->page_increment);
- changed = pos != int(adj->value + 0.5);
+ gdouble inc = unit == ScrollUnit_Line ? adj->step_increment
+ : adj->page_increment;
+
+ const int posOld = int(adj->value + 0.5);
+ gtk_range_set_value(range, posOld + units*inc);
+
+ changed = int(adj->value + 0.5) != posOld;
}
+
return changed;
}
+bool wxWindowGTK::ScrollLines(int lines)
+{
+ return DoScrollByUnits(ScrollDir_Vert, ScrollUnit_Line, lines);
+}
+
+bool wxWindowGTK::ScrollPages(int pages)
+{
+ return DoScrollByUnits(ScrollDir_Vert, ScrollUnit_Page, pages);
+}
+
void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
{
if (!m_widget)
if (m_wxwindow)
{
+ if (!GTK_PIZZA(m_wxwindow)->bin_window) return;
+
GdkRectangle gdk_rect,
*p;
if (rect)
{
p = NULL;
}
+
+ 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 );
return connect_widget;
}
-bool wxWindowGTK::IsOwnGtkWindow( GdkWindow *window )
+bool wxWindowGTK::GTKIsOwnWindow(GdkWindow *window) const
{
- if (m_wxwindow)
- return (window == GTK_PIZZA(m_wxwindow)->bin_window);
+ wxArrayGdkWindows windowsThis;
+ GdkWindow * const winThis = GTKGetWindow(windowsThis);
+
+ return winThis ? window == winThis
+ : windowsThis.Index(window) != wxNOT_FOUND;
+}
- return (window == m_widget->window);
+GdkWindow *wxWindowGTK::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
+{
+ return m_wxwindow ? GTK_PIZZA(m_wxwindow)->bin_window : m_widget->window;
}
bool wxWindowGTK::SetFont( const wxFont &font )
m_blockScrollEvent = false;
}
-void wxWindowGTK::SetScrollbar( int orient, int pos, int thumbVisible,
- int range, bool )
+void wxWindowGTK::SetScrollbar(int orient,
+ int pos,
+ int thumbVisible,
+ int range,
+ bool WXUNUSED(update))
{
wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
pos = range - thumbVisible;
if (pos < 0)
pos = 0;
- const int i = orient == wxVERTICAL;
- GtkAdjustment* adj = m_scrollBar[i]->adjustment;
+ GtkAdjustment* adj = m_scrollBar[ScrollDirFromOrient(orient)]->adjustment;
adj->step_increment = 1;
adj->page_increment =
adj->page_size = thumbVisible;
gtk_adjustment_changed(adj);
}
-void wxWindowGTK::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
+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") );
// will not move smoothly while tracking when using wxScrollHelper.
if (GetScrollPos(orient) != pos)
{
- const int i = orient == wxVERTICAL;
- GtkAdjustment* adj = m_scrollBar[i]->adjustment;
+ const int dir = ScrollDirFromOrient(orient);
+ GtkAdjustment* adj = m_scrollBar[dir]->adjustment;
const int max = int(adj->upper - adj->page_size);
if (pos > max)
pos = max;
if (pos < 0)
pos = 0;
- m_scrollPos[i] =
+ m_scrollPos[dir] =
adj->value = pos;
// If a "value_changed" signal emission is not already in progress
- if (!m_blockValueChanged[i])
+ if (!m_blockValueChanged[dir])
{
gtk_adjustment_value_changed(adj);
}
}
}
-int wxWindowGTK::GetScrollThumb( int orient ) const
+int wxWindowGTK::GetScrollThumb(int orient) const
{
wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
- const int i = orient == wxVERTICAL;
- return int(m_scrollBar[i]->adjustment->page_size);
+ return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->page_size);
}
int wxWindowGTK::GetScrollPos( int orient ) const
wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
- const int i = orient == wxVERTICAL;
- return int(m_scrollBar[i]->adjustment->value + 0.5);
+ return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->value + 0.5);
}
int wxWindowGTK::GetScrollRange( int orient ) const
wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
- const int i = orient == wxVERTICAL;
- return int(m_scrollBar[i]->adjustment->upper);
+ return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->upper);
}
// Determine if increment is the same as +/-x, allowing for some small
{
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);
-}