]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/motif/app.cpp
Applied #15375 to stop event-sending in generic wxSpinCtrl ctor (eco)
[wxWidgets.git] / src / motif / app.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/motif/app.cpp
3// Purpose: wxApp
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// Copyright: (c) Julian Smart
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#include "wx/app.h"
15
16#ifndef WX_PRECOMP
17 #include "wx/hash.h"
18 #include "wx/intl.h"
19 #include "wx/log.h"
20 #include "wx/utils.h"
21 #include "wx/memory.h"
22 #include "wx/font.h"
23#endif
24
25#include "wx/evtloop.h"
26
27#if wxUSE_THREADS
28 #include "wx/thread.h"
29#endif
30
31#ifdef __VMS__
32 #pragma message disable nosimpint
33#endif
34#include <Xm/Xm.h>
35#include <X11/Xlib.h>
36#include <X11/Xutil.h>
37#include <X11/Xresource.h>
38#include <X11/Xatom.h>
39#ifdef __VMS__
40 #pragma message enable nosimpint
41#endif
42
43#include "wx/motif/private.h"
44
45#include <string.h>
46
47struct wxPerDisplayData
48{
49 wxPerDisplayData()
50 {
51 m_visualInfo = NULL;
52 m_topLevelWidget = NULL;
53 m_topLevelRealizedWidget = NULL;
54 }
55
56 wxXVisualInfo* m_visualInfo;
57 Widget m_topLevelWidget, m_topLevelRealizedWidget;
58};
59
60static void wxTLWidgetDestroyCallback(Widget w, XtPointer clientData,
61 XtPointer ptr);
62static WXWidget wxCreateTopLevelWidget( WXDisplay* display );
63
64extern bool wxAddIdleCallback();
65
66wxHashTable *wxWidgetHashTable = NULL;
67
68IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
69
70extern "C"
71{
72 typedef int (*XErrorHandlerFunc)(Display *, XErrorEvent *);
73}
74
75XErrorHandlerFunc gs_pfnXErrorHandler = 0;
76
77extern "C"
78{
79
80static int wxXErrorHandler(Display *dpy, XErrorEvent *xevent)
81{
82 // just forward to the default handler for now
83 return gs_pfnXErrorHandler(dpy, xevent);
84}
85
86}
87
88bool wxApp::Initialize(int& argc_, wxChar **argv_)
89{
90#if wxUSE_INTL
91 wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
92#endif
93
94 if ( !wxAppBase::Initialize(argc_, argv_) )
95 return false;
96
97 wxWidgetHashTable = new wxHashTable(wxKEY_INTEGER);
98
99#ifdef __HPUX__
100 // under HP-UX creating XmFontSet fails when the system locale is C and
101 // we're using a remote DISPLAY, presumably because HP-UX uses its own
102 // names for C and ISO locales (roman8 and iso8859n respectively) and so
103 // its Motif libraries have troubles with non-HP X server
104 //
105 // whatever the reason, the fact is that without this hack any wxMotif
106 // program crashes on startup because it can't create any font (HP programs
107 // still work but they do spit out messages about failing to create font
108 // sets and failing back on "fixed" font too)
109 //
110 // notice that calling setlocale() here is not enough because X(m) init
111 // functions call setlocale() later so we really have to change environment
112 bool fixAll = false; // tweak LC_ALL (or just LC_CTYPE)?
113 const char *loc = getenv("LC_CTYPE");
114 if ( !loc )
115 {
116 loc = getenv("LC_ALL");
117 if ( loc )
118 fixAll = true;
119 }
120
121 if ( !loc ||
122 (loc[0] == 'C' && loc[1] == '\0') ||
123 strcmp(loc, "POSIX") == 0 )
124 {
125 // we're using C locale, "fix" it
126 wxLogDebug(wxT("HP-UX fontset hack: forcing locale to en_US.iso88591"));
127 putenv(fixAll ? "LC_ALL=en_US.iso88591" : "LC_CTYPE=en_US.iso88591");
128 }
129#endif // __HPUX__
130
131 XtSetLanguageProc(NULL, NULL, NULL);
132 XtToolkitInitialize() ;
133 wxTheApp->m_appContext = (WXAppContext) XtCreateApplicationContext();
134
135 static char *fallbackResources[] = {
136 // better defaults for CDE under Irix
137 //
138 // TODO: do something similar for the other systems, the hardcoded defaults
139 // below are ugly
140#ifdef __SGI__
141 wxMOTIF_STR("*sgiMode: True"),
142 wxMOTIF_STR("*useSchemes: all"),
143#else // !__SGI__
144#if !wxMOTIF_USE_RENDER_TABLE
145 wxMOTIF_STR("*.fontList: -*-helvetica-medium-r-normal-*-*-120-*-*-*-*-*-*"),
146#else
147 wxMOTIF_STR("*wxDefaultRendition.fontName: -*-helvetica-medium-r-normal-*-*-120-*-*-*-*-*-*"),
148 wxMOTIF_STR("*wxDefaultRendition.fontType: FONT_IS_FONTSET"),
149 wxMOTIF_STR("*.renderTable: wxDefaultRendition"),
150#endif
151 wxMOTIF_STR("*listBox.background: white"),
152 wxMOTIF_STR("*text.background: white"),
153 wxMOTIF_STR("*comboBox.Text.background: white"),
154 wxMOTIF_STR("*comboBox.List.background: white"),
155#endif // __SGI__/!__SGI__
156 NULL
157 };
158 XtAppSetFallbackResources((XtAppContext) wxTheApp->m_appContext, fallbackResources);
159
160 // we shouldn't pass empty application/class name as it results in
161 // immediate crash inside XOpenIM() (if XIM is used) under IRIX
162 wxString appname = wxTheApp->GetAppName();
163 if ( appname.empty() )
164 appname = wxT("wxapp");
165 wxString clsname = wxTheApp->GetClassName();
166 if ( clsname.empty() )
167 clsname = wxT("wx");
168
169 // FIXME-UTF8: This code is taken from wxGTK and duplicated here. This
170 // is just a temporary fix to make wxX11 compile in Unicode
171 // build, the real fix is to change Initialize()'s signature
172 // to use char* on Unix.
173#if wxUSE_UNICODE
174 // XtOpenDisplay() wants char*, not wchar_t*, so convert
175 int i;
176 char **argvX11 = new char *[argc + 1];
177 for ( i = 0; i < argc; i++ )
178 {
179 argvX11[i] = strdup(wxConvLibc.cWX2MB(argv_[i]));
180 }
181
182 argvX11[argc] = NULL;
183
184 int argcX11 = argc;
185
186 Display *dpy = XtOpenDisplay((XtAppContext) wxTheApp->m_appContext,
187 (String)NULL,
188 appname.c_str(),
189 clsname.c_str(),
190 NULL, 0, // no options
191# if XtSpecificationRelease < 5
192 (Cardinal*) &argcX11,
193# else
194 &argcX11,
195# endif
196 argvX11);
197
198 if ( argcX11 != argc )
199 {
200 // we have to drop the parameters which were consumed by X11+
201 for ( i = 0; i < argcX11; i++ )
202 {
203 while ( strcmp(wxConvLibc.cWX2MB(argv_[i]), argvX11[i]) != 0 )
204 {
205 memmove(argv_ + i, argv_ + i + 1, (argc - i)*sizeof(*argv_));
206 }
207 }
208
209 argc = argcX11;
210
211 // update internal arg[cv] as X11 may have removed processed options:
212 argc = argc_;
213 argv = argv_;
214 }
215 //else: XtOpenDisplay() didn't modify our parameters
216
217 // free our copy
218 for ( i = 0; i < argcX11; i++ )
219 {
220 free(argvX11[i]);
221 }
222
223 delete [] argvX11;
224
225#else // ANSI
226
227 Display *dpy = XtOpenDisplay((XtAppContext) wxTheApp->m_appContext,
228 (String)NULL,
229 appname.c_str(),
230 clsname.c_str(),
231 NULL, 0, // no options
232# if XtSpecificationRelease < 5
233 (Cardinal*) &argc,
234# else
235 &argc,
236# endif
237 argv);
238
239#endif // Unicode/ANSI
240
241 if (!dpy) {
242 // if you don't log to stderr, nothing will be shown...
243 delete wxLog::SetActiveTarget(new wxLogStderr);
244 wxString className(wxTheApp->GetClassName());
245 wxLogError(_("wxWidgets could not open display for '%s': exiting."),
246 className.c_str());
247 exit(-1);
248 }
249 m_initialDisplay = (WXDisplay*) dpy;
250
251 // install the X error handler
252 gs_pfnXErrorHandler = XSetErrorHandler(wxXErrorHandler);
253
254 // Add general resize proc
255 XtActionsRec rec;
256 rec.string = wxMOTIF_STR("resize");
257 rec.proc = (XtActionProc)wxWidgetResizeProc;
258 XtAppAddActions((XtAppContext) wxTheApp->m_appContext, &rec, 1);
259
260 GetMainColormap(dpy);
261
262 wxAddIdleCallback();
263
264 return true;
265}
266
267void wxApp::CleanUp()
268{
269 wxAppBase::CleanUp();
270
271 wxDELETE(wxWidgetHashTable);
272
273 delete m_mainLoop;
274
275 for( wxPerDisplayDataMap::iterator it = m_perDisplayData->begin(),
276 end = m_perDisplayData->end();
277 it != end; ++it )
278 {
279 delete it->second->m_visualInfo;
280 // On Solaris 10 calling XtDestroyWidget on the top level widget
281 // dumps core if the locale is set to something other than "C"
282#ifndef __SUN__
283 XtDestroyWidget( it->second->m_topLevelWidget );
284#endif
285 delete it->second;
286 }
287}
288
289void wxApp::Exit()
290{
291 wxApp::CleanUp();
292
293 wxAppConsole::Exit();
294}
295
296// ============================================================================
297// wxApp
298// ============================================================================
299
300wxApp::wxApp()
301{
302 m_mainLoop = new wxEventLoop;
303 m_mainColormap = (WXColormap) NULL;
304 m_appContext = (WXAppContext) NULL;
305 m_initialDisplay = (WXDisplay*) 0;
306 m_perDisplayData = new wxPerDisplayDataMap;
307}
308
309wxApp::~wxApp()
310{
311 delete m_perDisplayData;
312}
313
314int wxApp::MainLoop()
315{
316 /*
317 * Sit around forever waiting to process X-events. Property Change
318 * event are handled special, because they have to refer to
319 * the root window rather than to a widget. therefore we can't
320 * use an Xt-eventhandler.
321 */
322
323 XSelectInput(XtDisplay((Widget) wxTheApp->GetTopLevelWidget()),
324 XDefaultRootWindow(XtDisplay((Widget) wxTheApp->GetTopLevelWidget())),
325 PropertyChangeMask);
326
327 m_mainLoop->Run();
328
329 return 0;
330}
331
332// This should be redefined in a derived class for
333// handling property change events for XAtom IPC.
334void wxApp::HandlePropertyChange(WXEvent *event)
335{
336 // by default do nothing special
337 XtDispatchEvent((XEvent*) event); /* let Motif do the work */
338}
339
340WXColormap wxApp::GetMainColormap(WXDisplay* display)
341{
342 if (!display) /* Must be called first with non-NULL display */
343 return m_mainColormap;
344
345 int defaultScreen = DefaultScreen((Display*) display);
346 Screen* screen = XScreenOfDisplay((Display*) display, defaultScreen);
347
348 Colormap c = DefaultColormapOfScreen(screen);
349
350 if (!m_mainColormap)
351 m_mainColormap = (WXColormap) c;
352
353 return (WXColormap) c;
354}
355
356static inline wxPerDisplayData& GetOrCreatePerDisplayData
357 ( wxPerDisplayDataMap& m, WXDisplay* display )
358{
359 wxPerDisplayDataMap::iterator it = m.find( display );
360 if( it != m.end() && it->second != NULL )
361 return *(it->second);
362
363 wxPerDisplayData* nData = new wxPerDisplayData();
364 m[display] = nData;
365
366 return *nData;
367}
368
369wxXVisualInfo* wxApp::GetVisualInfo( WXDisplay* display )
370{
371 wxPerDisplayData& data = GetOrCreatePerDisplayData( *m_perDisplayData,
372 display );
373 if( data.m_visualInfo )
374 return data.m_visualInfo;
375
376 wxXVisualInfo* vi = new wxXVisualInfo;
377 wxFillXVisualInfo( vi, (Display*)display );
378
379 data.m_visualInfo = vi;
380
381 return vi;
382}
383
384static void wxTLWidgetDestroyCallback(Widget w, XtPointer WXUNUSED(clientData),
385 XtPointer WXUNUSED(ptr))
386{
387 if( wxTheApp )
388 {
389 wxTheApp->SetTopLevelWidget( (WXDisplay*)XtDisplay(w),
390 (WXWidget)NULL );
391 wxTheApp->SetTopLevelRealizedWidget( (WXDisplay*)XtDisplay(w),
392 (WXWidget)NULL );
393 }
394}
395
396WXWidget wxCreateTopLevelWidget( WXDisplay* display )
397{
398 Widget tlw = XtAppCreateShell( (String)NULL,
399 wxTheApp->GetClassName().c_str(),
400 applicationShellWidgetClass,
401 (Display*)display,
402 NULL, 0 );
403 XtVaSetValues( tlw,
404 XmNoverrideRedirect, True,
405 NULL );
406
407 XtAddCallback( tlw, XmNdestroyCallback,
408 (XtCallbackProc)wxTLWidgetDestroyCallback,
409 (XtPointer)NULL );
410
411 return (WXWidget)tlw;
412}
413
414WXWidget wxCreateTopLevelRealizedWidget( WXDisplay* WXUNUSED(display) )
415{
416 Widget rTlw = XtVaCreateWidget( "dummy_widget", topLevelShellWidgetClass,
417 (Widget)wxTheApp->GetTopLevelWidget(),
418 NULL );
419 XtSetMappedWhenManaged( rTlw, False );
420 XtRealizeWidget( rTlw );
421
422 return (WXWidget)rTlw;
423}
424
425WXWidget wxApp::GetTopLevelWidget()
426{
427 WXDisplay* display = wxGetDisplay();
428 wxPerDisplayData& data = GetOrCreatePerDisplayData( *m_perDisplayData,
429 display );
430 if( data.m_topLevelWidget )
431 return (WXWidget)data.m_topLevelWidget;
432
433 WXWidget tlw = wxCreateTopLevelWidget( display );
434 SetTopLevelWidget( display, tlw );
435
436 return tlw;
437}
438
439WXWidget wxApp::GetTopLevelRealizedWidget()
440{
441 WXDisplay* display = wxGetDisplay();
442 wxPerDisplayDataMap::iterator it = m_perDisplayData->find( display );
443
444 if( it != m_perDisplayData->end() && it->second->m_topLevelRealizedWidget )
445 return (WXWidget)it->second->m_topLevelRealizedWidget;
446
447 WXWidget rTlw = wxCreateTopLevelRealizedWidget( display );
448 SetTopLevelRealizedWidget( display, rTlw );
449
450 return rTlw;
451}
452
453void wxApp::SetTopLevelWidget(WXDisplay* display, WXWidget widget)
454{
455 GetOrCreatePerDisplayData( *m_perDisplayData, display )
456 .m_topLevelWidget = (Widget)widget;
457}
458
459void wxApp::SetTopLevelRealizedWidget(WXDisplay* display, WXWidget widget)
460{
461 GetOrCreatePerDisplayData( *m_perDisplayData, display )
462 .m_topLevelRealizedWidget = (Widget)widget;
463}
464
465
466// ----------------------------------------------------------------------------
467// accessors for C modules
468// ----------------------------------------------------------------------------
469
470extern "C" XtAppContext wxGetAppContext()
471{
472 return (XtAppContext)wxTheApp->GetAppContext();
473}