1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "window.h"
25 #define XtDisplay XTDISPLAY
26 #define XtWindow XTWINDOW
27 #define XtScreen XTSCREEN
33 #include "wx/dcclient.h"
37 #include "wx/layout.h"
38 #include "wx/dialog.h"
39 #include "wx/listbox.h"
40 #include "wx/button.h"
41 #include "wx/settings.h"
42 #include "wx/msgdlg.h"
44 #include "wx/scrolwin.h"
45 #include "wx/module.h"
46 #include "wx/menuitem.h"
49 #if wxUSE_DRAG_AND_DROP
53 // DoSetSizeIntr and CanvasSetSizeIntr
55 // under Motif composite controls (such as wxCalendarCtrl or generic wxSpinCtrl
56 // don't work and/or segfault because
57 // 1) wxWindow::Create calls SetSize,
58 // which results in a call to DoSetSize much earlier than in the other ports
59 // 2) if wxWindow::Create is called (wxControl::Create calls it)
60 // then DoSetSize is never called, causing layout problems in composite
64 // 1) don't call SetSize, DoSetSize, DoMoveWindow, DoGetPosition,
65 // DoSetPosition directly or indirectly from wxWindow::Create
66 // 2) call DoMoveWindow from DoSetSize, allowing controls to override it,
67 // but make wxWindow::DoMoveWindow a no-op if it is called from
68 // an overridden DoMoveWindow (i.e. wxFoo::DoMoveWindow calls
69 // wxWindow::DoMoveWindow; this is to preserve the behaviour
73 #pragma message disable nosimpint
77 #include <Xm/DrawingA.h>
78 #include <Xm/ScrolledW.h>
79 #include <Xm/ScrollBar.h>
82 #include <Xm/RowColumn.h> // for XmMenuPosition
84 #pragma message enable nosimpint
87 #include "wx/motif/private.h"
91 // ----------------------------------------------------------------------------
93 // ----------------------------------------------------------------------------
95 static const int SCROLL_MARGIN
= 4;
97 // ----------------------------------------------------------------------------
98 // global variables for this module
99 // ----------------------------------------------------------------------------
101 extern wxHashTable
*wxWidgetHashTable
;
102 static wxWindow
* g_captureWindow
= NULL
;
105 // ----------------------------------------------------------------------------
107 // ----------------------------------------------------------------------------
109 static void wxCanvasRepaintProc(Widget
, XtPointer
, XmDrawingAreaCallbackStruct
* cbs
);
110 static void wxCanvasInputEvent(Widget drawingArea
, XtPointer data
, XmDrawingAreaCallbackStruct
* cbs
);
111 static void wxCanvasMotionEvent(Widget
, XButtonEvent
* event
);
112 static void wxCanvasEnterLeave(Widget drawingArea
, XtPointer clientData
, XCrossingEvent
* event
);
113 static void wxScrollBarCallback(Widget widget
, XtPointer clientData
,
114 XmScrollBarCallbackStruct
*cbs
);
115 static void wxPanelItemEventHandler(Widget wid
,
116 XtPointer client_data
,
118 Boolean
*continueToDispatch
);
123 // Helper function for 16-bit fonts
124 static int str16len(const char *s
)
128 while (s
[0] && s
[1]) {
138 // ----------------------------------------------------------------------------
140 // ----------------------------------------------------------------------------
142 #define event_left_is_down(x) ((x)->xbutton.state & Button1Mask)
143 #define event_middle_is_down(x) ((x)->xbutton.state & Button2Mask)
144 #define event_right_is_down(x) ((x)->xbutton.state & Button3Mask)
146 // ----------------------------------------------------------------------------
148 // ----------------------------------------------------------------------------
150 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
152 BEGIN_EVENT_TABLE(wxWindow
, wxWindowBase
)
153 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged
)
154 EVT_IDLE(wxWindow::OnIdle
)
157 // ============================================================================
159 // ============================================================================
161 // ----------------------------------------------------------------------------
163 // ----------------------------------------------------------------------------
165 void wxWindow::UnmanageAndDestroy(WXWidget widget
)
167 Widget w
= (Widget
)widget
;
175 bool wxWindow::MapOrUnmap(WXWidget widget
, bool domap
)
177 Widget w
= (Widget
)widget
;
186 // Rationale: a lot of common operations (including but not
187 // limited to moving, resizing and appending items to a listbox)
188 // unmamange the widget, do their work, then manage it again.
189 // This means that, for example adding an item to a listbox will show it,
190 // or that most controls are shown every time they are moved or resized!
191 XtSetMappedWhenManaged( w
, domap
);
196 // ----------------------------------------------------------------------------
198 // ----------------------------------------------------------------------------
200 void wxWindow::Init()
202 // generic initializations first
206 m_needsRefresh
= TRUE
;
207 m_mainWidget
= (WXWidget
) 0;
211 m_button3Pressed
= FALSE
;
213 m_winCaptured
= FALSE
;
216 m_isBeingDeleted
= FALSE
;
222 m_drawingArea
= (WXWidget
) 0;
230 m_backingPixmap
= (WXPixmap
) 0;
239 m_canAddEventHandler
= FALSE
;
242 // real construction (Init() must have been called before!)
243 bool wxWindow::Create(wxWindow
*parent
, wxWindowID id
,
247 const wxString
& name
)
249 wxCHECK_MSG( parent
, FALSE
, "can't create wxWindow without parent" );
251 CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
);
253 parent
->AddChild(this);
255 m_backgroundColour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
256 m_foregroundColour
= *wxBLACK
;
258 //// TODO: we should probably optimize by only creating a
259 //// a drawing area if we have one or more scrollbars (wxVSCROLL/wxHSCROLL).
260 //// But for now, let's simplify things by always creating the
261 //// drawing area, since otherwise the translations are different.
263 // New translations for getting mouse motion feedback
264 static const String translations
=
265 "<Btn1Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
266 <Btn2Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
267 <Btn3Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
268 <BtnMotion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
269 <Btn1Down>: DrawingAreaInput() ManagerGadgetArm()\n\
270 <Btn2Down>: DrawingAreaInput() ManagerGadgetArm()\n\
271 <Btn3Down>: DrawingAreaInput() ManagerGadgetArm()\n\
272 <Btn1Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
273 <Btn2Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
274 <Btn3Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
275 <Motion>: wxCanvasMotionEvent() DrawingAreaInput()\n\
276 <EnterWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
277 <LeaveWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
278 <Key>: DrawingAreaInput()";
280 XtActionsRec actions
[1];
281 actions
[0].string
= "wxCanvasMotionEvent";
282 actions
[0].proc
= (XtActionProc
) wxCanvasMotionEvent
;
283 XtAppAddActions ((XtAppContext
) wxTheApp
->GetAppContext(), actions
, 1);
285 Widget parentWidget
= (Widget
) parent
->GetClientWidget();
287 if (style
& wxSIMPLE_BORDER
)
289 m_borderWidget
= (WXWidget
)XtVaCreateManagedWidget
292 xmFrameWidgetClass
, parentWidget
,
293 XmNshadowType
, XmSHADOW_IN
,
294 XmNshadowThickness
, 1,
297 } else if (style
& wxSUNKEN_BORDER
)
299 m_borderWidget
= (WXWidget
)XtVaCreateManagedWidget
302 xmFrameWidgetClass
, parentWidget
,
303 XmNshadowType
, XmSHADOW_IN
,
306 } else if (style
& wxRAISED_BORDER
)
308 m_borderWidget
= (WXWidget
)XtVaCreateManagedWidget
311 xmFrameWidgetClass
, parentWidget
,
312 XmNshadowType
, XmSHADOW_OUT
,
317 m_scrolledWindow
= (WXWidget
)XtVaCreateManagedWidget
320 xmScrolledWindowWidgetClass
,
321 m_borderWidget
? (Widget
) m_borderWidget
323 XmNresizePolicy
, XmRESIZE_NONE
,
325 XmNscrollingPolicy
, XmAPPLICATION_DEFINED
,
326 //XmNscrollBarDisplayPolicy, XmAS_NEEDED,
330 XtTranslations ptr
= XtParseTranslationTable(translations
);
331 m_drawingArea
= (WXWidget
)XtVaCreateWidget
334 xmDrawingAreaWidgetClass
, (Widget
) m_scrolledWindow
,
335 XmNunitType
, XmPIXELS
,
336 // XmNresizePolicy, XmRESIZE_ANY,
337 XmNresizePolicy
, XmRESIZE_NONE
,
340 XmNtranslations
, ptr
,
343 XtFree((char *) ptr
);
346 if (GetWindowStyleFlag() & wxOVERRIDE_KEY_TRANSLATIONS
)
348 ptr
= XtParseTranslationTable ("<Key>: DrawingAreaInput()");
349 XtOverrideTranslations ((Widget
) m_drawingArea
, ptr
);
350 XtFree ((char *) ptr
);
354 wxAddWindowToTable((Widget
) m_drawingArea
, this);
355 wxAddWindowToTable((Widget
) m_scrolledWindow
, this);
357 // This order is very important in Motif 1.2.1
358 XtRealizeWidget ((Widget
) m_scrolledWindow
);
359 XtRealizeWidget ((Widget
) m_drawingArea
);
360 XtManageChild ((Widget
) m_drawingArea
);
362 ptr
= XtParseTranslationTable("<Configure>: resize()");
363 XtOverrideTranslations((Widget
) m_drawingArea
, ptr
);
364 XtFree ((char *) ptr
);
366 XtAddCallback ((Widget
) m_drawingArea
, XmNexposeCallback
, (XtCallbackProc
) wxCanvasRepaintProc
, (XtPointer
) this);
367 XtAddCallback ((Widget
) m_drawingArea
, XmNinputCallback
, (XtCallbackProc
) wxCanvasInputEvent
, (XtPointer
) this);
371 display
= XtDisplay (scrolledWindow
);
372 xwindow
= XtWindow (drawingArea
);
376 (Widget
)m_drawingArea
,
377 PointerMotionHintMask
| EnterWindowMask
|
378 LeaveWindowMask
| FocusChangeMask
,
380 (XtEventHandler
) wxCanvasEnterLeave
,
384 // Scrolled widget needs to have its colour changed or we get a little blue
385 // square where the scrollbars abutt
386 wxColour backgroundColour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
387 DoChangeBackgroundColour(m_scrolledWindow
, backgroundColour
, TRUE
);
388 DoChangeBackgroundColour(m_drawingArea
, backgroundColour
, TRUE
);
390 XmScrolledWindowSetAreas(
391 (Widget
)m_scrolledWindow
,
392 (Widget
) 0, (Widget
) 0,
393 (Widget
) m_drawingArea
);
397 XtRealizeWidget ((Widget
) m_hScrollBar
);
399 XtRealizeWidget ((Widget
) m_vScrollBar
);
402 // Without this, the cursor may not be restored properly (e.g. in splitter
404 SetCursor(*wxSTANDARD_CURSOR
);
405 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
406 DoSetSizeIntr(pos
.x
, pos
.y
, size
.x
,size
.y
, wxSIZE_AUTO
, TRUE
);
411 wxWindow::~wxWindow()
413 if (g_captureWindow
== this)
414 g_captureWindow
= NULL
;
416 m_isBeingDeleted
= TRUE
;
418 // Motif-specific actions first
419 WXWidget wMain
= GetMainWidget();
422 // Removes event handlers
429 m_parent
->RemoveChild( this );
431 // If m_drawingArea, we're a fully-fledged window with drawing area,
432 // scrollbars etc. (what wxCanvas used to be)
435 // Destroy children before destroying self
439 XFreePixmap (XtDisplay ((Widget
) GetMainWidget()), (Pixmap
) m_backingPixmap
);
441 Widget w
= (Widget
) m_drawingArea
;
442 wxDeleteWindowFromTable(w
);
447 m_drawingArea
= (WXWidget
) 0;
450 // Only if we're _really_ a canvas (not a dialog box/panel)
451 if (m_scrolledWindow
)
453 wxDeleteWindowFromTable((Widget
) m_scrolledWindow
);
458 wxDeleteWindowFromTable((Widget
) m_hScrollBar
);
459 XtUnmanageChild((Widget
) m_hScrollBar
);
463 wxDeleteWindowFromTable((Widget
) m_vScrollBar
);
464 XtUnmanageChild((Widget
) m_vScrollBar
);
468 XtDestroyWidget((Widget
) m_hScrollBar
);
470 XtDestroyWidget((Widget
) m_vScrollBar
);
472 UnmanageAndDestroy(m_scrolledWindow
);
476 XtDestroyWidget ((Widget
) m_borderWidget
);
477 m_borderWidget
= (WXWidget
) 0;
480 else // Why wasn't this here before? JACS 8/3/2000
484 // Destroy the window
487 // If this line (XtDestroyWidget) causes a crash, you may comment it out.
488 // Child widgets will get destroyed automatically when a frame
489 // or dialog is destroyed, but before that you may get some memory
490 // leaks and potential layout problems if you delete and then add
493 // GRG, Feb/2000: commented this out when adding support for
494 // wxSCROLL[WIN]_THUMBRELEASE events. Also it was reported
495 // that this call crashed wxMotif under OS/2, so it seems
496 // that leaving it out is the right thing to do.
497 // SN, Feb/2000: newgrid/griddemo shows why it is needed :-(
498 XtDestroyWidget((Widget
) GetMainWidget());
499 SetMainWidget((WXWidget
) NULL
);
503 // ----------------------------------------------------------------------------
504 // scrollbar management
505 // ----------------------------------------------------------------------------
508 void wxWindow::CreateScrollbar(wxOrientation orientation
)
510 wxCHECK_RET( m_drawingArea
, "this window can't have scrollbars" );
512 XtVaSetValues((Widget
) m_scrolledWindow
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
);
514 // Add scrollbars if required
515 if (orientation
== wxHORIZONTAL
)
517 Widget hScrollBar
= XtVaCreateManagedWidget ("hsb",
518 xmScrollBarWidgetClass
, (Widget
) m_scrolledWindow
,
519 XmNorientation
, XmHORIZONTAL
,
521 XtAddCallback (hScrollBar
, XmNvalueChangedCallback
, (XtCallbackProc
) wxScrollBarCallback
, (XtPointer
) XmHORIZONTAL
);
522 XtAddCallback (hScrollBar
, XmNdragCallback
, (XtCallbackProc
) wxScrollBarCallback
, (XtPointer
) XmHORIZONTAL
);
523 XtAddCallback (hScrollBar
, XmNincrementCallback
, (XtCallbackProc
) wxScrollBarCallback
, (XtPointer
) XmHORIZONTAL
);
524 XtAddCallback (hScrollBar
, XmNdecrementCallback
, (XtCallbackProc
) wxScrollBarCallback
, (XtPointer
) XmHORIZONTAL
);
525 XtAddCallback (hScrollBar
, XmNpageIncrementCallback
, (XtCallbackProc
) wxScrollBarCallback
, (XtPointer
) XmHORIZONTAL
);
526 XtAddCallback (hScrollBar
, XmNpageDecrementCallback
, (XtCallbackProc
) wxScrollBarCallback
, (XtPointer
) XmHORIZONTAL
);
527 XtAddCallback (hScrollBar
, XmNtoTopCallback
, (XtCallbackProc
) wxScrollBarCallback
, (XtPointer
) XmHORIZONTAL
);
528 XtAddCallback (hScrollBar
, XmNtoBottomCallback
, (XtCallbackProc
) wxScrollBarCallback
, (XtPointer
) XmHORIZONTAL
);
530 XtVaSetValues (hScrollBar
,
535 m_hScrollBar
= (WXWidget
) hScrollBar
;
537 wxColour backgroundColour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
538 DoChangeBackgroundColour(m_hScrollBar
, backgroundColour
, TRUE
);
540 XtRealizeWidget(hScrollBar
);
542 XtVaSetValues((Widget
) m_scrolledWindow
,
543 XmNhorizontalScrollBar
, (Widget
) m_hScrollBar
,
548 wxAddWindowToTable( hScrollBar
, this );
551 if (orientation
== wxVERTICAL
)
553 Widget vScrollBar
= XtVaCreateManagedWidget ("vsb",
554 xmScrollBarWidgetClass
, (Widget
) m_scrolledWindow
,
555 XmNorientation
, XmVERTICAL
,
557 XtAddCallback (vScrollBar
, XmNvalueChangedCallback
, (XtCallbackProc
) wxScrollBarCallback
, (XtPointer
) XmVERTICAL
);
558 XtAddCallback (vScrollBar
, XmNdragCallback
, (XtCallbackProc
) wxScrollBarCallback
, (XtPointer
) XmVERTICAL
);
559 XtAddCallback (vScrollBar
, XmNincrementCallback
, (XtCallbackProc
) wxScrollBarCallback
, (XtPointer
) XmVERTICAL
);
560 XtAddCallback (vScrollBar
, XmNdecrementCallback
, (XtCallbackProc
) wxScrollBarCallback
, (XtPointer
) XmVERTICAL
);
561 XtAddCallback (vScrollBar
, XmNpageIncrementCallback
, (XtCallbackProc
) wxScrollBarCallback
, (XtPointer
) XmVERTICAL
);
562 XtAddCallback (vScrollBar
, XmNpageDecrementCallback
, (XtCallbackProc
) wxScrollBarCallback
, (XtPointer
) XmVERTICAL
);
563 XtAddCallback (vScrollBar
, XmNtoTopCallback
, (XtCallbackProc
) wxScrollBarCallback
, (XtPointer
) XmVERTICAL
);
564 XtAddCallback (vScrollBar
, XmNtoBottomCallback
, (XtCallbackProc
) wxScrollBarCallback
, (XtPointer
) XmVERTICAL
);
566 XtVaSetValues (vScrollBar
,
571 m_vScrollBar
= (WXWidget
) vScrollBar
;
572 wxColour backgroundColour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
573 DoChangeBackgroundColour(m_vScrollBar
, backgroundColour
, TRUE
);
575 XtRealizeWidget(vScrollBar
);
577 XtVaSetValues((Widget
) m_scrolledWindow
,
578 XmNverticalScrollBar
, (Widget
) m_vScrollBar
,
583 wxAddWindowToTable( vScrollBar
, this );
586 XtVaSetValues((Widget
) m_scrolledWindow
, XmNresizePolicy
, XmRESIZE_ANY
, NULL
);
589 void wxWindow::DestroyScrollbar(wxOrientation orientation
)
591 wxCHECK_RET( m_drawingArea
, "this window can't have scrollbars" );
593 XtVaSetValues((Widget
) m_scrolledWindow
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
);
594 // Add scrollbars if required
595 if (orientation
== wxHORIZONTAL
)
599 wxDeleteWindowFromTable((Widget
)m_hScrollBar
);
600 XtDestroyWidget((Widget
) m_hScrollBar
);
602 m_hScrollBar
= (WXWidget
) 0;
605 XtVaSetValues((Widget
) m_scrolledWindow
,
606 XmNhorizontalScrollBar
, (Widget
) 0,
611 if (orientation
== wxVERTICAL
)
615 wxDeleteWindowFromTable((Widget
)m_vScrollBar
);
616 XtDestroyWidget((Widget
) m_vScrollBar
);
618 m_vScrollBar
= (WXWidget
) 0;
621 XtVaSetValues((Widget
) m_scrolledWindow
,
622 XmNverticalScrollBar
, (Widget
) 0,
626 XtVaSetValues((Widget
) m_scrolledWindow
, XmNresizePolicy
, XmRESIZE_ANY
, NULL
);
629 // ---------------------------------------------------------------------------
631 // ---------------------------------------------------------------------------
633 void wxWindow::SetFocus()
635 Widget wMain
= (Widget
) GetMainWidget();
636 XmProcessTraversal(wMain
, XmTRAVERSE_CURRENT
);
637 XmProcessTraversal((Widget
) GetMainWidget(), XmTRAVERSE_CURRENT
);
640 // Get the window with the focus
641 wxWindow
*wxWindowBase::FindFocus()
644 // (1) Can there be multiple focussed widgets in an application?
645 // In which case we need to find the top-level window that's
647 // (2) The widget with the focus may not be in the widget table
648 // depending on which widgets I put in the table
649 wxWindow
*winFocus
= (wxWindow
*)NULL
;
650 for ( wxWindowList::Node
*node
= wxTopLevelWindows
.GetFirst();
652 node
= node
->GetNext() )
654 wxWindow
*win
= node
->GetData();
656 Widget w
= XmGetFocusWidget ((Widget
) win
->GetTopWidget());
658 if (w
!= (Widget
) NULL
)
660 winFocus
= wxGetWindowFromTable(w
);
669 bool wxWindow::Enable(bool enable
)
671 if ( !wxWindowBase::Enable(enable
) )
674 Widget wMain
= (Widget
)GetMainWidget();
677 XtSetSensitive(wMain
, enable
);
678 XmUpdateDisplay(wMain
);
684 bool wxWindow::Show(bool show
)
686 if ( !wxWindowBase::Show(show
) )
689 if (m_borderWidget
|| m_scrolledWindow
)
691 MapOrUnmap(m_drawingArea
, show
);
692 MapOrUnmap(m_borderWidget
? m_borderWidget
: m_scrolledWindow
, show
);
696 if ( !MapOrUnmap(GetTopWidget(), show
) )
697 MapOrUnmap(GetMainWidget(), show
);
701 Window xwin
= (Window
) GetXWindow();
702 Display
*xdisp
= (Display
*) GetXDisplay();
704 XMapWindow(xdisp
, xwin
);
706 XUnmapWindow(xdisp
, xwin
);
712 // Raise the window to the top of the Z order
713 void wxWindow::Raise()
715 Widget wTop
= (Widget
) GetTopWidget();
716 Window window
= XtWindow(wTop
);
717 XRaiseWindow(XtDisplay(wTop
), window
);
720 // Lower the window to the bottom of the Z order
721 void wxWindow::Lower()
723 Widget wTop
= (Widget
) GetTopWidget();
724 Window window
= XtWindow(wTop
);
725 XLowerWindow(XtDisplay(wTop
), window
);
728 void wxWindow::SetTitle(const wxString
& title
)
730 XtVaSetValues((Widget
)GetMainWidget(), XmNtitle
, title
.c_str(), NULL
);
733 wxString
wxWindow::GetTitle() const
736 XtVaGetValues((Widget
)GetMainWidget(), XmNtitle
, &title
, NULL
);
738 return wxString(title
);
741 void wxWindow::DoCaptureMouse()
743 g_captureWindow
= this;
747 Widget wMain
= (Widget
)GetMainWidget();
749 XtAddGrab(wMain
, TRUE
, FALSE
);
751 m_winCaptured
= TRUE
;
754 void wxWindow::DoReleaseMouse()
756 g_captureWindow
= NULL
;
757 if ( !m_winCaptured
)
760 Widget wMain
= (Widget
)GetMainWidget();
764 m_winCaptured
= FALSE
;
767 bool wxWindow::SetFont(const wxFont
& font
)
769 if ( !wxWindowBase::SetFont(font
) )
780 bool wxWindow::SetCursor(const wxCursor
& cursor
)
782 if ( !wxWindowBase::SetCursor(cursor
) )
788 // wxASSERT_MSG( m_cursor.Ok(),
789 // wxT("cursor must be valid after call to the base version"));
790 wxCursor
* cursor2
= NULL
;
792 cursor2
= & m_cursor
;
794 cursor2
= wxSTANDARD_CURSOR
;
796 WXDisplay
*dpy
= GetXDisplay();
797 WXCursor x_cursor
= cursor2
->GetXCursor(dpy
);
799 Widget w
= (Widget
) GetMainWidget();
800 Window win
= XtWindow(w
);
801 XDefineCursor((Display
*) dpy
, win
, (Cursor
) x_cursor
);
806 // Coordinates relative to the window
807 void wxWindow::WarpPointer (int x
, int y
)
809 Widget wClient
= (Widget
)GetClientWidget();
811 XWarpPointer(XtDisplay(wClient
), None
, XtWindow(wClient
), 0, 0, 0, 0, x
, y
);
814 // ---------------------------------------------------------------------------
816 // ---------------------------------------------------------------------------
818 int wxWindow::GetScrollPos(int orient
) const
820 if (orient
== wxHORIZONTAL
)
826 Widget scrollBar
= (Widget
) ((orient
== wxHORIZONTAL
) ? m_hScrollBar
: m_vScrollBar
);
830 XtVaGetValues(scrollBar
, XmNvalue
, &pos
, NULL
);
838 // This now returns the whole range, not just the number of positions that we
840 int wxWindow::GetScrollRange(int orient
) const
842 Widget scrollBar
= (Widget
)GetScrollbar((wxOrientation
)orient
);
843 wxCHECK_MSG( scrollBar
, 0, "no such scrollbar" );
847 XtVaGetValues(scrollBar
, XmNmaximum
, &range
, NULL
);
851 int wxWindow::GetScrollThumb(int orient
) const
853 Widget scrollBar
= (Widget
)GetScrollbar((wxOrientation
)orient
);
854 wxCHECK_MSG( scrollBar
, 0, "no such scrollbar" );
857 XtVaGetValues(scrollBar
, XmNsliderSize
, &thumb
, NULL
);
861 void wxWindow::SetScrollPos(int orient
, int pos
, bool WXUNUSED(refresh
))
863 Widget scrollBar
= (Widget
)GetScrollbar((wxOrientation
)orient
);
867 XtVaSetValues (scrollBar
, XmNvalue
, pos
, NULL
);
870 SetInternalScrollPos((wxOrientation
)orient
, pos
);
873 // New function that will replace some of the above.
874 void wxWindow::SetScrollbar(int orient
, int pos
, int thumbVisible
,
875 int range
, bool WXUNUSED(refresh
))
878 GetSize(& oldW
, & oldH
);
882 if (thumbVisible
== 0)
885 if (thumbVisible
> range
)
886 thumbVisible
= range
;
888 // Save the old state to see if it changed
889 WXWidget oldScrollBar
= GetScrollbar((wxOrientation
)orient
);
891 if (orient
== wxHORIZONTAL
)
893 if (thumbVisible
== range
)
896 DestroyScrollbar(wxHORIZONTAL
);
901 CreateScrollbar(wxHORIZONTAL
);
904 if (orient
== wxVERTICAL
)
906 if (thumbVisible
== range
)
909 DestroyScrollbar(wxVERTICAL
);
914 CreateScrollbar(wxVERTICAL
);
917 WXWidget newScrollBar
= GetScrollbar((wxOrientation
)orient
);
919 if (oldScrollBar
!= newScrollBar
)
921 // This is important! Without it, scrollbars misbehave badly.
922 XtUnrealizeWidget((Widget
) m_scrolledWindow
);
923 XmScrolledWindowSetAreas ((Widget
) m_scrolledWindow
, (Widget
) m_hScrollBar
, (Widget
) m_vScrollBar
, (Widget
) m_drawingArea
);
924 XtRealizeWidget((Widget
) m_scrolledWindow
);
925 XtManageChild((Widget
) m_scrolledWindow
);
930 XtVaSetValues((Widget
) newScrollBar
,
934 XmNsliderSize
, thumbVisible
,
938 SetInternalScrollPos((wxOrientation
)orient
, pos
);
941 GetSize(& newW
, & newH
);
943 // Adjusting scrollbars can resize the canvas accidentally
944 if (newW
!= oldW
|| newH
!= oldH
)
945 SetSize(-1, -1, oldW
, oldH
);
948 // Does a physical scroll
949 void wxWindow::ScrollWindow(int dx
, int dy
, const wxRect
*rect
)
954 // Use specified rectangle
955 x
= rect
->x
; y
= rect
->y
; w
= rect
->width
; h
= rect
->height
;
959 // Use whole client area
961 GetClientSize(& w
, & h
);
964 wxWindowList::Node
*cnode
= m_children
.GetFirst();
967 wxWindow
*child
= cnode
->GetData();
970 child
->GetSize( &sx
, &sy
);
971 wxPoint
pos( child
->GetPosition() );
972 child
->SetSize( pos
.x
+ dx
, pos
.y
+ dy
, sx
, sy
, wxSIZE_ALLOW_MINUS_ONE
);
973 cnode
= cnode
->GetNext();
976 int x1
= (dx
>= 0) ? x
: x
- dx
;
977 int y1
= (dy
>= 0) ? y
: y
- dy
;
978 int w1
= w
- abs(dx
);
979 int h1
= h
- abs(dy
);
980 int x2
= (dx
>= 0) ? x
+ dx
: x
;
981 int y2
= (dy
>= 0) ? y
+ dy
: y
;
985 dc
.SetLogicalFunction (wxCOPY
);
987 Widget widget
= (Widget
) GetMainWidget();
988 Window window
= XtWindow(widget
);
989 Display
* display
= XtDisplay(widget
);
991 XCopyArea(display
, window
, window
, (GC
) dc
.GetGC(),
992 x1
, y1
, w1
, h1
, x2
, y2
);
994 dc
.SetAutoSetting(TRUE
);
995 wxBrush
brush(GetBackgroundColour(), wxSOLID
);
996 dc
.SetBrush(brush
); // FIXME: needed?
998 // We'll add rectangles to the list of update rectangles according to which
999 // bits we've exposed.
1004 wxRect
*rect
= new wxRect
;
1010 XFillRectangle(display
, window
,
1011 (GC
) dc
.GetGC(), rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1015 rect
->width
= rect
->width
;
1016 rect
->height
= rect
->height
;
1018 updateRects
.Append((wxObject
*) rect
);
1022 wxRect
*rect
= new wxRect
;
1024 rect
->x
= x
+ w
+ dx
;
1029 XFillRectangle(display
, window
,
1030 (GC
) dc
.GetGC(), rect
->x
, rect
->y
, rect
->width
,
1035 rect
->width
= rect
->width
;
1036 rect
->height
= rect
->height
;
1038 updateRects
.Append((wxObject
*) rect
);
1042 wxRect
*rect
= new wxRect
;
1049 XFillRectangle(display
, window
,
1050 (GC
) dc
.GetGC(), rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1054 rect
->width
= rect
->width
;
1055 rect
->height
= rect
->height
;
1057 updateRects
.Append((wxObject
*) rect
);
1061 wxRect
*rect
= new wxRect
;
1064 rect
->y
= y
+ h
+ dy
;
1068 XFillRectangle(display
, window
,
1069 (GC
) dc
.GetGC(), rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1073 rect
->width
= rect
->width
;
1074 rect
->height
= rect
->height
;
1076 updateRects
.Append((wxObject
*) rect
);
1078 dc
.SetBrush(wxNullBrush
);
1080 // Now send expose events
1082 wxList::Node
* node
= updateRects
.GetFirst();
1085 wxRect
* rect
= (wxRect
*) node
->GetData();
1088 event
.type
= Expose
;
1089 event
.display
= display
;
1090 event
.send_event
= True
;
1091 event
.window
= window
;
1095 event
.width
= rect
->width
;
1096 event
.height
= rect
->height
;
1100 XSendEvent(display
, window
, False
, ExposureMask
, (XEvent
*)&event
);
1102 node
= node
->GetNext();
1106 // Delete the update rects
1107 node
= updateRects
.GetFirst();
1110 wxRect
* rect
= (wxRect
*) node
->GetData();
1112 node
= node
->GetNext();
1115 XmUpdateDisplay((Widget
) GetMainWidget());
1118 // ---------------------------------------------------------------------------
1120 // ---------------------------------------------------------------------------
1122 #if wxUSE_DRAG_AND_DROP
1124 void wxWindow::SetDropTarget(wxDropTarget
* WXUNUSED(pDropTarget
))
1131 // Old style file-manager drag&drop
1132 void wxWindow::DragAcceptFiles(bool WXUNUSED(accept
))
1137 // ----------------------------------------------------------------------------
1139 // ----------------------------------------------------------------------------
1143 void wxWindow::DoSetToolTip(wxToolTip
* WXUNUSED(tooltip
))
1148 #endif // wxUSE_TOOLTIPS
1150 // ----------------------------------------------------------------------------
1152 // ----------------------------------------------------------------------------
1154 bool wxWindow::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1156 Widget widget
= (Widget
) GetMainWidget();
1158 /* The menuId field seems to be usused, so we'll use it to
1159 indicate whether a menu is popped up or not:
1160 0: Not currently created as a popup
1161 -1: Created as a popup, but not active
1165 if (menu
->GetParent() && (menu
->GetId() != -1))
1168 if (menu
->GetMainWidget()) {
1169 menu
->DestroyMenu(TRUE
);
1172 menu
->SetId(1); /* Mark as popped-up */
1173 menu
->CreateMenu(NULL
, widget
, menu
);
1174 menu
->SetInvokingWindow(this);
1178 // menu->SetParent(parent);
1179 // parent->children->Append(menu); // Store menu for later deletion
1181 Widget menuWidget
= (Widget
) menu
->GetMainWidget();
1189 if (this->IsKindOf(CLASSINFO(wxCanvas)))
1191 wxCanvas *canvas = (wxCanvas *) this;
1192 deviceX = canvas->GetDC ()->LogicalToDeviceX (x);
1193 deviceY = canvas->GetDC ()->LogicalToDeviceY (y);
1197 Display
*display
= XtDisplay (widget
);
1198 Window rootWindow
= RootWindowOfScreen (XtScreen((Widget
)widget
));
1199 Window thisWindow
= XtWindow (widget
);
1201 XTranslateCoordinates (display
, thisWindow
, rootWindow
, (int) deviceX
, (int) deviceY
,
1202 &rootX
, &rootY
, &childWindow
);
1204 XButtonPressedEvent event
;
1205 event
.type
= ButtonPress
;
1211 event
.x_root
= rootX
;
1212 event
.y_root
= rootY
;
1214 XmMenuPosition (menuWidget
, &event
);
1215 XtManageChild (menuWidget
);
1218 // The ID of a pop-up menu is 1 when active, and is set to 0 by the
1219 // idle-time destroy routine.
1220 // Waiting until this ID changes causes this function to block until
1221 // the menu has been dismissed and the widgets cleaned up.
1222 // In other words, once this routine returns, it is safe to delete
1224 // Ian Brown <ian.brown@printsoft.de>
1225 while (menu
->GetId() == 1)
1227 XtAppNextEvent( (XtAppContext
) wxTheApp
->GetAppContext(), &x_event
);
1229 wxTheApp
->ProcessXEvent((WXEvent
*) & x_event
);
1231 if (XtAppPending( (XtAppContext
) wxTheApp
->GetAppContext() ) == 0)
1233 if (!wxTheApp
->ProcessIdle())
1236 // leave the main loop to give other threads a chance to
1237 // perform their GUI work
1248 // ---------------------------------------------------------------------------
1249 // moving and resizing
1250 // ---------------------------------------------------------------------------
1252 bool wxWindow::PreResize()
1258 void wxWindow::DoGetSize(int *x
, int *y
) const
1262 CanvasGetSize(x
, y
);
1266 Widget widget
= (Widget
) GetTopWidget();
1268 XtVaGetValues(widget
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
1269 if(x
) *x
= xx
; if(y
) *y
= yy
;
1272 void wxWindow::DoGetPosition(int *x
, int *y
) const
1276 CanvasGetPosition(x
, y
);
1279 Widget widget
= (Widget
) GetTopWidget();
1281 XtVaGetValues(widget
, XmNx
, &xx
, XmNy
, &yy
, NULL
);
1283 // We may be faking the client origin. So a window that's really at (0, 30)
1284 // may appear (to wxWin apps) to be at (0, 0).
1287 wxPoint
pt(GetParent()->GetClientAreaOrigin());
1292 if(x
) *x
= xx
; if(y
) *y
= yy
;
1295 void wxWindow::DoScreenToClient(int *x
, int *y
) const
1297 Widget widget
= (Widget
) GetClientWidget();
1298 Display
*display
= XtDisplay((Widget
) GetMainWidget());
1299 Window rootWindow
= RootWindowOfScreen(XtScreen(widget
));
1300 Window thisWindow
= XtWindow(widget
);
1305 XTranslateCoordinates(display
, rootWindow
, thisWindow
, xx
, yy
, x
, y
, &childWindow
);
1308 void wxWindow::DoClientToScreen(int *x
, int *y
) const
1310 Widget widget
= (Widget
) GetClientWidget();
1311 Display
*display
= XtDisplay(widget
);
1312 Window rootWindow
= RootWindowOfScreen(XtScreen(widget
));
1313 Window thisWindow
= XtWindow(widget
);
1318 XTranslateCoordinates(display
, thisWindow
, rootWindow
, xx
, yy
, x
, y
, &childWindow
);
1322 // Get size *available for subwindows* i.e. excluding menu bar etc.
1323 void wxWindow::DoGetClientSize(int *x
, int *y
) const
1325 Widget widget
= (Widget
) GetClientWidget();
1327 XtVaGetValues(widget
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
1328 if(x
) *x
= xx
; if(y
) *y
= yy
;
1331 void wxWindow::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1333 DoSetSizeIntr(x
, y
, width
, height
, sizeFlags
, FALSE
);
1336 void wxWindow::DoSetSizeIntr(int x
, int y
, int width
, int height
,
1337 int sizeFlags
, bool fromCtor
)
1339 // A bit of optimization to help sort out the flickers.
1340 int oldX
= -1, oldY
= -1, oldW
= -1, oldH
= -1;
1343 GetSize(& oldW
, & oldH
);
1344 GetPosition(& oldX
, & oldY
);
1347 if ( !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1360 bool nothingChanged
= (x
== oldX
) && (y
== oldY
) &&
1361 (width
== oldW
) && (height
== oldH
);
1363 if (!wxNoOptimize::CanOptimize())
1365 nothingChanged
= FALSE
;
1368 if ( !nothingChanged
)
1372 CanvasSetSizeIntr(x
, y
, width
, height
, sizeFlags
, fromCtor
);
1373 if( !fromCtor
) DoMoveWindow(x
, y
, width
, height
);
1377 Widget widget
= (Widget
) GetTopWidget();
1381 bool managed
= XtIsManaged( widget
);
1383 XtUnmanageChild(widget
);
1387 AdjustForParentClientOrigin(xx
, yy
, sizeFlags
);
1389 DoMoveWindow(xx
, yy
, width
, height
);
1392 XtManageChild(widget
);
1394 // How about this bit. Maybe we don't need to generate size events
1395 // all the time -- they'll be generated when the window is sized anyway.
1397 wxSizeEvent
sizeEvent(wxSize(width
, height
), GetId());
1398 sizeEvent
.SetEventObject(this);
1400 GetEventHandler()->ProcessEvent(sizeEvent
);
1405 void wxWindow::DoSetClientSize(int width
, int height
)
1409 CanvasSetClientSize(width
, height
);
1413 Widget widget
= (Widget
) GetTopWidget();
1416 XtVaSetValues(widget
, XmNwidth
, width
, NULL
);
1418 XtVaSetValues(widget
, XmNheight
, height
, NULL
);
1420 wxSizeEvent
sizeEvent(wxSize(width
, height
), GetId());
1421 sizeEvent
.SetEventObject(this);
1423 GetEventHandler()->ProcessEvent(sizeEvent
);
1426 // For implementation purposes - sometimes decorations make the client area
1428 wxPoint
wxWindow::GetClientAreaOrigin() const
1430 return wxPoint(0, 0);
1433 void wxWindow::SetSizeHints(int minW
, int minH
, int maxW
, int maxH
, int incW
, int incH
)
1440 wxFrame
*frame
= wxDynamicCast(this, wxFrame
);
1443 // TODO what about dialogs?
1447 Widget widget
= (Widget
) frame
->GetShellWidget();
1450 XtVaSetValues(widget
, XmNminWidth
, minW
, NULL
);
1452 XtVaSetValues(widget
, XmNminHeight
, minH
, NULL
);
1454 XtVaSetValues(widget
, XmNmaxWidth
, maxW
, NULL
);
1456 XtVaSetValues(widget
, XmNmaxHeight
, maxH
, NULL
);
1458 XtVaSetValues(widget
, XmNwidthInc
, incW
, NULL
);
1460 XtVaSetValues(widget
, XmNheightInc
, incH
, NULL
);
1463 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
1465 // see the top of the file, near DoSetSizeIntr
1474 XtVaSetValues((Widget
)GetTopWidget(),
1482 // ---------------------------------------------------------------------------
1484 // ---------------------------------------------------------------------------
1486 int wxWindow::GetCharHeight() const
1488 wxCHECK_MSG( m_font
.Ok(), 0, "valid window font needed" );
1490 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(1.0, GetXDisplay());
1492 int direction
, ascent
, descent
;
1493 XCharStruct overall
;
1494 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1495 &descent
, &overall
);
1497 // return (overall.ascent + overall.descent);
1498 return (ascent
+ descent
);
1501 int wxWindow::GetCharWidth() const
1503 wxCHECK_MSG( m_font
.Ok(), 0, "valid window font needed" );
1505 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(1.0, GetXDisplay());
1507 int direction
, ascent
, descent
;
1508 XCharStruct overall
;
1509 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1510 &descent
, &overall
);
1512 return overall
.width
;
1515 void wxWindow::GetTextExtent(const wxString
& string
,
1517 int *descent
, int *externalLeading
,
1518 const wxFont
*theFont
) const
1520 wxFont
*fontToUse
= (wxFont
*)theFont
;
1522 fontToUse
= (wxFont
*) & m_font
;
1524 wxCHECK_RET( fontToUse
->Ok(), "valid window font needed" );
1526 WXFontStructPtr pFontStruct
= fontToUse
->GetFontStruct(1.0, GetXDisplay());
1528 int direction
, ascent
, descent2
;
1529 XCharStruct overall
;
1530 int slen
= string
.Len();
1534 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1535 &ascent
, &descent2
, &overall
);
1538 XTextExtents((XFontStruct
*) pFontStruct
, string
, slen
,
1539 &direction
, &ascent
, &descent2
, &overall
);
1542 *x
= (overall
.width
);
1544 *y
= (ascent
+ descent2
);
1546 *descent
= descent2
;
1547 if (externalLeading
)
1548 *externalLeading
= 0;
1552 // ----------------------------------------------------------------------------
1554 // ----------------------------------------------------------------------------
1556 void wxWindow::Refresh(bool eraseBack
, const wxRect
*rect
)
1558 m_needsRefresh
= TRUE
;
1559 Display
*display
= XtDisplay((Widget
) GetMainWidget());
1560 Window thisWindow
= XtWindow((Widget
) GetMainWidget());
1562 XExposeEvent dummyEvent
;
1564 GetSize(&width
, &height
);
1566 dummyEvent
.type
= Expose
;
1567 dummyEvent
.display
= display
;
1568 dummyEvent
.send_event
= True
;
1569 dummyEvent
.window
= thisWindow
;
1572 dummyEvent
.x
= rect
->x
;
1573 dummyEvent
.y
= rect
->y
;
1574 dummyEvent
.width
= rect
->width
;
1575 dummyEvent
.height
= rect
->height
;
1581 dummyEvent
.width
= width
;
1582 dummyEvent
.height
= height
;
1584 dummyEvent
.count
= 0;
1588 wxClientDC
dc(this);
1589 wxBrush
backgroundBrush(GetBackgroundColour(), wxSOLID
);
1590 dc
.SetBackground(backgroundBrush
);
1597 XSendEvent(display
, thisWindow
, False
, ExposureMask
, (XEvent
*)&dummyEvent
);
1600 void wxWindow::Clear()
1602 wxClientDC
dc(this);
1603 wxBrush
brush(GetBackgroundColour(), wxSOLID
);
1604 dc
.SetBackground(brush
);
1608 void wxWindow::ClearUpdateRects()
1610 wxRectList::Node
* node
= m_updateRects
.GetFirst();
1613 wxRect
* rect
= node
->GetData();
1615 node
= node
->GetNext();
1618 m_updateRects
.Clear();
1621 void wxWindow::DoPaint()
1623 //TODO : make a temporary gc so we can do the XCopyArea below
1624 if (m_backingPixmap
&& !m_needsRefresh
)
1628 GC tempGC
= (GC
) dc
.GetBackingGC();
1630 Widget widget
= (Widget
) GetMainWidget();
1635 // We have to test whether it's a wxScrolledWindow (hack!) because
1636 // otherwise we don't know how many pixels have been scrolled. We might
1637 // solve this in the future by defining virtual wxWindow functions to get
1638 // the scroll position in pixels. Or, each kind of scrolled window has to
1639 // implement backing stores itself, using generic wxWindows code.
1640 wxScrolledWindow
* scrolledWindow
= wxDynamicCast(this, wxScrolledWindow
);
1641 if ( scrolledWindow
)
1644 scrolledWindow
->CalcScrolledPosition(0, 0, &x
, &y
);
1650 // TODO: This could be optimized further by only copying the areas in the
1651 // current update region.
1653 // Only blit the part visible in the client area. The backing pixmap
1654 // always starts at 0, 0 but we may be looking at only a portion of it.
1655 wxSize clientArea
= GetClientSize();
1656 int toBlitX
= m_pixmapWidth
- scrollPosX
;
1657 int toBlitY
= m_pixmapHeight
- scrollPosY
;
1659 // Copy whichever is samller, the amount of pixmap we have to copy,
1660 // or the size of the client area.
1661 toBlitX
= wxMin(toBlitX
, clientArea
.x
);
1662 toBlitY
= wxMin(toBlitY
, clientArea
.y
);
1664 // Make sure we're not negative
1665 toBlitX
= wxMax(0, toBlitX
);
1666 toBlitY
= wxMax(0, toBlitY
);
1671 (Pixmap
) m_backingPixmap
,
1674 scrollPosX
, scrollPosY
, // Start at the scroll position
1675 toBlitX
, toBlitY
, // How much of the pixmap to copy
1681 // Set an erase event first
1682 wxEraseEvent
eraseEvent(GetId());
1683 eraseEvent
.SetEventObject(this);
1684 GetEventHandler()->ProcessEvent(eraseEvent
);
1686 wxPaintEvent
event(GetId());
1687 event
.SetEventObject(this);
1688 GetEventHandler()->ProcessEvent(event
);
1690 m_needsRefresh
= FALSE
;
1694 // ----------------------------------------------------------------------------
1696 // ----------------------------------------------------------------------------
1698 // Responds to colour changes: passes event on to children.
1699 void wxWindow::OnSysColourChanged(wxSysColourChangedEvent
& event
)
1701 wxWindowList::Node
*node
= GetChildren().GetFirst();
1704 // Only propagate to non-top-level windows
1705 wxWindow
*win
= node
->GetData();
1706 if ( win
->GetParent() )
1708 wxSysColourChangedEvent event2
;
1709 event
.m_eventObject
= win
;
1710 win
->GetEventHandler()->ProcessEvent(event2
);
1713 node
= node
->GetNext();
1717 void wxWindow::OnIdle(wxIdleEvent
& WXUNUSED(event
))
1719 // This calls the UI-update mechanism (querying windows for
1720 // menu/toolbar/control state information)
1724 // ----------------------------------------------------------------------------
1726 // ----------------------------------------------------------------------------
1728 bool wxWindow::ProcessAccelerator(wxKeyEvent
& event
)
1730 if (!m_acceleratorTable
.Ok())
1733 int count
= m_acceleratorTable
.GetCount();
1734 wxAcceleratorEntry
* entries
= m_acceleratorTable
.GetEntries();
1736 for (i
= 0; i
< count
; i
++)
1738 wxAcceleratorEntry
* entry
= & (entries
[i
]);
1739 if (entry
->MatchesEvent(event
))
1741 // Bingo, we have a match. Now find a control that matches the
1742 // entry command id.
1744 // Need to go up to the top of the window hierarchy, since it might
1745 // be e.g. a menu item
1746 wxWindow
* parent
= this;
1747 while ( parent
&& !parent
->IsTopLevel() )
1748 parent
= parent
->GetParent();
1753 wxFrame
* frame
= wxDynamicCast(parent
, wxFrame
);
1756 // Try for a menu command
1757 if (frame
->GetMenuBar())
1759 wxMenuItem
* item
= frame
->GetMenuBar()->FindItem(entry
->GetCommand());
1762 wxCommandEvent
commandEvent(wxEVT_COMMAND_MENU_SELECTED
, entry
->GetCommand());
1763 commandEvent
.SetEventObject(frame
);
1765 // If ProcessEvent returns TRUE (it was handled), then
1766 // the calling code will skip the event handling.
1767 return frame
->GetEventHandler()->ProcessEvent(commandEvent
);
1772 // Find a child matching the command id
1773 wxWindow
* child
= parent
->FindWindow(entry
->GetCommand());
1779 // Now we process those kinds of windows that we can.
1780 // For now, only buttons.
1781 if ( wxDynamicCast(child
, wxButton
) )
1783 wxCommandEvent
commandEvent (wxEVT_COMMAND_BUTTON_CLICKED
, child
->GetId());
1784 commandEvent
.SetEventObject(child
);
1785 return child
->GetEventHandler()->ProcessEvent(commandEvent
);
1792 // We didn't match the key event against an accelerator.
1796 // ============================================================================
1797 // Motif-specific stuff from here on
1798 // ============================================================================
1800 // ----------------------------------------------------------------------------
1801 // function which maintain the global hash table mapping Widgets to wxWindows
1802 // ----------------------------------------------------------------------------
1804 bool wxAddWindowToTable(Widget w
, wxWindow
*win
)
1806 wxWindow
*oldItem
= NULL
;
1807 if ((oldItem
= (wxWindow
*)wxWidgetHashTable
->Get ((long) w
)))
1809 wxLogDebug("Widget table clash: new widget is %ld, %s",
1810 (long)w
, win
->GetClassInfo()->GetClassName());
1814 wxWidgetHashTable
->Put((long) w
, win
);
1816 wxLogTrace("widget", "Widget 0x%p <-> window %p (%s)",
1817 (WXWidget
)w
, win
, win
->GetClassInfo()->GetClassName());
1822 wxWindow
*wxGetWindowFromTable(Widget w
)
1824 return (wxWindow
*)wxWidgetHashTable
->Get((long) w
);
1827 void wxDeleteWindowFromTable(Widget w
)
1829 wxWidgetHashTable
->Delete((long)w
);
1832 // ----------------------------------------------------------------------------
1833 // add/remove window from the table
1834 // ----------------------------------------------------------------------------
1836 // Add to hash table, add event handler
1837 bool wxWindow::AttachWidget (wxWindow
* WXUNUSED(parent
), WXWidget mainWidget
,
1838 WXWidget formWidget
, int x
, int y
, int width
, int height
)
1840 wxAddWindowToTable((Widget
) mainWidget
, this);
1841 if (CanAddEventHandler())
1843 XtAddEventHandler((Widget
) mainWidget
,
1844 ButtonPressMask
| ButtonReleaseMask
| PointerMotionMask
, // | KeyPressMask,
1846 wxPanelItemEventHandler
,
1853 XtOverrideTranslations ((Widget
) mainWidget
,
1854 ptr
= XtParseTranslationTable ("<Configure>: resize()"));
1855 XtFree ((char *) ptr
);
1858 // Some widgets have a parent form widget, e.g. wxRadioBox
1861 if (!wxAddWindowToTable((Widget
) formWidget
, this))
1865 XtOverrideTranslations ((Widget
) formWidget
,
1866 ptr
= XtParseTranslationTable ("<Configure>: resize()"));
1867 XtFree ((char *) ptr
);
1874 SetSize (x
, y
, width
, height
);
1879 // Remove event handler, remove from hash table
1880 bool wxWindow::DetachWidget(WXWidget widget
)
1882 if (CanAddEventHandler())
1884 XtRemoveEventHandler((Widget
) widget
,
1885 ButtonPressMask
| ButtonReleaseMask
| PointerMotionMask
, // | KeyPressMask,
1887 wxPanelItemEventHandler
,
1891 wxDeleteWindowFromTable((Widget
) widget
);
1895 // ----------------------------------------------------------------------------
1896 // Motif-specific accessors
1897 // ----------------------------------------------------------------------------
1899 // Get the underlying X window
1900 WXWindow
wxWindow::GetXWindow() const
1902 Widget wMain
= (Widget
)GetMainWidget();
1904 return (WXWindow
) XtWindow(wMain
);
1906 return (WXWindow
) 0;
1909 // Get the underlying X display
1910 WXDisplay
*wxWindow::GetXDisplay() const
1912 Widget wMain
= (Widget
)GetMainWidget();
1914 return (WXDisplay
*) XtDisplay(wMain
);
1916 return (WXDisplay
*) NULL
;
1919 WXWidget
wxWindow::GetMainWidget() const
1922 return m_drawingArea
;
1924 return m_mainWidget
;
1927 WXWidget
wxWindow::GetClientWidget() const
1929 if (m_drawingArea
!= (WXWidget
) 0)
1930 return m_drawingArea
;
1932 return GetMainWidget();
1935 WXWidget
wxWindow::GetTopWidget() const
1937 return GetMainWidget();
1940 WXWidget
wxWindow::GetLabelWidget() const
1942 return GetMainWidget();
1945 // ----------------------------------------------------------------------------
1947 // ----------------------------------------------------------------------------
1949 // All widgets should have this as their resize proc.
1950 // OnSize sent to wxWindow via client data.
1951 void wxWidgetResizeProc(Widget w
, XConfigureEvent
*WXUNUSED(event
), String
WXUNUSED(args
)[], int *WXUNUSED(num_args
))
1953 wxWindow
*win
= wxGetWindowFromTable(w
);
1957 if (win
->PreResize())
1960 win
->GetSize(&width
, &height
);
1961 wxSizeEvent
sizeEvent(wxSize(width
, height
), win
->GetId());
1962 sizeEvent
.SetEventObject(win
);
1963 win
->GetEventHandler()->ProcessEvent(sizeEvent
);
1967 static void wxCanvasRepaintProc(Widget drawingArea
,
1968 XtPointer clientData
,
1969 XmDrawingAreaCallbackStruct
* cbs
)
1971 if (!wxGetWindowFromTable(drawingArea
))
1974 XEvent
* event
= cbs
->event
;
1975 wxWindow
* win
= (wxWindow
*) clientData
;
1977 switch (event
->type
)
1981 win
->AddUpdateRect(event
->xexpose
.x
, event
->xexpose
.y
,
1982 event
->xexpose
.width
, event
->xexpose
.height
);
1984 if (event
-> xexpose
.count
== 0)
1987 win
->ClearUpdateRects();
1994 // Unable to deal with Enter/Leave without a separate EventHandler (Motif 1.1.4)
1995 static void wxCanvasEnterLeave(Widget drawingArea
,
1996 XtPointer
WXUNUSED(clientData
),
1997 XCrossingEvent
* event
)
1999 XmDrawingAreaCallbackStruct cbs
;
2002 ((XCrossingEvent
&) ev
) = *event
;
2004 cbs
.reason
= XmCR_INPUT
;
2007 wxCanvasInputEvent(drawingArea
, (XtPointer
) NULL
, &cbs
);
2010 // Fix to make it work under Motif 1.0 (!)
2011 static void wxCanvasMotionEvent (Widget
WXUNUSED(drawingArea
), XButtonEvent
* WXUNUSED(event
))
2013 #if XmVersion <= 1000
2014 XmDrawingAreaCallbackStruct cbs
;
2017 ev
= *((XEvent
*) event
);
2018 cbs
.reason
= XmCR_INPUT
;
2021 wxCanvasInputEvent (drawingArea
, (XtPointer
) NULL
, &cbs
);
2022 #endif // XmVersion <= 1000
2025 static void wxCanvasInputEvent(Widget drawingArea
,
2026 XtPointer
WXUNUSED(data
),
2027 XmDrawingAreaCallbackStruct
* cbs
)
2029 wxWindow
*canvas
= wxGetWindowFromTable(drawingArea
);
2035 if (cbs
->reason
!= XmCR_INPUT
)
2038 local_event
= *(cbs
->event
); // We must keep a copy!
2040 switch (local_event
.xany
.type
)
2048 // FIXME: most of this mouse event code is more or less
2049 // duplicated in wxTranslateMouseEvent
2051 wxEventType eventType
= wxEVT_NULL
;
2053 if (local_event
.xany
.type
== EnterNotify
)
2055 //if (local_event.xcrossing.mode!=NotifyNormal)
2056 // return ; // Ignore grab events
2057 eventType
= wxEVT_ENTER_WINDOW
;
2058 // canvas->GetEventHandler()->OnSetFocus();
2060 else if (local_event
.xany
.type
== LeaveNotify
)
2062 //if (local_event.xcrossingr.mode!=NotifyNormal)
2063 // return ; // Ignore grab events
2064 eventType
= wxEVT_LEAVE_WINDOW
;
2065 // canvas->GetEventHandler()->OnKillFocus();
2067 else if (local_event
.xany
.type
== MotionNotify
)
2069 eventType
= wxEVT_MOTION
;
2072 else if (local_event
.xany
.type
== ButtonPress
)
2074 if (local_event
.xbutton
.button
== Button1
)
2076 eventType
= wxEVT_LEFT_DOWN
;
2077 canvas
->SetButton1(TRUE
);
2079 else if (local_event
.xbutton
.button
== Button2
)
2081 eventType
= wxEVT_MIDDLE_DOWN
;
2082 canvas
->SetButton2(TRUE
);
2084 else if (local_event
.xbutton
.button
== Button3
)
2086 eventType
= wxEVT_RIGHT_DOWN
;
2087 canvas
->SetButton3(TRUE
);
2090 else if (local_event
.xany
.type
== ButtonRelease
)
2092 if (local_event
.xbutton
.button
== Button1
)
2094 eventType
= wxEVT_LEFT_UP
;
2095 canvas
->SetButton1(FALSE
);
2097 else if (local_event
.xbutton
.button
== Button2
)
2099 eventType
= wxEVT_MIDDLE_UP
;
2100 canvas
->SetButton2(FALSE
);
2102 else if (local_event
.xbutton
.button
== Button3
)
2104 eventType
= wxEVT_RIGHT_UP
;
2105 canvas
->SetButton3(FALSE
);
2109 wxMouseEvent
wxevent (eventType
);
2111 wxevent
.m_leftDown
= ((eventType
== wxEVT_LEFT_DOWN
)
2112 || (event_left_is_down (&local_event
)
2113 && (eventType
!= wxEVT_LEFT_UP
)));
2114 wxevent
.m_middleDown
= ((eventType
== wxEVT_MIDDLE_DOWN
)
2115 || (event_middle_is_down (&local_event
)
2116 && (eventType
!= wxEVT_MIDDLE_UP
)));
2117 wxevent
.m_rightDown
= ((eventType
== wxEVT_RIGHT_DOWN
)
2118 || (event_right_is_down (&local_event
)
2119 && (eventType
!= wxEVT_RIGHT_UP
)));
2121 wxevent
.m_shiftDown
= local_event
.xbutton
.state
& ShiftMask
;
2122 wxevent
.m_controlDown
= local_event
.xbutton
.state
& ControlMask
;
2123 wxevent
.m_altDown
= local_event
.xbutton
.state
& Mod3Mask
;
2124 wxevent
.m_metaDown
= local_event
.xbutton
.state
& Mod1Mask
;
2125 wxevent
.SetTimestamp(local_event
.xbutton
.time
);
2127 if ( eventType
== wxEVT_MOTION
)
2129 if (local_event
.xmotion
.is_hint
== NotifyHint
)
2132 Display
*dpy
= XtDisplay (drawingArea
);
2134 XQueryPointer (dpy
, XtWindow (drawingArea
),
2136 &local_event
.xmotion
.x_root
,
2137 &local_event
.xmotion
.y_root
,
2138 &local_event
.xmotion
.x
,
2139 &local_event
.xmotion
.y
,
2140 &local_event
.xmotion
.state
);
2147 // Now check if we need to translate this event into a double click
2148 if (TRUE
) // canvas->doubleClickAllowed)
2150 if (wxevent
.ButtonDown())
2152 long dclickTime
= XtGetMultiClickTime((Display
*) wxGetDisplay());
2154 // get button and time-stamp
2156 if (wxevent
.LeftDown())
2158 else if (wxevent
.MiddleDown())
2160 else if (wxevent
.RightDown())
2162 long ts
= wxevent
.GetTimestamp();
2164 // check, if single or double click
2165 int buttonLast
= canvas
->GetLastClickedButton();
2166 long lastTS
= canvas
->GetLastClickTime();
2167 if ( buttonLast
&& buttonLast
== button
&& (ts
- lastTS
) < dclickTime
)
2170 canvas
->SetLastClick(0, ts
);
2172 wxEventType typeDouble
;
2173 if ( eventType
== wxEVT_LEFT_DOWN
)
2174 typeDouble
= wxEVT_LEFT_DCLICK
;
2175 else if ( eventType
== wxEVT_MIDDLE_DOWN
)
2176 typeDouble
= wxEVT_MIDDLE_DCLICK
;
2177 else if ( eventType
== wxEVT_RIGHT_DOWN
)
2178 typeDouble
= wxEVT_RIGHT_DCLICK
;
2180 typeDouble
= wxEVT_NULL
;
2182 if ( typeDouble
!= wxEVT_NULL
)
2184 wxevent
.SetEventType(typeDouble
);
2189 // not fast enough or different button
2190 canvas
->SetLastClick(button
, ts
);
2195 wxevent
.SetId(canvas
->GetId());
2196 wxevent
.SetEventObject(canvas
);
2197 wxevent
.m_x
= local_event
.xbutton
.x
;
2198 wxevent
.m_y
= local_event
.xbutton
.y
;
2199 canvas
->GetEventHandler()->ProcessEvent (wxevent
);
2201 if (eventType
== wxEVT_ENTER_WINDOW
||
2202 eventType
== wxEVT_LEAVE_WINDOW
||
2203 eventType
== wxEVT_MOTION
2211 wxKeyEvent
event (wxEVT_CHAR
);
2212 if (wxTranslateKeyEvent (event
, canvas
, (Widget
) 0, &local_event
))
2214 // Implement wxFrame::OnCharHook by checking ancestor.
2215 wxWindow
*parent
= canvas
->GetParent();
2216 while (parent
&& !parent
->IsKindOf(CLASSINFO(wxFrame
)))
2217 parent
= parent
->GetParent();
2221 event
.SetEventType(wxEVT_CHAR_HOOK
);
2222 if (parent
->GetEventHandler()->ProcessEvent(event
))
2226 // For simplicity, OnKeyDown is the same as OnChar
2227 // TODO: filter modifier key presses from OnChar
2228 event
.SetEventType(wxEVT_KEY_DOWN
);
2230 // Only process OnChar if OnKeyDown didn't swallow it
2231 if (!canvas
->GetEventHandler()->ProcessEvent (event
))
2233 event
.SetEventType(wxEVT_CHAR
);
2234 canvas
->GetEventHandler()->ProcessEvent (event
);
2241 wxKeyEvent
event (wxEVT_KEY_UP
);
2242 if (wxTranslateKeyEvent (event
, canvas
, (Widget
) 0, &local_event
))
2244 canvas
->GetEventHandler()->ProcessEvent (event
);
2250 if (local_event
.xfocus
.detail
!= NotifyPointer
)
2252 wxFocusEvent
event(wxEVT_SET_FOCUS
, canvas
->GetId());
2253 event
.SetEventObject(canvas
);
2254 canvas
->GetEventHandler()->ProcessEvent(event
);
2260 if (local_event
.xfocus
.detail
!= NotifyPointer
)
2262 wxFocusEvent
event(wxEVT_KILL_FOCUS
, canvas
->GetId());
2263 event
.SetEventObject(canvas
);
2264 canvas
->GetEventHandler()->ProcessEvent(event
);
2273 static void wxPanelItemEventHandler(Widget wid
,
2274 XtPointer
WXUNUSED(client_data
),
2276 Boolean
*continueToDispatch
)
2278 // Widget can be a label or the actual widget.
2280 wxWindow
*window
= wxGetWindowFromTable(wid
);
2283 wxMouseEvent
wxevent(0);
2284 if (wxTranslateMouseEvent(wxevent
, window
, wid
, event
))
2286 window
->GetEventHandler()->ProcessEvent(wxevent
);
2290 // TODO: probably the key to allowing default behaviour to happen. Say we
2291 // set a m_doDefault flag to FALSE at the start of this function. Then in
2292 // e.g. wxWindow::OnMouseEvent we can call Default() which sets this flag to
2293 // TRUE, indicating that default processing can happen. Thus, behaviour can
2294 // appear to be overridden just by adding an event handler and not calling
2295 // wxWindow::OnWhatever. ALSO, maybe we can use this instead of the current
2296 // way of handling drawing area events, to simplify things.
2297 *continueToDispatch
= True
;
2300 static void wxScrollBarCallback(Widget scrollbar
,
2301 XtPointer clientData
,
2302 XmScrollBarCallbackStruct
*cbs
)
2304 wxWindow
*win
= wxGetWindowFromTable(scrollbar
);
2305 int orientation
= (int) clientData
;
2307 wxEventType eventType
= wxEVT_NULL
;
2308 switch (cbs
->reason
)
2310 case XmCR_INCREMENT
:
2312 eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
2315 case XmCR_DECREMENT
:
2317 eventType
= wxEVT_SCROLLWIN_LINEUP
;
2322 eventType
= wxEVT_SCROLLWIN_THUMBTRACK
;
2325 case XmCR_VALUE_CHANGED
:
2327 eventType
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2330 case XmCR_PAGE_INCREMENT
:
2332 eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
2335 case XmCR_PAGE_DECREMENT
:
2337 eventType
= wxEVT_SCROLLWIN_PAGEUP
;
2342 eventType
= wxEVT_SCROLLWIN_TOP
;
2345 case XmCR_TO_BOTTOM
:
2347 eventType
= wxEVT_SCROLLWIN_BOTTOM
;
2352 // Should never get here
2353 wxFAIL_MSG("Unknown scroll event.");
2358 wxScrollWinEvent
event(eventType
,
2360 ((orientation
== XmHORIZONTAL
) ?
2361 wxHORIZONTAL
: wxVERTICAL
));
2362 event
.SetEventObject( win
);
2363 win
->GetEventHandler()->ProcessEvent(event
);
2366 // For repainting arbitrary windows
2367 void wxUniversalRepaintProc(Widget w
, XtPointer
WXUNUSED(c_data
), XEvent
*event
, char *)
2372 wxWindow
* win
= wxGetWindowFromTable(w
);
2376 switch(event
-> type
)
2380 window
= (Window
) win
-> GetXWindow();
2381 display
= (Display
*) win
-> GetXDisplay();
2383 if (event
-> xexpose
.count
== 0)
2387 win
->ClearUpdateRects();
2391 win
->AddUpdateRect(event
->xexpose
.x
, event
->xexpose
.y
,
2392 event
->xexpose
.width
, event
->xexpose
.height
);
2400 // ----------------------------------------------------------------------------
2401 // CanvaseXXXSize() functions
2402 // ----------------------------------------------------------------------------
2404 void wxWindow::CanvasSetSize(int x
, int y
, int w
, int h
, int sizeFlags
)
2406 CanvasSetSizeIntr(x
, y
, w
, h
, sizeFlags
, FALSE
);
2409 // SetSize, but as per old wxCanvas (with drawing widget etc.)
2410 void wxWindow::CanvasSetSizeIntr(int x
, int y
, int w
, int h
, int sizeFlags
,
2413 // A bit of optimization to help sort out the flickers.
2414 int oldX
= -1, oldY
= -1, oldW
= -1, oldH
= -1;
2415 // see the top of the file, near DoSetSizeIntr
2418 GetSize(& oldW
, & oldH
);
2419 GetPosition(& oldX
, & oldY
);
2422 bool useOldPos
= FALSE
;
2423 bool useOldSize
= FALSE
;
2425 if ((x
== -1) && (x
== -1) && ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0))
2427 else if (x
== oldX
&& y
== oldY
)
2430 if ((w
== -1) && (h
== -1))
2432 else if (w
== oldW
&& h
== oldH
)
2435 if (!wxNoOptimize::CanOptimize())
2437 useOldSize
= FALSE
; useOldPos
= FALSE
;
2440 if (useOldPos
&& useOldSize
)
2443 Widget drawingArea
= (Widget
) m_drawingArea
;
2444 bool managed
= XtIsManaged(m_borderWidget
? (Widget
) m_borderWidget
: (Widget
) m_scrolledWindow
);
2447 XtUnmanageChild (m_borderWidget
? (Widget
) m_borderWidget
: (Widget
) m_scrolledWindow
);
2448 XtVaSetValues(drawingArea
, XmNresizePolicy
, XmRESIZE_ANY
, NULL
);
2450 int xx
= x
; int yy
= y
;
2451 AdjustForParentClientOrigin(xx
, yy
, sizeFlags
);
2455 if (x
> -1 || (sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
))
2457 XtVaSetValues (m_borderWidget
? (Widget
) m_borderWidget
: (Widget
) m_scrolledWindow
,
2461 if (y
> -1 || (sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
))
2463 XtVaSetValues (m_borderWidget
? (Widget
) m_borderWidget
: (Widget
) m_scrolledWindow
,
2475 XtVaSetValues ((Widget
) m_borderWidget
, XmNwidth
, w
, NULL
);
2476 short thick
, margin
;
2477 XtVaGetValues ((Widget
) m_borderWidget
,
2478 XmNshadowThickness
, &thick
,
2479 XmNmarginWidth
, &margin
,
2481 w
-= 2 * (thick
+ margin
);
2484 XtVaSetValues ((Widget
) m_scrolledWindow
, XmNwidth
, w
, NULL
);
2488 XtVaGetValues ((Widget
) m_scrolledWindow
,
2489 XmNspacing
, &spacing
,
2490 XmNverticalScrollBar
, &sbar
,
2494 XtVaGetValues (sbar
, XmNwidth
, &wsbar
, NULL
);
2498 w
-= (spacing
+ wsbar
);
2501 XtVaSetValues(drawingArea
, XmNwidth
, w
, NULL
);
2508 XtVaSetValues ((Widget
) m_borderWidget
, XmNheight
, h
, NULL
);
2509 short thick
, margin
;
2510 XtVaGetValues ((Widget
) m_borderWidget
,
2511 XmNshadowThickness
, &thick
,
2512 XmNmarginHeight
, &margin
,
2514 h
-= 2 * (thick
+ margin
);
2517 XtVaSetValues ((Widget
) m_scrolledWindow
, XmNheight
, h
, NULL
);
2521 XtVaGetValues ((Widget
) m_scrolledWindow
,
2522 XmNspacing
, &spacing
,
2523 XmNhorizontalScrollBar
, &sbar
,
2527 XtVaGetValues (sbar
, XmNheight
, &wsbar
, NULL
);
2531 h
-= (spacing
+ wsbar
);
2534 XtVaSetValues(drawingArea
, XmNheight
, h
, NULL
);
2540 XtManageChild (m_borderWidget
? (Widget
) m_borderWidget
: (Widget
) m_scrolledWindow
);
2541 XtVaSetValues(drawingArea
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
);
2545 GetClientSize (&ww
, &hh
);
2546 wxSizeEvent
sizeEvent(wxSize(ww
, hh
), GetId());
2547 sizeEvent
.SetEventObject(this);
2549 GetEventHandler()->ProcessEvent(sizeEvent
);
2553 void wxWindow::CanvasSetClientSize (int w
, int h
)
2555 Widget drawingArea
= (Widget
) m_drawingArea
;
2557 XtVaSetValues(drawingArea
, XmNresizePolicy
, XmRESIZE_ANY
, NULL
);
2560 XtVaSetValues(drawingArea
, XmNwidth
, w
, NULL
);
2562 XtVaSetValues(drawingArea
, XmNheight
, h
, NULL
);
2565 // TODO: is this necessary?
2566 allowRepainting
= FALSE
;
2568 XSync (XtDisplay (drawingArea
), FALSE
);
2570 while (XtAppPending (wxTheApp
->appContext
))
2572 XFlush (XtDisplay (drawingArea
));
2573 XtAppNextEvent (wxTheApp
->appContext
, &event
);
2574 XtDispatchEvent (&event
);
2578 XtVaSetValues(drawingArea
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
);
2581 allowRepainting
= TRUE
;
2584 wxSizeEvent
sizeEvent(wxSize(w
, h
), GetId());
2585 sizeEvent
.SetEventObject(this);
2587 GetEventHandler()->ProcessEvent(sizeEvent
);
2591 void wxWindow::CanvasGetClientSize (int *w
, int *h
) const
2593 // Must return the same thing that was set via SetClientSize
2595 XtVaGetValues ((Widget
) m_drawingArea
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
2600 void wxWindow::CanvasGetSize (int *w
, int *h
) const
2603 if ((Widget
) m_borderWidget
)
2604 XtVaGetValues ((Widget
) m_borderWidget
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
2605 else if ((Widget
) m_scrolledWindow
)
2606 XtVaGetValues ((Widget
) m_scrolledWindow
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
2608 XtVaGetValues ((Widget
) m_drawingArea
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
2614 void wxWindow::CanvasGetPosition (int *x
, int *y
) const
2617 XtVaGetValues (m_borderWidget
? (Widget
) m_borderWidget
: (Widget
) m_scrolledWindow
, XmNx
, &xx
, XmNy
, &yy
, NULL
);
2619 // We may be faking the client origin.
2620 // So a window that's really at (0, 30) may appear
2621 // (to wxWin apps) to be at (0, 0).
2624 wxPoint
pt(GetParent()->GetClientAreaOrigin());
2633 // ----------------------------------------------------------------------------
2634 // TranslateXXXEvent() functions
2635 // ----------------------------------------------------------------------------
2637 bool wxTranslateMouseEvent(wxMouseEvent
& wxevent
, wxWindow
*win
, Widget widget
, XEvent
*xevent
)
2639 switch (xevent
->xany
.type
)
2641 case EnterNotify
: // never received here - yes ? MB
2642 case LeaveNotify
: // never received here - yes ? MB
2647 wxEventType eventType
= wxEVT_NULL
;
2649 // FIXME: this is never true I think - MB
2651 if (xevent
->xany
.type
== LeaveNotify
)
2653 win
->SetButton1(FALSE
);
2654 win
->SetButton2(FALSE
);
2655 win
->SetButton3(FALSE
);
2658 else if (xevent
->xany
.type
== MotionNotify
)
2660 eventType
= wxEVT_MOTION
;
2662 else if (xevent
->xany
.type
== ButtonPress
)
2664 wxevent
.SetTimestamp(xevent
->xbutton
.time
);
2666 if (xevent
->xbutton
.button
== Button1
)
2668 eventType
= wxEVT_LEFT_DOWN
;
2669 win
->SetButton1(TRUE
);
2672 else if (xevent
->xbutton
.button
== Button2
)
2674 eventType
= wxEVT_MIDDLE_DOWN
;
2675 win
->SetButton2(TRUE
);
2678 else if (xevent
->xbutton
.button
== Button3
)
2680 eventType
= wxEVT_RIGHT_DOWN
;
2681 win
->SetButton3(TRUE
);
2685 // check for a double click
2687 long dclickTime
= XtGetMultiClickTime((Display
*) wxGetDisplay());
2688 long ts
= wxevent
.GetTimestamp();
2690 int buttonLast
= win
->GetLastClickedButton();
2691 long lastTS
= win
->GetLastClickTime();
2692 if ( buttonLast
&& buttonLast
== button
&& (ts
- lastTS
) < dclickTime
)
2695 win
->SetLastClick(0, ts
);
2696 if ( eventType
== wxEVT_LEFT_DOWN
)
2697 eventType
= wxEVT_LEFT_DCLICK
;
2698 else if ( eventType
== wxEVT_MIDDLE_DOWN
)
2699 eventType
= wxEVT_MIDDLE_DCLICK
;
2700 else if ( eventType
== wxEVT_RIGHT_DOWN
)
2701 eventType
= wxEVT_RIGHT_DCLICK
;
2705 // not fast enough or different button
2706 win
->SetLastClick(button
, ts
);
2709 else if (xevent
->xany
.type
== ButtonRelease
)
2711 if (xevent
->xbutton
.button
== Button1
)
2713 eventType
= wxEVT_LEFT_UP
;
2714 win
->SetButton1(FALSE
);
2716 else if (xevent
->xbutton
.button
== Button2
)
2718 eventType
= wxEVT_MIDDLE_UP
;
2719 win
->SetButton2(FALSE
);
2721 else if (xevent
->xbutton
.button
== Button3
)
2723 eventType
= wxEVT_RIGHT_UP
;
2724 win
->SetButton3(FALSE
);
2733 wxevent
.SetEventType(eventType
);
2736 XtVaGetValues(widget
, XmNx
, &x1
, XmNy
, &y1
, NULL
);
2739 win
->GetPosition(&x2
, &y2
);
2741 // The button x/y must be translated to wxWindows
2742 // window space - the widget might be a label or button,
2746 if (widget
!= (Widget
)win
->GetMainWidget())
2752 wxevent
.m_x
= xevent
->xbutton
.x
+ dx
;
2753 wxevent
.m_y
= xevent
->xbutton
.y
+ dy
;
2755 wxevent
.m_leftDown
= ((eventType
== wxEVT_LEFT_DOWN
)
2756 || (event_left_is_down (xevent
)
2757 && (eventType
!= wxEVT_LEFT_UP
)));
2758 wxevent
.m_middleDown
= ((eventType
== wxEVT_MIDDLE_DOWN
)
2759 || (event_middle_is_down (xevent
)
2760 && (eventType
!= wxEVT_MIDDLE_UP
)));
2761 wxevent
.m_rightDown
= ((eventType
== wxEVT_RIGHT_DOWN
)
2762 || (event_right_is_down (xevent
)
2763 && (eventType
!= wxEVT_RIGHT_UP
)));
2765 wxevent
.m_shiftDown
= xevent
->xbutton
.state
& ShiftMask
;
2766 wxevent
.m_controlDown
= xevent
->xbutton
.state
& ControlMask
;
2767 wxevent
.m_altDown
= xevent
->xbutton
.state
& Mod3Mask
;
2768 wxevent
.m_metaDown
= xevent
->xbutton
.state
& Mod1Mask
;
2770 wxevent
.SetId(win
->GetId());
2771 wxevent
.SetEventObject(win
);
2779 bool wxTranslateKeyEvent(wxKeyEvent
& wxevent
, wxWindow
*win
, Widget
WXUNUSED(widget
), XEvent
*xevent
)
2781 switch (xevent
->xany
.type
)
2790 XComposeStatus compose
;
2791 (void) XLookupString ((XKeyEvent
*) xevent
, buf
, 20, &keySym
, &compose
);
2793 (void) XLookupString ((XKeyEvent
*) xevent
, buf
, 20, &keySym
, NULL
);
2794 int id
= wxCharCodeXToWX (keySym
);
2795 // id may be WXK_xxx code - these are outside ASCII range, so we
2796 // can't just use toupper() on id
2797 if (id
>= 'a' && id
<= 'z')
2800 if (xevent
->xkey
.state
& ShiftMask
)
2801 wxevent
.m_shiftDown
= TRUE
;
2802 if (xevent
->xkey
.state
& ControlMask
)
2803 wxevent
.m_controlDown
= TRUE
;
2804 if (xevent
->xkey
.state
& Mod3Mask
)
2805 wxevent
.m_altDown
= TRUE
;
2806 if (xevent
->xkey
.state
& Mod1Mask
)
2807 wxevent
.m_metaDown
= TRUE
;
2808 wxevent
.SetEventObject(win
);
2809 wxevent
.m_keyCode
= id
;
2810 wxevent
.SetTimestamp(xevent
->xkey
.time
);
2812 wxevent
.m_x
= xevent
->xbutton
.x
;
2813 wxevent
.m_y
= xevent
->xbutton
.y
;
2827 // ----------------------------------------------------------------------------
2829 // ----------------------------------------------------------------------------
2831 #define YAllocColor XAllocColor
2832 XColor g_itemColors
[5];
2833 int wxComputeColours (Display
*display
, wxColour
* back
, wxColour
* fore
)
2836 static XmColorProc colorProc
;
2838 result
= wxNO_COLORS
;
2842 g_itemColors
[0].red
= (((long) back
->Red ()) << 8);
2843 g_itemColors
[0].green
= (((long) back
->Green ()) << 8);
2844 g_itemColors
[0].blue
= (((long) back
->Blue ()) << 8);
2845 g_itemColors
[0].flags
= DoRed
| DoGreen
| DoBlue
;
2846 if (colorProc
== (XmColorProc
) NULL
)
2848 // Get a ptr to the actual function
2849 colorProc
= XmSetColorCalculation ((XmColorProc
) NULL
);
2850 // And set it back to motif.
2851 XmSetColorCalculation (colorProc
);
2853 (*colorProc
) (&g_itemColors
[wxBACK_INDEX
],
2854 &g_itemColors
[wxFORE_INDEX
],
2855 &g_itemColors
[wxSELE_INDEX
],
2856 &g_itemColors
[wxTOPS_INDEX
],
2857 &g_itemColors
[wxBOTS_INDEX
]);
2858 result
= wxBACK_COLORS
;
2862 g_itemColors
[wxFORE_INDEX
].red
= (((long) fore
->Red ()) << 8);
2863 g_itemColors
[wxFORE_INDEX
].green
= (((long) fore
->Green ()) << 8);
2864 g_itemColors
[wxFORE_INDEX
].blue
= (((long) fore
->Blue ()) << 8);
2865 g_itemColors
[wxFORE_INDEX
].flags
= DoRed
| DoGreen
| DoBlue
;
2866 if (result
== wxNO_COLORS
)
2867 result
= wxFORE_COLORS
;
2870 Display
*dpy
= display
;
2871 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dpy
);
2875 /* 5 Colours to allocate */
2876 for (int i
= 0; i
< 5; i
++)
2877 if (!YAllocColor (dpy
, cmap
, &g_itemColors
[i
]))
2878 result
= wxNO_COLORS
;
2882 /* Only 1 colour to allocate */
2883 if (!YAllocColor (dpy
, cmap
, &g_itemColors
[wxFORE_INDEX
]))
2884 result
= wxNO_COLORS
;
2891 // Changes the foreground and background colours to be derived from the current
2892 // background colour. To change the foreground colour, you must call
2893 // SetForegroundColour explicitly.
2894 void wxWindow::ChangeBackgroundColour()
2896 WXWidget mainWidget
= GetMainWidget();
2898 DoChangeBackgroundColour(mainWidget
, m_backgroundColour
);
2900 // This not necessary
2903 if (m_scrolledWindow
&& (GetMainWidget() != m_scrolledWindow
))
2905 DoChangeBackgroundColour(m_scrolledWindow
, m_backgroundColour
);
2906 // Have to set the scrollbar colours back since
2907 // the scrolled window seemed to change them
2908 wxColour backgroundColour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
2911 DoChangeBackgroundColour(m_hScrollBar
, backgroundColour
);
2913 DoChangeBackgroundColour(m_vScrollBar
, backgroundColour
);
2918 void wxWindow::ChangeForegroundColour()
2920 WXWidget mainWidget
= GetMainWidget();
2922 DoChangeForegroundColour(mainWidget
, m_foregroundColour
);
2923 if ( m_scrolledWindow
&& mainWidget
!= m_scrolledWindow
)
2924 DoChangeForegroundColour(m_scrolledWindow
, m_foregroundColour
);
2927 // Change a widget's foreground and background colours.
2928 void wxWindow::DoChangeForegroundColour(WXWidget widget
, wxColour
& foregroundColour
)
2930 // When should we specify the foreground, if it's calculated
2931 // by wxComputeColours?
2932 // Solution: say we start with the default (computed) foreground colour.
2933 // If we call SetForegroundColour explicitly for a control or window,
2934 // then the foreground is changed.
2935 // Therefore SetBackgroundColour computes the foreground colour, and
2936 // SetForegroundColour changes the foreground colour. The ordering is
2939 Widget w
= (Widget
)widget
;
2942 XmNforeground
, foregroundColour
.AllocColour(XtDisplay(w
)),
2947 void wxWindow::DoChangeBackgroundColour(WXWidget widget
, wxColour
& backgroundColour
, bool changeArmColour
)
2949 wxComputeColours (XtDisplay((Widget
) widget
), & backgroundColour
,
2952 XtVaSetValues ((Widget
) widget
,
2953 XmNbackground
, g_itemColors
[wxBACK_INDEX
].pixel
,
2954 XmNtopShadowColor
, g_itemColors
[wxTOPS_INDEX
].pixel
,
2955 XmNbottomShadowColor
, g_itemColors
[wxBOTS_INDEX
].pixel
,
2956 XmNforeground
, g_itemColors
[wxFORE_INDEX
].pixel
,
2959 if (changeArmColour
)
2960 XtVaSetValues ((Widget
) widget
,
2961 XmNarmColor
, g_itemColors
[wxSELE_INDEX
].pixel
,
2965 bool wxWindow::SetBackgroundColour(const wxColour
& col
)
2967 if ( !wxWindowBase::SetBackgroundColour(col
) )
2970 ChangeBackgroundColour();
2975 bool wxWindow::SetForegroundColour(const wxColour
& col
)
2977 if ( !wxWindowBase::SetForegroundColour(col
) )
2980 ChangeForegroundColour();
2985 void wxWindow::ChangeFont(bool keepOriginalSize
)
2987 // Note that this causes the widget to be resized back
2988 // to its original size! We therefore have to set the size
2989 // back again. TODO: a better way in Motif?
2990 Widget w
= (Widget
) GetLabelWidget(); // Usually the main widget
2991 if (w
&& m_font
.Ok())
2993 int width
, height
, width1
, height1
;
2994 GetSize(& width
, & height
);
2996 // lesstif 0.87 hangs here, but 0.93 does not
2997 #if !defined(LESSTIF_VERSION) \
2998 || (defined(LesstifVersion) && LesstifVersion >= 93)
3000 XmNfontList
, (XmFontList
) m_font
.GetFontList(1.0, XtDisplay(w
)),
3004 GetSize(& width1
, & height1
);
3005 if (keepOriginalSize
&& (width
!= width1
|| height
!= height1
))
3007 SetSize(-1, -1, width
, height
);
3012 // ----------------------------------------------------------------------------
3014 // ----------------------------------------------------------------------------
3016 wxWindow
*wxGetActiveWindow()
3019 wxFAIL_MSG("Not implemented");
3024 wxWindow
*wxWindowBase::GetCapture()
3026 return (wxWindow
*)g_captureWindow
;
3030 // Find the wxWindow at the current mouse position, returning the mouse
3032 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
3034 return wxFindWindowAtPoint(wxGetMousePosition());
3037 // Get the current mouse position.
3038 wxPoint
wxGetMousePosition()
3040 Display
*display
= (Display
*) wxGetDisplay();
3041 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
3042 Window rootReturn
, childReturn
;
3043 int rootX
, rootY
, winX
, winY
;
3044 unsigned int maskReturn
;
3046 XQueryPointer (display
,
3050 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
3051 return wxPoint(rootX
, rootY
);
3055 // ----------------------------------------------------------------------------
3056 // wxNoOptimize: switch off size optimization
3057 // ----------------------------------------------------------------------------
3059 int wxNoOptimize::ms_count
= 0;