1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/motif/window.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"
30 #include "wx/dcclient.h"
31 #include "wx/button.h"
33 #include "wx/settings.h"
34 #include "wx/scrolwin.h"
35 #include "wx/layout.h"
36 #include "wx/menuitem.h"
37 #include "wx/module.h"
40 #include "wx/evtloop.h"
42 #if wxUSE_DRAG_AND_DROP
46 // DoSetSizeIntr and DoMoveWindowIntr
48 // under Motif composite controls (such as wxCalendarCtrl or generic wxSpinCtrl
49 // did not work and/or segfaulted because
50 // 1) wxWindow::Create calls SetSize,
51 // which results in a call to DoSetSize much earlier than in the other ports
52 // 2) if wxWindow::Create is called (wxControl::Create calls it)
53 // then DoSetSize is never called, causing layout problems in composite
57 // 1) don't call SetSize, DoSetSize, DoMoveWindow, DoGetPosition,
58 // DoSetPosition directly or indirectly from wxWindow::Create
59 // 2) call DoMoveWindow from DoSetSize, allowing controls to override it
62 #pragma message disable nosimpint
66 #include <Xm/DrawingA.h>
67 #include <Xm/ScrolledW.h>
68 #include <Xm/ScrollBar.h>
71 #include <Xm/RowColumn.h> // for XmMenuPosition
73 #pragma message enable nosimpint
76 #include "wx/motif/private.h"
77 #include "wx/motif/dcclient.h"
81 // ----------------------------------------------------------------------------
82 // global variables for this module
83 // ----------------------------------------------------------------------------
85 extern wxHashTable
*wxWidgetHashTable
;
86 static wxWindow
* g_captureWindow
= NULL
;
89 // ----------------------------------------------------------------------------
91 // ----------------------------------------------------------------------------
93 static void wxCanvasRepaintProc(Widget
, XtPointer
, XmDrawingAreaCallbackStruct
* cbs
);
94 static void wxCanvasInputEvent(Widget drawingArea
, XtPointer data
, XmDrawingAreaCallbackStruct
* cbs
);
95 static void wxCanvasMotionEvent(Widget
, XButtonEvent
* event
);
96 static void wxCanvasEnterLeave(Widget drawingArea
, XtPointer clientData
, XCrossingEvent
* event
);
97 static void wxScrollBarCallback(Widget widget
, XtPointer clientData
,
98 XmScrollBarCallbackStruct
*cbs
);
99 static void wxPanelItemEventHandler(Widget wid
,
100 XtPointer client_data
,
102 Boolean
*continueToDispatch
);
107 // Helper function for 16-bit fonts
108 static int str16len(const char *s
)
112 while (s
[0] && s
[1]) {
122 // ----------------------------------------------------------------------------
124 // ----------------------------------------------------------------------------
126 #define event_left_is_down(x) ((x)->xbutton.state & Button1Mask)
127 #define event_middle_is_down(x) ((x)->xbutton.state & Button2Mask)
128 #define event_right_is_down(x) ((x)->xbutton.state & Button3Mask)
130 // ----------------------------------------------------------------------------
132 // ----------------------------------------------------------------------------
134 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
136 BEGIN_EVENT_TABLE(wxWindow
, wxWindowBase
)
137 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged
)
140 // ============================================================================
142 // ============================================================================
144 // ----------------------------------------------------------------------------
146 // ----------------------------------------------------------------------------
148 void wxWindow::UnmanageAndDestroy(WXWidget widget
)
150 Widget w
= (Widget
)widget
;
158 bool wxWindow::MapOrUnmap(WXWidget widget
, bool domap
)
160 Widget w
= (Widget
)widget
;
164 // Rationale: a lot of common operations (including but not
165 // limited to moving, resizing and appending items to a listbox)
166 // unmamange the widget, do their work, then manage it again.
167 // This means that, for example adding an item to a listbox will show it,
168 // or that most controls are shown every time they are moved or resized!
169 XtSetMappedWhenManaged( w
, domap
);
171 // if the widget is not unmanaged, it still intercepts
172 // mouse events, even if it is not mapped (and hence invisible)
187 // ----------------------------------------------------------------------------
189 // ----------------------------------------------------------------------------
191 void wxWindow::Init()
194 m_needsRefresh
= true;
195 m_mainWidget
= (WXWidget
) 0;
197 m_winCaptured
= false;
205 m_drawingArea
= (WXWidget
) 0;
210 m_backingPixmap
= (WXPixmap
) 0;
221 // real construction (Init() must have been called before!)
222 bool wxWindow::Create(wxWindow
*parent
, wxWindowID id
,
226 const wxString
& name
)
228 // Get default border
229 wxBorder border
= GetBorder(style
);
230 style
&= ~wxBORDER_MASK
;
233 wxCHECK_MSG( parent
, false, "can't create wxWindow without parent" );
235 CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
);
237 parent
->AddChild(this);
240 //// TODO: we should probably optimize by only creating a
241 //// a drawing area if we have one or more scrollbars (wxVSCROLL/wxHSCROLL).
242 //// But for now, let's simplify things by always creating the
243 //// drawing area, since otherwise the translations are different.
245 // New translations for getting mouse motion feedback
246 static const String translations
= wxMOTIF_STR(
247 "<Btn1Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
248 <Btn2Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
249 <Btn3Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
250 <BtnMotion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
251 <Btn1Down>: DrawingAreaInput() ManagerGadgetArm()\n\
252 <Btn2Down>: DrawingAreaInput() ManagerGadgetArm()\n\
253 <Btn3Down>: DrawingAreaInput() ManagerGadgetArm()\n\
254 <Btn1Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
255 <Btn2Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
256 <Btn3Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
257 <Motion>: wxCanvasMotionEvent() DrawingAreaInput()\n\
258 <EnterWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
259 <LeaveWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
260 <Key>: DrawingAreaInput()");
262 XtActionsRec actions
[1];
263 actions
[0].string
= wxMOTIF_STR("wxCanvasMotionEvent");
264 actions
[0].proc
= (XtActionProc
) wxCanvasMotionEvent
;
265 XtAppAddActions ((XtAppContext
) wxTheApp
->GetAppContext(), actions
, 1);
267 Widget parentWidget
= (Widget
) parent
->GetClientWidget();
268 m_borderWidget
= wxCreateBorderWidget( (WXWidget
)parentWidget
, style
);
270 m_scrolledWindow
= (WXWidget
)XtVaCreateManagedWidget
273 xmScrolledWindowWidgetClass
,
274 m_borderWidget
? (Widget
) m_borderWidget
276 XmNresizePolicy
, XmRESIZE_NONE
,
278 XmNscrollingPolicy
, XmAPPLICATION_DEFINED
,
279 //XmNscrollBarDisplayPolicy, XmAS_NEEDED,
283 XtTranslations ptr
= XtParseTranslationTable(translations
);
284 m_drawingArea
= (WXWidget
)XtVaCreateWidget
287 xmDrawingAreaWidgetClass
, (Widget
) m_scrolledWindow
,
288 XmNunitType
, XmPIXELS
,
289 // XmNresizePolicy, XmRESIZE_ANY,
290 XmNresizePolicy
, XmRESIZE_NONE
,
293 XmNtranslations
, ptr
,
296 XtFree((char *) ptr
);
299 if (GetWindowStyleFlag() & wxOVERRIDE_KEY_TRANSLATIONS
)
301 ptr
= XtParseTranslationTable ("<Key>: DrawingAreaInput()");
302 XtOverrideTranslations ((Widget
) m_drawingArea
, ptr
);
303 XtFree ((char *) ptr
);
307 wxAddWindowToTable((Widget
) m_drawingArea
, this);
308 wxAddWindowToTable((Widget
) m_scrolledWindow
, this);
310 // This order is very important in Motif 1.2.1
311 XtRealizeWidget ((Widget
) m_scrolledWindow
);
312 XtRealizeWidget ((Widget
) m_drawingArea
);
313 XtManageChild ((Widget
) m_drawingArea
);
315 ptr
= XtParseTranslationTable("<Configure>: resize()");
316 XtOverrideTranslations((Widget
) m_drawingArea
, ptr
);
317 XtFree ((char *) ptr
);
319 XtAddCallback ((Widget
) m_drawingArea
, XmNexposeCallback
, (XtCallbackProc
) wxCanvasRepaintProc
, (XtPointer
) this);
320 XtAddCallback ((Widget
) m_drawingArea
, XmNinputCallback
, (XtCallbackProc
) wxCanvasInputEvent
, (XtPointer
) this);
323 (Widget
)m_drawingArea
,
324 PointerMotionHintMask
| EnterWindowMask
|
325 LeaveWindowMask
| FocusChangeMask
,
327 (XtEventHandler
) wxCanvasEnterLeave
,
331 XmScrolledWindowSetAreas(
332 (Widget
)m_scrolledWindow
,
333 (Widget
) 0, (Widget
) 0,
334 (Widget
) m_drawingArea
);
338 // Without this, the cursor may not be restored properly (e.g. in splitter
340 SetCursor(*wxSTANDARD_CURSOR
);
341 DoSetSizeIntr(pos
.x
, pos
.y
, size
.x
,size
.y
, wxSIZE_AUTO
, true);
346 wxWindow::~wxWindow()
348 if (g_captureWindow
== this)
349 g_captureWindow
= NULL
;
351 m_isBeingDeleted
= true;
353 // Motif-specific actions first
354 WXWidget wMain
= GetMainWidget();
357 // Removes event handlers
361 // If m_drawingArea, we're a fully-fledged window with drawing area,
362 // scrollbars etc. (what wxCanvas used to be)
365 // Destroy children before destroying self
369 XFreePixmap (XtDisplay ((Widget
) GetMainWidget()), (Pixmap
) m_backingPixmap
);
371 Widget w
= (Widget
) m_drawingArea
;
372 wxDeleteWindowFromTable(w
);
377 m_drawingArea
= (WXWidget
) 0;
380 // Only if we're _really_ a canvas (not a dialog box/panel)
381 if (m_scrolledWindow
)
383 wxDeleteWindowFromTable((Widget
) m_scrolledWindow
);
388 wxDeleteWindowFromTable((Widget
) m_hScrollBar
);
389 XtUnmanageChild((Widget
) m_hScrollBar
);
393 wxDeleteWindowFromTable((Widget
) m_vScrollBar
);
394 XtUnmanageChild((Widget
) m_vScrollBar
);
398 XtDestroyWidget((Widget
) m_hScrollBar
);
400 XtDestroyWidget((Widget
) m_vScrollBar
);
402 UnmanageAndDestroy(m_scrolledWindow
);
406 XtDestroyWidget ((Widget
) m_borderWidget
);
407 m_borderWidget
= (WXWidget
) 0;
410 else // Why wasn't this here before? JACS 8/3/2000
414 // Destroy the window
417 // If this line (XtDestroyWidget) causes a crash, you may comment it out.
418 // Child widgets will get destroyed automatically when a frame
419 // or dialog is destroyed, but before that you may get some memory
420 // leaks and potential layout problems if you delete and then add
423 // GRG, Feb/2000: commented this out when adding support for
424 // wxSCROLL[WIN]_THUMBRELEASE events. Also it was reported
425 // that this call crashed wxMotif under OS/2, so it seems
426 // that leaving it out is the right thing to do.
427 // SN, Feb/2000: newgrid/griddemo shows why it is needed :-(
428 XtDestroyWidget((Widget
) GetMainWidget());
429 SetMainWidget((WXWidget
) NULL
);
433 // ----------------------------------------------------------------------------
434 // scrollbar management
435 // ----------------------------------------------------------------------------
437 WXWidget
wxWindow::DoCreateScrollBar(WXWidget parent
,
438 wxOrientation orientation
,
441 int orient
= ( orientation
& wxHORIZONTAL
) ? XmHORIZONTAL
: XmVERTICAL
;
443 XtVaCreateManagedWidget( "scrollBarWidget",
444 xmScrollBarWidgetClass
, (Widget
)parent
,
445 XmNorientation
, orient
,
450 XtPointer o
= (XtPointer
)orientation
;
451 XtCallbackProc cb
= (XtCallbackProc
)callback
;
453 XtAddCallback( sb
, XmNvalueChangedCallback
, cb
, o
);
454 XtAddCallback( sb
, XmNdragCallback
, cb
, o
);
455 XtAddCallback( sb
, XmNincrementCallback
, cb
, o
);
456 XtAddCallback( sb
, XmNdecrementCallback
, cb
, o
);
457 XtAddCallback( sb
, XmNpageIncrementCallback
, cb
, o
);
458 XtAddCallback( sb
, XmNpageDecrementCallback
, cb
, o
);
459 XtAddCallback( sb
, XmNtoTopCallback
, cb
, o
);
460 XtAddCallback( sb
, XmNtoBottomCallback
, cb
, o
);
466 void wxWindow::CreateScrollbar(wxOrientation orientation
)
468 wxCHECK_RET( m_drawingArea
, "this window can't have scrollbars" );
470 XtVaSetValues( (Widget
) m_scrolledWindow
,
471 XmNresizePolicy
, XmRESIZE_NONE
,
474 wxColour backgroundColour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
475 // Add scrollbars if required
476 if (orientation
== wxHORIZONTAL
)
478 m_hScrollBar
= DoCreateScrollBar( m_scrolledWindow
, wxHORIZONTAL
,
479 (void (*)())wxScrollBarCallback
);
481 wxDoChangeBackgroundColour(m_hScrollBar
, backgroundColour
, true);
483 XtRealizeWidget( (Widget
)m_hScrollBar
);
485 XtVaSetValues((Widget
) m_scrolledWindow
,
486 XmNhorizontalScrollBar
, (Widget
) m_hScrollBar
,
489 wxAddWindowToTable( (Widget
)m_hScrollBar
, this );
491 else if (orientation
== wxVERTICAL
)
493 m_vScrollBar
= DoCreateScrollBar( m_scrolledWindow
, wxVERTICAL
,
494 (void (*)())wxScrollBarCallback
);
496 wxDoChangeBackgroundColour(m_vScrollBar
, backgroundColour
, true);
498 XtRealizeWidget((Widget
)m_vScrollBar
);
500 XtVaSetValues((Widget
) m_scrolledWindow
,
501 XmNverticalScrollBar
, (Widget
) m_vScrollBar
,
504 wxAddWindowToTable( (Widget
)m_vScrollBar
, this );
507 XtVaSetValues( (Widget
) m_scrolledWindow
,
508 XmNresizePolicy
, XmRESIZE_ANY
,
512 void wxWindow::DestroyScrollbar(wxOrientation orientation
)
514 wxCHECK_RET( m_drawingArea
, "this window can't have scrollbars" );
516 XtVaSetValues((Widget
) m_scrolledWindow
,
517 XmNresizePolicy
, XmRESIZE_NONE
,
519 String stringSB
= orientation
== wxHORIZONTAL
?
520 XmNhorizontalScrollBar
: XmNverticalScrollBar
;
521 WXWidget
* widgetSB
= orientation
== wxHORIZONTAL
?
522 &m_hScrollBar
: &m_vScrollBar
;
526 wxDeleteWindowFromTable( (Widget
)*widgetSB
);
527 XtDestroyWidget( (Widget
)*widgetSB
);
528 *widgetSB
= (WXWidget
)NULL
;
531 XtVaSetValues( (Widget
)m_scrolledWindow
,
532 stringSB
, (Widget
) 0,
535 XtVaSetValues((Widget
) m_scrolledWindow
,
536 XmNresizePolicy
, XmRESIZE_ANY
,
540 // ---------------------------------------------------------------------------
542 // ---------------------------------------------------------------------------
544 void wxWindow::SetFocus()
546 Widget wMain
= (Widget
) GetMainWidget();
547 XmProcessTraversal(wMain
, XmTRAVERSE_CURRENT
);
548 XmProcessTraversal((Widget
) GetMainWidget(), XmTRAVERSE_CURRENT
);
551 // Get the window with the focus
552 wxWindow
*wxWindowBase::DoFindFocus()
555 // (1) Can there be multiple focussed widgets in an application?
556 // In which case we need to find the top-level window that's
558 // (2) The widget with the focus may not be in the widget table
559 // depending on which widgets I put in the table
560 wxWindow
*winFocus
= (wxWindow
*)NULL
;
561 for ( wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetFirst();
563 node
= node
->GetNext() )
565 wxWindow
*win
= node
->GetData();
567 Widget w
= XmGetFocusWidget ((Widget
) win
->GetTopWidget());
569 if (w
!= (Widget
) NULL
)
571 winFocus
= wxGetWindowFromTable(w
);
580 bool wxWindow::Enable(bool enable
)
582 if ( !wxWindowBase::Enable(enable
) )
585 Widget wMain
= (Widget
)GetMainWidget();
588 XtSetSensitive(wMain
, enable
);
589 XmUpdateDisplay(wMain
);
595 bool wxWindow::Show(bool show
)
597 if ( !wxWindowBase::Show(show
) )
600 if (m_borderWidget
|| m_scrolledWindow
)
602 MapOrUnmap(m_borderWidget
? m_borderWidget
: m_scrolledWindow
, show
);
603 // MapOrUnmap(m_drawingArea, show);
607 if ( !MapOrUnmap(GetTopWidget(), show
) )
608 MapOrUnmap(GetMainWidget(), show
);
614 // Raise the window to the top of the Z order
615 void wxWindow::Raise()
617 Widget wTop
= (Widget
) GetTopWidget();
618 Window window
= XtWindow(wTop
);
619 XRaiseWindow(XtDisplay(wTop
), window
);
622 // Lower the window to the bottom of the Z order
623 void wxWindow::Lower()
625 Widget wTop
= (Widget
) GetTopWidget();
626 Window window
= XtWindow(wTop
);
627 XLowerWindow(XtDisplay(wTop
), window
);
630 void wxWindow::SetLabel(const wxString
& label
)
632 XtVaSetValues((Widget
)GetMainWidget(), XmNtitle
,
633 (const char*)label
.mb_str(), NULL
);
636 wxString
wxWindow::GetLabel() const
639 XtVaGetValues((Widget
)GetMainWidget(), XmNtitle
, &label
, NULL
);
641 return wxString(label
);
644 void wxWindow::DoCaptureMouse()
646 g_captureWindow
= this;
650 Widget wMain
= (Widget
)GetMainWidget();
652 XtAddGrab(wMain
, True
, False
);
654 m_winCaptured
= true;
657 void wxWindow::DoReleaseMouse()
659 g_captureWindow
= NULL
;
660 if ( !m_winCaptured
)
663 Widget wMain
= (Widget
)GetMainWidget();
667 m_winCaptured
= false;
670 bool wxWindow::SetFont(const wxFont
& font
)
672 if ( !wxWindowBase::SetFont(font
) )
683 bool wxWindow::SetCursor(const wxCursor
& cursor
)
685 if ( !wxWindowBase::SetCursor(cursor
) )
691 // wxASSERT_MSG( m_cursor.Ok(),
692 // wxT("cursor must be valid after call to the base version"));
693 const wxCursor
* cursor2
= NULL
;
695 cursor2
= & m_cursor
;
697 cursor2
= wxSTANDARD_CURSOR
;
699 WXDisplay
*dpy
= GetXDisplay();
700 WXCursor x_cursor
= cursor2
->GetXCursor(dpy
);
702 Widget w
= (Widget
) GetMainWidget();
703 Window win
= XtWindow(w
);
704 XDefineCursor((Display
*) dpy
, win
, (Cursor
) x_cursor
);
709 // Coordinates relative to the window
710 void wxWindow::WarpPointer (int x
, int y
)
712 Widget wClient
= (Widget
)GetClientWidget();
714 XWarpPointer(XtDisplay(wClient
), None
, XtWindow(wClient
), 0, 0, 0, 0, x
, y
);
717 // ---------------------------------------------------------------------------
719 // ---------------------------------------------------------------------------
721 int wxWindow::GetScrollPos(int orient
) const
723 if (orient
== wxHORIZONTAL
)
729 Widget scrollBar
= (Widget
) ((orient
== wxHORIZONTAL
) ? m_hScrollBar
: m_vScrollBar
);
733 XtVaGetValues(scrollBar
, XmNvalue
, &pos
, NULL
);
741 // This now returns the whole range, not just the number of positions that we
743 int wxWindow::GetScrollRange(int orient
) const
745 Widget scrollBar
= (Widget
)GetScrollbar((wxOrientation
)orient
);
746 // CE scintilla windows don't always have these scrollbars
747 // and it tends to pile up a whole bunch of asserts
748 //wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
752 XtVaGetValues(scrollBar
, XmNmaximum
, &range
, NULL
);
756 int wxWindow::GetScrollThumb(int orient
) const
758 Widget scrollBar
= (Widget
)GetScrollbar((wxOrientation
)orient
);
759 //wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
763 XtVaGetValues(scrollBar
, XmNsliderSize
, &thumb
, NULL
);
767 void wxWindow::SetScrollPos(int orient
, int pos
, bool WXUNUSED(refresh
))
769 Widget scrollBar
= (Widget
)GetScrollbar((wxOrientation
)orient
);
773 XtVaSetValues (scrollBar
, XmNvalue
, pos
, NULL
);
776 SetInternalScrollPos((wxOrientation
)orient
, pos
);
779 // New function that will replace some of the above.
780 void wxWindow::SetScrollbar(int orient
, int pos
, int thumbVisible
,
781 int range
, bool WXUNUSED(refresh
))
784 GetSize(& oldW
, & oldH
);
788 if (thumbVisible
== 0)
791 if (thumbVisible
> range
)
792 thumbVisible
= range
;
794 // Save the old state to see if it changed
795 WXWidget oldScrollBar
= GetScrollbar((wxOrientation
)orient
);
797 if (orient
== wxHORIZONTAL
)
799 if (thumbVisible
== range
)
802 DestroyScrollbar(wxHORIZONTAL
);
807 CreateScrollbar(wxHORIZONTAL
);
810 if (orient
== wxVERTICAL
)
812 if (thumbVisible
== range
)
815 DestroyScrollbar(wxVERTICAL
);
820 CreateScrollbar(wxVERTICAL
);
823 WXWidget newScrollBar
= GetScrollbar((wxOrientation
)orient
);
825 if (oldScrollBar
!= newScrollBar
)
827 // This is important! Without it, scrollbars misbehave badly.
828 XtUnrealizeWidget((Widget
) m_scrolledWindow
);
829 XmScrolledWindowSetAreas ((Widget
) m_scrolledWindow
, (Widget
) m_hScrollBar
, (Widget
) m_vScrollBar
, (Widget
) m_drawingArea
);
830 XtRealizeWidget((Widget
) m_scrolledWindow
);
831 XtManageChild((Widget
) m_scrolledWindow
);
836 XtVaSetValues((Widget
) newScrollBar
,
840 XmNsliderSize
, thumbVisible
,
844 SetInternalScrollPos((wxOrientation
)orient
, pos
);
847 GetSize(& newW
, & newH
);
849 // Adjusting scrollbars can resize the canvas accidentally
850 if (newW
!= oldW
|| newH
!= oldH
)
851 SetSize(wxDefaultCoord
, wxDefaultCoord
, oldW
, oldH
);
854 // Does a physical scroll
855 void wxWindow::ScrollWindow(int dx
, int dy
, const wxRect
*rect
)
860 // Use specified rectangle
861 x
= rect
->x
; y
= rect
->y
; w
= rect
->width
; h
= rect
->height
;
865 // Use whole client area
867 GetClientSize(& w
, & h
);
870 int x1
= (dx
>= 0) ? x
: x
- dx
;
871 int y1
= (dy
>= 0) ? y
: y
- dy
;
872 int w1
= w
- abs(dx
);
873 int h1
= h
- abs(dy
);
874 int x2
= (dx
>= 0) ? x
+ dx
: x
;
875 int y2
= (dy
>= 0) ? y
+ dy
: y
;
878 wxClientDCImpl
* const
879 dcimpl
= static_cast<wxClientDCImpl
*>(dc
.GetImpl());
880 GC
const gc
= (GC
) dcimpl
->GetGC();
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
, x1
, y1
, w1
, h1
, x2
, y2
);
890 dcimpl
->SetAutoSetting(true);
891 wxBrush
brush(GetBackgroundColour(), wxSOLID
);
892 dc
.SetBrush(brush
); // FIXME: needed?
894 wxWindowList::compatibility_iterator cnode
= m_children
.GetFirst();
897 wxWindow
*child
= cnode
->GetData();
900 child
->GetSize( &sx
, &sy
);
901 wxPoint
pos( child
->GetPosition() );
902 child
->SetSize( pos
.x
+ dx
, pos
.y
+ dy
, sx
, sy
, wxSIZE_ALLOW_MINUS_ONE
);
903 cnode
= cnode
->GetNext();
906 // We'll add rectangles to the list of update rectangles according to which
907 // bits we've exposed.
912 wxRect
*rect
= new wxRect
;
918 XFillRectangle(display
, window
, gc
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
922 rect
->width
= rect
->width
;
923 rect
->height
= rect
->height
;
925 updateRects
.Append((wxObject
*) rect
);
929 wxRect
*rect
= new wxRect
;
931 rect
->x
= x
+ w
+ dx
;
936 XFillRectangle(display
, window
, gc
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
940 rect
->width
= rect
->width
;
941 rect
->height
= rect
->height
;
943 updateRects
.Append((wxObject
*) rect
);
947 wxRect
*rect
= new wxRect
;
954 XFillRectangle(display
, window
, gc
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
958 rect
->width
= rect
->width
;
959 rect
->height
= rect
->height
;
961 updateRects
.Append((wxObject
*) rect
);
965 wxRect
*rect
= new wxRect
;
968 rect
->y
= y
+ h
+ dy
;
972 XFillRectangle(display
, window
, gc
, rect
->x
, rect
->y
, rect
->width
, rect
->height
);
976 rect
->width
= rect
->width
;
977 rect
->height
= rect
->height
;
979 updateRects
.Append((wxObject
*) rect
);
981 dc
.SetBrush(wxNullBrush
);
983 // Now send expose events
985 wxList::compatibility_iterator node
= updateRects
.GetFirst();
988 wxRect
* rect
= (wxRect
*) node
->GetData();
992 event
.display
= display
;
993 event
.send_event
= True
;
994 event
.window
= window
;
998 event
.width
= rect
->width
;
999 event
.height
= rect
->height
;
1003 XSendEvent(display
, window
, False
, ExposureMask
, (XEvent
*)&event
);
1005 node
= node
->GetNext();
1009 // Delete the update rects
1010 node
= updateRects
.GetFirst();
1013 wxRect
* rect
= (wxRect
*) node
->GetData();
1015 node
= node
->GetNext();
1018 XmUpdateDisplay((Widget
) GetMainWidget());
1021 // ---------------------------------------------------------------------------
1023 // ---------------------------------------------------------------------------
1025 #if wxUSE_DRAG_AND_DROP
1027 void wxWindow::SetDropTarget(wxDropTarget
* WXUNUSED(pDropTarget
))
1034 // Old style file-manager drag&drop
1035 void wxWindow::DragAcceptFiles(bool WXUNUSED(accept
))
1040 // ----------------------------------------------------------------------------
1042 // ----------------------------------------------------------------------------
1046 void wxWindow::DoSetToolTip(wxToolTip
* WXUNUSED(tooltip
))
1051 #endif // wxUSE_TOOLTIPS
1053 // ----------------------------------------------------------------------------
1055 // ----------------------------------------------------------------------------
1059 bool wxWindow::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1061 if ( x
== wxDefaultCoord
&& y
== wxDefaultCoord
)
1063 wxPoint mouse
= ScreenToClient(wxGetMousePosition());
1064 x
= mouse
.x
; y
= mouse
.y
;
1067 Widget widget
= (Widget
) GetMainWidget();
1069 /* The menuId field seems to be usused, so we'll use it to
1070 indicate whether a menu is popped up or not:
1071 0: Not currently created as a popup
1072 -1: Created as a popup, but not active
1076 if (menu
->GetParent() && (menu
->GetId() != -1))
1079 if (menu
->GetMainWidget())
1081 menu
->DestroyMenu(true);
1084 menu
->SetId(1); /* Mark as popped-up */
1085 menu
->CreateMenu(NULL
, widget
, menu
, 0);
1086 menu
->SetInvokingWindow(this);
1090 // menu->SetParent(parent);
1091 // parent->children->Append(menu); // Store menu for later deletion
1093 Widget menuWidget
= (Widget
) menu
->GetMainWidget();
1101 if (this->IsKindOf(CLASSINFO(wxCanvas)))
1103 wxCanvas *canvas = (wxCanvas *) this;
1104 deviceX = canvas->GetDC ()->LogicalToDeviceX (x);
1105 deviceY = canvas->GetDC ()->LogicalToDeviceY (y);
1109 Display
*display
= XtDisplay (widget
);
1110 Window rootWindow
= RootWindowOfScreen (XtScreen((Widget
)widget
));
1111 Window thisWindow
= XtWindow (widget
);
1113 XTranslateCoordinates (display
, thisWindow
, rootWindow
, (int) deviceX
, (int) deviceY
,
1114 &rootX
, &rootY
, &childWindow
);
1116 XButtonPressedEvent event
;
1117 event
.type
= ButtonPress
;
1123 event
.x_root
= rootX
;
1124 event
.y_root
= rootY
;
1126 XmMenuPosition (menuWidget
, &event
);
1127 XtManageChild (menuWidget
);
1129 // The ID of a pop-up menu is 1 when active, and is set to 0 by the
1130 // idle-time destroy routine.
1131 // Waiting until this ID changes causes this function to block until
1132 // the menu has been dismissed and the widgets cleaned up.
1133 // In other words, once this routine returns, it is safe to delete
1135 // Ian Brown <ian.brown@printsoft.de>
1137 wxEventLoop evtLoop
;
1139 while (menu
->GetId() == 1)
1141 wxDoEventLoopIteration( evtLoop
);
1149 // ---------------------------------------------------------------------------
1150 // moving and resizing
1151 // ---------------------------------------------------------------------------
1153 bool wxWindow::PreResize()
1159 void wxWindow::DoGetSize(int *x
, int *y
) const
1161 Widget widget
= (Widget
)( !m_drawingArea
? GetTopWidget() :
1162 ( m_borderWidget
? m_borderWidget
:
1163 m_scrolledWindow
? m_scrolledWindow
:
1168 XtVaGetValues( widget
,
1172 if(x
) *x
= widget
? xx
: -1;
1173 if(y
) *y
= widget
? yy
: -1;
1176 void wxWindow::DoGetPosition(int *x
, int *y
) const
1178 Widget widget
= (Widget
)
1180 ( m_borderWidget
? m_borderWidget
: m_scrolledWindow
) :
1184 XtVaGetValues(widget
, XmNx
, &xx
, XmNy
, &yy
, NULL
);
1186 // We may be faking the client origin. So a window that's really at (0, 30)
1187 // may appear (to wxWin apps) to be at (0, 0).
1190 wxPoint
pt(GetParent()->GetClientAreaOrigin());
1191 xx
= (Position
)(xx
- pt
.x
);
1192 yy
= (Position
)(yy
- pt
.y
);
1199 void wxWindow::DoScreenToClient(int *x
, int *y
) const
1201 Widget widget
= (Widget
) GetClientWidget();
1202 Display
*display
= XtDisplay((Widget
) GetMainWidget());
1203 Window rootWindow
= RootWindowOfScreen(XtScreen(widget
));
1204 Window thisWindow
= XtWindow(widget
);
1207 int xx
= x
? *x
: 0;
1208 int yy
= y
? *y
: 0;
1209 XTranslateCoordinates(display
, rootWindow
, thisWindow
,
1210 xx
, yy
, x
? x
: &xx
, y
? y
: &yy
,
1214 void wxWindow::DoClientToScreen(int *x
, int *y
) const
1216 Widget widget
= (Widget
) GetClientWidget();
1217 Display
*display
= XtDisplay(widget
);
1218 Window rootWindow
= RootWindowOfScreen(XtScreen(widget
));
1219 Window thisWindow
= XtWindow(widget
);
1222 int xx
= x
? *x
: 0;
1223 int yy
= y
? *y
: 0;
1224 XTranslateCoordinates(display
, thisWindow
, rootWindow
,
1225 xx
, yy
, x
? x
: &xx
, y
? y
: &yy
,
1230 // Get size *available for subwindows* i.e. excluding menu bar etc.
1231 void wxWindow::DoGetClientSize(int *x
, int *y
) const
1233 Widget widget
= (Widget
) GetClientWidget();
1235 XtVaGetValues(widget
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
1236 if(x
) *x
= xx
; if(y
) *y
= yy
;
1239 void wxWindow::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1241 DoSetSizeIntr(x
, y
, width
, height
, sizeFlags
, false);
1244 void wxWindow::DoSetSizeIntr(int x
, int y
, int width
, int height
,
1245 int sizeFlags
, bool fromCtor
)
1247 // A bit of optimization to help sort out the flickers.
1248 int oldX
= -1, oldY
= -1, oldW
= -1, oldH
= -1;
1252 GetSize(& oldW
, & oldH
);
1253 GetPosition(& oldX
, & oldY
);
1261 if ( !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1269 wxSize
size(wxDefaultSize
);
1272 if ( ( sizeFlags
& wxSIZE_AUTO_WIDTH
) && !fromCtor
)
1274 size
= DoGetBestSize();
1285 if( ( sizeFlags
& wxSIZE_AUTO_HEIGHT
) && !fromCtor
)
1287 if( size
.x
== -1 ) size
= DoGetBestSize();
1296 if ( x
!= oldX
|| y
!= oldY
|| width
!= oldW
|| height
!= oldH
1297 || !wxNoOptimize::CanOptimize() )
1310 flags
|= wxMOVE_WIDTH
;
1313 flags
|= wxMOVE_HEIGHT
;
1315 int xx
= x
; int yy
= y
;
1316 AdjustForParentClientOrigin(xx
, yy
, sizeFlags
);
1318 DoMoveWindow( xx
, yy
, width
, height
);
1320 DoMoveWindowIntr( xx
, yy
, width
, height
, flags
);
1325 Widget widget
= (Widget
) GetTopWidget();
1329 bool managed
= XtIsManaged( widget
);
1331 XtUnmanageChild(widget
);
1335 AdjustForParentClientOrigin(xx
, yy
, sizeFlags
);
1337 DoMoveWindow(xx
, yy
, width
, height
);
1340 XtManageChild(widget
);
1344 void wxWindow::DoSetClientSize(int width
, int height
)
1348 Widget drawingArea
= (Widget
) m_drawingArea
;
1350 XtVaSetValues(drawingArea
, XmNresizePolicy
, XmRESIZE_ANY
, NULL
);
1353 XtVaSetValues(drawingArea
, XmNwidth
, width
, NULL
);
1355 XtVaSetValues(drawingArea
, XmNheight
, height
, NULL
);
1357 XtVaSetValues(drawingArea
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
);
1361 Widget widget
= (Widget
) GetTopWidget();
1364 XtVaSetValues(widget
, XmNwidth
, width
, NULL
);
1366 XtVaSetValues(widget
, XmNheight
, height
, NULL
);
1369 void wxWindow::DoMoveWindowIntr(int xx
, int yy
, int w
, int h
,
1374 Widget drawingArea
= (Widget
) m_drawingArea
;
1375 Widget borderOrScrolled
= m_borderWidget
?
1376 (Widget
) m_borderWidget
:
1377 (Widget
) m_scrolledWindow
;
1379 bool managed
= XtIsManaged(borderOrScrolled
);
1381 XtUnmanageChild (borderOrScrolled
);
1382 XtVaSetValues(drawingArea
, XmNresizePolicy
, XmRESIZE_ANY
, NULL
);
1384 if (flags
& wxMOVE_X
)
1385 XtVaSetValues (borderOrScrolled
,
1388 if (flags
& wxMOVE_Y
)
1389 XtVaSetValues (borderOrScrolled
,
1393 if (flags
& wxMOVE_WIDTH
)
1397 XtVaSetValues ((Widget
) m_borderWidget
, XmNwidth
, w
, NULL
);
1398 short thick
, margin
;
1399 XtVaGetValues ((Widget
) m_borderWidget
,
1400 XmNshadowThickness
, &thick
,
1401 XmNmarginWidth
, &margin
,
1403 w
-= 2 * (thick
+ margin
);
1407 XtVaSetValues ((Widget
) m_scrolledWindow
, XmNwidth
, w
, NULL
);
1410 if (flags
& wxMOVE_HEIGHT
)
1414 XtVaSetValues ((Widget
) m_borderWidget
, XmNheight
, h
, NULL
);
1415 short thick
, margin
;
1416 XtVaGetValues ((Widget
) m_borderWidget
,
1417 XmNshadowThickness
, &thick
,
1418 XmNmarginHeight
, &margin
,
1420 h
-= 2 * (thick
+ margin
);
1424 XtVaSetValues ((Widget
) m_scrolledWindow
, XmNheight
, h
, NULL
);
1428 XtManageChild (borderOrScrolled
);
1429 XtVaSetValues(drawingArea
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
);
1436 XtVaSetValues((Widget
)GetTopWidget(),
1445 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
1447 DoMoveWindowIntr (x
, y
, width
, height
,
1448 wxMOVE_X
|wxMOVE_Y
|wxMOVE_WIDTH
|wxMOVE_HEIGHT
);
1451 // ---------------------------------------------------------------------------
1453 // ---------------------------------------------------------------------------
1455 int wxWindow::GetCharHeight() const
1460 wxGetTextExtent (GetXDisplay(), m_font
, 1.0,
1461 "x", NULL
, &height
, NULL
, NULL
);
1463 wxGetTextExtent (this, "x", NULL
, &height
, NULL
, NULL
);
1468 int wxWindow::GetCharWidth() const
1473 wxGetTextExtent (GetXDisplay(), m_font
, 1.0,
1474 "x", &width
, NULL
, NULL
, NULL
);
1476 wxGetTextExtent (this, "x", &width
, NULL
, NULL
, NULL
);
1481 void wxWindow::GetTextExtent(const wxString
& string
,
1483 int *descent
, int *externalLeading
,
1484 const wxFont
*theFont
) const
1486 const wxFont
*fontToUse
= theFont
? theFont
: &m_font
;
1488 if (externalLeading
)
1489 *externalLeading
= 0;
1490 if (fontToUse
->Ok())
1491 wxGetTextExtent (GetXDisplay(), *fontToUse
, 1.0,
1492 string
, x
, y
, NULL
, descent
);
1494 wxGetTextExtent (this, string
, x
, y
, NULL
, descent
);
1497 // ----------------------------------------------------------------------------
1499 // ----------------------------------------------------------------------------
1501 void wxWindow::AddUpdateRect(int x
, int y
, int w
, int h
)
1503 m_updateRegion
.Union( x
, y
, w
, h
);
1506 void wxWindow::Refresh(bool eraseBack
, const wxRect
*rect
)
1508 Widget widget
= (Widget
) GetMainWidget();
1511 m_needsRefresh
= true;
1512 Display
*display
= XtDisplay(widget
);
1513 Window thisWindow
= XtWindow(widget
);
1515 XExposeEvent dummyEvent
;
1517 GetSize(&width
, &height
);
1519 dummyEvent
.type
= Expose
;
1520 dummyEvent
.display
= display
;
1521 dummyEvent
.send_event
= True
;
1522 dummyEvent
.window
= thisWindow
;
1525 dummyEvent
.x
= rect
->x
;
1526 dummyEvent
.y
= rect
->y
;
1527 dummyEvent
.width
= rect
->width
;
1528 dummyEvent
.height
= rect
->height
;
1534 dummyEvent
.width
= width
;
1535 dummyEvent
.height
= height
;
1537 dummyEvent
.count
= 0;
1541 wxClientDC
dc(this);
1542 wxBrush
backgroundBrush(GetBackgroundColour(), wxSOLID
);
1543 dc
.SetBackground(backgroundBrush
);
1545 wxClientDCImpl
* const
1546 dcimpl
= static_cast<wxClientDCImpl
*>(dc
.GetImpl());
1548 dcimpl
->Clear(*rect
);
1553 XSendEvent(display
, thisWindow
, False
, ExposureMask
, (XEvent
*)&dummyEvent
);
1556 void wxWindow::DoPaint()
1558 //TODO : make a temporary gc so we can do the XCopyArea below
1559 if (m_backingPixmap
&& !m_needsRefresh
)
1563 wxPaintDCImpl
* const
1564 dcimpl
= static_cast<wxPaintDCImpl
*>(dc
.GetImpl());
1566 GC tempGC
= (GC
) dcimpl
->GetBackingGC();
1568 Widget widget
= (Widget
) GetMainWidget();
1573 // We have to test whether it's a wxScrolledWindow (hack!) because
1574 // otherwise we don't know how many pixels have been scrolled. We might
1575 // solve this in the future by defining virtual wxWindow functions to get
1576 // the scroll position in pixels. Or, each kind of scrolled window has to
1577 // implement backing stores itself, using generic wxWidgets code.
1578 wxScrolledWindow
* scrolledWindow
= wxDynamicCast(this, wxScrolledWindow
);
1579 if ( scrolledWindow
)
1582 scrolledWindow
->CalcScrolledPosition(0, 0, &x
, &y
);
1588 // TODO: This could be optimized further by only copying the areas in the
1589 // current update region.
1591 // Only blit the part visible in the client area. The backing pixmap
1592 // always starts at 0, 0 but we may be looking at only a portion of it.
1593 wxSize clientArea
= GetClientSize();
1594 int toBlitX
= m_pixmapWidth
- scrollPosX
;
1595 int toBlitY
= m_pixmapHeight
- scrollPosY
;
1597 // Copy whichever is samller, the amount of pixmap we have to copy,
1598 // or the size of the client area.
1599 toBlitX
= wxMin(toBlitX
, clientArea
.x
);
1600 toBlitY
= wxMin(toBlitY
, clientArea
.y
);
1602 // Make sure we're not negative
1603 toBlitX
= wxMax(0, toBlitX
);
1604 toBlitY
= wxMax(0, toBlitY
);
1609 (Pixmap
) m_backingPixmap
,
1612 scrollPosX
, scrollPosY
, // Start at the scroll position
1613 toBlitX
, toBlitY
, // How much of the pixmap to copy
1619 wxWindowDC
dc(this);
1620 // Set an erase event first
1621 wxEraseEvent
eraseEvent(GetId(), &dc
);
1622 eraseEvent
.SetEventObject(this);
1623 HandleWindowEvent(eraseEvent
);
1625 wxPaintEvent
event(GetId());
1626 event
.SetEventObject(this);
1627 HandleWindowEvent(event
);
1629 m_needsRefresh
= false;
1633 // ----------------------------------------------------------------------------
1635 // ----------------------------------------------------------------------------
1637 // Responds to colour changes: passes event on to children.
1638 void wxWindow::OnSysColourChanged(wxSysColourChangedEvent
& event
)
1640 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
1643 // Only propagate to non-top-level windows
1644 wxWindow
*win
= node
->GetData();
1645 if ( win
->GetParent() )
1647 wxSysColourChangedEvent event2
;
1648 event
.SetEventObject(win
);
1649 win
->HandleWindowEvent(event2
);
1652 node
= node
->GetNext();
1656 void wxWindow::OnInternalIdle()
1658 // This calls the UI-update mechanism (querying windows for
1659 // menu/toolbar/control state information)
1660 if (wxUpdateUIEvent::CanUpdate(this) && IsShown())
1661 UpdateWindowUI(wxUPDATE_UI_FROMIDLE
);
1664 // ----------------------------------------------------------------------------
1666 // ----------------------------------------------------------------------------
1668 bool wxWindow::ProcessAccelerator(wxKeyEvent
& event
)
1671 if (!m_acceleratorTable
.Ok())
1674 int count
= m_acceleratorTable
.GetCount();
1675 wxAcceleratorEntry
* entries
= m_acceleratorTable
.GetEntries();
1677 for (i
= 0; i
< count
; i
++)
1679 wxAcceleratorEntry
* entry
= & (entries
[i
]);
1680 if (entry
->MatchesEvent(event
))
1682 // Bingo, we have a match. Now find a control that matches the
1683 // entry command id.
1685 // Need to go up to the top of the window hierarchy, since it might
1686 // be e.g. a menu item
1687 wxWindow
* parent
= this;
1688 while ( parent
&& !parent
->IsTopLevel() )
1689 parent
= parent
->GetParent();
1694 wxFrame
* frame
= wxDynamicCast(parent
, wxFrame
);
1698 // Try for a menu command
1699 if (frame
->GetMenuBar())
1701 wxMenuItem
* item
= frame
->GetMenuBar()->FindItem(entry
->GetCommand());
1704 wxCommandEvent
commandEvent(wxEVT_COMMAND_MENU_SELECTED
, entry
->GetCommand());
1705 commandEvent
.SetEventObject(frame
);
1707 // If ProcessEvent returns true (it was handled), then
1708 // the calling code will skip the event handling.
1709 return frame
->HandleWindowEvent(commandEvent
);
1715 // Find a child matching the command id
1716 wxWindow
* child
= parent
->FindWindow(entry
->GetCommand());
1722 // Now we process those kinds of windows that we can.
1723 // For now, only buttons.
1724 if ( wxDynamicCast(child
, wxButton
) )
1726 wxCommandEvent
commandEvent (wxEVT_COMMAND_BUTTON_CLICKED
, child
->GetId());
1727 commandEvent
.SetEventObject(child
);
1728 return child
->HandleWindowEvent(commandEvent
);
1736 // We didn't match the key event against an accelerator.
1740 // ============================================================================
1741 // Motif-specific stuff from here on
1742 // ============================================================================
1744 // ----------------------------------------------------------------------------
1745 // function which maintain the global hash table mapping Widgets to wxWidgets
1746 // ----------------------------------------------------------------------------
1748 bool wxAddWindowToTable(Widget w
, wxWindow
*win
)
1750 const long key
= (long)w
;
1751 if ( wxWidgetHashTable
->Get(key
))
1753 wxLogDebug("Widget table clash: new widget is %ld, %s",
1754 key
, win
->GetClassInfo()->GetClassName());
1758 wxWidgetHashTable
->Put(key
, win
);
1760 wxLogTrace("widget", "Widget 0x%p <-> window %p (%s)",
1761 w
, win
, win
->GetClassInfo()->GetClassName());
1766 wxWindow
*wxGetWindowFromTable(Widget w
)
1768 return (wxWindow
*)wxWidgetHashTable
->Get((long) w
);
1771 void wxDeleteWindowFromTable(Widget w
)
1773 wxLogTrace("widget", "Widget 0x%p", (WXWidget
)w
);
1775 wxWidgetHashTable
->Delete((long)w
);
1778 // ----------------------------------------------------------------------------
1779 // add/remove window from the table
1780 // ----------------------------------------------------------------------------
1782 // Add to hash table, add event handler
1783 bool wxWindow::AttachWidget (wxWindow
* WXUNUSED(parent
), WXWidget mainWidget
,
1784 WXWidget formWidget
, int x
, int y
, int width
, int height
)
1786 wxAddWindowToTable((Widget
) mainWidget
, this);
1787 XtAddEventHandler( (Widget
) mainWidget
,
1788 ButtonPressMask
| ButtonReleaseMask
1789 | PointerMotionMask
,
1791 wxPanelItemEventHandler
,
1797 XtOverrideTranslations ((Widget
) mainWidget
,
1798 ptr
= XtParseTranslationTable ("<Configure>: resize()"));
1799 XtFree ((char *) ptr
);
1802 // Some widgets have a parent form widget, e.g. wxRadioBox
1805 if (!wxAddWindowToTable((Widget
) formWidget
, this))
1809 XtOverrideTranslations ((Widget
) formWidget
,
1810 ptr
= XtParseTranslationTable ("<Configure>: resize()"));
1811 XtFree ((char *) ptr
);
1818 DoSetSize (x
, y
, width
, height
, wxSIZE_USE_EXISTING
);
1823 // Remove event handler, remove from hash table
1824 bool wxWindow::DetachWidget(WXWidget widget
)
1826 XtRemoveEventHandler( (Widget
) widget
,
1827 ButtonPressMask
| ButtonReleaseMask
1828 | PointerMotionMask
,
1830 wxPanelItemEventHandler
,
1833 wxDeleteWindowFromTable((Widget
) widget
);
1837 // ----------------------------------------------------------------------------
1838 // Motif-specific accessors
1839 // ----------------------------------------------------------------------------
1841 WXWindow
wxWindow::GetClientXWindow() const
1843 Widget wMain
= (Widget
)GetClientWidget();
1845 return (WXWindow
) XtWindow(wMain
);
1847 return (WXWindow
) 0;
1850 // Get the underlying X window
1851 WXWindow
wxWindow::GetXWindow() const
1853 Widget wMain
= (Widget
)GetMainWidget();
1855 return (WXWindow
) XtWindow(wMain
);
1857 return (WXWindow
) 0;
1860 // Get the underlying X display
1861 WXDisplay
*wxWindow::GetXDisplay() const
1863 Widget wMain
= (Widget
)GetMainWidget();
1865 return (WXDisplay
*) XtDisplay(wMain
);
1867 return (WXDisplay
*) NULL
;
1870 WXWidget
wxWindow::GetMainWidget() const
1873 return m_drawingArea
;
1875 return m_mainWidget
;
1878 WXWidget
wxWindow::GetClientWidget() const
1880 if (m_drawingArea
!= (WXWidget
) 0)
1881 return m_drawingArea
;
1883 return GetMainWidget();
1886 WXWidget
wxWindow::GetTopWidget() const
1888 return GetMainWidget();
1891 WXWidget
wxWindow::GetLabelWidget() const
1893 return GetMainWidget();
1896 // ----------------------------------------------------------------------------
1898 // ----------------------------------------------------------------------------
1900 // All widgets should have this as their resize proc.
1901 // OnSize sent to wxWindow via client data.
1902 void wxWidgetResizeProc(Widget w
, XConfigureEvent
*WXUNUSED(event
),
1903 String
WXUNUSED(args
)[], int *WXUNUSED(num_args
))
1905 wxWindow
*win
= wxGetWindowFromTable(w
);
1909 if (win
->PreResize())
1911 wxSize
newSize(win
->GetSize());
1912 wxSizeEvent
sizeEvent(newSize
, win
->GetId());
1913 sizeEvent
.SetEventObject(win
);
1914 win
->HandleWindowEvent(sizeEvent
);
1918 static void wxCanvasRepaintProc(Widget drawingArea
,
1919 XtPointer clientData
,
1920 XmDrawingAreaCallbackStruct
* cbs
)
1922 if (!wxGetWindowFromTable(drawingArea
))
1925 XEvent
* event
= cbs
->event
;
1926 wxWindow
* win
= (wxWindow
*) clientData
;
1928 switch (event
->type
)
1932 win
->AddUpdateRect(event
->xexpose
.x
, event
->xexpose
.y
,
1933 event
->xexpose
.width
, event
->xexpose
.height
);
1935 if (event
-> xexpose
.count
== 0)
1944 // Unable to deal with Enter/Leave without a separate EventHandler (Motif 1.1.4)
1945 static void wxCanvasEnterLeave(Widget drawingArea
,
1946 XtPointer
WXUNUSED(clientData
),
1947 XCrossingEvent
* event
)
1949 XmDrawingAreaCallbackStruct cbs
;
1952 ((XCrossingEvent
&) ev
) = *event
;
1954 cbs
.reason
= XmCR_INPUT
;
1957 wxCanvasInputEvent(drawingArea
, (XtPointer
) NULL
, &cbs
);
1960 // Fix to make it work under Motif 1.0 (!)
1961 static void wxCanvasMotionEvent (Widget
WXUNUSED(drawingArea
),
1962 XButtonEvent
*WXUNUSED(event
))
1964 #if XmVersion <= 1000
1965 XmDrawingAreaCallbackStruct cbs
;
1968 ev
= *((XEvent
*) event
);
1969 cbs
.reason
= XmCR_INPUT
;
1972 wxCanvasInputEvent (drawingArea
, (XtPointer
) NULL
, &cbs
);
1973 #endif // XmVersion <= 1000
1976 static void wxCanvasInputEvent(Widget drawingArea
,
1977 XtPointer
WXUNUSED(data
),
1978 XmDrawingAreaCallbackStruct
* cbs
)
1980 wxWindow
*canvas
= wxGetWindowFromTable(drawingArea
);
1981 XEvent
* xevent
= cbs
->event
;
1986 if (cbs
->reason
!= XmCR_INPUT
)
1989 switch (xevent
->xany
.type
)
1997 wxMouseEvent
wxevent(0);
1998 if (wxTranslateMouseEvent(wxevent
, canvas
, drawingArea
, xevent
))
2000 canvas
->HandleWindowEvent(wxevent
);
2006 wxKeyEvent
event (wxEVT_CHAR
);
2007 if (wxTranslateKeyEvent (event
, canvas
, (Widget
) 0, xevent
))
2009 // Implement wxFrame::OnCharHook by checking ancestor.
2010 wxWindow
*parent
= canvas
;
2011 while (parent
&& !parent
->IsTopLevel())
2012 parent
= parent
->GetParent();
2016 event
.SetEventType(wxEVT_CHAR_HOOK
);
2017 if (parent
->HandleWindowEvent(event
))
2021 // For simplicity, OnKeyDown is the same as OnChar
2022 // TODO: filter modifier key presses from OnChar
2023 event
.SetEventType(wxEVT_KEY_DOWN
);
2025 // Only process OnChar if OnKeyDown didn't swallow it
2026 if (!canvas
->HandleWindowEvent (event
))
2028 event
.SetEventType(wxEVT_CHAR
);
2029 canvas
->HandleWindowEvent (event
);
2036 wxKeyEvent
event (wxEVT_KEY_UP
);
2037 if (wxTranslateKeyEvent (event
, canvas
, (Widget
) 0, xevent
))
2039 canvas
->HandleWindowEvent (event
);
2045 if (xevent
->xfocus
.detail
!= NotifyPointer
)
2047 wxFocusEvent
event(wxEVT_SET_FOCUS
, canvas
->GetId());
2048 event
.SetEventObject(canvas
);
2049 canvas
->HandleWindowEvent(event
);
2055 if (xevent
->xfocus
.detail
!= NotifyPointer
)
2057 wxFocusEvent
event(wxEVT_KILL_FOCUS
, canvas
->GetId());
2058 event
.SetEventObject(canvas
);
2059 canvas
->HandleWindowEvent(event
);
2068 static void wxPanelItemEventHandler(Widget wid
,
2069 XtPointer
WXUNUSED(client_data
),
2071 Boolean
*continueToDispatch
)
2073 // Widget can be a label or the actual widget.
2075 wxWindow
*window
= wxGetWindowFromTable(wid
);
2078 wxMouseEvent
wxevent(0);
2079 if (wxTranslateMouseEvent(wxevent
, window
, wid
, event
))
2081 window
->HandleWindowEvent(wxevent
);
2085 // TODO: probably the key to allowing default behaviour to happen. Say we
2086 // set a m_doDefault flag to false at the start of this function. Then in
2087 // e.g. wxWindow::OnMouseEvent we can call Default() which sets this flag to
2088 // true, indicating that default processing can happen. Thus, behaviour can
2089 // appear to be overridden just by adding an event handler and not calling
2090 // wxWindow::OnWhatever. ALSO, maybe we can use this instead of the current
2091 // way of handling drawing area events, to simplify things.
2092 *continueToDispatch
= True
;
2095 static void wxScrollBarCallback(Widget scrollbar
,
2096 XtPointer clientData
,
2097 XmScrollBarCallbackStruct
*cbs
)
2099 wxWindow
*win
= wxGetWindowFromTable(scrollbar
);
2100 wxCHECK_RET( win
, _T("invalid widget in scrollbar callback") );
2102 wxOrientation orientation
= (wxOrientation
)wxPtrToUInt(clientData
);
2104 wxEventType eventType
= wxEVT_NULL
;
2105 switch (cbs
->reason
)
2107 case XmCR_INCREMENT
:
2109 eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
2112 case XmCR_DECREMENT
:
2114 eventType
= wxEVT_SCROLLWIN_LINEUP
;
2119 eventType
= wxEVT_SCROLLWIN_THUMBTRACK
;
2122 case XmCR_VALUE_CHANGED
:
2124 eventType
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2127 case XmCR_PAGE_INCREMENT
:
2129 eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
2132 case XmCR_PAGE_DECREMENT
:
2134 eventType
= wxEVT_SCROLLWIN_PAGEUP
;
2139 eventType
= wxEVT_SCROLLWIN_TOP
;
2142 case XmCR_TO_BOTTOM
:
2144 eventType
= wxEVT_SCROLLWIN_BOTTOM
;
2149 // Should never get here
2150 wxFAIL_MSG("Unknown scroll event.");
2155 wxScrollWinEvent
event(eventType
,
2158 event
.SetEventObject( win
);
2159 win
->HandleWindowEvent(event
);
2162 // For repainting arbitrary windows
2163 void wxUniversalRepaintProc(Widget w
, XtPointer
WXUNUSED(c_data
), XEvent
*event
, char *)
2165 wxWindow
* win
= wxGetWindowFromTable(w
);
2169 switch ( event
->type
)
2173 win
->AddUpdateRect(event
->xexpose
.x
, event
->xexpose
.y
,
2174 event
->xexpose
.width
, event
->xexpose
.height
);
2176 if ( event
->xexpose
.count
== 0 )
2186 // ----------------------------------------------------------------------------
2187 // TranslateXXXEvent() functions
2188 // ----------------------------------------------------------------------------
2190 bool wxTranslateMouseEvent(wxMouseEvent
& wxevent
, wxWindow
*win
,
2191 Widget widget
, const XEvent
*xevent
)
2193 switch (xevent
->xany
.type
)
2198 fprintf(stderr
, "Widget 0x%p <-> window %p (%s), %s\n",
2199 (WXWidget
)widget
, win
, win
->GetClassInfo()->GetClassName(),
2200 (xevent
->xany
.type
== EnterNotify
? "ENTER" : "LEAVE"));
2206 int eventx
= xevent
->xbutton
.x
, eventy
= xevent
->xbutton
.y
;
2208 wxEventType eventType
= wxEVT_NULL
;
2210 if (xevent
->xany
.type
== LeaveNotify
)
2212 eventType
= wxEVT_LEAVE_WINDOW
;
2214 if (xevent
->xany
.type
== EnterNotify
)
2216 eventType
= wxEVT_ENTER_WINDOW
;
2218 else if (xevent
->xany
.type
== MotionNotify
)
2220 eventType
= wxEVT_MOTION
;
2222 if (xevent
->xmotion
.is_hint
== NotifyHint
)
2227 Display
*dpy
= XtDisplay (widget
);
2229 XQueryPointer (dpy
, XtWindow (widget
),
2231 &x_root
, &y_root
, &eventx
, &eventy
, &state
);
2234 else if (xevent
->xany
.type
== ButtonPress
)
2236 wxevent
.SetTimestamp(xevent
->xbutton
.time
);
2238 if (xevent
->xbutton
.button
== Button1
)
2240 eventType
= wxEVT_LEFT_DOWN
;
2243 else if (xevent
->xbutton
.button
== Button2
)
2245 eventType
= wxEVT_MIDDLE_DOWN
;
2248 else if (xevent
->xbutton
.button
== Button3
)
2250 eventType
= wxEVT_RIGHT_DOWN
;
2254 // check for a double click
2256 long dclickTime
= XtGetMultiClickTime(xevent
->xany
.display
);
2257 long ts
= wxevent
.GetTimestamp();
2259 int buttonLast
= win
->GetLastClickedButton();
2260 long lastTS
= win
->GetLastClickTime();
2261 if ( buttonLast
&& buttonLast
== button
&&
2262 (ts
- lastTS
) < dclickTime
)
2265 win
->SetLastClick(0, ts
);
2266 if ( eventType
== wxEVT_LEFT_DOWN
)
2267 eventType
= wxEVT_LEFT_DCLICK
;
2268 else if ( eventType
== wxEVT_MIDDLE_DOWN
)
2269 eventType
= wxEVT_MIDDLE_DCLICK
;
2270 else if ( eventType
== wxEVT_RIGHT_DOWN
)
2271 eventType
= wxEVT_RIGHT_DCLICK
;
2275 // not fast enough or different button
2276 win
->SetLastClick(button
, ts
);
2279 else if (xevent
->xany
.type
== ButtonRelease
)
2281 if (xevent
->xbutton
.button
== Button1
)
2283 eventType
= wxEVT_LEFT_UP
;
2285 else if (xevent
->xbutton
.button
== Button2
)
2287 eventType
= wxEVT_MIDDLE_UP
;
2289 else if (xevent
->xbutton
.button
== Button3
)
2291 eventType
= wxEVT_RIGHT_UP
;
2301 wxevent
.SetEventType(eventType
);
2304 XtVaGetValues(widget
, XmNx
, &x1
, XmNy
, &y1
, NULL
);
2307 win
->GetPosition(&x2
, &y2
);
2309 // The button x/y must be translated to wxWidgets
2310 // window space - the widget might be a label or button,
2314 if (widget
!= (Widget
)win
->GetMainWidget())
2320 wxevent
.m_x
= eventx
+ dx
;
2321 wxevent
.m_y
= eventy
+ dy
;
2323 wxevent
.m_leftDown
= ((eventType
== wxEVT_LEFT_DOWN
)
2324 || (event_left_is_down (xevent
)
2325 && (eventType
!= wxEVT_LEFT_UP
)));
2326 wxevent
.m_middleDown
= ((eventType
== wxEVT_MIDDLE_DOWN
)
2327 || (event_middle_is_down (xevent
)
2328 && (eventType
!= wxEVT_MIDDLE_UP
)));
2329 wxevent
.m_rightDown
= ((eventType
== wxEVT_RIGHT_DOWN
)
2330 || (event_right_is_down (xevent
)
2331 && (eventType
!= wxEVT_RIGHT_UP
)));
2333 wxevent
.m_shiftDown
= (xevent
->xbutton
.state
& ShiftMask
) == ShiftMask
;
2334 wxevent
.m_controlDown
= (xevent
->xbutton
.state
& ControlMask
) == ControlMask
;
2335 wxevent
.m_altDown
= (xevent
->xbutton
.state
& Mod3Mask
) == Mod3Mask
;
2336 wxevent
.m_metaDown
= (xevent
->xbutton
.state
& Mod1Mask
) == Mod1Mask
;
2338 wxevent
.SetId(win
->GetId());
2339 wxevent
.SetEventObject(win
);
2347 bool wxTranslateKeyEvent(wxKeyEvent
& wxevent
, wxWindow
*win
,
2348 Widget
WXUNUSED(widget
), const XEvent
*xevent
)
2350 switch (xevent
->xany
.type
)
2358 (void) XLookupString((XKeyEvent
*)xevent
, buf
, 20, &keySym
, NULL
);
2359 int id
= wxCharCodeXToWX (keySym
);
2360 // id may be WXK_xxx code - these are outside ASCII range, so we
2361 // can't just use toupper() on id
2362 if (id
>= 'a' && id
<= 'z')
2365 if (xevent
->xkey
.state
& ShiftMask
)
2366 wxevent
.m_shiftDown
= true;
2367 if (xevent
->xkey
.state
& ControlMask
)
2368 wxevent
.m_controlDown
= true;
2369 if (xevent
->xkey
.state
& Mod3Mask
)
2370 wxevent
.m_altDown
= true;
2371 if (xevent
->xkey
.state
& Mod1Mask
)
2372 wxevent
.m_metaDown
= true;
2373 wxevent
.SetEventObject(win
);
2374 wxevent
.m_keyCode
= id
;
2375 wxevent
.SetTimestamp(xevent
->xkey
.time
);
2377 wxevent
.m_x
= xevent
->xbutton
.x
;
2378 wxevent
.m_y
= xevent
->xbutton
.y
;
2391 // ----------------------------------------------------------------------------
2393 // ----------------------------------------------------------------------------
2395 #define YAllocColor XAllocColor
2396 XColor g_itemColors
[5];
2397 int wxComputeColours (Display
*display
, const wxColour
* back
, const wxColour
* fore
)
2400 static XmColorProc colorProc
;
2402 result
= wxNO_COLORS
;
2406 g_itemColors
[0].red
= (unsigned short)(((long) back
->Red ()) << 8);
2407 g_itemColors
[0].green
= (unsigned short)(((long) back
->Green ()) << 8);
2408 g_itemColors
[0].blue
= (unsigned short)(((long) back
->Blue ()) << 8);
2409 g_itemColors
[0].flags
= DoRed
| DoGreen
| DoBlue
;
2410 if (colorProc
== (XmColorProc
) NULL
)
2412 // Get a ptr to the actual function
2413 colorProc
= XmSetColorCalculation ((XmColorProc
) NULL
);
2414 // And set it back to motif.
2415 XmSetColorCalculation (colorProc
);
2417 (*colorProc
) (&g_itemColors
[wxBACK_INDEX
],
2418 &g_itemColors
[wxFORE_INDEX
],
2419 &g_itemColors
[wxSELE_INDEX
],
2420 &g_itemColors
[wxTOPS_INDEX
],
2421 &g_itemColors
[wxBOTS_INDEX
]);
2422 result
= wxBACK_COLORS
;
2426 g_itemColors
[wxFORE_INDEX
].red
= (unsigned short)(((long) fore
->Red ()) << 8);
2427 g_itemColors
[wxFORE_INDEX
].green
= (unsigned short)(((long) fore
->Green ()) << 8);
2428 g_itemColors
[wxFORE_INDEX
].blue
= (unsigned short)(((long) fore
->Blue ()) << 8);
2429 g_itemColors
[wxFORE_INDEX
].flags
= DoRed
| DoGreen
| DoBlue
;
2430 if (result
== wxNO_COLORS
)
2431 result
= wxFORE_COLORS
;
2434 Display
*dpy
= display
;
2435 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dpy
);
2439 /* 5 Colours to allocate */
2440 for (int i
= 0; i
< 5; i
++)
2441 if (!YAllocColor (dpy
, cmap
, &g_itemColors
[i
]))
2442 result
= wxNO_COLORS
;
2446 /* Only 1 colour to allocate */
2447 if (!YAllocColor (dpy
, cmap
, &g_itemColors
[wxFORE_INDEX
]))
2448 result
= wxNO_COLORS
;
2454 // Changes the foreground and background colours to be derived from the current
2455 // background colour. To change the foreground colour, you must call
2456 // SetForegroundColour explicitly.
2457 void wxWindow::ChangeBackgroundColour()
2459 WXWidget mainWidget
= GetMainWidget();
2461 wxDoChangeBackgroundColour(mainWidget
, m_backgroundColour
);
2462 if ( m_scrolledWindow
&& mainWidget
!= m_scrolledWindow
)
2463 wxDoChangeForegroundColour(m_scrolledWindow
, m_backgroundColour
);
2466 void wxWindow::ChangeForegroundColour()
2468 WXWidget mainWidget
= GetMainWidget();
2470 wxDoChangeForegroundColour(mainWidget
, m_foregroundColour
);
2471 if ( m_scrolledWindow
&& mainWidget
!= m_scrolledWindow
)
2472 wxDoChangeForegroundColour(m_scrolledWindow
, m_foregroundColour
);
2475 bool wxWindow::SetBackgroundColour(const wxColour
& col
)
2477 if ( !wxWindowBase::SetBackgroundColour(col
) )
2480 ChangeBackgroundColour();
2485 bool wxWindow::SetForegroundColour(const wxColour
& col
)
2487 if ( !wxWindowBase::SetForegroundColour(col
) )
2490 ChangeForegroundColour();
2495 void wxWindow::ChangeFont(bool keepOriginalSize
)
2497 // Note that this causes the widget to be resized back
2498 // to its original size! We therefore have to set the size
2499 // back again. TODO: a better way in Motif?
2500 Widget w
= (Widget
) GetLabelWidget(); // Usually the main widget
2501 if (w
&& m_font
.Ok())
2503 int width
, height
, width1
, height1
;
2504 GetSize(& width
, & height
);
2506 wxDoChangeFont( w
, m_font
);
2508 GetSize(& width1
, & height1
);
2509 if (keepOriginalSize
&& (width
!= width1
|| height
!= height1
))
2511 SetSize(wxDefaultCoord
, wxDefaultCoord
, width
, height
);
2517 void wxWindow::PostCreation()
2520 ChangeForegroundColour();
2521 ChangeBackgroundColour();
2525 void wxWindow::PreCreation()
2527 InheritAttributes();
2530 // ----------------------------------------------------------------------------
2532 // ----------------------------------------------------------------------------
2534 wxWindow
*wxGetActiveWindow()
2537 wxFAIL_MSG("Not implemented");
2542 wxWindow
*wxWindowBase::GetCapture()
2544 return (wxWindow
*)g_captureWindow
;
2548 // Find the wxWindow at the current mouse position, returning the mouse
2550 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
2552 pt
= wxGetMousePosition();
2553 return wxFindWindowAtPoint(pt
);
2556 void wxGetMouseState(int& rootX
, int& rootY
, unsigned& maskReturn
)
2558 Display
*display
= wxGlobalDisplay();
2559 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
2560 Window rootReturn
, childReturn
;
2563 XQueryPointer (display
,
2567 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
2570 // Get the current mouse position.
2571 wxPoint
wxGetMousePosition()
2576 wxGetMouseState(x
, y
, mask
);
2577 return wxPoint(x
, y
);
2580 wxMouseState
wxGetMouseState()
2586 wxGetMouseState(x
, y
, mask
);
2591 ms
.SetLeftDown(mask
& Button1Mask
);
2592 ms
.SetMiddleDown(mask
& Button2Mask
);
2593 ms
.SetRightDown(mask
& Button3Mask
);
2595 ms
.SetControlDown(mask
& ControlMask
);
2596 ms
.SetShiftDown(mask
& ShiftMask
);
2597 ms
.SetAltDown(mask
& Mod3Mask
);
2598 ms
.SetMetaDown(mask
& Mod1Mask
);
2604 #if wxMOTIF_NEW_FONT_HANDLING
2608 void wxGetTextExtent(const wxWindow
* window
, const wxString
& str
,
2609 int* width
, int* height
, int* ascent
, int* descent
)
2613 XmRendition rendition
= NULL
;
2614 XmRenderTable table
= NULL
;
2615 Widget w
= (Widget
) window
->GetLabelWidget();
2617 XtVaGetValues( w
, XmNrenderTable
, &table
, NULL
);
2619 table
= XmeGetDefaultRenderTable(w
, XmTEXT_RENDER_TABLE
);
2621 rendition
= XmRenderTableGetRendition( table
, "" );
2622 XtSetArg( args
[count
], XmNfont
, 0 ); ++count
;
2623 XtSetArg( args
[count
], XmNfontType
, 0 ); ++count
;
2624 XmRenditionRetrieve( rendition
, args
, count
);
2626 if (args
[1].value
== XmFONT_IS_FONTSET
)
2628 XRectangle ink
, logical
;
2629 WXFontSet fset
= (WXFontSet
) args
[0].value
;
2631 XmbTextExtents( (XFontSet
)fset
, str
.c_str(), str
.length(),
2634 if( width
) *width
= logical
.width
;
2635 if( height
) *height
= logical
.height
;
2636 if( ascent
) *ascent
= -logical
.y
;
2637 if( descent
) *descent
= logical
.height
+ logical
.y
;
2641 int direction
, ascent2
, descent2
;
2642 XCharStruct overall
;
2643 XFontStruct
* fontStruct
;
2645 XmeRenderTableGetDefaultFont( table
, &fontStruct
);
2646 XTextExtents(fontStruct
, (const char*)str
.c_str(), str
.length(),
2647 &direction
, &ascent2
, &descent2
, &overall
);
2649 if ( width
) *width
= overall
.width
;
2650 if ( height
) *height
= ascent2
+ descent2
;
2651 if ( descent
) *descent
= descent2
;
2652 if ( ascent
) *ascent
= ascent2
;
2656 #else // if !wxMOTIF_NEW_FONT_HANDLING
2658 void wxGetTextExtent(const wxWindow
* window
, const wxString
& str
,
2659 int* width
, int* height
, int* ascent
, int* descent
)
2661 XmFontList list
= NULL
;
2664 Widget w
= (Widget
) window
->GetLabelWidget();
2666 XtVaGetValues( w
, XmNfontList
, &list
, NULL
);
2667 XmFontListInitFontContext( &cxt
, list
);
2669 XmFontListEntry entry
= XmFontListNextEntry( cxt
);
2670 XmFontListFreeFontContext( cxt
);
2671 XtPointer thing
= XmFontListEntryGetFont( entry
, &type
);
2673 if (type
== XmFONT_IS_FONTSET
)
2675 XRectangle ink
, logical
;
2677 XmbTextExtents( (XFontSet
)thing
, str
.c_str(), str
.length(),
2680 if( width
) *width
= logical
.width
;
2681 if( height
) *height
= logical
.height
;
2682 if( ascent
) *ascent
= -logical
.y
;
2683 if( descent
) *descent
= logical
.height
+ logical
.y
;
2687 int direction
, ascent2
, descent2
;
2688 XCharStruct overall
;
2690 XTextExtents( (XFontStruct
*)thing
, (char*)(const char*)str
.c_str(), str
.length(),
2691 &direction
, &ascent2
, &descent2
, &overall
);
2693 if ( width
) *width
= overall
.width
;
2694 if ( height
) *height
= ascent2
+ descent2
;
2695 if ( descent
) *descent
= descent2
;
2696 if ( ascent
) *ascent
= ascent2
;
2700 #endif // !wxMOTIF_NEW_FONT_HANDLING
2702 // ----------------------------------------------------------------------------
2703 // wxNoOptimize: switch off size optimization
2704 // ----------------------------------------------------------------------------
2706 int wxNoOptimize::ms_count
= 0;