X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7eaac9f513554791e1219c7062657624a8a91026..6feddea302d401adad1a97796675f8737d3b9d23:/src/x11/app.cpp diff --git a/src/x11/app.cpp b/src/x11/app.cpp index 7929a5e6ca..ebcb2d9da1 100644 --- a/src/x11/app.cpp +++ b/src/x11/app.cpp @@ -21,8 +21,6 @@ #include "wx/brush.h" #include "wx/cursor.h" #include "wx/icon.h" -#include "wx/palette.h" -#include "wx/dc.h" #include "wx/dialog.h" #include "wx/msgdlg.h" #include "wx/log.h" @@ -30,6 +28,7 @@ #include "wx/memory.h" #include "wx/log.h" #include "wx/intl.h" +#include "wx/evtloop.h" #if wxUSE_THREADS #include "wx/thread.h" @@ -61,6 +60,8 @@ wxApp *wxTheApp = NULL; wxHashTable *wxWidgetHashTable = NULL; +static Window wxGetParentWindow(Window window); + IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler) BEGIN_EVENT_TABLE(wxApp, wxEvtHandler) @@ -68,15 +69,15 @@ BEGIN_EVENT_TABLE(wxApp, wxEvtHandler) END_EVENT_TABLE() #ifdef __WXDEBUG__ - typedef int (*XErrorHandlerFunc)(Display *, XErrorEvent *); +typedef int (*XErrorHandlerFunc)(Display *, XErrorEvent *); - XErrorHandlerFunc gs_pfnXErrorHandler = 0; +XErrorHandlerFunc gs_pfnXErrorHandler = 0; - static int wxXErrorHandler(Display *dpy, XErrorEvent *xevent) - { - // just forward to the default handler for now - return gs_pfnXErrorHandler(dpy, xevent); - } +static int wxXErrorHandler(Display *dpy, XErrorEvent *xevent) +{ + // just forward to the default handler for now + return gs_pfnXErrorHandler(dpy, xevent); +} #endif // __WXDEBUG__ long wxApp::sm_lastMessageTime = 0; @@ -259,6 +260,7 @@ wxApp::wxApp() m_topLevelWidget = (WXWindow) NULL; m_maxRequestSize = 0; m_initialDisplay = (WXDisplay*) 0; + m_mainLoop = NULL; } bool wxApp::Initialized() @@ -271,131 +273,191 @@ bool wxApp::Initialized() int wxApp::MainLoop() { - m_keepGoing = TRUE; + int rt; + m_mainLoop = new wxEventLoop; - /* - * Sit around forever waiting to process X-events. Property Change - * event are handled special, because they have to refer to - * the root window rather than to a widget. therefore we can't - * use an Xt-eventhandler. - */ + rt = m_mainLoop->Run(); - XSelectInput(wxGetDisplay(), - XDefaultRootWindow(wxGetDisplay()), - PropertyChangeMask); + delete m_mainLoop; + m_mainLoop = NULL; + return rt; +} - XEvent event; +// Processes an X event. +void wxApp::ProcessXEvent(WXEvent* _event) +{ + XEvent* event = (XEvent*) _event; - // Use this flag to allow breaking the loop via wxApp::ExitMainLoop() - while (m_keepGoing) - { - XNextEvent(wxGetDisplay(), & event); + wxWindow* win = NULL; + Window window = event->xany.window; + Window actualWindow = window; - ProcessXEvent((WXEvent*) & event); + // Find the first wxWindow that corresponds to this event window + // TODO: may need to translate coordinates from actualWindow + // to window, if the receiving window != wxWindow window + while (window && !(win = wxGetWindowFromTable(window))) + window = wxGetParentWindow(window); - if (XtPending(wxGetDisplay()) == 0) + // TODO: shouldn't all the ProcessEvents below + // be win->GetEventHandler()->ProcessEvent? + switch (event->type) + { + case KeyPress: { - if (!ProcessIdle()) + if (win && !win->IsEnabled()) + return; + { -#if wxUSE_THREADS - // leave the main loop to give other threads a chance to - // perform their GUI work - wxMutexGuiLeave(); - wxUsleep(20); - wxMutexGuiEnter(); -#endif + if (win) + { + wxKeyEvent keyEvent(wxEVT_KEY_DOWN); + wxTranslateKeyEvent(keyEvent, win, window, event); + + // 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; + } } + return; } - - } - - return 0; -} - -// Processes an X event. -void wxApp::ProcessXEvent(WXEvent* _event) -{ - XEvent* event = (XEvent*) _event; - - if (event->type == KeyPress) - { - if (CheckForAccelerator(_event)) + case KeyRelease: { - // Do nothing! We intercepted and processed the event as an - // accelerator. + if (win && !win->IsEnabled()) + return; + + if (win) + { + wxKeyEvent keyEvent(wxEVT_KEY_UP); + wxTranslateKeyEvent(keyEvent, win, window, event); + + win->GetEventHandler()->ProcessEvent( keyEvent ); + } return; } -#if 1 - // It seemed before that this hack was redundant and - // key down events were being generated by wxCanvasInputEvent. - // But no longer - why ??? - // - else if (CheckForKeyDown(_event)) + case PropertyNotify: { - // We intercepted and processed the key down event + HandlePropertyChange(_event); return; } -#endif - else + case ClientMessage: + { + 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 (event->xclient.data.l[0] == wm_delete_window) + { + if (win) + { + win->Close(FALSE); + } + } + } + return; + } + case ResizeRequest: { - // TODO for X11 implementation -- the equivalent of XtDispatchEvent. - // Presumably, we need to form the wxEvents and - // and send them to the appropriate windows. - // XtDispatchEvent(event); + /* Terry Gitnick - 1/21/98 + * If resize event, don't resize until the last resize event for this + * window is recieved. Prevents flicker as windows are resized. + */ + + Display *disp = (Display*) wxGetDisplay(); + XEvent report; + + // to avoid flicker + report = * event; + while( XCheckTypedWindowEvent (disp, actualWindow, ResizeRequest, &report)); + + // TODO: when implementing refresh optimization, we can use + // XtAddExposureToRegion to expand the window's paint region. + + if (win) + { + wxSize sz = win->GetSize(); + wxSizeEvent sizeEvent(sz, win->GetId()); + sizeEvent.SetEventObject(win); + + win->GetEventHandler()->ProcessEvent( sizeEvent ); + } + return; } - } - else if (event->type == KeyRelease) - { - // TODO: work out why we still need this ! -michael - // - if (CheckForKeyUp(_event)) + case Expose: { - // We intercepted and processed the key up event + if (win) + { + win->GetUpdateRegion().Union( event->xexpose.x, event->xexpose.y, + event->xexpose.width, event->xexpose.height); + if (event->xexpose.count == 0) + { + win->X11SendPaintEvents(); // TODO let an idle handler do that + } + } + return; } - else + case EnterNotify: + case LeaveNotify: + case ButtonPress: + case ButtonRelease: + case MotionNotify: { - // TODO: The X equivalent of XtDispatchEvent - // (see above) - // XtDispatchEvent(event); + if (win && !win->IsEnabled()) + return; + + if (win) + { + wxMouseEvent wxevent; + wxTranslateMouseEvent(wxevent, win, window, event); + win->GetEventHandler()->ProcessEvent( wxevent ); + } return; } - } - else if (event->type == PropertyNotify) - { - HandlePropertyChange(_event); - return; - } - else if (event->type == ResizeRequest) - { - /* Terry Gitnick - 1/21/98 - * If resize event, don't resize until the last resize event for this - * window is recieved. Prevents flicker as windows are resized. - */ - - Display *disp = wxGetDisplay(); - Window win = event->xany.window; - XEvent report; - - // to avoid flicker - report = * event; - while( XCheckTypedWindowEvent (disp, win, ResizeRequest, &report)); - - // TODO: when implementing refresh optimization, we can use - // XtAddExposureToRegion to expand the window's paint region. - - // TODO: generate resize event - // XtDispatchEvent(event); - } - else - { - // TODO: generate all other events - // XtDispatchEvent(event); + case FocusIn: + { + if (win && event->xfocus.detail != NotifyPointer) + { + wxFocusEvent focusEvent(wxEVT_SET_FOCUS, win->GetId()); + focusEvent.SetEventObject(win); + win->GetEventHandler()->ProcessEvent(focusEvent); + } + break; + } + case FocusOut: + { + if (win && event->xfocus.detail != NotifyPointer) + { + wxFocusEvent focusEvent(wxEVT_KILL_FOCUS, win->GetId()); + focusEvent.SetEventObject(win); + win->GetEventHandler()->ProcessEvent(focusEvent); + } + break; + } + case DestroyNotify: + { + // Do we want to process this (for top-level windows)? + // But we want to be able to veto closes, anyway + break; + } + default: + { + break; + } } } // Returns TRUE if more time is needed. +// Note that this duplicates wxEventLoopImpl::SendIdleEvent +// but ProcessIdle may be needed by apps, so is kept. bool wxApp::ProcessIdle() { wxIdleEvent event; @@ -407,23 +469,20 @@ bool wxApp::ProcessIdle() void wxApp::ExitMainLoop() { - m_keepGoing = FALSE; + if (m_mainLoop) + m_mainLoop->Exit(0); } // Is a message/event pending? bool wxApp::Pending() { - XFlush(wxGetDisplay()); - - return (XPending(wxGetDisplay()) > 0); + return wxEventLoop::GetActive()->Pending(); } // Dispatch a message. void wxApp::Dispatch() { - XEvent event; - XNextEvent(wxGetDisplay(), & event); - ProcessXEvent((WXEvent*) & event); + wxEventLoop::GetActive()->Dispatch(); } // This should be redefined in a derived class for @@ -553,19 +612,15 @@ bool wxApp::OnInitGui() (const char*) className); exit(-1); } + XSelectInput((Display*) m_initialDisplay, + XDefaultRootWindow((Display*) m_initialDisplay), + PropertyChangeMask); #ifdef __WXDEBUG__ // install the X error handler gs_pfnXErrorHandler = XSetErrorHandler(wxXErrorHandler); #endif // __WXDEBUG__ - // Do we need to create the top-level window initially? -#if 0 - wxTheApp->m_topLevelWidget = (WXWidget) XtAppCreateShell((String)NULL, (const char*) wxTheApp->GetClassName(), - applicationShellWidgetClass,dpy, - NULL,0) ; -#endif - GetMainColormap(dpy); m_maxRequestSize = XMaxRequestSize((Display*) dpy); @@ -588,100 +643,17 @@ WXColormap wxApp::GetMainColormap(WXDisplay* display) return (WXColormap) c; } -static Window XGetParent(Window window) +Window wxGetParentWindow(Window window) { Window parent, root = 0; unsigned int noChildren = 0; - if (XQueryTree(wxGetDisplay(), window, & root, & parent, + if (XQueryTree((Display*) wxGetDisplay(), window, & root, & parent, NULL, & noChildren)) return parent; else return (Window) 0; } -// Returns TRUE if an accelerator has been processed -bool wxApp::CheckForAccelerator(WXEvent* event) -{ - XEvent* xEvent = (XEvent*) event; - if (xEvent->xany.type == KeyPress) - { - // Find a wxWindow for this window - // TODO: should get display for the window, not the current display - Window window = xEvent->xany.window; - wxWindow* win = NULL; - - // Find the first wxWindow that corresponds to this event window - while (window && !(win = wxGetWindowFromTable(window))) - window = XGetParent(window); - - if (!window || !win) - return FALSE; - - wxKeyEvent keyEvent(wxEVT_CHAR); - wxTranslateKeyEvent(keyEvent, win, (Window) 0, xEvent); - - // Now we have a wxKeyEvent and we have a wxWindow. - // Go up the hierarchy until we find a matching accelerator, - // or we get to the top. - while (win) - { - if (win->ProcessAccelerator(keyEvent)) - return TRUE; - win = win->GetParent(); - } - return FALSE; - } - return FALSE; -} - -bool wxApp::CheckForKeyDown(WXEvent* event) -{ - XEvent* xEvent = (XEvent*) event; - if (xEvent->xany.type == KeyPress) - { - Window window = xEvent->xany.window; - wxWindow* win = NULL; - - // Find the first wxWindow that corresponds to this event window - while (window && !(win = wxGetWindowFromTable(window))) - window = XGetParent(window); - - if (!window || !win) - return FALSE; - - wxKeyEvent keyEvent(wxEVT_KEY_DOWN); - wxTranslateKeyEvent(keyEvent, win, (Window) 0, xEvent); - - return win->ProcessEvent( keyEvent ); - } - - return FALSE; -} - -bool wxApp::CheckForKeyUp(WXEvent* event) -{ - XEvent* xEvent = (XEvent*) event; - if (xEvent->xany.type == KeyRelease) - { - Window window = xEvent->xany.window; - wxWindow* win = NULL; - - // Find the first wxWindow that corresponds to this event window - while (window && !(win = wxGetWindowFromTable(window))) - window = XGetParent(window); - - if (!window || !win) - return FALSE; - - wxKeyEvent keyEvent(wxEVT_KEY_UP); - wxTranslateKeyEvent(keyEvent, win, (Window) 0, xEvent); - - return win->ProcessEvent( keyEvent ); - } - - return FALSE; -} - void wxExit() { int retValue = 0; @@ -766,4 +738,4 @@ extern "C" XtAppContext wxGetAppContext() { return (XtAppContext)wxTheApp->GetAppContext(); } -#endif \ No newline at end of file +#endif