X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/887dd52f06a985ec0455e91f4b3d2b091a1b1c7b..cd560c961a09a8ae80b9c32856e195ed784cc547:/src/x11/app.cpp?ds=sidebyside diff --git a/src/x11/app.cpp b/src/x11/app.cpp index d45ff95d4a..34416b4f9b 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 *); @@ -72,19 +77,25 @@ XErrorHandlerFunc gs_pfnXErrorHandler = 0; static int wxXErrorHandler(Display *dpy, XErrorEvent *xevent) { // just forward to the default handler for now - return gs_pfnXErrorHandler(dpy, xevent); + if (gs_pfnXErrorHandler) + return gs_pfnXErrorHandler(dpy, xevent); + else + return 0; } #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() { @@ -169,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; @@ -230,11 +243,11 @@ int wxEntryStart( int& argc, char *argv[] ) g_newArgc ++; } - Display* xdisplay; + Display* xdisplay = NULL; if (displayName.IsEmpty()) xdisplay = XOpenDisplay(NULL); else - xdisplay = XOpenDisplay(displayName); + xdisplay = XOpenDisplay((char*) displayName.c_str()); if (!xdisplay) { @@ -390,7 +403,7 @@ bool wxApp::Initialized() int wxApp::MainLoop() { - int rt; + int rt; m_mainLoop = new wxEventLoop; rt = m_mainLoop->Run(); @@ -400,15 +413,53 @@ int wxApp::MainLoop() return rt; } -// Processes an X event. -void wxApp::ProcessXEvent(WXEvent* _event) +#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, returning TRUE if the event was processed. +//----------------------------------------------------------------------- + +bool wxApp::ProcessXEvent(WXEvent* _event) { XEvent* event = (XEvent*) _event; wxWindow* win = NULL; - Window window = event->xany.window; + 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 @@ -417,72 +468,69 @@ void wxApp::ProcessXEvent(WXEvent* _event) win = wxGetWindowFromTable(window); if (!win) - return; + return FALSE; +#ifdef __WXDEBUG__ + wxString windowClass = win->GetClassInfo()->GetClassName(); +#endif + switch (event->type) { case KeyPress: { - if (win && !win->IsEnabled()) - return; + if (!win->IsEnabled()) + return FALSE; - { - 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); + if (!win->GetEventHandler()->ProcessEvent( keyEvent )) + return FALSE; } - return; + return TRUE; } case KeyRelease: { - if (win && !win->IsEnabled()) - return; + if (!win->IsEnabled()) + return FALSE; - 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 ); - } - return; + return win->GetEventHandler()->ProcessEvent( keyEvent ); } case ConfigureNotify: { - // Not clear if this is the same in NanoX - if (win) +#if wxUSE_NANOX + if (event->update.utype == GR_UPDATE_SIZE) +#endif { - wxSizeEvent sizeEvent( wxSize(event->xconfigure.width,event->xconfigure.height), win->GetId() ); + //wxLogDebug("ConfigureNotify: %s", windowClass.c_str()); + wxSizeEvent sizeEvent( wxSize(XConfigureEventGetWidth(event), XConfigureEventGetHeight(event)), win->GetId() ); sizeEvent.SetEventObject( win ); - win->GetEventHandler()->ProcessEvent( sizeEvent ); + return win->GetEventHandler()->ProcessEvent( sizeEvent ); } + return FALSE; + break; } #if !wxUSE_NANOX case PropertyNotify: { - HandlePropertyChange(_event); - return; + //wxLogDebug("PropertyNotify: %s", windowClass.c_str()); + return HandlePropertyChange(_event); } case ClientMessage: { - if (win && !win->IsEnabled()) - return; + if (!win->IsEnabled()) + return FALSE; Atom wm_delete_window = XInternAtom(wxGlobalDisplay(), "WM_DELETE_WINDOW", True); Atom wm_protocols = XInternAtom(wxGlobalDisplay(), "WM_PROTOCOLS", True); @@ -491,13 +539,11 @@ void wxApp::ProcessXEvent(WXEvent* _event) { if ((Atom) (event->xclient.data.l[0]) == wm_delete_window) { - if (win) - { - win->Close(FALSE); - } + win->Close(FALSE); + return TRUE; } } - return; + return FALSE; } case ResizeRequest: { @@ -519,10 +565,10 @@ void wxApp::ProcessXEvent(WXEvent* _event) wxSizeEvent sizeEvent(sz, win->GetId()); sizeEvent.SetEventObject(win); - win->GetEventHandler()->ProcessEvent( sizeEvent ); + return win->GetEventHandler()->ProcessEvent( sizeEvent ); } - return; + return FALSE; } #endif #if wxUSE_NANOX @@ -531,120 +577,163 @@ void wxApp::ProcessXEvent(WXEvent* _event) if (win) { win->Close(FALSE); + return TRUE; } + return FALSE; break; } #endif case Expose: { - if (win) + //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)); + + +#if !wxUSE_NANOX + 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( event->xexpose.x, event->xexpose.y, - event->xexpose.width, event->xexpose.height); + win->GetUpdateRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y, + tmp_event.xexpose.width, tmp_event.xexpose.height ); - win->GetClearRegion().Union( event->xexpose.x, event->xexpose.y, - event->xexpose.width, event->xexpose.height); - - if (event->xexpose.count == 0) - { - // Only erase background, paint in idle time. - win->SendEraseEvents(); - } + win->GetClearRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y, + tmp_event.xexpose.width, tmp_event.xexpose.height ); } +#endif + + win->SendEraseEvents(); - return; + return TRUE; } +#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; + return TRUE; } +#endif case EnterNotify: case LeaveNotify: case ButtonPress: case ButtonRelease: case MotionNotify: { - if (!win) - return; - if (!win->IsEnabled()) - return; - -#if 1 + return FALSE; + + // Here we check if the top level window is + // disabled, which is one aspect of modality. + wxWindow *tlw = win; + while (tlw && !tlw->IsTopLevel()) + tlw = tlw->GetParent(); + if (tlw && !tlw->IsEnabled()) + return FALSE; + 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(); + // return TRUE; + } + } + +#if !wxUSE_NANOX + if (event->type == LeaveNotify || event->type == EnterNotify) + { + // Throw out NotifyGrab and NotifyUngrab + if (event->xcrossing.mode != NotifyNormal) + return FALSE; } #endif - wxMouseEvent wxevent; wxTranslateMouseEvent(wxevent, win, window, event); - win->GetEventHandler()->ProcessEvent( wxevent ); - return; + return win->GetEventHandler()->ProcessEvent( wxevent ); } 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); - win->GetEventHandler()->ProcessEvent(focusEvent); + focusEvent.SetWindow( g_prevFocus ); + g_prevFocus = NULL; + + return win->GetEventHandler()->ProcessEvent(focusEvent); } + return FALSE; break; } 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); - win->GetEventHandler()->ProcessEvent(focusEvent); + focusEvent.SetWindow( g_nextFocus ); + g_nextFocus = NULL; + return win->GetEventHandler()->ProcessEvent(focusEvent); } + return FALSE; break; } - case DestroyNotify: +#ifndef wxUSE_NANOX + case DestroyNotify: { // Do we want to process this (for top-level windows)? // But we want to be able to veto closes, anyway + return FALSE; break; } +#endif default: { #ifdef __WXDEBUG__ //wxString eventName = wxGetXEventName(XEvent& event); //wxLogDebug(wxT("Event %s not handled"), eventName.c_str()); #endif + return FALSE; break; } } + return FALSE; } // Returns TRUE if more time is needed. @@ -679,11 +768,12 @@ void wxApp::Dispatch() // This should be redefined in a derived class for // handling property change events for XAtom IPC. -void wxApp::HandlePropertyChange(WXEvent *event) +bool wxApp::HandlePropertyChange(WXEvent *event) { // by default do nothing special // TODO: what to do for X11 // XtDispatchEvent((XEvent*) event); + return FALSE; } void wxApp::OnIdle(wxIdleEvent& event) @@ -791,7 +881,7 @@ bool wxApp::OnInitGui() delete wxLog::SetActiveTarget(new wxLogStderr); if (!wxAppBase::OnInitGui()) - return FALSE; + return FALSE; GetMainColormap( wxApp::GetDisplay() ); @@ -823,10 +913,20 @@ Window wxGetWindowParent(Window window) return (Window) 0; Window parent, root = 0; +#if wxUSE_NANOX + int noChildren = 0; +#else unsigned int noChildren = 0; +#endif Window* children = NULL; - int res = XQueryTree((Display*) wxGetDisplay(), window, & root, & parent, - & children, & noChildren); + + // #define XQueryTree(d,w,r,p,c,nc) GrQueryTree(w,p,c,nc) + int res = 1; +#if !wxUSE_NANOX + res = +#endif + XQueryTree((Display*) wxGetDisplay(), window, & root, & parent, + & children, & noChildren); if (children) XFree(children); if (res)