1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/utilsgtk.cpp 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 // For compilers that support precompilation, includes "wx.h". 
  11 #include "wx/wxprec.h" 
  16     #include "wx/string.h" 
  21 #include "wx/apptrait.h" 
  22 #include "wx/process.h" 
  23 #include "wx/sysopt.h" 
  24 #include "wx/unix/execute.h" 
  26 #include "wx/gtk/private/timer.h" 
  27 #include "wx/evtloop.h" 
  30     #include "wx/gtk/assertdlg_gtk.h" 
  32         #include "wx/stackwalk.h" 
  33     #endif // wxUSE_STACKWALKER 
  34 #endif // wxDEBUG_LEVEL 
  39 #include <sys/types.h> 
  40 #include <sys/wait.h>   // for WNOHANG 
  50     #include "X11/SM/SMlib.h" 
  52     #include "wx/unix/utilsx11.h" 
  55 //----------------------------------------------------------------------------- 
  57 //----------------------------------------------------------------------------- 
  59 extern GtkWidget 
*wxGetRootWindow(); 
  61 //---------------------------------------------------------------------------- 
  63 //---------------------------------------------------------------------------- 
  65 // on OS/2, we use the wxBell from wxBase library 
  73 // ---------------------------------------------------------------------------- 
  74 // display characterstics 
  75 // ---------------------------------------------------------------------------- 
  82 void wxDisplaySize( int *width
, int *height 
) 
  84     if (width
) *width 
= gdk_screen_width(); 
  85     if (height
) *height 
= gdk_screen_height(); 
  88 void wxDisplaySizeMM( int *width
, int *height 
) 
  90     if (width
) *width 
= gdk_screen_width_mm(); 
  91     if (height
) *height 
= gdk_screen_height_mm(); 
  94 void wxGetMousePosition( int* x
, int* y 
) 
  96     gdk_window_get_pointer( NULL
, x
, y
, NULL 
); 
  99 bool wxColourDisplay() 
 106     return gdk_drawable_get_visual( wxGetRootWindow()->window 
)->depth
; 
 109 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
) 
 111     return wxGenericFindWindowAtPoint(pt
); 
 116 WXDLLIMPEXP_CORE wxCharBuffer
 
 117 wxConvertToGTK(const wxString
& s
, wxFontEncoding enc
) 
 120     if ( enc 
== wxFONTENCODING_SYSTEM 
|| enc 
== wxFONTENCODING_DEFAULT 
) 
 122         wbuf 
= wxConvUI
->cMB2WC(s
.c_str()); 
 124     else // another encoding, use generic conversion class 
 126         wbuf 
= wxCSConv(enc
).cMB2WC(s
.c_str()); 
 129     if ( !wbuf 
&& !s
.empty() ) 
 131         // conversion failed, but we still want to show something to the user 
 132         // even if it's going to be wrong it is better than nothing 
 134         // we choose ISO8859-1 here arbitrarily, it's just the most common 
 135         // encoding probably and, also importantly here, conversion from it 
 136         // never fails as it's done internally by wxCSConv 
 137         wbuf 
= wxCSConv(wxFONTENCODING_ISO8859_1
).cMB2WC(s
.c_str()); 
 140     return wxConvUTF8
.cWC2MB(wbuf
); 
 143 WXDLLIMPEXP_CORE wxCharBuffer
 
 144 wxConvertFromGTK(const wxString
& s
, wxFontEncoding enc
) 
 146     // this conversion should never fail as GTK+ always uses UTF-8 internally 
 147     // so there are no complications here 
 148     const wxWCharBuffer 
wbuf(wxConvUTF8
.cMB2WC(s
.c_str())); 
 149     if ( enc 
== wxFONTENCODING_SYSTEM 
) 
 150         return wxConvUI
->cWC2MB(wbuf
); 
 152     return wxCSConv(enc
).cWC2MB(wbuf
); 
 155 #endif // !wxUSE_UNICODE 
 157 // Returns NULL if version is certainly greater or equal than major.minor.micro 
 158 // Returns string describing the error if version is lower than 
 159 // major.minor.micro OR it cannot be determined and one should not rely on the 
 160 // availability of pango version major.minor.micro, nor the non-availability 
 161 const gchar 
*wx_pango_version_check (int major
, int minor
, int micro
) 
 163     // NOTE: you don't need to use this macro to check for Pango features 
 164     //       added in pango-1.4 or earlier since GTK 2.4 (our minimum requirement 
 165     //       for GTK lib) required pango 1.4... 
 167 #ifdef PANGO_VERSION_MAJOR 
 168     if (!gtk_check_version (2,11,0)) 
 170         // GTK+ 2.11 requires Pango >= 1.15.3 and pango_version_check 
 171         // was added in Pango 1.15.2 thus we know for sure the pango lib we're 
 172         // using has the pango_version_check function: 
 173         return pango_version_check (major
, minor
, micro
); 
 176     return "can't check"; 
 177 #else // !PANGO_VERSION_MAJOR 
 182     return "too old headers"; 
 187 // ---------------------------------------------------------------------------- 
 188 // subprocess routines 
 189 // ---------------------------------------------------------------------------- 
 193 void GTK_EndProcessDetector(gpointer data
, gint source
, 
 194                             GdkInputCondition 
WXUNUSED(condition
)) 
 196     wxEndProcessData 
* const 
 197         proc_data 
= static_cast<wxEndProcessData 
*>(data
); 
 199     // child exited, end waiting 
 202     // don't call us again! 
 203     gdk_input_remove(proc_data
->tag
); 
 205     wxHandleProcessTermination(proc_data
); 
 209 int wxGUIAppTraits::AddProcessCallback(wxEndProcessData 
*proc_data
, int fd
) 
 211     int tag 
= gdk_input_add(fd
, 
 213                             GTK_EndProcessDetector
, 
 214                             (gpointer
)proc_data
); 
 221 // ---------------------------------------------------------------------------- 
 222 // wxPlatformInfo-related 
 223 // ---------------------------------------------------------------------------- 
 225 wxPortId 
wxGUIAppTraits::GetToolkitVersion(int *verMaj
, int *verMin
) const 
 228         *verMaj 
= gtk_major_version
; 
 230         *verMin 
= gtk_minor_version
; 
 237 wxTimerImpl 
*wxGUIAppTraits::CreateTimerImpl(wxTimer 
*timer
) 
 239     return new wxGTKTimerImpl(timer
); 
 242 #endif // wxUSE_TIMER 
 245 static wxString 
GetSM() 
 249         return wxEmptyString
; 
 253     SmcConn smc_conn 
= SmcOpenConnection(NULL
, NULL
, 
 255                                          0 /* mask */, NULL 
/* callbacks */, 
 257                                          WXSIZEOF(smerr
), smerr
); 
 261         wxLogDebug("Failed to connect to session manager: %s", smerr
); 
 262         return wxEmptyString
; 
 265     char *vendor 
= SmcVendor(smc_conn
); 
 266     wxString ret 
= wxString::FromAscii( vendor 
); 
 269     SmcCloseConnection(smc_conn
, 0, NULL
); 
 274 #endif // wxUSE_DETECT_SM 
 277 //----------------------------------------------------------------------------- 
 279 //----------------------------------------------------------------------------- 
 281 wxEventLoopBase 
*wxGUIAppTraits::CreateEventLoop() 
 283     return new wxEventLoop(); 
 288 void wxGUIAppTraits::SetLocale() 
 291     wxUpdateLocaleIsUtf8(); 
 295 #if wxDEBUG_LEVEL && wxUSE_STACKWALKER 
 297 // private helper class 
 298 class StackDump 
: public wxStackWalker
 
 301     StackDump(GtkAssertDialog 
*dlg
) { m_dlg
=dlg
; } 
 304     virtual void OnStackFrame(const wxStackFrame
& frame
) 
 306         wxString fncname 
= frame
.GetName(); 
 307         wxString fncargs 
= fncname
; 
 309         size_t n 
= fncname
.find(wxT('(')); 
 310         if (n 
!= wxString::npos
) 
 312             // remove arguments from function name 
 315             // remove function name and brackets from arguments 
 316             fncargs 
= fncargs
.substr(n
+1, fncargs
.length()-n
-2); 
 319             fncargs 
= wxEmptyString
; 
 321         // append this stack frame's info in the dialog 
 322         if (!frame
.GetFileName().empty() || !fncname
.empty()) 
 323             gtk_assert_dialog_append_stack_frame(m_dlg
, 
 326                                                 frame
.GetFileName().mb_str(), 
 331     GtkAssertDialog 
*m_dlg
; 
 334 // the callback functions must be extern "C" to comply with GTK+ declarations 
 337     void get_stackframe_callback(StackDump 
*dump
) 
 339         // skip over frames up to including wxOnAssert() 
 340         dump
->ProcessFrames(3); 
 344 #endif // wxDEBUG_LEVEL && wxUSE_STACKWALKER 
 346 bool wxGUIAppTraits::ShowAssertDialog(const wxString
& msg
) 
 349     // we can't show the dialog from another thread 
 350     if ( wxIsMainThread() ) 
 352         // under GTK2 we prefer to use a dialog widget written using directly 
 353         // in GTK+ as use a dialog written using wxWidgets would need the 
 354         // wxWidgets idle processing to work correctly which might not be the 
 355         // case when assert happens 
 356         GtkWidget 
*dialog 
= gtk_assert_dialog_new(); 
 357         gtk_assert_dialog_set_message(GTK_ASSERT_DIALOG(dialog
), msg
.mb_str()); 
 359 #if wxUSE_STACKWALKER 
 360         // save the current stack ow... 
 361         StackDump 
dump(GTK_ASSERT_DIALOG(dialog
)); 
 362         dump
.SaveStack(100); // showing more than 100 frames is not very useful 
 364         // ...but process it only if the user needs it 
 365         gtk_assert_dialog_set_backtrace_callback
 
 367             GTK_ASSERT_DIALOG(dialog
), 
 368             (GtkAssertDialogStackFrameCallback
)get_stackframe_callback
, 
 371 #endif // wxUSE_STACKWALKER 
 373         gint result 
= gtk_dialog_run(GTK_DIALOG (dialog
)); 
 374         bool returnCode 
= false; 
 377             case GTK_ASSERT_DIALOG_STOP
: 
 380             case GTK_ASSERT_DIALOG_CONTINUE
: 
 383             case GTK_ASSERT_DIALOG_CONTINUE_SUPPRESSING
: 
 389                 wxFAIL_MSG( wxT("unexpected return code from GtkAssertDialog") ); 
 392         gtk_widget_destroy(dialog
); 
 395 #endif // wxDEBUG_LEVEL 
 397     return wxAppTraitsBase::ShowAssertDialog(msg
); 
 400 wxString 
wxGUIAppTraits::GetDesktopEnvironment() const 
 402     wxString de 
= wxSystemOptions::GetOption(wxT("gtk.desktop")); 
 406         static const wxString s_SM 
= GetSM(); 
 408         if (s_SM 
== wxT("GnomeSM")) 
 410         else if (s_SM 
== wxT("KDE")) 
 413 #endif // wxUSE_DETECT_SM 
 420 // see the hack below in wxCmdLineParser::GetUsageString(). 
 421 // TODO: replace this hack with a g_option_group_get_entries() 
 422 //       call as soon as such function exists; 
 423 //       see http://bugzilla.gnome.org/show_bug.cgi?id=431021 for the relative 
 429   gchar           
*help_description
; 
 431   GDestroyNotify   destroy_notify
; 
 434   GTranslateFunc   translate_func
; 
 435   GDestroyNotify   translate_notify
; 
 436   gpointer     translate_data
; 
 438   GOptionEntry    
*entries
; 
 441   GOptionParseFunc pre_parse_func
; 
 442   GOptionParseFunc post_parse_func
; 
 443   GOptionErrorFunc error_func
; 
 446 wxString 
wxGetNameFromGtkOptionEntry(const GOptionEntry 
*opt
) 
 451         ret 
<< wxT("-") << opt
->short_name
; 
 456         ret 
<< wxT("--") << opt
->long_name
; 
 458         if (opt
->arg_description
) 
 459             ret 
<< wxT("=") << opt
->arg_description
; 
 462     return wxT("  ") + ret
; 
 465 #endif // __WXGTK26__ 
 468 wxGUIAppTraits::GetStandardCmdLineOptions(wxArrayString
& names
, 
 469                                           wxArrayString
& desc
) const 
 474     if (!gtk_check_version(2,6,0)) 
 476         // since GTK>=2.6, we can use the glib_check_version() symbol... 
 478         // check whether GLib version is greater than 2.6 but also lower than 2.19 
 479         // because, as we use the undocumented _GOptionGroup struct, we don't want 
 480         // to run this code with future versions which might change it (2.19 is the 
 481         // latest one at the time of this writing) 
 482         if (!glib_check_version(2,6,0) && glib_check_version(2,20,0)) 
 484             usage 
<< _("The following standard GTK+ options are also supported:\n"); 
 486             // passing true here means that the function can open the default 
 487             // display while parsing (not really used here anyhow) 
 488             GOptionGroup 
*gtkOpts 
= gtk_get_option_group(true); 
 490             // WARNING: here we access the internals of GOptionGroup: 
 491             GOptionEntry 
*entries 
= ((_GOptionGroup
*)gtkOpts
)->entries
; 
 492             unsigned int n_entries 
= ((_GOptionGroup
*)gtkOpts
)->n_entries
; 
 493             wxArrayString namesOptions
, descOptions
; 
 495             for ( size_t n 
= 0; n 
< n_entries
; n
++ ) 
 497                 if ( entries
[n
].flags 
& G_OPTION_FLAG_HIDDEN 
) 
 500                 names
.push_back(wxGetNameFromGtkOptionEntry(&entries
[n
])); 
 502                 const gchar 
* const entryDesc 
= entries
[n
].description
; 
 503                 desc
.push_back(wxString(entryDesc
)); 
 506             g_option_group_free (gtkOpts
); 
 512 #endif // __WXGTK26__