]> git.saurik.com Git - wxWidgets.git/blame - src/x11/app.cpp
more fixes to radio menu items: fixed Check() for them; allow separators inside the...
[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"
868741e9 28#include "wx/timer.h"
83df96d6 29
ef8c973b
VS
30#include "wx/univ/theme.h"
31#include "wx/univ/renderer.h"
32
83df96d6
JS
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
7eaac9f5 41#include "wx/x11/private.h"
83df96d6
JS
42
43#include <string.h>
44
9d2cef1c
RR
45//------------------------------------------------------------------------
46// global data
47//------------------------------------------------------------------------
48
83df96d6
JS
49extern wxList wxPendingDelete;
50
9d2cef1c 51wxHashTable *wxWidgetHashTable = NULL;
ab6b6b15 52wxHashTable *wxClientWidgetHashTable = NULL;
9d2cef1c 53
83df96d6
JS
54wxApp *wxTheApp = NULL;
55
9d2cef1c
RR
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;
83df96d6 62
9d2cef1c
RR
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;
83df96d6 69
9d2cef1c
RR
70//------------------------------------------------------------------------
71// X11 error handling
72//------------------------------------------------------------------------
83df96d6
JS
73
74#ifdef __WXDEBUG__
1b0fb34b 75typedef int (*XErrorHandlerFunc)(Display *, XErrorEvent *);
83df96d6 76
1b0fb34b 77XErrorHandlerFunc gs_pfnXErrorHandler = 0;
83df96d6 78
1b0fb34b
JS
79static int wxXErrorHandler(Display *dpy, XErrorEvent *xevent)
80{
81 // just forward to the default handler for now
c79a329d
JS
82 if (gs_pfnXErrorHandler)
83 return gs_pfnXErrorHandler(dpy, xevent);
84 else
85 return 0;
1b0fb34b 86}
83df96d6
JS
87#endif // __WXDEBUG__
88
9d2cef1c
RR
89//------------------------------------------------------------------------
90// wxApp
91//------------------------------------------------------------------------
92
83df96d6 93long wxApp::sm_lastMessageTime = 0;
a11672a4 94WXDisplay *wxApp::ms_display = NULL;
83df96d6 95
9d2cef1c
RR
96IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
97
98BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
99 EVT_IDLE(wxApp::OnIdle)
100END_EVENT_TABLE()
256d631a 101
83df96d6
JS
102bool wxApp::Initialize()
103{
83df96d6
JS
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
83df96d6 122 wxWidgetHashTable = new wxHashTable(wxKEY_INTEGER);
ab6b6b15 123 wxClientWidgetHashTable = new wxHashTable(wxKEY_INTEGER);
83df96d6
JS
124
125 wxModule::RegisterModules();
126 if (!wxModule::InitializeModules()) return FALSE;
127
128 return TRUE;
129}
130
131void wxApp::CleanUp()
132{
256d631a
JS
133 if (g_newArgv)
134 delete[] g_newArgv;
135 g_newArgv = NULL;
136
83df96d6
JS
137 delete wxWidgetHashTable;
138 wxWidgetHashTable = NULL;
ab6b6b15
RR
139 delete wxClientWidgetHashTable;
140 wxClientWidgetHashTable = NULL;
83df96d6
JS
141
142 wxModule::CleanUpModules();
143
144#if wxUSE_WX_RESOURCES
145 wxCleanUpResourceSystem();
146#endif
147
83df96d6
JS
148 delete wxTheColourDatabase;
149 wxTheColourDatabase = NULL;
150
a11672a4
RR
151 wxDeleteStockObjects();
152
153 wxDeleteStockLists();
154
155 delete wxTheApp;
156 wxTheApp = NULL;
83df96d6 157
83df96d6
JS
158 wxClassInfo::CleanUpClasses();
159
83df96d6
JS
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 {
ba696cfa 172 wxLogDebug("There were memory leaks.");
83df96d6
JS
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
a11672a4
RR
184// NB: argc and argv may be changed here, pass by reference!
185int wxEntryStart( int& argc, char *argv[] )
186{
187#ifdef __WXDEBUG__
ff6b424a 188#if !wxUSE_NANOX
a11672a4
RR
189 // install the X error handler
190 gs_pfnXErrorHandler = XSetErrorHandler( wxXErrorHandler );
ff6b424a 191#endif
a11672a4
RR
192#endif // __WXDEBUG__
193
256d631a
JS
194 wxString displayName;
195 bool syncDisplay = FALSE;
196
3a0b23eb 197 // Parse the arguments.
256d631a
JS
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 ++;
eb90fb3e 221 wxString windowGeometry = argv[i];
256d631a
JS
222 int w, h;
223 if (wxSscanf(windowGeometry.c_str(), _T("%dx%d"), &w, &h) != 2)
224 {
eb90fb3e 225 wxLogError(_("Invalid geometry specification '%s'"), windowGeometry.c_str());
256d631a
JS
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;
45ff6421 242
256d631a
JS
243 continue;
244 }
245
246 // Not eaten by wxWindows, so pass through
247 g_newArgv[g_newArgc] = argv[i];
248 g_newArgc ++;
249 }
250
c79a329d 251 Display* xdisplay = NULL;
256d631a
JS
252 if (displayName.IsEmpty())
253 xdisplay = XOpenDisplay(NULL);
254 else
461e93f9 255 xdisplay = XOpenDisplay((char*) displayName.c_str());
a11672a4
RR
256
257 if (!xdisplay)
258 {
259 wxLogError( _("wxWindows could not open display. Exiting.") );
260 return -1;
261 }
256d631a
JS
262
263 if (syncDisplay)
264 {
265 XSynchronize(xdisplay, True);
266 }
a11672a4
RR
267
268 wxApp::ms_display = (WXDisplay*) xdisplay;
269
270 XSelectInput( xdisplay, XDefaultRootWindow(xdisplay), PropertyChangeMask);
271
7e4501ee 272 wxSetDetectableAutoRepeat( TRUE );
a11672a4
RR
273
274 if (!wxApp::Initialize())
275 return -1;
276
277 return 0;
278}
279
a11672a4
RR
280int wxEntryInitGui()
281{
282 int retValue = 0;
283
284 if ( !wxTheApp->OnInitGui() )
285 retValue = -1;
286
287 return retValue;
288}
289
290
83df96d6
JS
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
a11672a4
RR
302 int err = wxEntryStart(argc, argv);
303 if (err)
304 return err;
83df96d6
JS
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
45ff6421
JS
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 }
256d631a
JS
338 wxTheApp->m_showIconic = g_showIconic;
339 wxTheApp->m_initialSize = g_initialSize;
83df96d6 340
a11672a4
RR
341 int retValue;
342 retValue = wxEntryInitGui();
83df96d6
JS
343
344 // Here frames insert themselves automatically into wxTopLevelWindows by
345 // getting created in OnInit().
a11672a4
RR
346 if ( retValue == 0 )
347 {
348 if ( !wxTheApp->OnInit() )
349 retValue = -1;
350 }
83df96d6 351
a11672a4 352 if ( retValue == 0 )
83df96d6
JS
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;
83df96d6 393 m_mainColormap = (WXColormap) NULL;
7eaac9f5 394 m_topLevelWidget = (WXWindow) NULL;
83df96d6 395 m_maxRequestSize = 0;
1b0fb34b 396 m_mainLoop = NULL;
256d631a
JS
397 m_showIconic = FALSE;
398 m_initialSize = wxDefaultSize;
83df96d6
JS
399}
400
401bool wxApp::Initialized()
402{
403 if (GetTopWindow())
404 return TRUE;
405 else
406 return FALSE;
407}
408
409int wxApp::MainLoop()
410{
c978d361 411 int rt;
1b0fb34b 412 m_mainLoop = new wxEventLoop;
83df96d6 413
1b0fb34b 414 rt = m_mainLoop->Run();
83df96d6 415
1b0fb34b
JS
416 delete m_mainLoop;
417 m_mainLoop = NULL;
418 return rt;
419}
83df96d6 420
70b8ab77 421#if !wxUSE_NANOX
f809133f
RR
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}
70b8ab77
JS
453#endif
454 // wxUSE_NANOX
f809133f
RR
455
456//-----------------------------------------------------------------------
086fd560 457// Processes an X event, returning TRUE if the event was processed.
f809133f
RR
458//-----------------------------------------------------------------------
459
086fd560 460bool wxApp::ProcessXEvent(WXEvent* _event)
1b0fb34b
JS
461{
462 XEvent* event = (XEvent*) _event;
83df96d6 463
1b0fb34b 464 wxWindow* win = NULL;
c79a329d 465 Window window = XEventGetWindow(event);
1b0fb34b 466 Window actualWindow = window;
0b5c0e1a 467
1b0fb34b 468 // Find the first wxWindow that corresponds to this event window
774b90fb
JS
469 // Because we're receiving events after a window
470 // has been destroyed, assume a 1:1 match between
471 // Window and wxWindow, so if it's not in the table,
472 // it must have been destroyed.
ab6b6b15 473
774b90fb
JS
474 win = wxGetWindowFromTable(window);
475 if (!win)
ab6b6b15
RR
476 {
477#if wxUSE_TWO_WINDOWS
478 win = wxGetClientWindowFromTable(window);
479 if (!win)
480#endif
481 return FALSE;
482 }
83df96d6 483
0b5c0e1a
JS
484#ifdef __WXDEBUG__
485 wxString windowClass = win->GetClassInfo()->GetClassName();
486#endif
487
1b0fb34b
JS
488 switch (event->type)
489 {
2f12683e
RR
490 case Expose:
491 {
ab6b6b15
RR
492#if wxUSE_TWO_WINDOWS
493 if (event->xexpose.window != (Window)win->GetClientWindow())
494 {
495 XEvent tmp_event;
496 wxExposeInfo info;
497 info.window = event->xexpose.window;
498 info.found_non_matching = FALSE;
499 while (XCheckIfEvent( wxGlobalDisplay(), &tmp_event, expose_predicate, (XPointer) &info ))
500 {
501 // Don't worry about optimizing redrawing the border etc.
502 }
503 win->NeedUpdateNcAreaInIdle();
504 }
505 else
506#endif
507 {
508 win->GetUpdateRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event),
509 XExposeEventGetWidth(event), XExposeEventGetHeight(event));
2f12683e 510
ab6b6b15 511 win->GetClearRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event),
2f12683e
RR
512 XExposeEventGetWidth(event), XExposeEventGetHeight(event));
513
514#if !wxUSE_NANOX
ab6b6b15
RR
515 XEvent tmp_event;
516 wxExposeInfo info;
517 info.window = event->xexpose.window;
518 info.found_non_matching = FALSE;
519 while (XCheckIfEvent( wxGlobalDisplay(), &tmp_event, expose_predicate, (XPointer) &info ))
520 {
521 win->GetUpdateRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y,
522 tmp_event.xexpose.width, tmp_event.xexpose.height );
2f12683e 523
ab6b6b15
RR
524 win->GetClearRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y,
525 tmp_event.xexpose.width, tmp_event.xexpose.height );
526 }
2f12683e 527#endif
ab6b6b15
RR
528 if (win->GetMainWindow() == win->GetClientWindow())
529 win->NeedUpdateNcAreaInIdle();
2f12683e 530
ab6b6b15
RR
531 // Only erase background, paint in idle time.
532 win->SendEraseEvents();
533 //win->Update();
534 }
2f12683e
RR
535
536 return TRUE;
537 }
538
539#if !wxUSE_NANOX
540 case GraphicsExpose:
541 {
542 // wxLogDebug( "GraphicsExpose from %s", win->GetName().c_str(),
543 // event->xgraphicsexpose.x, event->xgraphicsexpose.y,
544 // event->xgraphicsexpose.width, event->xgraphicsexpose.height);
545
546 win->GetUpdateRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y,
547 event->xgraphicsexpose.width, event->xgraphicsexpose.height);
548
549 win->GetClearRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y,
550 event->xgraphicsexpose.width, event->xgraphicsexpose.height);
551
552 if (event->xgraphicsexpose.count == 0)
553 {
554 // Only erase background, paint in idle time.
555 win->SendEraseEvents();
556 //win->Update();
557 }
558
559 return TRUE;
560 }
561#endif
562
1b0fb34b 563 case KeyPress:
83df96d6 564 {
9d2cef1c 565 if (!win->IsEnabled())
086fd560 566 return FALSE;
b513212d 567
9d2cef1c
RR
568 wxKeyEvent keyEvent(wxEVT_KEY_DOWN);
569 wxTranslateKeyEvent(keyEvent, win, window, event);
ba696cfa 570
9d2cef1c 571 // wxLogDebug( "OnKey from %s", win->GetName().c_str() );
1b0fb34b 572
120b822d
RR
573 // We didn't process wxEVT_KEY_DOWN, so send wxEVT_CHAR
574 if (win->GetEventHandler()->ProcessEvent( keyEvent ))
575 return TRUE;
576
577 keyEvent.SetEventType(wxEVT_CHAR);
578 if (win->GetEventHandler()->ProcessEvent( keyEvent ))
579 return TRUE;
580
581 if ( (keyEvent.m_keyCode == WXK_TAB) &&
582 win->GetParent() && (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
9d2cef1c 583 {
120b822d
RR
584 wxNavigationKeyEvent new_event;
585 new_event.SetEventObject( win->GetParent() );
586 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
587 new_event.SetDirection( (keyEvent.m_keyCode == WXK_TAB) );
588 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
589 new_event.SetWindowChange( keyEvent.ControlDown() );
590 new_event.SetCurrentFocus( win );
591 return win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
1b0fb34b 592 }
120b822d
RR
593
594 return FALSE;
83df96d6 595 }
1b0fb34b 596 case KeyRelease:
7eaac9f5 597 {
9d2cef1c 598 if (!win->IsEnabled())
086fd560 599 return FALSE;
b513212d 600
9d2cef1c
RR
601 wxKeyEvent keyEvent(wxEVT_KEY_UP);
602 wxTranslateKeyEvent(keyEvent, win, window, event);
1b0fb34b 603
086fd560 604 return win->GetEventHandler()->ProcessEvent( keyEvent );
7eaac9f5 605 }
256d631a
JS
606 case ConfigureNotify:
607 {
c79a329d 608#if wxUSE_NANOX
9d2cef1c 609 if (event->update.utype == GR_UPDATE_SIZE)
c79a329d 610#endif
256d631a 611 {
2f12683e 612 if (win->IsTopLevel() && win->IsShown())
77df2fbc
RR
613 {
614 wxTopLevelWindowX11 *tlw = (wxTopLevelWindowX11 *) win;
615 tlw->SetNeedResizeInIdle();
616 }
617 else
618 {
619 wxSizeEvent sizeEvent( wxSize(XConfigureEventGetWidth(event), XConfigureEventGetHeight(event)), win->GetId() );
620 sizeEvent.SetEventObject( win );
256d631a 621
77df2fbc
RR
622 return win->GetEventHandler()->ProcessEvent( sizeEvent );
623 }
256d631a 624 }
086fd560 625 return FALSE;
c2ff68d3 626 break;
256d631a
JS
627 }
628#if !wxUSE_NANOX
1b0fb34b 629 case PropertyNotify:
7eaac9f5 630 {
0b5c0e1a 631 //wxLogDebug("PropertyNotify: %s", windowClass.c_str());
086fd560 632 return HandlePropertyChange(_event);
7eaac9f5 633 }
b513212d 634 case ClientMessage:
3a0b23eb 635 {
9d2cef1c 636 if (!win->IsEnabled())
086fd560 637 return FALSE;
3a0b23eb 638
7e4501ee
RR
639 Atom wm_delete_window = XInternAtom(wxGlobalDisplay(), "WM_DELETE_WINDOW", True);
640 Atom wm_protocols = XInternAtom(wxGlobalDisplay(), "WM_PROTOCOLS", True);
b513212d
JS
641
642 if (event->xclient.message_type == wm_protocols)
643 {
6a44bffd 644 if ((Atom) (event->xclient.data.l[0]) == wm_delete_window)
b513212d 645 {
9d2cef1c 646 win->Close(FALSE);
086fd560 647 return TRUE;
b513212d
JS
648 }
649 }
086fd560 650 return FALSE;
b513212d 651 }
2f12683e
RR
652#if 0
653 case DestroyNotify:
654 {
655 printf( "destroy from %s\n", win->GetName().c_str() );
656 break;
657 }
658 case CreateNotify:
659 {
660 printf( "create from %s\n", win->GetName().c_str() );
661 break;
662 }
663 case MapRequest:
664 {
665 printf( "map request from %s\n", win->GetName().c_str() );
666 break;
667 }
1b0fb34b 668 case ResizeRequest:
7eaac9f5 669 {
2f12683e
RR
670 printf( "resize request from %s\n", win->GetName().c_str() );
671
7266b672 672 Display *disp = (Display*) wxGetDisplay();
1b0fb34b
JS
673 XEvent report;
674
675 // to avoid flicker
676 report = * event;
677 while( XCheckTypedWindowEvent (disp, actualWindow, ResizeRequest, &report));
678
b1633d20
RR
679 wxSize sz = win->GetSize();
680 wxSizeEvent sizeEvent(sz, win->GetId());
681 sizeEvent.SetEventObject(win);
1b0fb34b 682
b1633d20 683 return win->GetEventHandler()->ProcessEvent( sizeEvent );
7eaac9f5 684 }
256d631a 685#endif
b1633d20 686#endif
256d631a
JS
687#if wxUSE_NANOX
688 case GR_EVENT_TYPE_CLOSE_REQ:
689 {
690 if (win)
691 {
692 win->Close(FALSE);
086fd560 693 return TRUE;
256d631a 694 }
086fd560 695 return FALSE;
256d631a
JS
696 break;
697 }
c79a329d 698#endif
1b0fb34b
JS
699 case EnterNotify:
700 case LeaveNotify:
701 case ButtonPress:
702 case ButtonRelease:
703 case MotionNotify:
7eaac9f5 704 {
7e4501ee 705 if (!win->IsEnabled())
086fd560 706 return FALSE;
9691c806
RR
707
708 // Here we check if the top level window is
709 // disabled, which is one aspect of modality.
710 wxWindow *tlw = win;
711 while (tlw && !tlw->IsTopLevel())
712 tlw = tlw->GetParent();
713 if (tlw && !tlw->IsEnabled())
086fd560 714 return FALSE;
ea1ad04b 715
7e4501ee 716 if (event->type == ButtonPress)
1b0fb34b 717 {
7e4501ee 718 if ((win != wxWindow::FindFocus()) && win->AcceptsFocus())
9d2cef1c
RR
719 {
720 // This might actually be done in wxWindow::SetFocus()
ea1ad04b 721 // and not here. TODO.
9d2cef1c
RR
722 g_prevFocus = wxWindow::FindFocus();
723 g_nextFocus = win;
724
725 win->SetFocus();
726 }
1b0fb34b 727 }
ea1ad04b
RR
728
729#if !wxUSE_NANOX
730 if (event->type == LeaveNotify || event->type == EnterNotify)
731 {
732 // Throw out NotifyGrab and NotifyUngrab
733 if (event->xcrossing.mode != NotifyNormal)
086fd560 734 return FALSE;
ea1ad04b
RR
735 }
736#endif
7e4501ee
RR
737 wxMouseEvent wxevent;
738 wxTranslateMouseEvent(wxevent, win, window, event);
086fd560 739 return win->GetEventHandler()->ProcessEvent( wxevent );
7eaac9f5 740 }
1b0fb34b
JS
741 case FocusIn:
742 {
256d631a 743#if !wxUSE_NANOX
9d2cef1c
RR
744 if ((event->xfocus.detail != NotifyPointer) &&
745 (event->xfocus.mode == NotifyNormal))
256d631a 746#endif
1b0fb34b 747 {
9d2cef1c 748 // wxLogDebug( "FocusIn from %s of type %s", win->GetName().c_str(), win->GetClassInfo()->GetClassName() );
ba696cfa 749
1b0fb34b
JS
750 wxFocusEvent focusEvent(wxEVT_SET_FOCUS, win->GetId());
751 focusEvent.SetEventObject(win);
9d2cef1c
RR
752 focusEvent.SetWindow( g_prevFocus );
753 g_prevFocus = NULL;
f809133f 754
086fd560 755 return win->GetEventHandler()->ProcessEvent(focusEvent);
1b0fb34b 756 }
086fd560 757 return FALSE;
1b0fb34b
JS
758 break;
759 }
760 case FocusOut:
761 {
256d631a 762#if !wxUSE_NANOX
9d2cef1c
RR
763 if ((event->xfocus.detail != NotifyPointer) &&
764 (event->xfocus.mode == NotifyNormal))
256d631a 765#endif
1b0fb34b 766 {
9d2cef1c 767 // wxLogDebug( "FocusOut from %s of type %s", win->GetName().c_str(), win->GetClassInfo()->GetClassName() );
ba696cfa 768
1b0fb34b
JS
769 wxFocusEvent focusEvent(wxEVT_KILL_FOCUS, win->GetId());
770 focusEvent.SetEventObject(win);
9d2cef1c
RR
771 focusEvent.SetWindow( g_nextFocus );
772 g_nextFocus = NULL;
086fd560 773 return win->GetEventHandler()->ProcessEvent(focusEvent);
1b0fb34b 774 }
086fd560 775 return FALSE;
1b0fb34b
JS
776 break;
777 }
778 default:
779 {
45ff6421
JS
780#ifdef __WXDEBUG__
781 //wxString eventName = wxGetXEventName(XEvent& event);
782 //wxLogDebug(wxT("Event %s not handled"), eventName.c_str());
783#endif
086fd560 784 return FALSE;
1b0fb34b
JS
785 break;
786 }
83df96d6 787 }
086fd560 788 return FALSE;
83df96d6
JS
789}
790
791// Returns TRUE if more time is needed.
1b0fb34b
JS
792// Note that this duplicates wxEventLoopImpl::SendIdleEvent
793// but ProcessIdle may be needed by apps, so is kept.
83df96d6
JS
794bool wxApp::ProcessIdle()
795{
796 wxIdleEvent event;
797 event.SetEventObject(this);
798 ProcessEvent(event);
799
800 return event.MoreRequested();
801}
802
803void wxApp::ExitMainLoop()
804{
1b0fb34b
JS
805 if (m_mainLoop)
806 m_mainLoop->Exit(0);
83df96d6
JS
807}
808
809// Is a message/event pending?
810bool wxApp::Pending()
811{
1b0fb34b 812 return wxEventLoop::GetActive()->Pending();
83df96d6
JS
813}
814
815// Dispatch a message.
816void wxApp::Dispatch()
817{
1b0fb34b 818 wxEventLoop::GetActive()->Dispatch();
83df96d6
JS
819}
820
821// This should be redefined in a derived class for
822// handling property change events for XAtom IPC.
086fd560 823bool wxApp::HandlePropertyChange(WXEvent *event)
83df96d6
JS
824{
825 // by default do nothing special
7eaac9f5 826 // TODO: what to do for X11
256d631a 827 // XtDispatchEvent((XEvent*) event);
086fd560 828 return FALSE;
83df96d6
JS
829}
830
831void wxApp::OnIdle(wxIdleEvent& event)
832{
0d1dff01 833 static bool s_inOnIdle = FALSE;
83df96d6
JS
834
835 // Avoid recursion (via ProcessEvent default case)
0d1dff01 836 if (s_inOnIdle)
83df96d6
JS
837 return;
838
0d1dff01 839 s_inOnIdle = TRUE;
83df96d6 840
0d1dff01
RR
841 // Resend in the main thread events which have been prepared in other
842 // threads
83df96d6
JS
843 ProcessPendingEvents();
844
0d1dff01 845 // 'Garbage' collection of windows deleted with Close()
83df96d6
JS
846 DeletePendingObjects();
847
83df96d6
JS
848 // Send OnIdle events to all windows
849 bool needMore = SendIdleEvents();
850
851 if (needMore)
852 event.RequestMore(TRUE);
853
0d1dff01 854 s_inOnIdle = FALSE;
83df96d6
JS
855}
856
857void wxWakeUpIdle()
858{
859 // **** please implement me! ****
860 // Wake up the idle handler processor, even if it is in another thread...
861}
862
863
864// Send idle event to all top-level windows
865bool wxApp::SendIdleEvents()
866{
867 bool needMore = FALSE;
868
869 wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
870 while (node)
871 {
872 wxWindow* win = node->GetData();
873 if (SendIdleEvents(win))
874 needMore = TRUE;
875 node = node->GetNext();
876 }
877
878 return needMore;
879}
880
881// Send idle event to window and all subwindows
882bool wxApp::SendIdleEvents(wxWindow* win)
883{
884 bool needMore = FALSE;
885
886 wxIdleEvent event;
887 event.SetEventObject(win);
0d1dff01
RR
888
889 win->GetEventHandler()->ProcessEvent(event);
890
891 win->OnInternalIdle();
83df96d6
JS
892
893 if (event.MoreRequested())
894 needMore = TRUE;
895
896 wxNode* node = win->GetChildren().First();
897 while (node)
898 {
899 wxWindow* win = (wxWindow*) node->Data();
900 if (SendIdleEvents(win))
901 needMore = TRUE;
902
903 node = node->Next();
904 }
0d1dff01
RR
905
906 return needMore;
83df96d6
JS
907}
908
909void wxApp::DeletePendingObjects()
910{
911 wxNode *node = wxPendingDelete.First();
912 while (node)
913 {
914 wxObject *obj = (wxObject *)node->Data();
915
916 delete obj;
917
918 if (wxPendingDelete.Member(obj))
919 delete node;
920
921 // Deleting one object may have deleted other pending
922 // objects, so start from beginning of list again.
923 node = wxPendingDelete.First();
924 }
925}
926
256d631a 927// Create display, and other initialization
83df96d6
JS
928bool wxApp::OnInitGui()
929{
ca7497c2
JS
930 // Eventually this line will be removed, but for
931 // now we don't want to try popping up a dialog
932 // for error messages.
933 delete wxLog::SetActiveTarget(new wxLogStderr);
a11672a4 934
ea596687 935 if (!wxAppBase::OnInitGui())
ee351013 936 return FALSE;
ea596687 937
a11672a4 938 GetMainColormap( wxApp::GetDisplay() );
256d631a 939
a11672a4 940 m_maxRequestSize = XMaxRequestSize( (Display*) wxApp::GetDisplay() );
83df96d6
JS
941
942 return TRUE;
943}
944
945WXColormap wxApp::GetMainColormap(WXDisplay* display)
946{
947 if (!display) /* Must be called first with non-NULL display */
948 return m_mainColormap;
949
950 int defaultScreen = DefaultScreen((Display*) display);
951 Screen* screen = XScreenOfDisplay((Display*) display, defaultScreen);
952
953 Colormap c = DefaultColormapOfScreen(screen);
954
955 if (!m_mainColormap)
956 m_mainColormap = (WXColormap) c;
957
958 return (WXColormap) c;
959}
960
8354aa92 961Window wxGetWindowParent(Window window)
7eaac9f5 962{
86fd8bda
RR
963 wxASSERT_MSG( window, "invalid window" );
964
965 return (Window) 0;
966
7eaac9f5 967 Window parent, root = 0;
c79a329d
JS
968#if wxUSE_NANOX
969 int noChildren = 0;
970#else
7eaac9f5 971 unsigned int noChildren = 0;
c79a329d 972#endif
ea596687 973 Window* children = NULL;
c79a329d 974
ee351013 975 // #define XQueryTree(d,w,r,p,c,nc) GrQueryTree(w,p,c,nc)
c79a329d
JS
976 int res = 1;
977#if !wxUSE_NANOX
978 res =
979#endif
980 XQueryTree((Display*) wxGetDisplay(), window, & root, & parent,
ee351013 981 & children, & noChildren);
ea596687
JS
982 if (children)
983 XFree(children);
984 if (res)
7eaac9f5
JS
985 return parent;
986 else
987 return (Window) 0;
988}
989
83df96d6
JS
990void wxExit()
991{
992 int retValue = 0;
993 if (wxTheApp)
994 retValue = wxTheApp->OnExit();
995
996 wxApp::CleanUp();
997 /*
998 * Exit in some platform-specific way. Not recommended that the app calls this:
999 * only for emergencies.
1000 */
1001 exit(retValue);
1002}
1003
1004// Yield to other processes
1005
1006bool wxApp::Yield(bool onlyIfNeeded)
1007{
1008 bool s_inYield = FALSE;
1009
1010 if ( s_inYield )
1011 {
1012 if ( !onlyIfNeeded )
1013 {
1014 wxFAIL_MSG( wxT("wxYield called recursively" ) );
1015 }
1016
1017 return FALSE;
1018 }
1019
1020 s_inYield = TRUE;
1021
df0e1b64
JS
1022 // Make sure we have an event loop object,
1023 // or Pending/Dispatch will fail
1024 wxEventLoop* eventLoop = wxEventLoop::GetActive();
1025 wxEventLoop* newEventLoop = NULL;
1026 if (!eventLoop)
1027 {
1028 newEventLoop = new wxEventLoop;
1029 wxEventLoop::SetActive(newEventLoop);
1030 }
1031
83df96d6
JS
1032 while (wxTheApp && wxTheApp->Pending())
1033 wxTheApp->Dispatch();
1034
868741e9
JS
1035#if wxUSE_TIMER
1036 wxTimer::NotifyTimers();
1037#endif
1038 ProcessIdle();
1039
df0e1b64
JS
1040 if (newEventLoop)
1041 {
1042 wxEventLoop::SetActive(NULL);
1043 delete newEventLoop;
1044 }
1045
83df96d6
JS
1046 s_inYield = FALSE;
1047
1048 return TRUE;
1049}
1050
7edcafa4
JS
1051void wxApp::OnAssert(const wxChar *file, int line, const wxChar *msg)
1052{
1053 // While the GUI isn't working that well, just print out the
1054 // message.
1055#if 0
1056 wxAppBase::OnAssert(file, line, msg);
1057#else
1058 wxString msg2;
1059 msg2.Printf("At file %s:%d: %s", file, line, msg);
1060 wxLogDebug(msg2);
1061#endif
1062}
1063