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