1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/motif/windows.cpp
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
24 #define XtDisplay XTDISPLAY
25 #define XtWindow XTWINDOW
26 #define XtScreen XTSCREEN
31 #include "wx/dcclient.h"
34 #include "wx/layout.h"
35 #include "wx/button.h"
36 #include "wx/settings.h"
38 #include "wx/scrolwin.h"
39 #include "wx/module.h"
40 #include "wx/menuitem.h"
42 #include "wx/evtloop.h"
45 #if wxUSE_DRAG_AND_DROP
49 // DoSetSizeIntr and DoMoveWindowIntr
51 // under Motif composite controls (such as wxCalendarCtrl or generic wxSpinCtrl
52 // did not work and/or segfaulted because
53 // 1) wxWindow::Create calls SetSize,
54 // which results in a call to DoSetSize much earlier than in the other ports
55 // 2) if wxWindow::Create is called (wxControl::Create calls it)
56 // then DoSetSize is never called, causing layout problems in composite
60 // 1) don't call SetSize, DoSetSize, DoMoveWindow, DoGetPosition,
61 // DoSetPosition directly or indirectly from wxWindow::Create
62 // 2) call DoMoveWindow from DoSetSize, allowing controls to override it
65 #pragma message disable nosimpint
69 #include <Xm/DrawingA.h>
70 #include <Xm/ScrolledW.h>
71 #include <Xm/ScrollBar.h>
74 #include <Xm/RowColumn.h> // for XmMenuPosition
76 #pragma message enable nosimpint
79 #include "wx/motif/private.h"
83 // ----------------------------------------------------------------------------
84 // global variables for this module
85 // ----------------------------------------------------------------------------
87 extern wxHashTable
*wxWidgetHashTable
;
88 static wxWindow
* g_captureWindow
= NULL
;
91 // ----------------------------------------------------------------------------
93 // ----------------------------------------------------------------------------
95 static void wxCanvasRepaintProc(Widget
, XtPointer
, XmDrawingAreaCallbackStruct
* cbs
);
96 static void wxCanvasInputEvent(Widget drawingArea
, XtPointer data
, XmDrawingAreaCallbackStruct
* cbs
);
97 static void wxCanvasMotionEvent(Widget
, XButtonEvent
* event
);
98 static void wxCanvasEnterLeave(Widget drawingArea
, XtPointer clientData
, XCrossingEvent
* event
);
99 static void wxScrollBarCallback(Widget widget
, XtPointer clientData
,
100 XmScrollBarCallbackStruct
*cbs
);
101 static void wxPanelItemEventHandler(Widget wid
,
102 XtPointer client_data
,
104 Boolean
*continueToDispatch
);
109 // Helper function for 16-bit fonts
110 static int str16len(const char *s
)
114 while (s
[0] && s
[1]) {
124 // ----------------------------------------------------------------------------
126 // ----------------------------------------------------------------------------
128 #define event_left_is_down(x) ((x)->xbutton.state & Button1Mask)
129 #define event_middle_is_down(x) ((x)->xbutton.state & Button2Mask)
130 #define event_right_is_down(x) ((x)->xbutton.state & Button3Mask)
132 // ----------------------------------------------------------------------------
134 // ----------------------------------------------------------------------------
136 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
138 BEGIN_EVENT_TABLE(wxWindow
, wxWindowBase
)
139 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged
)
142 // ============================================================================
144 // ============================================================================
146 // ----------------------------------------------------------------------------
148 // ----------------------------------------------------------------------------
150 void wxWindow::UnmanageAndDestroy(WXWidget widget
)
152 Widget w
= (Widget
)widget
;
160 bool wxWindow::MapOrUnmap(WXWidget widget
, bool domap
)
162 Widget w
= (Widget
)widget
;
166 // Rationale: a lot of common operations (including but not
167 // limited to moving, resizing and appending items to a listbox)
168 // unmamange the widget, do their work, then manage it again.
169 // This means that, for example adding an item to a listbox will show it,
170 // or that most controls are shown every time they are moved or resized!
171 XtSetMappedWhenManaged( w
, domap
);
173 // if the widget is not unmanaged, it still intercepts
174 // mouse events, even if it is not mapped (and hence invisible)
189 // ----------------------------------------------------------------------------
191 // ----------------------------------------------------------------------------
193 void wxWindow::Init()
196 m_needsRefresh
= true;
197 m_mainWidget
= (WXWidget
) 0;
199 m_winCaptured
= false;
207 m_drawingArea
= (WXWidget
) 0;
212 m_backingPixmap
= (WXPixmap
) 0;
223 // real construction (Init() must have been called before!)
224 bool wxWindow::Create(wxWindow
*parent
, wxWindowID id
,
228 const wxString
& name
)
230 wxCHECK_MSG( parent
, false, "can't create wxWindow without parent" );
232 CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
);
234 parent
->AddChild(this);
236 m_backgroundColour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
237 m_foregroundColour
= *wxBLACK
;
239 //// TODO: we should probably optimize by only creating a
240 //// a drawing area if we have one or more scrollbars (wxVSCROLL/wxHSCROLL).
241 //// But for now, let's simplify things by always creating the
242 //// drawing area, since otherwise the translations are different.
244 // New translations for getting mouse motion feedback
245 static const String translations
= wxMOTIF_STR(
246 "<Btn1Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
247 <Btn2Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
248 <Btn3Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
249 <BtnMotion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
250 <Btn1Down>: DrawingAreaInput() ManagerGadgetArm()\n\
251 <Btn2Down>: DrawingAreaInput() ManagerGadgetArm()\n\
252 <Btn3Down>: DrawingAreaInput() ManagerGadgetArm()\n\
253 <Btn1Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
254 <Btn2Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
255 <Btn3Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
256 <Motion>: wxCanvasMotionEvent() DrawingAreaInput()\n\
257 <EnterWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
258 <LeaveWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
259 <Key>: DrawingAreaInput()");
261 XtActionsRec actions
[1];
262 actions
[0].string
= wxMOTIF_STR("wxCanvasMotionEvent");
263 actions
[0].proc
= (XtActionProc
) wxCanvasMotionEvent
;
264 XtAppAddActions ((XtAppContext
) wxTheApp
->GetAppContext(), actions
, 1);
266 Widget parentWidget
= (Widget
) parent
->GetClientWidget();
267 m_borderWidget
= wxCreateBorderWidget( (WXWidget
)parentWidget
, style
);
269 m_scrolledWindow
= (WXWidget
)XtVaCreateManagedWidget
272 xmScrolledWindowWidgetClass
,
273 m_borderWidget
? (Widget
) m_borderWidget
275 XmNresizePolicy
, XmRESIZE_NONE
,
277 XmNscrollingPolicy
, XmAPPLICATION_DEFINED
,
278 //XmNscrollBarDisplayPolicy, XmAS_NEEDED,
282 XtTranslations ptr
= XtParseTranslationTable(translations
);
283 m_drawingArea
= (WXWidget
)XtVaCreateWidget
286 xmDrawingAreaWidgetClass
, (Widget
) m_scrolledWindow
,
287 XmNunitType
, XmPIXELS
,
288 // XmNresizePolicy, XmRESIZE_ANY,
289 XmNresizePolicy
, XmRESIZE_NONE
,
292 XmNtranslations
, ptr
,
295 XtFree((char *) ptr
);
298 if (GetWindowStyleFlag() & wxOVERRIDE_KEY_TRANSLATIONS
)
300 ptr
= XtParseTranslationTable ("<Key>: DrawingAreaInput()");
301 XtOverrideTranslations ((Widget
) m_drawingArea
, ptr
);
302 XtFree ((char *) ptr
);
306 wxAddWindowToTable((Widget
) m_drawingArea
, this);
307 wxAddWindowToTable((Widget
) m_scrolledWindow
, this);
309 // This order is very important in Motif 1.2.1
310 XtRealizeWidget ((Widget
) m_scrolledWindow
);
311 XtRealizeWidget ((Widget
) m_drawingArea
);
312 XtManageChild ((Widget
) m_drawingArea
);
314 ptr
= XtParseTranslationTable("<Configure>: resize()");
315 XtOverrideTranslations((Widget
) m_drawingArea
, ptr
);
316 XtFree ((char *) ptr
);
318 XtAddCallback ((Widget
) m_drawingArea
, XmNexposeCallback
, (XtCallbackProc
) wxCanvasRepaintProc
, (XtPointer
) this);
319 XtAddCallback ((Widget
) m_drawingArea
, XmNinputCallback
, (XtCallbackProc
) wxCanvasInputEvent
, (XtPointer
) this);
322 (Widget
)m_drawingArea
,
323 PointerMotionHintMask
| EnterWindowMask
|
324 LeaveWindowMask
| FocusChangeMask
,
326 (XtEventHandler
) wxCanvasEnterLeave
,
330 // Scrolled widget needs to have its colour changed or we get a little blue
331 // square where the scrollbars abutt
332 wxColour backgroundColour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
333 wxDoChangeBackgroundColour(m_scrolledWindow
, backgroundColour
, true);
334 wxDoChangeBackgroundColour(m_drawingArea
, backgroundColour
, true);
336 XmScrolledWindowSetAreas(
337 (Widget
)m_scrolledWindow
,
338 (Widget
) 0, (Widget
) 0,
339 (Widget
) m_drawingArea
);
341 // Without this, the cursor may not be restored properly (e.g. in splitter
343 SetCursor(*wxSTANDARD_CURSOR
);
344 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
345 DoSetSizeIntr(pos
.x
, pos
.y
, size
.x
,size
.y
, wxSIZE_AUTO
, true);
350 wxWindow::~wxWindow()
352 if (g_captureWindow
== this)
353 g_captureWindow
= NULL
;
355 m_isBeingDeleted
= true;
357 // Motif-specific actions first
358 WXWidget wMain
= GetMainWidget();
361 // Removes event handlers
365 // If m_drawingArea, we're a fully-fledged window with drawing area,
366 // scrollbars etc. (what wxCanvas used to be)
369 // Destroy children before destroying self
373 XFreePixmap (XtDisplay ((Widget
) GetMainWidget()), (Pixmap
) m_backingPixmap
);
375 Widget w
= (Widget
) m_drawingArea
;
376 wxDeleteWindowFromTable(w
);
381 m_drawingArea
= (WXWidget
) 0;
384 // Only if we're _really_ a canvas (not a dialog box/panel)
385 if (m_scrolledWindow
)
387 wxDeleteWindowFromTable((Widget
) m_scrolledWindow
);
392 wxDeleteWindowFromTable((Widget
) m_hScrollBar
);
393 XtUnmanageChild((Widget
) m_hScrollBar
);
397 wxDeleteWindowFromTable((Widget
) m_vScrollBar
);
398 XtUnmanageChild((Widget
) m_vScrollBar
);
402 XtDestroyWidget((Widget
) m_hScrollBar
);
404 XtDestroyWidget((Widget
) m_vScrollBar
);
406 UnmanageAndDestroy(m_scrolledWindow
);
410 XtDestroyWidget ((Widget
) m_borderWidget
);
411 m_borderWidget
= (WXWidget
) 0;
414 else // Why wasn't this here before? JACS 8/3/2000
418 // Destroy the window
421 // If this line (XtDestroyWidget) causes a crash, you may comment it out.
422 // Child widgets will get destroyed automatically when a frame
423 // or dialog is destroyed, but before that you may get some memory
424 // leaks and potential layout problems if you delete and then add
427 // GRG, Feb/2000: commented this out when adding support for
428 // wxSCROLL[WIN]_THUMBRELEASE events. Also it was reported
429 // that this call crashed wxMotif under OS/2, so it seems
430 // that leaving it out is the right thing to do.
431 // SN, Feb/2000: newgrid/griddemo shows why it is needed :-(
432 XtDestroyWidget((Widget
) GetMainWidget());
433 SetMainWidget((WXWidget
) NULL
);
437 // ----------------------------------------------------------------------------
438 // scrollbar management
439 // ----------------------------------------------------------------------------
441 WXWidget
wxWindow::DoCreateScrollBar(WXWidget parent
,
442 wxOrientation orientation
,
445 int orient
= ( orientation
& wxHORIZONTAL
) ? XmHORIZONTAL
: XmVERTICAL
;
447 XtVaCreateManagedWidget( "scrollBarWidget",
448 xmScrollBarWidgetClass
, (Widget
)parent
,
449 XmNorientation
, orient
,
454 XtPointer o
= (XtPointer
)orientation
;
455 XtCallbackProc cb
= (XtCallbackProc
)callback
;
457 XtAddCallback( sb
, XmNvalueChangedCallback
, cb
, o
);
458 XtAddCallback( sb
, XmNdragCallback
, cb
, o
);
459 XtAddCallback( sb
, XmNincrementCallback
, cb
, o
);
460 XtAddCallback( sb
, XmNdecrementCallback
, cb
, o
);
461 XtAddCallback( sb
, XmNpageIncrementCallback
, cb
, o
);
462 XtAddCallback( sb
, XmNpageDecrementCallback
, cb
, o
);
463 XtAddCallback( sb
, XmNtoTopCallback
, cb
, o
);
464 XtAddCallback( sb
, XmNtoBottomCallback
, cb
, o
);
470 void wxWindow::CreateScrollbar(wxOrientation orientation
)
472 wxCHECK_RET( m_drawingArea
, "this window can't have scrollbars" );
474 XtVaSetValues( (Widget
) m_scrolledWindow
,
475 XmNresizePolicy
, XmRESIZE_NONE
,
478 wxColour backgroundColour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
479 // Add scrollbars if required
480 if (orientation
== wxHORIZONTAL
)
482 m_hScrollBar
= DoCreateScrollBar( m_scrolledWindow
, wxHORIZONTAL
,
483 (void (*)())wxScrollBarCallback
);
485 wxDoChangeBackgroundColour(m_hScrollBar
, backgroundColour
, true);
487 XtRealizeWidget( (Widget
)m_hScrollBar
);
489 XtVaSetValues((Widget
) m_scrolledWindow
,
490 XmNhorizontalScrollBar
, (Widget
) m_hScrollBar
,
493 wxAddWindowToTable( (Widget
)m_hScrollBar
, this );
495 else if (orientation
== wxVERTICAL
)
497 m_vScrollBar
= DoCreateScrollBar( m_scrolledWindow
, wxVERTICAL
,
498 (void (*)())wxScrollBarCallback
);
500 wxDoChangeBackgroundColour(m_vScrollBar
, backgroundColour
, true);
502 XtRealizeWidget((Widget
)m_vScrollBar
);
504 XtVaSetValues((Widget
) m_scrolledWindow
,
505 XmNverticalScrollBar
, (Widget
) m_vScrollBar
,
508 wxAddWindowToTable( (Widget
)m_vScrollBar
, this );
511 XtVaSetValues( (Widget
) m_scrolledWindow
,
512 XmNresizePolicy
, XmRESIZE_ANY
,
516 void wxWindow::DestroyScrollbar(wxOrientation orientation
)
518 wxCHECK_RET( m_drawingArea
, "this window can't have scrollbars" );
520 XtVaSetValues((Widget
) m_scrolledWindow
,
521 XmNresizePolicy
, XmRESIZE_NONE
,
523 String stringSB
= orientation
== wxHORIZONTAL
?
524 XmNhorizontalScrollBar
: XmNverticalScrollBar
;
525 WXWidget
* widgetSB
= orientation
== wxHORIZONTAL
?
526 &m_hScrollBar
: &m_vScrollBar
;
530 wxDeleteWindowFromTable( (Widget
)*widgetSB
);
531 XtDestroyWidget( (Widget
)*widgetSB
);
532 *widgetSB
= (WXWidget
)NULL
;
535 XtVaSetValues( (Widget
)m_scrolledWindow
,
536 stringSB
, (Widget
) 0,
539 XtVaSetValues((Widget
) m_scrolledWindow
,
540 XmNresizePolicy
, XmRESIZE_ANY
,
544 // ---------------------------------------------------------------------------
546 // ---------------------------------------------------------------------------
548 void wxWindow::SetFocus()
550 Widget wMain
= (Widget
) GetMainWidget();
551 XmProcessTraversal(wMain
, XmTRAVERSE_CURRENT
);
552 XmProcessTraversal((Widget
) GetMainWidget(), XmTRAVERSE_CURRENT
);
555 // Get the window with the focus
556 wxWindow
*wxWindowBase::DoFindFocus()
559 // (1) Can there be multiple focussed widgets in an application?
560 // In which case we need to find the top-level window that's
562 // (2) The widget with the focus may not be in the widget table
563 // depending on which widgets I put in the table
564 wxWindow
*winFocus
= (wxWindow
*)NULL
;
565 for ( wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetFirst();
567 node
= node
->GetNext() )
569 wxWindow
*win
= node
->GetData();
571 Widget w
= XmGetFocusWidget ((Widget
) win
->GetTopWidget());
573 if (w
!= (Widget
) NULL
)
575 winFocus
= wxGetWindowFromTable(w
);
584 bool wxWindow::Enable(bool enable
)
586 if ( !wxWindowBase::Enable(enable
) )
589 Widget wMain
= (Widget
)GetMainWidget();
592 XtSetSensitive(wMain
, enable
);
593 XmUpdateDisplay(wMain
);
599 bool wxWindow::Show(bool show
)
601 if ( !wxWindowBase::Show(show
) )
604 if (m_borderWidget
|| m_scrolledWindow
)
606 MapOrUnmap(m_borderWidget
? m_borderWidget
: m_scrolledWindow
, show
);
607 // MapOrUnmap(m_drawingArea, show);
611 if ( !MapOrUnmap(GetTopWidget(), show
) )
612 MapOrUnmap(GetMainWidget(), show
);
618 // Raise the window to the top of the Z order
619 void wxWindow::Raise()
621 Widget wTop
= (Widget
) GetTopWidget();
622 Window window
= XtWindow(wTop
);
623 XRaiseWindow(XtDisplay(wTop
), window
);
626 // Lower the window to the bottom of the Z order
627 void wxWindow::Lower()
629 Widget wTop
= (Widget
) GetTopWidget();
630 Window window
= XtWindow(wTop
);
631 XLowerWindow(XtDisplay(wTop
), window
);
634 void wxWindow::SetLabel(const wxString
& label
)
636 XtVaSetValues((Widget
)GetMainWidget(), XmNtitle
, label
.c_str(), NULL
);
639 wxString
wxWindow::GetLabel() const
642 XtVaGetValues((Widget
)GetMainWidget(), XmNtitle
, &label
, NULL
);
644 return wxString(label
);
647 void wxWindow::DoCaptureMouse()
649 g_captureWindow
= this;
653 Widget wMain
= (Widget
)GetMainWidget();
655 XtAddGrab(wMain
, True
, False
);
657 m_winCaptured
= true;
660 void wxWindow::DoReleaseMouse()
662 g_captureWindow
= NULL
;
663 if ( !m_winCaptured
)
666 Widget wMain
= (Widget
)GetMainWidget();
670 m_winCaptured
= false;
673 bool wxWindow::SetFont(const wxFont
& font
)
675 if ( !wxWindowBase::SetFont(font
) )
686 bool wxWindow::SetCursor(const wxCursor
& cursor
)
688 if ( !wxWindowBase::SetCursor(cursor
) )
694 // wxASSERT_MSG( m_cursor.Ok(),
695 // wxT("cursor must be valid after call to the base version"));
696 wxCursor
* cursor2
= NULL
;
698 cursor2
= & m_cursor
;
700 cursor2
= wxSTANDARD_CURSOR
;
702 WXDisplay
*dpy
= GetXDisplay();
703 WXCursor x_cursor
= cursor2
->GetXCursor(dpy
);
705 Widget w
= (Widget
) GetMainWidget();
706 Window win
= XtWindow(w
);
707 XDefineCursor((Display
*) dpy
, win
, (Cursor
) x_cursor
);
712 // Coordinates relative to the window
713 void wxWindow::WarpPointer (int x
, int y
)
715 Widget wClient
= (Widget
)GetClientWidget();
717 XWarpPointer(XtDisplay(wClient
), None
, XtWindow(wClient
), 0, 0, 0, 0, x
, y
);
720 // ---------------------------------------------------------------------------
722 // ---------------------------------------------------------------------------
724 int wxWindow::GetScrollPos(int orient
) const
726 if (orient
== wxHORIZONTAL
)
732 Widget scrollBar
= (Widget
) ((orient
== wxHORIZONTAL
) ? m_hScrollBar
: m_vScrollBar
);
736 XtVaGetValues(scrollBar
, XmNvalue
, &pos
, NULL
);
744 // This now returns the whole range, not just the number of positions that we
746 int wxWindow::GetScrollRange(int orient
) const
748 Widget scrollBar
= (Widget
)GetScrollbar((wxOrientation
)orient
);
749 // CE scintilla windows don't always have these scrollbars
750 // and it tends to pile up a whole bunch of asserts
751 //wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
755 XtVaGetValues(scrollBar
, XmNmaximum
, &range
, NULL
);
759 int wxWindow::GetScrollThumb(int orient
) const
761 Widget scrollBar
= (Widget
)GetScrollbar((wxOrientation
)orient
);
762 //wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
766 XtVaGetValues(scrollBar
, XmNsliderSize
, &thumb
, NULL
);
770 void wxWindow::SetScrollPos(int orient
, int pos
, bool WXUNUSED(refresh
))
772 Widget scrollBar
= (Widget
)GetScrollbar((wxOrientation
)orient
);
776 XtVaSetValues (scrollBar
, XmNvalue
, pos
, NULL
);
779 SetInternalScrollPos((wxOrientation
)orient
, pos
);
782 // New function that will replace some of the above.
783 void wxWindow::SetScrollbar(int orient
, int pos
, int thumbVisible
,
784 int range
, bool WXUNUSED(refresh
))
787 GetSize(& oldW
, & oldH
);
791 if (thumbVisible
== 0)
794 if (thumbVisible
> range
)
795 thumbVisible
= range
;
797 // Save the old state to see if it changed
798 WXWidget oldScrollBar
= GetScrollbar((wxOrientation
)orient
);
800 if (orient
== wxHORIZONTAL
)
802 if (thumbVisible
== range
)
805 DestroyScrollbar(wxHORIZONTAL
);
810 CreateScrollbar(wxHORIZONTAL
);
813 if (orient
== wxVERTICAL
)
815 if (thumbVisible
== range
)
818 DestroyScrollbar(wxVERTICAL
);
823 CreateScrollbar(wxVERTICAL
);
826 WXWidget newScrollBar
= GetScrollbar((wxOrientation
)orient
);
828 if (oldScrollBar
!= newScrollBar
)
830 // This is important! Without it, scrollbars misbehave badly.
831 XtUnrealizeWidget((Widget
) m_scrolledWindow
);
832 XmScrolledWindowSetAreas ((Widget
) m_scrolledWindow
, (Widget
) m_hScrollBar
, (Widget
) m_vScrollBar
, (Widget
) m_drawingArea
);
833 XtRealizeWidget((Widget
) m_scrolledWindow
);
834 XtManageChild((Widget
) m_scrolledWindow
);
839 XtVaSetValues((Widget
) newScrollBar
,
843 XmNsliderSize
, thumbVisible
,
847 SetInternalScrollPos((wxOrientation
)orient
, pos
);
850 GetSize(& newW
, & newH
);
852 // Adjusting scrollbars can resize the canvas accidentally
853 if (newW
!= oldW
|| newH
!= oldH
)
854 SetSize(wxDefaultCoord
, wxDefaultCoord
, oldW
, oldH
);
857 // Does a physical scroll
858 void wxWindow::ScrollWindow(int dx
, int dy
, const wxRect
*rect
)
863 // Use specified rectangle
864 x
= rect
->x
; y
= rect
->y
; w
= rect
->width
; h
= rect
->height
;
868 // Use whole client area
870 GetClientSize(& w
, & h
);
873 int x1
= (dx
>= 0) ? x
: x
- dx
;
874 int y1
= (dy
>= 0) ? y
: y
- dy
;
875 int w1
= w
- abs(dx
);
876 int h1
= h
- abs(dy
);
877 int x2
= (dx
>= 0) ? x
+ dx
: x
;
878 int y2
= (dy
>= 0) ? y
+ dy
: y
;
882 dc
.SetLogicalFunction (wxCOPY
);
884 Widget widget
= (Widget
) GetMainWidget();
885 Window window
= XtWindow(widget
);
886 Display
* display
= XtDisplay(widget
);
888 XCopyArea(display
, window
, window
, (GC
) dc
.GetGC(),
889 x1
, y1
, w1
, h1
, x2
, y2
);
891 dc
.SetAutoSetting(true);
892 wxBrush
brush(GetBackgroundColour(), wxSOLID
);
893 dc
.SetBrush(brush
); // FIXME: needed?
895 wxWindowList::compatibility_iterator cnode
= m_children
.GetFirst();
898 wxWindow
*child
= cnode
->GetData();
901 child
->GetSize( &sx
, &sy
);
902 wxPoint
pos( child
->GetPosition() );
903 child
->SetSize( pos
.x
+ dx
, pos
.y
+ dy
, sx
, sy
, wxSIZE_ALLOW_MINUS_ONE
);
904 cnode
= cnode
->GetNext();
907 // We'll add rectangles to the list of update rectangles according to which
908 // bits we've exposed.
913 wxRect
*rect
= new wxRect
;
919 XFillRectangle(display
, window
,
920 (GC
) dc
.GetGC(), rect
->x
, rect
->y
, rect
->width
, rect
->height
);
924 rect
->width
= rect
->width
;
925 rect
->height
= rect
->height
;
927 updateRects
.Append((wxObject
*) rect
);
931 wxRect
*rect
= new wxRect
;
933 rect
->x
= x
+ w
+ dx
;
938 XFillRectangle(display
, window
,
939 (GC
) dc
.GetGC(), rect
->x
, rect
->y
, rect
->width
,
944 rect
->width
= rect
->width
;
945 rect
->height
= rect
->height
;
947 updateRects
.Append((wxObject
*) rect
);
951 wxRect
*rect
= new wxRect
;
958 XFillRectangle(display
, window
,
959 (GC
) dc
.GetGC(), rect
->x
, rect
->y
, rect
->width
, rect
->height
);
963 rect
->width
= rect
->width
;
964 rect
->height
= rect
->height
;
966 updateRects
.Append((wxObject
*) rect
);
970 wxRect
*rect
= new wxRect
;
973 rect
->y
= y
+ h
+ dy
;
977 XFillRectangle(display
, window
,
978 (GC
) dc
.GetGC(), rect
->x
, rect
->y
, rect
->width
, rect
->height
);
982 rect
->width
= rect
->width
;
983 rect
->height
= rect
->height
;
985 updateRects
.Append((wxObject
*) rect
);
987 dc
.SetBrush(wxNullBrush
);
989 // Now send expose events
991 wxList::compatibility_iterator node
= updateRects
.GetFirst();
994 wxRect
* rect
= (wxRect
*) node
->GetData();
998 event
.display
= display
;
999 event
.send_event
= True
;
1000 event
.window
= window
;
1004 event
.width
= rect
->width
;
1005 event
.height
= rect
->height
;
1009 XSendEvent(display
, window
, False
, ExposureMask
, (XEvent
*)&event
);
1011 node
= node
->GetNext();
1015 // Delete the update rects
1016 node
= updateRects
.GetFirst();
1019 wxRect
* rect
= (wxRect
*) node
->GetData();
1021 node
= node
->GetNext();
1024 XmUpdateDisplay((Widget
) GetMainWidget());
1027 // ---------------------------------------------------------------------------
1029 // ---------------------------------------------------------------------------
1031 #if wxUSE_DRAG_AND_DROP
1033 void wxWindow::SetDropTarget(wxDropTarget
* WXUNUSED(pDropTarget
))
1040 // Old style file-manager drag&drop
1041 void wxWindow::DragAcceptFiles(bool WXUNUSED(accept
))
1046 // ----------------------------------------------------------------------------
1048 // ----------------------------------------------------------------------------
1052 void wxWindow::DoSetToolTip(wxToolTip
* WXUNUSED(tooltip
))
1057 #endif // wxUSE_TOOLTIPS
1059 // ----------------------------------------------------------------------------
1061 // ----------------------------------------------------------------------------
1065 bool wxWindow::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1067 if ( x
== wxDefaultCoord
&& y
== wxDefaultCoord
)
1069 wxPoint mouse
= ScreenToClient(wxGetMousePosition());
1070 x
= mouse
.x
; y
= mouse
.y
;
1073 Widget widget
= (Widget
) GetMainWidget();
1075 /* The menuId field seems to be usused, so we'll use it to
1076 indicate whether a menu is popped up or not:
1077 0: Not currently created as a popup
1078 -1: Created as a popup, but not active
1082 if (menu
->GetParent() && (menu
->GetId() != -1))
1085 if (menu
->GetMainWidget())
1087 menu
->DestroyMenu(true);
1090 menu
->SetId(1); /* Mark as popped-up */
1091 menu
->CreateMenu(NULL
, widget
, menu
, 0);
1092 menu
->SetInvokingWindow(this);
1096 // menu->SetParent(parent);
1097 // parent->children->Append(menu); // Store menu for later deletion
1099 Widget menuWidget
= (Widget
) menu
->GetMainWidget();
1107 if (this->IsKindOf(CLASSINFO(wxCanvas)))
1109 wxCanvas *canvas = (wxCanvas *) this;
1110 deviceX = canvas->GetDC ()->LogicalToDeviceX (x);
1111 deviceY = canvas->GetDC ()->LogicalToDeviceY (y);
1115 Display
*display
= XtDisplay (widget
);
1116 Window rootWindow
= RootWindowOfScreen (XtScreen((Widget
)widget
));
1117 Window thisWindow
= XtWindow (widget
);
1119 XTranslateCoordinates (display
, thisWindow
, rootWindow
, (int) deviceX
, (int) deviceY
,
1120 &rootX
, &rootY
, &childWindow
);
1122 XButtonPressedEvent event
;
1123 event
.type
= ButtonPress
;
1129 event
.x_root
= rootX
;
1130 event
.y_root
= rootY
;
1132 XmMenuPosition (menuWidget
, &event
);
1133 XtManageChild (menuWidget
);
1135 // The ID of a pop-up menu is 1 when active, and is set to 0 by the
1136 // idle-time destroy routine.
1137 // Waiting until this ID changes causes this function to block until
1138 // the menu has been dismissed and the widgets cleaned up.
1139 // In other words, once this routine returns, it is safe to delete
1141 // Ian Brown <ian.brown@printsoft.de>
1143 wxEventLoop evtLoop
;
1145 while (menu
->GetId() == 1)
1147 wxDoEventLoopIteration( evtLoop
);
1155 // ---------------------------------------------------------------------------
1156 // moving and resizing
1157 // ---------------------------------------------------------------------------
1159 bool wxWindow::PreResize()
1165 void wxWindow::DoGetSize(int *x
, int *y
) const
1167 Widget widget
= (Widget
)( !m_drawingArea
? GetTopWidget() :
1168 ( m_borderWidget
? m_borderWidget
:
1169 m_scrolledWindow
? m_scrolledWindow
:
1173 XtVaGetValues( widget
,
1181 void wxWindow::DoGetPosition(int *x
, int *y
) const
1183 Widget widget
= (Widget
)
1185 ( m_borderWidget
? m_borderWidget
: m_scrolledWindow
) :
1189 XtVaGetValues(widget
, XmNx
, &xx
, XmNy
, &yy
, NULL
);
1191 // We may be faking the client origin. So a window that's really at (0, 30)
1192 // may appear (to wxWin apps) to be at (0, 0).
1195 wxPoint
pt(GetParent()->GetClientAreaOrigin());
1196 xx
= (Position
)(xx
- pt
.x
);
1197 yy
= (Position
)(yy
- pt
.y
);
1204 void wxWindow::DoScreenToClient(int *x
, int *y
) const
1206 Widget widget
= (Widget
) GetClientWidget();
1207 Display
*display
= XtDisplay((Widget
) GetMainWidget());
1208 Window rootWindow
= RootWindowOfScreen(XtScreen(widget
));
1209 Window thisWindow
= XtWindow(widget
);
1214 XTranslateCoordinates(display
, rootWindow
, thisWindow
, xx
, yy
, x
, y
, &childWindow
);
1217 void wxWindow::DoClientToScreen(int *x
, int *y
) const
1219 Widget widget
= (Widget
) GetClientWidget();
1220 Display
*display
= XtDisplay(widget
);
1221 Window rootWindow
= RootWindowOfScreen(XtScreen(widget
));
1222 Window thisWindow
= XtWindow(widget
);
1227 XTranslateCoordinates(display
, thisWindow
, rootWindow
, xx
, yy
, x
, y
, &childWindow
);
1231 // Get size *available for subwindows* i.e. excluding menu bar etc.
1232 void wxWindow::DoGetClientSize(int *x
, int *y
) const
1234 Widget widget
= (Widget
) GetClientWidget();
1236 XtVaGetValues(widget
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
1237 if(x
) *x
= xx
; if(y
) *y
= yy
;
1240 void wxWindow::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1242 DoSetSizeIntr(x
, y
, width
, height
, sizeFlags
, false);
1245 void wxWindow::DoSetSizeIntr(int x
, int y
, int width
, int height
,
1246 int sizeFlags
, bool fromCtor
)
1248 // A bit of optimization to help sort out the flickers.
1249 int oldX
= -1, oldY
= -1, oldW
= -1, oldH
= -1;
1252 GetSize(& oldW
, & oldH
);
1253 GetPosition(& oldX
, & oldY
);
1256 if ( !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1264 wxSize
size(wxDefaultSize
);
1267 if ( ( sizeFlags
& wxSIZE_AUTO_WIDTH
) && !fromCtor
)
1269 size
= DoGetBestSize();
1280 if( ( sizeFlags
& wxSIZE_AUTO_HEIGHT
) && !fromCtor
)
1282 if( size
.x
== -1 ) size
= DoGetBestSize();
1291 if ( x
!= oldX
|| y
!= oldY
|| width
!= oldW
|| height
!= oldH
1292 || !wxNoOptimize::CanOptimize() )
1298 if (x
> -1 || (sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
))
1301 if (y
> -1 || (sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
))
1305 flags
|= wxMOVE_WIDTH
;
1308 flags
|= wxMOVE_HEIGHT
;
1310 int xx
= x
; int yy
= y
;
1311 AdjustForParentClientOrigin(xx
, yy
, sizeFlags
);
1313 DoMoveWindow( xx
, yy
, width
, height
);
1315 DoMoveWindowIntr( xx
, yy
, width
, height
, flags
);
1320 Widget widget
= (Widget
) GetTopWidget();
1324 bool managed
= XtIsManaged( widget
);
1326 XtUnmanageChild(widget
);
1330 AdjustForParentClientOrigin(xx
, yy
, sizeFlags
);
1332 DoMoveWindow(xx
, yy
, width
, height
);
1335 XtManageChild(widget
);
1339 void wxWindow::DoSetClientSize(int width
, int height
)
1343 Widget drawingArea
= (Widget
) m_drawingArea
;
1345 XtVaSetValues(drawingArea
, XmNresizePolicy
, XmRESIZE_ANY
, NULL
);
1348 XtVaSetValues(drawingArea
, XmNwidth
, width
, NULL
);
1350 XtVaSetValues(drawingArea
, XmNheight
, height
, NULL
);
1352 XtVaSetValues(drawingArea
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
);
1356 Widget widget
= (Widget
) GetTopWidget();
1359 XtVaSetValues(widget
, XmNwidth
, width
, NULL
);
1361 XtVaSetValues(widget
, XmNheight
, height
, NULL
);
1364 void wxWindow::DoMoveWindowIntr(int xx
, int yy
, int w
, int h
,
1369 Widget drawingArea
= (Widget
) m_drawingArea
;
1370 Widget borderOrScrolled
= m_borderWidget
?
1371 (Widget
) m_borderWidget
:
1372 (Widget
) m_scrolledWindow
;
1374 bool managed
= XtIsManaged(borderOrScrolled
);
1376 XtUnmanageChild (borderOrScrolled
);
1377 XtVaSetValues(drawingArea
, XmNresizePolicy
, XmRESIZE_ANY
, NULL
);
1379 if (flags
& wxMOVE_X
)
1380 XtVaSetValues (borderOrScrolled
,
1383 if (flags
& wxMOVE_Y
)
1384 XtVaSetValues (borderOrScrolled
,
1388 if (flags
& wxMOVE_WIDTH
)
1392 XtVaSetValues ((Widget
) m_borderWidget
, XmNwidth
, w
, NULL
);
1393 short thick
, margin
;
1394 XtVaGetValues ((Widget
) m_borderWidget
,
1395 XmNshadowThickness
, &thick
,
1396 XmNmarginWidth
, &margin
,
1398 w
-= 2 * (thick
+ margin
);
1402 XtVaSetValues ((Widget
) m_scrolledWindow
, XmNwidth
, w
, NULL
);
1405 if (flags
& wxMOVE_HEIGHT
)
1409 XtVaSetValues ((Widget
) m_borderWidget
, XmNheight
, h
, NULL
);
1410 short thick
, margin
;
1411 XtVaGetValues ((Widget
) m_borderWidget
,
1412 XmNshadowThickness
, &thick
,
1413 XmNmarginHeight
, &margin
,
1415 h
-= 2 * (thick
+ margin
);
1419 XtVaSetValues ((Widget
) m_scrolledWindow
, XmNheight
, h
, NULL
);
1423 XtManageChild (borderOrScrolled
);
1424 XtVaSetValues(drawingArea
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
);
1428 if( xx
< 0 ) xx
= 0;
1429 if( yy
< 0 ) yy
= 0;
1433 XtVaSetValues((Widget
)GetTopWidget(),
1442 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
1444 DoMoveWindowIntr (x
, y
, width
, height
,
1445 wxMOVE_X
|wxMOVE_Y
|wxMOVE_WIDTH
|wxMOVE_HEIGHT
);
1448 // ---------------------------------------------------------------------------
1450 // ---------------------------------------------------------------------------
1452 int wxWindow::GetCharHeight() const
1454 wxCHECK_MSG( m_font
.Ok(), 0, "valid window font needed" );
1458 wxGetTextExtent (GetXDisplay(), m_font
, 1.0,
1459 "x", NULL
, &height
, NULL
, NULL
);
1464 int wxWindow::GetCharWidth() const
1466 wxCHECK_MSG( m_font
.Ok(), 0, "valid window font needed" );
1470 wxGetTextExtent (GetXDisplay(), m_font
, 1.0,
1471 "x", &width
, NULL
, NULL
, NULL
);
1476 void wxWindow::GetTextExtent(const wxString
& string
,
1478 int *descent
, int *externalLeading
,
1479 const wxFont
*theFont
) const
1481 const wxFont
*fontToUse
= theFont
? theFont
: &m_font
;
1483 wxCHECK_RET( fontToUse
->Ok(), "valid window font needed" );
1485 if (externalLeading
)
1486 *externalLeading
= 0;
1487 wxGetTextExtent (GetXDisplay(), *fontToUse
, 1.0,
1488 string
, x
, y
, NULL
, descent
);
1491 // ----------------------------------------------------------------------------
1493 // ----------------------------------------------------------------------------
1495 void wxWindow::AddUpdateRect(int x
, int y
, int w
, int h
)
1497 m_updateRegion
.Union( x
, y
, w
, h
);
1500 void wxWindow::Refresh(bool eraseBack
, const wxRect
*rect
)
1502 m_needsRefresh
= true;
1503 Display
*display
= XtDisplay((Widget
) GetMainWidget());
1504 Window thisWindow
= XtWindow((Widget
) GetMainWidget());
1506 XExposeEvent dummyEvent
;
1508 GetSize(&width
, &height
);
1510 dummyEvent
.type
= Expose
;
1511 dummyEvent
.display
= display
;
1512 dummyEvent
.send_event
= True
;
1513 dummyEvent
.window
= thisWindow
;
1516 dummyEvent
.x
= rect
->x
;
1517 dummyEvent
.y
= rect
->y
;
1518 dummyEvent
.width
= rect
->width
;
1519 dummyEvent
.height
= rect
->height
;
1525 dummyEvent
.width
= width
;
1526 dummyEvent
.height
= height
;
1528 dummyEvent
.count
= 0;
1532 wxClientDC
dc(this);
1533 wxBrush
backgroundBrush(GetBackgroundColour(), wxSOLID
);
1534 dc
.SetBackground(backgroundBrush
);
1541 XSendEvent(display
, thisWindow
, False
, ExposureMask
, (XEvent
*)&dummyEvent
);
1544 void wxWindow::DoPaint()
1546 //TODO : make a temporary gc so we can do the XCopyArea below
1547 if (m_backingPixmap
&& !m_needsRefresh
)
1551 GC tempGC
= (GC
) dc
.GetBackingGC();
1553 Widget widget
= (Widget
) GetMainWidget();
1558 // We have to test whether it's a wxScrolledWindow (hack!) because
1559 // otherwise we don't know how many pixels have been scrolled. We might
1560 // solve this in the future by defining virtual wxWindow functions to get
1561 // the scroll position in pixels. Or, each kind of scrolled window has to
1562 // implement backing stores itself, using generic wxWidgets code.
1563 wxScrolledWindow
* scrolledWindow
= wxDynamicCast(this, wxScrolledWindow
);
1564 if ( scrolledWindow
)
1567 scrolledWindow
->CalcScrolledPosition(0, 0, &x
, &y
);
1573 // TODO: This could be optimized further by only copying the areas in the
1574 // current update region.
1576 // Only blit the part visible in the client area. The backing pixmap
1577 // always starts at 0, 0 but we may be looking at only a portion of it.
1578 wxSize clientArea
= GetClientSize();
1579 int toBlitX
= m_pixmapWidth
- scrollPosX
;
1580 int toBlitY
= m_pixmapHeight
- scrollPosY
;
1582 // Copy whichever is samller, the amount of pixmap we have to copy,
1583 // or the size of the client area.
1584 toBlitX
= wxMin(toBlitX
, clientArea
.x
);
1585 toBlitY
= wxMin(toBlitY
, clientArea
.y
);
1587 // Make sure we're not negative
1588 toBlitX
= wxMax(0, toBlitX
);
1589 toBlitY
= wxMax(0, toBlitY
);
1594 (Pixmap
) m_backingPixmap
,
1597 scrollPosX
, scrollPosY
, // Start at the scroll position
1598 toBlitX
, toBlitY
, // How much of the pixmap to copy
1604 wxWindowDC
dc(this);
1605 // Set an erase event first
1606 wxEraseEvent
eraseEvent(GetId(), &dc
);
1607 eraseEvent
.SetEventObject(this);
1608 GetEventHandler()->ProcessEvent(eraseEvent
);
1610 wxPaintEvent
event(GetId());
1611 event
.SetEventObject(this);
1612 GetEventHandler()->ProcessEvent(event
);
1614 m_needsRefresh
= false;
1618 // ----------------------------------------------------------------------------
1620 // ----------------------------------------------------------------------------
1622 // Responds to colour changes: passes event on to children.
1623 void wxWindow::OnSysColourChanged(wxSysColourChangedEvent
& event
)
1625 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
1628 // Only propagate to non-top-level windows
1629 wxWindow
*win
= node
->GetData();
1630 if ( win
->GetParent() )
1632 wxSysColourChangedEvent event2
;
1633 event
.SetEventObject(win
);
1634 win
->GetEventHandler()->ProcessEvent(event2
);
1637 node
= node
->GetNext();
1641 void wxWindow::OnInternalIdle()
1643 // This calls the UI-update mechanism (querying windows for
1644 // menu/toolbar/control state information)
1645 if (wxUpdateUIEvent::CanUpdate(this))
1646 UpdateWindowUI(wxUPDATE_UI_FROMIDLE
);
1649 // ----------------------------------------------------------------------------
1651 // ----------------------------------------------------------------------------
1653 bool wxWindow::ProcessAccelerator(wxKeyEvent
& event
)
1656 if (!m_acceleratorTable
.Ok())
1659 int count
= m_acceleratorTable
.GetCount();
1660 wxAcceleratorEntry
* entries
= m_acceleratorTable
.GetEntries();
1662 for (i
= 0; i
< count
; i
++)
1664 wxAcceleratorEntry
* entry
= & (entries
[i
]);
1665 if (entry
->MatchesEvent(event
))
1667 // Bingo, we have a match. Now find a control that matches the
1668 // entry command id.
1670 // Need to go up to the top of the window hierarchy, since it might
1671 // be e.g. a menu item
1672 wxWindow
* parent
= this;
1673 while ( parent
&& !parent
->IsTopLevel() )
1674 parent
= parent
->GetParent();
1679 wxFrame
* frame
= wxDynamicCast(parent
, wxFrame
);
1683 // Try for a menu command
1684 if (frame
->GetMenuBar())
1686 wxMenuItem
* item
= frame
->GetMenuBar()->FindItem(entry
->GetCommand());
1689 wxCommandEvent
commandEvent(wxEVT_COMMAND_MENU_SELECTED
, entry
->GetCommand());
1690 commandEvent
.SetEventObject(frame
);
1692 // If ProcessEvent returns true (it was handled), then
1693 // the calling code will skip the event handling.
1694 return frame
->GetEventHandler()->ProcessEvent(commandEvent
);
1700 // Find a child matching the command id
1701 wxWindow
* child
= parent
->FindWindow(entry
->GetCommand());
1707 // Now we process those kinds of windows that we can.
1708 // For now, only buttons.
1709 if ( wxDynamicCast(child
, wxButton
) )
1711 wxCommandEvent
commandEvent (wxEVT_COMMAND_BUTTON_CLICKED
, child
->GetId());
1712 commandEvent
.SetEventObject(child
);
1713 return child
->GetEventHandler()->ProcessEvent(commandEvent
);
1721 // We didn't match the key event against an accelerator.
1725 // ============================================================================
1726 // Motif-specific stuff from here on
1727 // ============================================================================
1729 // ----------------------------------------------------------------------------
1730 // function which maintain the global hash table mapping Widgets to wxWidgets
1731 // ----------------------------------------------------------------------------
1733 bool wxAddWindowToTable(Widget w
, wxWindow
*win
)
1735 const long key
= (long)w
;
1736 if ( wxWidgetHashTable
->Get(key
))
1738 wxLogDebug("Widget table clash: new widget is %ld, %s",
1739 key
, win
->GetClassInfo()->GetClassName());
1743 wxWidgetHashTable
->Put(key
, win
);
1745 wxLogTrace("widget", "Widget 0x%p <-> window %p (%s)",
1746 w
, win
, win
->GetClassInfo()->GetClassName());
1751 wxWindow
*wxGetWindowFromTable(Widget w
)
1753 return (wxWindow
*)wxWidgetHashTable
->Get((long) w
);
1756 void wxDeleteWindowFromTable(Widget w
)
1758 wxLogTrace("widget", "Widget 0x%p", (WXWidget
)w
);
1760 wxWidgetHashTable
->Delete((long)w
);
1763 // ----------------------------------------------------------------------------
1764 // add/remove window from the table
1765 // ----------------------------------------------------------------------------
1767 // Add to hash table, add event handler
1768 bool wxWindow::AttachWidget (wxWindow
* WXUNUSED(parent
), WXWidget mainWidget
,
1769 WXWidget formWidget
, int x
, int y
, int width
, int height
)
1771 wxAddWindowToTable((Widget
) mainWidget
, this);
1772 XtAddEventHandler( (Widget
) mainWidget
,
1773 ButtonPressMask
| ButtonReleaseMask
1774 | PointerMotionMask
,
1776 wxPanelItemEventHandler
,
1782 XtOverrideTranslations ((Widget
) mainWidget
,
1783 ptr
= XtParseTranslationTable ("<Configure>: resize()"));
1784 XtFree ((char *) ptr
);
1787 // Some widgets have a parent form widget, e.g. wxRadioBox
1790 if (!wxAddWindowToTable((Widget
) formWidget
, this))
1794 XtOverrideTranslations ((Widget
) formWidget
,
1795 ptr
= XtParseTranslationTable ("<Configure>: resize()"));
1796 XtFree ((char *) ptr
);
1803 DoSetSize (x
, y
, width
, height
, wxSIZE_USE_EXISTING
);
1808 // Remove event handler, remove from hash table
1809 bool wxWindow::DetachWidget(WXWidget widget
)
1811 XtRemoveEventHandler( (Widget
) widget
,
1812 ButtonPressMask
| ButtonReleaseMask
1813 | PointerMotionMask
,
1815 wxPanelItemEventHandler
,
1818 wxDeleteWindowFromTable((Widget
) widget
);
1822 // ----------------------------------------------------------------------------
1823 // Motif-specific accessors
1824 // ----------------------------------------------------------------------------
1826 WXWindow
wxWindow::GetClientXWindow() const
1828 Widget wMain
= (Widget
)GetClientWidget();
1830 return (WXWindow
) XtWindow(wMain
);
1832 return (WXWindow
) 0;
1835 // Get the underlying X window
1836 WXWindow
wxWindow::GetXWindow() const
1838 Widget wMain
= (Widget
)GetMainWidget();
1840 return (WXWindow
) XtWindow(wMain
);
1842 return (WXWindow
) 0;
1845 // Get the underlying X display
1846 WXDisplay
*wxWindow::GetXDisplay() const
1848 Widget wMain
= (Widget
)GetMainWidget();
1850 return (WXDisplay
*) XtDisplay(wMain
);
1852 return (WXDisplay
*) NULL
;
1855 WXWidget
wxWindow::GetMainWidget() const
1858 return m_drawingArea
;
1860 return m_mainWidget
;
1863 WXWidget
wxWindow::GetClientWidget() const
1865 if (m_drawingArea
!= (WXWidget
) 0)
1866 return m_drawingArea
;
1868 return GetMainWidget();
1871 WXWidget
wxWindow::GetTopWidget() const
1873 return GetMainWidget();
1876 WXWidget
wxWindow::GetLabelWidget() const
1878 return GetMainWidget();
1881 // ----------------------------------------------------------------------------
1883 // ----------------------------------------------------------------------------
1885 // All widgets should have this as their resize proc.
1886 // OnSize sent to wxWindow via client data.
1887 void wxWidgetResizeProc(Widget w
, XConfigureEvent
*WXUNUSED(event
),
1888 String
WXUNUSED(args
)[], int *WXUNUSED(num_args
))
1890 wxWindow
*win
= wxGetWindowFromTable(w
);
1894 if (win
->PreResize())
1896 wxSize
newSize(win
->GetSize());
1897 wxSizeEvent
sizeEvent(newSize
, win
->GetId());
1898 sizeEvent
.SetEventObject(win
);
1899 win
->GetEventHandler()->ProcessEvent(sizeEvent
);
1903 static void wxCanvasRepaintProc(Widget drawingArea
,
1904 XtPointer clientData
,
1905 XmDrawingAreaCallbackStruct
* cbs
)
1907 if (!wxGetWindowFromTable(drawingArea
))
1910 XEvent
* event
= cbs
->event
;
1911 wxWindow
* win
= (wxWindow
*) clientData
;
1913 switch (event
->type
)
1917 win
->AddUpdateRect(event
->xexpose
.x
, event
->xexpose
.y
,
1918 event
->xexpose
.width
, event
->xexpose
.height
);
1920 if (event
-> xexpose
.count
== 0)
1929 // Unable to deal with Enter/Leave without a separate EventHandler (Motif 1.1.4)
1930 static void wxCanvasEnterLeave(Widget drawingArea
,
1931 XtPointer
WXUNUSED(clientData
),
1932 XCrossingEvent
* event
)
1934 XmDrawingAreaCallbackStruct cbs
;
1937 ((XCrossingEvent
&) ev
) = *event
;
1939 cbs
.reason
= XmCR_INPUT
;
1942 wxCanvasInputEvent(drawingArea
, (XtPointer
) NULL
, &cbs
);
1945 // Fix to make it work under Motif 1.0 (!)
1946 static void wxCanvasMotionEvent (Widget
WXUNUSED(drawingArea
),
1947 XButtonEvent
*WXUNUSED(event
))
1949 #if XmVersion <= 1000
1950 XmDrawingAreaCallbackStruct cbs
;
1953 ev
= *((XEvent
*) event
);
1954 cbs
.reason
= XmCR_INPUT
;
1957 wxCanvasInputEvent (drawingArea
, (XtPointer
) NULL
, &cbs
);
1958 #endif // XmVersion <= 1000
1961 static void wxCanvasInputEvent(Widget drawingArea
,
1962 XtPointer
WXUNUSED(data
),
1963 XmDrawingAreaCallbackStruct
* cbs
)
1965 wxWindow
*canvas
= wxGetWindowFromTable(drawingArea
);
1966 XEvent
* xevent
= cbs
->event
;
1971 if (cbs
->reason
!= XmCR_INPUT
)
1974 switch (xevent
->xany
.type
)
1982 wxMouseEvent
wxevent(0);
1983 if (wxTranslateMouseEvent(wxevent
, canvas
, drawingArea
, xevent
))
1985 canvas
->GetEventHandler()->ProcessEvent(wxevent
);
1991 wxKeyEvent
event (wxEVT_CHAR
);
1992 if (wxTranslateKeyEvent (event
, canvas
, (Widget
) 0, xevent
))
1994 // Implement wxFrame::OnCharHook by checking ancestor.
1995 wxWindow
*parent
= canvas
;
1996 while (parent
&& !parent
->IsTopLevel())
1997 parent
= parent
->GetParent();
2001 event
.SetEventType(wxEVT_CHAR_HOOK
);
2002 if (parent
->GetEventHandler()->ProcessEvent(event
))
2006 // For simplicity, OnKeyDown is the same as OnChar
2007 // TODO: filter modifier key presses from OnChar
2008 event
.SetEventType(wxEVT_KEY_DOWN
);
2010 // Only process OnChar if OnKeyDown didn't swallow it
2011 if (!canvas
->GetEventHandler()->ProcessEvent (event
))
2013 event
.SetEventType(wxEVT_CHAR
);
2014 canvas
->GetEventHandler()->ProcessEvent (event
);
2021 wxKeyEvent
event (wxEVT_KEY_UP
);
2022 if (wxTranslateKeyEvent (event
, canvas
, (Widget
) 0, xevent
))
2024 canvas
->GetEventHandler()->ProcessEvent (event
);
2030 if (xevent
->xfocus
.detail
!= NotifyPointer
)
2032 wxFocusEvent
event(wxEVT_SET_FOCUS
, canvas
->GetId());
2033 event
.SetEventObject(canvas
);
2034 canvas
->GetEventHandler()->ProcessEvent(event
);
2040 if (xevent
->xfocus
.detail
!= NotifyPointer
)
2042 wxFocusEvent
event(wxEVT_KILL_FOCUS
, canvas
->GetId());
2043 event
.SetEventObject(canvas
);
2044 canvas
->GetEventHandler()->ProcessEvent(event
);
2053 static void wxPanelItemEventHandler(Widget wid
,
2054 XtPointer
WXUNUSED(client_data
),
2056 Boolean
*continueToDispatch
)
2058 // Widget can be a label or the actual widget.
2060 wxWindow
*window
= wxGetWindowFromTable(wid
);
2063 wxMouseEvent
wxevent(0);
2064 if (wxTranslateMouseEvent(wxevent
, window
, wid
, event
))
2066 window
->GetEventHandler()->ProcessEvent(wxevent
);
2070 // TODO: probably the key to allowing default behaviour to happen. Say we
2071 // set a m_doDefault flag to false at the start of this function. Then in
2072 // e.g. wxWindow::OnMouseEvent we can call Default() which sets this flag to
2073 // true, indicating that default processing can happen. Thus, behaviour can
2074 // appear to be overridden just by adding an event handler and not calling
2075 // wxWindow::OnWhatever. ALSO, maybe we can use this instead of the current
2076 // way of handling drawing area events, to simplify things.
2077 *continueToDispatch
= True
;
2080 static void wxScrollBarCallback(Widget scrollbar
,
2081 XtPointer clientData
,
2082 XmScrollBarCallbackStruct
*cbs
)
2084 wxWindow
*win
= wxGetWindowFromTable(scrollbar
);
2085 wxOrientation orientation
= (wxOrientation
)wxPtrToUInt(clientData
);
2087 wxEventType eventType
= wxEVT_NULL
;
2088 switch (cbs
->reason
)
2090 case XmCR_INCREMENT
:
2092 eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
2095 case XmCR_DECREMENT
:
2097 eventType
= wxEVT_SCROLLWIN_LINEUP
;
2102 eventType
= wxEVT_SCROLLWIN_THUMBTRACK
;
2105 case XmCR_VALUE_CHANGED
:
2107 eventType
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2110 case XmCR_PAGE_INCREMENT
:
2112 eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
2115 case XmCR_PAGE_DECREMENT
:
2117 eventType
= wxEVT_SCROLLWIN_PAGEUP
;
2122 eventType
= wxEVT_SCROLLWIN_TOP
;
2125 case XmCR_TO_BOTTOM
:
2127 eventType
= wxEVT_SCROLLWIN_BOTTOM
;
2132 // Should never get here
2133 wxFAIL_MSG("Unknown scroll event.");
2138 wxScrollWinEvent
event(eventType
,
2141 event
.SetEventObject( win
);
2142 win
->GetEventHandler()->ProcessEvent(event
);
2145 // For repainting arbitrary windows
2146 void wxUniversalRepaintProc(Widget w
, XtPointer
WXUNUSED(c_data
), XEvent
*event
, char *)
2148 wxWindow
* win
= wxGetWindowFromTable(w
);
2152 switch ( event
->type
)
2156 win
->AddUpdateRect(event
->xexpose
.x
, event
->xexpose
.y
,
2157 event
->xexpose
.width
, event
->xexpose
.height
);
2159 if ( event
->xexpose
.count
== 0 )
2169 // ----------------------------------------------------------------------------
2170 // TranslateXXXEvent() functions
2171 // ----------------------------------------------------------------------------
2173 bool wxTranslateMouseEvent(wxMouseEvent
& wxevent
, wxWindow
*win
,
2174 Widget widget
, const XEvent
*xevent
)
2176 switch (xevent
->xany
.type
)
2181 fprintf(stderr
, "Widget 0x%p <-> window %p (%s), %s\n",
2182 (WXWidget
)widget
, win
, win
->GetClassInfo()->GetClassName(),
2183 (xevent
->xany
.type
== EnterNotify
? "ENTER" : "LEAVE"));
2189 int eventx
= xevent
->xbutton
.x
, eventy
= xevent
->xbutton
.y
;
2191 wxEventType eventType
= wxEVT_NULL
;
2193 if (xevent
->xany
.type
== LeaveNotify
)
2195 eventType
= wxEVT_LEAVE_WINDOW
;
2197 if (xevent
->xany
.type
== EnterNotify
)
2199 eventType
= wxEVT_ENTER_WINDOW
;
2201 else if (xevent
->xany
.type
== MotionNotify
)
2203 eventType
= wxEVT_MOTION
;
2205 if (xevent
->xmotion
.is_hint
== NotifyHint
)
2210 Display
*dpy
= XtDisplay (widget
);
2212 XQueryPointer (dpy
, XtWindow (widget
),
2214 &x_root
, &y_root
, &eventx
, &eventy
, &state
);
2217 else if (xevent
->xany
.type
== ButtonPress
)
2219 wxevent
.SetTimestamp(xevent
->xbutton
.time
);
2221 if (xevent
->xbutton
.button
== Button1
)
2223 eventType
= wxEVT_LEFT_DOWN
;
2226 else if (xevent
->xbutton
.button
== Button2
)
2228 eventType
= wxEVT_MIDDLE_DOWN
;
2231 else if (xevent
->xbutton
.button
== Button3
)
2233 eventType
= wxEVT_RIGHT_DOWN
;
2237 // check for a double click
2239 long dclickTime
= XtGetMultiClickTime(xevent
->xany
.display
);
2240 long ts
= wxevent
.GetTimestamp();
2242 int buttonLast
= win
->GetLastClickedButton();
2243 long lastTS
= win
->GetLastClickTime();
2244 if ( buttonLast
&& buttonLast
== button
&&
2245 (ts
- lastTS
) < dclickTime
)
2248 win
->SetLastClick(0, ts
);
2249 if ( eventType
== wxEVT_LEFT_DOWN
)
2250 eventType
= wxEVT_LEFT_DCLICK
;
2251 else if ( eventType
== wxEVT_MIDDLE_DOWN
)
2252 eventType
= wxEVT_MIDDLE_DCLICK
;
2253 else if ( eventType
== wxEVT_RIGHT_DOWN
)
2254 eventType
= wxEVT_RIGHT_DCLICK
;
2258 // not fast enough or different button
2259 win
->SetLastClick(button
, ts
);
2262 else if (xevent
->xany
.type
== ButtonRelease
)
2264 if (xevent
->xbutton
.button
== Button1
)
2266 eventType
= wxEVT_LEFT_UP
;
2268 else if (xevent
->xbutton
.button
== Button2
)
2270 eventType
= wxEVT_MIDDLE_UP
;
2272 else if (xevent
->xbutton
.button
== Button3
)
2274 eventType
= wxEVT_RIGHT_UP
;
2284 wxevent
.SetEventType(eventType
);
2287 XtVaGetValues(widget
, XmNx
, &x1
, XmNy
, &y1
, NULL
);
2290 win
->GetPosition(&x2
, &y2
);
2292 // The button x/y must be translated to wxWidgets
2293 // window space - the widget might be a label or button,
2297 if (widget
!= (Widget
)win
->GetMainWidget())
2303 wxevent
.m_x
= eventx
+ dx
;
2304 wxevent
.m_y
= eventy
+ dy
;
2306 wxevent
.m_leftDown
= ((eventType
== wxEVT_LEFT_DOWN
)
2307 || (event_left_is_down (xevent
)
2308 && (eventType
!= wxEVT_LEFT_UP
)));
2309 wxevent
.m_middleDown
= ((eventType
== wxEVT_MIDDLE_DOWN
)
2310 || (event_middle_is_down (xevent
)
2311 && (eventType
!= wxEVT_MIDDLE_UP
)));
2312 wxevent
.m_rightDown
= ((eventType
== wxEVT_RIGHT_DOWN
)
2313 || (event_right_is_down (xevent
)
2314 && (eventType
!= wxEVT_RIGHT_UP
)));
2316 wxevent
.m_shiftDown
= (xevent
->xbutton
.state
& ShiftMask
) == ShiftMask
;
2317 wxevent
.m_controlDown
= (xevent
->xbutton
.state
& ControlMask
) == ControlMask
;
2318 wxevent
.m_altDown
= (xevent
->xbutton
.state
& Mod3Mask
) == Mod3Mask
;
2319 wxevent
.m_metaDown
= (xevent
->xbutton
.state
& Mod1Mask
) == Mod1Mask
;
2321 wxevent
.SetId(win
->GetId());
2322 wxevent
.SetEventObject(win
);
2330 bool wxTranslateKeyEvent(wxKeyEvent
& wxevent
, wxWindow
*win
,
2331 Widget
WXUNUSED(widget
), const XEvent
*xevent
)
2333 switch (xevent
->xany
.type
)
2341 (void) XLookupString((XKeyEvent
*)xevent
, buf
, 20, &keySym
, NULL
);
2342 int id
= wxCharCodeXToWX (keySym
);
2343 // id may be WXK_xxx code - these are outside ASCII range, so we
2344 // can't just use toupper() on id
2345 if (id
>= 'a' && id
<= 'z')
2348 if (xevent
->xkey
.state
& ShiftMask
)
2349 wxevent
.m_shiftDown
= true;
2350 if (xevent
->xkey
.state
& ControlMask
)
2351 wxevent
.m_controlDown
= true;
2352 if (xevent
->xkey
.state
& Mod3Mask
)
2353 wxevent
.m_altDown
= true;
2354 if (xevent
->xkey
.state
& Mod1Mask
)
2355 wxevent
.m_metaDown
= true;
2356 wxevent
.SetEventObject(win
);
2357 wxevent
.m_keyCode
= id
;
2358 wxevent
.SetTimestamp(xevent
->xkey
.time
);
2360 wxevent
.m_x
= xevent
->xbutton
.x
;
2361 wxevent
.m_y
= xevent
->xbutton
.y
;
2374 // ----------------------------------------------------------------------------
2376 // ----------------------------------------------------------------------------
2378 #define YAllocColor XAllocColor
2379 XColor g_itemColors
[5];
2380 int wxComputeColours (Display
*display
, wxColour
* back
, wxColour
* fore
)
2383 static XmColorProc colorProc
;
2385 result
= wxNO_COLORS
;
2389 g_itemColors
[0].red
= (unsigned short)(((long) back
->Red ()) << 8);
2390 g_itemColors
[0].green
= (unsigned short)(((long) back
->Green ()) << 8);
2391 g_itemColors
[0].blue
= (unsigned short)(((long) back
->Blue ()) << 8);
2392 g_itemColors
[0].flags
= DoRed
| DoGreen
| DoBlue
;
2393 if (colorProc
== (XmColorProc
) NULL
)
2395 // Get a ptr to the actual function
2396 colorProc
= XmSetColorCalculation ((XmColorProc
) NULL
);
2397 // And set it back to motif.
2398 XmSetColorCalculation (colorProc
);
2400 (*colorProc
) (&g_itemColors
[wxBACK_INDEX
],
2401 &g_itemColors
[wxFORE_INDEX
],
2402 &g_itemColors
[wxSELE_INDEX
],
2403 &g_itemColors
[wxTOPS_INDEX
],
2404 &g_itemColors
[wxBOTS_INDEX
]);
2405 result
= wxBACK_COLORS
;
2409 g_itemColors
[wxFORE_INDEX
].red
= (unsigned short)(((long) fore
->Red ()) << 8);
2410 g_itemColors
[wxFORE_INDEX
].green
= (unsigned short)(((long) fore
->Green ()) << 8);
2411 g_itemColors
[wxFORE_INDEX
].blue
= (unsigned short)(((long) fore
->Blue ()) << 8);
2412 g_itemColors
[wxFORE_INDEX
].flags
= DoRed
| DoGreen
| DoBlue
;
2413 if (result
== wxNO_COLORS
)
2414 result
= wxFORE_COLORS
;
2417 Display
*dpy
= display
;
2418 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dpy
);
2422 /* 5 Colours to allocate */
2423 for (int i
= 0; i
< 5; i
++)
2424 if (!YAllocColor (dpy
, cmap
, &g_itemColors
[i
]))
2425 result
= wxNO_COLORS
;
2429 /* Only 1 colour to allocate */
2430 if (!YAllocColor (dpy
, cmap
, &g_itemColors
[wxFORE_INDEX
]))
2431 result
= wxNO_COLORS
;
2437 // Changes the foreground and background colours to be derived from the current
2438 // background colour. To change the foreground colour, you must call
2439 // SetForegroundColour explicitly.
2440 void wxWindow::ChangeBackgroundColour()
2442 WXWidget mainWidget
= GetMainWidget();
2444 wxDoChangeBackgroundColour(mainWidget
, m_backgroundColour
);
2445 if ( m_scrolledWindow
&& mainWidget
!= m_scrolledWindow
)
2446 wxDoChangeForegroundColour(m_scrolledWindow
, m_backgroundColour
);
2449 void wxWindow::ChangeForegroundColour()
2451 WXWidget mainWidget
= GetMainWidget();
2453 wxDoChangeForegroundColour(mainWidget
, m_foregroundColour
);
2454 if ( m_scrolledWindow
&& mainWidget
!= m_scrolledWindow
)
2455 wxDoChangeForegroundColour(m_scrolledWindow
, m_foregroundColour
);
2458 bool wxWindow::SetBackgroundColour(const wxColour
& col
)
2460 if ( !wxWindowBase::SetBackgroundColour(col
) )
2463 ChangeBackgroundColour();
2468 bool wxWindow::SetForegroundColour(const wxColour
& col
)
2470 if ( !wxWindowBase::SetForegroundColour(col
) )
2473 ChangeForegroundColour();
2478 void wxWindow::ChangeFont(bool keepOriginalSize
)
2480 // Note that this causes the widget to be resized back
2481 // to its original size! We therefore have to set the size
2482 // back again. TODO: a better way in Motif?
2483 Widget w
= (Widget
) GetLabelWidget(); // Usually the main widget
2484 if (w
&& m_font
.Ok())
2486 int width
, height
, width1
, height1
;
2487 GetSize(& width
, & height
);
2489 wxDoChangeFont( GetLabelWidget(), m_font
);
2491 GetSize(& width1
, & height1
);
2492 if (keepOriginalSize
&& (width
!= width1
|| height
!= height1
))
2494 SetSize(wxDefaultCoord
, wxDefaultCoord
, width
, height
);
2499 // ----------------------------------------------------------------------------
2501 // ----------------------------------------------------------------------------
2503 wxWindow
*wxGetActiveWindow()
2506 wxFAIL_MSG("Not implemented");
2511 wxWindow
*wxWindowBase::GetCapture()
2513 return (wxWindow
*)g_captureWindow
;
2517 // Find the wxWindow at the current mouse position, returning the mouse
2519 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
2521 pt
= wxGetMousePosition();
2522 return wxFindWindowAtPoint(pt
);
2525 // Get the current mouse position.
2526 wxPoint
wxGetMousePosition()
2528 Display
*display
= wxGlobalDisplay();
2529 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
2530 Window rootReturn
, childReturn
;
2531 int rootX
, rootY
, winX
, winY
;
2532 unsigned int maskReturn
;
2534 XQueryPointer (display
,
2538 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
2539 return wxPoint(rootX
, rootY
);
2543 // ----------------------------------------------------------------------------
2544 // wxNoOptimize: switch off size optimization
2545 // ----------------------------------------------------------------------------
2547 int wxNoOptimize::ms_count
= 0;