1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "window.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
28 #define XtDisplay XTDISPLAY
29 #define XtWindow XTWINDOW
30 #define XtScreen XTSCREEN
36 #include "wx/dcclient.h"
39 #include "wx/layout.h"
40 #include "wx/button.h"
41 #include "wx/settings.h"
43 #include "wx/scrolwin.h"
44 #include "wx/module.h"
45 #include "wx/menuitem.h"
47 #include "wx/evtloop.h"
50 #if wxUSE_DRAG_AND_DROP
54 // DoSetSizeIntr and DoMoveWindowIntr
56 // under Motif composite controls (such as wxCalendarCtrl or generic wxSpinCtrl
57 // did not work and/or segfaulted because
58 // 1) wxWindow::Create calls SetSize,
59 // which results in a call to DoSetSize much earlier than in the other ports
60 // 2) if wxWindow::Create is called (wxControl::Create calls it)
61 // then DoSetSize is never called, causing layout problems in composite
65 // 1) don't call SetSize, DoSetSize, DoMoveWindow, DoGetPosition,
66 // DoSetPosition directly or indirectly from wxWindow::Create
67 // 2) call DoMoveWindow from DoSetSize, allowing controls to override it
70 #pragma message disable nosimpint
74 #include <Xm/DrawingA.h>
75 #include <Xm/ScrolledW.h>
76 #include <Xm/ScrollBar.h>
79 #include <Xm/RowColumn.h> // for XmMenuPosition
81 #pragma message enable nosimpint
84 #include "wx/motif/private.h"
88 // ----------------------------------------------------------------------------
90 // ----------------------------------------------------------------------------
92 static const int SCROLL_MARGIN
= 4;
94 // ----------------------------------------------------------------------------
95 // global variables for this module
96 // ----------------------------------------------------------------------------
98 extern wxHashTable
*wxWidgetHashTable
;
99 static wxWindow
* g_captureWindow
= NULL
;
102 // ----------------------------------------------------------------------------
104 // ----------------------------------------------------------------------------
106 static void wxCanvasRepaintProc(Widget
, XtPointer
, XmDrawingAreaCallbackStruct
* cbs
);
107 static void wxCanvasInputEvent(Widget drawingArea
, XtPointer data
, XmDrawingAreaCallbackStruct
* cbs
);
108 static void wxCanvasMotionEvent(Widget
, XButtonEvent
* event
);
109 static void wxCanvasEnterLeave(Widget drawingArea
, XtPointer clientData
, XCrossingEvent
* event
);
110 static void wxScrollBarCallback(Widget widget
, XtPointer clientData
,
111 XmScrollBarCallbackStruct
*cbs
);
112 static void wxPanelItemEventHandler(Widget wid
,
113 XtPointer client_data
,
115 Boolean
*continueToDispatch
);
120 // Helper function for 16-bit fonts
121 static int str16len(const char *s
)
125 while (s
[0] && s
[1]) {
135 // ----------------------------------------------------------------------------
137 // ----------------------------------------------------------------------------
139 #define event_left_is_down(x) ((x)->xbutton.state & Button1Mask)
140 #define event_middle_is_down(x) ((x)->xbutton.state & Button2Mask)
141 #define event_right_is_down(x) ((x)->xbutton.state & Button3Mask)
143 // ----------------------------------------------------------------------------
145 // ----------------------------------------------------------------------------
147 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
149 BEGIN_EVENT_TABLE(wxWindow
, wxWindowBase
)
150 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged
)
153 // ============================================================================
155 // ============================================================================
157 // ----------------------------------------------------------------------------
159 // ----------------------------------------------------------------------------
161 void wxWindow::UnmanageAndDestroy(WXWidget widget
)
163 Widget w
= (Widget
)widget
;
171 bool wxWindow::MapOrUnmap(WXWidget widget
, bool domap
)
173 Widget w
= (Widget
)widget
;
177 // Rationale: a lot of common operations (including but not
178 // limited to moving, resizing and appending items to a listbox)
179 // unmamange the widget, do their work, then manage it again.
180 // This means that, for example adding an item to a listbox will show it,
181 // or that most controls are shown every time they are moved or resized!
182 XtSetMappedWhenManaged( w
, domap
);
184 // if the widget is not unmanaged, it still intercepts
185 // mouse events, even if it is not mapped (and hence invisible)
200 // ----------------------------------------------------------------------------
202 // ----------------------------------------------------------------------------
204 void wxWindow::Init()
207 m_needsRefresh
= true;
208 m_mainWidget
= (WXWidget
) 0;
210 m_winCaptured
= false;
218 m_drawingArea
= (WXWidget
) 0;
223 m_backingPixmap
= (WXPixmap
) 0;
234 // real construction (Init() must have been called before!)
235 bool wxWindow::Create(wxWindow
*parent
, wxWindowID id
,
239 const wxString
& name
)
241 wxCHECK_MSG( parent
, false, "can't create wxWindow without parent" );
243 CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
);
245 parent
->AddChild(this);
247 m_backgroundColour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
248 m_foregroundColour
= *wxBLACK
;
250 //// TODO: we should probably optimize by only creating a
251 //// a drawing area if we have one or more scrollbars (wxVSCROLL/wxHSCROLL).
252 //// But for now, let's simplify things by always creating the
253 //// drawing area, since otherwise the translations are different.
255 // New translations for getting mouse motion feedback
256 static const String translations
=
257 "<Btn1Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
258 <Btn2Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
259 <Btn3Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
260 <BtnMotion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
261 <Btn1Down>: DrawingAreaInput() ManagerGadgetArm()\n\
262 <Btn2Down>: DrawingAreaInput() ManagerGadgetArm()\n\
263 <Btn3Down>: DrawingAreaInput() ManagerGadgetArm()\n\
264 <Btn1Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
265 <Btn2Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
266 <Btn3Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
267 <Motion>: wxCanvasMotionEvent() DrawingAreaInput()\n\
268 <EnterWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
269 <LeaveWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
270 <Key>: DrawingAreaInput()";
272 XtActionsRec actions
[1];
273 actions
[0].string
= "wxCanvasMotionEvent";
274 actions
[0].proc
= (XtActionProc
) wxCanvasMotionEvent
;
275 XtAppAddActions ((XtAppContext
) wxTheApp
->GetAppContext(), actions
, 1);
277 Widget parentWidget
= (Widget
) parent
->GetClientWidget();
278 m_borderWidget
= wxCreateBorderWidget( (WXWidget
)parentWidget
, style
);
280 m_scrolledWindow
= (WXWidget
)XtVaCreateManagedWidget
283 xmScrolledWindowWidgetClass
,
284 m_borderWidget
? (Widget
) m_borderWidget
286 XmNresizePolicy
, XmRESIZE_NONE
,
288 XmNscrollingPolicy
, XmAPPLICATION_DEFINED
,
289 //XmNscrollBarDisplayPolicy, XmAS_NEEDED,
293 XtTranslations ptr
= XtParseTranslationTable(translations
);
294 m_drawingArea
= (WXWidget
)XtVaCreateWidget
297 xmDrawingAreaWidgetClass
, (Widget
) m_scrolledWindow
,
298 XmNunitType
, XmPIXELS
,
299 // XmNresizePolicy, XmRESIZE_ANY,
300 XmNresizePolicy
, XmRESIZE_NONE
,
303 XmNtranslations
, ptr
,
306 XtFree((char *) ptr
);
309 if (GetWindowStyleFlag() & wxOVERRIDE_KEY_TRANSLATIONS
)
311 ptr
= XtParseTranslationTable ("<Key>: DrawingAreaInput()");
312 XtOverrideTranslations ((Widget
) m_drawingArea
, ptr
);
313 XtFree ((char *) ptr
);
317 wxAddWindowToTable((Widget
) m_drawingArea
, this);
318 wxAddWindowToTable((Widget
) m_scrolledWindow
, this);
320 // This order is very important in Motif 1.2.1
321 XtRealizeWidget ((Widget
) m_scrolledWindow
);
322 XtRealizeWidget ((Widget
) m_drawingArea
);
323 XtManageChild ((Widget
) m_drawingArea
);
325 ptr
= XtParseTranslationTable("<Configure>: resize()");
326 XtOverrideTranslations((Widget
) m_drawingArea
, ptr
);
327 XtFree ((char *) ptr
);
329 XtAddCallback ((Widget
) m_drawingArea
, XmNexposeCallback
, (XtCallbackProc
) wxCanvasRepaintProc
, (XtPointer
) this);
330 XtAddCallback ((Widget
) m_drawingArea
, XmNinputCallback
, (XtCallbackProc
) wxCanvasInputEvent
, (XtPointer
) this);
333 (Widget
)m_drawingArea
,
334 PointerMotionHintMask
| EnterWindowMask
|
335 LeaveWindowMask
| FocusChangeMask
,
337 (XtEventHandler
) wxCanvasEnterLeave
,
341 // Scrolled widget needs to have its colour changed or we get a little blue
342 // square where the scrollbars abutt
343 wxColour backgroundColour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
344 wxDoChangeBackgroundColour(m_scrolledWindow
, backgroundColour
, true);
345 wxDoChangeBackgroundColour(m_drawingArea
, backgroundColour
, true);
347 XmScrolledWindowSetAreas(
348 (Widget
)m_scrolledWindow
,
349 (Widget
) 0, (Widget
) 0,
350 (Widget
) m_drawingArea
);
352 // Without this, the cursor may not be restored properly (e.g. in splitter
354 SetCursor(*wxSTANDARD_CURSOR
);
355 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
356 DoSetSizeIntr(pos
.x
, pos
.y
, size
.x
,size
.y
, wxSIZE_AUTO
, true);
361 wxWindow::~wxWindow()
363 if (g_captureWindow
== this)
364 g_captureWindow
= NULL
;
366 m_isBeingDeleted
= true;
368 // Motif-specific actions first
369 WXWidget wMain
= GetMainWidget();
372 // Removes event handlers
376 // If m_drawingArea, we're a fully-fledged window with drawing area,
377 // scrollbars etc. (what wxCanvas used to be)
380 // Destroy children before destroying self
384 XFreePixmap (XtDisplay ((Widget
) GetMainWidget()), (Pixmap
) m_backingPixmap
);
386 Widget w
= (Widget
) m_drawingArea
;
387 wxDeleteWindowFromTable(w
);
392 m_drawingArea
= (WXWidget
) 0;
395 // Only if we're _really_ a canvas (not a dialog box/panel)
396 if (m_scrolledWindow
)
398 wxDeleteWindowFromTable((Widget
) m_scrolledWindow
);
403 wxDeleteWindowFromTable((Widget
) m_hScrollBar
);
404 XtUnmanageChild((Widget
) m_hScrollBar
);
408 wxDeleteWindowFromTable((Widget
) m_vScrollBar
);
409 XtUnmanageChild((Widget
) m_vScrollBar
);
413 XtDestroyWidget((Widget
) m_hScrollBar
);
415 XtDestroyWidget((Widget
) m_vScrollBar
);
417 UnmanageAndDestroy(m_scrolledWindow
);
421 XtDestroyWidget ((Widget
) m_borderWidget
);
422 m_borderWidget
= (WXWidget
) 0;
425 else // Why wasn't this here before? JACS 8/3/2000
429 // Destroy the window
432 // If this line (XtDestroyWidget) causes a crash, you may comment it out.
433 // Child widgets will get destroyed automatically when a frame
434 // or dialog is destroyed, but before that you may get some memory
435 // leaks and potential layout problems if you delete and then add
438 // GRG, Feb/2000: commented this out when adding support for
439 // wxSCROLL[WIN]_THUMBRELEASE events. Also it was reported
440 // that this call crashed wxMotif under OS/2, so it seems
441 // that leaving it out is the right thing to do.
442 // SN, Feb/2000: newgrid/griddemo shows why it is needed :-(
443 XtDestroyWidget((Widget
) GetMainWidget());
444 SetMainWidget((WXWidget
) NULL
);
448 // ----------------------------------------------------------------------------
449 // scrollbar management
450 // ----------------------------------------------------------------------------
452 WXWidget
wxWindow::DoCreateScrollBar(WXWidget parent
,
453 wxOrientation orientation
,
456 int orient
= ( orientation
& wxHORIZONTAL
) ? XmHORIZONTAL
: XmVERTICAL
;
458 XtVaCreateManagedWidget( "scrollBarWidget",
459 xmScrollBarWidgetClass
, (Widget
)parent
,
460 XmNorientation
, orient
,
465 XtPointer o
= (XtPointer
)orientation
;
466 XtCallbackProc cb
= (XtCallbackProc
)callback
;
468 XtAddCallback( sb
, XmNvalueChangedCallback
, cb
, o
);
469 XtAddCallback( sb
, XmNdragCallback
, cb
, o
);
470 XtAddCallback( sb
, XmNincrementCallback
, cb
, o
);
471 XtAddCallback( sb
, XmNdecrementCallback
, cb
, o
);
472 XtAddCallback( sb
, XmNpageIncrementCallback
, cb
, o
);
473 XtAddCallback( sb
, XmNpageDecrementCallback
, cb
, o
);
474 XtAddCallback( sb
, XmNtoTopCallback
, cb
, o
);
475 XtAddCallback( sb
, XmNtoBottomCallback
, cb
, o
);
481 void wxWindow::CreateScrollbar(wxOrientation orientation
)
483 wxCHECK_RET( m_drawingArea
, "this window can't have scrollbars" );
485 XtVaSetValues( (Widget
) m_scrolledWindow
,
486 XmNresizePolicy
, XmRESIZE_NONE
,
489 wxColour backgroundColour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
490 // Add scrollbars if required
491 if (orientation
== wxHORIZONTAL
)
493 m_hScrollBar
= DoCreateScrollBar( m_scrolledWindow
, wxHORIZONTAL
,
494 (void (*)())wxScrollBarCallback
);
496 wxDoChangeBackgroundColour(m_hScrollBar
, backgroundColour
, true);
498 XtRealizeWidget( (Widget
)m_hScrollBar
);
500 XtVaSetValues((Widget
) m_scrolledWindow
,
501 XmNhorizontalScrollBar
, (Widget
) m_hScrollBar
,
504 wxAddWindowToTable( (Widget
)m_hScrollBar
, this );
506 else if (orientation
== wxVERTICAL
)
508 m_vScrollBar
= DoCreateScrollBar( m_scrolledWindow
, wxVERTICAL
,
509 (void (*)())wxScrollBarCallback
);
511 wxDoChangeBackgroundColour(m_vScrollBar
, backgroundColour
, true);
513 XtRealizeWidget((Widget
)m_vScrollBar
);
515 XtVaSetValues((Widget
) m_scrolledWindow
,
516 XmNverticalScrollBar
, (Widget
) m_vScrollBar
,
519 wxAddWindowToTable( (Widget
)m_vScrollBar
, this );
522 XtVaSetValues( (Widget
) m_scrolledWindow
,
523 XmNresizePolicy
, XmRESIZE_ANY
,
527 void wxWindow::DestroyScrollbar(wxOrientation orientation
)
529 wxCHECK_RET( m_drawingArea
, "this window can't have scrollbars" );
531 XtVaSetValues((Widget
) m_scrolledWindow
,
532 XmNresizePolicy
, XmRESIZE_NONE
,
534 String stringSB
= orientation
== wxHORIZONTAL
?
535 XmNhorizontalScrollBar
: XmNverticalScrollBar
;
536 WXWidget
* widgetSB
= orientation
== wxHORIZONTAL
?
537 &m_hScrollBar
: &m_vScrollBar
;
541 wxDeleteWindowFromTable( (Widget
)*widgetSB
);
542 XtDestroyWidget( (Widget
)*widgetSB
);
543 *widgetSB
= (WXWidget
)NULL
;
546 XtVaSetValues( (Widget
)m_scrolledWindow
,
547 stringSB
, (Widget
) 0,
550 XtVaSetValues((Widget
) m_scrolledWindow
,
551 XmNresizePolicy
, XmRESIZE_ANY
,
555 // ---------------------------------------------------------------------------
557 // ---------------------------------------------------------------------------
559 void wxWindow::SetFocus()
561 Widget wMain
= (Widget
) GetMainWidget();
562 XmProcessTraversal(wMain
, XmTRAVERSE_CURRENT
);
563 XmProcessTraversal((Widget
) GetMainWidget(), XmTRAVERSE_CURRENT
);
566 // Get the window with the focus
567 wxWindow
*wxWindowBase::DoFindFocus()
570 // (1) Can there be multiple focussed widgets in an application?
571 // In which case we need to find the top-level window that's
573 // (2) The widget with the focus may not be in the widget table
574 // depending on which widgets I put in the table
575 wxWindow
*winFocus
= (wxWindow
*)NULL
;
576 for ( wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetFirst();
578 node
= node
->GetNext() )
580 wxWindow
*win
= node
->GetData();
582 Widget w
= XmGetFocusWidget ((Widget
) win
->GetTopWidget());
584 if (w
!= (Widget
) NULL
)
586 winFocus
= wxGetWindowFromTable(w
);
595 bool wxWindow::Enable(bool enable
)
597 if ( !wxWindowBase::Enable(enable
) )
600 Widget wMain
= (Widget
)GetMainWidget();
603 XtSetSensitive(wMain
, enable
);
604 XmUpdateDisplay(wMain
);
610 bool wxWindow::Show(bool show
)
612 if ( !wxWindowBase::Show(show
) )
615 if (m_borderWidget
|| m_scrolledWindow
)
617 MapOrUnmap(m_borderWidget
? m_borderWidget
: m_scrolledWindow
, show
);
618 // MapOrUnmap(m_drawingArea, show);
622 if ( !MapOrUnmap(GetTopWidget(), show
) )
623 MapOrUnmap(GetMainWidget(), show
);
629 // Raise the window to the top of the Z order
630 void wxWindow::Raise()
632 Widget wTop
= (Widget
) GetTopWidget();
633 Window window
= XtWindow(wTop
);
634 XRaiseWindow(XtDisplay(wTop
), window
);
637 // Lower the window to the bottom of the Z order
638 void wxWindow::Lower()
640 Widget wTop
= (Widget
) GetTopWidget();
641 Window window
= XtWindow(wTop
);
642 XLowerWindow(XtDisplay(wTop
), window
);
645 void wxWindow::SetTitle(const wxString
& title
)
647 XtVaSetValues((Widget
)GetMainWidget(), XmNtitle
, title
.c_str(), NULL
);
650 wxString
wxWindow::GetTitle() const
653 XtVaGetValues((Widget
)GetMainWidget(), XmNtitle
, &title
, NULL
);
655 return wxString(title
);
658 void wxWindow::DoCaptureMouse()
660 g_captureWindow
= this;
664 Widget wMain
= (Widget
)GetMainWidget();
666 XtAddGrab(wMain
, True
, False
);
668 m_winCaptured
= true;
671 void wxWindow::DoReleaseMouse()
673 g_captureWindow
= NULL
;
674 if ( !m_winCaptured
)
677 Widget wMain
= (Widget
)GetMainWidget();
681 m_winCaptured
= false;
684 bool wxWindow::SetFont(const wxFont
& font
)
686 if ( !wxWindowBase::SetFont(font
) )
697 bool wxWindow::SetCursor(const wxCursor
& cursor
)
699 if ( !wxWindowBase::SetCursor(cursor
) )
705 // wxASSERT_MSG( m_cursor.Ok(),
706 // wxT("cursor must be valid after call to the base version"));
707 wxCursor
* cursor2
= NULL
;
709 cursor2
= & m_cursor
;
711 cursor2
= wxSTANDARD_CURSOR
;
713 WXDisplay
*dpy
= GetXDisplay();
714 WXCursor x_cursor
= cursor2
->GetXCursor(dpy
);
716 Widget w
= (Widget
) GetMainWidget();
717 Window win
= XtWindow(w
);
718 XDefineCursor((Display
*) dpy
, win
, (Cursor
) x_cursor
);
723 // Coordinates relative to the window
724 void wxWindow::WarpPointer (int x
, int y
)
726 Widget wClient
= (Widget
)GetClientWidget();
728 XWarpPointer(XtDisplay(wClient
), None
, XtWindow(wClient
), 0, 0, 0, 0, x
, y
);
731 // ---------------------------------------------------------------------------
733 // ---------------------------------------------------------------------------
735 int wxWindow::GetScrollPos(int orient
) const
737 if (orient
== wxHORIZONTAL
)
743 Widget scrollBar
= (Widget
) ((orient
== wxHORIZONTAL
) ? m_hScrollBar
: m_vScrollBar
);
747 XtVaGetValues(scrollBar
, XmNvalue
, &pos
, NULL
);
755 // This now returns the whole range, not just the number of positions that we
757 int wxWindow::GetScrollRange(int orient
) const
759 Widget scrollBar
= (Widget
)GetScrollbar((wxOrientation
)orient
);
760 // CE scintilla windows don't always have these scrollbars
761 // and it tends to pile up a whole bunch of asserts
762 //wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
766 XtVaGetValues(scrollBar
, XmNmaximum
, &range
, NULL
);
770 int wxWindow::GetScrollThumb(int orient
) const
772 Widget scrollBar
= (Widget
)GetScrollbar((wxOrientation
)orient
);
773 //wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
777 XtVaGetValues(scrollBar
, XmNsliderSize
, &thumb
, NULL
);
781 void wxWindow::SetScrollPos(int orient
, int pos
, bool WXUNUSED(refresh
))
783 Widget scrollBar
= (Widget
)GetScrollbar((wxOrientation
)orient
);
787 XtVaSetValues (scrollBar
, XmNvalue
, pos
, NULL
);
790 SetInternalScrollPos((wxOrientation
)orient
, pos
);
793 // New function that will replace some of the above.
794 void wxWindow::SetScrollbar(int orient
, int pos
, int thumbVisible
,
795 int range
, bool WXUNUSED(refresh
))
798 GetSize(& oldW
, & oldH
);
802 if (thumbVisible
== 0)
805 if (thumbVisible
> range
)
806 thumbVisible
= range
;
808 // Save the old state to see if it changed
809 WXWidget oldScrollBar
= GetScrollbar((wxOrientation
)orient
);
811 if (orient
== wxHORIZONTAL
)
813 if (thumbVisible
== range
)
816 DestroyScrollbar(wxHORIZONTAL
);
821 CreateScrollbar(wxHORIZONTAL
);
824 if (orient
== wxVERTICAL
)
826 if (thumbVisible
== range
)
829 DestroyScrollbar(wxVERTICAL
);
834 CreateScrollbar(wxVERTICAL
);
837 WXWidget newScrollBar
= GetScrollbar((wxOrientation
)orient
);
839 if (oldScrollBar
!= newScrollBar
)
841 // This is important! Without it, scrollbars misbehave badly.
842 XtUnrealizeWidget((Widget
) m_scrolledWindow
);
843 XmScrolledWindowSetAreas ((Widget
) m_scrolledWindow
, (Widget
) m_hScrollBar
, (Widget
) m_vScrollBar
, (Widget
) m_drawingArea
);
844 XtRealizeWidget((Widget
) m_scrolledWindow
);
845 XtManageChild((Widget
) m_scrolledWindow
);
850 XtVaSetValues((Widget
) newScrollBar
,
854 XmNsliderSize
, thumbVisible
,
858 SetInternalScrollPos((wxOrientation
)orient
, pos
);
861 GetSize(& newW
, & newH
);
863 // Adjusting scrollbars can resize the canvas accidentally
864 if (newW
!= oldW
|| newH
!= oldH
)
865 SetSize(-1, -1, oldW
, oldH
);
868 // Does a physical scroll
869 void wxWindow::ScrollWindow(int dx
, int dy
, const wxRect
*rect
)
874 // Use specified rectangle
875 x
= rect
->x
; y
= rect
->y
; w
= rect
->width
; h
= rect
->height
;
879 // Use whole client area
881 GetClientSize(& w
, & h
);
884 int x1
= (dx
>= 0) ? x
: x
- dx
;
885 int y1
= (dy
>= 0) ? y
: y
- dy
;
886 int w1
= w
- abs(dx
);
887 int h1
= h
- abs(dy
);
888 int x2
= (dx
>= 0) ? x
+ dx
: x
;
889 int y2
= (dy
>= 0) ? y
+ dy
: y
;
893 dc
.SetLogicalFunction (wxCOPY
);
895 Widget widget
= (Widget
) GetMainWidget();
896 Window window
= XtWindow(widget
);
897 Display
* display
= XtDisplay(widget
);
899 XCopyArea(display
, window
, window
, (GC
) dc
.GetGC(),
900 x1
, y1
, w1
, h1
, x2
, y2
);
902 dc
.SetAutoSetting(true);
903 wxBrush
brush(GetBackgroundColour(), wxSOLID
);
904 dc
.SetBrush(brush
); // FIXME: needed?
906 wxWindowList::compatibility_iterator cnode
= m_children
.GetFirst();
909 wxWindow
*child
= cnode
->GetData();
912 child
->GetSize( &sx
, &sy
);
913 wxPoint
pos( child
->GetPosition() );
914 child
->SetSize( pos
.x
+ dx
, pos
.y
+ dy
, sx
, sy
, wxSIZE_ALLOW_MINUS_ONE
);
915 cnode
= cnode
->GetNext();
918 // We'll add rectangles to the list of update rectangles according to which
919 // bits we've exposed.
924 wxRect
*rect
= new wxRect
;
930 XFillRectangle(display
, window
,
931 (GC
) dc
.GetGC(), rect
->x
, rect
->y
, rect
->width
, rect
->height
);
935 rect
->width
= rect
->width
;
936 rect
->height
= rect
->height
;
938 updateRects
.Append((wxObject
*) rect
);
942 wxRect
*rect
= new wxRect
;
944 rect
->x
= x
+ w
+ dx
;
949 XFillRectangle(display
, window
,
950 (GC
) dc
.GetGC(), rect
->x
, rect
->y
, rect
->width
,
955 rect
->width
= rect
->width
;
956 rect
->height
= rect
->height
;
958 updateRects
.Append((wxObject
*) rect
);
962 wxRect
*rect
= new wxRect
;
969 XFillRectangle(display
, window
,
970 (GC
) dc
.GetGC(), rect
->x
, rect
->y
, rect
->width
, rect
->height
);
974 rect
->width
= rect
->width
;
975 rect
->height
= rect
->height
;
977 updateRects
.Append((wxObject
*) rect
);
981 wxRect
*rect
= new wxRect
;
984 rect
->y
= y
+ h
+ dy
;
988 XFillRectangle(display
, window
,
989 (GC
) dc
.GetGC(), rect
->x
, rect
->y
, rect
->width
, rect
->height
);
993 rect
->width
= rect
->width
;
994 rect
->height
= rect
->height
;
996 updateRects
.Append((wxObject
*) rect
);
998 dc
.SetBrush(wxNullBrush
);
1000 // Now send expose events
1002 wxList::compatibility_iterator node
= updateRects
.GetFirst();
1005 wxRect
* rect
= (wxRect
*) node
->GetData();
1008 event
.type
= Expose
;
1009 event
.display
= display
;
1010 event
.send_event
= True
;
1011 event
.window
= window
;
1015 event
.width
= rect
->width
;
1016 event
.height
= rect
->height
;
1020 XSendEvent(display
, window
, False
, ExposureMask
, (XEvent
*)&event
);
1022 node
= node
->GetNext();
1026 // Delete the update rects
1027 node
= updateRects
.GetFirst();
1030 wxRect
* rect
= (wxRect
*) node
->GetData();
1032 node
= node
->GetNext();
1035 XmUpdateDisplay((Widget
) GetMainWidget());
1038 // ---------------------------------------------------------------------------
1040 // ---------------------------------------------------------------------------
1042 #if wxUSE_DRAG_AND_DROP
1044 void wxWindow::SetDropTarget(wxDropTarget
* WXUNUSED(pDropTarget
))
1051 // Old style file-manager drag&drop
1052 void wxWindow::DragAcceptFiles(bool WXUNUSED(accept
))
1057 // ----------------------------------------------------------------------------
1059 // ----------------------------------------------------------------------------
1063 void wxWindow::DoSetToolTip(wxToolTip
* WXUNUSED(tooltip
))
1068 #endif // wxUSE_TOOLTIPS
1070 // ----------------------------------------------------------------------------
1072 // ----------------------------------------------------------------------------
1076 bool wxWindow::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1078 if ( x
== -1 && y
== -1 )
1080 wxPoint mouse
= ScreenToClient(wxGetMousePosition());
1081 x
= mouse
.x
; y
= mouse
.y
;
1084 Widget widget
= (Widget
) GetMainWidget();
1086 /* The menuId field seems to be usused, so we'll use it to
1087 indicate whether a menu is popped up or not:
1088 0: Not currently created as a popup
1089 -1: Created as a popup, but not active
1093 if (menu
->GetParent() && (menu
->GetId() != -1))
1096 if (menu
->GetMainWidget())
1098 menu
->DestroyMenu(true);
1101 menu
->SetId(1); /* Mark as popped-up */
1102 menu
->CreateMenu(NULL
, widget
, menu
);
1103 menu
->SetInvokingWindow(this);
1107 // menu->SetParent(parent);
1108 // parent->children->Append(menu); // Store menu for later deletion
1110 Widget menuWidget
= (Widget
) menu
->GetMainWidget();
1118 if (this->IsKindOf(CLASSINFO(wxCanvas)))
1120 wxCanvas *canvas = (wxCanvas *) this;
1121 deviceX = canvas->GetDC ()->LogicalToDeviceX (x);
1122 deviceY = canvas->GetDC ()->LogicalToDeviceY (y);
1126 Display
*display
= XtDisplay (widget
);
1127 Window rootWindow
= RootWindowOfScreen (XtScreen((Widget
)widget
));
1128 Window thisWindow
= XtWindow (widget
);
1130 XTranslateCoordinates (display
, thisWindow
, rootWindow
, (int) deviceX
, (int) deviceY
,
1131 &rootX
, &rootY
, &childWindow
);
1133 XButtonPressedEvent event
;
1134 event
.type
= ButtonPress
;
1140 event
.x_root
= rootX
;
1141 event
.y_root
= rootY
;
1143 XmMenuPosition (menuWidget
, &event
);
1144 XtManageChild (menuWidget
);
1146 // The ID of a pop-up menu is 1 when active, and is set to 0 by the
1147 // idle-time destroy routine.
1148 // Waiting until this ID changes causes this function to block until
1149 // the menu has been dismissed and the widgets cleaned up.
1150 // In other words, once this routine returns, it is safe to delete
1152 // Ian Brown <ian.brown@printsoft.de>
1154 wxEventLoop evtLoop
;
1156 while (menu
->GetId() == 1)
1158 wxDoEventLoopIteration( evtLoop
);
1166 // ---------------------------------------------------------------------------
1167 // moving and resizing
1168 // ---------------------------------------------------------------------------
1170 bool wxWindow::PreResize()
1176 void wxWindow::DoGetSize(int *x
, int *y
) const
1178 Widget widget
= (Widget
)( !m_drawingArea
? GetTopWidget() :
1179 ( m_borderWidget
? m_borderWidget
:
1180 m_scrolledWindow
? m_scrolledWindow
:
1184 XtVaGetValues( widget
,
1192 void wxWindow::DoGetPosition(int *x
, int *y
) const
1194 Widget widget
= (Widget
)
1196 ( m_borderWidget
? m_borderWidget
: m_scrolledWindow
) :
1200 XtVaGetValues(widget
, XmNx
, &xx
, XmNy
, &yy
, NULL
);
1202 // We may be faking the client origin. So a window that's really at (0, 30)
1203 // may appear (to wxWin apps) to be at (0, 0).
1206 wxPoint
pt(GetParent()->GetClientAreaOrigin());
1215 void wxWindow::DoScreenToClient(int *x
, int *y
) const
1217 Widget widget
= (Widget
) GetClientWidget();
1218 Display
*display
= XtDisplay((Widget
) GetMainWidget());
1219 Window rootWindow
= RootWindowOfScreen(XtScreen(widget
));
1220 Window thisWindow
= XtWindow(widget
);
1225 XTranslateCoordinates(display
, rootWindow
, thisWindow
, xx
, yy
, x
, y
, &childWindow
);
1228 void wxWindow::DoClientToScreen(int *x
, int *y
) const
1230 Widget widget
= (Widget
) GetClientWidget();
1231 Display
*display
= XtDisplay(widget
);
1232 Window rootWindow
= RootWindowOfScreen(XtScreen(widget
));
1233 Window thisWindow
= XtWindow(widget
);
1238 XTranslateCoordinates(display
, thisWindow
, rootWindow
, xx
, yy
, x
, y
, &childWindow
);
1242 // Get size *available for subwindows* i.e. excluding menu bar etc.
1243 void wxWindow::DoGetClientSize(int *x
, int *y
) const
1245 Widget widget
= (Widget
) GetClientWidget();
1247 XtVaGetValues(widget
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
1248 if(x
) *x
= xx
; if(y
) *y
= yy
;
1251 void wxWindow::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1253 DoSetSizeIntr(x
, y
, width
, height
, sizeFlags
, false);
1256 void wxWindow::DoSetSizeIntr(int x
, int y
, int width
, int height
,
1257 int sizeFlags
, bool fromCtor
)
1259 // A bit of optimization to help sort out the flickers.
1260 int oldX
= -1, oldY
= -1, oldW
= -1, oldH
= -1;
1263 GetSize(& oldW
, & oldH
);
1264 GetPosition(& oldX
, & oldY
);
1267 if ( !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1275 wxSize
size(-1, -1);
1278 if ( ( sizeFlags
& wxSIZE_AUTO_WIDTH
) && !fromCtor
)
1280 size
= DoGetBestSize();
1291 if( ( sizeFlags
& wxSIZE_AUTO_HEIGHT
) && !fromCtor
)
1293 if( size
.x
== -1 ) size
= DoGetBestSize();
1302 if ( x
!= oldX
|| y
!= oldY
|| width
!= oldW
|| height
!= oldH
1303 || !wxNoOptimize::CanOptimize() )
1309 if (x
> -1 || (sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
))
1312 if (y
> -1 || (sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
))
1316 flags
|= wxMOVE_WIDTH
;
1319 flags
|= wxMOVE_HEIGHT
;
1321 int xx
= x
; int yy
= y
;
1322 AdjustForParentClientOrigin(xx
, yy
, sizeFlags
);
1324 DoMoveWindow( xx
, yy
, width
, height
);
1326 DoMoveWindowIntr( xx
, yy
, width
, height
, flags
);
1331 Widget widget
= (Widget
) GetTopWidget();
1335 bool managed
= XtIsManaged( widget
);
1337 XtUnmanageChild(widget
);
1341 AdjustForParentClientOrigin(xx
, yy
, sizeFlags
);
1343 DoMoveWindow(xx
, yy
, width
, height
);
1346 XtManageChild(widget
);
1350 void wxWindow::DoSetClientSize(int width
, int height
)
1354 Widget drawingArea
= (Widget
) m_drawingArea
;
1356 XtVaSetValues(drawingArea
, XmNresizePolicy
, XmRESIZE_ANY
, NULL
);
1359 XtVaSetValues(drawingArea
, XmNwidth
, width
, NULL
);
1361 XtVaSetValues(drawingArea
, XmNheight
, height
, NULL
);
1363 XtVaSetValues(drawingArea
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
);
1367 Widget widget
= (Widget
) GetTopWidget();
1370 XtVaSetValues(widget
, XmNwidth
, width
, NULL
);
1372 XtVaSetValues(widget
, XmNheight
, height
, NULL
);
1375 // For implementation purposes - sometimes decorations make the client area
1377 wxPoint
wxWindow::GetClientAreaOrigin() const
1379 return wxPoint(0, 0);
1382 void wxWindow::DoMoveWindowIntr(int xx
, int yy
, int w
, int h
,
1387 Widget drawingArea
= (Widget
) m_drawingArea
;
1388 Widget borderOrScrolled
= m_borderWidget
?
1389 (Widget
) m_borderWidget
:
1390 (Widget
) m_scrolledWindow
;
1392 bool managed
= XtIsManaged(borderOrScrolled
);
1394 XtUnmanageChild (borderOrScrolled
);
1395 XtVaSetValues(drawingArea
, XmNresizePolicy
, XmRESIZE_ANY
, NULL
);
1397 if (flags
& wxMOVE_X
)
1398 XtVaSetValues (borderOrScrolled
,
1401 if (flags
& wxMOVE_Y
)
1402 XtVaSetValues (borderOrScrolled
,
1406 if (flags
& wxMOVE_WIDTH
)
1410 XtVaSetValues ((Widget
) m_borderWidget
, XmNwidth
, w
, NULL
);
1411 short thick
, margin
;
1412 XtVaGetValues ((Widget
) m_borderWidget
,
1413 XmNshadowThickness
, &thick
,
1414 XmNmarginWidth
, &margin
,
1416 w
-= 2 * (thick
+ margin
);
1420 XtVaSetValues ((Widget
) m_scrolledWindow
, XmNwidth
, w
, NULL
);
1423 if (flags
& wxMOVE_HEIGHT
)
1427 XtVaSetValues ((Widget
) m_borderWidget
, XmNheight
, h
, NULL
);
1428 short thick
, margin
;
1429 XtVaGetValues ((Widget
) m_borderWidget
,
1430 XmNshadowThickness
, &thick
,
1431 XmNmarginHeight
, &margin
,
1433 h
-= 2 * (thick
+ margin
);
1437 XtVaSetValues ((Widget
) m_scrolledWindow
, XmNheight
, h
, NULL
);
1441 XtManageChild (borderOrScrolled
);
1442 XtVaSetValues(drawingArea
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
);
1449 XtVaSetValues((Widget
)GetTopWidget(),
1458 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
1460 DoMoveWindowIntr (x
, y
, width
, height
,
1461 wxMOVE_X
|wxMOVE_Y
|wxMOVE_WIDTH
|wxMOVE_HEIGHT
);
1464 // ---------------------------------------------------------------------------
1466 // ---------------------------------------------------------------------------
1468 int wxWindow::GetCharHeight() const
1470 wxCHECK_MSG( m_font
.Ok(), 0, "valid window font needed" );
1472 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(1.0, GetXDisplay());
1474 int direction
, ascent
, descent
;
1475 XCharStruct overall
;
1476 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1477 &descent
, &overall
);
1479 // return (overall.ascent + overall.descent);
1480 return (ascent
+ descent
);
1483 int wxWindow::GetCharWidth() const
1485 wxCHECK_MSG( m_font
.Ok(), 0, "valid window font needed" );
1487 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(1.0, GetXDisplay());
1489 int direction
, ascent
, descent
;
1490 XCharStruct overall
;
1491 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1492 &descent
, &overall
);
1494 return overall
.width
;
1497 void wxWindow::GetTextExtent(const wxString
& string
,
1499 int *descent
, int *externalLeading
,
1500 const wxFont
*theFont
) const
1502 wxFont
*fontToUse
= (wxFont
*)theFont
;
1504 fontToUse
= (wxFont
*) & m_font
;
1506 wxCHECK_RET( fontToUse
->Ok(), "valid window font needed" );
1508 WXFontStructPtr pFontStruct
= fontToUse
->GetFontStruct(1.0, GetXDisplay());
1510 int direction
, ascent
, descent2
;
1511 XCharStruct overall
;
1512 int slen
= string
.Len();
1516 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1517 &ascent
, &descent2
, &overall
);
1520 XTextExtents((XFontStruct
*) pFontStruct
, string
, slen
,
1521 &direction
, &ascent
, &descent2
, &overall
);
1524 *x
= (overall
.width
);
1526 *y
= (ascent
+ descent2
);
1528 *descent
= descent2
;
1529 if (externalLeading
)
1530 *externalLeading
= 0;
1534 // ----------------------------------------------------------------------------
1536 // ----------------------------------------------------------------------------
1538 void wxWindow::AddUpdateRect(int x
, int y
, int w
, int h
)
1540 m_updateRegion
.Union( x
, y
, w
, h
);
1543 void wxWindow::Refresh(bool eraseBack
, const wxRect
*rect
)
1545 m_needsRefresh
= true;
1546 Display
*display
= XtDisplay((Widget
) GetMainWidget());
1547 Window thisWindow
= XtWindow((Widget
) GetMainWidget());
1549 XExposeEvent dummyEvent
;
1551 GetSize(&width
, &height
);
1553 dummyEvent
.type
= Expose
;
1554 dummyEvent
.display
= display
;
1555 dummyEvent
.send_event
= True
;
1556 dummyEvent
.window
= thisWindow
;
1559 dummyEvent
.x
= rect
->x
;
1560 dummyEvent
.y
= rect
->y
;
1561 dummyEvent
.width
= rect
->width
;
1562 dummyEvent
.height
= rect
->height
;
1568 dummyEvent
.width
= width
;
1569 dummyEvent
.height
= height
;
1571 dummyEvent
.count
= 0;
1575 wxClientDC
dc(this);
1576 wxBrush
backgroundBrush(GetBackgroundColour(), wxSOLID
);
1577 dc
.SetBackground(backgroundBrush
);
1584 XSendEvent(display
, thisWindow
, False
, ExposureMask
, (XEvent
*)&dummyEvent
);
1587 void wxWindow::DoPaint()
1589 //TODO : make a temporary gc so we can do the XCopyArea below
1590 if (m_backingPixmap
&& !m_needsRefresh
)
1594 GC tempGC
= (GC
) dc
.GetBackingGC();
1596 Widget widget
= (Widget
) GetMainWidget();
1601 // We have to test whether it's a wxScrolledWindow (hack!) because
1602 // otherwise we don't know how many pixels have been scrolled. We might
1603 // solve this in the future by defining virtual wxWindow functions to get
1604 // the scroll position in pixels. Or, each kind of scrolled window has to
1605 // implement backing stores itself, using generic wxWidgets code.
1606 wxScrolledWindow
* scrolledWindow
= wxDynamicCast(this, wxScrolledWindow
);
1607 if ( scrolledWindow
)
1610 scrolledWindow
->CalcScrolledPosition(0, 0, &x
, &y
);
1616 // TODO: This could be optimized further by only copying the areas in the
1617 // current update region.
1619 // Only blit the part visible in the client area. The backing pixmap
1620 // always starts at 0, 0 but we may be looking at only a portion of it.
1621 wxSize clientArea
= GetClientSize();
1622 int toBlitX
= m_pixmapWidth
- scrollPosX
;
1623 int toBlitY
= m_pixmapHeight
- scrollPosY
;
1625 // Copy whichever is samller, the amount of pixmap we have to copy,
1626 // or the size of the client area.
1627 toBlitX
= wxMin(toBlitX
, clientArea
.x
);
1628 toBlitY
= wxMin(toBlitY
, clientArea
.y
);
1630 // Make sure we're not negative
1631 toBlitX
= wxMax(0, toBlitX
);
1632 toBlitY
= wxMax(0, toBlitY
);
1637 (Pixmap
) m_backingPixmap
,
1640 scrollPosX
, scrollPosY
, // Start at the scroll position
1641 toBlitX
, toBlitY
, // How much of the pixmap to copy
1647 wxWindowDC
dc(this);
1648 // Set an erase event first
1649 wxEraseEvent
eraseEvent(GetId(), &dc
);
1650 eraseEvent
.SetEventObject(this);
1651 GetEventHandler()->ProcessEvent(eraseEvent
);
1653 wxPaintEvent
event(GetId());
1654 event
.SetEventObject(this);
1655 GetEventHandler()->ProcessEvent(event
);
1657 m_needsRefresh
= false;
1661 // ----------------------------------------------------------------------------
1663 // ----------------------------------------------------------------------------
1665 // Responds to colour changes: passes event on to children.
1666 void wxWindow::OnSysColourChanged(wxSysColourChangedEvent
& event
)
1668 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
1671 // Only propagate to non-top-level windows
1672 wxWindow
*win
= node
->GetData();
1673 if ( win
->GetParent() )
1675 wxSysColourChangedEvent event2
;
1676 event
.SetEventObject(win
);
1677 win
->GetEventHandler()->ProcessEvent(event2
);
1680 node
= node
->GetNext();
1684 void wxWindow::OnInternalIdle()
1686 // This calls the UI-update mechanism (querying windows for
1687 // menu/toolbar/control state information)
1688 if (wxUpdateUIEvent::CanUpdate(this))
1689 UpdateWindowUI(wxUPDATE_UI_FROMIDLE
);
1692 // ----------------------------------------------------------------------------
1694 // ----------------------------------------------------------------------------
1696 bool wxWindow::ProcessAccelerator(wxKeyEvent
& event
)
1699 if (!m_acceleratorTable
.Ok())
1702 int count
= m_acceleratorTable
.GetCount();
1703 wxAcceleratorEntry
* entries
= m_acceleratorTable
.GetEntries();
1705 for (i
= 0; i
< count
; i
++)
1707 wxAcceleratorEntry
* entry
= & (entries
[i
]);
1708 if (entry
->MatchesEvent(event
))
1710 // Bingo, we have a match. Now find a control that matches the
1711 // entry command id.
1713 // Need to go up to the top of the window hierarchy, since it might
1714 // be e.g. a menu item
1715 wxWindow
* parent
= this;
1716 while ( parent
&& !parent
->IsTopLevel() )
1717 parent
= parent
->GetParent();
1722 wxFrame
* frame
= wxDynamicCast(parent
, wxFrame
);
1726 // Try for a menu command
1727 if (frame
->GetMenuBar())
1729 wxMenuItem
* item
= frame
->GetMenuBar()->FindItem(entry
->GetCommand());
1732 wxCommandEvent
commandEvent(wxEVT_COMMAND_MENU_SELECTED
, entry
->GetCommand());
1733 commandEvent
.SetEventObject(frame
);
1735 // If ProcessEvent returns true (it was handled), then
1736 // the calling code will skip the event handling.
1737 return frame
->GetEventHandler()->ProcessEvent(commandEvent
);
1743 // Find a child matching the command id
1744 wxWindow
* child
= parent
->FindWindow(entry
->GetCommand());
1750 // Now we process those kinds of windows that we can.
1751 // For now, only buttons.
1752 if ( wxDynamicCast(child
, wxButton
) )
1754 wxCommandEvent
commandEvent (wxEVT_COMMAND_BUTTON_CLICKED
, child
->GetId());
1755 commandEvent
.SetEventObject(child
);
1756 return child
->GetEventHandler()->ProcessEvent(commandEvent
);
1764 // We didn't match the key event against an accelerator.
1768 // ============================================================================
1769 // Motif-specific stuff from here on
1770 // ============================================================================
1772 // ----------------------------------------------------------------------------
1773 // function which maintain the global hash table mapping Widgets to wxWidgets
1774 // ----------------------------------------------------------------------------
1776 bool wxAddWindowToTable(Widget w
, wxWindow
*win
)
1778 wxWindow
*oldItem
= NULL
;
1779 if ((oldItem
= (wxWindow
*)wxWidgetHashTable
->Get ((long) w
)))
1781 wxLogDebug("Widget table clash: new widget is %ld, %s",
1782 (long)w
, win
->GetClassInfo()->GetClassName());
1786 wxWidgetHashTable
->Put((long) w
, win
);
1788 wxLogTrace("widget", "Widget 0x%p <-> window %p (%s)",
1789 (WXWidget
)w
, win
, win
->GetClassInfo()->GetClassName());
1794 wxWindow
*wxGetWindowFromTable(Widget w
)
1796 return (wxWindow
*)wxWidgetHashTable
->Get((long) w
);
1799 void wxDeleteWindowFromTable(Widget w
)
1801 wxLogTrace("widget", "Widget 0x%p", (WXWidget
)w
);
1803 wxWidgetHashTable
->Delete((long)w
);
1806 // ----------------------------------------------------------------------------
1807 // add/remove window from the table
1808 // ----------------------------------------------------------------------------
1810 // Add to hash table, add event handler
1811 bool wxWindow::AttachWidget (wxWindow
* WXUNUSED(parent
), WXWidget mainWidget
,
1812 WXWidget formWidget
, int x
, int y
, int width
, int height
)
1814 wxAddWindowToTable((Widget
) mainWidget
, this);
1815 XtAddEventHandler( (Widget
) mainWidget
,
1816 ButtonPressMask
| ButtonReleaseMask
1817 | PointerMotionMask
,
1819 wxPanelItemEventHandler
,
1825 XtOverrideTranslations ((Widget
) mainWidget
,
1826 ptr
= XtParseTranslationTable ("<Configure>: resize()"));
1827 XtFree ((char *) ptr
);
1830 // Some widgets have a parent form widget, e.g. wxRadioBox
1833 if (!wxAddWindowToTable((Widget
) formWidget
, this))
1837 XtOverrideTranslations ((Widget
) formWidget
,
1838 ptr
= XtParseTranslationTable ("<Configure>: resize()"));
1839 XtFree ((char *) ptr
);
1846 SetSize (x
, y
, width
, height
);
1851 // Remove event handler, remove from hash table
1852 bool wxWindow::DetachWidget(WXWidget widget
)
1854 XtRemoveEventHandler( (Widget
) widget
,
1855 ButtonPressMask
| ButtonReleaseMask
1856 | PointerMotionMask
,
1858 wxPanelItemEventHandler
,
1861 wxDeleteWindowFromTable((Widget
) widget
);
1865 // ----------------------------------------------------------------------------
1866 // Motif-specific accessors
1867 // ----------------------------------------------------------------------------
1869 WXWindow
wxWindow::GetClientXWindow() const
1871 Widget wMain
= (Widget
)GetClientWidget();
1873 return (WXWindow
) XtWindow(wMain
);
1875 return (WXWindow
) 0;
1878 // Get the underlying X window
1879 WXWindow
wxWindow::GetXWindow() const
1881 Widget wMain
= (Widget
)GetMainWidget();
1883 return (WXWindow
) XtWindow(wMain
);
1885 return (WXWindow
) 0;
1888 // Get the underlying X display
1889 WXDisplay
*wxWindow::GetXDisplay() const
1891 Widget wMain
= (Widget
)GetMainWidget();
1893 return (WXDisplay
*) XtDisplay(wMain
);
1895 return (WXDisplay
*) NULL
;
1898 WXWidget
wxWindow::GetMainWidget() const
1901 return m_drawingArea
;
1903 return m_mainWidget
;
1906 WXWidget
wxWindow::GetClientWidget() const
1908 if (m_drawingArea
!= (WXWidget
) 0)
1909 return m_drawingArea
;
1911 return GetMainWidget();
1914 WXWidget
wxWindow::GetTopWidget() const
1916 return GetMainWidget();
1919 WXWidget
wxWindow::GetLabelWidget() const
1921 return GetMainWidget();
1924 // ----------------------------------------------------------------------------
1926 // ----------------------------------------------------------------------------
1928 // All widgets should have this as their resize proc.
1929 // OnSize sent to wxWindow via client data.
1930 void wxWidgetResizeProc(Widget w
, XConfigureEvent
*WXUNUSED(event
),
1931 String
WXUNUSED(args
)[], int *WXUNUSED(num_args
))
1933 wxWindow
*win
= wxGetWindowFromTable(w
);
1937 if (win
->PreResize())
1940 win
->GetSize(&width
, &height
);
1941 wxSizeEvent
sizeEvent(wxSize(width
, height
), win
->GetId());
1942 sizeEvent
.SetEventObject(win
);
1943 win
->GetEventHandler()->ProcessEvent(sizeEvent
);
1947 static void wxCanvasRepaintProc(Widget drawingArea
,
1948 XtPointer clientData
,
1949 XmDrawingAreaCallbackStruct
* cbs
)
1951 if (!wxGetWindowFromTable(drawingArea
))
1954 XEvent
* event
= cbs
->event
;
1955 wxWindow
* win
= (wxWindow
*) clientData
;
1957 switch (event
->type
)
1961 win
->AddUpdateRect(event
->xexpose
.x
, event
->xexpose
.y
,
1962 event
->xexpose
.width
, event
->xexpose
.height
);
1964 if (event
-> xexpose
.count
== 0)
1973 // Unable to deal with Enter/Leave without a separate EventHandler (Motif 1.1.4)
1974 static void wxCanvasEnterLeave(Widget drawingArea
,
1975 XtPointer
WXUNUSED(clientData
),
1976 XCrossingEvent
* event
)
1978 XmDrawingAreaCallbackStruct cbs
;
1981 ((XCrossingEvent
&) ev
) = *event
;
1983 cbs
.reason
= XmCR_INPUT
;
1986 wxCanvasInputEvent(drawingArea
, (XtPointer
) NULL
, &cbs
);
1989 // Fix to make it work under Motif 1.0 (!)
1990 static void wxCanvasMotionEvent (Widget
WXUNUSED(drawingArea
),
1991 XButtonEvent
*WXUNUSED(event
))
1993 #if XmVersion <= 1000
1994 XmDrawingAreaCallbackStruct cbs
;
1997 ev
= *((XEvent
*) event
);
1998 cbs
.reason
= XmCR_INPUT
;
2001 wxCanvasInputEvent (drawingArea
, (XtPointer
) NULL
, &cbs
);
2002 #endif // XmVersion <= 1000
2005 static void wxCanvasInputEvent(Widget drawingArea
,
2006 XtPointer
WXUNUSED(data
),
2007 XmDrawingAreaCallbackStruct
* cbs
)
2009 wxWindow
*canvas
= wxGetWindowFromTable(drawingArea
);
2010 XEvent
* xevent
= cbs
->event
;
2015 if (cbs
->reason
!= XmCR_INPUT
)
2018 switch (xevent
->xany
.type
)
2026 wxMouseEvent
wxevent(0);
2027 if (wxTranslateMouseEvent(wxevent
, canvas
, drawingArea
, xevent
))
2029 canvas
->GetEventHandler()->ProcessEvent(wxevent
);
2035 wxKeyEvent
event (wxEVT_CHAR
);
2036 if (wxTranslateKeyEvent (event
, canvas
, (Widget
) 0, xevent
))
2038 // Implement wxFrame::OnCharHook by checking ancestor.
2039 wxWindow
*parent
= canvas
;
2040 while (parent
&& !parent
->IsTopLevel())
2041 parent
= parent
->GetParent();
2045 event
.SetEventType(wxEVT_CHAR_HOOK
);
2046 if (parent
->GetEventHandler()->ProcessEvent(event
))
2050 // For simplicity, OnKeyDown is the same as OnChar
2051 // TODO: filter modifier key presses from OnChar
2052 event
.SetEventType(wxEVT_KEY_DOWN
);
2054 // Only process OnChar if OnKeyDown didn't swallow it
2055 if (!canvas
->GetEventHandler()->ProcessEvent (event
))
2057 event
.SetEventType(wxEVT_CHAR
);
2058 canvas
->GetEventHandler()->ProcessEvent (event
);
2065 wxKeyEvent
event (wxEVT_KEY_UP
);
2066 if (wxTranslateKeyEvent (event
, canvas
, (Widget
) 0, xevent
))
2068 canvas
->GetEventHandler()->ProcessEvent (event
);
2074 if (xevent
->xfocus
.detail
!= NotifyPointer
)
2076 wxFocusEvent
event(wxEVT_SET_FOCUS
, canvas
->GetId());
2077 event
.SetEventObject(canvas
);
2078 canvas
->GetEventHandler()->ProcessEvent(event
);
2084 if (xevent
->xfocus
.detail
!= NotifyPointer
)
2086 wxFocusEvent
event(wxEVT_KILL_FOCUS
, canvas
->GetId());
2087 event
.SetEventObject(canvas
);
2088 canvas
->GetEventHandler()->ProcessEvent(event
);
2097 static void wxPanelItemEventHandler(Widget wid
,
2098 XtPointer
WXUNUSED(client_data
),
2100 Boolean
*continueToDispatch
)
2102 // Widget can be a label or the actual widget.
2104 wxWindow
*window
= wxGetWindowFromTable(wid
);
2107 wxMouseEvent
wxevent(0);
2108 if (wxTranslateMouseEvent(wxevent
, window
, wid
, event
))
2110 window
->GetEventHandler()->ProcessEvent(wxevent
);
2114 // TODO: probably the key to allowing default behaviour to happen. Say we
2115 // set a m_doDefault flag to false at the start of this function. Then in
2116 // e.g. wxWindow::OnMouseEvent we can call Default() which sets this flag to
2117 // true, indicating that default processing can happen. Thus, behaviour can
2118 // appear to be overridden just by adding an event handler and not calling
2119 // wxWindow::OnWhatever. ALSO, maybe we can use this instead of the current
2120 // way of handling drawing area events, to simplify things.
2121 *continueToDispatch
= True
;
2124 static void wxScrollBarCallback(Widget scrollbar
,
2125 XtPointer clientData
,
2126 XmScrollBarCallbackStruct
*cbs
)
2128 wxWindow
*win
= wxGetWindowFromTable(scrollbar
);
2129 wxOrientation orientation
= (wxOrientation
)(int)clientData
;
2131 wxEventType eventType
= wxEVT_NULL
;
2132 switch (cbs
->reason
)
2134 case XmCR_INCREMENT
:
2136 eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
2139 case XmCR_DECREMENT
:
2141 eventType
= wxEVT_SCROLLWIN_LINEUP
;
2146 eventType
= wxEVT_SCROLLWIN_THUMBTRACK
;
2149 case XmCR_VALUE_CHANGED
:
2151 eventType
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2154 case XmCR_PAGE_INCREMENT
:
2156 eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
2159 case XmCR_PAGE_DECREMENT
:
2161 eventType
= wxEVT_SCROLLWIN_PAGEUP
;
2166 eventType
= wxEVT_SCROLLWIN_TOP
;
2169 case XmCR_TO_BOTTOM
:
2171 eventType
= wxEVT_SCROLLWIN_BOTTOM
;
2176 // Should never get here
2177 wxFAIL_MSG("Unknown scroll event.");
2182 wxScrollWinEvent
event(eventType
,
2185 event
.SetEventObject( win
);
2186 win
->GetEventHandler()->ProcessEvent(event
);
2189 // For repainting arbitrary windows
2190 void wxUniversalRepaintProc(Widget w
, XtPointer
WXUNUSED(c_data
), XEvent
*event
, char *)
2195 wxWindow
* win
= wxGetWindowFromTable(w
);
2199 switch(event
-> type
)
2203 window
= (Window
) win
-> GetXWindow();
2204 display
= (Display
*) win
-> GetXDisplay();
2206 win
->AddUpdateRect(event
->xexpose
.x
, event
->xexpose
.y
,
2207 event
->xexpose
.width
, event
->xexpose
.height
);
2209 if (event
-> xexpose
.count
== 0)
2219 // ----------------------------------------------------------------------------
2220 // TranslateXXXEvent() functions
2221 // ----------------------------------------------------------------------------
2223 bool wxTranslateMouseEvent(wxMouseEvent
& wxevent
, wxWindow
*win
,
2224 Widget widget
, const XEvent
*xevent
)
2226 switch (xevent
->xany
.type
)
2231 fprintf(stderr
, "Widget 0x%p <-> window %p (%s), %s\n",
2232 (WXWidget
)widget
, win
, win
->GetClassInfo()->GetClassName(),
2233 (xevent
->xany
.type
== EnterNotify
? "ENTER" : "LEAVE"));
2239 int eventx
= xevent
->xbutton
.x
, eventy
= xevent
->xbutton
.y
;
2241 wxEventType eventType
= wxEVT_NULL
;
2243 if (xevent
->xany
.type
== LeaveNotify
)
2245 eventType
= wxEVT_LEAVE_WINDOW
;
2247 if (xevent
->xany
.type
== EnterNotify
)
2249 eventType
= wxEVT_ENTER_WINDOW
;
2251 else if (xevent
->xany
.type
== MotionNotify
)
2253 eventType
= wxEVT_MOTION
;
2255 if (xevent
->xmotion
.is_hint
== NotifyHint
)
2260 Display
*dpy
= XtDisplay (widget
);
2262 XQueryPointer (dpy
, XtWindow (widget
),
2264 &x_root
, &y_root
, &eventx
, &eventy
, &state
);
2267 else if (xevent
->xany
.type
== ButtonPress
)
2269 wxevent
.SetTimestamp(xevent
->xbutton
.time
);
2271 if (xevent
->xbutton
.button
== Button1
)
2273 eventType
= wxEVT_LEFT_DOWN
;
2276 else if (xevent
->xbutton
.button
== Button2
)
2278 eventType
= wxEVT_MIDDLE_DOWN
;
2281 else if (xevent
->xbutton
.button
== Button3
)
2283 eventType
= wxEVT_RIGHT_DOWN
;
2287 // check for a double click
2289 long dclickTime
= XtGetMultiClickTime(xevent
->xany
.display
);
2290 long ts
= wxevent
.GetTimestamp();
2292 int buttonLast
= win
->GetLastClickedButton();
2293 long lastTS
= win
->GetLastClickTime();
2294 if ( buttonLast
&& buttonLast
== button
&&
2295 (ts
- lastTS
) < dclickTime
)
2298 win
->SetLastClick(0, ts
);
2299 if ( eventType
== wxEVT_LEFT_DOWN
)
2300 eventType
= wxEVT_LEFT_DCLICK
;
2301 else if ( eventType
== wxEVT_MIDDLE_DOWN
)
2302 eventType
= wxEVT_MIDDLE_DCLICK
;
2303 else if ( eventType
== wxEVT_RIGHT_DOWN
)
2304 eventType
= wxEVT_RIGHT_DCLICK
;
2308 // not fast enough or different button
2309 win
->SetLastClick(button
, ts
);
2312 else if (xevent
->xany
.type
== ButtonRelease
)
2314 if (xevent
->xbutton
.button
== Button1
)
2316 eventType
= wxEVT_LEFT_UP
;
2318 else if (xevent
->xbutton
.button
== Button2
)
2320 eventType
= wxEVT_MIDDLE_UP
;
2322 else if (xevent
->xbutton
.button
== Button3
)
2324 eventType
= wxEVT_RIGHT_UP
;
2334 wxevent
.SetEventType(eventType
);
2337 XtVaGetValues(widget
, XmNx
, &x1
, XmNy
, &y1
, NULL
);
2340 win
->GetPosition(&x2
, &y2
);
2342 // The button x/y must be translated to wxWidgets
2343 // window space - the widget might be a label or button,
2347 if (widget
!= (Widget
)win
->GetMainWidget())
2353 wxevent
.m_x
= eventx
+ dx
;
2354 wxevent
.m_y
= eventy
+ dy
;
2356 wxevent
.m_leftDown
= ((eventType
== wxEVT_LEFT_DOWN
)
2357 || (event_left_is_down (xevent
)
2358 && (eventType
!= wxEVT_LEFT_UP
)));
2359 wxevent
.m_middleDown
= ((eventType
== wxEVT_MIDDLE_DOWN
)
2360 || (event_middle_is_down (xevent
)
2361 && (eventType
!= wxEVT_MIDDLE_UP
)));
2362 wxevent
.m_rightDown
= ((eventType
== wxEVT_RIGHT_DOWN
)
2363 || (event_right_is_down (xevent
)
2364 && (eventType
!= wxEVT_RIGHT_UP
)));
2366 wxevent
.m_shiftDown
= xevent
->xbutton
.state
& ShiftMask
;
2367 wxevent
.m_controlDown
= xevent
->xbutton
.state
& ControlMask
;
2368 wxevent
.m_altDown
= xevent
->xbutton
.state
& Mod3Mask
;
2369 wxevent
.m_metaDown
= xevent
->xbutton
.state
& Mod1Mask
;
2371 wxevent
.SetId(win
->GetId());
2372 wxevent
.SetEventObject(win
);
2380 bool wxTranslateKeyEvent(wxKeyEvent
& wxevent
, wxWindow
*win
,
2381 Widget
WXUNUSED(widget
), const XEvent
*xevent
)
2383 switch (xevent
->xany
.type
)
2391 (void) XLookupString((XKeyEvent
*)xevent
, buf
, 20, &keySym
, NULL
);
2392 int id
= wxCharCodeXToWX (keySym
);
2393 // id may be WXK_xxx code - these are outside ASCII range, so we
2394 // can't just use toupper() on id
2395 if (id
>= 'a' && id
<= 'z')
2398 if (xevent
->xkey
.state
& ShiftMask
)
2399 wxevent
.m_shiftDown
= true;
2400 if (xevent
->xkey
.state
& ControlMask
)
2401 wxevent
.m_controlDown
= true;
2402 if (xevent
->xkey
.state
& Mod3Mask
)
2403 wxevent
.m_altDown
= true;
2404 if (xevent
->xkey
.state
& Mod1Mask
)
2405 wxevent
.m_metaDown
= true;
2406 wxevent
.SetEventObject(win
);
2407 wxevent
.m_keyCode
= id
;
2408 wxevent
.SetTimestamp(xevent
->xkey
.time
);
2410 wxevent
.m_x
= xevent
->xbutton
.x
;
2411 wxevent
.m_y
= xevent
->xbutton
.y
;
2425 // ----------------------------------------------------------------------------
2427 // ----------------------------------------------------------------------------
2429 #define YAllocColor XAllocColor
2430 XColor g_itemColors
[5];
2431 int wxComputeColours (Display
*display
, wxColour
* back
, wxColour
* fore
)
2434 static XmColorProc colorProc
;
2436 result
= wxNO_COLORS
;
2440 g_itemColors
[0].red
= (((long) back
->Red ()) << 8);
2441 g_itemColors
[0].green
= (((long) back
->Green ()) << 8);
2442 g_itemColors
[0].blue
= (((long) back
->Blue ()) << 8);
2443 g_itemColors
[0].flags
= DoRed
| DoGreen
| DoBlue
;
2444 if (colorProc
== (XmColorProc
) NULL
)
2446 // Get a ptr to the actual function
2447 colorProc
= XmSetColorCalculation ((XmColorProc
) NULL
);
2448 // And set it back to motif.
2449 XmSetColorCalculation (colorProc
);
2451 (*colorProc
) (&g_itemColors
[wxBACK_INDEX
],
2452 &g_itemColors
[wxFORE_INDEX
],
2453 &g_itemColors
[wxSELE_INDEX
],
2454 &g_itemColors
[wxTOPS_INDEX
],
2455 &g_itemColors
[wxBOTS_INDEX
]);
2456 result
= wxBACK_COLORS
;
2460 g_itemColors
[wxFORE_INDEX
].red
= (((long) fore
->Red ()) << 8);
2461 g_itemColors
[wxFORE_INDEX
].green
= (((long) fore
->Green ()) << 8);
2462 g_itemColors
[wxFORE_INDEX
].blue
= (((long) fore
->Blue ()) << 8);
2463 g_itemColors
[wxFORE_INDEX
].flags
= DoRed
| DoGreen
| DoBlue
;
2464 if (result
== wxNO_COLORS
)
2465 result
= wxFORE_COLORS
;
2468 Display
*dpy
= display
;
2469 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dpy
);
2473 /* 5 Colours to allocate */
2474 for (int i
= 0; i
< 5; i
++)
2475 if (!YAllocColor (dpy
, cmap
, &g_itemColors
[i
]))
2476 result
= wxNO_COLORS
;
2480 /* Only 1 colour to allocate */
2481 if (!YAllocColor (dpy
, cmap
, &g_itemColors
[wxFORE_INDEX
]))
2482 result
= wxNO_COLORS
;
2488 // Changes the foreground and background colours to be derived from the current
2489 // background colour. To change the foreground colour, you must call
2490 // SetForegroundColour explicitly.
2491 void wxWindow::ChangeBackgroundColour()
2493 WXWidget mainWidget
= GetMainWidget();
2495 wxDoChangeBackgroundColour(mainWidget
, m_backgroundColour
);
2498 void wxWindow::ChangeForegroundColour()
2500 WXWidget mainWidget
= GetMainWidget();
2502 wxDoChangeForegroundColour(mainWidget
, m_foregroundColour
);
2503 if ( m_scrolledWindow
&& mainWidget
!= m_scrolledWindow
)
2504 wxDoChangeForegroundColour(m_scrolledWindow
, m_foregroundColour
);
2507 bool wxWindow::SetBackgroundColour(const wxColour
& col
)
2509 if ( !wxWindowBase::SetBackgroundColour(col
) )
2512 ChangeBackgroundColour();
2517 bool wxWindow::SetForegroundColour(const wxColour
& col
)
2519 if ( !wxWindowBase::SetForegroundColour(col
) )
2522 ChangeForegroundColour();
2527 void wxWindow::ChangeFont(bool keepOriginalSize
)
2529 // Note that this causes the widget to be resized back
2530 // to its original size! We therefore have to set the size
2531 // back again. TODO: a better way in Motif?
2532 Widget w
= (Widget
) GetLabelWidget(); // Usually the main widget
2533 if (w
&& m_font
.Ok())
2535 int width
, height
, width1
, height1
;
2536 GetSize(& width
, & height
);
2538 wxDoChangeFont( GetLabelWidget(), m_font
);
2540 GetSize(& width1
, & height1
);
2541 if (keepOriginalSize
&& (width
!= width1
|| height
!= height1
))
2543 SetSize(-1, -1, width
, height
);
2548 // ----------------------------------------------------------------------------
2550 // ----------------------------------------------------------------------------
2552 wxWindow
*wxGetActiveWindow()
2555 wxFAIL_MSG("Not implemented");
2560 wxWindow
*wxWindowBase::GetCapture()
2562 return (wxWindow
*)g_captureWindow
;
2566 // Find the wxWindow at the current mouse position, returning the mouse
2568 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
2570 return wxFindWindowAtPoint(wxGetMousePosition());
2573 // Get the current mouse position.
2574 wxPoint
wxGetMousePosition()
2576 Display
*display
= wxGlobalDisplay();
2577 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
2578 Window rootReturn
, childReturn
;
2579 int rootX
, rootY
, winX
, winY
;
2580 unsigned int maskReturn
;
2582 XQueryPointer (display
,
2586 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
2587 return wxPoint(rootX
, rootY
);
2591 // ----------------------------------------------------------------------------
2592 // wxNoOptimize: switch off size optimization
2593 // ----------------------------------------------------------------------------
2595 int wxNoOptimize::ms_count
= 0;