]> git.saurik.com Git - wxWidgets.git/blobdiff - src/motif/window.cpp
wxUSE_THREADS in sckint.h; wxMotif Clone error fixed; JPEG makefile.unx for wxMotif
[wxWidgets.git] / src / motif / window.cpp
index 139f5cced43c91fa398dbb0551dcdc7c6e6b2165..620a925f4e36f1329a1665c38f65c860ffa2e9b4 100644 (file)
@@ -27,6 +27,7 @@
 #include "wx/settings.h"
 #include "wx/msgdlg.h"
 #include "wx/frame.h"
+#include "wx/scrolwin.h"
 
 #include "wx/menuitem.h"
 #include "wx/log.h"
@@ -85,6 +86,7 @@ END_EVENT_TABLE()
 wxWindow::wxWindow()
 {
     // Generic
+    m_isWindow = TRUE; // An optimization
     m_windowId = 0;
     m_windowStyle = 0;
     m_windowParent = NULL;
@@ -114,6 +116,7 @@ wxWindow::wxWindow()
     m_clientData = NULL;
     
     /// Motif-specific
+    m_needsRefresh = TRUE;
     m_mainWidget = (WXWidget) 0;
     m_button1Pressed = FALSE;
     m_button2Pressed = FALSE;
@@ -225,7 +228,11 @@ wxWindow::~wxWindow()
     // Destroy the window
     if (GetMainWidget())
     {
-        wxDeleteWindowFromTable((Widget) GetMainWidget());
+        // If this line (XtDestroyWidget) causes a crash, you may comment it out.
+        // Child widgets will get destroyed automatically when a frame
+        // or dialog is destroyed, but before that you may get some memory
+        // leaks and potential layout problems if you delete and then add
+        // child windows.
         XtDestroyWidget((Widget) GetMainWidget());
         SetMainWidget((WXWidget) NULL);
     }
@@ -259,6 +266,7 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id,
                       const wxString& name)
 {
     // Generic
+    m_isWindow = TRUE; // An optimization
     m_windowId = 0;
     m_windowStyle = 0;
     m_windowParent = NULL;
@@ -287,6 +295,7 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id,
     m_clientData = NULL;
     
     // Motif-specific
+    m_needsRefresh = TRUE;
     m_canAddEventHandler = FALSE;
     m_mainWidget = (WXWidget) 0;
     m_button1Pressed = FALSE;
@@ -740,7 +749,7 @@ void wxWindow::GetClientSize(int *x, int *y) const
     *x = xx; *y = yy;
 }
 
-void wxWindow::SetSize(int x, int y, int width, int height, int sizeFlags)
+void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags)
 {
     // A bit of optimization to help sort out the flickers.
     int oldX, oldY, oldW, oldH;
@@ -812,7 +821,7 @@ void wxWindow::SetSize(int x, int y, int width, int height, int sizeFlags)
     */
 }
 
-void wxWindow::SetClientSize(int width, int height)
+void wxWindow::DoSetClientSize(int width, int height)
 {
     if (m_drawingArea)
     {
@@ -983,6 +992,7 @@ void wxWindow::GetTextExtent(const wxString& string, int *x, int *y,
 
 void wxWindow::Refresh(bool eraseBack, const wxRect *rect)
 {
+    m_needsRefresh = TRUE;
     Display *display = XtDisplay((Widget) GetMainWidget());
     Window thisWindow = XtWindow((Widget) GetMainWidget());
     
@@ -1469,11 +1479,13 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
         delete rect;
         node = node->Next();
     }
-    
+
+    XmUpdateDisplay((Widget) GetMainWidget());
 }
 
 void wxWindow::OnChar(wxKeyEvent& event)
 {
+    event.Skip();
 /* ??
 if ( event.KeyCode() == WXK_TAB ) {
 // propagate the TABs to the parent - it's up to it to decide what
@@ -1488,12 +1500,12 @@ return;
 
 void wxWindow::OnKeyDown(wxKeyEvent& event)
 {
-    Default();
+    event.Skip();
 }
 
 void wxWindow::OnKeyUp(wxKeyEvent& event)
 {
-    Default();
+    event.Skip();
 }
 
 void wxWindow::OnPaint(wxPaintEvent& event)
@@ -1572,8 +1584,30 @@ bool wxWindow::Validate()
 // Get the window with the focus
 wxWindow *wxWindow::FindFocus()
 {
-    // TODO
-    return NULL;
+    // TODO Problems:
+    // (1) Can there be multiple focussed widgets in an application?
+    // In which case we need to find the top-level window that's
+    // currently active.
+    // (2) The widget with the focus may not be in the widget table
+    // depending on which widgets I put in the table
+
+    wxNode *node = wxTopLevelWindows.First();
+    while (node)
+    {
+        wxWindow *win = (wxWindow *)node->Data();
+
+        Widget w = XmGetFocusWidget ((Widget) win->GetTopWidget()) ;
+
+        if (w != (Widget) NULL)
+        {
+            wxWindow* focusWin = wxGetWindowFromTable(w);
+            if (focusWin)
+                return focusWin;
+        }
+
+        node = node->Next();
+    }
+    return (wxWindow*) NULL;
 }
 
 void wxWindow::AddChild(wxWindow *child)
@@ -2064,7 +2098,10 @@ bool wxWindow::Close(bool force)
 {
     wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
     event.SetEventObject(this);
+#if WXWIN_COMPATIBILITY
     event.SetForce(force);
+#endif
+    event.SetCanVeto(!force);
     
     return GetEventHandler()->ProcessEvent(event);
 }
@@ -2124,7 +2161,7 @@ void wxWindow::SetValidator(const wxValidator& validator)
 {
     if ( m_windowValidator )
         delete m_windowValidator;
-    m_windowValidator = validator.Clone();
+    m_windowValidator = (wxValidator*) validator.Clone();
     
     if ( m_windowValidator )
         m_windowValidator->SetWindow(this) ;
@@ -2294,12 +2331,18 @@ void wxDeleteWindowFromTable(Widget w)
 // Get the underlying X window and display
 WXWindow wxWindow::GetXWindow() const
 {
-    return (WXWindow) XtWindow((Widget) GetMainWidget());
+    if (GetMainWidget())
+        return (WXWindow) XtWindow((Widget) GetMainWidget());
+    else
+        return (WXWindow) 0;
 }
 
 WXDisplay *wxWindow::GetXDisplay() const
 {
-    return (WXDisplay*) XtDisplay((Widget) GetMainWidget());
+    if (GetMainWidget())
+        return (WXDisplay*) XtDisplay((Widget) GetMainWidget());
+    else
+        return (WXDisplay*) NULL;
 }
 
 WXWidget wxWindow::GetMainWidget() const
@@ -2348,10 +2391,13 @@ void wxCanvasRepaintProc (Widget drawingArea, XtPointer clientData,
             
             if (event -> xexpose.count == 0)
             {
+             /*
                 wxPaintEvent event(win->GetId());
                 event.SetEventObject(win);
                 win->GetEventHandler()->ProcessEvent(event);
+               */
                 
+                win->DoPaint();
                 win->ClearUpdateRects();
             }
             break;
@@ -2606,10 +2652,6 @@ void wxCanvasInputEvent (Widget drawingArea, XtPointer data, XmDrawingAreaCallba
 
             wxEventType eventType = wxEVT_CHAR;
 
-            // TODO: Is this the correct criterion for wxEVT_KEY_DOWN down versus wxEVT_CHAR?
-            if (id > WXK_START) // Non-ASCII values
-                eventType = wxEVT_KEY_DOWN;
-            
             wxKeyEvent event (eventType);
             
             if (local_event.xkey.state & ShiftMask)
@@ -2636,10 +2678,18 @@ void wxCanvasInputEvent (Widget drawingArea, XtPointer data, XmDrawingAreaCallba
                     event.SetEventType(wxEVT_CHAR_HOOK);
                     if (parent->GetEventHandler()->ProcessEvent(event))
                         return;
-                    event.SetEventType(wxEVT_CHAR);
                 }
-                
-                canvas->GetEventHandler()->ProcessEvent (event);
+
+                // For simplicity, OnKeyDown is the same as OnChar
+                // TODO: filter modifier key presses from OnChar
+                event.SetEventType(wxEVT_KEY_DOWN);
+
+                // Only process OnChar if OnKeyDown didn't swallow it
+                if (!canvas->GetEventHandler()->ProcessEvent (event))
+                {
+                  event.SetEventType(wxEVT_CHAR);
+                  canvas->GetEventHandler()->ProcessEvent (event);
+               }
             }
             break;
         }
@@ -2697,28 +2747,68 @@ void wxCanvasInputEvent (Widget drawingArea, XtPointer data, XmDrawingAreaCallba
 void wxWindow::DoPaint()
 {
     //TODO : make a temporary gc so we can do the XCopyArea below
-    if (0) // m_backingPixmap)
+    if (m_backingPixmap && !m_needsRefresh)
     {
-    /*
-    Widget drawingArea = (Widget) m_drawingArea;
-    //      int orig = GetDC()->GetLogicalFunction();
-    //      GetDC()->SetLogicalFunction (wxCOPY);
-    
-      // TODO: it may not be necessary to store m_pixmapOffsetX/Y; we
-      // should be able to calculate them.
-      XCopyArea (XtDisplay (drawingArea), m_backingPixmap, XtWindow (drawingArea), GetDC ()->gc,
-      m_pixmapOffsetX, m_pixmapOffsetY,
-      m_pixmapWidth, m_pixmapHeight,
-      0, 0);
-      
-        //      GetDC()->SetLogicalFunction (orig);
-        */
+      wxPaintDC dc(this);
+
+      GC tempGC = (GC) dc.GetBackingGC();
+
+      Widget widget = (Widget) GetMainWidget();
+
+      int scrollPosX = 0;
+      int scrollPosY = 0;
+
+      // We have to test whether it's a wxScrolledWindow (hack!)
+      // because otherwise we don't know how many pixels have been
+      // scrolled. We might solve this in the future by defining
+      // virtual wxWindow functions to get the scroll position in pixels.
+      // Or, each kind of scrolled window has to implement backing
+      // stores itself, using generic wxWindows code.
+      if (this->IsKindOf(CLASSINFO(wxScrolledWindow)))
+      {
+          wxScrolledWindow* scrolledWindow = (wxScrolledWindow*) this;
+          int x, y;
+          scrolledWindow->CalcScrolledPosition(0, 0, & x, & y);
+
+          scrollPosX = - x;
+          scrollPosY = - y;
+      }
+
+      // TODO: This could be optimized further by only copying the
+      // areas in the current update region.
+
+      // Only blit the part visible in the client area. The backing pixmap
+      // always starts at 0, 0 but we may be looking at only a portion of it.
+      wxSize clientArea = GetClientSize();
+      int toBlitX = m_pixmapWidth - scrollPosX;
+      int toBlitY = m_pixmapHeight - scrollPosY;
+
+      // Copy whichever is samller, the amount of pixmap we have to copy,
+      // or the size of the client area.
+      toBlitX = wxMin(toBlitX, clientArea.x);
+      toBlitY = wxMin(toBlitY, clientArea.y);
+
+      // Make sure we're not negative
+      toBlitX = wxMax(0, toBlitX);
+      toBlitY = wxMax(0, toBlitY);
+    
+      XCopyArea (XtDisplay (widget), (Pixmap) m_backingPixmap, XtWindow (widget), tempGC,
+        scrollPosX, scrollPosY, // Start at the scroll position
+        toBlitX, toBlitY,       // How much of the pixmap to copy
+        0, 0);                  // Destination
     }
     else
     {
+        // Set an erase event first
+        wxEraseEvent eraseEvent(GetId());
+        eraseEvent.SetEventObject(this);
+        GetEventHandler()->ProcessEvent(eraseEvent);
+
         wxPaintEvent event(GetId());
         event.SetEventObject(this);
         GetEventHandler()->ProcessEvent(event);
+
+        m_needsRefresh = FALSE;
     }
 }
 
@@ -3414,6 +3504,11 @@ void wxWindow::SetFont(const wxFont& font)
     ChangeFont();
 }
 
+void wxWindow::SetToolTip(const wxString& tooltip)
+{
+    // TODO
+}
+
 void wxWindow::ClearUpdateRects()
 {
     wxNode* node = m_updateRects.First();
@@ -3515,3 +3610,40 @@ bool wxNoOptimize::CanOptimize()
     return (m_count == 0);
 }
 
+// For repainting arbitrary windows
+void wxUniversalRepaintProc(Widget w, XtPointer WXUNUSED(c_data), XEvent *event, char *)
+{
+    Window window;
+    Display *display;
+    
+    wxWindow* win = (wxWindow *)wxWidgetHashTable->Get((long)w);
+    if (!win)
+        return;
+    
+    switch(event -> type)
+    {
+    case Expose :
+        {
+            window = (Window) win -> GetXWindow();
+            display = (Display *) win -> GetXDisplay();
+            
+            wxRect* rect = new wxRect(event->xexpose.x, event->xexpose.y,
+                event->xexpose.width, event->xexpose.height);
+            win->m_updateRects.Append((wxObject*) rect);
+            
+            if (event -> xexpose.count == 0)
+            {
+                win->DoPaint();
+                
+                win->ClearUpdateRects();
+            }
+            break;
+        }
+    default :
+        {
+            cout << "\n\nNew Event ! is = " << event -> type << "\n";
+            break;
+        }
+    }
+}
+