}
}
- // 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
-// 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
-// (with wxTE_PROCESS_TAB you have to call Navigate to get default
-// navigation behaviour)
-#if wxUSE_TEXTCTRL
- (! (win->HasFlag(wxTE_PROCESS_TAB) && win->IsKindOf(CLASSINFO(wxTextCtrl)) )) &&
-#endif
- win->GetParent() && (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
- {
- wxNavigationKeyEvent new_event;
- new_event.SetEventObject( win->GetParent() );
- // 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
- new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) );
- new_event.SetCurrentFocus( win );
- ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
- }
-
return ret;
}
}
g_lastButtonNumber = gdk_event->button;
- if (win->m_wxwindow && (g_focusWindow != win) && win->AcceptsFocus())
+ if (win->m_wxwindow && (g_focusWindow != win) && win->CanAcceptFocus())
{
gtk_widget_grab_focus( win->m_wxwindow );
}
event.SetId( win->GetId() );
bool ret = win->GTKProcessEvent(event);
-
+
g_lastMouseEvent = NULL;
-
+
return ret;
}
}
#endif // wxUSE_CARET
- gboolean ret = FALSE;
-
// don't send the window a kill focus event if it thinks that it doesn't
// have focus already
if ( win->m_hasFocus )
{
+ // the event handler might delete the window when it loses focus, so
+ // check whether this is a custom window before calling it
+ const bool has_wxwindow = win->m_wxwindow != NULL;
+
win->m_hasFocus = false;
wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
(void)win->GTKProcessEvent( event );
- ret = TRUE;
+ // Disable default focus handling for custom windows
+ // since the default GTK+ handler issues a repaint
+ if ( has_wxwindow )
+ return TRUE;
}
- // Disable default focus handling for custom windows
- // since the default GTK+ handler issues a repaint
- if (win->m_wxwindow)
- return ret;
+ // continue with normal processing
+ return FALSE;
+}
+static gboolean
+wx_window_focus_callback(GtkWidget *widget,
+ GtkDirectionType direction,
+ wxWindowGTK *win)
+{
+ // the default handler for focus signal in GtkPizza (or, rather, in
+ // GtkScrolledWindow from which GtkPizza inherits this behaviour) sets
+ // focus to the window itself even if it doesn't accept focus, i.e. has no
+ // GTK_CAN_FOCUS in its style -- work around this by forcibly preventing
+ // the signal from reaching gtk_scrolled_window_focus() if we don't have
+ // any children which might accept focus (we know we don't accept the focus
+ // ourselves as this signal is only connected in this case)
+ if ( win->GetChildren().empty() )
+ g_signal_stop_emission_by_name(widget, "focus");
+
+ // we didn't change the focus
return FALSE;
}
m_insertCallback = (wxInsertChildFunction) NULL;
- m_acceptsFocus = false;
m_hasFocus = false;
m_clipPaintRegion = false;
m_insertCallback = wxInsertChildInWindow;
- m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
- GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
- GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
-
- GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
- scroll_class->scrollbar_spacing = 0;
-
- if (HasFlag(wxALWAYS_SHOW_SB))
+ if (!HasFlag(wxHSCROLL) && !HasFlag(wxVSCROLL))
{
- gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS );
+ m_wxwindow = gtk_pizza_new_no_scroll();
+
+#ifndef __WXUNIVERSAL__
+ if (HasFlag(wxSIMPLE_BORDER))
+ gtk_container_set_border_width((GtkContainer*)m_wxwindow, 1);
+ else if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
+ gtk_container_set_border_width((GtkContainer*)m_wxwindow, 2);
+#endif // __WXUNIVERSAL__
- scrolledWindow->hscrollbar_visible = TRUE;
- scrolledWindow->vscrollbar_visible = TRUE;
+ m_widget = m_wxwindow;
}
else
{
- gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
- }
-
- 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();
+ m_wxwindow = gtk_pizza_new();
#ifndef __WXUNIVERSAL__
- if (HasFlag(wxSIMPLE_BORDER))
- gtk_container_set_border_width((GtkContainer*)m_wxwindow, 1);
- else if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
- gtk_container_set_border_width((GtkContainer*)m_wxwindow, 2);
+ if (HasFlag(wxSIMPLE_BORDER))
+ gtk_container_set_border_width((GtkContainer*)m_wxwindow, 1);
+ else if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
+ gtk_container_set_border_width((GtkContainer*)m_wxwindow, 2);
#endif // __WXUNIVERSAL__
- gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
+ m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
- GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
- m_acceptsFocus = true;
+ GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
- // 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",
+ GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
+ scroll_class->scrollbar_spacing = 0;
+
+ // There is a conflict with default bindings at GTK+
+ // level between scrolled windows and notebooks both of which want to use
+ // Ctrl-PageUp/Down: scrolled windows for scrolling in the horizontal
+ // direction and notebooks for changing pages -- we decide that if we don't
+ // have wxHSCROLL style we can safely sacrifice horizontal scrolling if it
+ // means we can get working keyboard navigation in notebooks
+ if ( !HasFlag(wxHSCROLL) )
+ {
+ GtkBindingSet *
+ bindings = gtk_binding_set_by_class(G_OBJECT_GET_CLASS(m_widget));
+ if ( bindings )
+ {
+ gtk_binding_entry_remove(bindings, GDK_Page_Up, GDK_CONTROL_MASK);
+ gtk_binding_entry_remove(bindings, GDK_Page_Down, GDK_CONTROL_MASK);
+ }
+ }
+
+ if (HasFlag(wxALWAYS_SHOW_SB))
+ {
+ gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS );
+
+ scrolledWindow->hscrollbar_visible = TRUE;
+ scrolledWindow->vscrollbar_visible = TRUE;
+ }
+ else
+ {
+ gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
+ }
+
+ 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 );
+
+ gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
+
+ // 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_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",
+ 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);
+ 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",
+ // 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 );
+ gtk_widget_show( m_wxwindow );
+ }
if (m_parent)
m_parent->DoAddChild( this );
// delete before the widgets to avoid a crash on solaris
delete m_imData;
- if (m_wxwindow)
+ if (m_wxwindow && (m_wxwindow != m_widget))
{
gtk_widget_destroy( m_wxwindow );
m_wxwindow = (GtkWidget*) NULL;
}
}
+ if ( !AcceptsFocusFromKeyboard() )
+ {
+ SetCanFocus(false);
+
+ g_signal_connect(m_widget, "focus",
+ G_CALLBACK(wx_window_focus_callback), this);
+ }
+
// connect to the various key and mouse handlers
GtkWidget *connect_widget = GetConnectWidget();
windows above so that checking for the current cursor is
not possible. */
- if (m_wxwindow)
+ if (m_wxwindow && (m_wxwindow != m_widget))
{
GdkWindow *window = GTK_PIZZA(m_wxwindow)->bin_window;
if (window)
int org_y = 0;
gdk_window_get_origin( source, &org_x, &org_y );
- if (GetParent())
- GetParent()->ScreenToClient(&org_x, &org_y);
+ if (m_parent)
+ m_parent->ScreenToClient(&org_x, &org_y);
wx_const_cast(wxWindowGTK*, this)->m_x = org_x;
wx_const_cast(wxWindowGTK*, this)->m_y = org_y;
return true;
}
-static void wxWindowNotifyEnable(wxWindowGTK* win, bool enable)
-{
- win->OnParentEnable(enable);
-
- // Recurse, so that children have the opportunity to Do The Right Thing
- // and reset colours that have been messed up by a parent's (really ancestor's)
- // Enable call
- for ( wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
- node;
- node = node->GetNext() )
- {
- wxWindow *child = node->GetData();
- if (!child->IsKindOf(CLASSINFO(wxDialog)) && !child->IsKindOf(CLASSINFO(wxFrame)))
- wxWindowNotifyEnable(child, enable);
- }
-}
-
-bool wxWindowGTK::Enable( bool enable )
+void wxWindowGTK::DoEnable( bool enable )
{
- wxCHECK_MSG( (m_widget != NULL), false, wxT("invalid window") );
-
- if (!wxWindowBase::Enable(enable))
- {
- // nothing to do
- return false;
- }
+ wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
gtk_widget_set_sensitive( m_widget, enable );
- if ( m_wxwindow )
+ if (m_wxwindow && (m_wxwindow != m_widget))
gtk_widget_set_sensitive( m_wxwindow, enable );
-
- wxWindowNotifyEnable(this, enable);
-
- return true;
}
int wxWindowGTK::GetCharHeight() const
}
}
-bool wxWindowGTK::AcceptsFocus() const
+void wxWindowGTK::SetCanFocus(bool canFocus)
{
- return m_acceptsFocus && wxWindowBase::AcceptsFocus();
+ if ( canFocus )
+ GTK_WIDGET_SET_FLAGS(m_widget, GTK_CAN_FOCUS);
+ else
+ GTK_WIDGET_UNSET_FLAGS(m_widget, GTK_CAN_FOCUS);
+
+ if ( m_wxwindow && (m_widget != m_wxwindow) )
+ {
+ if ( canFocus )
+ GTK_WIDGET_SET_FLAGS(m_wxwindow, GTK_CAN_FOCUS);
+ else
+ GTK_WIDGET_UNSET_FLAGS(m_wxwindow, GTK_CAN_FOCUS);
+ }
}
bool wxWindowGTK::Reparent( wxWindowBase *newParentBase )
GTKSetLayout(m_widget, dir);
- if (m_wxwindow)
+ if (m_wxwindow && (m_wxwindow != m_widget))
GTKSetLayout(m_wxwindow, dir);
}
wxapp_install_idle_handler();
}
+bool wxWindowGTK::DoNavigateIn(int flags)
+{
+ if ( flags & wxNavigationKeyEvent::WinChange )
+ {
+ wxFAIL_MSG( _T("not implemented") );
+
+ return false;
+ }
+ else // navigate inside the container
+ {
+ wxWindow *parent = wxGetTopLevelParent(this);
+ wxCHECK_MSG( parent, false, _T("every window must have a TLW parent") );
+
+ GtkDirectionType dir;
+ dir = flags & wxNavigationKeyEvent::IsForward ? GTK_DIR_TAB_FORWARD
+ : GTK_DIR_TAB_BACKWARD;
+
+ gboolean rc;
+ g_signal_emit_by_name(parent->m_widget, "focus", dir, &rc);
+
+ return rc == TRUE;
+ }
+}
+
bool wxWindowGTK::GTKWidgetNeedsMnemonic() const
{
// none needed by default
{
if (m_wxwindow && GTK_PIZZA(m_wxwindow)->bin_window)
gdk_window_process_updates( GTK_PIZZA(m_wxwindow)->bin_window, FALSE );
- if (m_widget && m_widget->window)
+ if (m_widget && m_widget->window && (m_wxwindow != m_widget))
gdk_window_process_updates( m_widget->window, FALSE );
// for consistency with other platforms (and also because it's convenient
pango_font_description_copy( m_font.GetNativeFontInfo()->description );
}
+ int flagsNormal = 0,
+ flagsPrelight = 0,
+ flagsActive = 0,
+ flagsInsensitive = 0;
+
if ( m_foregroundColour.Ok() )
{
const GdkColor *fg = m_foregroundColour.GetColor();
- style->fg[GTK_STATE_NORMAL] = *fg;
- style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG;
+ style->fg[GTK_STATE_NORMAL] =
+ style->text[GTK_STATE_NORMAL] = *fg;
+ flagsNormal |= GTK_RC_FG | GTK_RC_TEXT;
- style->fg[GTK_STATE_PRELIGHT] = *fg;
- style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG;
+ style->fg[GTK_STATE_PRELIGHT] =
+ style->text[GTK_STATE_PRELIGHT] = *fg;
+ flagsPrelight |= GTK_RC_FG | GTK_RC_TEXT;
- style->fg[GTK_STATE_ACTIVE] = *fg;
- style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG;
+ style->fg[GTK_STATE_ACTIVE] =
+ style->text[GTK_STATE_ACTIVE] = *fg;
+ flagsActive |= GTK_RC_FG | GTK_RC_TEXT;
}
if ( m_backgroundColour.Ok() )
{
const GdkColor *bg = m_backgroundColour.GetColor();
- style->bg[GTK_STATE_NORMAL] = *bg;
+ style->bg[GTK_STATE_NORMAL] =
style->base[GTK_STATE_NORMAL] = *bg;
- style->color_flags[GTK_STATE_NORMAL] = (GtkRcFlags)
- (style->color_flags[GTK_STATE_NORMAL] | GTK_RC_BG | GTK_RC_BASE);
+ flagsNormal |= GTK_RC_BG | GTK_RC_BASE;
- style->bg[GTK_STATE_PRELIGHT] = *bg;
+ style->bg[GTK_STATE_PRELIGHT] =
style->base[GTK_STATE_PRELIGHT] = *bg;
- style->color_flags[GTK_STATE_PRELIGHT] = (GtkRcFlags)
- (style->color_flags[GTK_STATE_PRELIGHT] | GTK_RC_BG | GTK_RC_BASE);
+ flagsPrelight |= GTK_RC_BG | GTK_RC_BASE;
- style->bg[GTK_STATE_ACTIVE] = *bg;
+ style->bg[GTK_STATE_ACTIVE] =
style->base[GTK_STATE_ACTIVE] = *bg;
- style->color_flags[GTK_STATE_ACTIVE] = (GtkRcFlags)
- (style->color_flags[GTK_STATE_ACTIVE] | GTK_RC_BG | GTK_RC_BASE);
+ flagsActive |= GTK_RC_BG | GTK_RC_BASE;
- style->bg[GTK_STATE_INSENSITIVE] = *bg;
+ style->bg[GTK_STATE_INSENSITIVE] =
style->base[GTK_STATE_INSENSITIVE] = *bg;
- style->color_flags[GTK_STATE_INSENSITIVE] = (GtkRcFlags)
- (style->color_flags[GTK_STATE_INSENSITIVE] | GTK_RC_BG | GTK_RC_BASE);
+ flagsInsensitive |= GTK_RC_BG | GTK_RC_BASE;
}
+ style->color_flags[GTK_STATE_NORMAL] = (GtkRcFlags)flagsNormal;
+ style->color_flags[GTK_STATE_PRELIGHT] = (GtkRcFlags)flagsPrelight;
+ style->color_flags[GTK_STATE_ACTIVE] = (GtkRcFlags)flagsActive;
+ style->color_flags[GTK_STATE_INSENSITIVE] = (GtkRcFlags)flagsInsensitive;
+
return style;
}
{
wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
+ wxCHECK_RET( m_wxwindow != m_widget, wxT("no scrolling for this wxWindow, use wxHSCROLL or wxVSCROLL") );
if (range > 0)
{
{
wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
+ wxCHECK_RET( m_wxwindow != m_widget, wxT("no scrolling for this wxWindow, use wxHSCROLL or wxVSCROLL") );
// This check is more than an optimization. Without it, the slider
// will not move smoothly while tracking when using wxScrollHelper.
{
wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
+ wxCHECK_MSG( m_wxwindow != m_widget, 0, wxT("no scrolling for this wxWindow, use wxHSCROLL or wxVSCROLL") );
return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->page_size);
}
{
wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
+ wxCHECK_MSG( m_wxwindow != m_widget, 0, wxT("no scrolling for this wxWindow, use wxHSCROLL or wxVSCROLL") );
return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->value + 0.5);
}
{
wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
+ wxCHECK_MSG( m_wxwindow != m_widget, 0, wxT("no scrolling for this wxWindow, use wxHSCROLL or wxVSCROLL") );
return int(m_scrollBar[ScrollDirFromOrient(orient)]->adjustment->upper);
}