X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/eb90fb3ee8cbfa859907e3561caa456924556acf..cd72551c2b6cbf67a4a5caf0ba00ba64e41183b2:/src/x11/app.cpp?ds=sidebyside diff --git a/src/x11/app.cpp b/src/x11/app.cpp index 21eff48925..91b39edbb7 100644 --- a/src/x11/app.cpp +++ b/src/x11/app.cpp @@ -26,6 +26,9 @@ #include "wx/intl.h" #include "wx/evtloop.h" +#include "wx/univ/theme.h" +#include "wx/univ/renderer.h" + #if wxUSE_THREADS #include "wx/thread.h" #endif @@ -34,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 *); @@ -69,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() { @@ -166,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; @@ -227,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) { @@ -248,7 +264,7 @@ int wxEntryStart( int& argc, char *argv[] ) XSelectInput( xdisplay, XDefaultRootWindow(xdisplay), PropertyChangeMask); -// wxSetDetectableAutoRepeat( TRUE ); + wxSetDetectableAutoRepeat( TRUE ); if (!wxApp::Initialize()) return -1; @@ -397,13 +413,51 @@ 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; 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 @@ -416,82 +470,76 @@ 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: { - // 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 ); } + 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);; - Atom wm_protocols = XInternAtom(wxGlobalDisplay(), "WM_PROTOCOLS", True);; + Atom wm_delete_window = XInternAtom(wxGlobalDisplay(), "WM_DELETE_WINDOW", True); + Atom wm_protocols = XInternAtom(wxGlobalDisplay(), "WM_PROTOCOLS", True); if (event->xclient.message_type == wm_protocols) { if ((Atom) (event->xclient.data.l[0]) == wm_delete_window) { - if (win) - { - win->Close(FALSE); - } + win->Close(FALSE); } } return; @@ -534,47 +582,113 @@ void wxApp::ProcessXEvent(WXEvent* _event) #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); + 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: + { + // 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); - // if (event->xexpose.count == 0) - // win->Update(); + if (event->xgraphicsexpose.count == 0) + { + // Only erase background, paint in idle time. + win->SendEraseEvents(); } return; } +#endif case EnterNotify: case LeaveNotify: case ButtonPress: case ButtonRelease: case MotionNotify: { - if (win && !win->IsEnabled()) + if (!win->IsEnabled()) return; - - if (win) + + // 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; + + if (event->type == ButtonPress) { - wxMouseEvent wxevent; - wxTranslateMouseEvent(wxevent, win, window, event); - win->GetEventHandler()->ProcessEvent( wxevent ); + if ((win != wxWindow::FindFocus()) && win->AcceptsFocus()) + { + // 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; @@ -582,23 +696,28 @@ 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\n", 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; } - 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 break; } +#endif default: { #ifdef __WXDEBUG__ @@ -786,9 +905,19 @@ 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, + + // #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); @@ -838,37 +967,9 @@ bool wxApp::Yield(bool onlyIfNeeded) return TRUE; } -// XPM hack: make the arrays const -#define static static const - -#include "wx/generic/info.xpm" -#include "wx/generic/error.xpm" -#include "wx/generic/question.xpm" -#include "wx/generic/warning.xpm" - -#undef static - -wxIcon -wxApp::GetStdIcon(int which) const +wxIcon wxApp::GetStdIcon(int which) const { - switch(which) - { - case wxICON_INFORMATION: - return wxIcon(info_xpm); - - case wxICON_QUESTION: - return wxIcon(question_xpm); - - case wxICON_EXCLAMATION: - return wxIcon(warning_xpm); - - default: - wxFAIL_MSG("requested non existent standard icon"); - // still fall through - - case wxICON_HAND: - return wxIcon(error_xpm); - } + return wxTheme::Get()->GetRenderer()->GetStdIcon(which); } void wxApp::OnAssert(const wxChar *file, int line, const wxChar *msg)