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