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