+ g_object_unref (layout);
+
+ return (int) PANGO_PIXELS(rect.width);
+}
+
+void wxWindowGTK::DoGetTextExtent( const wxString& string,
+ int *x,
+ int *y,
+ int *descent,
+ int *externalLeading,
+ const wxFont *theFont ) const
+{
+ wxFont fontToUse = theFont ? *theFont : GetFont();
+
+ wxCHECK_RET( fontToUse.IsOk(), wxT("invalid font") );
+
+ if (string.empty())
+ {
+ if (x) (*x) = 0;
+ if (y) (*y) = 0;
+ return;
+ }
+
+ PangoContext *context = NULL;
+ if (m_widget)
+ context = gtk_widget_get_pango_context( m_widget );
+
+ if (!context)
+ {
+ if (x) (*x) = 0;
+ if (y) (*y) = 0;
+ return;
+ }
+
+ PangoFontDescription *desc = fontToUse.GetNativeFontInfo()->description;
+ PangoLayout *layout = pango_layout_new(context);
+ pango_layout_set_font_description(layout, desc);
+ {
+ const wxCharBuffer data = wxGTK_CONV( string );
+ if ( data )
+ pango_layout_set_text(layout, data, strlen(data));
+ }
+
+ PangoRectangle rect;
+ pango_layout_get_extents(layout, NULL, &rect);
+
+ if (x) (*x) = (wxCoord) PANGO_PIXELS(rect.width);
+ if (y) (*y) = (wxCoord) PANGO_PIXELS(rect.height);
+ if (descent)
+ {
+ PangoLayoutIter *iter = pango_layout_get_iter(layout);
+ int baseline = pango_layout_iter_get_baseline(iter);
+ pango_layout_iter_free(iter);
+ *descent = *y - PANGO_PIXELS(baseline);
+ }
+ if (externalLeading) (*externalLeading) = 0; // ??
+
+ g_object_unref (layout);
+}
+
+void wxWindowGTK::GTKDisableFocusOutEvent()
+{
+ g_signal_handlers_block_by_func( m_focusWidget,
+ (gpointer) gtk_window_focus_out_callback, this);
+}
+
+void wxWindowGTK::GTKEnableFocusOutEvent()
+{
+ g_signal_handlers_unblock_by_func( m_focusWidget,
+ (gpointer) gtk_window_focus_out_callback, this);
+}
+
+bool wxWindowGTK::GTKHandleFocusIn()
+{
+ // Disable default focus handling for custom windows since the default GTK+
+ // handler issues a repaint
+ const bool retval = m_wxwindow ? true : false;
+
+
+ // NB: if there's still unprocessed deferred focus-out event (see
+ // GTKHandleFocusOut() for explanation), we need to process it first so
+ // that the order of focus events -- focus-out first, then focus-in
+ // elsewhere -- is preserved
+ if ( gs_deferredFocusOut )
+ {
+ if ( GTKNeedsToFilterSameWindowFocus() &&
+ gs_deferredFocusOut == this )
+ {
+ // GTK+ focus changed from this wxWindow back to itself, so don't
+ // emit any events at all
+ wxLogTrace(TRACE_FOCUS,
+ "filtered out spurious focus change within %s(%p, %s)",
+ GetClassInfo()->GetClassName(), this, GetLabel());
+ gs_deferredFocusOut = NULL;
+ return retval;
+ }
+
+ // otherwise we need to send focus-out first
+ wxASSERT_MSG ( gs_deferredFocusOut != this,
+ "GTKHandleFocusIn(GTKFocus_Normal) called even though focus changed back to itself - derived class should handle this" );
+ GTKHandleDeferredFocusOut();
+ }
+
+
+ wxLogTrace(TRACE_FOCUS,
+ "handling focus_in event for %s(%p, %s)",
+ GetClassInfo()->GetClassName(), this, GetLabel());
+
+ if (m_imData)
+ gtk_im_context_focus_in(m_imData->context);
+
+ gs_currentFocus = this;
+ gs_pendingFocus = NULL;
+
+#if wxUSE_CARET
+ // caret needs to be informed about focus change
+ wxCaret *caret = GetCaret();
+ if ( caret )
+ {
+ caret->OnSetFocus();
+ }
+#endif // wxUSE_CARET
+
+ // Notify the parent keeping track of focus for the kbd navigation
+ // purposes that we got it.
+ wxChildFocusEvent eventChildFocus(static_cast<wxWindow*>(this));
+ GTKProcessEvent(eventChildFocus);
+
+ wxFocusEvent eventFocus(wxEVT_SET_FOCUS, GetId());
+ eventFocus.SetEventObject(this);
+ GTKProcessEvent(eventFocus);