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