X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9691c806e6fbb08b01c9eec9998ad1e8242c7df3..cd72551c2b6cbf67a4a5caf0ba00ba64e41183b2:/src/x11/app.cpp diff --git a/src/x11/app.cpp b/src/x11/app.cpp index 39f1eb2d53..91b39edbb7 100644 --- a/src/x11/app.cpp +++ b/src/x11/app.cpp @@ -37,32 +37,37 @@ #include "wx/resource.h" #endif -#ifdef __VMS__ -#pragma message disable nosimpint -#endif -#include -#include -#include - -#ifdef __VMS__ -#pragma message enable nosimpint -#endif - #include "wx/x11/private.h" #include +//------------------------------------------------------------------------ +// global data +//------------------------------------------------------------------------ + extern wxList wxPendingDelete; +wxHashTable *wxWidgetHashTable = NULL; + wxApp *wxTheApp = NULL; -wxHashTable *wxWidgetHashTable = NULL; +// This is set within wxEntryStart -- too early on +// to put these in wxTheApp +static int g_newArgc = 0; +static wxChar** g_newArgv = NULL; +static bool g_showIconic = FALSE; +static wxSize g_initialSize = wxDefaultSize; -IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler) +// This is required for wxFocusEvent::SetWindow(). It will only +// work for focus events which we provoke ourselves (by calling +// SetFocus()). It will not work for those events, which X11 +// generates itself. +static wxWindow *g_nextFocus = NULL; +static wxWindow *g_prevFocus = NULL; -BEGIN_EVENT_TABLE(wxApp, wxEvtHandler) - EVT_IDLE(wxApp::OnIdle) -END_EVENT_TABLE() +//------------------------------------------------------------------------ +// X11 error handling +//------------------------------------------------------------------------ #ifdef __WXDEBUG__ typedef int (*XErrorHandlerFunc)(Display *, XErrorEvent *); @@ -79,15 +84,18 @@ static int wxXErrorHandler(Display *dpy, XErrorEvent *xevent) } #endif // __WXDEBUG__ +//------------------------------------------------------------------------ +// wxApp +//------------------------------------------------------------------------ + long wxApp::sm_lastMessageTime = 0; WXDisplay *wxApp::ms_display = NULL; -// This is set within wxEntryStart -- too early on -// to put these in wxTheApp -static int g_newArgc = 0; -static wxChar** g_newArgv = NULL; -static bool g_showIconic = FALSE; -static wxSize g_initialSize = wxDefaultSize; +IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler) + +BEGIN_EVENT_TABLE(wxApp, wxEvtHandler) + EVT_IDLE(wxApp::OnIdle) +END_EVENT_TABLE() bool wxApp::Initialize() { @@ -172,8 +180,10 @@ void wxApp::CleanUp() int wxEntryStart( int& argc, char *argv[] ) { #ifdef __WXDEBUG__ +#if !wxUSE_NANOX // install the X error handler gs_pfnXErrorHandler = XSetErrorHandler( wxXErrorHandler ); +#endif #endif // __WXDEBUG__ wxString displayName; @@ -403,7 +413,45 @@ int wxApp::MainLoop() return rt; } +#if !wxUSE_NANOX +//----------------------------------------------------------------------- +// X11 predicate function for exposure compression +//----------------------------------------------------------------------- + +struct wxExposeInfo +{ + Window window; + Bool found_non_matching; +}; + +static Bool expose_predicate (Display *display, XEvent *xevent, XPointer arg) +{ + wxExposeInfo *info = (wxExposeInfo*) arg; + + if (info->found_non_matching) + return FALSE; + + if (xevent->xany.type != Expose) + { + info->found_non_matching = TRUE; + return FALSE; + } + + if (xevent->xexpose.window != info->window) + { + info->found_non_matching = TRUE; + return FALSE; + } + + return TRUE; +} +#endif + // wxUSE_NANOX + +//----------------------------------------------------------------------- // Processes an X event. +//----------------------------------------------------------------------- + void wxApp::ProcessXEvent(WXEvent* _event) { XEvent* event = (XEvent*) _event; @@ -411,7 +459,7 @@ void wxApp::ProcessXEvent(WXEvent* _event) wxWindow* win = NULL; Window window = XEventGetWindow(event); Window actualWindow = window; - + // Find the first wxWindow that corresponds to this event window // Because we're receiving events after a window // has been destroyed, assume a 1:1 match between @@ -422,72 +470,66 @@ void wxApp::ProcessXEvent(WXEvent* _event) if (!win) return; +#ifdef __WXDEBUG__ + wxString windowClass = win->GetClassInfo()->GetClassName(); +#endif + switch (event->type) { case KeyPress: { - if (win && !win->IsEnabled()) + if (!win->IsEnabled()) return; - { - if (win) - { - wxKeyEvent keyEvent(wxEVT_KEY_DOWN); - wxTranslateKeyEvent(keyEvent, win, window, event); + wxKeyEvent keyEvent(wxEVT_KEY_DOWN); + wxTranslateKeyEvent(keyEvent, win, window, event); - // wxLogDebug( "OnKey from %s", win->GetName().c_str() ); + // wxLogDebug( "OnKey from %s", win->GetName().c_str() ); - // We didn't process wxEVT_KEY_DOWN, so send - // wxEVT_CHAR - if (!win->GetEventHandler()->ProcessEvent( keyEvent )) - { - keyEvent.SetEventType(wxEVT_CHAR); - win->GetEventHandler()->ProcessEvent( keyEvent ); - } - - // We intercepted and processed the key down event - return; - } + // We didn't process wxEVT_KEY_DOWN, so send + // wxEVT_CHAR + if (!win->GetEventHandler()->ProcessEvent( keyEvent )) + { + keyEvent.SetEventType(wxEVT_CHAR); + win->GetEventHandler()->ProcessEvent( keyEvent ); } return; } case KeyRelease: { - if (win && !win->IsEnabled()) + if (!win->IsEnabled()) return; - if (win) - { - wxKeyEvent keyEvent(wxEVT_KEY_UP); - wxTranslateKeyEvent(keyEvent, win, window, event); + wxKeyEvent keyEvent(wxEVT_KEY_UP); + wxTranslateKeyEvent(keyEvent, win, window, event); - win->GetEventHandler()->ProcessEvent( keyEvent ); - } + win->GetEventHandler()->ProcessEvent( keyEvent ); return; } case ConfigureNotify: { - if (win #if wxUSE_NANOX - && (event->update.utype == GR_UPDATE_SIZE) + if (event->update.utype == GR_UPDATE_SIZE) #endif - ) { + //wxLogDebug("ConfigureNotify: %s", windowClass.c_str()); wxSizeEvent sizeEvent( wxSize(XConfigureEventGetWidth(event), XConfigureEventGetHeight(event)), win->GetId() ); sizeEvent.SetEventObject( win ); win->GetEventHandler()->ProcessEvent( sizeEvent ); } + break; } #if !wxUSE_NANOX case PropertyNotify: { + //wxLogDebug("PropertyNotify: %s", windowClass.c_str()); HandlePropertyChange(_event); return; } case ClientMessage: { - if (win && !win->IsEnabled()) + if (!win->IsEnabled()) return; Atom wm_delete_window = XInternAtom(wxGlobalDisplay(), "WM_DELETE_WINDOW", True); @@ -497,10 +539,7 @@ void wxApp::ProcessXEvent(WXEvent* _event) { if ((Atom) (event->xclient.data.l[0]) == wm_delete_window) { - if (win) - { - win->Close(FALSE); - } + win->Close(FALSE); } } return; @@ -543,45 +582,50 @@ void wxApp::ProcessXEvent(WXEvent* _event) #endif case Expose: { - if (win) - { - win->GetUpdateRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event), - XExposeEventGetWidth(event), XExposeEventGetHeight(event)); + //wxLogDebug("Expose: %s", windowClass.c_str()); + win->GetUpdateRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event), + XExposeEventGetWidth(event), XExposeEventGetHeight(event)); - win->GetClearRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event), - XExposeEventGetWidth(event), XExposeEventGetHeight(event)); + win->GetClearRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event), + XExposeEventGetWidth(event), XExposeEventGetHeight(event)); + #if !wxUSE_NANOX - if (event->xexpose.count == 0) -#endif - { - // Only erase background, paint in idle time. - win->SendEraseEvents(); - } + XEvent tmp_event; + wxExposeInfo info; + info.window = event->xexpose.window; + info.found_non_matching = FALSE; + while (XCheckIfEvent( wxGlobalDisplay(), &tmp_event, expose_predicate, (XPointer) &info )) + { + win->GetUpdateRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y, + tmp_event.xexpose.width, tmp_event.xexpose.height ); + + win->GetClearRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y, + tmp_event.xexpose.width, tmp_event.xexpose.height ); } +#endif + + win->SendEraseEvents(); return; } #if !wxUSE_NANOX case GraphicsExpose: { - if (win) - { - // wxLogDebug( "GraphicsExpose from %s", win->GetName().c_str(), - // event->xgraphicsexpose.x, event->xgraphicsexpose.y, - // event->xgraphicsexpose.width, event->xgraphicsexpose.height); + // wxLogDebug( "GraphicsExpose from %s", win->GetName().c_str(), + // event->xgraphicsexpose.x, event->xgraphicsexpose.y, + // event->xgraphicsexpose.width, event->xgraphicsexpose.height); - win->GetUpdateRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y, - event->xgraphicsexpose.width, event->xgraphicsexpose.height); - - win->GetClearRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y, - event->xgraphicsexpose.width, event->xgraphicsexpose.height); + win->GetUpdateRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y, + event->xgraphicsexpose.width, event->xgraphicsexpose.height); + + win->GetClearRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y, + event->xgraphicsexpose.width, event->xgraphicsexpose.height); - if (event->xgraphicsexpose.count == 0) - { - // Only erase background, paint in idle time. - win->SendEraseEvents(); - } + if (event->xgraphicsexpose.count == 0) + { + // Only erase background, paint in idle time. + win->SendEraseEvents(); } return; @@ -593,9 +637,6 @@ void wxApp::ProcessXEvent(WXEvent* _event) case ButtonRelease: case MotionNotify: { - if (!win) - return; - if (!win->IsEnabled()) return; @@ -606,28 +647,48 @@ void wxApp::ProcessXEvent(WXEvent* _event) tlw = tlw->GetParent(); if (tlw && !tlw->IsEnabled()) return; - + if (event->type == ButtonPress) { if ((win != wxWindow::FindFocus()) && win->AcceptsFocus()) - win->SetFocus(); + { + // This might actually be done in wxWindow::SetFocus() + // and not here. TODO. + g_prevFocus = wxWindow::FindFocus(); + g_nextFocus = win; + + win->SetFocus(); + } } - + +#if !wxUSE_NANOX + if (event->type == LeaveNotify || event->type == EnterNotify) + { + // Throw out NotifyGrab and NotifyUngrab + if (event->xcrossing.mode != NotifyNormal) + return; + } +#endif wxMouseEvent wxevent; wxTranslateMouseEvent(wxevent, win, window, event); win->GetEventHandler()->ProcessEvent( wxevent ); + return; } case FocusIn: { #if !wxUSE_NANOX - if (win && event->xfocus.detail != NotifyPointer) + if ((event->xfocus.detail != NotifyPointer) && + (event->xfocus.mode == NotifyNormal)) #endif { - // wxLogDebug( "FocusIn from %s", win->GetName().c_str() ); + // wxLogDebug( "FocusIn from %s of type %s", win->GetName().c_str(), win->GetClassInfo()->GetClassName() ); wxFocusEvent focusEvent(wxEVT_SET_FOCUS, win->GetId()); focusEvent.SetEventObject(win); + focusEvent.SetWindow( g_prevFocus ); + g_prevFocus = NULL; + win->GetEventHandler()->ProcessEvent(focusEvent); } break; @@ -635,13 +696,16 @@ void wxApp::ProcessXEvent(WXEvent* _event) case FocusOut: { #if !wxUSE_NANOX - if (win && event->xfocus.detail != NotifyPointer) + if ((event->xfocus.detail != NotifyPointer) && + (event->xfocus.mode == NotifyNormal)) #endif { - // wxLogDebug( "FocusOut from %s", win->GetName().c_str() ); + // wxLogDebug( "FocusOut from %s of type %s", win->GetName().c_str(), win->GetClassInfo()->GetClassName() ); wxFocusEvent focusEvent(wxEVT_KILL_FOCUS, win->GetId()); focusEvent.SetEventObject(win); + focusEvent.SetWindow( g_nextFocus ); + g_nextFocus = NULL; win->GetEventHandler()->ProcessEvent(focusEvent); } break;