]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/utilsgtk.cpp
disable select root menu command when the root is hidden
[wxWidgets.git] / src / gtk / utilsgtk.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
dbd25330 2// Name: src/gtk/utilsgtk.cpp
c801d85f
KB
3// Purpose:
4// Author: Robert Roebling
dfcb1ae0 5// Id: $Id$
6c9a19aa 6// Copyright: (c) 1998 Robert Roebling
65571936 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
14f355c2
VS
10// For compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
12
c801d85f 13#include "wx/utils.h"
df91131c
WS
14
15#ifndef WX_PRECOMP
16 #include "wx/string.h"
88a7a4e1 17 #include "wx/intl.h"
e4db172a 18 #include "wx/log.h"
df91131c 19#endif
c801d85f 20
46446cc2 21#include "wx/apptrait.h"
02847e59 22
5336ece4
VZ
23#include "wx/process.h"
24
518b5d2f
VZ
25#include "wx/unix/execute.h"
26
db9febdf 27#ifdef __WXDEBUG__
92696e94 28 #include "wx/gtk/assertdlg_gtk.h"
db9febdf 29 #if wxUSE_STACKWALKER
db9febdf
RR
30 #include "wx/stackwalk.h"
31 #endif // wxUSE_STACKWALKER
32#endif // __WXDEBUG__
33
c801d85f 34#include <stdarg.h>
c801d85f
KB
35#include <string.h>
36#include <sys/stat.h>
37#include <sys/types.h>
dbd25330 38#include <sys/wait.h> // for WNOHANG
c801d85f 39#include <unistd.h>
91b8de8d
RR
40
41#include "glib.h"
42#include "gdk/gdk.h"
43#include "gtk/gtk.h"
91b8de8d 44#include "gdk/gdkx.h"
88ac883a 45
27933891 46#ifdef HAVE_X11_XKBLIB_H
154c4aa1
VZ
47 /* under HP-UX and Solaris 2.6, at least, XKBlib.h defines structures with
48 * field named "explicit" - which is, of course, an error for a C++
49 * compiler. To be on the safe side, just redefine it everywhere. */
88ac883a 50 #define explicit __wx_explicit
ec5d7799 51
154c4aa1 52 #include "X11/XKBlib.h"
ec5d7799 53
88ac883a 54 #undef explicit
27933891 55#endif // HAVE_X11_XKBLIB_H
dfcb1ae0 56
88bbc332
RR
57
58#if wxUSE_DETECT_SM
59 #include "X11/Xlib.h"
60 #include "X11/SM/SMlib.h"
61#endif
62
d76fe38b
RR
63//-----------------------------------------------------------------------------
64// data
65//-----------------------------------------------------------------------------
66
c2fa61e8 67extern GtkWidget *wxGetRootWindow();
d76fe38b
RR
68
69//----------------------------------------------------------------------------
c801d85f 70// misc.
d76fe38b 71//----------------------------------------------------------------------------
189d1ae7
SN
72#ifndef __EMX__
73// on OS/2, we use the wxBell from wxBase library
c801d85f 74
518b5d2f 75void wxBell()
c801d85f 76{
e52f60e6
RR
77 gdk_beep();
78}
189d1ae7 79#endif
c801d85f 80
27933891
RR
81/* Don't synthesize KeyUp events holding down a key and producing
82 KeyDown events with autorepeat. */
83#ifdef HAVE_X11_XKBLIB_H
f0492f7d
RR
84bool wxSetDetectableAutoRepeat( bool flag )
85{
86 Bool result;
87 XkbSetDetectableAutoRepeat( GDK_DISPLAY(), flag, &result );
df91131c 88 return result; /* true if keyboard hardware supports this mode */
27933891
RR
89}
90#else
91bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag) )
92{
df91131c 93 return false;
f0492f7d 94}
27933891 95#endif
f0492f7d 96
66bd83b4
VS
97// Escapes string so that it is valid Pango markup XML string:
98wxString wxEscapeStringForPangoMarkup(const wxString& str)
99{
100 size_t len = str.length();
101 wxString out;
102 out.Alloc(len);
103 for (size_t i = 0; i < len; i++)
104 {
105 wxChar c = str[i];
106 switch (c)
107 {
108 case _T('&'):
109 out << _T("&amp;");
110 break;
111 case _T('<'):
112 out << _T("&lt;");
113 break;
114 case _T('>'):
115 out << _T("&gt;");
116 break;
117 case _T('\''):
118 out << _T("&apos;");
119 break;
120 case _T('"'):
121 out << _T("&quot;");
122 break;
123 default:
124 out << c;
125 break;
126 }
127 }
128 return out;
129}
66bd83b4
VS
130
131
518b5d2f
VZ
132// ----------------------------------------------------------------------------
133// display characterstics
134// ----------------------------------------------------------------------------
82052aff 135
d111a89a
VZ
136void *wxGetDisplay()
137{
27df579a 138 return GDK_DISPLAY();
d111a89a
VZ
139}
140
c0392997
RR
141void wxDisplaySize( int *width, int *height )
142{
e52f60e6
RR
143 if (width) *width = gdk_screen_width();
144 if (height) *height = gdk_screen_height();
c0392997
RR
145}
146
904a68b6
RL
147void wxDisplaySizeMM( int *width, int *height )
148{
149 if (width) *width = gdk_screen_width_mm();
150 if (height) *height = gdk_screen_height_mm();
151}
152
ec5d7799
RD
153void wxClientDisplayRect(int *x, int *y, int *width, int *height)
154{
155 // This is supposed to return desktop dimensions minus any window
156 // manager panels, menus, taskbars, etc. If there is a way to do that
157 // for this platform please fix this function, otherwise it defaults
158 // to the entire desktop.
159 if (x) *x = 0;
160 if (y) *y = 0;
161 wxDisplaySize(width, height);
162}
163
6de97a3b
RR
164void wxGetMousePosition( int* x, int* y )
165{
bbe0af5b 166 gdk_window_get_pointer( (GdkWindow*) NULL, x, y, (GdkModifierType*) NULL );
e52f60e6 167}
6de97a3b 168
518b5d2f 169bool wxColourDisplay()
6de97a3b 170{
df91131c 171 return true;
6de97a3b
RR
172}
173
518b5d2f 174int wxDisplayDepth()
6de97a3b 175{
22a3bce4 176 return gdk_drawable_get_visual( wxGetRootWindow()->window )->depth;
6de97a3b
RR
177}
178
57591e0e
JS
179wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
180{
181 return wxGenericFindWindowAtPoint(pt);
182}
183
5f11fef5
VZ
184#if !wxUSE_UNICODE
185
186wxCharBuffer wxConvertToGTK(const wxString& s, wxFontEncoding enc)
187{
404ac4c6
VZ
188 wxWCharBuffer wbuf;
189 if ( enc == wxFONTENCODING_SYSTEM || enc == wxFONTENCODING_DEFAULT )
5f11fef5 190 {
404ac4c6 191 wbuf = wxConvUI->cMB2WC(s);
12bc5f9a 192 }
404ac4c6 193 else // another encoding, use generic conversion class
12bc5f9a 194 {
404ac4c6
VZ
195 wbuf = wxCSConv(enc).cMB2WC(s);
196 }
12bc5f9a 197
404ac4c6
VZ
198 if ( !wbuf && !s.empty() )
199 {
200 // conversion failed, but we still want to show something to the user
201 // even if it's going to be wrong it is better than nothing
202 //
203 // we choose ISO8859-1 here arbitrarily, it's just the most common
204 // encoding probably and, also importantly here, conversion from it
205 // never fails as it's done internally by wxCSConv
206 wbuf = wxCSConv(wxFONTENCODING_ISO8859_1).cMB2WC(s);
27dee9ae 207 }
5f11fef5 208
404ac4c6 209 return wxConvUTF8.cWC2MB(wbuf);
5f11fef5
VZ
210}
211
30083ad8
VZ
212wxCharBuffer wxConvertFromGTK(const wxString& s, wxFontEncoding enc)
213{
214 // this conversion should never fail as GTK+ always uses UTF-8 internally
215 // so there are no complications here
216 const wxWCharBuffer wbuf(wxConvUTF8.cMB2WC(s));
217 if ( enc == wxFONTENCODING_SYSTEM )
218 return wxConvUI->cWC2MB(wbuf);
219
220 return wxCSConv(enc).cWC2MB(wbuf);
221}
222
5f11fef5 223#endif // !wxUSE_UNICODE
57591e0e 224
518b5d2f 225// ----------------------------------------------------------------------------
c801d85f 226// subprocess routines
518b5d2f 227// ----------------------------------------------------------------------------
cf447356 228
865bb325
VZ
229extern "C" {
230static
90350682
VZ
231void GTK_EndProcessDetector(gpointer data, gint source,
232 GdkInputCondition WXUNUSED(condition) )
cf447356 233{
ab857a4e 234 wxEndProcessData *proc_data = (wxEndProcessData *)data;
dbd25330
VZ
235
236 // has the process really terminated? unfortunately GDK (or GLib) seem to
237 // generate G_IO_HUP notification even when it simply tries to read from a
238 // closed fd and hasn't terminated at all
239 int pid = (proc_data->pid > 0) ? proc_data->pid : -(proc_data->pid);
447f908a
VZ
240 int status = 0;
241 int rc = waitpid(pid, &status, WNOHANG);
242
243 if ( rc == 0 )
dbd25330
VZ
244 {
245 // no, it didn't exit yet, continue waiting
246 return;
247 }
248
447f908a
VZ
249 // set exit code to -1 if something bad happened
250 proc_data->exitcode = rc != -1 && WIFEXITED(status) ? WEXITSTATUS(status)
251 : -1;
252
dbd25330 253 // child exited, end waiting
ab857a4e 254 close(source);
dbd25330
VZ
255
256 // don't call us again!
ab857a4e
KB
257 gdk_input_remove(proc_data->tag);
258
ab857a4e 259 wxHandleProcessTermination(proc_data);
3069ac4e 260}
865bb325 261}
cf447356 262
518b5d2f 263int wxAddProcessCallback(wxEndProcessData *proc_data, int fd)
c801d85f 264{
518b5d2f
VZ
265 int tag = gdk_input_add(fd,
266 GDK_INPUT_READ,
267 GTK_EndProcessDetector,
268 (gpointer)proc_data);
c801d85f 269
518b5d2f 270 return tag;
3069ac4e 271}
8bb6b2c0
VZ
272
273
274
275// ----------------------------------------------------------------------------
276// wxPlatformInfo-related
277// ----------------------------------------------------------------------------
278
279wxPortId wxGUIAppTraits::GetToolkitVersion(int *verMaj, int *verMin) const
280{
281 if ( verMaj )
282 *verMaj = gtk_major_version;
283 if ( verMin )
284 *verMin = gtk_minor_version;
285
286 return wxPORT_GTK;
287}
88bbc332
RR
288
289#if wxUSE_DETECT_SM
290static wxString GetSM()
291{
391bf008 292 class Dpy
cb1bf052 293 {
391bf008
VZ
294 public:
295 Dpy() { m_dpy = XOpenDisplay(NULL); }
296 ~Dpy() { if ( m_dpy ) XCloseDisplay(m_dpy); }
88bbc332 297
391bf008
VZ
298 operator Display *() const { return m_dpy; }
299 private:
300 Display *m_dpy;
301 } dpy;
88bbc332 302
391bf008
VZ
303 if ( !dpy )
304 return wxEmptyString;
305
306 char *client_id;
307 SmcConn smc_conn = SmcOpenConnection(NULL, NULL,
308 999, 999,
309 0 /* mask */, NULL /* callbacks */,
310 NULL, &client_id,
311 0, NULL);
312
313 if ( !smc_conn )
314 return wxEmptyString;
315
316 char *vendor = SmcVendor(smc_conn);
317 wxString ret = wxString::FromAscii( vendor );
318 free(vendor);
319
320 SmcCloseConnection(smc_conn, 0, NULL);
321 free(client_id);
322
323 return ret;
88bbc332 324}
391bf008 325#endif // wxUSE_DETECT_SM
88bbc332 326
db9febdf
RR
327
328//-----------------------------------------------------------------------------
329// wxGUIAppTraits
330//-----------------------------------------------------------------------------
331
6c4f5ea5 332#if wxUSE_INTL
d774f916
VZ
333void wxGUIAppTraits::SetLocale()
334{
335 gtk_set_locale();
336}
6c4f5ea5 337#endif
d774f916 338
db9febdf
RR
339#ifdef __WXDEBUG__
340
341#if wxUSE_STACKWALKER
342
343// private helper class
344class StackDump : public wxStackWalker
345{
346public:
347 StackDump(GtkAssertDialog *dlg) { m_dlg=dlg; }
348
349protected:
350 virtual void OnStackFrame(const wxStackFrame& frame)
351 {
352 wxString fncname = frame.GetName();
353 wxString fncargs = fncname;
354
355 size_t n = fncname.find(wxT('('));
356 if (n != wxString::npos)
357 {
358 // remove arguments from function name
359 fncname.erase(n);
360
361 // remove function name and brackets from arguments
362 fncargs = fncargs.substr(n+1, fncargs.length()-n-2);
363 }
364 else
365 fncargs = wxEmptyString;
366
367 // append this stack frame's info in the dialog
368 if (!frame.GetFileName().empty() || !fncname.empty())
369 gtk_assert_dialog_append_stack_frame(m_dlg,
370 fncname.mb_str(),
371 fncargs.mb_str(),
372 frame.GetFileName().mb_str(),
373 frame.GetLine());
374 }
375
376private:
377 GtkAssertDialog *m_dlg;
378};
379
380// the callback functions must be extern "C" to comply with GTK+ declarations
381extern "C"
382{
383 void get_stackframe_callback(StackDump *dump)
384 {
62710178
VZ
385 // skip over frames up to including wxOnAssert()
386 dump->ProcessFrames(3);
db9febdf
RR
387 }
388}
389
390#endif // wxUSE_STACKWALKER
391
392bool wxGUIAppTraits::ShowAssertDialog(const wxString& msg)
393{
394 // under GTK2 we prefer to use a dialog widget written using directly GTK+;
395 // in fact we cannot use a dialog written using wxWidgets: it would need
396 // the wxWidgets idle processing to work correctly!
397 GtkWidget *dialog = gtk_assert_dialog_new();
398 gtk_assert_dialog_set_message(GTK_ASSERT_DIALOG(dialog), msg.mb_str());
399
400#if wxUSE_STACKWALKER
401 // don't show more than maxLines or we could get a dialog too tall to be
402 // shown on screen: 20 should be ok everywhere as even with 15 pixel high
403 // characters it is still only 300 pixels...
404 static const int maxLines = 20;
405
406 // save current stack frame...
407 StackDump dump(GTK_ASSERT_DIALOG(dialog));
408 dump.SaveStack(maxLines);
409
410 // ...but process it only if the user needs it
411 gtk_assert_dialog_set_backtrace_callback(GTK_ASSERT_DIALOG(dialog),
412 (GtkAssertDialogStackFrameCallback)get_stackframe_callback,
413 &dump);
414#endif // wxUSE_STACKWALKER
415
416 gint result = gtk_dialog_run(GTK_DIALOG (dialog));
417 bool returnCode = false;
418 switch (result)
419 {
420 case GTK_ASSERT_DIALOG_STOP:
421 wxTrap();
422 break;
423 case GTK_ASSERT_DIALOG_CONTINUE:
424 // nothing to do
425 break;
426 case GTK_ASSERT_DIALOG_CONTINUE_SUPPRESSING:
427 // no more asserts
428 returnCode = true;
429 break;
430
431 default:
432 wxFAIL_MSG( _T("unexpected return code from GtkAssertDialog") );
433 }
434
435 gtk_widget_destroy(dialog);
436 return returnCode;
437}
438
439#endif // __WXDEBUG__
440
88bbc332
RR
441wxString wxGUIAppTraits::GetDesktopEnvironment() const
442{
443#if wxUSE_DETECT_SM
391bf008
VZ
444 const wxString SM = GetSM();
445
88bbc332
RR
446 if (SM == wxT("GnomeSM"))
447 return wxT("GNOME");
391bf008 448
88bbc332
RR
449 if (SM == wxT("KDE"))
450 return wxT("KDE");
391bf008 451#endif // wxUSE_DETECT_SM
88bbc332
RR
452
453 return wxEmptyString;
454}
455
456
457