X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/af0bb3b161bc687d4a53a83c930c807bfa300a2d..8e72b8b51770b59a83eb32f4d766b89f6c4dc615:/src/motif/window.cpp diff --git a/src/motif/window.cpp b/src/motif/window.cpp index 0cae0d05d1..b2f4037d0e 100644 --- a/src/motif/window.cpp +++ b/src/motif/window.cpp @@ -21,6 +21,12 @@ #pragma implementation "window.h" #endif +#ifdef __VMS +#define XtDisplay XTDISPLAY +#define XtWindow XTWINDOW +#define XtScreen XTSCREEN +#endif + #include "wx/setup.h" #include "wx/menu.h" #include "wx/dc.h" @@ -36,16 +42,17 @@ #include "wx/msgdlg.h" #include "wx/frame.h" #include "wx/scrolwin.h" - +#include "wx/module.h" #include "wx/menuitem.h" #include "wx/log.h" -#include "wx/listimpl.cpp" - #if wxUSE_DRAG_AND_DROP #include "wx/dnd.h" #endif +#ifdef __VMS__ +#pragma message disable nosimpint +#endif #include #include @@ -53,6 +60,10 @@ #include #include #include +#include // for XmMenuPosition +#ifdef __VMS__ +#pragma message enable nosimpint +#endif #include "wx/motif/private.h" @@ -68,7 +79,9 @@ static const int SCROLL_MARGIN = 4; // global variables for this module // ---------------------------------------------------------------------------- -static wxHashTable *gs_wxWidgetHashTable; +extern wxHashTable *wxWidgetHashTable; +static wxWindow* g_captureWindow = NULL; + // ---------------------------------------------------------------------------- // private functions @@ -79,7 +92,7 @@ static void wxCanvasInputEvent(Widget drawingArea, XtPointer data, XmDrawingArea static void wxCanvasMotionEvent(Widget, XButtonEvent * event); static void wxCanvasEnterLeave(Widget drawingArea, XtPointer clientData, XCrossingEvent * event); static void wxScrollBarCallback(Widget widget, XtPointer clientData, - XmScaleCallbackStruct *cbs); + XmScrollBarCallbackStruct *cbs); static void wxPanelItemEventHandler(Widget wid, XtPointer client_data, XEvent* event, @@ -115,25 +128,17 @@ static int str16len(const char *s) // event tables // ---------------------------------------------------------------------------- -#if !USE_SHARED_LIBRARY - IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxEvtHandler) + IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase) - BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler) + BEGIN_EVENT_TABLE(wxWindow, wxWindowBase) EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged) EVT_IDLE(wxWindow::OnIdle) END_EVENT_TABLE() -#endif // USE_SHARED_LIBRARY // ============================================================================ // implementation // ============================================================================ -// ---------------------------------------------------------------------------- -// list types -// ---------------------------------------------------------------------------- - -WX_DEFINE_LIST(wxRectList); - // ---------------------------------------------------------------------------- // helper functions // ---------------------------------------------------------------------------- @@ -182,7 +187,8 @@ void wxWindow::Init() m_winCaptured = FALSE; m_isShown = TRUE; - + m_isBeingDeleted = FALSE; + m_hScrollBar = m_vScrollBar = m_borderWidget = @@ -216,7 +222,7 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id, { wxCHECK_MSG( parent, FALSE, "can't create wxWindow without parent" ); - CreateBase(parent, id, pos, size, style, name); + CreateBase(parent, id, pos, size, style, wxDefaultValidator, name); parent->AddChild(this); @@ -251,13 +257,33 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id, XtAppAddActions ((XtAppContext) wxTheApp->GetAppContext(), actions, 1); Widget parentWidget = (Widget) parent->GetClientWidget(); - if (style & wxBORDER) + + if (style & wxSIMPLE_BORDER) { m_borderWidget = (WXWidget)XtVaCreateManagedWidget ( "canvasBorder", xmFrameWidgetClass, parentWidget, XmNshadowType, XmSHADOW_IN, + XmNshadowThickness, 1, + NULL + ); + } else if (style & wxSUNKEN_BORDER) + { + m_borderWidget = (WXWidget)XtVaCreateManagedWidget + ( + "canvasBorder", + xmFrameWidgetClass, parentWidget, + XmNshadowType, XmSHADOW_IN, + NULL + ); + } else if (style & wxRAISED_BORDER) + { + m_borderWidget = (WXWidget)XtVaCreateManagedWidget + ( + "canvasBorder", + xmFrameWidgetClass, parentWidget, + XmNshadowType, XmSHADOW_OUT, NULL ); } @@ -359,6 +385,11 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id, // Destructor wxWindow::~wxWindow() { + if (g_captureWindow == this) + g_captureWindow = NULL; + + m_isBeingDeleted = TRUE; + // Motif-specific actions first WXWidget wMain = GetMainWidget(); if ( wMain ) @@ -369,6 +400,9 @@ wxWindow::~wxWindow() ClearUpdateRects(); + if ( m_parent ) + m_parent->RemoveChild( this ); + // If m_drawingArea, we're a fully-fledged window with drawing area, // scrollbars etc. (what wxCanvas used to be) if ( m_drawingArea ) @@ -385,18 +419,31 @@ wxWindow::~wxWindow() if (w) { XtDestroyWidget(w); + m_drawingArea = (WXWidget) 0; } - m_mainWidget = (WXWidget) 0; - // Only if we're _really_ a canvas (not a dialog box/panel) if (m_scrolledWindow) { wxDeleteWindowFromTable((Widget) m_scrolledWindow); } - UnmanageAndDestroy(m_hScrollBar); - UnmanageAndDestroy(m_vScrollBar); + if (m_hScrollBar) + { + wxDeleteWindowFromTable((Widget) m_hScrollBar); + XtUnmanageChild((Widget) m_hScrollBar); + } + if (m_vScrollBar) + { + wxDeleteWindowFromTable((Widget) m_vScrollBar); + XtUnmanageChild((Widget) m_vScrollBar); + } + + if (m_hScrollBar) + XtDestroyWidget((Widget) m_hScrollBar); + if (m_vScrollBar) + XtDestroyWidget((Widget) m_vScrollBar); + UnmanageAndDestroy(m_scrolledWindow); if (m_borderWidget) @@ -405,6 +452,9 @@ wxWindow::~wxWindow() m_borderWidget = (WXWidget) 0; } } + else // Why wasn't this here before? JACS 8/3/2000 + DestroyChildren(); + // Destroy the window if (GetMainWidget()) @@ -414,6 +464,12 @@ wxWindow::~wxWindow() // 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. + + // GRG, Feb/2000: commented this out when adding support for + // wxSCROLL[WIN]_THUMBRELEASE events. Also it was reported + // that this call crashed wxMotif under OS/2, so it seems + // that leaving it out is the right thing to do. + // SN, Feb/2000: newgrid/griddemo shows why it is needed :-( XtDestroyWidget((Widget) GetMainWidget()); SetMainWidget((WXWidget) NULL); } @@ -437,7 +493,7 @@ void wxWindow::CreateScrollbar(wxOrientation orientation) xmScrollBarWidgetClass, (Widget) m_scrolledWindow, XmNorientation, XmHORIZONTAL, NULL); - // XtAddCallback (hScrollBar, XmNvalueChangedCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL); + XtAddCallback (hScrollBar, XmNvalueChangedCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL); XtAddCallback (hScrollBar, XmNdragCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL); XtAddCallback (hScrollBar, XmNincrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL); XtAddCallback (hScrollBar, XmNdecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL); @@ -463,6 +519,8 @@ void wxWindow::CreateScrollbar(wxOrientation orientation) NULL); m_hScroll = TRUE; + + wxAddWindowToTable( hScrollBar, this ); } if (orientation == wxVERTICAL) @@ -471,7 +529,7 @@ void wxWindow::CreateScrollbar(wxOrientation orientation) xmScrollBarWidgetClass, (Widget) m_scrolledWindow, XmNorientation, XmVERTICAL, NULL); - // XtAddCallback (vScrollBar, XmNvalueChangedCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL); + XtAddCallback (vScrollBar, XmNvalueChangedCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL); XtAddCallback (vScrollBar, XmNdragCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL); XtAddCallback (vScrollBar, XmNincrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL); XtAddCallback (vScrollBar, XmNdecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL); @@ -496,6 +554,8 @@ void wxWindow::CreateScrollbar(wxOrientation orientation) NULL); m_vScroll = TRUE; + + wxAddWindowToTable( vScrollBar, this ); } XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_ANY, NULL); @@ -511,6 +571,7 @@ void wxWindow::DestroyScrollbar(wxOrientation orientation) { if (m_hScrollBar) { + wxDeleteWindowFromTable((Widget)m_hScrollBar); XtDestroyWidget((Widget) m_hScrollBar); } m_hScrollBar = (WXWidget) 0; @@ -526,10 +587,11 @@ void wxWindow::DestroyScrollbar(wxOrientation orientation) { if (m_vScrollBar) { + wxDeleteWindowFromTable((Widget)m_vScrollBar); XtDestroyWidget((Widget) m_vScrollBar); } m_vScrollBar = (WXWidget) 0; - m_vScroll = TRUE; + m_vScroll = FALSE; XtVaSetValues((Widget) m_scrolledWindow, XmNverticalScrollBar, (Widget) 0, @@ -653,6 +715,7 @@ wxString wxWindow::GetTitle() const void wxWindow::CaptureMouse() { + g_captureWindow = this; if ( m_winCaptured ) return; @@ -665,6 +728,7 @@ void wxWindow::CaptureMouse() void wxWindow::ReleaseMouse() { + g_captureWindow = NULL; if ( !m_winCaptured ) return; @@ -696,11 +760,16 @@ bool wxWindow::SetCursor(const wxCursor& cursor) return FALSE; } - wxASSERT_MSG( m_cursor.Ok(), - _T("cursor must be valid after call to the base version")); + // wxASSERT_MSG( m_cursor.Ok(), + // wxT("cursor must be valid after call to the base version")); + wxCursor* cursor2 = NULL; + if (m_cursor.Ok()) + cursor2 = & m_cursor; + else + cursor2 = wxSTANDARD_CURSOR; WXDisplay *dpy = GetXDisplay(); - WXCursor x_cursor = m_cursor.GetXCursor(dpy); + WXCursor x_cursor = cursor2->GetXCursor(dpy); Widget w = (Widget) GetMainWidget(); Window win = XtWindow(w); @@ -866,6 +935,18 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect) GetClientSize(& w, & h); } + wxNode *cnode = m_children.First(); + while (cnode) + { + wxWindow *child = (wxWindow*) cnode->Data(); + int sx = 0; + int sy = 0; + child->GetSize( &sx, &sy ); + wxPoint pos( child->GetPosition() ); + child->SetSize( pos.x + dx, pos.y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE ); + cnode = cnode->Next(); + } + int x1 = (dx >= 0) ? x : x - dx; int y1 = (dy >= 0) ? y : y - dy; int w1 = w - abs(dx); @@ -1040,6 +1121,76 @@ void wxWindow::DoSetToolTip(wxToolTip * WXUNUSED(tooltip)) #endif // wxUSE_TOOLTIPS +// ---------------------------------------------------------------------------- +// popup menus +// ---------------------------------------------------------------------------- + +bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y) +{ + Widget widget = (Widget) GetMainWidget(); + + /* The menuId field seems to be usused, so we'll use it to + indicate whether a menu is popped up or not: + 0: Not currently created as a popup + -1: Created as a popup, but not active + 1: Active popup. + */ + + if (menu->GetParent() && (menu->GetId() != -1)) + return FALSE; + + if (menu->GetMainWidget()) { + menu->DestroyMenu(TRUE); + } + + menu->SetId(1); /* Mark as popped-up */ + menu->CreateMenu(NULL, widget, menu); + menu->SetInvokingWindow(this); + + menu->UpdateUI(); + + // menu->SetParent(parent); + // parent->children->Append(menu); // Store menu for later deletion + + Widget menuWidget = (Widget) menu->GetMainWidget(); + + int rootX = 0; + int rootY = 0; + + int deviceX = x; + int deviceY = y; + /* + if (this->IsKindOf(CLASSINFO(wxCanvas))) + { + wxCanvas *canvas = (wxCanvas *) this; + deviceX = canvas->GetDC ()->LogicalToDeviceX (x); + deviceY = canvas->GetDC ()->LogicalToDeviceY (y); + } + */ + + Display *display = XtDisplay (widget); + Window rootWindow = RootWindowOfScreen (XtScreen((Widget)widget)); + Window thisWindow = XtWindow (widget); + Window childWindow; + XTranslateCoordinates (display, thisWindow, rootWindow, (int) deviceX, (int) deviceY, + &rootX, &rootY, &childWindow); + + XButtonPressedEvent event; + event.type = ButtonPress; + event.button = 1; + + event.x = deviceX; + event.y = deviceY; + + event.x_root = rootX; + event.y_root = rootY; + + XmMenuPosition (menuWidget, &event); + XtManageChild (menuWidget); + + return TRUE; +} + // --------------------------------------------------------------------------- // moving and resizing // --------------------------------------------------------------------------- @@ -1061,7 +1212,7 @@ void wxWindow::DoGetSize(int *x, int *y) const Widget widget = (Widget) GetTopWidget(); Dimension xx, yy; XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL); - *x = xx; *y = yy; + if(x) *x = xx; if(y) *y = yy; } void wxWindow::DoGetPosition(int *x, int *y) const @@ -1084,7 +1235,7 @@ void wxWindow::DoGetPosition(int *x, int *y) const yy -= pt.y; } - *x = xx; *y = yy; + if(x) *x = xx; if(y) *y = yy; } void wxWindow::DoScreenToClient(int *x, int *y) const @@ -1120,7 +1271,7 @@ void wxWindow::DoGetClientSize(int *x, int *y) const Widget widget = (Widget) GetClientWidget(); Dimension xx, yy; XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL); - *x = xx; *y = yy; + if(x) *x = xx; if(y) *y = yy; } void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags) @@ -1130,69 +1281,61 @@ void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags) GetSize(& oldW, & oldH); GetPosition(& oldX, & oldY); - bool useOldPos = FALSE; - bool useOldSize = FALSE; + if ( !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) ) + { + if ( x == -1 ) + x = oldX; + if ( y == -1 ) + y = oldY; + } - if ((x == -1) && (x == -1) && ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)) - useOldPos = TRUE; - else if (x == oldX && y == oldY) - useOldPos = TRUE; + if ( width == -1 ) + width = oldW; + if ( height == -1 ) + height = oldH; - if ((width == -1) && (height == -1)) - useOldSize = TRUE; - else if (width == oldW && height == oldH) - useOldSize = TRUE; + bool nothingChanged = (x == oldX) && (y == oldY) && + (width == oldW) && (height == oldH); if (!wxNoOptimize::CanOptimize()) { - useOldSize = FALSE; useOldPos = FALSE; + nothingChanged = FALSE; } - if (useOldPos && useOldSize) - return; - - if (m_drawingArea) + if ( !nothingChanged ) { - CanvasSetSize(x, y, width, height, sizeFlags); - return; - } - Widget widget = (Widget) GetTopWidget(); - if (!widget) - return; + if (m_drawingArea) + { + CanvasSetSize(x, y, width, height, sizeFlags); + return; + } - bool managed = XtIsManaged( widget ); - if (managed) - XtUnmanageChild(widget); + Widget widget = (Widget) GetTopWidget(); + if (!widget) + return; - int xx = x; int yy = y; - AdjustForParentClientOrigin(xx, yy, sizeFlags); + bool managed = XtIsManaged( widget ); + if (managed) + XtUnmanageChild(widget); - if (!useOldPos) - { - if (x > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) - XtVaSetValues(widget, XmNx, xx, NULL); - if (y > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) - XtVaSetValues(widget, XmNy, yy, NULL); - } - if (!useOldSize) - { - if (width > -1) - XtVaSetValues(widget, XmNwidth, width, NULL); - if (height > -1) - XtVaSetValues(widget, XmNheight, height, NULL); - } + int xx = x; + int yy = y; + AdjustForParentClientOrigin(xx, yy, sizeFlags); - if (managed) - XtManageChild(widget); + DoMoveWindow(xx, yy, width, height); + + if (managed) + XtManageChild(widget); - // How about this bit. Maybe we don't need to generate size events - // all the time -- they'll be generated when the window is sized anyway. + // How about this bit. Maybe we don't need to generate size events + // all the time -- they'll be generated when the window is sized anyway. #if 0 - wxSizeEvent sizeEvent(wxSize(width, height), GetId()); - sizeEvent.SetEventObject(this); + wxSizeEvent sizeEvent(wxSize(width, height), GetId()); + sizeEvent.SetEventObject(this); - GetEventHandler()->ProcessEvent(sizeEvent); + GetEventHandler()->ProcessEvent(sizeEvent); #endif // 0 + } } void wxWindow::DoSetClientSize(int width, int height) @@ -1264,6 +1407,16 @@ void wxWindow::SetSizeHints(int minW, int minH, int maxW, int maxH, int incW, in XtVaSetValues(widget, XmNheightInc, incH, NULL); } +void wxWindow::DoMoveWindow(int x, int y, int width, int height) +{ + XtVaSetValues((Widget)GetTopWidget(), + XmNx, x, + XmNy, y, + XmNwidth, width, + XmNheight, height, + NULL); +} + // --------------------------------------------------------------------------- // text metrics // --------------------------------------------------------------------------- @@ -1307,12 +1460,12 @@ void wxWindow::GetTextExtent(const wxString& string, fontToUse = (wxFont *) & m_font; wxCHECK_RET( fontToUse->Ok(), "valid window font needed" ); - + WXFontStructPtr pFontStruct = theFont->GetFontStruct(1.0, GetXDisplay()); int direction, ascent, descent2; XCharStruct overall; - int slen; + int slen = string.Len(); #if 0 if (use16) @@ -1331,6 +1484,7 @@ void wxWindow::GetTextExtent(const wxString& string, *descent = descent2; if (externalLeading) *externalLeading = 0; + } // ---------------------------------------------------------------------------- @@ -1498,7 +1652,7 @@ void wxWindow::OnSysColourChanged(wxSysColourChangedEvent& event) } } -void wxWindow::OnIdle(wxIdleEvent& event) +void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event)) { // This calls the UI-update mechanism (querying windows for // menu/toolbar/control state information) @@ -1522,8 +1676,8 @@ bool wxWindow::ProcessAccelerator(wxKeyEvent& event) wxAcceleratorEntry* entry = & (entries[i]); if (entry->MatchesEvent(event)) { - // Bingo, we have a match. Now find a control that matches the entry - // command id. + // Bingo, we have a match. Now find a control that matches the + // entry command id. // Need to go up to the top of the window hierarchy, since it might // be e.g. a menu item @@ -1540,7 +1694,7 @@ bool wxWindow::ProcessAccelerator(wxKeyEvent& event) // Try for a menu command if (frame->GetMenuBar()) { - wxMenuItem* item = frame->GetMenuBar()->FindItemForId(entry->GetCommand()); + wxMenuItem* item = frame->GetMenuBar()->FindItem(entry->GetCommand()); if (item) { wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, entry->GetCommand()); @@ -1588,26 +1742,29 @@ bool wxWindow::ProcessAccelerator(wxKeyEvent& event) bool wxAddWindowToTable(Widget w, wxWindow *win) { wxWindow *oldItem = NULL; - if ((oldItem = (wxWindow *)gs_wxWidgetHashTable->Get ((long) w))) + if ((oldItem = (wxWindow *)wxWidgetHashTable->Get ((long) w))) { wxLogDebug("Widget table clash: new widget is %ld, %s", (long)w, win->GetClassInfo()->GetClassName()); return FALSE; } - gs_wxWidgetHashTable->Put((long) w, win); + wxWidgetHashTable->Put((long) w, win); + + wxLogTrace("widget", "Widget 0x%08x <-> window %p (%s)", + w, win, win->GetClassInfo()->GetClassName()); return TRUE; } wxWindow *wxGetWindowFromTable(Widget w) { - return (wxWindow *)gs_wxWidgetHashTable->Get((long) w); + return (wxWindow *)wxWidgetHashTable->Get((long) w); } void wxDeleteWindowFromTable(Widget w) { - gs_wxWidgetHashTable->Delete((long)w); + wxWidgetHashTable->Delete((long)w); } // ---------------------------------------------------------------------------- @@ -1615,7 +1772,7 @@ void wxDeleteWindowFromTable(Widget w) // ---------------------------------------------------------------------------- // Add to hash table, add event handler -bool wxWindow::AttachWidget (wxWindow* parent, WXWidget mainWidget, +bool wxWindow::AttachWidget (wxWindow* WXUNUSED(parent), WXWidget mainWidget, WXWidget formWidget, int x, int y, int width, int height) { wxAddWindowToTable((Widget) mainWidget, this); @@ -1729,7 +1886,7 @@ WXWidget wxWindow::GetLabelWidget() const // All widgets should have this as their resize proc. // OnSize sent to wxWindow via client data. -void wxWidgetResizeProc(Widget w, XConfigureEvent *event, String args[], int *num_args) +void wxWidgetResizeProc(Widget w, XConfigureEvent *WXUNUSED(event), String WXUNUSED(args)[], int *WXUNUSED(num_args)) { wxWindow *win = wxGetWindowFromTable(w); if (!win) @@ -1759,22 +1916,14 @@ static void wxCanvasRepaintProc(Widget drawingArea, { case Expose: { + win->AddUpdateRect(event->xexpose.x, event->xexpose.y, + event->xexpose.width, event->xexpose.height); + if (event -> xexpose.count == 0) { -#if 0 - wxPaintEvent event(win->GetId()); - event.SetEventObject(win); - win->GetEventHandler()->ProcessEvent(event); -#endif // 0 - win->DoPaint(); win->ClearUpdateRects(); } - else - { - win->AddUpdateRect(event->xexpose.x, event->xexpose.y, - event->xexpose.width, event->xexpose.height); - } break; } } @@ -1782,7 +1931,7 @@ static void wxCanvasRepaintProc(Widget drawingArea, // Unable to deal with Enter/Leave without a separate EventHandler (Motif 1.1.4) static void wxCanvasEnterLeave(Widget drawingArea, - XtPointer clientData, + XtPointer WXUNUSED(clientData), XCrossingEvent * event) { XmDrawingAreaCallbackStruct cbs; @@ -1797,7 +1946,7 @@ static void wxCanvasEnterLeave(Widget drawingArea, } // Fix to make it work under Motif 1.0 (!) -static void wxCanvasMotionEvent (Widget drawingArea, XButtonEvent * event) +static void wxCanvasMotionEvent (Widget WXUNUSED(drawingArea), XButtonEvent * WXUNUSED(event)) { #if XmVersion <= 1000 XmDrawingAreaCallbackStruct cbs; @@ -1812,7 +1961,7 @@ static void wxCanvasMotionEvent (Widget drawingArea, XButtonEvent * event) } static void wxCanvasInputEvent(Widget drawingArea, - XtPointer data, + XtPointer WXUNUSED(data), XmDrawingAreaCallbackStruct * cbs) { wxWindow *canvas = wxGetWindowFromTable(drawingArea); @@ -1834,6 +1983,9 @@ static void wxCanvasInputEvent(Widget drawingArea, case ButtonRelease: case MotionNotify: { + // FIXME: most of this mouse event code is more or less + // duplicated in wxTranslateMouseEvent + // wxEventType eventType = wxEVT_NULL; if (local_event.xany.type == EnterNotify) @@ -1845,7 +1997,7 @@ static void wxCanvasInputEvent(Widget drawingArea, } else if (local_event.xany.type == LeaveNotify) { - //if (local_event.xcrossing.mode!=NotifyNormal) + //if (local_event.xcrossingr.mode!=NotifyNormal) // return ; // Ignore grab events eventType = wxEVT_LEAVE_WINDOW; // canvas->GetEventHandler()->OnKillFocus(); @@ -1853,22 +2005,6 @@ static void wxCanvasInputEvent(Widget drawingArea, else if (local_event.xany.type == MotionNotify) { eventType = wxEVT_MOTION; - if (local_event.xmotion.is_hint == NotifyHint) - { - Window root, child; - Display *dpy = XtDisplay (drawingArea); - - XQueryPointer (dpy, XtWindow (drawingArea), - &root, &child, - &local_event.xmotion.x_root, - &local_event.xmotion.y_root, - &local_event.xmotion.x, - &local_event.xmotion.y, - &local_event.xmotion.state); - } - else - { - } } else if (local_event.xany.type == ButtonPress) @@ -1926,6 +2062,26 @@ static void wxCanvasInputEvent(Widget drawingArea, wxevent.m_metaDown = local_event.xbutton.state & Mod1Mask; wxevent.SetTimestamp(local_event.xbutton.time); + if ( eventType == wxEVT_MOTION ) + { + if (local_event.xmotion.is_hint == NotifyHint) + { + Window root, child; + Display *dpy = XtDisplay (drawingArea); + + XQueryPointer (dpy, XtWindow (drawingArea), + &root, &child, + &local_event.xmotion.x_root, + &local_event.xmotion.y_root, + &local_event.xmotion.x, + &local_event.xmotion.y, + &local_event.xmotion.state); + } + else + { + } + } + // Now check if we need to translate this event into a double click if (TRUE) // canvas->doubleClickAllowed) { @@ -1950,22 +2106,21 @@ static void wxCanvasInputEvent(Widget drawingArea, { // I have a dclick canvas->SetLastClick(0, ts); - switch ( eventType ) + + wxEventType typeDouble; + if ( eventType == wxEVT_LEFT_DOWN ) + typeDouble = wxEVT_LEFT_DCLICK; + else if ( eventType == wxEVT_MIDDLE_DOWN ) + typeDouble = wxEVT_MIDDLE_DCLICK; + else if ( eventType == wxEVT_RIGHT_DOWN ) + typeDouble = wxEVT_RIGHT_DCLICK; + else + typeDouble = wxEVT_NULL; + + if ( typeDouble != wxEVT_NULL ) { - case wxEVT_LEFT_DOWN: - wxevent.SetEventType(wxEVT_LEFT_DCLICK); - break; - case wxEVT_MIDDLE_DOWN: - wxevent.SetEventType(wxEVT_MIDDLE_DCLICK); - break; - case wxEVT_RIGHT_DOWN: - wxevent.SetEventType(wxEVT_RIGHT_DCLICK); - break; - - default : - break; + wxevent.SetEventType(typeDouble); } - } else { @@ -2095,7 +2250,7 @@ static void wxCanvasInputEvent(Widget drawingArea, } static void wxPanelItemEventHandler(Widget wid, - XtPointer client_data, + XtPointer WXUNUSED(client_data), XEvent* event, Boolean *continueToDispatch) { @@ -2123,7 +2278,7 @@ static void wxPanelItemEventHandler(Widget wid, static void wxScrollBarCallback(Widget scrollbar, XtPointer clientData, - XmScaleCallbackStruct *cbs) + XmScrollBarCallbackStruct *cbs) { wxWindow *win = wxGetWindowFromTable(scrollbar); int orientation = (int) clientData; @@ -2133,44 +2288,42 @@ static void wxScrollBarCallback(Widget scrollbar, { case XmCR_INCREMENT: { - eventType = wxEVT_SCROLL_LINEDOWN; + eventType = wxEVT_SCROLLWIN_LINEDOWN; break; } case XmCR_DECREMENT: { - eventType = wxEVT_SCROLL_LINEUP; + eventType = wxEVT_SCROLLWIN_LINEUP; break; } case XmCR_DRAG: { - eventType = wxEVT_SCROLL_THUMBTRACK; + eventType = wxEVT_SCROLLWIN_THUMBTRACK; break; } case XmCR_VALUE_CHANGED: { - // TODO: Should this be intercepted too, or will it cause - // duplicate events? - eventType = wxEVT_SCROLL_THUMBTRACK; + eventType = wxEVT_SCROLLWIN_THUMBRELEASE; break; } case XmCR_PAGE_INCREMENT: { - eventType = wxEVT_SCROLL_PAGEDOWN; + eventType = wxEVT_SCROLLWIN_PAGEDOWN; break; } case XmCR_PAGE_DECREMENT: { - eventType = wxEVT_SCROLL_PAGEUP; + eventType = wxEVT_SCROLLWIN_PAGEUP; break; } case XmCR_TO_TOP: { - eventType = wxEVT_SCROLL_TOP; + eventType = wxEVT_SCROLLWIN_TOP; break; } case XmCR_TO_BOTTOM: { - eventType = wxEVT_SCROLL_BOTTOM; + eventType = wxEVT_SCROLLWIN_BOTTOM; break; } default: @@ -2181,11 +2334,11 @@ static void wxScrollBarCallback(Widget scrollbar, } } - wxScrollEvent event(eventType, win->GetId()); - event.SetEventObject(win); - event.SetPosition(cbs->value); - event.SetOrientation( (orientation == XmHORIZONTAL) ? wxHORIZONTAL : wxVERTICAL ); - + wxScrollWinEvent event(eventType, + cbs->value, + ((orientation == XmHORIZONTAL) ? + wxHORIZONTAL : wxVERTICAL)); + event.SetEventObject( win ); win->GetEventHandler()->ProcessEvent(event); } @@ -2454,14 +2607,16 @@ bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Widget widget, { switch (xevent->xany.type) { - case EnterNotify: - case LeaveNotify: - case ButtonPress: - case ButtonRelease: - case MotionNotify: + case EnterNotify: // never received here - yes ? MB + case LeaveNotify: // never received here - yes ? MB + case ButtonPress: + case ButtonRelease: + case MotionNotify: { wxEventType eventType = wxEVT_NULL; + // FIXME: this is never true I think - MB + // if (xevent->xany.type == LeaveNotify) { win->SetButton1(FALSE); @@ -2475,20 +2630,49 @@ bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Widget widget, } else if (xevent->xany.type == ButtonPress) { + wxevent.SetTimestamp(xevent->xbutton.time); + int button = 0; if (xevent->xbutton.button == Button1) { eventType = wxEVT_LEFT_DOWN; win->SetButton1(TRUE); + button = 1; } else if (xevent->xbutton.button == Button2) { eventType = wxEVT_MIDDLE_DOWN; win->SetButton2(TRUE); + button = 2; } else if (xevent->xbutton.button == Button3) { eventType = wxEVT_RIGHT_DOWN; win->SetButton3(TRUE); + button = 3; + } + + // check for a double click + // + long dclickTime = XtGetMultiClickTime((Display*) wxGetDisplay()); + long ts = wxevent.GetTimestamp(); + + int buttonLast = win->GetLastClickedButton(); + long lastTS = win->GetLastClickTime(); + if ( buttonLast && buttonLast == button && (ts - lastTS) < dclickTime ) + { + // I have a dclick + win->SetLastClick(0, ts); + if ( eventType == wxEVT_LEFT_DOWN ) + eventType = wxEVT_LEFT_DCLICK; + else if ( eventType == wxEVT_MIDDLE_DOWN ) + eventType = wxEVT_MIDDLE_DCLICK; + else if ( eventType == wxEVT_RIGHT_DOWN ) + eventType = wxEVT_RIGHT_DCLICK; + } + else + { + // not fast enough or different button + win->SetLastClick(button, ts); } } else if (xevent->xany.type == ButtonRelease) @@ -2549,17 +2733,24 @@ bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Widget widget, wxevent.m_shiftDown = xevent->xbutton.state & ShiftMask; wxevent.m_controlDown = xevent->xbutton.state & ControlMask; + wxevent.m_altDown = xevent->xbutton.state & Mod3Mask; + wxevent.m_metaDown = xevent->xbutton.state & Mod1Mask; + + wxevent.SetId(win->GetId()); + wxevent.SetEventObject(win); + return TRUE; } } return FALSE; } -bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Widget widget, XEvent *xevent) +bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Widget WXUNUSED(widget), XEvent *xevent) { switch (xevent->xany.type) { case KeyPress: + case KeyRelease: { char buf[20]; @@ -2789,11 +2980,45 @@ void wxWindow::ChangeFont(bool keepOriginalSize) wxWindow *wxGetActiveWindow() { // TODO + wxFAIL_MSG("Not implemented"); return NULL; } +/* static */ +wxWindow *wxWindowBase::GetCapture() +{ + return (wxWindow *)g_captureWindow; +} + + +// Find the wxWindow at the current mouse position, returning the mouse +// position. +wxWindow* wxFindWindowAtPointer(wxPoint& pt) +{ + return wxFindWindowAtPoint(wxGetMousePosition()); +} + +// Get the current mouse position. +wxPoint wxGetMousePosition() +{ + Display *display = (Display*) wxGetDisplay(); + Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display)); + Window rootReturn, childReturn; + int rootX, rootY, winX, winY; + unsigned int maskReturn; + + XQueryPointer (display, + rootWindow, + &rootReturn, + &childReturn, + &rootX, &rootY, &winX, &winY, &maskReturn); + return wxPoint(rootX, rootY); +} + + // ---------------------------------------------------------------------------- // wxNoOptimize: switch off size optimization // ---------------------------------------------------------------------------- int wxNoOptimize::ms_count = 0; +