// Author: Robert Roebling
// Id: $Id$
// Copyright: (c) 1998 Robert Roebling, Julian Smart
-// Licence: wxWidgets licence
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
thw wxWindow class has a member variable called m_widget which holds a
pointer to this widget. When the window class represents a GTK native widget,
this is (in most cases) the only GTK widget the class manages. E.g. the
- wxStatitText class handles only a GtkLabel widget a pointer to which you
+ wxStaticText class handles only a GtkLabel widget a pointer to which you
can find in m_widget (defined in wxWindow)
When the class has a client area for drawing into and for containing children
// debug
//-----------------------------------------------------------------------------
-#ifndef __WXGTK20__
-#define DISABLE_STYLE_IF_BROKEN_THEME 0
-#endif
-
#ifdef __WXDEBUG__
#if wxUSE_THREADS
if (g_blockEventsOnDrag)
return FALSE;
+#ifdef __WXGTK20__
+ if (win->m_imContext)
+ {
+ // In GTK 2.0, we need to hand over the key event to an input method
+ // and the IM will emit a "commit" event containing the actual utf8
+ // character. In that case the EVT_CHAR events will be sent from
+ // there.
+ if ( gtk_im_context_filter_keypress(win->m_imContext, gdk_event) )
+ return TRUE;
+ }
+#endif
wxKeyEvent event( wxEVT_KEY_DOWN );
if ( !wxTranslateGTKKeyEventToWx(event, win, gdk_event) )
{
long key_code;
KeySym keysym = gdk_event->keyval;
-#ifdef __WXGTK20__
- // In GTK 2.0, we need to hand over the key event to an input method
- // and the IM will emit a "commit" event containing the actual utf8
- // character. In that case the EVT_CHAR events will be sent from
- // there. But only do it this way for non-KeySym keys.
- key_code = wxTranslateKeySymToWXKey(gdk_event->keyval, FALSE /* isChar */);
- if ( !key_code && win->m_imContext )
- {
- gtk_im_context_filter_keypress ( (GtkIMContext*) win->m_imContext, gdk_event );
- ret = TRUE;
- }
- else
-#endif
+ // Find key code for EVT_CHAR and EVT_CHAR_HOOK events
+ key_code = wxTranslateKeySymToWXKey(keysym, TRUE /* isChar */);
+ if ( !key_code )
{
- // Find key code for EVT_CHAR and EVT_CHAR_HOOK events
- key_code = wxTranslateKeySymToWXKey(keysym, TRUE /* isChar */);
- if ( !key_code )
+ if ( gdk_event->length == 1 )
{
- if ( gdk_event->length == 1 )
- {
- key_code = (unsigned char)gdk_event->string[0];
- }
- else if ( wxIsAsciiKeysym(keysym) )
- {
- // ASCII key
- key_code = (unsigned char)keysym;
- }
+ key_code = (unsigned char)gdk_event->string[0];
}
-
- if ( key_code )
+ else if ( wxIsAsciiKeysym(keysym) )
{
- wxLogTrace(TRACE_KEYS, _T("Char event: %ld"), key_code);
+ // ASCII key
+ key_code = (unsigned char)keysym;
+ }
+ }
- event.m_keyCode = key_code;
+ if ( key_code )
+ {
+ wxLogTrace(TRACE_KEYS, _T("Char event: %ld"), key_code);
- // Implement OnCharHook by checking ancesteror top level windows
- wxWindow *parent = win;
- while (parent && !parent->IsTopLevel())
- parent = parent->GetParent();
- if (parent)
- {
- event.SetEventType( wxEVT_CHAR_HOOK );
- ret = parent->GetEventHandler()->ProcessEvent( event );
- }
+ event.m_keyCode = key_code;
- if (!ret)
- {
- event.SetEventType(wxEVT_CHAR);
- ret = win->GetEventHandler()->ProcessEvent( event );
- }
+ // Implement OnCharHook by checking ancesteror top level windows
+ wxWindow *parent = win;
+ while (parent && !parent->IsTopLevel())
+ parent = parent->GetParent();
+ if (parent)
+ {
+ event.SetEventType( wxEVT_CHAR_HOOK );
+ ret = parent->GetEventHandler()->ProcessEvent( event );
+ }
+
+ if (!ret)
+ {
+ event.SetEventType(wxEVT_CHAR);
+ ret = win->GetEventHandler()->ProcessEvent( event );
}
}
}
// 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
-#if 0
- !win->HasFlag(wxTE_PROCESS_TAB) &&
-#endif // 0
+// 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;
if (event.m_uniChar < 256)
event.m_keyCode = event.m_uniChar;
#else
- gunichar uniChar = g_utf8_get_char( str );
- // We cannot handle Unicode in non-Unicode mode
- if (uniChar > 255) return;
-
- event.m_keyCode = uniChar;
+ wchar_t unistr[2];
+ unistr[0] = g_utf8_get_char(str);
+ unistr[1] = 0;
+ wxCharBuffer ansistr(wxConvLocal.cWC2MB(unistr));
+ // We cannot handle characters that cannot be represented in
+ // current locale's charset in non-Unicode mode:
+ if (ansistr.data() == NULL) return;
+
+ event.m_keyCode = ansistr[0u];
#endif
// mouse event processing helpers
// ----------------------------------------------------------------------------
-// init wxMouseEvent with the info from gdk_event
-//
-// NB: this has to be a macro as gdk_event type is different for different
-// events we're used with
-#define InitMouseEvent(/* wxWindowGTK * */ win, \
- /* wxMouseEvent& */ event, \
- /* GdkEventXXX * */ gdk_event) \
-{ \
- event.SetTimestamp( gdk_event->time ); \
- event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
- event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
- event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
- event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
- event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
- event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
- event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
- if (event.GetEventType()==wxEVT_MOUSEWHEEL) \
- { \
- event.m_linesPerAction = 3; \
- if (((GdkEventButton*)gdk_event)->button == 4) \
- event.m_wheelRotation = 120; \
- else if (((GdkEventButton*)gdk_event)->button == 5) \
- event.m_wheelRotation = -120; \
- } \
- \
- wxPoint pt = win->GetClientAreaOrigin(); \
- event.m_x = (wxCoord)gdk_event->x - pt.x; \
- event.m_y = (wxCoord)gdk_event->y - pt.y; \
- \
- event.SetEventObject( win ); \
- event.SetId( win->GetId() ); \
- event.SetTimestamp( gdk_event->time ); \
-} \
+// init wxMouseEvent with the info from GdkEventXXX struct
+template<typename T> void InitMouseEvent(wxWindowGTK *win,
+ wxMouseEvent& event,
+ T *gdk_event)
+{
+ event.SetTimestamp( gdk_event->time );
+ event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
+ event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
+ event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
+ event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
+ event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
+ event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
+ event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
+ if (event.GetEventType() == wxEVT_MOUSEWHEEL)
+ {
+ event.m_linesPerAction = 3;
+ if (((GdkEventButton*)gdk_event)->button == 4)
+ event.m_wheelRotation = 120;
+ else if (((GdkEventButton*)gdk_event)->button == 5)
+ event.m_wheelRotation = -120;
+ }
+
+ wxPoint pt = win->GetClientAreaOrigin();
+ event.m_x = (wxCoord)gdk_event->x - pt.x;
+ event.m_y = (wxCoord)gdk_event->y - pt.y;
+
+ event.SetEventObject( win );
+ event.SetId( win->GetId() );
+ event.SetTimestamp( gdk_event->time );
+}
static void AdjustEventButtonState(wxMouseEvent& event)
{
wxEventType event_type = wxEVT_NULL;
- // GdkDisplay is a GTK+ 2.1.0 thing
-#if defined(__WXGTK20__) && GTK_CHECK_VERSION(2, 1, 0)
+ // GdkDisplay is a GTK+ 2.2.0 thing
+#if defined(__WXGTK20__) && GTK_CHECK_VERSION(2, 2, 0)
if ( gdk_event->type == GDK_2BUTTON_PRESS &&
gdk_event->button >= 1 && gdk_event->button <= 3 )
{
if (g_isIdle)
wxapp_install_idle_handler();
+#ifdef __WXGTK20__
+ if (win->m_imContext)
+ gtk_im_context_focus_in(win->m_imContext);
+#endif
+
if (!win->m_hasVMT) return FALSE;
if (g_blockEventsOnDrag) return FALSE;
if (g_isIdle)
wxapp_install_idle_handler();
+#ifdef __WXGTK20__
+ if (win->m_imContext)
+ gtk_im_context_focus_out(win->m_imContext);
+#endif
+
if (!win->m_hasVMT) return FALSE;
if (g_blockEventsOnDrag) return FALSE;
if (g_isIdle)
wxapp_install_idle_handler();
- if (win->m_delayedBackgroundColour && !win->GetThemeEnabled())
- win->GtkSetBackgroundColour( win->GetBackgroundColour() );
-
- if (win->m_delayedForegroundColour && !win->GetThemeEnabled())
- win->GtkSetForegroundColour( win->GetForegroundColour() );
-
#ifdef __WXGTK20__
if (win->m_imContext)
{
GtkPizza *pizza = GTK_PIZZA( m_widget );
- gtk_im_context_set_client_window( (GtkIMContext*) win->m_imContext, pizza->bin_window );
+ gtk_im_context_set_client_window( win->m_imContext, pizza->bin_window );
}
#endif
m_oldClientHeight = 0;
m_resizing = FALSE;
- m_widgetStyle = (GtkStyle*) NULL;
m_insertCallback = (wxInsertChildFunction) NULL;
m_cursor = *wxSTANDARD_CURSOR;
- m_delayedForegroundColour = FALSE;
- m_delayedBackgroundColour = FALSE;
-
#ifdef __WXGTK20__
m_imContext = NULL;
m_x11Context = NULL;
m_insertCallback = wxInsertChildInWindow;
- // always needed for background clearing
- m_delayedBackgroundColour = TRUE;
-
m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
(GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
-#ifdef __WXGTK20__
- // Create input method handler
- m_imContext = (GtkIMMulticontext*) gtk_im_multicontext_new ();
-
- // Cannot handle drawing preedited text yet
- gtk_im_context_set_use_preedit( (GtkIMContext*) m_imContext, FALSE );
-
- g_signal_connect (G_OBJECT (m_imContext), "commit",
- G_CALLBACK (gtk_wxwindow_commit_cb), this);
-#endif
-
gtk_widget_show( m_wxwindow );
if (m_parent)
gdk_ic_attr_destroy (m_icattr);
#endif
- if (m_widgetStyle)
- {
-#if DISABLE_STYLE_IF_BROKEN_THEME
- // don't delete if it's a pixmap theme style
- if (!m_widgetStyle->engine_data)
- gtk_style_unref( m_widgetStyle );
-#endif
- m_widgetStyle = (GtkStyle*) NULL;
- }
-
if (m_wxwindow)
{
gtk_widget_destroy( m_wxwindow );
#else
// gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow), !HasFlag( wxFULL_REPAINT_ON_RESIZE ) );
#endif
+ }
#ifdef __WXGTK20__
// Create input method handler
- m_imContext = (GtkIMMulticontext*) gtk_im_multicontext_new ();
+ m_imContext = gtk_im_multicontext_new();
// Cannot handle drawing preedited text yet
- gtk_im_context_set_use_preedit( (GtkIMContext*) m_imContext, FALSE );
+ gtk_im_context_set_use_preedit( m_imContext, FALSE );
g_signal_connect (G_OBJECT (m_imContext), "commit",
- G_CALLBACK (gtk_wxwindow_commit_cb), this);
+ G_CALLBACK (gtk_wxwindow_commit_cb), this);
#endif
- }
// these are called when the "sunken" or "raised" borders are drawn
gtk_signal_connect( GTK_OBJECT(m_widget), "expose_event",
// Clip to paint region in wxClientDC
m_clipPaintRegion = TRUE;
-#ifndef __WXGTK20__
// widget to draw on
GtkPizza *pizza = GTK_PIZZA (m_wxwindow);
- // later for GTK 2.0, too.
if (GetThemeEnabled())
{
// find ancestor from which to steal background
gtk_paint_flat_box( parent->m_widget->style,
pizza->bin_window,
- GTK_STATE_NORMAL,
+ (GtkStateType)GTK_WIDGET_STATE(m_wxwindow),
GTK_SHADOW_NONE,
&rect,
parent->m_widget,
}
}
else
-#endif
#ifdef __WXGTK20__
{
}
#endif // wxUSE_TOOLTIPS
-void wxWindowGTK::GtkSetBackgroundColour( const wxColour &colour )
-{
- GdkWindow *window = (GdkWindow*) NULL;
- if (m_wxwindow)
- window = GTK_PIZZA(m_wxwindow)->bin_window;
- else
- window = GetConnectWidget()->window;
-
- wxASSERT( window );
-
- // We need the pixel value e.g. for background clearing.
- m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
-
- if (m_wxwindow)
- {
- // wxMSW doesn't clear the window here, either.
- gdk_window_set_background( window, m_backgroundColour.GetColor() );
- }
-
- ApplyWidgetStyle();
-}
-
bool wxWindowGTK::SetBackgroundColour( const wxColour &colour )
{
wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
if (!wxWindowBase::SetBackgroundColour(colour))
- return FALSE;
+ return false;
- GdkWindow *window = (GdkWindow*) NULL;
- if (m_wxwindow)
- window = GTK_PIZZA(m_wxwindow)->bin_window;
- else
- window = GetConnectWidget()->window;
-
- if (!window)
+ if (colour.Ok())
{
- // indicate that a new style has been set
- // but it couldn't get applied as the
- // widget hasn't been realized yet.
- m_delayedBackgroundColour = TRUE;
- return TRUE;
+ // We need the pixel value e.g. for background clearing.
+ m_backgroundColour.CalcPixel(gtk_widget_get_colormap(m_widget));
}
- else
- {
- GtkSetBackgroundColour( colour );
- }
-
- return TRUE;
-}
-void wxWindowGTK::GtkSetForegroundColour( const wxColour &colour )
-{
- GdkWindow *window = (GdkWindow*) NULL;
- if (m_wxwindow)
- window = GTK_PIZZA(m_wxwindow)->bin_window;
- else
- window = GetConnectWidget()->window;
-
- wxASSERT( window );
+ // apply style change (forceStyle=true so that new style is applied
+ // even if the bg colour changed from valid to wxNullColour):
+ ApplyWidgetStyle(true);
- ApplyWidgetStyle();
+ return true;
}
bool wxWindowGTK::SetForegroundColour( const wxColour &colour )
if (!wxWindowBase::SetForegroundColour(colour))
{
- // don't leave if the GTK widget has just
- // been realized
- if (!m_delayedForegroundColour) return FALSE;
- }
-
- GdkWindow *window = (GdkWindow*) NULL;
- if (m_wxwindow)
- window = GTK_PIZZA(m_wxwindow)->bin_window;
- else
- window = GetConnectWidget()->window;
-
- if (!window)
- {
- // indicate that a new style has been set
- // but it couldn't get applied as the
- // widget hasn't been realized yet.
- m_delayedForegroundColour = TRUE;
+ return false;
}
- else
+
+ if (colour.Ok())
{
- GtkSetForegroundColour( colour );
+ // We need the pixel value e.g. for background clearing.
+ m_foregroundColour.CalcPixel(gtk_widget_get_colormap(m_widget));
}
- return TRUE;
+ // apply style change (forceStyle=true so that new style is applied
+ // even if the bg colour changed from valid to wxNullColour):
+ ApplyWidgetStyle(true);
+
+ return true;
}
#ifdef __WXGTK20__
return m_x11Context;
}
#endif
-
-GtkStyle *wxWindowGTK::GetWidgetStyle()
+
+GtkRcStyle *wxWindowGTK::CreateWidgetStyle(bool forceStyle)
{
- if (m_widgetStyle)
+ // do we need to apply any changes at all?
+ if ( !forceStyle &&
+ !m_font.Ok() &&
+ !m_foregroundColour.Ok() && !m_backgroundColour.Ok() )
{
- GtkStyle *remake = gtk_style_copy( m_widgetStyle );
-
- // FIXME: no more klass in 2.0
-#ifndef __WXGTK20__
- remake->klass = m_widgetStyle->klass;
-#endif
-
- gtk_style_unref( m_widgetStyle );
- m_widgetStyle = remake;
+ return NULL;
}
- else
- {
- GtkStyle *def = gtk_rc_get_style( m_widget );
- if (!def)
- def = gtk_widget_get_default_style();
+ GtkRcStyle *style = gtk_rc_style_new();
- m_widgetStyle = gtk_style_copy( def );
-
- // FIXME: no more klass in 2.0
-#ifndef __WXGTK20__
- m_widgetStyle->klass = def->klass;
+ if ( m_font.Ok() )
+ {
+#ifdef __WXGTK20__
+ style->font_desc =
+ pango_font_description_copy( m_font.GetNativeFontInfo()->description );
+#else
+ wxString xfontname = m_font.GetNativeFontInfo()->GetXFontName();
+ style->fontset_name = g_strdup(xfontname.c_str());
#endif
}
- return m_widgetStyle;
-}
-
-void wxWindowGTK::SetWidgetStyle()
-{
-#if DISABLE_STYLE_IF_BROKEN_THEME
- if (m_widget->style->engine_data)
+ if ( m_foregroundColour.Ok() )
{
- static bool s_warningPrinted = FALSE;
- if (!s_warningPrinted)
- {
- printf( "wxWidgets warning: Widget styles disabled due to buggy GTK theme.\n" );
- s_warningPrinted = TRUE;
- }
- m_widgetStyle = m_widget->style;
- return;
+ GdkColor *fg = m_foregroundColour.GetColor();
+
+ style->fg[GTK_STATE_NORMAL] = *fg;
+ style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG;
+
+ style->fg[GTK_STATE_PRELIGHT] = *fg;
+ style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG;
+
+ style->fg[GTK_STATE_ACTIVE] = *fg;
+ style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG;
}
-#endif
- GtkStyle *style = GetWidgetStyle();
-
- if ( m_hasFont )
+ if ( m_backgroundColour.Ok() )
{
-#ifdef __WXGTK20__
- pango_font_description_free( style->font_desc );
- style->font_desc = pango_font_description_copy( m_font.GetNativeFontInfo()->description );
-#else
- gdk_font_unref( style->font );
- style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
-#endif
- }
+ GdkColor *bg = m_backgroundColour.GetColor();
- if ( m_hasFgCol )
- {
- m_foregroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
- if (m_foregroundColour != wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT))
- {
- style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
- style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
- style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
- }
- else
- {
- // Try to restore the gtk default style. This is still a little
- // oversimplified for what is probably really needed here for controls
- // other than buttons, but is better than not being able to (re)set a
- // control's foreground colour to *wxBLACK -- RL
- GtkStyle *def = gtk_rc_get_style( m_widget );
-
- if (!def)
- def = gtk_widget_get_default_style();
-
- style->fg[GTK_STATE_NORMAL] = def->fg[GTK_STATE_NORMAL];
- style->fg[GTK_STATE_PRELIGHT] = def->fg[GTK_STATE_PRELIGHT];
- style->fg[GTK_STATE_ACTIVE] = def->fg[GTK_STATE_ACTIVE];
- }
+ style->bg[GTK_STATE_NORMAL] = *bg;
+ 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);
+
+ style->bg[GTK_STATE_PRELIGHT] = *bg;
+ 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);
+
+ style->bg[GTK_STATE_ACTIVE] = *bg;
+ 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);
+
+ style->bg[GTK_STATE_INSENSITIVE] = *bg;
+ 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);
}
+
+ return style;
+}
- if ( m_hasBgCol && m_backgroundColour.Ok() )
+void wxWindowGTK::ApplyWidgetStyle(bool forceStyle)
+{
+ GtkRcStyle *style = CreateWidgetStyle(forceStyle);
+ if ( style )
{
- m_backgroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
- if (m_backgroundColour != wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE))
- {
- style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
- style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
- style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
- style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
- style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
- style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
- style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
- style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
- }
- else
- {
- // Try to restore the gtk default style. This is still a little
- // oversimplified for what is probably really needed here for controls
- // other than buttons, but is better than not being able to (re)set a
- // control's background colour to default grey and means resetting a
- // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
- // behavior -- RL
- GtkStyle *def = gtk_rc_get_style( m_widget );
-
- if (!def)
- def = gtk_widget_get_default_style();
-
- style->bg[GTK_STATE_NORMAL] = def->bg[GTK_STATE_NORMAL];
- style->base[GTK_STATE_NORMAL] = def->base[GTK_STATE_NORMAL];
- style->bg[GTK_STATE_PRELIGHT] = def->bg[GTK_STATE_PRELIGHT];
- style->base[GTK_STATE_PRELIGHT] = def->base[GTK_STATE_PRELIGHT];
- style->bg[GTK_STATE_ACTIVE] = def->bg[GTK_STATE_ACTIVE];
- style->base[GTK_STATE_ACTIVE] = def->base[GTK_STATE_ACTIVE];
- style->bg[GTK_STATE_INSENSITIVE] = def->bg[GTK_STATE_INSENSITIVE];
- style->base[GTK_STATE_INSENSITIVE] = def->base[GTK_STATE_INSENSITIVE];
- }
+ DoApplyWidgetStyle(style);
+ gtk_rc_style_unref(style);
}
}
-void wxWindowGTK::ApplyWidgetStyle()
+void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle *style)
{
+ if (m_wxwindow)
+ // should we also do m_widget in this case?
+ gtk_widget_modify_style(m_wxwindow, style);
+ else
+ gtk_widget_modify_style(m_widget, style);
}
+
//-----------------------------------------------------------------------------
// Pop-up menu stuff
//-----------------------------------------------------------------------------
}
}
-// used to pass the coordinates from wxWindowGTK::DoPopupMenu() to
-// wxPopupMenuPositionCallback()
-//
-// should be safe even in the MT case as the user can hardly popup 2 menus
-// simultaneously, can he?
-static gint gs_pop_x = 0;
-static gint gs_pop_y = 0;
-
extern "C" void wxPopupMenuPositionCallback( GtkMenu *menu,
gint *x, gint *y,
#ifdef __WXGTK20__
gboolean * WXUNUSED(whatever),
#endif
- gpointer WXUNUSED(user_data) )
+ gpointer user_data )
{
// ensure that the menu appears entirely on screen
GtkRequisition req;
gtk_widget_get_child_requisition(GTK_WIDGET(menu), &req);
wxSize sizeScreen = wxGetDisplaySize();
+ wxPoint *pos = (wxPoint*)user_data;
gint xmax = sizeScreen.x - req.width,
ymax = sizeScreen.y - req.height;
- *x = gs_pop_x < xmax ? gs_pop_x : xmax;
- *y = gs_pop_y < ymax ? gs_pop_y : ymax;
+ *x = pos->x < xmax ? pos->x : xmax;
+ *y = pos->y < ymax ? pos->y : ymax;
}
bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y )
{
- wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
+ wxCHECK_MSG( m_widget != NULL, false, wxT("invalid window") );
- wxCHECK_MSG( menu != NULL, FALSE, wxT("invalid popup-menu") );
+ wxCHECK_MSG( menu != NULL, false, wxT("invalid popup-menu") );
SetInvokingWindow( menu, this );
menu->UpdateUI();
- gs_pop_x = x;
- gs_pop_y = y;
- ClientToScreen( &gs_pop_x, &gs_pop_y );
-
- bool is_waiting = TRUE;
+ bool is_waiting = true;
gtk_signal_connect( GTK_OBJECT(menu->m_menu),
"hide",
GTK_SIGNAL_FUNC(gtk_pop_hide_callback),
(gpointer)&is_waiting );
+ wxPoint pos;
+ gpointer userdata;
+ GtkMenuPositionFunc posfunc;
+ if ( x == -1 && y == -1 )
+ {
+ // use GTK's default positioning algorithm
+ userdata = NULL;
+ posfunc = NULL;
+ }
+ else
+ {
+ pos = ClientToScreen(wxPoint(x, y));
+ userdata = &pos;
+ posfunc = wxPopupMenuPositionCallback;
+ }
+
gtk_menu_popup(
GTK_MENU(menu->m_menu),
(GtkWidget *) NULL, // parent menu shell
(GtkWidget *) NULL, // parent menu item
- wxPopupMenuPositionCallback, // function to position it
- NULL, // client data
+ posfunc, // function to position it
+ userdata, // client data
0, // button used to activate it
#ifdef __WXGTK20__
gtk_get_current_event_time()
gtk_main_iteration();
}
- return TRUE;
+ return true;
}
#endif // wxUSE_MENUS_NATIVE
bool wxWindowGTK::SetFont( const wxFont &font )
{
- if (!wxWindowBase::SetFont(font) || !m_widget)
- {
- return FALSE;
- }
+ wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
- wxColour sysbg = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE );
- if ( sysbg == m_backgroundColour )
- {
- m_backgroundColour = wxNullColour;
- ApplyWidgetStyle();
- m_backgroundColour = sysbg;
- }
- else
- {
- ApplyWidgetStyle();
- }
+ if (!wxWindowBase::SetFont(font))
+ return false;
- return TRUE;
+ // apply style change (forceStyle=true so that new style is applied
+ // even if the font changed from valid to wxNullFont):
+ ApplyWidgetStyle(true);
+
+ return true;
}
void wxWindowGTK::DoCaptureMouse()