X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1f916a19f14ce4f8d172f81344dd2b978dd29340..7ef156f79756492ef0955869c017db1f34d3eac1:/src/motif/window.cpp diff --git a/src/motif/window.cpp b/src/motif/window.cpp index e654d4aad0..2642297fd9 100644 --- a/src/motif/window.cpp +++ b/src/motif/window.cpp @@ -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; @@ -142,14 +145,6 @@ wxWindow::wxWindow() // Destructor wxWindow::~wxWindow() { - // Remove potential dangling pointer - if (GetParent() && GetParent()->IsKindOf(CLASSINFO(wxPanel))) - { - wxPanel* panel = (wxPanel*) GetParent(); - if (panel->GetLastFocus() == this) - panel->SetLastFocus((wxWindow*) NULL); - } - //// Motif-specific if (GetMainWidget()) @@ -233,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); } @@ -267,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; @@ -295,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; @@ -748,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; @@ -820,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) { @@ -991,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()); @@ -1477,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 @@ -1496,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) @@ -1580,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) @@ -2305,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 @@ -2359,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; @@ -2617,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) @@ -2647,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; } @@ -2708,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; } } @@ -3531,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; + } + } +} +