]> git.saurik.com Git - wxWidgets.git/blame - src/x11/app.cpp
Fixed #1338966.
[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
65571936 9// Licence: wxWindows licence
83df96d6
JS
10/////////////////////////////////////////////////////////////////////////////
11
83df96d6
JS
12#include "wx/frame.h"
13#include "wx/app.h"
14#include "wx/utils.h"
15#include "wx/gdicmn.h"
83df96d6 16#include "wx/icon.h"
83df96d6 17#include "wx/dialog.h"
83df96d6
JS
18#include "wx/log.h"
19#include "wx/module.h"
20#include "wx/memory.h"
21#include "wx/log.h"
22#include "wx/intl.h"
1b0fb34b 23#include "wx/evtloop.h"
868741e9 24#include "wx/timer.h"
2b5f62a0 25#include "wx/filename.h"
ed39ff57 26#include "wx/hash.h"
83df96d6 27
ef8c973b
VS
28#include "wx/univ/theme.h"
29#include "wx/univ/renderer.h"
30
83df96d6
JS
31#if wxUSE_THREADS
32 #include "wx/thread.h"
33#endif
34
7eaac9f5 35#include "wx/x11/private.h"
83df96d6
JS
36
37#include <string.h>
38
9d2cef1c
RR
39//------------------------------------------------------------------------
40// global data
41//------------------------------------------------------------------------
42
83df96d6
JS
43extern wxList wxPendingDelete;
44
b8033a5d
VZ
45wxWindowHash *wxWidgetHashTable = NULL;
46wxWindowHash *wxClientWidgetHashTable = NULL;
9d2cef1c 47
9d2cef1c
RR
48static bool g_showIconic = FALSE;
49static wxSize g_initialSize = wxDefaultSize;
83df96d6 50
9d2cef1c
RR
51// This is required for wxFocusEvent::SetWindow(). It will only
52// work for focus events which we provoke ourselves (by calling
53// SetFocus()). It will not work for those events, which X11
54// generates itself.
55static wxWindow *g_nextFocus = NULL;
56static wxWindow *g_prevFocus = NULL;
83df96d6 57
9d2cef1c
RR
58//------------------------------------------------------------------------
59// X11 error handling
60//------------------------------------------------------------------------
83df96d6
JS
61
62#ifdef __WXDEBUG__
1b0fb34b 63typedef int (*XErrorHandlerFunc)(Display *, XErrorEvent *);
83df96d6 64
1b0fb34b 65XErrorHandlerFunc gs_pfnXErrorHandler = 0;
83df96d6 66
1b0fb34b
JS
67static int wxXErrorHandler(Display *dpy, XErrorEvent *xevent)
68{
69 // just forward to the default handler for now
c79a329d
JS
70 if (gs_pfnXErrorHandler)
71 return gs_pfnXErrorHandler(dpy, xevent);
72 else
73 return 0;
1b0fb34b 74}
83df96d6
JS
75#endif // __WXDEBUG__
76
9d2cef1c
RR
77//------------------------------------------------------------------------
78// wxApp
79//------------------------------------------------------------------------
80
83df96d6 81long wxApp::sm_lastMessageTime = 0;
a11672a4 82WXDisplay *wxApp::ms_display = NULL;
83df96d6 83
9d2cef1c
RR
84IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
85
86BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
955a9197 87 EVT_IDLE(wxAppBase::OnIdle)
9d2cef1c 88END_EVENT_TABLE()
256d631a 89
05e2b077 90bool wxApp::Initialize(int& argc, wxChar **argv)
83df96d6 91{
05e2b077 92#if defined(__WXDEBUG__) && !wxUSE_NANOX
a11672a4
RR
93 // install the X error handler
94 gs_pfnXErrorHandler = XSetErrorHandler( wxXErrorHandler );
95#endif // __WXDEBUG__
96
c6441a0d 97 wxString displayName;
256d631a
JS
98 bool syncDisplay = FALSE;
99
05e2b077
VZ
100 int argcOrig = argc;
101 for ( int i = 0; i < argcOrig; i++ )
256d631a 102 {
05e2b077 103 if (wxStrcmp( argv[i], _T("-display") ) == 0)
256d631a
JS
104 {
105 if (i < (argc - 1))
106 {
05e2b077
VZ
107 argv[i++] = NULL;
108
256d631a 109 displayName = argv[i];
05e2b077
VZ
110
111 argv[i] = NULL;
112 argc -= 2;
256d631a
JS
113 }
114 }
05e2b077 115 else if (wxStrcmp( argv[i], _T("-geometry") ) == 0)
256d631a
JS
116 {
117 if (i < (argc - 1))
118 {
05e2b077
VZ
119 argv[i++] = NULL;
120
256d631a 121 int w, h;
05e2b077 122 if (wxSscanf(argv[i], _T("%dx%d"), &w, &h) != 2)
256d631a 123 {
05e2b077 124 wxLogError( _("Invalid geometry specification '%s'"),
c6441a0d 125 wxString(argv[i]).c_str() );
256d631a
JS
126 }
127 else
128 {
129 g_initialSize = wxSize(w, h);
130 }
05e2b077
VZ
131
132 argv[i] = NULL;
133 argc -= 2;
256d631a
JS
134 }
135 }
05e2b077 136 else if (wxStrcmp( argv[i], _T("-sync") ) == 0)
256d631a
JS
137 {
138 syncDisplay = TRUE;
05e2b077
VZ
139
140 argv[i] = NULL;
141 argc--;
256d631a 142 }
05e2b077 143 else if (wxStrcmp( argv[i], _T("-iconic") ) == 0)
256d631a
JS
144 {
145 g_showIconic = TRUE;
45ff6421 146
05e2b077
VZ
147 argv[i] = NULL;
148 argc--;
256d631a 149 }
05e2b077 150 }
256d631a 151
05e2b077
VZ
152 if ( argc != argcOrig )
153 {
154 // remove the argumens we consumed
155 for ( int i = 0; i < argc; i++ )
156 {
157 while ( !argv[i] )
158 {
159 memmove(argv + i, argv + i + 1, argcOrig - i);
160 }
161 }
256d631a 162 }
a11672a4 163
7c9955d1 164 // X11 display stuff
c6441a0d
VS
165 Display *xdisplay;
166 if ( displayName.empty() )
167 xdisplay = XOpenDisplay( NULL );
168 else
169 xdisplay = XOpenDisplay( displayName.ToAscii() );
a11672a4
RR
170 if (!xdisplay)
171 {
77ffb593 172 wxLogError( _("wxWidgets could not open display. Exiting.") );
05e2b077
VZ
173 return false;
174 }
175
256d631a 176 if (syncDisplay)
256d631a 177 XSynchronize(xdisplay, True);
e2386592 178
05e2b077 179 ms_display = (WXDisplay*) xdisplay;
7c9955d1 180
a11672a4 181 XSelectInput( xdisplay, XDefaultRootWindow(xdisplay), PropertyChangeMask);
e2386592 182
2b5f62a0 183 // Misc.
7e4501ee 184 wxSetDetectableAutoRepeat( TRUE );
a11672a4 185
5b004007
VZ
186 if ( !wxAppBase::Initialize(argc, argv) )
187 {
188 XCloseDisplay(xdisplay);
189
190 return false;
191 }
192
2b5f62a0
VZ
193#if wxUSE_UNICODE
194 // Glib's type system required by Pango
195 g_type_init();
7c9955d1 196#endif
2b5f62a0 197
05e2b077
VZ
198#if wxUSE_INTL
199 wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
200#endif
a11672a4 201
b8033a5d
VZ
202 wxWidgetHashTable = new wxWindowHash;
203 wxClientWidgetHashTable = new wxWindowHash;
a11672a4 204
05e2b077 205 return true;
a11672a4
RR
206}
207
05e2b077 208void wxApp::CleanUp()
83df96d6 209{
05e2b077
VZ
210 delete wxWidgetHashTable;
211 wxWidgetHashTable = NULL;
212 delete wxClientWidgetHashTable;
213 wxClientWidgetHashTable = NULL;
83df96d6 214
05e2b077
VZ
215 wxAppBase::CleanUp();
216}
83df96d6 217
83df96d6
JS
218wxApp::wxApp()
219{
00344dd0 220 // TODO: parse the command line
83df96d6
JS
221 argc = 0;
222 argv = NULL;
00344dd0 223
83df96d6 224 m_mainColormap = (WXColormap) NULL;
7eaac9f5 225 m_topLevelWidget = (WXWindow) NULL;
83df96d6 226 m_maxRequestSize = 0;
256d631a
JS
227 m_showIconic = FALSE;
228 m_initialSize = wxDefaultSize;
366e8ae6 229
8601b2e1 230#if !wxUSE_NANOX
9ce8d6a2 231 m_visualInfo = NULL;
8601b2e1 232#endif
dc4025af
RR
233}
234
235wxApp::~wxApp()
236{
8601b2e1 237#if !wxUSE_NANOX
9ce8d6a2 238 delete m_visualInfo;
8601b2e1 239#endif
83df96d6
JS
240}
241
70b8ab77 242#if !wxUSE_NANOX
f809133f
RR
243//-----------------------------------------------------------------------
244// X11 predicate function for exposure compression
245//-----------------------------------------------------------------------
246
247struct wxExposeInfo
248{
249 Window window;
250 Bool found_non_matching;
251};
252
253static Bool expose_predicate (Display *display, XEvent *xevent, XPointer arg)
254{
255 wxExposeInfo *info = (wxExposeInfo*) arg;
e2386592 256
f809133f
RR
257 if (info->found_non_matching)
258 return FALSE;
e2386592 259
f809133f
RR
260 if (xevent->xany.type != Expose)
261 {
262 info->found_non_matching = TRUE;
263 return FALSE;
264 }
e2386592 265
f809133f
RR
266 if (xevent->xexpose.window != info->window)
267 {
268 info->found_non_matching = TRUE;
269 return FALSE;
270 }
e2386592 271
f809133f
RR
272 return TRUE;
273}
70b8ab77
JS
274#endif
275 // wxUSE_NANOX
f809133f
RR
276
277//-----------------------------------------------------------------------
086fd560 278// Processes an X event, returning TRUE if the event was processed.
f809133f
RR
279//-----------------------------------------------------------------------
280
086fd560 281bool wxApp::ProcessXEvent(WXEvent* _event)
1b0fb34b
JS
282{
283 XEvent* event = (XEvent*) _event;
83df96d6 284
1b0fb34b 285 wxWindow* win = NULL;
c79a329d 286 Window window = XEventGetWindow(event);
e2386592 287#if 0
1b0fb34b 288 Window actualWindow = window;
e2386592 289#endif
0b5c0e1a 290
1b0fb34b 291 // Find the first wxWindow that corresponds to this event window
774b90fb
JS
292 // Because we're receiving events after a window
293 // has been destroyed, assume a 1:1 match between
294 // Window and wxWindow, so if it's not in the table,
295 // it must have been destroyed.
e2386592 296
774b90fb
JS
297 win = wxGetWindowFromTable(window);
298 if (!win)
ab6b6b15
RR
299 {
300#if wxUSE_TWO_WINDOWS
301 win = wxGetClientWindowFromTable(window);
302 if (!win)
303#endif
304 return FALSE;
305 }
83df96d6 306
0b5c0e1a
JS
307#ifdef __WXDEBUG__
308 wxString windowClass = win->GetClassInfo()->GetClassName();
309#endif
e2386592 310
1b0fb34b
JS
311 switch (event->type)
312 {
2f12683e
RR
313 case Expose:
314 {
8601b2e1 315#if wxUSE_TWO_WINDOWS && !wxUSE_NANOX
f41bc3e3 316 if (event->xexpose.window != (Window)win->GetClientAreaWindow())
ab6b6b15
RR
317 {
318 XEvent tmp_event;
319 wxExposeInfo info;
320 info.window = event->xexpose.window;
321 info.found_non_matching = FALSE;
322 while (XCheckIfEvent( wxGlobalDisplay(), &tmp_event, expose_predicate, (XPointer) &info ))
323 {
324 // Don't worry about optimizing redrawing the border etc.
325 }
326 win->NeedUpdateNcAreaInIdle();
327 }
328 else
329#endif
330 {
331 win->GetUpdateRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event),
332 XExposeEventGetWidth(event), XExposeEventGetHeight(event));
ab6b6b15 333 win->GetClearRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event),
2f12683e
RR
334 XExposeEventGetWidth(event), XExposeEventGetHeight(event));
335
336#if !wxUSE_NANOX
ab6b6b15
RR
337 XEvent tmp_event;
338 wxExposeInfo info;
339 info.window = event->xexpose.window;
340 info.found_non_matching = FALSE;
341 while (XCheckIfEvent( wxGlobalDisplay(), &tmp_event, expose_predicate, (XPointer) &info ))
342 {
343 win->GetUpdateRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y,
344 tmp_event.xexpose.width, tmp_event.xexpose.height );
e2386592 345
ab6b6b15
RR
346 win->GetClearRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y,
347 tmp_event.xexpose.width, tmp_event.xexpose.height );
348 }
2f12683e 349#endif
c2c0dabf
RR
350
351 // This simplifies the expose and clear areas to simple
352 // rectangles.
353 win->GetUpdateRegion() = win->GetUpdateRegion().GetBox();
354 win->GetClearRegion() = win->GetClearRegion().GetBox();
e2386592 355
c2c0dabf 356 // If we only have one X11 window, always indicate
e2386592 357 // that borders might have to be redrawn.
f41bc3e3 358 if (win->GetMainWindow() == win->GetClientAreaWindow())
ab6b6b15 359 win->NeedUpdateNcAreaInIdle();
2f12683e 360
ab6b6b15
RR
361 // Only erase background, paint in idle time.
362 win->SendEraseEvents();
09a1dffa
JS
363
364 // EXPERIMENT
365 //win->Update();
ab6b6b15 366 }
2f12683e
RR
367
368 return TRUE;
369 }
e2386592 370
2f12683e
RR
371#if !wxUSE_NANOX
372 case GraphicsExpose:
373 {
89cd4125 374 wxLogTrace( _T("expose"), _T("GraphicsExpose from %s"), win->GetName().c_str());
e2386592 375
2f12683e
RR
376 win->GetUpdateRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y,
377 event->xgraphicsexpose.width, event->xgraphicsexpose.height);
e2386592 378
2f12683e
RR
379 win->GetClearRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y,
380 event->xgraphicsexpose.width, event->xgraphicsexpose.height);
e2386592 381
2f12683e
RR
382 if (event->xgraphicsexpose.count == 0)
383 {
384 // Only erase background, paint in idle time.
385 win->SendEraseEvents();
c2c0dabf 386 // win->Update();
2f12683e
RR
387 }
388
389 return TRUE;
390 }
391#endif
392
1b0fb34b 393 case KeyPress:
83df96d6 394 {
9d2cef1c 395 if (!win->IsEnabled())
086fd560 396 return FALSE;
b513212d 397
9d2cef1c
RR
398 wxKeyEvent keyEvent(wxEVT_KEY_DOWN);
399 wxTranslateKeyEvent(keyEvent, win, window, event);
e2386592 400
9d2cef1c 401 // wxLogDebug( "OnKey from %s", win->GetName().c_str() );
e2386592 402
120b822d
RR
403 // We didn't process wxEVT_KEY_DOWN, so send wxEVT_CHAR
404 if (win->GetEventHandler()->ProcessEvent( keyEvent ))
405 return TRUE;
e2386592 406
120b822d 407 keyEvent.SetEventType(wxEVT_CHAR);
2b5f62a0
VZ
408 // Do the translation again, retaining the ASCII
409 // code.
410 wxTranslateKeyEvent(keyEvent, win, window, event, TRUE);
120b822d
RR
411 if (win->GetEventHandler()->ProcessEvent( keyEvent ))
412 return TRUE;
e2386592 413
120b822d
RR
414 if ( (keyEvent.m_keyCode == WXK_TAB) &&
415 win->GetParent() && (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
9d2cef1c 416 {
120b822d
RR
417 wxNavigationKeyEvent new_event;
418 new_event.SetEventObject( win->GetParent() );
419 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
420 new_event.SetDirection( (keyEvent.m_keyCode == WXK_TAB) );
421 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
422 new_event.SetWindowChange( keyEvent.ControlDown() );
423 new_event.SetCurrentFocus( win );
424 return win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
1b0fb34b 425 }
120b822d
RR
426
427 return FALSE;
83df96d6 428 }
1b0fb34b 429 case KeyRelease:
7eaac9f5 430 {
9d2cef1c 431 if (!win->IsEnabled())
086fd560 432 return FALSE;
b513212d 433
9d2cef1c
RR
434 wxKeyEvent keyEvent(wxEVT_KEY_UP);
435 wxTranslateKeyEvent(keyEvent, win, window, event);
e2386592 436
086fd560 437 return win->GetEventHandler()->ProcessEvent( keyEvent );
7eaac9f5 438 }
256d631a
JS
439 case ConfigureNotify:
440 {
c79a329d 441#if wxUSE_NANOX
9d2cef1c 442 if (event->update.utype == GR_UPDATE_SIZE)
c79a329d 443#endif
256d631a 444 {
3cd2f0bd
VZ
445 wxTopLevelWindow *tlw = wxDynamicCast(win, wxTopLevelWindow);
446 if ( tlw )
c2c0dabf 447 {
c2c0dabf
RR
448 tlw->SetConfigureGeometry( XConfigureEventGetX(event), XConfigureEventGetY(event),
449 XConfigureEventGetWidth(event), XConfigureEventGetHeight(event) );
450 }
e2386592 451
3cd2f0bd 452 if ( tlw && tlw->IsShown() )
77df2fbc 453 {
77df2fbc
RR
454 tlw->SetNeedResizeInIdle();
455 }
456 else
457 {
458 wxSizeEvent sizeEvent( wxSize(XConfigureEventGetWidth(event), XConfigureEventGetHeight(event)), win->GetId() );
459 sizeEvent.SetEventObject( win );
e2386592 460
77df2fbc
RR
461 return win->GetEventHandler()->ProcessEvent( sizeEvent );
462 }
256d631a 463 }
086fd560 464 return FALSE;
256d631a
JS
465 }
466#if !wxUSE_NANOX
1b0fb34b 467 case PropertyNotify:
7eaac9f5 468 {
0b5c0e1a 469 //wxLogDebug("PropertyNotify: %s", windowClass.c_str());
086fd560 470 return HandlePropertyChange(_event);
7eaac9f5 471 }
b513212d 472 case ClientMessage:
3a0b23eb 473 {
9d2cef1c 474 if (!win->IsEnabled())
086fd560 475 return FALSE;
3a0b23eb 476
7e4501ee
RR
477 Atom wm_delete_window = XInternAtom(wxGlobalDisplay(), "WM_DELETE_WINDOW", True);
478 Atom wm_protocols = XInternAtom(wxGlobalDisplay(), "WM_PROTOCOLS", True);
b513212d
JS
479
480 if (event->xclient.message_type == wm_protocols)
481 {
6a44bffd 482 if ((Atom) (event->xclient.data.l[0]) == wm_delete_window)
b513212d 483 {
9d2cef1c 484 win->Close(FALSE);
086fd560 485 return TRUE;
b513212d
JS
486 }
487 }
086fd560 488 return FALSE;
b513212d 489 }
2f12683e
RR
490#if 0
491 case DestroyNotify:
492 {
493 printf( "destroy from %s\n", win->GetName().c_str() );
494 break;
495 }
496 case CreateNotify:
497 {
498 printf( "create from %s\n", win->GetName().c_str() );
499 break;
500 }
501 case MapRequest:
502 {
503 printf( "map request from %s\n", win->GetName().c_str() );
504 break;
505 }
1b0fb34b 506 case ResizeRequest:
7eaac9f5 507 {
2f12683e 508 printf( "resize request from %s\n", win->GetName().c_str() );
e2386592 509
7266b672 510 Display *disp = (Display*) wxGetDisplay();
1b0fb34b 511 XEvent report;
e2386592 512
1b0fb34b
JS
513 // to avoid flicker
514 report = * event;
515 while( XCheckTypedWindowEvent (disp, actualWindow, ResizeRequest, &report));
e2386592 516
b1633d20
RR
517 wxSize sz = win->GetSize();
518 wxSizeEvent sizeEvent(sz, win->GetId());
519 sizeEvent.SetEventObject(win);
1b0fb34b 520
b1633d20 521 return win->GetEventHandler()->ProcessEvent( sizeEvent );
7eaac9f5 522 }
256d631a 523#endif
b1633d20 524#endif
256d631a
JS
525#if wxUSE_NANOX
526 case GR_EVENT_TYPE_CLOSE_REQ:
527 {
528 if (win)
529 {
530 win->Close(FALSE);
086fd560 531 return TRUE;
256d631a 532 }
086fd560 533 return FALSE;
256d631a
JS
534 break;
535 }
c79a329d 536#endif
1b0fb34b
JS
537 case EnterNotify:
538 case LeaveNotify:
539 case ButtonPress:
540 case ButtonRelease:
541 case MotionNotify:
7eaac9f5 542 {
7e4501ee 543 if (!win->IsEnabled())
086fd560 544 return FALSE;
366e8ae6 545
9691c806
RR
546 // Here we check if the top level window is
547 // disabled, which is one aspect of modality.
548 wxWindow *tlw = win;
549 while (tlw && !tlw->IsTopLevel())
550 tlw = tlw->GetParent();
551 if (tlw && !tlw->IsEnabled())
086fd560 552 return FALSE;
e2386592 553
7e4501ee 554 if (event->type == ButtonPress)
1b0fb34b 555 {
7e4501ee 556 if ((win != wxWindow::FindFocus()) && win->AcceptsFocus())
9d2cef1c
RR
557 {
558 // This might actually be done in wxWindow::SetFocus()
ea1ad04b 559 // and not here. TODO.
9d2cef1c
RR
560 g_prevFocus = wxWindow::FindFocus();
561 g_nextFocus = win;
e2386592 562
58ec2255
JS
563 wxLogTrace( _T("focus"), _T("About to call SetFocus on %s of type %s due to button press"), win->GetName().c_str(), win->GetClassInfo()->GetClassName() );
564
565 // Record the fact that this window is
566 // getting the focus, because we'll need to
567 // check if its parent is getting a bogus
568 // focus and duly ignore it.
569 // TODO: may need to have this code in SetFocus, too.
570 extern wxWindow* g_GettingFocus;
571 g_GettingFocus = win;
9d2cef1c
RR
572 win->SetFocus();
573 }
1b0fb34b 574 }
e2386592 575
ea1ad04b
RR
576#if !wxUSE_NANOX
577 if (event->type == LeaveNotify || event->type == EnterNotify)
578 {
579 // Throw out NotifyGrab and NotifyUngrab
580 if (event->xcrossing.mode != NotifyNormal)
086fd560 581 return FALSE;
ea1ad04b
RR
582 }
583#endif
7e4501ee
RR
584 wxMouseEvent wxevent;
585 wxTranslateMouseEvent(wxevent, win, window, event);
086fd560 586 return win->GetEventHandler()->ProcessEvent( wxevent );
7eaac9f5 587 }
1b0fb34b 588 case FocusIn:
256d631a 589#if !wxUSE_NANOX
bcd3832a
VZ
590 if ((event->xfocus.detail != NotifyPointer) &&
591 (event->xfocus.mode == NotifyNormal))
256d631a 592#endif
bcd3832a
VZ
593 {
594 wxLogTrace( _T("focus"), _T("FocusIn from %s of type %s"), win->GetName().c_str(), win->GetClassInfo()->GetClassName() );
595
596 extern wxWindow* g_GettingFocus;
597 if (g_GettingFocus && g_GettingFocus->GetParent() == win)
598 {
599 // Ignore this, this can be a spurious FocusIn
600 // caused by a child having its focus set.
601 g_GettingFocus = NULL;
602 wxLogTrace( _T("focus"), _T("FocusIn from %s of type %s being deliberately ignored"), win->GetName().c_str(), win->GetClassInfo()->GetClassName() );
603 return TRUE;
604 }
605 else
1b0fb34b 606 {
bcd3832a
VZ
607 wxFocusEvent focusEvent(wxEVT_SET_FOCUS, win->GetId());
608 focusEvent.SetEventObject(win);
609 focusEvent.SetWindow( g_prevFocus );
610 g_prevFocus = NULL;
366e8ae6 611
bcd3832a 612 return win->GetEventHandler()->ProcessEvent(focusEvent);
1b0fb34b 613 }
1b0fb34b 614 }
bcd3832a
VZ
615 return FALSE;
616
1b0fb34b 617 case FocusOut:
256d631a 618#if !wxUSE_NANOX
bcd3832a
VZ
619 if ((event->xfocus.detail != NotifyPointer) &&
620 (event->xfocus.mode == NotifyNormal))
256d631a 621#endif
bcd3832a
VZ
622 {
623 wxLogTrace( _T("focus"), _T("FocusOut from %s of type %s"), win->GetName().c_str(), win->GetClassInfo()->GetClassName() );
e2386592 624
bcd3832a
VZ
625 wxFocusEvent focusEvent(wxEVT_KILL_FOCUS, win->GetId());
626 focusEvent.SetEventObject(win);
627 focusEvent.SetWindow( g_nextFocus );
628 g_nextFocus = NULL;
629 return win->GetEventHandler()->ProcessEvent(focusEvent);
1b0fb34b 630 }
bcd3832a
VZ
631 return FALSE;
632
45ff6421 633#ifdef __WXDEBUG__
bcd3832a 634 default:
45ff6421
JS
635 //wxString eventName = wxGetXEventName(XEvent& event);
636 //wxLogDebug(wxT("Event %s not handled"), eventName.c_str());
5b3b52ef 637 break;
bcd3832a 638#endif // __WXDEBUG__
83df96d6 639 }
83df96d6 640
bcd3832a 641 return FALSE;
83df96d6
JS
642}
643
644// This should be redefined in a derived class for
645// handling property change events for XAtom IPC.
086fd560 646bool wxApp::HandlePropertyChange(WXEvent *event)
83df96d6
JS
647{
648 // by default do nothing special
7eaac9f5 649 // TODO: what to do for X11
256d631a 650 // XtDispatchEvent((XEvent*) event);
086fd560 651 return FALSE;
83df96d6
JS
652}
653
e2478fde 654void wxApp::WakeUpIdle()
83df96d6 655{
e2478fde
VZ
656 // TODO: use wxMotif implementation?
657
83df96d6
JS
658 // Wake up the idle handler processor, even if it is in another thread...
659}
660
661
256d631a 662// Create display, and other initialization
83df96d6
JS
663bool wxApp::OnInitGui()
664{
ca7497c2
JS
665 // Eventually this line will be removed, but for
666 // now we don't want to try popping up a dialog
667 // for error messages.
668 delete wxLog::SetActiveTarget(new wxLogStderr);
e2386592 669
ea596687 670 if (!wxAppBase::OnInitGui())
dc4025af 671 return FALSE;
e2386592 672
a11672a4 673 GetMainColormap( wxApp::GetDisplay() );
256d631a 674
a11672a4 675 m_maxRequestSize = XMaxRequestSize( (Display*) wxApp::GetDisplay() );
83df96d6 676
8601b2e1 677#if !wxUSE_NANOX
9ce8d6a2
MB
678 m_visualInfo = new wxXVisualInfo;
679 wxFillXVisualInfo( m_visualInfo, (Display*) wxApp::GetDisplay() );
8601b2e1 680#endif
366e8ae6 681
83df96d6
JS
682 return TRUE;
683}
684
2b5f62a0
VZ
685#if wxUSE_UNICODE
686
687#include <pango/pango.h>
688#include <pango/pangox.h>
4ae1af05
MB
689#ifdef HAVE_PANGO_XFT
690 #include <pango/pangoxft.h>
691#endif
2b5f62a0
VZ
692
693PangoContext* wxApp::GetPangoContext()
694{
695 static PangoContext *ret = NULL;
696 if (ret)
697 return ret;
7c9955d1 698
2b5f62a0 699 Display *xdisplay = (Display*) wxApp::GetDisplay();
7c9955d1 700
4ae1af05 701#ifdef HAVE_PANGO_XFT
2b5f62a0
VZ
702 int xscreen = DefaultScreen(xdisplay);
703 static int use_xft = -1;
704 if (use_xft == -1)
705 {
706 wxString val = wxGetenv( L"GDK_USE_XFT" );
707 use_xft = (val == L"1");
708 }
7c9955d1 709
2b5f62a0
VZ
710 if (use_xft)
711 ret = pango_xft_get_context( xdisplay, xscreen );
712 else
713#endif
714 ret = pango_x_get_context( xdisplay );
7c9955d1 715
2b5f62a0
VZ
716 if (!PANGO_IS_CONTEXT(ret))
717 wxLogError( wxT("No pango context.") );
7c9955d1 718
2b5f62a0
VZ
719 return ret;
720}
721#endif
722
83df96d6
JS
723WXColormap wxApp::GetMainColormap(WXDisplay* display)
724{
725 if (!display) /* Must be called first with non-NULL display */
726 return m_mainColormap;
727
728 int defaultScreen = DefaultScreen((Display*) display);
729 Screen* screen = XScreenOfDisplay((Display*) display, defaultScreen);
730
731 Colormap c = DefaultColormapOfScreen(screen);
732
733 if (!m_mainColormap)
734 m_mainColormap = (WXColormap) c;
735
736 return (WXColormap) c;
737}
738
8354aa92 739Window wxGetWindowParent(Window window)
7eaac9f5 740{
54385bdb 741 wxASSERT_MSG( window, _T("invalid window") );
e2386592 742
86fd8bda
RR
743 return (Window) 0;
744
a371f703
JJ
745#ifndef __VMS
746 // VMS chokes on unreacheable code
747 Window parent, root = 0;
c79a329d
JS
748#if wxUSE_NANOX
749 int noChildren = 0;
750#else
7eaac9f5 751 unsigned int noChildren = 0;
c79a329d 752#endif
ea596687 753 Window* children = NULL;
c79a329d 754
ee351013 755 // #define XQueryTree(d,w,r,p,c,nc) GrQueryTree(w,p,c,nc)
c79a329d
JS
756 int res = 1;
757#if !wxUSE_NANOX
758 res =
759#endif
760 XQueryTree((Display*) wxGetDisplay(), window, & root, & parent,
ee351013 761 & children, & noChildren);
ea596687
JS
762 if (children)
763 XFree(children);
764 if (res)
7eaac9f5
JS
765 return parent;
766 else
767 return (Window) 0;
a371f703 768#endif
7eaac9f5
JS
769}
770
e2478fde 771void wxApp::Exit()
83df96d6 772{
83df96d6 773 wxApp::CleanUp();
e2478fde
VZ
774
775 wxAppConsole::Exit();
83df96d6
JS
776}
777
778// Yield to other processes
779
780bool wxApp::Yield(bool onlyIfNeeded)
781{
bbcd408a
JS
782 // Sometimes only 2 yields seem
783 // to do the trick, e.g. in the
784 // progress dialog
785 int i;
786 for (i = 0; i < 2; i++)
83df96d6 787 {
f6afb56a 788 static bool s_inYield = FALSE;
bbcd408a
JS
789
790 if ( s_inYield )
83df96d6 791 {
bbcd408a
JS
792 if ( !onlyIfNeeded )
793 {
794 wxFAIL_MSG( wxT("wxYield called recursively" ) );
795 }
83df96d6 796
bbcd408a
JS
797 return FALSE;
798 }
83df96d6 799
bbcd408a 800 s_inYield = TRUE;
83df96d6 801
bbcd408a
JS
802 // Make sure we have an event loop object,
803 // or Pending/Dispatch will fail
804 wxEventLoop* eventLoop = wxEventLoop::GetActive();
805 wxEventLoop* newEventLoop = NULL;
806 if (!eventLoop)
807 {
808 newEventLoop = new wxEventLoop;
809 wxEventLoop::SetActive(newEventLoop);
810 }
df0e1b64 811
2b5f62a0
VZ
812 // Call dispatch at least once so that sockets
813 // can be tested
814 wxTheApp->Dispatch();
7c9955d1 815
bbcd408a
JS
816 while (wxTheApp && wxTheApp->Pending())
817 wxTheApp->Dispatch();
83df96d6 818
868741e9 819#if wxUSE_TIMER
bbcd408a 820 wxTimer::NotifyTimers();
868741e9 821#endif
bbcd408a 822 ProcessIdle();
868741e9 823
bbcd408a
JS
824 if (newEventLoop)
825 {
826 wxEventLoop::SetActive(NULL);
827 delete newEventLoop;
828 }
df0e1b64 829
bbcd408a
JS
830 s_inYield = FALSE;
831 }
83df96d6
JS
832
833 return TRUE;
834}
835
d715d419
VZ
836#ifdef __WXDEBUG__
837
5968a0dc 838void wxApp::OnAssert(const wxChar *file, int line, const wxChar* cond, const wxChar *msg)
7edcafa4
JS
839{
840 // While the GUI isn't working that well, just print out the
841 // message.
193e19cf 842#if 1
5968a0dc 843 wxAppBase::OnAssert(file, line, cond, msg);
7edcafa4
JS
844#else
845 wxString msg2;
846 msg2.Printf("At file %s:%d: %s", file, line, msg);
847 wxLogDebug(msg2);
848#endif
849}
850
d715d419
VZ
851#endif // __WXDEBUG__
852