]> git.saurik.com Git - wxWidgets.git/blobdiff - src/x11/app.cpp
fixed menubar attaching: create it first, THEN set pointer to it
[wxWidgets.git] / src / x11 / app.cpp
index 8b019fdf6e64ab9c51d6ee1082329f777fefe230..c21c217a82574af1ce79911b25f5c88878ceecd0 100644 (file)
     #pragma implementation "app.h"
 #endif
 
-#ifdef __VMS
-#define XtParent XTPARENT
-#define XtDisplay XTDISPLAY
-#endif
-
 #include "wx/frame.h"
 #include "wx/app.h"
 #include "wx/utils.h"
@@ -26,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"
@@ -35,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"
@@ -47,7 +41,6 @@
 #ifdef __VMS__
 #pragma message disable nosimpint
 #endif
-#include <Xm/Xm.h>
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 #include <X11/Xresource.h>
@@ -56,7 +49,7 @@
 #pragma message enable nosimpint
 #endif
 
-#include "wx/motif/private.h"
+#include "wx/x11/private.h"
 
 #include <string.h>
 
@@ -74,15 +67,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;
@@ -109,15 +102,6 @@ bool wxApp::Initialize()
     wxInitializeResourceSystem();
 #endif
 
-    // For PostScript printing
-#if wxUSE_POSTSCRIPT
-    /* Done using wxModule now
-    wxInitializePrintSetupData();
-    wxThePrintPaperDatabase = new wxPrintPaperDatabase;
-    wxThePrintPaperDatabase->CreateDatabase();
-    */
-#endif
-
     wxBitmap::InitStandardHandlers();
 
     wxWidgetHashTable = new wxHashTable(wxKEY_INTEGER);
@@ -148,14 +132,6 @@ void wxApp::CleanUp()
     delete wxTheColourDatabase;
     wxTheColourDatabase = NULL;
 
-#if wxUSE_POSTSCRIPT
-    /* Done using wxModule now
-    wxInitializePrintSetupData(FALSE);
-    delete wxThePrintPaperDatabase;
-    wxThePrintPaperDatabase = NULL;
-    */
-#endif
-
     wxBitmap::CleanUpHandlers();
 
     delete[] wxBuffer;
@@ -278,12 +254,11 @@ wxApp::wxApp()
     argc = 0;
     argv = NULL;
     m_exitOnFrameDelete = TRUE;
-
     m_mainColormap = (WXColormap) NULL;
-    m_appContext = (WXAppContext) NULL;
-    m_topLevelWidget = (WXWidget) NULL;
+    m_topLevelWidget = (WXWindow) NULL;
     m_maxRequestSize = 0;
     m_initialDisplay = (WXDisplay*) 0;
+    m_mainLoop = NULL;
 }
 
 bool wxApp::Initialized()
@@ -296,45 +271,14 @@ 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(XtDisplay((Widget) wxTheApp->GetTopLevelWidget()),
-        XDefaultRootWindow(XtDisplay((Widget) wxTheApp->GetTopLevelWidget())),
-        PropertyChangeMask);
-
-    XEvent event;
-
-    // Use this flag to allow breaking the loop via wxApp::ExitMainLoop()
-    while (m_keepGoing)
-    {
-        XtAppNextEvent( (XtAppContext) wxTheApp->GetAppContext(), &event);
-
-        ProcessXEvent((WXEvent*) & event);
-
-        if (XtAppPending( (XtAppContext) wxTheApp->GetAppContext() ) == 0)
-        {
-            if (!ProcessIdle())
-            {
-#if wxUSE_THREADS
-                // leave the main loop to give other threads a chance to
-                // perform their GUI work
-                wxMutexGuiLeave();
-                wxUsleep(20);
-                wxMutexGuiEnter();
-#endif
-            }
-        }
-
-    }
-
-    return 0;
+    delete m_mainLoop;
+    m_mainLoop = NULL;
+    return rt;
 }
 
 // Processes an X event.
@@ -342,84 +286,193 @@ void wxApp::ProcessXEvent(WXEvent* _event)
 {
     XEvent* event = (XEvent*) _event;
 
-    if (event->type == KeyPress)
-    {
-#if 0 // def __WXDEBUG__
-        Widget widget = XtWindowToWidget(event->xany.display, event->xany.window);
-        wxLogDebug("Got key press event for 0x%08x (parent = 0x%08x)",
-                   widget, XtParent(widget));
-#endif // DEBUG
+    wxWindow* win = NULL;
+    Window window = event->xany.window;
+    Window actualWindow = window;
 
-    if (CheckForAccelerator(_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 = wxGetWindowParent(window);
+
+    // Because we're receiving events after a window
+    // has been destroyed, assume a 1:1 match between
+    // Window and wxWindow, so if it's not in the table,
+    // it must have been destroyed.
+
+    win = wxGetWindowFromTable(window);
+    if (!win)
+       return;
+
+    switch (event->type)
     {
-            // Do nothing! We intercepted and processed the event as an
-            // accelerator.
+        case KeyPress:
+        {
+            if (win && !win->IsEnabled())
+                return;
+
+            {
+                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;
-    }
-#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))
-    {
-            // We intercepted and processed the key down event
+        }
+        case KeyRelease:
+        {
+            if (win && !win->IsEnabled())
+                return;
+
+            if (win)
+            {
+                wxKeyEvent keyEvent(wxEVT_KEY_UP);
+                wxTranslateKeyEvent(keyEvent, win, window, event);
+        
+                win->GetEventHandler()->ProcessEvent( keyEvent );
+            }
             return;
-    }
-#endif
-    else
-    {
-            XtDispatchEvent(event);
-        return;
-    }
-    }
-    else if (event->type == KeyRelease)
-    {
-        // TODO: work out why we still need this !  -michael
-        //
-        if (CheckForKeyUp(_event))
-    {
-        // We intercepted and processed the key up event
-        return;
-    }
-    else
-    {
-        XtDispatchEvent(event);
-        return;
-    }
-    }
-    else if (event->type == PropertyNotify)
-    {
-        HandlePropertyChange(_event);
-        return;
-    }
-    else if (event->type == ResizeRequest)
-    {
-        /* Terry Gitnick <terryg@scientech.com> - 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.
-         */
+        }
+        case PropertyNotify:
+        {
+            HandlePropertyChange(_event);
+            return;
+        }
+        case ClientMessage:
+        {           
+            Atom wm_delete_window = XInternAtom(wxGlobalDisplay(), "WM_DELETE_WINDOW", True);;
+            Atom wm_protocols = XInternAtom(wxGlobalDisplay(), "WM_PROTOCOLS", True);;
 
-        Display *disp = XtDisplay((Widget) wxTheApp->GetTopLevelWidget());
-        Window win = event->xany.window;
-        XEvent report;
+            if (event->xclient.message_type == wm_protocols)
+            {
+                if ((Atom) (event->xclient.data.l[0]) == wm_delete_window)
+                {
+                    if (win)
+                    {
+                        win->Close(FALSE);
+                    }
+                }
+            }
+            return;
+        }
+        case ConfigureNotify:
+        {
+            if (win)
+            {
+                wxSizeEvent sizeEvent( wxSize(event->xconfigure.width,event->xconfigure.height), win->GetId() );
+                sizeEvent.SetEventObject( win );
+                
+                win->GetEventHandler()->ProcessEvent( sizeEvent );
+            }
+        }
+        case ResizeRequest:
+        {
+            /* Terry Gitnick <terryg@scientech.com> - 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);
 
-        //  to avoid flicker
-        report = * event;
-        while( XCheckTypedWindowEvent (disp, win, ResizeRequest, &report));
+                win->GetEventHandler()->ProcessEvent( sizeEvent );
+            }
 
-        // TODO: when implementing refresh optimization, we can use
-        // XtAddExposureToRegion to expand the window's paint region.
+            return;
+        }
+        case Expose:
+        {
+            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
+                }
+            }
 
-        XtDispatchEvent(event);
-    }
-    else
-    {
-        XtDispatchEvent(event);
+            return;
+        }
+        case EnterNotify:
+        case LeaveNotify:
+        case ButtonPress:
+        case ButtonRelease:
+        case MotionNotify:
+        {
+            if (win && !win->IsEnabled())
+                return;
+
+            if (win)
+            {
+                wxMouseEvent wxevent;
+                wxTranslateMouseEvent(wxevent, win, window, event);
+                win->GetEventHandler()->ProcessEvent( wxevent );
+            }
+            return;
+        }
+        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;
@@ -431,27 +484,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(XtDisplay( (Widget) wxTheApp->GetTopLevelWidget() ));
-
-    // Fix by Doug from STI, to prevent a stall if non-X event
-    // is found.
-    return ((XtAppPending( (XtAppContext) GetAppContext() ) & XtIMXEvent) != 0) ;
+    return wxEventLoop::GetActive()->Pending();
 }
 
 // Dispatch a message.
 void wxApp::Dispatch()
 {
-    //    XtAppProcessEvent( (XtAppContext) wxTheApp->GetAppContext(), XtIMAll);
-
-    XEvent event;
-    XtAppNextEvent((XtAppContext) GetAppContext(), &event);
-    ProcessXEvent((WXEvent*) & event);
+    wxEventLoop::GetActive()->Dispatch();
 }
 
 // This should be redefined in a derived class for
@@ -459,7 +505,8 @@ void wxApp::Dispatch()
 void wxApp::HandlePropertyChange(WXEvent *event)
 {
     // by default do nothing special
-    XtDispatchEvent((XEvent*) event); /* let Motif do the work */
+    // TODO: what to do for X11
+    // XtDispatchEvent((XEvent*) event); /* let Motif do the work */
 }
 
 void wxApp::OnIdle(wxIdleEvent& event)
@@ -570,40 +617,32 @@ void wxApp::DeletePendingObjects()
 // Create an application context
 bool wxApp::OnInitGui()
 {
-    XtToolkitInitialize() ;
-    wxTheApp->m_appContext = (WXAppContext) XtCreateApplicationContext() ;
-    Display *dpy = XtOpenDisplay((XtAppContext) wxTheApp->m_appContext,(String)NULL,NULL,
-        (const char*) wxTheApp->GetClassName(), NULL, 0,
-# if XtSpecificationRelease < 5
-        (Cardinal*) &argc,
-# else
-        &argc,
-# endif
-        argv);
+    // Eventually this line will be removed, but for
+    // now we don't want to try popping up a dialog
+    // for error messages.
+    delete wxLog::SetActiveTarget(new wxLogStderr);
+    if (!wxAppBase::OnInitGui())
+       return FALSE;
+    
+    // TODO: parse argv and get display to pass to XOpenDisplay
+    Display* dpy = XOpenDisplay(NULL);
+    m_initialDisplay = (WXDisplay*) dpy;
 
     if (!dpy) {
         wxString className(wxTheApp->GetClassName());
         wxLogError(_("wxWindows could not open display for '%s': exiting."),
-                   (const char*) className);
+            (const char*) className);
         exit(-1);
     }
-    m_initialDisplay = (WXDisplay*) dpy;
+    XSelectInput((Display*) m_initialDisplay,
+        XDefaultRootWindow((Display*) m_initialDisplay),
+        PropertyChangeMask);
 
 #ifdef __WXDEBUG__
     // install the X error handler
     gs_pfnXErrorHandler = XSetErrorHandler(wxXErrorHandler);
 #endif // __WXDEBUG__
 
-    wxTheApp->m_topLevelWidget = (WXWidget) XtAppCreateShell((String)NULL, (const char*) wxTheApp->GetClassName(),
-        applicationShellWidgetClass,dpy,
-        NULL,0) ;
-
-    // Add general resize proc
-    XtActionsRec rec;
-    rec.string = "resize";
-    rec.proc = (XtActionProc)wxWidgetResizeProc;
-    XtAppAddActions((XtAppContext) wxTheApp->m_appContext, &rec, 1);
-
     GetMainColormap(dpy);
     m_maxRequestSize = XMaxRequestSize((Display*) dpy);
 
@@ -626,89 +665,19 @@ WXColormap wxApp::GetMainColormap(WXDisplay* display)
     return (WXColormap) c;
 }
 
-// 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
-        Widget widget = XtWindowToWidget((Display*) wxGetDisplay(), xEvent->xany.window);
-        wxWindow* win = NULL;
-
-        // Find the first wxWindow that corresponds to this event window
-        while (widget && !(win = wxGetWindowFromTable(widget)))
-            widget = XtParent(widget);
-
-        if (!widget || !win)
-            return FALSE;
-
-        wxKeyEvent keyEvent(wxEVT_CHAR);
-        wxTranslateKeyEvent(keyEvent, win, (Widget) 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)
-    {
-        Widget widget = XtWindowToWidget((Display*) wxGetDisplay(),
-                     xEvent->xany.window);
-    wxWindow* win = NULL;
-
-    // Find the first wxWindow that corresponds to this event window
-    while (widget && !(win = wxGetWindowFromTable(widget)))
-            widget = XtParent(widget);
-
-    if (!widget || !win)
-            return FALSE;
-
-    wxKeyEvent keyEvent(wxEVT_KEY_DOWN);
-    wxTranslateKeyEvent(keyEvent, win, (Widget) 0, xEvent);
-
-    return win->ProcessEvent( keyEvent );
-    }
-
-    return FALSE;
-}
-
-bool wxApp::CheckForKeyUp(WXEvent* event)
+Window wxGetWindowParent(Window window)
 {
-    XEvent* xEvent = (XEvent*) event;
-    if (xEvent->xany.type == KeyRelease)
-    {
-        Widget widget = XtWindowToWidget((Display*) wxGetDisplay(),
-                         xEvent->xany.window);
-        wxWindow* win = NULL;
-
-        // Find the first wxWindow that corresponds to this event window
-        while (widget && !(win = wxGetWindowFromTable(widget)))
-                widget = XtParent(widget);
-
-        if (!widget || !win)
-                return FALSE;
-
-        wxKeyEvent keyEvent(wxEVT_KEY_UP);
-        wxTranslateKeyEvent(keyEvent, win, (Widget) 0, xEvent);
-
-        return win->ProcessEvent( keyEvent );
-    }
-
-    return FALSE;
+    Window parent, root = 0;
+    unsigned int noChildren = 0;
+    Window* children = NULL;
+    int res = XQueryTree((Display*) wxGetDisplay(), window, & root, & parent,
+                        & children, & noChildren);
+    if (children)
+        XFree(children);
+    if (res)
+        return parent;
+    else
+        return (Window) 0;
 }
 
 void wxExit()
@@ -790,7 +759,9 @@ wxApp::GetStdIcon(int which) const
 // accessors for C modules
 // ----------------------------------------------------------------------------
 
+#if 0
 extern "C" XtAppContext wxGetAppContext()
 {
     return (XtAppContext)wxTheApp->GetAppContext();
 }
+#endif