]> git.saurik.com Git - wxWidgets.git/blame - src/motif/app.cpp
Fix horizontal mouse wheel scrolling in wxGTK.
[wxWidgets.git] / src / motif / app.cpp
CommitLineData
4bb6408c 1/////////////////////////////////////////////////////////////////////////////
55034339 2// Name: src/motif/app.cpp
4bb6408c
JS
3// Purpose: wxApp
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
4bb6408c 7// Copyright: (c) Julian Smart
65571936 8// Licence: wxWindows licence
4bb6408c
JS
9/////////////////////////////////////////////////////////////////////////////
10
1248b41f
MB
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
88a7a4e1
WS
14#include "wx/app.h"
15
32d4c30a
WS
16#ifndef WX_PRECOMP
17 #include "wx/hash.h"
88a7a4e1 18 #include "wx/intl.h"
e4db172a 19 #include "wx/log.h"
de6185e2 20 #include "wx/utils.h"
5b56bffb 21 #include "wx/memory.h"
73216ce6 22 #include "wx/font.h"
32d4c30a
WS
23#endif
24
7e1bcfa8 25#include "wx/evtloop.h"
b412f9be 26
7bcb11d3 27#if wxUSE_THREADS
dfe1eee3 28 #include "wx/thread.h"
7bcb11d3 29#endif
4bb6408c 30
338dd992 31#ifdef __VMS__
02761f6c 32 #pragma message disable nosimpint
338dd992 33#endif
4bb6408c
JS
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>
338dd992 39#ifdef __VMS__
02761f6c 40 #pragma message enable nosimpint
338dd992 41#endif
4bb6408c
JS
42
43#include "wx/motif/private.h"
44
45#include <string.h>
46
eb6fa4b4
MB
47struct wxPerDisplayData
48{
49 wxPerDisplayData()
5a2e3d8c
MB
50 {
51 m_visualInfo = NULL;
52 m_topLevelWidget = NULL;
53 m_topLevelRealizedWidget = NULL;
54 }
eb6fa4b4
MB
55
56 wxXVisualInfo* m_visualInfo;
5a2e3d8c 57 Widget m_topLevelWidget, m_topLevelRealizedWidget;
eb6fa4b4
MB
58};
59
eb6fa4b4
MB
60static void wxTLWidgetDestroyCallback(Widget w, XtPointer clientData,
61 XtPointer ptr);
62static WXWidget wxCreateTopLevelWidget( WXDisplay* display );
9ce8d6a2 63
7e1bcfa8 64extern bool wxAddIdleCallback();
7491d644 65
4bb6408c
JS
66wxHashTable *wxWidgetHashTable = NULL;
67
4bb6408c 68IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
9c6e1335 69
86ac4a22
VZ
70extern "C"
71{
e838cc14 72 typedef int (*XErrorHandlerFunc)(Display *, XErrorEvent *);
86ac4a22 73}
e838cc14 74
86ac4a22 75XErrorHandlerFunc gs_pfnXErrorHandler = 0;
e838cc14 76
86ac4a22
VZ
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}
e838cc14 87
8ecf7346 88bool wxApp::Initialize(int& argc_, wxChar **argv_)
4bb6408c 89{
105fbe1f
MB
90#if wxUSE_INTL
91 wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
92#endif
93
8ecf7346 94 if ( !wxAppBase::Initialize(argc_, argv_) )
94826170 95 return false;
afb74891 96
4bb6408c 97 wxWidgetHashTable = new wxHashTable(wxKEY_INTEGER);
afb74891 98
0fad0dfd
VZ
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
9a83f860 126 wxLogDebug(wxT("HP-UX fontset hack: forcing locale to en_US.iso88591"));
0fad0dfd
VZ
127 putenv(fixAll ? "LC_ALL=en_US.iso88591" : "LC_CTYPE=en_US.iso88591");
128 }
129#endif // __HPUX__
130
9d02485e 131 XtSetLanguageProc(NULL, NULL, NULL);
4bb6408c 132 XtToolkitInitialize() ;
edc1cd8b 133 wxTheApp->m_appContext = (WXAppContext) XtCreateApplicationContext();
8ecf7346
VZ
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 };
edc1cd8b
JS
158 XtAppSetFallbackResources((XtAppContext) wxTheApp->m_appContext, fallbackResources);
159
0b6d76bf
VZ
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() )
9a83f860 164 appname = wxT("wxapp");
0b6d76bf
VZ
165 wxString clsname = wxTheApp->GetClassName();
166 if ( clsname.empty() )
9a83f860 167 clsname = wxT("wx");
0b6d76bf 168
6991087b
VS
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 {
8ecf7346 179 argvX11[i] = strdup(wxConvLibc.cWX2MB(argv_[i]));
6991087b
VS
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 {
8ecf7346 203 while ( strcmp(wxConvLibc.cWX2MB(argv_[i]), argvX11[i]) != 0 )
6991087b 204 {
8ecf7346 205 memmove(argv_ + i, argv_ + i + 1, (argc - i)*sizeof(*argv_));
6991087b
VS
206 }
207 }
208
209 argc = argcX11;
8ecf7346
VZ
210
211 // update internal arg[cv] as X11 may have removed processed options:
212 argc = argc_;
213 argv = argv_;
6991087b
VS
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
0b6d76bf
VZ
227 Display *dpy = XtOpenDisplay((XtAppContext) wxTheApp->m_appContext,
228 (String)NULL,
229 appname.c_str(),
230 clsname.c_str(),
231 NULL, 0, // no options
4bb6408c 232# if XtSpecificationRelease < 5
9c6e1335 233 (Cardinal*) &argc,
4bb6408c 234# else
9c6e1335 235 &argc,
4bb6408c 236# endif
9c6e1335
VZ
237 argv);
238
6991087b
VS
239#endif // Unicode/ANSI
240
4bb6408c 241 if (!dpy) {
c88b736c
MB
242 // if you don't log to stderr, nothing will be shown...
243 delete wxLog::SetActiveTarget(new wxLogStderr);
7bcb11d3 244 wxString className(wxTheApp->GetClassName());
77ffb593 245 wxLogError(_("wxWidgets could not open display for '%s': exiting."),
d3a80c92 246 className.c_str());
2d120f83 247 exit(-1);
4bb6408c 248 }
47bc1060 249 m_initialDisplay = (WXDisplay*) dpy;
afb74891 250
e838cc14
VZ
251 // install the X error handler
252 gs_pfnXErrorHandler = XSetErrorHandler(wxXErrorHandler);
e838cc14 253
4bb6408c
JS
254 // Add general resize proc
255 XtActionsRec rec;
f1db433a 256 rec.string = wxMOTIF_STR("resize");
4bb6408c
JS
257 rec.proc = (XtActionProc)wxWidgetResizeProc;
258 XtAppAddActions((XtAppContext) wxTheApp->m_appContext, &rec, 1);
afb74891 259
4bb6408c 260 GetMainColormap(dpy);
afb74891 261
7e1bcfa8
MB
262 wxAddIdleCallback();
263
96be256b 264 return true;
4bb6408c
JS
265}
266
8ecf7346
VZ
267void wxApp::CleanUp()
268{
269 wxAppBase::CleanUp();
270
5276b0a5 271 wxDELETE(wxWidgetHashTable);
8ecf7346
VZ
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
4bb6408c
JS
340WXColormap wxApp::GetMainColormap(WXDisplay* display)
341{
342 if (!display) /* Must be called first with non-NULL display */
2d120f83 343 return m_mainColormap;
a91b47e8
JS
344
345 int defaultScreen = DefaultScreen((Display*) display);
346 Screen* screen = XScreenOfDisplay((Display*) display, defaultScreen);
afb74891 347
a91b47e8 348 Colormap c = DefaultColormapOfScreen(screen);
afb74891 349
4bb6408c 350 if (!m_mainColormap)
2d120f83 351 m_mainColormap = (WXColormap) c;
afb74891 352
4bb6408c
JS
353 return (WXColormap) c;
354}
355
bdcade0a
MB
356static inline wxPerDisplayData& GetOrCreatePerDisplayData
357 ( wxPerDisplayDataMap& m, WXDisplay* display )
9ce8d6a2 358{
bdcade0a
MB
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}
9ce8d6a2 368
bdcade0a
MB
369wxXVisualInfo* wxApp::GetVisualInfo( WXDisplay* display )
370{
371 wxPerDisplayData& data = GetOrCreatePerDisplayData( *m_perDisplayData,
372 display );
373 if( data.m_visualInfo )
374 return data.m_visualInfo;
9ce8d6a2
MB
375
376 wxXVisualInfo* vi = new wxXVisualInfo;
377 wxFillXVisualInfo( vi, (Display*)display );
378
bdcade0a 379 data.m_visualInfo = vi;
9ce8d6a2
MB
380
381 return vi;
382}
383
55034339
WS
384static void wxTLWidgetDestroyCallback(Widget w, XtPointer WXUNUSED(clientData),
385 XtPointer WXUNUSED(ptr))
eb6fa4b4
MB
386{
387 if( wxTheApp )
5a2e3d8c 388 {
eb6fa4b4
MB
389 wxTheApp->SetTopLevelWidget( (WXDisplay*)XtDisplay(w),
390 (WXWidget)NULL );
5a2e3d8c
MB
391 wxTheApp->SetTopLevelRealizedWidget( (WXDisplay*)XtDisplay(w),
392 (WXWidget)NULL );
393 }
eb6fa4b4
MB
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 );
5a2e3d8c
MB
403 XtVaSetValues( tlw,
404 XmNoverrideRedirect, True,
405 NULL );
eb6fa4b4
MB
406
407 XtAddCallback( tlw, XmNdestroyCallback,
408 (XtCallbackProc)wxTLWidgetDestroyCallback,
409 (XtPointer)NULL );
410
411 return (WXWidget)tlw;
412}
413
55034339 414WXWidget wxCreateTopLevelRealizedWidget( WXDisplay* WXUNUSED(display) )
5a2e3d8c 415{
cb81f1a6 416 Widget rTlw = XtVaCreateWidget( "dummy_widget", topLevelShellWidgetClass,
5a2e3d8c 417 (Widget)wxTheApp->GetTopLevelWidget(),
b09a59f5 418 NULL );
5a2e3d8c
MB
419 XtSetMappedWhenManaged( rTlw, False );
420 XtRealizeWidget( rTlw );
421
422 return (WXWidget)rTlw;
423}
424
eb6fa4b4
MB
425WXWidget wxApp::GetTopLevelWidget()
426{
427 WXDisplay* display = wxGetDisplay();
bdcade0a
MB
428 wxPerDisplayData& data = GetOrCreatePerDisplayData( *m_perDisplayData,
429 display );
430 if( data.m_topLevelWidget )
431 return (WXWidget)data.m_topLevelWidget;
eb6fa4b4
MB
432
433 WXWidget tlw = wxCreateTopLevelWidget( display );
434 SetTopLevelWidget( display, tlw );
435
436 return tlw;
437}
438
5a2e3d8c
MB
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
eb6fa4b4
MB
453void wxApp::SetTopLevelWidget(WXDisplay* display, WXWidget widget)
454{
5a2e3d8c
MB
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;
eb6fa4b4
MB
463}
464
4bb6408c 465
d391a345
VZ
466// ----------------------------------------------------------------------------
467// accessors for C modules
468// ----------------------------------------------------------------------------
469
470extern "C" XtAppContext wxGetAppContext()
471{
472 return (XtAppContext)wxTheApp->GetAppContext();
473}