]> git.saurik.com Git - wxWidgets.git/blame - src/x11/app.cpp
show the standard wxWin fonts (modified patch 530698)
[wxWidgets.git] / src / x11 / app.cpp
CommitLineData
83df96d6
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: app.cpp
3// Purpose: wxApp
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13 #pragma implementation "app.h"
14#endif
15
83df96d6
JS
16#include "wx/frame.h"
17#include "wx/app.h"
18#include "wx/utils.h"
19#include "wx/gdicmn.h"
83df96d6 20#include "wx/icon.h"
83df96d6 21#include "wx/dialog.h"
83df96d6
JS
22#include "wx/log.h"
23#include "wx/module.h"
24#include "wx/memory.h"
25#include "wx/log.h"
26#include "wx/intl.h"
1b0fb34b 27#include "wx/evtloop.h"
83df96d6 28
ef8c973b
VS
29#include "wx/univ/theme.h"
30#include "wx/univ/renderer.h"
31
83df96d6
JS
32#if wxUSE_THREADS
33 #include "wx/thread.h"
34#endif
35
36#if wxUSE_WX_RESOURCES
37 #include "wx/resource.h"
38#endif
39
7eaac9f5 40#include "wx/x11/private.h"
83df96d6
JS
41
42#include <string.h>
43
9d2cef1c
RR
44//------------------------------------------------------------------------
45// global data
46//------------------------------------------------------------------------
47
83df96d6
JS
48extern wxList wxPendingDelete;
49
9d2cef1c
RR
50wxHashTable *wxWidgetHashTable = NULL;
51
83df96d6
JS
52wxApp *wxTheApp = NULL;
53
9d2cef1c
RR
54// This is set within wxEntryStart -- too early on
55// to put these in wxTheApp
56static int g_newArgc = 0;
57static wxChar** g_newArgv = NULL;
58static bool g_showIconic = FALSE;
59static wxSize g_initialSize = wxDefaultSize;
83df96d6 60
9d2cef1c
RR
61// This is required for wxFocusEvent::SetWindow(). It will only
62// work for focus events which we provoke ourselves (by calling
63// SetFocus()). It will not work for those events, which X11
64// generates itself.
65static wxWindow *g_nextFocus = NULL;
66static wxWindow *g_prevFocus = NULL;
83df96d6 67
9d2cef1c
RR
68//------------------------------------------------------------------------
69// X11 error handling
70//------------------------------------------------------------------------
83df96d6
JS
71
72#ifdef __WXDEBUG__
1b0fb34b 73typedef int (*XErrorHandlerFunc)(Display *, XErrorEvent *);
83df96d6 74
1b0fb34b 75XErrorHandlerFunc gs_pfnXErrorHandler = 0;
83df96d6 76
1b0fb34b
JS
77static int wxXErrorHandler(Display *dpy, XErrorEvent *xevent)
78{
79 // just forward to the default handler for now
c79a329d
JS
80 if (gs_pfnXErrorHandler)
81 return gs_pfnXErrorHandler(dpy, xevent);
82 else
83 return 0;
1b0fb34b 84}
83df96d6
JS
85#endif // __WXDEBUG__
86
9d2cef1c
RR
87//------------------------------------------------------------------------
88// wxApp
89//------------------------------------------------------------------------
90
83df96d6 91long wxApp::sm_lastMessageTime = 0;
a11672a4 92WXDisplay *wxApp::ms_display = NULL;
83df96d6 93
9d2cef1c
RR
94IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
95
96BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
97 EVT_IDLE(wxApp::OnIdle)
98END_EVENT_TABLE()
256d631a 99
83df96d6
JS
100bool wxApp::Initialize()
101{
83df96d6
JS
102 wxClassInfo::InitializeClasses();
103
104 // GL: I'm annoyed ... I don't know where to put this and I don't want to
105 // create a module for that as it's part of the core.
106#if wxUSE_THREADS
107 wxPendingEventsLocker = new wxCriticalSection();
108#endif
109
110 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
111 wxTheColourDatabase->Initialize();
112
113 wxInitializeStockLists();
114 wxInitializeStockObjects();
115
116#if wxUSE_WX_RESOURCES
117 wxInitializeResourceSystem();
118#endif
119
83df96d6
JS
120 wxWidgetHashTable = new wxHashTable(wxKEY_INTEGER);
121
122 wxModule::RegisterModules();
123 if (!wxModule::InitializeModules()) return FALSE;
124
125 return TRUE;
126}
127
128void wxApp::CleanUp()
129{
256d631a
JS
130 if (g_newArgv)
131 delete[] g_newArgv;
132 g_newArgv = NULL;
133
83df96d6
JS
134 delete wxWidgetHashTable;
135 wxWidgetHashTable = NULL;
136
137 wxModule::CleanUpModules();
138
139#if wxUSE_WX_RESOURCES
140 wxCleanUpResourceSystem();
141#endif
142
83df96d6
JS
143 delete wxTheColourDatabase;
144 wxTheColourDatabase = NULL;
145
a11672a4
RR
146 wxDeleteStockObjects();
147
148 wxDeleteStockLists();
149
150 delete wxTheApp;
151 wxTheApp = NULL;
83df96d6 152
83df96d6
JS
153 wxClassInfo::CleanUpClasses();
154
83df96d6
JS
155#if wxUSE_THREADS
156 delete wxPendingEvents;
157 delete wxPendingEventsLocker;
158#endif
159
160#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
161 // At this point we want to check if there are any memory
162 // blocks that aren't part of the wxDebugContext itself,
163 // as a special case. Then when dumping we need to ignore
164 // wxDebugContext, too.
165 if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
166 {
ba696cfa 167 wxLogDebug("There were memory leaks.");
83df96d6
JS
168 wxDebugContext::Dump();
169 wxDebugContext::PrintStatistics();
170 }
171#endif
172
173 // do it as the very last thing because everything else can log messages
174 wxLog::DontCreateOnDemand();
175 // do it as the very last thing because everything else can log messages
176 delete wxLog::SetActiveTarget(NULL);
177}
178
a11672a4
RR
179// NB: argc and argv may be changed here, pass by reference!
180int wxEntryStart( int& argc, char *argv[] )
181{
182#ifdef __WXDEBUG__
ff6b424a 183#if !wxUSE_NANOX
a11672a4
RR
184 // install the X error handler
185 gs_pfnXErrorHandler = XSetErrorHandler( wxXErrorHandler );
ff6b424a 186#endif
a11672a4
RR
187#endif // __WXDEBUG__
188
256d631a
JS
189 wxString displayName;
190 bool syncDisplay = FALSE;
191
3a0b23eb 192 // Parse the arguments.
256d631a
JS
193 // We can't use wxCmdLineParser or OnInitCmdLine and friends because
194 // we have to create the Display earlier. If we can find a way to
195 // use the wxAppBase API then I'll be quite happy to change it.
196 g_newArgv = new wxChar*[argc];
197 g_newArgc = 0;
198 int i;
199 for (i = 0; i < argc; i++)
200 {
201 wxString arg(argv[i]);
202 if (arg == wxT("-display"))
203 {
204 if (i < (argc - 1))
205 {
206 i ++;
207 displayName = argv[i];
208 continue;
209 }
210 }
211 else if (arg == wxT("-geometry"))
212 {
213 if (i < (argc - 1))
214 {
215 i ++;
eb90fb3e 216 wxString windowGeometry = argv[i];
256d631a
JS
217 int w, h;
218 if (wxSscanf(windowGeometry.c_str(), _T("%dx%d"), &w, &h) != 2)
219 {
eb90fb3e 220 wxLogError(_("Invalid geometry specification '%s'"), windowGeometry.c_str());
256d631a
JS
221 }
222 else
223 {
224 g_initialSize = wxSize(w, h);
225 }
226 continue;
227 }
228 }
229 else if (arg == wxT("-sync"))
230 {
231 syncDisplay = TRUE;
232 continue;
233 }
234 else if (arg == wxT("-iconic"))
235 {
236 g_showIconic = TRUE;
45ff6421 237
256d631a
JS
238 continue;
239 }
240
241 // Not eaten by wxWindows, so pass through
242 g_newArgv[g_newArgc] = argv[i];
243 g_newArgc ++;
244 }
245
c79a329d 246 Display* xdisplay = NULL;
256d631a
JS
247 if (displayName.IsEmpty())
248 xdisplay = XOpenDisplay(NULL);
249 else
461e93f9 250 xdisplay = XOpenDisplay((char*) displayName.c_str());
a11672a4
RR
251
252 if (!xdisplay)
253 {
254 wxLogError( _("wxWindows could not open display. Exiting.") );
255 return -1;
256 }
256d631a
JS
257
258 if (syncDisplay)
259 {
260 XSynchronize(xdisplay, True);
261 }
a11672a4
RR
262
263 wxApp::ms_display = (WXDisplay*) xdisplay;
264
265 XSelectInput( xdisplay, XDefaultRootWindow(xdisplay), PropertyChangeMask);
266
7e4501ee 267 wxSetDetectableAutoRepeat( TRUE );
a11672a4
RR
268
269 if (!wxApp::Initialize())
270 return -1;
271
272 return 0;
273}
274
a11672a4
RR
275int wxEntryInitGui()
276{
277 int retValue = 0;
278
279 if ( !wxTheApp->OnInitGui() )
280 retValue = -1;
281
282 return retValue;
283}
284
285
83df96d6
JS
286int wxEntry( int argc, char *argv[] )
287{
288#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
289 // This seems to be necessary since there are 'rogue'
290 // objects present at this point (perhaps global objects?)
291 // Setting a checkpoint will ignore them as far as the
292 // memory checking facility is concerned.
293 // Of course you may argue that memory allocated in globals should be
294 // checked, but this is a reasonable compromise.
295 wxDebugContext::SetCheckpoint();
296#endif
a11672a4
RR
297 int err = wxEntryStart(argc, argv);
298 if (err)
299 return err;
83df96d6
JS
300
301 if (!wxTheApp)
302 {
303 if (!wxApp::GetInitializerFunction())
304 {
305 printf( "wxWindows error: No initializer - use IMPLEMENT_APP macro.\n" );
306 return 0;
307 };
308
309 wxTheApp = (wxApp*) (* wxApp::GetInitializerFunction()) ();
310 };
311
312 if (!wxTheApp)
313 {
314 printf( "wxWindows error: wxTheApp == NULL\n" );
315 return 0;
316 };
317
318 wxTheApp->SetClassName(wxFileNameFromPath(argv[0]));
319 wxTheApp->SetAppName(wxFileNameFromPath(argv[0]));
320
45ff6421
JS
321 // The command line may have been changed
322 // by stripping out -display etc.
323 if (g_newArgc > 0)
324 {
325 wxTheApp->argc = g_newArgc;
326 wxTheApp->argv = g_newArgv;
327 }
328 else
329 {
330 wxTheApp->argc = argc;
331 wxTheApp->argv = argv;
332 }
256d631a
JS
333 wxTheApp->m_showIconic = g_showIconic;
334 wxTheApp->m_initialSize = g_initialSize;
83df96d6 335
a11672a4
RR
336 int retValue;
337 retValue = wxEntryInitGui();
83df96d6
JS
338
339 // Here frames insert themselves automatically into wxTopLevelWindows by
340 // getting created in OnInit().
a11672a4
RR
341 if ( retValue == 0 )
342 {
343 if ( !wxTheApp->OnInit() )
344 retValue = -1;
345 }
83df96d6 346
a11672a4 347 if ( retValue == 0 )
83df96d6
JS
348 {
349 if (wxTheApp->Initialized()) retValue = wxTheApp->OnRun();
350 }
351
352 // flush the logged messages if any
353 wxLog *pLog = wxLog::GetActiveTarget();
354 if ( pLog != NULL && pLog->HasPendingMessages() )
355 pLog->Flush();
356
357 delete wxLog::SetActiveTarget(new wxLogStderr); // So dialog boxes aren't used
358 // for further messages
359
360 if (wxTheApp->GetTopWindow())
361 {
362 delete wxTheApp->GetTopWindow();
363 wxTheApp->SetTopWindow(NULL);
364 }
365
366 wxTheApp->DeletePendingObjects();
367
368 wxTheApp->OnExit();
369
370 wxApp::CleanUp();
371
372 return retValue;
373};
374
375// Static member initialization
376wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
377
378wxApp::wxApp()
379{
380 m_topWindow = NULL;
381 wxTheApp = this;
382 m_className = "";
383 m_wantDebugOutput = TRUE ;
384 m_appName = "";
385 argc = 0;
386 argv = NULL;
387 m_exitOnFrameDelete = TRUE;
83df96d6 388 m_mainColormap = (WXColormap) NULL;
7eaac9f5 389 m_topLevelWidget = (WXWindow) NULL;
83df96d6 390 m_maxRequestSize = 0;
1b0fb34b 391 m_mainLoop = NULL;
256d631a
JS
392 m_showIconic = FALSE;
393 m_initialSize = wxDefaultSize;
83df96d6
JS
394}
395
396bool wxApp::Initialized()
397{
398 if (GetTopWindow())
399 return TRUE;
400 else
401 return FALSE;
402}
403
404int wxApp::MainLoop()
405{
c978d361 406 int rt;
1b0fb34b 407 m_mainLoop = new wxEventLoop;
83df96d6 408
1b0fb34b 409 rt = m_mainLoop->Run();
83df96d6 410
1b0fb34b
JS
411 delete m_mainLoop;
412 m_mainLoop = NULL;
413 return rt;
414}
83df96d6 415
70b8ab77 416#if !wxUSE_NANOX
f809133f
RR
417//-----------------------------------------------------------------------
418// X11 predicate function for exposure compression
419//-----------------------------------------------------------------------
420
421struct wxExposeInfo
422{
423 Window window;
424 Bool found_non_matching;
425};
426
427static Bool expose_predicate (Display *display, XEvent *xevent, XPointer arg)
428{
429 wxExposeInfo *info = (wxExposeInfo*) arg;
430
431 if (info->found_non_matching)
432 return FALSE;
433
434 if (xevent->xany.type != Expose)
435 {
436 info->found_non_matching = TRUE;
437 return FALSE;
438 }
439
440 if (xevent->xexpose.window != info->window)
441 {
442 info->found_non_matching = TRUE;
443 return FALSE;
444 }
445
446 return TRUE;
447}
70b8ab77
JS
448#endif
449 // wxUSE_NANOX
f809133f
RR
450
451//-----------------------------------------------------------------------
086fd560 452// Processes an X event, returning TRUE if the event was processed.
f809133f
RR
453//-----------------------------------------------------------------------
454
086fd560 455bool wxApp::ProcessXEvent(WXEvent* _event)
1b0fb34b
JS
456{
457 XEvent* event = (XEvent*) _event;
83df96d6 458
1b0fb34b 459 wxWindow* win = NULL;
c79a329d 460 Window window = XEventGetWindow(event);
1b0fb34b 461 Window actualWindow = window;
0b5c0e1a 462
1b0fb34b 463 // Find the first wxWindow that corresponds to this event window
774b90fb
JS
464 // Because we're receiving events after a window
465 // has been destroyed, assume a 1:1 match between
466 // Window and wxWindow, so if it's not in the table,
467 // it must have been destroyed.
468
469 win = wxGetWindowFromTable(window);
470 if (!win)
ee351013 471 return FALSE;
83df96d6 472
0b5c0e1a
JS
473#ifdef __WXDEBUG__
474 wxString windowClass = win->GetClassInfo()->GetClassName();
475#endif
476
1b0fb34b
JS
477 switch (event->type)
478 {
2f12683e
RR
479 case Expose:
480 {
481 //wxLogDebug("Expose: %s", windowClass.c_str());
482 win->GetUpdateRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event),
483 XExposeEventGetWidth(event), XExposeEventGetHeight(event));
484
485 win->GetClearRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event),
486 XExposeEventGetWidth(event), XExposeEventGetHeight(event));
487
488#if !wxUSE_NANOX
489 XEvent tmp_event;
490 wxExposeInfo info;
491 info.window = event->xexpose.window;
492 info.found_non_matching = FALSE;
493 while (XCheckIfEvent( wxGlobalDisplay(), &tmp_event, expose_predicate, (XPointer) &info ))
494 {
495 win->GetUpdateRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y,
496 tmp_event.xexpose.width, tmp_event.xexpose.height );
497
498 win->GetClearRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y,
499 tmp_event.xexpose.width, tmp_event.xexpose.height );
500 }
501#endif
502
503 // Only erase background, paint in idle time.
504 win->SendEraseEvents();
505
506 return TRUE;
507 }
508
509#if !wxUSE_NANOX
510 case GraphicsExpose:
511 {
512 // wxLogDebug( "GraphicsExpose from %s", win->GetName().c_str(),
513 // event->xgraphicsexpose.x, event->xgraphicsexpose.y,
514 // event->xgraphicsexpose.width, event->xgraphicsexpose.height);
515
516 win->GetUpdateRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y,
517 event->xgraphicsexpose.width, event->xgraphicsexpose.height);
518
519 win->GetClearRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y,
520 event->xgraphicsexpose.width, event->xgraphicsexpose.height);
521
522 if (event->xgraphicsexpose.count == 0)
523 {
524 // Only erase background, paint in idle time.
525 win->SendEraseEvents();
526 //win->Update();
527 }
528
529 return TRUE;
530 }
531#endif
532
1b0fb34b 533 case KeyPress:
83df96d6 534 {
9d2cef1c 535 if (!win->IsEnabled())
086fd560 536 return FALSE;
b513212d 537
9d2cef1c
RR
538 wxKeyEvent keyEvent(wxEVT_KEY_DOWN);
539 wxTranslateKeyEvent(keyEvent, win, window, event);
ba696cfa 540
9d2cef1c 541 // wxLogDebug( "OnKey from %s", win->GetName().c_str() );
1b0fb34b 542
120b822d
RR
543 // We didn't process wxEVT_KEY_DOWN, so send wxEVT_CHAR
544 if (win->GetEventHandler()->ProcessEvent( keyEvent ))
545 return TRUE;
546
547 keyEvent.SetEventType(wxEVT_CHAR);
548 if (win->GetEventHandler()->ProcessEvent( keyEvent ))
549 return TRUE;
550
551 if ( (keyEvent.m_keyCode == WXK_TAB) &&
552 win->GetParent() && (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
9d2cef1c 553 {
120b822d
RR
554 wxNavigationKeyEvent new_event;
555 new_event.SetEventObject( win->GetParent() );
556 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
557 new_event.SetDirection( (keyEvent.m_keyCode == WXK_TAB) );
558 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
559 new_event.SetWindowChange( keyEvent.ControlDown() );
560 new_event.SetCurrentFocus( win );
561 return win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
1b0fb34b 562 }
120b822d
RR
563
564 return FALSE;
83df96d6 565 }
1b0fb34b 566 case KeyRelease:
7eaac9f5 567 {
9d2cef1c 568 if (!win->IsEnabled())
086fd560 569 return FALSE;
b513212d 570
9d2cef1c
RR
571 wxKeyEvent keyEvent(wxEVT_KEY_UP);
572 wxTranslateKeyEvent(keyEvent, win, window, event);
1b0fb34b 573
086fd560 574 return win->GetEventHandler()->ProcessEvent( keyEvent );
7eaac9f5 575 }
256d631a
JS
576 case ConfigureNotify:
577 {
c79a329d 578#if wxUSE_NANOX
9d2cef1c 579 if (event->update.utype == GR_UPDATE_SIZE)
c79a329d 580#endif
256d631a 581 {
0b5c0e1a 582 //wxLogDebug("ConfigureNotify: %s", windowClass.c_str());
2f12683e 583 if (win->IsTopLevel() && win->IsShown())
77df2fbc
RR
584 {
585 wxTopLevelWindowX11 *tlw = (wxTopLevelWindowX11 *) win;
586 tlw->SetNeedResizeInIdle();
587 }
588 else
589 {
590 wxSizeEvent sizeEvent( wxSize(XConfigureEventGetWidth(event), XConfigureEventGetHeight(event)), win->GetId() );
591 sizeEvent.SetEventObject( win );
256d631a 592
77df2fbc
RR
593 return win->GetEventHandler()->ProcessEvent( sizeEvent );
594 }
256d631a 595 }
086fd560 596 return FALSE;
c2ff68d3 597 break;
256d631a
JS
598 }
599#if !wxUSE_NANOX
1b0fb34b 600 case PropertyNotify:
7eaac9f5 601 {
0b5c0e1a 602 //wxLogDebug("PropertyNotify: %s", windowClass.c_str());
086fd560 603 return HandlePropertyChange(_event);
7eaac9f5 604 }
b513212d 605 case ClientMessage:
3a0b23eb 606 {
9d2cef1c 607 if (!win->IsEnabled())
086fd560 608 return FALSE;
3a0b23eb 609
7e4501ee
RR
610 Atom wm_delete_window = XInternAtom(wxGlobalDisplay(), "WM_DELETE_WINDOW", True);
611 Atom wm_protocols = XInternAtom(wxGlobalDisplay(), "WM_PROTOCOLS", True);
b513212d
JS
612
613 if (event->xclient.message_type == wm_protocols)
614 {
6a44bffd 615 if ((Atom) (event->xclient.data.l[0]) == wm_delete_window)
b513212d 616 {
9d2cef1c 617 win->Close(FALSE);
086fd560 618 return TRUE;
b513212d
JS
619 }
620 }
086fd560 621 return FALSE;
b513212d 622 }
2f12683e
RR
623#if 0
624 case DestroyNotify:
625 {
626 printf( "destroy from %s\n", win->GetName().c_str() );
627 break;
628 }
629 case CreateNotify:
630 {
631 printf( "create from %s\n", win->GetName().c_str() );
632 break;
633 }
634 case MapRequest:
635 {
636 printf( "map request from %s\n", win->GetName().c_str() );
637 break;
638 }
1b0fb34b 639 case ResizeRequest:
7eaac9f5 640 {
2f12683e
RR
641 printf( "resize request from %s\n", win->GetName().c_str() );
642
7266b672 643 Display *disp = (Display*) wxGetDisplay();
1b0fb34b
JS
644 XEvent report;
645
646 // to avoid flicker
647 report = * event;
648 while( XCheckTypedWindowEvent (disp, actualWindow, ResizeRequest, &report));
649
b1633d20
RR
650 wxSize sz = win->GetSize();
651 wxSizeEvent sizeEvent(sz, win->GetId());
652 sizeEvent.SetEventObject(win);
1b0fb34b 653
b1633d20 654 return win->GetEventHandler()->ProcessEvent( sizeEvent );
7eaac9f5 655 }
256d631a 656#endif
b1633d20 657#endif
256d631a
JS
658#if wxUSE_NANOX
659 case GR_EVENT_TYPE_CLOSE_REQ:
660 {
661 if (win)
662 {
663 win->Close(FALSE);
086fd560 664 return TRUE;
256d631a 665 }
086fd560 666 return FALSE;
256d631a
JS
667 break;
668 }
c79a329d 669#endif
1b0fb34b
JS
670 case EnterNotify:
671 case LeaveNotify:
672 case ButtonPress:
673 case ButtonRelease:
674 case MotionNotify:
7eaac9f5 675 {
7e4501ee 676 if (!win->IsEnabled())
086fd560 677 return FALSE;
9691c806
RR
678
679 // Here we check if the top level window is
680 // disabled, which is one aspect of modality.
681 wxWindow *tlw = win;
682 while (tlw && !tlw->IsTopLevel())
683 tlw = tlw->GetParent();
684 if (tlw && !tlw->IsEnabled())
086fd560 685 return FALSE;
ea1ad04b 686
7e4501ee 687 if (event->type == ButtonPress)
1b0fb34b 688 {
7e4501ee 689 if ((win != wxWindow::FindFocus()) && win->AcceptsFocus())
9d2cef1c
RR
690 {
691 // This might actually be done in wxWindow::SetFocus()
ea1ad04b 692 // and not here. TODO.
9d2cef1c
RR
693 g_prevFocus = wxWindow::FindFocus();
694 g_nextFocus = win;
695
696 win->SetFocus();
697 }
1b0fb34b 698 }
ea1ad04b
RR
699
700#if !wxUSE_NANOX
701 if (event->type == LeaveNotify || event->type == EnterNotify)
702 {
703 // Throw out NotifyGrab and NotifyUngrab
704 if (event->xcrossing.mode != NotifyNormal)
086fd560 705 return FALSE;
ea1ad04b
RR
706 }
707#endif
7e4501ee
RR
708 wxMouseEvent wxevent;
709 wxTranslateMouseEvent(wxevent, win, window, event);
086fd560 710 return win->GetEventHandler()->ProcessEvent( wxevent );
7eaac9f5 711 }
1b0fb34b
JS
712 case FocusIn:
713 {
256d631a 714#if !wxUSE_NANOX
9d2cef1c
RR
715 if ((event->xfocus.detail != NotifyPointer) &&
716 (event->xfocus.mode == NotifyNormal))
256d631a 717#endif
1b0fb34b 718 {
9d2cef1c 719 // wxLogDebug( "FocusIn from %s of type %s", win->GetName().c_str(), win->GetClassInfo()->GetClassName() );
ba696cfa 720
1b0fb34b
JS
721 wxFocusEvent focusEvent(wxEVT_SET_FOCUS, win->GetId());
722 focusEvent.SetEventObject(win);
9d2cef1c
RR
723 focusEvent.SetWindow( g_prevFocus );
724 g_prevFocus = NULL;
f809133f 725
086fd560 726 return win->GetEventHandler()->ProcessEvent(focusEvent);
1b0fb34b 727 }
086fd560 728 return FALSE;
1b0fb34b
JS
729 break;
730 }
731 case FocusOut:
732 {
256d631a 733#if !wxUSE_NANOX
9d2cef1c
RR
734 if ((event->xfocus.detail != NotifyPointer) &&
735 (event->xfocus.mode == NotifyNormal))
256d631a 736#endif
1b0fb34b 737 {
9d2cef1c 738 // wxLogDebug( "FocusOut from %s of type %s", win->GetName().c_str(), win->GetClassInfo()->GetClassName() );
ba696cfa 739
1b0fb34b
JS
740 wxFocusEvent focusEvent(wxEVT_KILL_FOCUS, win->GetId());
741 focusEvent.SetEventObject(win);
9d2cef1c
RR
742 focusEvent.SetWindow( g_nextFocus );
743 g_nextFocus = NULL;
086fd560 744 return win->GetEventHandler()->ProcessEvent(focusEvent);
1b0fb34b 745 }
086fd560 746 return FALSE;
1b0fb34b
JS
747 break;
748 }
749 default:
750 {
45ff6421
JS
751#ifdef __WXDEBUG__
752 //wxString eventName = wxGetXEventName(XEvent& event);
753 //wxLogDebug(wxT("Event %s not handled"), eventName.c_str());
754#endif
086fd560 755 return FALSE;
1b0fb34b
JS
756 break;
757 }
83df96d6 758 }
086fd560 759 return FALSE;
83df96d6
JS
760}
761
762// Returns TRUE if more time is needed.
1b0fb34b
JS
763// Note that this duplicates wxEventLoopImpl::SendIdleEvent
764// but ProcessIdle may be needed by apps, so is kept.
83df96d6
JS
765bool wxApp::ProcessIdle()
766{
767 wxIdleEvent event;
768 event.SetEventObject(this);
769 ProcessEvent(event);
770
771 return event.MoreRequested();
772}
773
774void wxApp::ExitMainLoop()
775{
1b0fb34b
JS
776 if (m_mainLoop)
777 m_mainLoop->Exit(0);
83df96d6
JS
778}
779
780// Is a message/event pending?
781bool wxApp::Pending()
782{
1b0fb34b 783 return wxEventLoop::GetActive()->Pending();
83df96d6
JS
784}
785
786// Dispatch a message.
787void wxApp::Dispatch()
788{
1b0fb34b 789 wxEventLoop::GetActive()->Dispatch();
83df96d6
JS
790}
791
792// This should be redefined in a derived class for
793// handling property change events for XAtom IPC.
086fd560 794bool wxApp::HandlePropertyChange(WXEvent *event)
83df96d6
JS
795{
796 // by default do nothing special
7eaac9f5 797 // TODO: what to do for X11
256d631a 798 // XtDispatchEvent((XEvent*) event);
086fd560 799 return FALSE;
83df96d6
JS
800}
801
802void wxApp::OnIdle(wxIdleEvent& event)
803{
0d1dff01 804 static bool s_inOnIdle = FALSE;
83df96d6
JS
805
806 // Avoid recursion (via ProcessEvent default case)
0d1dff01 807 if (s_inOnIdle)
83df96d6
JS
808 return;
809
0d1dff01 810 s_inOnIdle = TRUE;
83df96d6 811
0d1dff01
RR
812 // Resend in the main thread events which have been prepared in other
813 // threads
83df96d6
JS
814 ProcessPendingEvents();
815
0d1dff01 816 // 'Garbage' collection of windows deleted with Close()
83df96d6
JS
817 DeletePendingObjects();
818
83df96d6
JS
819 // Send OnIdle events to all windows
820 bool needMore = SendIdleEvents();
821
822 if (needMore)
823 event.RequestMore(TRUE);
824
0d1dff01 825 s_inOnIdle = FALSE;
83df96d6
JS
826}
827
828void wxWakeUpIdle()
829{
830 // **** please implement me! ****
831 // Wake up the idle handler processor, even if it is in another thread...
832}
833
834
835// Send idle event to all top-level windows
836bool wxApp::SendIdleEvents()
837{
838 bool needMore = FALSE;
839
840 wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
841 while (node)
842 {
843 wxWindow* win = node->GetData();
844 if (SendIdleEvents(win))
845 needMore = TRUE;
846 node = node->GetNext();
847 }
848
849 return needMore;
850}
851
852// Send idle event to window and all subwindows
853bool wxApp::SendIdleEvents(wxWindow* win)
854{
855 bool needMore = FALSE;
856
857 wxIdleEvent event;
858 event.SetEventObject(win);
0d1dff01
RR
859
860 win->GetEventHandler()->ProcessEvent(event);
861
862 win->OnInternalIdle();
83df96d6
JS
863
864 if (event.MoreRequested())
865 needMore = TRUE;
866
867 wxNode* node = win->GetChildren().First();
868 while (node)
869 {
870 wxWindow* win = (wxWindow*) node->Data();
871 if (SendIdleEvents(win))
872 needMore = TRUE;
873
874 node = node->Next();
875 }
0d1dff01
RR
876
877 return needMore;
83df96d6
JS
878}
879
880void wxApp::DeletePendingObjects()
881{
882 wxNode *node = wxPendingDelete.First();
883 while (node)
884 {
885 wxObject *obj = (wxObject *)node->Data();
886
887 delete obj;
888
889 if (wxPendingDelete.Member(obj))
890 delete node;
891
892 // Deleting one object may have deleted other pending
893 // objects, so start from beginning of list again.
894 node = wxPendingDelete.First();
895 }
896}
897
256d631a 898// Create display, and other initialization
83df96d6
JS
899bool wxApp::OnInitGui()
900{
ca7497c2
JS
901 // Eventually this line will be removed, but for
902 // now we don't want to try popping up a dialog
903 // for error messages.
904 delete wxLog::SetActiveTarget(new wxLogStderr);
a11672a4 905
ea596687 906 if (!wxAppBase::OnInitGui())
ee351013 907 return FALSE;
ea596687 908
a11672a4 909 GetMainColormap( wxApp::GetDisplay() );
256d631a 910
a11672a4 911 m_maxRequestSize = XMaxRequestSize( (Display*) wxApp::GetDisplay() );
83df96d6
JS
912
913 return TRUE;
914}
915
916WXColormap wxApp::GetMainColormap(WXDisplay* display)
917{
918 if (!display) /* Must be called first with non-NULL display */
919 return m_mainColormap;
920
921 int defaultScreen = DefaultScreen((Display*) display);
922 Screen* screen = XScreenOfDisplay((Display*) display, defaultScreen);
923
924 Colormap c = DefaultColormapOfScreen(screen);
925
926 if (!m_mainColormap)
927 m_mainColormap = (WXColormap) c;
928
929 return (WXColormap) c;
930}
931
8354aa92 932Window wxGetWindowParent(Window window)
7eaac9f5 933{
86fd8bda
RR
934 wxASSERT_MSG( window, "invalid window" );
935
936 return (Window) 0;
937
7eaac9f5 938 Window parent, root = 0;
c79a329d
JS
939#if wxUSE_NANOX
940 int noChildren = 0;
941#else
7eaac9f5 942 unsigned int noChildren = 0;
c79a329d 943#endif
ea596687 944 Window* children = NULL;
c79a329d 945
ee351013 946 // #define XQueryTree(d,w,r,p,c,nc) GrQueryTree(w,p,c,nc)
c79a329d
JS
947 int res = 1;
948#if !wxUSE_NANOX
949 res =
950#endif
951 XQueryTree((Display*) wxGetDisplay(), window, & root, & parent,
ee351013 952 & children, & noChildren);
ea596687
JS
953 if (children)
954 XFree(children);
955 if (res)
7eaac9f5
JS
956 return parent;
957 else
958 return (Window) 0;
959}
960
83df96d6
JS
961void wxExit()
962{
963 int retValue = 0;
964 if (wxTheApp)
965 retValue = wxTheApp->OnExit();
966
967 wxApp::CleanUp();
968 /*
969 * Exit in some platform-specific way. Not recommended that the app calls this:
970 * only for emergencies.
971 */
972 exit(retValue);
973}
974
975// Yield to other processes
976
977bool wxApp::Yield(bool onlyIfNeeded)
978{
979 bool s_inYield = FALSE;
980
981 if ( s_inYield )
982 {
983 if ( !onlyIfNeeded )
984 {
985 wxFAIL_MSG( wxT("wxYield called recursively" ) );
986 }
987
988 return FALSE;
989 }
990
991 s_inYield = TRUE;
992
993 while (wxTheApp && wxTheApp->Pending())
994 wxTheApp->Dispatch();
995
996 s_inYield = FALSE;
997
998 return TRUE;
999}
1000
ef8c973b 1001wxIcon wxApp::GetStdIcon(int which) const
83df96d6 1002{
ef8c973b 1003 return wxTheme::Get()->GetRenderer()->GetStdIcon(which);
83df96d6
JS
1004}
1005
7edcafa4
JS
1006void wxApp::OnAssert(const wxChar *file, int line, const wxChar *msg)
1007{
1008 // While the GUI isn't working that well, just print out the
1009 // message.
1010#if 0
1011 wxAppBase::OnAssert(file, line, msg);
1012#else
1013 wxString msg2;
1014 msg2.Printf("At file %s:%d: %s", file, line, msg);
1015 wxLogDebug(msg2);
1016#endif
1017}
1018