]> git.saurik.com Git - wxWidgets.git/blame - src/motif/window.cpp
non-pch build fix for wxUSE_DISPLAY==0
[wxWidgets.git] / src / motif / window.cpp
CommitLineData
4bb6408c 1/////////////////////////////////////////////////////////////////////////////
25466131 2// Name: src/motif/window.cpp
4bb6408c
JS
3// Purpose: wxWindow
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
4bb6408c
JS
10/////////////////////////////////////////////////////////////////////////////
11
34636400
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
1248b41f
MB
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
4dff3400
JJ
23#ifdef __VMS
24#define XtDisplay XTDISPLAY
bcd055ae
JJ
25#define XtWindow XTWINDOW
26#define XtScreen XTSCREEN
4dff3400
JJ
27#endif
28
32d4c30a
WS
29#ifndef WX_PRECOMP
30 #include "wx/hash.h"
e4db172a 31 #include "wx/log.h"
670f9935 32 #include "wx/app.h"
de6185e2 33 #include "wx/utils.h"
76b49cf4 34 #include "wx/frame.h"
da80ae71 35 #include "wx/dc.h"
ed4b0fdc 36 #include "wx/dcclient.h"
f1e01716 37 #include "wx/button.h"
3b3dc801 38 #include "wx/menu.h"
9eddec69 39 #include "wx/settings.h"
1ab440bc 40 #include "wx/scrolwin.h"
ed2fbeb8 41 #include "wx/layout.h"
25466131 42 #include "wx/menuitem.h"
02761f6c 43 #include "wx/module.h"
32d4c30a
WS
44#endif
45
7e1bcfa8 46#include "wx/evtloop.h"
4bb6408c 47
47d67540 48#if wxUSE_DRAG_AND_DROP
34636400 49 #include "wx/dnd.h"
4bb6408c
JS
50#endif
51
fc7ca9b3 52// DoSetSizeIntr and DoMoveWindowIntr
37c997b4
MB
53// PROBLEM:
54// under Motif composite controls (such as wxCalendarCtrl or generic wxSpinCtrl
96be256b 55// did not work and/or segfaulted because
37c997b4
MB
56// 1) wxWindow::Create calls SetSize,
57// which results in a call to DoSetSize much earlier than in the other ports
58// 2) if wxWindow::Create is called (wxControl::Create calls it)
59// then DoSetSize is never called, causing layout problems in composite
60// controls
61//
62// SOLUTION:
63// 1) don't call SetSize, DoSetSize, DoMoveWindow, DoGetPosition,
64// DoSetPosition directly or indirectly from wxWindow::Create
fc7ca9b3 65// 2) call DoMoveWindow from DoSetSize, allowing controls to override it
37c997b4 66
338dd992 67#ifdef __VMS__
02761f6c 68 #pragma message disable nosimpint
338dd992 69#endif
4bb6408c 70#include <Xm/Xm.h>
50414e24
JS
71
72#include <Xm/DrawingA.h>
73#include <Xm/ScrolledW.h>
74#include <Xm/ScrollBar.h>
75#include <Xm/Frame.h>
76#include <Xm/Label.h>
ee31c392 77#include <Xm/RowColumn.h> // for XmMenuPosition
338dd992 78#ifdef __VMS__
02761f6c 79 #pragma message enable nosimpint
338dd992 80#endif
50414e24 81
4bb6408c
JS
82#include "wx/motif/private.h"
83
84#include <string.h>
85
34636400
VZ
86// ----------------------------------------------------------------------------
87// global variables for this module
88// ----------------------------------------------------------------------------
89
33caefb3 90extern wxHashTable *wxWidgetHashTable;
9806a47c
JS
91static wxWindow* g_captureWindow = NULL;
92
34636400
VZ
93
94// ----------------------------------------------------------------------------
95// private functions
96// ----------------------------------------------------------------------------
97
98static void wxCanvasRepaintProc(Widget, XtPointer, XmDrawingAreaCallbackStruct * cbs);
99static void wxCanvasInputEvent(Widget drawingArea, XtPointer data, XmDrawingAreaCallbackStruct * cbs);
100static void wxCanvasMotionEvent(Widget, XButtonEvent * event);
101static void wxCanvasEnterLeave(Widget drawingArea, XtPointer clientData, XCrossingEvent * event);
8aa04e8b 102static void wxScrollBarCallback(Widget widget, XtPointer clientData,
311227c3 103 XmScrollBarCallbackStruct *cbs);
34636400
VZ
104static void wxPanelItemEventHandler(Widget wid,
105 XtPointer client_data,
106 XEvent* event,
107 Boolean *continueToDispatch);
108
109// unused for now
110#if 0
111
112// Helper function for 16-bit fonts
113static int str16len(const char *s)
114{
115 int count = 0;
116
117 while (s[0] && s[1]) {
118 count++;
119 s += 2;
120 }
121
122 return count;
123}
124
125#endif // 0
126
127// ----------------------------------------------------------------------------
128// macros
129// ----------------------------------------------------------------------------
50414e24
JS
130
131#define event_left_is_down(x) ((x)->xbutton.state & Button1Mask)
132#define event_middle_is_down(x) ((x)->xbutton.state & Button2Mask)
133#define event_right_is_down(x) ((x)->xbutton.state & Button3Mask)
134
34636400
VZ
135// ----------------------------------------------------------------------------
136// event tables
137// ----------------------------------------------------------------------------
4bb6408c 138
8e877c19 139 IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
4bb6408c 140
8e877c19 141 BEGIN_EVENT_TABLE(wxWindow, wxWindowBase)
34636400 142 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
34636400 143 END_EVENT_TABLE()
4bb6408c 144
34636400
VZ
145// ============================================================================
146// implementation
147// ============================================================================
4bb6408c 148
34636400
VZ
149// ----------------------------------------------------------------------------
150// helper functions
151// ----------------------------------------------------------------------------
4bb6408c 152
34636400 153void wxWindow::UnmanageAndDestroy(WXWidget widget)
4bb6408c 154{
34636400
VZ
155 Widget w = (Widget)widget;
156 if ( w )
4bb6408c 157 {
34636400
VZ
158 XtUnmanageChild(w);
159 XtDestroyWidget(w);
4bb6408c 160 }
4bb6408c
JS
161}
162
b9ecc16a 163bool wxWindow::MapOrUnmap(WXWidget widget, bool domap)
4bb6408c 164{
34636400
VZ
165 Widget w = (Widget)widget;
166 if ( !w )
96be256b 167 return false;
34636400 168
882b1d8d
MB
169 // Rationale: a lot of common operations (including but not
170 // limited to moving, resizing and appending items to a listbox)
171 // unmamange the widget, do their work, then manage it again.
172 // This means that, for example adding an item to a listbox will show it,
173 // or that most controls are shown every time they are moved or resized!
174 XtSetMappedWhenManaged( w, domap );
175
28169f14
MB
176 // if the widget is not unmanaged, it still intercepts
177 // mouse events, even if it is not mapped (and hence invisible)
b9ecc16a 178 if ( domap )
28169f14
MB
179 {
180 XtManageChild(w);
882b1d8d 181 // XtMapWidget(w);
28169f14 182 }
34636400 183 else
28169f14 184 {
28169f14 185 XtUnmanageChild(w);
882b1d8d 186 // XtUnmapWidget(w);
28169f14 187 }
34636400 188
96be256b 189 return true;
4bb6408c
JS
190}
191
34636400
VZ
192// ----------------------------------------------------------------------------
193// constructors
194// ----------------------------------------------------------------------------
195
196void wxWindow::Init()
4bb6408c 197{
50414e24 198 // Motif-specific
96be256b 199 m_needsRefresh = true;
50414e24 200 m_mainWidget = (WXWidget) 0;
34636400 201
96be256b 202 m_winCaptured = false;
34636400 203
96be256b 204 m_isShown = true;
355b4d3d 205
34636400
VZ
206 m_hScrollBar =
207 m_vScrollBar =
208 m_borderWidget =
209 m_scrolledWindow =
50414e24 210 m_drawingArea = (WXWidget) 0;
34636400 211
34636400
VZ
212 m_scrollPosX =
213 m_scrollPosY = 0;
214
50414e24 215 m_backingPixmap = (WXPixmap) 0;
34636400 216 m_pixmapWidth =
50414e24 217 m_pixmapHeight = 0;
34636400
VZ
218
219 m_pixmapOffsetX =
50414e24 220 m_pixmapOffsetY = 0;
34636400
VZ
221
222 m_lastTS = 0;
223 m_lastButton = 0;
34636400
VZ
224}
225
226// real construction (Init() must have been called before!)
227bool wxWindow::Create(wxWindow *parent, wxWindowID id,
228 const wxPoint& pos,
229 const wxSize& size,
230 long style,
231 const wxString& name)
232{
cce69fec
JS
233 // Get default border
234 wxBorder border = GetBorder(style);
235 style &= ~wxBORDER_MASK;
236 style |= border;
237
96be256b 238 wxCHECK_MSG( parent, false, "can't create wxWindow without parent" );
34636400 239
813c20a6 240 CreateBase(parent, id, pos, size, style, wxDefaultValidator, name);
34636400
VZ
241
242 parent->AddChild(this);
105fbe1f 243 PreCreation();
34636400 244
50414e24
JS
245 //// TODO: we should probably optimize by only creating a
246 //// a drawing area if we have one or more scrollbars (wxVSCROLL/wxHSCROLL).
247 //// But for now, let's simplify things by always creating the
248 //// drawing area, since otherwise the translations are different.
34636400 249
2d120f83 250 // New translations for getting mouse motion feedback
f1db433a 251 static const String translations = wxMOTIF_STR(
34636400 252"<Btn1Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
2d120f83
JS
253<Btn2Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
254<Btn3Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
255<BtnMotion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
256<Btn1Down>: DrawingAreaInput() ManagerGadgetArm()\n\
257<Btn2Down>: DrawingAreaInput() ManagerGadgetArm()\n\
258<Btn3Down>: DrawingAreaInput() ManagerGadgetArm()\n\
259<Btn1Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
260<Btn2Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
261<Btn3Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
262<Motion>: wxCanvasMotionEvent() DrawingAreaInput()\n\
263<EnterWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
264<LeaveWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
f1db433a 265<Key>: DrawingAreaInput()");
34636400 266
2d120f83 267 XtActionsRec actions[1];
f1db433a 268 actions[0].string = wxMOTIF_STR("wxCanvasMotionEvent");
2d120f83
JS
269 actions[0].proc = (XtActionProc) wxCanvasMotionEvent;
270 XtAppAddActions ((XtAppContext) wxTheApp->GetAppContext(), actions, 1);
34636400
VZ
271
272 Widget parentWidget = (Widget) parent->GetClientWidget();
6769d0cb 273 m_borderWidget = wxCreateBorderWidget( (WXWidget)parentWidget, style );
34636400
VZ
274
275 m_scrolledWindow = (WXWidget)XtVaCreateManagedWidget
276 (
277 "scrolledWindow",
278 xmScrolledWindowWidgetClass,
279 m_borderWidget ? (Widget) m_borderWidget
280 : parentWidget,
281 XmNresizePolicy, XmRESIZE_NONE,
282 XmNspacing, 0,
283 XmNscrollingPolicy, XmAPPLICATION_DEFINED,
284 //XmNscrollBarDisplayPolicy, XmAS_NEEDED,
285 NULL
286 );
287
288 XtTranslations ptr = XtParseTranslationTable(translations);
289 m_drawingArea = (WXWidget)XtVaCreateWidget
290 (
291 name,
292 xmDrawingAreaWidgetClass, (Widget) m_scrolledWindow,
293 XmNunitType, XmPIXELS,
294 // XmNresizePolicy, XmRESIZE_ANY,
295 XmNresizePolicy, XmRESIZE_NONE,
296 XmNmarginHeight, 0,
297 XmNmarginWidth, 0,
298 XmNtranslations, ptr,
299 NULL
300 );
301 XtFree((char *) ptr);
302
303#if 0
304 if (GetWindowStyleFlag() & wxOVERRIDE_KEY_TRANSLATIONS)
305 {
2d120f83
JS
306 ptr = XtParseTranslationTable ("<Key>: DrawingAreaInput()");
307 XtOverrideTranslations ((Widget) m_drawingArea, ptr);
308 XtFree ((char *) ptr);
34636400
VZ
309 }
310#endif // 0
311
2d120f83
JS
312 wxAddWindowToTable((Widget) m_drawingArea, this);
313 wxAddWindowToTable((Widget) m_scrolledWindow, this);
34636400
VZ
314
315 // This order is very important in Motif 1.2.1
2d120f83
JS
316 XtRealizeWidget ((Widget) m_scrolledWindow);
317 XtRealizeWidget ((Widget) m_drawingArea);
318 XtManageChild ((Widget) m_drawingArea);
34636400
VZ
319
320 ptr = XtParseTranslationTable("<Configure>: resize()");
321 XtOverrideTranslations((Widget) m_drawingArea, ptr);
50414e24 322 XtFree ((char *) ptr);
34636400 323
2d120f83
JS
324 XtAddCallback ((Widget) m_drawingArea, XmNexposeCallback, (XtCallbackProc) wxCanvasRepaintProc, (XtPointer) this);
325 XtAddCallback ((Widget) m_drawingArea, XmNinputCallback, (XtCallbackProc) wxCanvasInputEvent, (XtPointer) this);
34636400 326
34636400
VZ
327 XtAddEventHandler(
328 (Widget)m_drawingArea,
329 PointerMotionHintMask | EnterWindowMask |
330 LeaveWindowMask | FocusChangeMask,
331 False,
332 (XtEventHandler) wxCanvasEnterLeave,
333 (XtPointer) this
334 );
335
34636400
VZ
336 XmScrolledWindowSetAreas(
337 (Widget)m_scrolledWindow,
338 (Widget) 0, (Widget) 0,
339 (Widget) m_drawingArea);
340
105fbe1f
MB
341 PostCreation();
342
34636400
VZ
343 // Without this, the cursor may not be restored properly (e.g. in splitter
344 // sample).
2d120f83 345 SetCursor(*wxSTANDARD_CURSOR);
96be256b
MB
346 DoSetSizeIntr(pos.x, pos.y, size.x,size.y, wxSIZE_AUTO, true);
347 return true;
88150e60
JS
348}
349
34636400
VZ
350// Destructor
351wxWindow::~wxWindow()
352{
9806a47c 353 if (g_captureWindow == this)
2b5f62a0 354 g_captureWindow = NULL;
355b4d3d 355
96be256b 356 m_isBeingDeleted = true;
f9204363 357
34636400
VZ
358 // Motif-specific actions first
359 WXWidget wMain = GetMainWidget();
360 if ( wMain )
361 {
362 // Removes event handlers
363 DetachWidget(wMain);
364 }
365
34636400
VZ
366 // If m_drawingArea, we're a fully-fledged window with drawing area,
367 // scrollbars etc. (what wxCanvas used to be)
368 if ( m_drawingArea )
369 {
370 // Destroy children before destroying self
371 DestroyChildren();
372
373 if (m_backingPixmap)
374 XFreePixmap (XtDisplay ((Widget) GetMainWidget()), (Pixmap) m_backingPixmap);
375
376 Widget w = (Widget) m_drawingArea;
377 wxDeleteWindowFromTable(w);
378
379 if (w)
380 {
381 XtDestroyWidget(w);
2b5f62a0 382 m_drawingArea = (WXWidget) 0;
34636400
VZ
383 }
384
34636400
VZ
385 // Only if we're _really_ a canvas (not a dialog box/panel)
386 if (m_scrolledWindow)
387 {
388 wxDeleteWindowFromTable((Widget) m_scrolledWindow);
389 }
390
311227c3
MB
391 if (m_hScrollBar)
392 {
393 wxDeleteWindowFromTable((Widget) m_hScrollBar);
2b5f62a0 394 XtUnmanageChild((Widget) m_hScrollBar);
311227c3
MB
395 }
396 if (m_vScrollBar)
397 {
398 wxDeleteWindowFromTable((Widget) m_vScrollBar);
2b5f62a0 399 XtUnmanageChild((Widget) m_vScrollBar);
311227c3
MB
400 }
401
f0d5fc50 402 if (m_hScrollBar)
2b5f62a0 403 XtDestroyWidget((Widget) m_hScrollBar);
f0d5fc50 404 if (m_vScrollBar)
2b5f62a0 405 XtDestroyWidget((Widget) m_vScrollBar);
f0d5fc50 406
34636400
VZ
407 UnmanageAndDestroy(m_scrolledWindow);
408
409 if (m_borderWidget)
410 {
411 XtDestroyWidget ((Widget) m_borderWidget);
412 m_borderWidget = (WXWidget) 0;
413 }
414 }
7b28757f
JS
415 else // Why wasn't this here before? JACS 8/3/2000
416 DestroyChildren();
417
34636400
VZ
418
419 // Destroy the window
420 if (GetMainWidget())
421 {
422 // If this line (XtDestroyWidget) causes a crash, you may comment it out.
423 // Child widgets will get destroyed automatically when a frame
424 // or dialog is destroyed, but before that you may get some memory
425 // leaks and potential layout problems if you delete and then add
426 // child windows.
bdeca1d1
GRG
427
428 // GRG, Feb/2000: commented this out when adding support for
429 // wxSCROLL[WIN]_THUMBRELEASE events. Also it was reported
430 // that this call crashed wxMotif under OS/2, so it seems
431 // that leaving it out is the right thing to do.
b3ef4fb5
SN
432 // SN, Feb/2000: newgrid/griddemo shows why it is needed :-(
433 XtDestroyWidget((Widget) GetMainWidget());
34636400
VZ
434 SetMainWidget((WXWidget) NULL);
435 }
436}
437
438// ----------------------------------------------------------------------------
439// scrollbar management
440// ----------------------------------------------------------------------------
441
148b44a1
MB
442WXWidget wxWindow::DoCreateScrollBar(WXWidget parent,
443 wxOrientation orientation,
444 void (*callback)())
445{
446 int orient = ( orientation & wxHORIZONTAL ) ? XmHORIZONTAL : XmVERTICAL;
447 Widget sb =
448 XtVaCreateManagedWidget( "scrollBarWidget",
449 xmScrollBarWidgetClass, (Widget)parent,
450 XmNorientation, orient,
451 XmNincrement, 1,
452 XmNvalue, 0,
453 NULL );
454
455 XtPointer o = (XtPointer)orientation;
456 XtCallbackProc cb = (XtCallbackProc)callback;
457
458 XtAddCallback( sb, XmNvalueChangedCallback, cb, o );
459 XtAddCallback( sb, XmNdragCallback, cb, o );
460 XtAddCallback( sb, XmNincrementCallback, cb, o );
461 XtAddCallback( sb, XmNdecrementCallback, cb, o );
462 XtAddCallback( sb, XmNpageIncrementCallback, cb, o );
463 XtAddCallback( sb, XmNpageDecrementCallback, cb, o );
464 XtAddCallback( sb, XmNtoTopCallback, cb, o );
465 XtAddCallback( sb, XmNtoBottomCallback, cb, o );
466
467 return (WXWidget)sb;
468}
469
88150e60 470// Helper function
af0bb3b1 471void wxWindow::CreateScrollbar(wxOrientation orientation)
88150e60 472{
34636400
VZ
473 wxCHECK_RET( m_drawingArea, "this window can't have scrollbars" );
474
148b44a1
MB
475 XtVaSetValues( (Widget) m_scrolledWindow,
476 XmNresizePolicy, XmRESIZE_NONE,
477 NULL );
34636400 478
148b44a1 479 wxColour backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
2d120f83
JS
480 // Add scrollbars if required
481 if (orientation == wxHORIZONTAL)
482 {
148b44a1
MB
483 m_hScrollBar = DoCreateScrollBar( m_scrolledWindow, wxHORIZONTAL,
484 (void (*)())wxScrollBarCallback );
34636400 485
96be256b 486 wxDoChangeBackgroundColour(m_hScrollBar, backgroundColour, true);
34636400 487
148b44a1 488 XtRealizeWidget( (Widget)m_hScrollBar );
34636400 489
2d120f83
JS
490 XtVaSetValues((Widget) m_scrolledWindow,
491 XmNhorizontalScrollBar, (Widget) m_hScrollBar,
492 NULL);
34636400 493
148b44a1 494 wxAddWindowToTable( (Widget)m_hScrollBar, this );
2d120f83 495 }
148b44a1 496 else if (orientation == wxVERTICAL)
2d120f83 497 {
148b44a1
MB
498 m_vScrollBar = DoCreateScrollBar( m_scrolledWindow, wxVERTICAL,
499 (void (*)())wxScrollBarCallback );
34636400 500
96be256b 501 wxDoChangeBackgroundColour(m_vScrollBar, backgroundColour, true);
34636400 502
148b44a1 503 XtRealizeWidget((Widget)m_vScrollBar);
34636400 504
2d120f83
JS
505 XtVaSetValues((Widget) m_scrolledWindow,
506 XmNverticalScrollBar, (Widget) m_vScrollBar,
507 NULL);
34636400 508
148b44a1 509 wxAddWindowToTable( (Widget)m_vScrollBar, this );
2d120f83 510 }
34636400 511
148b44a1
MB
512 XtVaSetValues( (Widget) m_scrolledWindow,
513 XmNresizePolicy, XmRESIZE_ANY,
514 NULL );
88150e60 515}
34636400 516
af0bb3b1 517void wxWindow::DestroyScrollbar(wxOrientation orientation)
88150e60 518{
34636400
VZ
519 wxCHECK_RET( m_drawingArea, "this window can't have scrollbars" );
520
148b44a1
MB
521 XtVaSetValues((Widget) m_scrolledWindow,
522 XmNresizePolicy, XmRESIZE_NONE,
523 NULL);
524 String stringSB = orientation == wxHORIZONTAL ?
525 XmNhorizontalScrollBar : XmNverticalScrollBar;
526 WXWidget* widgetSB = orientation == wxHORIZONTAL ?
527 &m_hScrollBar : &m_vScrollBar;
34636400 528
148b44a1 529 if( *widgetSB )
2d120f83 530 {
148b44a1
MB
531 wxDeleteWindowFromTable( (Widget)*widgetSB );
532 XtDestroyWidget( (Widget)*widgetSB );
533 *widgetSB = (WXWidget)NULL;
534 }
34636400 535
148b44a1
MB
536 XtVaSetValues( (Widget)m_scrolledWindow,
537 stringSB, (Widget) 0,
538 NULL );
34636400 539
148b44a1
MB
540 XtVaSetValues((Widget) m_scrolledWindow,
541 XmNresizePolicy, XmRESIZE_ANY,
542 NULL);
4bb6408c
JS
543}
544
34636400
VZ
545// ---------------------------------------------------------------------------
546// basic operations
547// ---------------------------------------------------------------------------
548
4bb6408c
JS
549void wxWindow::SetFocus()
550{
34636400
VZ
551 Widget wMain = (Widget) GetMainWidget();
552 XmProcessTraversal(wMain, XmTRAVERSE_CURRENT);
2d120f83 553 XmProcessTraversal((Widget) GetMainWidget(), XmTRAVERSE_CURRENT);
4bb6408c
JS
554}
555
34636400 556// Get the window with the focus
0fe02759 557wxWindow *wxWindowBase::DoFindFocus()
4bb6408c 558{
34636400
VZ
559 // TODO Problems:
560 // (1) Can there be multiple focussed widgets in an application?
561 // In which case we need to find the top-level window that's
562 // currently active.
563 // (2) The widget with the focus may not be in the widget table
564 // depending on which widgets I put in the table
565 wxWindow *winFocus = (wxWindow *)NULL;
1807c27d 566 for ( wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
34636400
VZ
567 node;
568 node = node->GetNext() )
2d120f83 569 {
34636400
VZ
570 wxWindow *win = node->GetData();
571
572 Widget w = XmGetFocusWidget ((Widget) win->GetTopWidget());
573
574 if (w != (Widget) NULL)
575 {
576 winFocus = wxGetWindowFromTable(w);
577 if ( winFocus )
578 break;
579 }
2d120f83 580 }
4bb6408c 581
34636400 582 return winFocus;
4bb6408c
JS
583}
584
af0bb3b1 585bool wxWindow::Enable(bool enable)
4bb6408c 586{
34636400 587 if ( !wxWindowBase::Enable(enable) )
96be256b 588 return false;
4bb6408c 589
af0bb3b1 590 Widget wMain = (Widget)GetMainWidget();
34636400
VZ
591 if ( wMain )
592 {
593 XtSetSensitive(wMain, enable);
594 XmUpdateDisplay(wMain);
595 }
596
96be256b 597 return true;
4bb6408c
JS
598}
599
34636400 600bool wxWindow::Show(bool show)
4bb6408c 601{
34636400 602 if ( !wxWindowBase::Show(show) )
96be256b 603 return false;
34636400
VZ
604
605 if (m_borderWidget || m_scrolledWindow)
2d120f83 606 {
34636400 607 MapOrUnmap(m_borderWidget ? m_borderWidget : m_scrolledWindow, show);
882b1d8d 608 // MapOrUnmap(m_drawingArea, show);
2d120f83
JS
609 }
610 else
34636400
VZ
611 {
612 if ( !MapOrUnmap(GetTopWidget(), show) )
613 MapOrUnmap(GetMainWidget(), show);
614 }
615
96be256b 616 return true;
34636400 617}
4bb6408c 618
34636400
VZ
619// Raise the window to the top of the Z order
620void wxWindow::Raise()
4bb6408c 621{
34636400
VZ
622 Widget wTop = (Widget) GetTopWidget();
623 Window window = XtWindow(wTop);
624 XRaiseWindow(XtDisplay(wTop), window);
4bb6408c
JS
625}
626
34636400
VZ
627// Lower the window to the bottom of the Z order
628void wxWindow::Lower()
629{
630 Widget wTop = (Widget) GetTopWidget();
631 Window window = XtWindow(wTop);
632 XLowerWindow(XtDisplay(wTop), window);
633}
4bb6408c 634
34097680 635void wxWindow::SetLabel(const wxString& label)
4bb6408c 636{
6991087b
VS
637 XtVaSetValues((Widget)GetMainWidget(), XmNtitle,
638 (const char*)label.mb_str(), NULL);
4bb6408c
JS
639}
640
34097680 641wxString wxWindow::GetLabel() const
4bb6408c 642{
4871d342 643 char *label = NULL;
34097680 644 XtVaGetValues((Widget)GetMainWidget(), XmNtitle, &label, NULL);
af0bb3b1 645
34097680 646 return wxString(label);
4bb6408c
JS
647}
648
4116c221 649void wxWindow::DoCaptureMouse()
4bb6408c 650{
9806a47c 651 g_captureWindow = this;
34636400 652 if ( m_winCaptured )
a4294b78 653 return;
34636400 654
af0bb3b1 655 Widget wMain = (Widget)GetMainWidget();
34636400 656 if ( wMain )
96be256b 657 XtAddGrab(wMain, True, False);
34636400 658
96be256b 659 m_winCaptured = true;
4bb6408c
JS
660}
661
4116c221 662void wxWindow::DoReleaseMouse()
4bb6408c 663{
9806a47c 664 g_captureWindow = NULL;
34636400
VZ
665 if ( !m_winCaptured )
666 return;
667
af0bb3b1 668 Widget wMain = (Widget)GetMainWidget();
34636400
VZ
669 if ( wMain )
670 XtRemoveGrab(wMain);
671
96be256b 672 m_winCaptured = false;
4bb6408c
JS
673}
674
34636400 675bool wxWindow::SetFont(const wxFont& font)
4bb6408c 676{
34636400
VZ
677 if ( !wxWindowBase::SetFont(font) )
678 {
679 // nothing to do
96be256b 680 return false;
34636400
VZ
681 }
682
683 ChangeFont();
684
96be256b 685 return true;
4bb6408c
JS
686}
687
34636400 688bool wxWindow::SetCursor(const wxCursor& cursor)
4bb6408c 689{
34636400 690 if ( !wxWindowBase::SetCursor(cursor) )
2d120f83 691 {
34636400 692 // no change
96be256b 693 return false;
2d120f83 694 }
4bb6408c 695
f6bcfd97
BP
696 // wxASSERT_MSG( m_cursor.Ok(),
697 // wxT("cursor must be valid after call to the base version"));
f516d986 698 const wxCursor* cursor2 = NULL;
f6bcfd97
BP
699 if (m_cursor.Ok())
700 cursor2 = & m_cursor;
701 else
702 cursor2 = wxSTANDARD_CURSOR;
4bb6408c 703
34636400 704 WXDisplay *dpy = GetXDisplay();
f6bcfd97 705 WXCursor x_cursor = cursor2->GetXCursor(dpy);
34636400
VZ
706
707 Widget w = (Widget) GetMainWidget();
708 Window win = XtWindow(w);
709 XDefineCursor((Display*) dpy, win, (Cursor) x_cursor);
af0bb3b1 710
96be256b 711 return true;
34636400
VZ
712}
713
714// Coordinates relative to the window
715void wxWindow::WarpPointer (int x, int y)
4bb6408c 716{
34636400
VZ
717 Widget wClient = (Widget)GetClientWidget();
718
719 XWarpPointer(XtDisplay(wClient), None, XtWindow(wClient), 0, 0, 0, 0, x, y);
4bb6408c
JS
720}
721
34636400
VZ
722// ---------------------------------------------------------------------------
723// scrolling stuff
724// ---------------------------------------------------------------------------
725
726int wxWindow::GetScrollPos(int orient) const
4bb6408c 727{
34636400
VZ
728 if (orient == wxHORIZONTAL)
729 return m_scrollPosX;
730 else
731 return m_scrollPosY;
732
733#if 0
734 Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar);
735 if (scrollBar)
2d120f83 736 {
34636400
VZ
737 int pos;
738 XtVaGetValues(scrollBar, XmNvalue, &pos, NULL);
739 return pos;
2d120f83 740 }
34636400
VZ
741 else
742 return 0;
743#endif // 0
2d120f83 744}
7fe7d506 745
34636400
VZ
746// This now returns the whole range, not just the number of positions that we
747// can scroll.
748int wxWindow::GetScrollRange(int orient) const
2d120f83 749{
af0bb3b1 750 Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
355b4d3d 751 // CE scintilla windows don't always have these scrollbars
34e8f097
CE
752 // and it tends to pile up a whole bunch of asserts
753 //wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
34636400 754
c4cb3d0f 755 int range = 0;
355b4d3d 756 if (scrollBar)
c4cb3d0f 757 XtVaGetValues(scrollBar, XmNmaximum, &range, NULL);
34636400 758 return range;
2d120f83 759}
4bb6408c 760
34636400 761int wxWindow::GetScrollThumb(int orient) const
4bb6408c 762{
af0bb3b1 763 Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
34e8f097 764 //wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
34636400 765
34e8f097
CE
766 int thumb = 0;
767 if (scrollBar)
768 XtVaGetValues(scrollBar, XmNsliderSize, &thumb, NULL);
34636400 769 return thumb;
4bb6408c
JS
770}
771
34636400 772void wxWindow::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
4bb6408c 773{
af0bb3b1 774 Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
34636400
VZ
775
776 if ( scrollBar )
4bb6408c 777 {
34636400 778 XtVaSetValues (scrollBar, XmNvalue, pos, NULL);
4bb6408c 779 }
34636400 780
af0bb3b1 781 SetInternalScrollPos((wxOrientation)orient, pos);
4bb6408c
JS
782}
783
34636400
VZ
784// New function that will replace some of the above.
785void wxWindow::SetScrollbar(int orient, int pos, int thumbVisible,
786 int range, bool WXUNUSED(refresh))
4bb6408c 787{
34636400
VZ
788 int oldW, oldH;
789 GetSize(& oldW, & oldH);
790
791 if (range == 0)
792 range = 1;
793 if (thumbVisible == 0)
794 thumbVisible = 1;
795
796 if (thumbVisible > range)
797 thumbVisible = range;
798
799 // Save the old state to see if it changed
af0bb3b1 800 WXWidget oldScrollBar = GetScrollbar((wxOrientation)orient);
34636400
VZ
801
802 if (orient == wxHORIZONTAL)
50414e24 803 {
34636400 804 if (thumbVisible == range)
2d120f83 805 {
34636400
VZ
806 if (m_hScrollBar)
807 DestroyScrollbar(wxHORIZONTAL);
2d120f83
JS
808 }
809 else
810 {
34636400
VZ
811 if (!m_hScrollBar)
812 CreateScrollbar(wxHORIZONTAL);
2d120f83 813 }
50414e24 814 }
34636400 815 if (orient == wxVERTICAL)
50414e24 816 {
34636400 817 if (thumbVisible == range)
2d120f83 818 {
34636400
VZ
819 if (m_vScrollBar)
820 DestroyScrollbar(wxVERTICAL);
2d120f83
JS
821 }
822 else
823 {
34636400
VZ
824 if (!m_vScrollBar)
825 CreateScrollbar(wxVERTICAL);
2d120f83 826 }
50414e24 827 }
af0bb3b1 828 WXWidget newScrollBar = GetScrollbar((wxOrientation)orient);
4bb6408c 829
88150e60 830 if (oldScrollBar != newScrollBar)
28ab302b 831 {
34636400 832 // This is important! Without it, scrollbars misbehave badly.
2d120f83
JS
833 XtUnrealizeWidget((Widget) m_scrolledWindow);
834 XmScrolledWindowSetAreas ((Widget) m_scrolledWindow, (Widget) m_hScrollBar, (Widget) m_vScrollBar, (Widget) m_drawingArea);
835 XtRealizeWidget((Widget) m_scrolledWindow);
836 XtManageChild((Widget) m_scrolledWindow);
28ab302b 837 }
34636400 838
88150e60 839 if (newScrollBar)
34636400 840 {
2d120f83
JS
841 XtVaSetValues((Widget) newScrollBar,
842 XmNvalue, pos,
843 XmNminimum, 0,
844 XmNmaximum, range,
845 XmNsliderSize, thumbVisible,
846 NULL);
34636400
VZ
847 }
848
af0bb3b1 849 SetInternalScrollPos((wxOrientation)orient, pos);
34636400 850
88150e60
JS
851 int newW, newH;
852 GetSize(& newW, & newH);
34636400 853
88150e60
JS
854 // Adjusting scrollbars can resize the canvas accidentally
855 if (newW != oldW || newH != oldH)
34097680 856 SetSize(wxDefaultCoord, wxDefaultCoord, oldW, oldH);
4bb6408c
JS
857}
858
859// Does a physical scroll
16e93305 860void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
4bb6408c 861{
2d120f83
JS
862 int x, y, w, h;
863 if (rect)
864 {
865 // Use specified rectangle
866 x = rect->x; y = rect->y; w = rect->width; h = rect->height;
867 }
868 else
869 {
870 // Use whole client area
871 x = 0; y = 0;
872 GetClientSize(& w, & h);
873 }
34636400
VZ
874
875 int x1 = (dx >= 0) ? x : x - dx;
2d120f83
JS
876 int y1 = (dy >= 0) ? y : y - dy;
877 int w1 = w - abs(dx);
878 int h1 = h - abs(dy);
879 int x2 = (dx >= 0) ? x + dx : x;
880 int y2 = (dy >= 0) ? y + dy : y;
34636400 881
2d120f83 882 wxClientDC dc(this);
34636400 883
2d120f83 884 dc.SetLogicalFunction (wxCOPY);
34636400 885
2d120f83
JS
886 Widget widget = (Widget) GetMainWidget();
887 Window window = XtWindow(widget);
888 Display* display = XtDisplay(widget);
34636400
VZ
889
890 XCopyArea(display, window, window, (GC) dc.GetGC(),
891 x1, y1, w1, h1, x2, y2);
892
96be256b 893 dc.SetAutoSetting(true);
2d120f83 894 wxBrush brush(GetBackgroundColour(), wxSOLID);
34636400
VZ
895 dc.SetBrush(brush); // FIXME: needed?
896
1807c27d 897 wxWindowList::compatibility_iterator cnode = m_children.GetFirst();
fc7ca9b3
MB
898 while (cnode)
899 {
900 wxWindow *child = cnode->GetData();
901 int sx = 0;
902 int sy = 0;
903 child->GetSize( &sx, &sy );
904 wxPoint pos( child->GetPosition() );
905 child->SetSize( pos.x + dx, pos.y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
906 cnode = cnode->GetNext();
907 }
908
34636400
VZ
909 // We'll add rectangles to the list of update rectangles according to which
910 // bits we've exposed.
2d120f83 911 wxList updateRects;
34636400 912
2d120f83
JS
913 if (dx > 0)
914 {
915 wxRect *rect = new wxRect;
916 rect->x = x;
917 rect->y = y;
918 rect->width = dx;
919 rect->height = h;
34636400 920
2d120f83
JS
921 XFillRectangle(display, window,
922 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
34636400 923
2d120f83
JS
924 rect->x = rect->x;
925 rect->y = rect->y;
926 rect->width = rect->width;
927 rect->height = rect->height;
34636400 928
2d120f83
JS
929 updateRects.Append((wxObject*) rect);
930 }
931 else if (dx < 0)
932 {
933 wxRect *rect = new wxRect;
34636400 934
2d120f83
JS
935 rect->x = x + w + dx;
936 rect->y = y;
937 rect->width = -dx;
938 rect->height = h;
34636400 939
2d120f83
JS
940 XFillRectangle(display, window,
941 (GC) dc.GetGC(), rect->x, rect->y, rect->width,
942 rect->height);
34636400 943
2d120f83
JS
944 rect->x = rect->x;
945 rect->y = rect->y;
946 rect->width = rect->width;
947 rect->height = rect->height;
34636400 948
2d120f83
JS
949 updateRects.Append((wxObject*) rect);
950 }
951 if (dy > 0)
952 {
953 wxRect *rect = new wxRect;
34636400 954
2d120f83
JS
955 rect->x = x;
956 rect->y = y;
957 rect->width = w;
958 rect->height = dy;
34636400 959
2d120f83
JS
960 XFillRectangle(display, window,
961 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
34636400 962
2d120f83
JS
963 rect->x = rect->x;
964 rect->y = rect->y;
965 rect->width = rect->width;
966 rect->height = rect->height;
34636400 967
2d120f83
JS
968 updateRects.Append((wxObject*) rect);
969 }
970 else if (dy < 0)
971 {
972 wxRect *rect = new wxRect;
34636400 973
2d120f83
JS
974 rect->x = x;
975 rect->y = y + h + dy;
976 rect->width = w;
977 rect->height = -dy;
34636400 978
2d120f83
JS
979 XFillRectangle(display, window,
980 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
34636400 981
2d120f83
JS
982 rect->x = rect->x;
983 rect->y = rect->y;
984 rect->width = rect->width;
985 rect->height = rect->height;
34636400 986
2d120f83
JS
987 updateRects.Append((wxObject*) rect);
988 }
989 dc.SetBrush(wxNullBrush);
34636400 990
2d120f83 991 // Now send expose events
34636400 992
1807c27d 993 wxList::compatibility_iterator node = updateRects.GetFirst();
2d120f83
JS
994 while (node)
995 {
1bc822df 996 wxRect* rect = (wxRect*) node->GetData();
2d120f83 997 XExposeEvent event;
34636400 998
2d120f83
JS
999 event.type = Expose;
1000 event.display = display;
1001 event.send_event = True;
1002 event.window = window;
34636400 1003
2d120f83
JS
1004 event.x = rect->x;
1005 event.y = rect->y;
1006 event.width = rect->width;
1007 event.height = rect->height;
34636400 1008
2d120f83 1009 event.count = 0;
34636400 1010
2d120f83 1011 XSendEvent(display, window, False, ExposureMask, (XEvent *)&event);
34636400 1012
1bc822df 1013 node = node->GetNext();
34636400 1014
2d120f83 1015 }
34636400 1016
2d120f83 1017 // Delete the update rects
1bc822df 1018 node = updateRects.GetFirst();
2d120f83
JS
1019 while (node)
1020 {
1bc822df 1021 wxRect* rect = (wxRect*) node->GetData();
2d120f83 1022 delete rect;
1bc822df 1023 node = node->GetNext();
2d120f83 1024 }
a91b47e8
JS
1025
1026 XmUpdateDisplay((Widget) GetMainWidget());
4bb6408c
JS
1027}
1028
34636400
VZ
1029// ---------------------------------------------------------------------------
1030// drag and drop
1031// ---------------------------------------------------------------------------
4ce81a75 1032
34636400 1033#if wxUSE_DRAG_AND_DROP
4ce81a75 1034
34636400 1035void wxWindow::SetDropTarget(wxDropTarget * WXUNUSED(pDropTarget))
4ce81a75 1036{
34636400 1037 // TODO
4bb6408c
JS
1038}
1039
34636400
VZ
1040#endif
1041
1042// Old style file-manager drag&drop
1043void wxWindow::DragAcceptFiles(bool WXUNUSED(accept))
4bb6408c 1044{
34636400 1045 // TODO
4bb6408c
JS
1046}
1047
34636400
VZ
1048// ----------------------------------------------------------------------------
1049// tooltips
1050// ----------------------------------------------------------------------------
1051
1052#if wxUSE_TOOLTIPS
1053
1054void wxWindow::DoSetToolTip(wxToolTip * WXUNUSED(tooltip))
4bb6408c 1055{
34636400 1056 // TODO
4bb6408c
JS
1057}
1058
34636400
VZ
1059#endif // wxUSE_TOOLTIPS
1060
ee31c392
VZ
1061// ----------------------------------------------------------------------------
1062// popup menus
1063// ----------------------------------------------------------------------------
1064
7e1bcfa8
MB
1065#if wxUSE_MENUS
1066
ee31c392
VZ
1067bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
1068{
34097680 1069 if ( x == wxDefaultCoord && y == wxDefaultCoord )
971562cb
VS
1070 {
1071 wxPoint mouse = ScreenToClient(wxGetMousePosition());
1072 x = mouse.x; y = mouse.y;
1073 }
1074
ee31c392
VZ
1075 Widget widget = (Widget) GetMainWidget();
1076
1077 /* The menuId field seems to be usused, so we'll use it to
1078 indicate whether a menu is popped up or not:
1079 0: Not currently created as a popup
1080 -1: Created as a popup, but not active
1081 1: Active popup.
1082 */
1083
1084 if (menu->GetParent() && (menu->GetId() != -1))
96be256b 1085 return false;
ee31c392 1086
7e1bcfa8
MB
1087 if (menu->GetMainWidget())
1088 {
96be256b 1089 menu->DestroyMenu(true);
ee31c392
VZ
1090 }
1091
1092 menu->SetId(1); /* Mark as popped-up */
51c9a5db 1093 menu->CreateMenu(NULL, widget, menu, 0);
ee31c392
VZ
1094 menu->SetInvokingWindow(this);
1095
1096 menu->UpdateUI();
1097
1098 // menu->SetParent(parent);
1099 // parent->children->Append(menu); // Store menu for later deletion
1100
1101 Widget menuWidget = (Widget) menu->GetMainWidget();
1102
1103 int rootX = 0;
1104 int rootY = 0;
1105
1106 int deviceX = x;
1107 int deviceY = y;
1108 /*
1109 if (this->IsKindOf(CLASSINFO(wxCanvas)))
1110 {
1111 wxCanvas *canvas = (wxCanvas *) this;
1112 deviceX = canvas->GetDC ()->LogicalToDeviceX (x);
1113 deviceY = canvas->GetDC ()->LogicalToDeviceY (y);
1114 }
1115 */
1116
1117 Display *display = XtDisplay (widget);
1118 Window rootWindow = RootWindowOfScreen (XtScreen((Widget)widget));
1119 Window thisWindow = XtWindow (widget);
1120 Window childWindow;
1121 XTranslateCoordinates (display, thisWindow, rootWindow, (int) deviceX, (int) deviceY,
1122 &rootX, &rootY, &childWindow);
1123
1124 XButtonPressedEvent event;
1125 event.type = ButtonPress;
1126 event.button = 1;
1127
1128 event.x = deviceX;
1129 event.y = deviceY;
1130
1131 event.x_root = rootX;
1132 event.y_root = rootY;
1133
1134 XmMenuPosition (menuWidget, &event);
1135 XtManageChild (menuWidget);
1136
2b5f62a0 1137 // The ID of a pop-up menu is 1 when active, and is set to 0 by the
e41e1385 1138 // idle-time destroy routine.
2b5f62a0 1139 // Waiting until this ID changes causes this function to block until
e41e1385
JS
1140 // the menu has been dismissed and the widgets cleaned up.
1141 // In other words, once this routine returns, it is safe to delete
1142 // the menu object.
1143 // Ian Brown <ian.brown@printsoft.de>
e41e1385 1144
7e1bcfa8 1145 wxEventLoop evtLoop;
e41e1385 1146
7e1bcfa8
MB
1147 while (menu->GetId() == 1)
1148 {
1149 wxDoEventLoopIteration( evtLoop );
e41e1385 1150 }
7e1bcfa8 1151
96be256b 1152 return true;
ee31c392
VZ
1153}
1154
7e1bcfa8
MB
1155#endif
1156
34636400
VZ
1157// ---------------------------------------------------------------------------
1158// moving and resizing
1159// ---------------------------------------------------------------------------
4bb6408c 1160
34636400 1161bool wxWindow::PreResize()
4bb6408c 1162{
96be256b 1163 return true;
4bb6408c
JS
1164}
1165
34636400 1166// Get total size
af0bb3b1 1167void wxWindow::DoGetSize(int *x, int *y) const
4bb6408c 1168{
fc7ca9b3
MB
1169 Widget widget = (Widget)( !m_drawingArea ? GetTopWidget() :
1170 ( m_borderWidget ? m_borderWidget :
1171 m_scrolledWindow ? m_scrolledWindow :
1172 m_drawingArea ) );
34636400 1173 Dimension xx, yy;
fc7ca9b3 1174
105fbe1f
MB
1175 if (widget)
1176 XtVaGetValues( widget,
1177 XmNwidth, &xx,
1178 XmNheight, &yy,
1179 NULL );
24bd6cb9 1180 if(x) *x = widget ? xx : -1;
105fbe1f 1181 if(y) *y = widget ? yy : -1;
4bb6408c
JS
1182}
1183
af0bb3b1 1184void wxWindow::DoGetPosition(int *x, int *y) const
4bb6408c 1185{
fc7ca9b3
MB
1186 Widget widget = (Widget)
1187 ( m_drawingArea ?
355b4d3d 1188 ( m_borderWidget ? m_borderWidget : m_scrolledWindow ) :
fc7ca9b3
MB
1189 GetTopWidget() );
1190
34636400
VZ
1191 Position xx, yy;
1192 XtVaGetValues(widget, XmNx, &xx, XmNy, &yy, NULL);
b59bf2db 1193
34636400
VZ
1194 // We may be faking the client origin. So a window that's really at (0, 30)
1195 // may appear (to wxWin apps) to be at (0, 0).
1196 if (GetParent())
b59bf2db 1197 {
34636400 1198 wxPoint pt(GetParent()->GetClientAreaOrigin());
355b4d3d
WS
1199 xx = (Position)(xx - pt.x);
1200 yy = (Position)(yy - pt.y);
b59bf2db 1201 }
34636400 1202
fc7ca9b3
MB
1203 if(x) *x = xx;
1204 if(y) *y = yy;
4bb6408c
JS
1205}
1206
af0bb3b1 1207void wxWindow::DoScreenToClient(int *x, int *y) const
4bb6408c 1208{
34636400
VZ
1209 Widget widget = (Widget) GetClientWidget();
1210 Display *display = XtDisplay((Widget) GetMainWidget());
1211 Window rootWindow = RootWindowOfScreen(XtScreen(widget));
1212 Window thisWindow = XtWindow(widget);
1213
1214 Window childWindow;
c5c01214
VZ
1215 int xx = x ? *x : 0;
1216 int yy = y ? *y : 0;
1217 XTranslateCoordinates(display, rootWindow, thisWindow,
1218 xx, yy, x ? x : &xx, y ? y : &yy,
1219 &childWindow);
4bb6408c
JS
1220}
1221
af0bb3b1 1222void wxWindow::DoClientToScreen(int *x, int *y) const
4bb6408c 1223{
34636400
VZ
1224 Widget widget = (Widget) GetClientWidget();
1225 Display *display = XtDisplay(widget);
1226 Window rootWindow = RootWindowOfScreen(XtScreen(widget));
1227 Window thisWindow = XtWindow(widget);
1228
1229 Window childWindow;
c5c01214
VZ
1230 int xx = x ? *x : 0;
1231 int yy = y ? *y : 0;
1232 XTranslateCoordinates(display, thisWindow, rootWindow,
1233 xx, yy, x ? x : &xx, y ? y : &yy,
1234 &childWindow);
4bb6408c
JS
1235}
1236
34636400
VZ
1237
1238// Get size *available for subwindows* i.e. excluding menu bar etc.
af0bb3b1 1239void wxWindow::DoGetClientSize(int *x, int *y) const
4fabb575 1240{
34636400
VZ
1241 Widget widget = (Widget) GetClientWidget();
1242 Dimension xx, yy;
1243 XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL);
f6fb552e 1244 if(x) *x = xx; if(y) *y = yy;
4fabb575
JS
1245}
1246
34636400 1247void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags)
37c997b4 1248{
96be256b 1249 DoSetSizeIntr(x, y, width, height, sizeFlags, false);
37c997b4
MB
1250}
1251
1252void wxWindow::DoSetSizeIntr(int x, int y, int width, int height,
1253 int sizeFlags, bool fromCtor)
4bb6408c 1254{
34636400 1255 // A bit of optimization to help sort out the flickers.
9577d302 1256 int oldX = -1, oldY = -1, oldW = -1, oldH = -1;
32d4c30a 1257
37c997b4
MB
1258 if( !fromCtor )
1259 {
1260 GetSize(& oldW, & oldH);
1261 GetPosition(& oldX, & oldY);
1262 }
34636400 1263
105fbe1f
MB
1264 if (x == -1)
1265 x = oldX;
1266 if (x == -1)
1267 x = oldY;
1268
9d9b7755
VZ
1269 if ( !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
1270 {
9fd8f2dd
MB
1271 if ( width == -1 )
1272 width = oldW;
1273 if ( height == -1 )
1274 height = oldH;
9d9b7755 1275 }
34636400 1276
34097680 1277 wxSize size(wxDefaultSize);
7e1bcfa8 1278 if ( width <= 0 )
fc7ca9b3 1279 {
66f8b9ac 1280 if ( ( sizeFlags & wxSIZE_AUTO_WIDTH ) && !fromCtor )
fc7ca9b3
MB
1281 {
1282 size = DoGetBestSize();
1283 width = size.x;
1284 }
1285 else
1286 {
1287 width = oldW;
1288 }
1289 }
34636400 1290
fc7ca9b3 1291 if ( height == -1 )
02800301 1292 {
66f8b9ac 1293 if( ( sizeFlags & wxSIZE_AUTO_HEIGHT ) && !fromCtor )
fc7ca9b3
MB
1294 {
1295 if( size.x == -1 ) size = DoGetBestSize();
1296 height = size.y;
1297 }
1298 else
1299 {
1300 height = oldH;
1301 }
34636400
VZ
1302 }
1303
fc7ca9b3
MB
1304 if ( x != oldX || y != oldY || width != oldW || height != oldH
1305 || !wxNoOptimize::CanOptimize() )
34636400 1306 {
9d9b7755
VZ
1307 if (m_drawingArea)
1308 {
fc7ca9b3
MB
1309 int flags = 0;
1310
9fd8f2dd 1311 if (x != oldX)
fc7ca9b3
MB
1312 flags |= wxMOVE_X;
1313
9fd8f2dd 1314 if (y != oldY)
fc7ca9b3
MB
1315 flags |= wxMOVE_Y;
1316
1317 if (width > 0)
1318 flags |= wxMOVE_WIDTH;
1319
1320 if (height > 0)
1321 flags |= wxMOVE_HEIGHT;
1322
1323 int xx = x; int yy = y;
1324 AdjustForParentClientOrigin(xx, yy, sizeFlags);
1325 if( !fromCtor )
1326 DoMoveWindow( xx, yy, width, height );
1327 else
1328 DoMoveWindowIntr( xx, yy, width, height, flags );
1329
9d9b7755
VZ
1330 return;
1331 }
34636400 1332
9d9b7755
VZ
1333 Widget widget = (Widget) GetTopWidget();
1334 if (!widget)
1335 return;
34636400 1336
9d9b7755
VZ
1337 bool managed = XtIsManaged( widget );
1338 if (managed)
1339 XtUnmanageChild(widget);
34636400 1340
9d9b7755
VZ
1341 int xx = x;
1342 int yy = y;
1343 AdjustForParentClientOrigin(xx, yy, sizeFlags);
1344
1345 DoMoveWindow(xx, yy, width, height);
34636400 1346
9d9b7755
VZ
1347 if (managed)
1348 XtManageChild(widget);
9d9b7755 1349 }
4bb6408c
JS
1350}
1351
34636400 1352void wxWindow::DoSetClientSize(int width, int height)
4bb6408c 1353{
34636400 1354 if (m_drawingArea)
4bb6408c 1355 {
fc7ca9b3
MB
1356 Widget drawingArea = (Widget) m_drawingArea;
1357
1358 XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
1359
1360 if (width > -1)
1361 XtVaSetValues(drawingArea, XmNwidth, width, NULL);
1362 if (height > -1)
1363 XtVaSetValues(drawingArea, XmNheight, height, NULL);
1364
1365 XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
34636400 1366 return;
4bb6408c 1367 }
34636400
VZ
1368
1369 Widget widget = (Widget) GetTopWidget();
1370
1371 if (width > -1)
1372 XtVaSetValues(widget, XmNwidth, width, NULL);
1373 if (height > -1)
1374 XtVaSetValues(widget, XmNheight, height, NULL);
4bb6408c
JS
1375}
1376
fc7ca9b3
MB
1377void wxWindow::DoMoveWindowIntr(int xx, int yy, int w, int h,
1378 int flags)
9d9b7755 1379{
37c997b4 1380 if (m_drawingArea)
fc7ca9b3
MB
1381 {
1382 Widget drawingArea = (Widget) m_drawingArea;
1383 Widget borderOrScrolled = m_borderWidget ?
1384 (Widget) m_borderWidget :
1385 (Widget) m_scrolledWindow;
1386
1387 bool managed = XtIsManaged(borderOrScrolled);
fc7ca9b3
MB
1388 if (managed)
1389 XtUnmanageChild (borderOrScrolled);
1390 XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
1391
1392 if (flags & wxMOVE_X)
1393 XtVaSetValues (borderOrScrolled,
1394 XmNx, xx,
1395 NULL);
1396 if (flags & wxMOVE_Y)
1397 XtVaSetValues (borderOrScrolled,
1398 XmNy, yy,
1399 NULL);
1400
1401 if (flags & wxMOVE_WIDTH)
1402 {
1403 if (m_borderWidget)
1404 {
1405 XtVaSetValues ((Widget) m_borderWidget, XmNwidth, w, NULL);
1406 short thick, margin;
1407 XtVaGetValues ((Widget) m_borderWidget,
1408 XmNshadowThickness, &thick,
1409 XmNmarginWidth, &margin,
1410 NULL);
1411 w -= 2 * (thick + margin);
1412 }
37c997b4 1413
88793548 1414 if( w < 1 ) w = 1;
fc7ca9b3
MB
1415 XtVaSetValues ((Widget) m_scrolledWindow, XmNwidth, w, NULL);
1416 }
d9d3622e 1417
fc7ca9b3
MB
1418 if (flags & wxMOVE_HEIGHT)
1419 {
1420 if (m_borderWidget)
1421 {
1422 XtVaSetValues ((Widget) m_borderWidget, XmNheight, h, NULL);
1423 short thick, margin;
1424 XtVaGetValues ((Widget) m_borderWidget,
1425 XmNshadowThickness, &thick,
1426 XmNmarginHeight, &margin,
1427 NULL);
1428 h -= 2 * (thick + margin);
1429 }
1430
88793548 1431 if( h < 1 ) h = 1;
fc7ca9b3
MB
1432 XtVaSetValues ((Widget) m_scrolledWindow, XmNheight, h, NULL);
1433 }
1434
1435 if (managed)
1436 XtManageChild (borderOrScrolled);
1437 XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
1438 }
1439 else
1440 {
1441 if( w < 1 ) w = 1;
1442 if( h < 1 ) h = 1;
1443
1444 XtVaSetValues((Widget)GetTopWidget(),
1445 XmNx, xx,
1446 XmNy, yy,
1447 XmNwidth, w,
1448 XmNheight, h,
1449 NULL);
1450 }
1451}
1452
1453void wxWindow::DoMoveWindow(int x, int y, int width, int height)
1454{
1455 DoMoveWindowIntr (x, y, width, height,
1456 wxMOVE_X|wxMOVE_Y|wxMOVE_WIDTH|wxMOVE_HEIGHT);
9d9b7755
VZ
1457}
1458
34636400
VZ
1459// ---------------------------------------------------------------------------
1460// text metrics
1461// ---------------------------------------------------------------------------
1462
1463int wxWindow::GetCharHeight() const
4bb6408c 1464{
996994c7 1465 int height;
355b4d3d 1466
105fbe1f
MB
1467 if (m_font.Ok())
1468 wxGetTextExtent (GetXDisplay(), m_font, 1.0,
1469 "x", NULL, &height, NULL, NULL);
1470 else
1471 wxGetTextExtent (this, "x", NULL, &height, NULL, NULL);
34636400 1472
996994c7 1473 return height;
4bb6408c
JS
1474}
1475
34636400 1476int wxWindow::GetCharWidth() const
4bb6408c 1477{
996994c7 1478 int width;
355b4d3d 1479
105fbe1f
MB
1480 if (m_font.Ok())
1481 wxGetTextExtent (GetXDisplay(), m_font, 1.0,
1482 "x", &width, NULL, NULL, NULL);
1483 else
1484 wxGetTextExtent (this, "x", &width, NULL, NULL, NULL);
34636400 1485
996994c7 1486 return width;
4bb6408c
JS
1487}
1488
34636400
VZ
1489void wxWindow::GetTextExtent(const wxString& string,
1490 int *x, int *y,
1491 int *descent, int *externalLeading,
1492 const wxFont *theFont) const
4bb6408c 1493{
996994c7 1494 const wxFont *fontToUse = theFont ? theFont : &m_font;
34636400 1495
34636400
VZ
1496 if (externalLeading)
1497 *externalLeading = 0;
105fbe1f
MB
1498 if (fontToUse->Ok())
1499 wxGetTextExtent (GetXDisplay(), *fontToUse, 1.0,
1500 string, x, y, NULL, descent);
1501 else
1502 wxGetTextExtent (this, string, x, y, NULL, descent);
4bb6408c
JS
1503}
1504
34636400
VZ
1505// ----------------------------------------------------------------------------
1506// painting
1507// ----------------------------------------------------------------------------
4bb6408c 1508
148b44a1
MB
1509void wxWindow::AddUpdateRect(int x, int y, int w, int h)
1510{
1511 m_updateRegion.Union( x, y, w, h );
1512}
1513
34636400 1514void wxWindow::Refresh(bool eraseBack, const wxRect *rect)
4bb6408c 1515{
105fbe1f
MB
1516 Widget widget = (Widget) GetMainWidget();
1517 if (!widget)
1518 return;
96be256b 1519 m_needsRefresh = true;
105fbe1f
MB
1520 Display *display = XtDisplay(widget);
1521 Window thisWindow = XtWindow(widget);
34636400
VZ
1522
1523 XExposeEvent dummyEvent;
1524 int width, height;
1525 GetSize(&width, &height);
1526
1527 dummyEvent.type = Expose;
1528 dummyEvent.display = display;
1529 dummyEvent.send_event = True;
1530 dummyEvent.window = thisWindow;
1531 if (rect)
2d120f83 1532 {
34636400
VZ
1533 dummyEvent.x = rect->x;
1534 dummyEvent.y = rect->y;
1535 dummyEvent.width = rect->width;
1536 dummyEvent.height = rect->height;
2d120f83
JS
1537 }
1538 else
1539 {
34636400
VZ
1540 dummyEvent.x = 0;
1541 dummyEvent.y = 0;
1542 dummyEvent.width = width;
1543 dummyEvent.height = height;
2d120f83 1544 }
34636400 1545 dummyEvent.count = 0;
4bb6408c 1546
34636400 1547 if (eraseBack)
2d120f83 1548 {
34636400
VZ
1549 wxClientDC dc(this);
1550 wxBrush backgroundBrush(GetBackgroundColour(), wxSOLID);
1551 dc.SetBackground(backgroundBrush);
1552 if (rect)
1553 dc.Clear(*rect);
1554 else
1555 dc.Clear();
2d120f83 1556 }
4bb6408c 1557
34636400 1558 XSendEvent(display, thisWindow, False, ExposureMask, (XEvent *)&dummyEvent);
4bb6408c
JS
1559}
1560
34636400 1561void wxWindow::DoPaint()
4bb6408c 1562{
34636400
VZ
1563 //TODO : make a temporary gc so we can do the XCopyArea below
1564 if (m_backingPixmap && !m_needsRefresh)
4bb6408c 1565 {
34636400 1566 wxPaintDC dc(this);
4bb6408c 1567
34636400 1568 GC tempGC = (GC) dc.GetBackingGC();
4bb6408c 1569
34636400 1570 Widget widget = (Widget) GetMainWidget();
4bb6408c 1571
34636400
VZ
1572 int scrollPosX = 0;
1573 int scrollPosY = 0;
4bb6408c 1574
34636400
VZ
1575 // We have to test whether it's a wxScrolledWindow (hack!) because
1576 // otherwise we don't know how many pixels have been scrolled. We might
1577 // solve this in the future by defining virtual wxWindow functions to get
1578 // the scroll position in pixels. Or, each kind of scrolled window has to
77ffb593 1579 // implement backing stores itself, using generic wxWidgets code.
34636400
VZ
1580 wxScrolledWindow* scrolledWindow = wxDynamicCast(this, wxScrolledWindow);
1581 if ( scrolledWindow )
1582 {
1583 int x, y;
1584 scrolledWindow->CalcScrolledPosition(0, 0, &x, &y);
1585
1586 scrollPosX = - x;
1587 scrollPosY = - y;
1588 }
1589
1590 // TODO: This could be optimized further by only copying the areas in the
1591 // current update region.
1592
1593 // Only blit the part visible in the client area. The backing pixmap
1594 // always starts at 0, 0 but we may be looking at only a portion of it.
1595 wxSize clientArea = GetClientSize();
1596 int toBlitX = m_pixmapWidth - scrollPosX;
1597 int toBlitY = m_pixmapHeight - scrollPosY;
1598
1599 // Copy whichever is samller, the amount of pixmap we have to copy,
1600 // or the size of the client area.
1601 toBlitX = wxMin(toBlitX, clientArea.x);
1602 toBlitY = wxMin(toBlitY, clientArea.y);
1603
1604 // Make sure we're not negative
1605 toBlitX = wxMax(0, toBlitX);
1606 toBlitY = wxMax(0, toBlitY);
1607
1608 XCopyArea
1609 (
1610 XtDisplay(widget),
1611 (Pixmap) m_backingPixmap,
1612 XtWindow (widget),
1613 tempGC,
1614 scrollPosX, scrollPosY, // Start at the scroll position
1615 toBlitX, toBlitY, // How much of the pixmap to copy
1616 0, 0 // Destination
1617 );
1618 }
1619 else
4bb6408c 1620 {
fc7ca9b3 1621 wxWindowDC dc(this);
34636400 1622 // Set an erase event first
fc7ca9b3 1623 wxEraseEvent eraseEvent(GetId(), &dc);
34636400
VZ
1624 eraseEvent.SetEventObject(this);
1625 GetEventHandler()->ProcessEvent(eraseEvent);
1626
1627 wxPaintEvent event(GetId());
1628 event.SetEventObject(this);
1629 GetEventHandler()->ProcessEvent(event);
1630
96be256b 1631 m_needsRefresh = false;
4bb6408c 1632 }
4bb6408c
JS
1633}
1634
34636400
VZ
1635// ----------------------------------------------------------------------------
1636// event handlers
1637// ----------------------------------------------------------------------------
1638
1639// Responds to colour changes: passes event on to children.
1640void wxWindow::OnSysColourChanged(wxSysColourChangedEvent& event)
4bb6408c 1641{
1807c27d 1642 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
34636400 1643 while ( node )
4bb6408c 1644 {
34636400
VZ
1645 // Only propagate to non-top-level windows
1646 wxWindow *win = node->GetData();
1647 if ( win->GetParent() )
2d120f83 1648 {
34636400 1649 wxSysColourChangedEvent event2;
687706f5 1650 event.SetEventObject(win);
34636400 1651 win->GetEventHandler()->ProcessEvent(event2);
2d120f83 1652 }
4bb6408c 1653
34636400 1654 node = node->GetNext();
2d120f83 1655 }
4bb6408c
JS
1656}
1657
e39af974 1658void wxWindow::OnInternalIdle()
4bb6408c 1659{
34636400
VZ
1660 // This calls the UI-update mechanism (querying windows for
1661 // menu/toolbar/control state information)
24bd6cb9 1662 if (wxUpdateUIEvent::CanUpdate(this) && IsShown())
e39af974 1663 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
4bb6408c
JS
1664}
1665
34636400
VZ
1666// ----------------------------------------------------------------------------
1667// accelerators
1668// ----------------------------------------------------------------------------
4bb6408c 1669
34636400 1670bool wxWindow::ProcessAccelerator(wxKeyEvent& event)
4bb6408c 1671{
7e1bcfa8 1672#if wxUSE_ACCEL
34636400 1673 if (!m_acceleratorTable.Ok())
96be256b 1674 return false;
4bb6408c 1675
34636400
VZ
1676 int count = m_acceleratorTable.GetCount();
1677 wxAcceleratorEntry* entries = m_acceleratorTable.GetEntries();
1678 int i;
1679 for (i = 0; i < count; i++)
2d120f83 1680 {
34636400
VZ
1681 wxAcceleratorEntry* entry = & (entries[i]);
1682 if (entry->MatchesEvent(event))
1683 {
f6045f99 1684 // Bingo, we have a match. Now find a control that matches the
2b5f62a0 1685 // entry command id.
4bb6408c 1686
34636400
VZ
1687 // Need to go up to the top of the window hierarchy, since it might
1688 // be e.g. a menu item
1689 wxWindow* parent = this;
1690 while ( parent && !parent->IsTopLevel() )
1691 parent = parent->GetParent();
4bb6408c 1692
34636400 1693 if (!parent)
96be256b 1694 return false;
4bb6408c 1695
34636400
VZ
1696 wxFrame* frame = wxDynamicCast(parent, wxFrame);
1697 if ( frame )
1698 {
7e1bcfa8 1699#if wxUSE_MENUS
34636400
VZ
1700 // Try for a menu command
1701 if (frame->GetMenuBar())
1702 {
c71830c3 1703 wxMenuItem* item = frame->GetMenuBar()->FindItem(entry->GetCommand());
34636400
VZ
1704 if (item)
1705 {
1706 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, entry->GetCommand());
1707 commandEvent.SetEventObject(frame);
4bb6408c 1708
96be256b 1709 // If ProcessEvent returns true (it was handled), then
34636400
VZ
1710 // the calling code will skip the event handling.
1711 return frame->GetEventHandler()->ProcessEvent(commandEvent);
1712 }
1713 }
7e1bcfa8 1714#endif
34636400 1715 }
3dd4e4e0 1716
34636400
VZ
1717 // Find a child matching the command id
1718 wxWindow* child = parent->FindWindow(entry->GetCommand());
3dd4e4e0 1719
34636400
VZ
1720 // No such child
1721 if (!child)
96be256b 1722 return false;
3dd4e4e0 1723
34636400
VZ
1724 // Now we process those kinds of windows that we can.
1725 // For now, only buttons.
1726 if ( wxDynamicCast(child, wxButton) )
1727 {
1728 wxCommandEvent commandEvent (wxEVT_COMMAND_BUTTON_CLICKED, child->GetId());
1729 commandEvent.SetEventObject(child);
1730 return child->GetEventHandler()->ProcessEvent(commandEvent);
1731 }
3dd4e4e0 1732
96be256b 1733 return false;
34636400
VZ
1734 } // matches event
1735 }// for
7e1bcfa8 1736#endif
4bb6408c 1737
34636400 1738 // We didn't match the key event against an accelerator.
96be256b 1739 return false;
4bb6408c
JS
1740}
1741
34636400
VZ
1742// ============================================================================
1743// Motif-specific stuff from here on
1744// ============================================================================
1745
1746// ----------------------------------------------------------------------------
77ffb593 1747// function which maintain the global hash table mapping Widgets to wxWidgets
34636400
VZ
1748// ----------------------------------------------------------------------------
1749
1750bool wxAddWindowToTable(Widget w, wxWindow *win)
4bb6408c 1751{
e1bce3ca
VZ
1752 const long key = (long)w;
1753 if ( wxWidgetHashTable->Get(key))
2d120f83 1754 {
34636400 1755 wxLogDebug("Widget table clash: new widget is %ld, %s",
e1bce3ca 1756 key, win->GetClassInfo()->GetClassName());
96be256b 1757 return false;
2d120f83 1758 }
4bb6408c 1759
e1bce3ca 1760 wxWidgetHashTable->Put(key, win);
4bb6408c 1761
1bc822df 1762 wxLogTrace("widget", "Widget 0x%p <-> window %p (%s)",
e1bce3ca 1763 w, win, win->GetClassInfo()->GetClassName());
31528cd3 1764
96be256b 1765 return true;
4bb6408c
JS
1766}
1767
34636400 1768wxWindow *wxGetWindowFromTable(Widget w)
4bb6408c 1769{
33caefb3 1770 return (wxWindow *)wxWidgetHashTable->Get((long) w);
4bb6408c
JS
1771}
1772
34636400 1773void wxDeleteWindowFromTable(Widget w)
4bb6408c 1774{
fc7ca9b3
MB
1775 wxLogTrace("widget", "Widget 0x%p", (WXWidget)w);
1776
33caefb3 1777 wxWidgetHashTable->Delete((long)w);
4bb6408c
JS
1778}
1779
34636400
VZ
1780// ----------------------------------------------------------------------------
1781// add/remove window from the table
1782// ----------------------------------------------------------------------------
4bb6408c 1783
34636400 1784// Add to hash table, add event handler
af111fc3 1785bool wxWindow::AttachWidget (wxWindow* WXUNUSED(parent), WXWidget mainWidget,
34636400 1786 WXWidget formWidget, int x, int y, int width, int height)
4bb6408c 1787{
34636400 1788 wxAddWindowToTable((Widget) mainWidget, this);
a8680e3e
MB
1789 XtAddEventHandler( (Widget) mainWidget,
1790 ButtonPressMask | ButtonReleaseMask
1791 | PointerMotionMask,
1792 False,
1793 wxPanelItemEventHandler,
1794 (XtPointer) this);
4bb6408c 1795
34636400
VZ
1796 if (!formWidget)
1797 {
1798 XtTranslations ptr;
1799 XtOverrideTranslations ((Widget) mainWidget,
1800 ptr = XtParseTranslationTable ("<Configure>: resize()"));
1801 XtFree ((char *) ptr);
1802 }
4bb6408c 1803
34636400
VZ
1804 // Some widgets have a parent form widget, e.g. wxRadioBox
1805 if (formWidget)
1806 {
1807 if (!wxAddWindowToTable((Widget) formWidget, this))
96be256b 1808 return false;
4bb6408c 1809
34636400
VZ
1810 XtTranslations ptr;
1811 XtOverrideTranslations ((Widget) formWidget,
1812 ptr = XtParseTranslationTable ("<Configure>: resize()"));
1813 XtFree ((char *) ptr);
1814 }
4bb6408c 1815
24490a1c
MB
1816 if (x == -1)
1817 x = 0;
1818 if (y == -1)
1819 y = 0;
1820 DoSetSize (x, y, width, height, wxSIZE_USE_EXISTING);
4bb6408c 1821
f9204363 1822 return true;
4bb6408c
JS
1823}
1824
34636400
VZ
1825// Remove event handler, remove from hash table
1826bool wxWindow::DetachWidget(WXWidget widget)
4bb6408c 1827{
a8680e3e
MB
1828 XtRemoveEventHandler( (Widget) widget,
1829 ButtonPressMask | ButtonReleaseMask
1830 | PointerMotionMask,
1831 False,
1832 wxPanelItemEventHandler,
1833 (XtPointer)this);
4bb6408c 1834
34636400 1835 wxDeleteWindowFromTable((Widget) widget);
96be256b 1836 return true;
4bb6408c
JS
1837}
1838
34636400
VZ
1839// ----------------------------------------------------------------------------
1840// Motif-specific accessors
1841// ----------------------------------------------------------------------------
2d120f83 1842
1807c27d
MB
1843WXWindow wxWindow::GetClientXWindow() const
1844{
1845 Widget wMain = (Widget)GetClientWidget();
1846 if ( wMain )
1847 return (WXWindow) XtWindow(wMain);
1848 else
1849 return (WXWindow) 0;
1850}
1851
34636400 1852// Get the underlying X window
4bb6408c
JS
1853WXWindow wxWindow::GetXWindow() const
1854{
af0bb3b1 1855 Widget wMain = (Widget)GetMainWidget();
34636400
VZ
1856 if ( wMain )
1857 return (WXWindow) XtWindow(wMain);
ad813b00
JS
1858 else
1859 return (WXWindow) 0;
4bb6408c
JS
1860}
1861
34636400 1862// Get the underlying X display
4bb6408c
JS
1863WXDisplay *wxWindow::GetXDisplay() const
1864{
af0bb3b1 1865 Widget wMain = (Widget)GetMainWidget();
34636400
VZ
1866 if ( wMain )
1867 return (WXDisplay*) XtDisplay(wMain);
ad813b00
JS
1868 else
1869 return (WXDisplay*) NULL;
4bb6408c
JS
1870}
1871
1872WXWidget wxWindow::GetMainWidget() const
1873{
50414e24 1874 if (m_drawingArea)
2d120f83 1875 return m_drawingArea;
50414e24 1876 else
2d120f83 1877 return m_mainWidget;
50414e24
JS
1878}
1879
1880WXWidget wxWindow::GetClientWidget() const
1881{
1882 if (m_drawingArea != (WXWidget) 0)
1883 return m_drawingArea;
1884 else
02e8b2f9
JS
1885 return GetMainWidget();
1886}
1887
1888WXWidget wxWindow::GetTopWidget() const
1889{
1890 return GetMainWidget();
4bb6408c
JS
1891}
1892
34636400
VZ
1893WXWidget wxWindow::GetLabelWidget() const
1894{
1895 return GetMainWidget();
1896}
1897
1898// ----------------------------------------------------------------------------
1899// Motif callbacks
1900// ----------------------------------------------------------------------------
1901
1902// All widgets should have this as their resize proc.
1903// OnSize sent to wxWindow via client data.
66f8b9ac
MB
1904void wxWidgetResizeProc(Widget w, XConfigureEvent *WXUNUSED(event),
1905 String WXUNUSED(args)[], int *WXUNUSED(num_args))
34636400
VZ
1906{
1907 wxWindow *win = wxGetWindowFromTable(w);
1908 if (!win)
1909 return;
1910
1911 if (win->PreResize())
1912 {
355b4d3d
WS
1913 wxSize newSize(win->GetSize());
1914 wxSizeEvent sizeEvent(newSize, win->GetId());
34636400
VZ
1915 sizeEvent.SetEventObject(win);
1916 win->GetEventHandler()->ProcessEvent(sizeEvent);
1917 }
1918}
1919
1920static void wxCanvasRepaintProc(Widget drawingArea,
1921 XtPointer clientData,
1922 XmDrawingAreaCallbackStruct * cbs)
50414e24 1923{
34636400 1924 if (!wxGetWindowFromTable(drawingArea))
2d120f83 1925 return;
34636400 1926
50414e24 1927 XEvent * event = cbs->event;
55acd85e 1928 wxWindow * win = (wxWindow *) clientData;
34636400 1929
50414e24
JS
1930 switch (event->type)
1931 {
2d120f83 1932 case Expose:
55acd85e 1933 {
6970c7b9
MB
1934 win->AddUpdateRect(event->xexpose.x, event->xexpose.y,
1935 event->xexpose.width, event->xexpose.height);
148b44a1 1936
55acd85e
JS
1937 if (event -> xexpose.count == 0)
1938 {
a91b47e8 1939 win->DoPaint();
55acd85e
JS
1940 }
1941 break;
1942 }
50414e24 1943 }
50414e24
JS
1944}
1945
1946// Unable to deal with Enter/Leave without a separate EventHandler (Motif 1.1.4)
34636400 1947static void wxCanvasEnterLeave(Widget drawingArea,
af111fc3 1948 XtPointer WXUNUSED(clientData),
34636400 1949 XCrossingEvent * event)
50414e24 1950{
2d120f83
JS
1951 XmDrawingAreaCallbackStruct cbs;
1952 XEvent ev;
34636400 1953
2d120f83 1954 ((XCrossingEvent &) ev) = *event;
34636400 1955
2d120f83
JS
1956 cbs.reason = XmCR_INPUT;
1957 cbs.event = &ev;
34636400
VZ
1958
1959 wxCanvasInputEvent(drawingArea, (XtPointer) NULL, &cbs);
50414e24
JS
1960}
1961
1962// Fix to make it work under Motif 1.0 (!)
da494b40
MB
1963static void wxCanvasMotionEvent (Widget WXUNUSED(drawingArea),
1964 XButtonEvent *WXUNUSED(event))
50414e24 1965{
34636400 1966#if XmVersion <= 1000
2d120f83
JS
1967 XmDrawingAreaCallbackStruct cbs;
1968 XEvent ev;
34636400 1969
2d120f83
JS
1970 ev = *((XEvent *) event);
1971 cbs.reason = XmCR_INPUT;
1972 cbs.event = &ev;
34636400 1973
2d120f83 1974 wxCanvasInputEvent (drawingArea, (XtPointer) NULL, &cbs);
34636400 1975#endif // XmVersion <= 1000
50414e24
JS
1976}
1977
34636400 1978static void wxCanvasInputEvent(Widget drawingArea,
af111fc3 1979 XtPointer WXUNUSED(data),
34636400 1980 XmDrawingAreaCallbackStruct * cbs)
50414e24 1981{
34636400 1982 wxWindow *canvas = wxGetWindowFromTable(drawingArea);
2a23a89d 1983 XEvent* xevent = cbs->event;
34636400 1984
2d120f83 1985 if (canvas==NULL)
34636400
VZ
1986 return;
1987
2d120f83
JS
1988 if (cbs->reason != XmCR_INPUT)
1989 return;
34636400 1990
2a23a89d 1991 switch (xevent->xany.type)
50414e24
JS
1992 {
1993 case EnterNotify:
1994 case LeaveNotify:
1995 case ButtonPress:
1996 case ButtonRelease:
1997 case MotionNotify:
2d120f83 1998 {
2a23a89d
MB
1999 wxMouseEvent wxevent(0);
2000 if (wxTranslateMouseEvent(wxevent, canvas, drawingArea, xevent))
e700df04 2001 {
2a23a89d 2002 canvas->GetEventHandler()->ProcessEvent(wxevent);
e700df04 2003 }
e700df04 2004 break;
2a23a89d 2005 }
50414e24 2006 case KeyPress:
50414e24 2007 {
2b5f62a0 2008 wxKeyEvent event (wxEVT_CHAR);
2a23a89d 2009 if (wxTranslateKeyEvent (event, canvas, (Widget) 0, xevent))
2d120f83
JS
2010 {
2011 // Implement wxFrame::OnCharHook by checking ancestor.
66f8b9ac
MB
2012 wxWindow *parent = canvas;
2013 while (parent && !parent->IsTopLevel())
2d120f83 2014 parent = parent->GetParent();
34636400 2015
2d120f83
JS
2016 if (parent)
2017 {
2018 event.SetEventType(wxEVT_CHAR_HOOK);
2019 if (parent->GetEventHandler()->ProcessEvent(event))
2020 return;
2d120f83 2021 }
a91b47e8
JS
2022
2023 // For simplicity, OnKeyDown is the same as OnChar
2024 // TODO: filter modifier key presses from OnChar
2025 event.SetEventType(wxEVT_KEY_DOWN);
2026
2027 // Only process OnChar if OnKeyDown didn't swallow it
2028 if (!canvas->GetEventHandler()->ProcessEvent (event))
2029 {
66f8b9ac
MB
2030 event.SetEventType(wxEVT_CHAR);
2031 canvas->GetEventHandler()->ProcessEvent (event);
2032 }
2d120f83
JS
2033 }
2034 break;
2035 }
2036 case KeyRelease:
2037 {
2d120f83 2038 wxKeyEvent event (wxEVT_KEY_UP);
2a23a89d 2039 if (wxTranslateKeyEvent (event, canvas, (Widget) 0, xevent))
2d120f83
JS
2040 {
2041 canvas->GetEventHandler()->ProcessEvent (event);
2042 }
2043 break;
50414e24 2044 }
50414e24 2045 case FocusIn:
2d120f83 2046 {
2a23a89d 2047 if (xevent->xfocus.detail != NotifyPointer)
2d120f83
JS
2048 {
2049 wxFocusEvent event(wxEVT_SET_FOCUS, canvas->GetId());
2050 event.SetEventObject(canvas);
2051 canvas->GetEventHandler()->ProcessEvent(event);
2052 }
2053 break;
50414e24 2054 }
50414e24 2055 case FocusOut:
2d120f83 2056 {
2a23a89d 2057 if (xevent->xfocus.detail != NotifyPointer)
2d120f83
JS
2058 {
2059 wxFocusEvent event(wxEVT_KILL_FOCUS, canvas->GetId());
2060 event.SetEventObject(canvas);
2061 canvas->GetEventHandler()->ProcessEvent(event);
2062 }
2063 break;
2064 }
50414e24 2065 default:
2d120f83 2066 break;
50414e24
JS
2067 }
2068}
2069
34636400 2070static void wxPanelItemEventHandler(Widget wid,
af111fc3 2071 XtPointer WXUNUSED(client_data),
34636400
VZ
2072 XEvent* event,
2073 Boolean *continueToDispatch)
50414e24 2074{
34636400 2075 // Widget can be a label or the actual widget.
a91b47e8 2076
af0bb3b1 2077 wxWindow *window = wxGetWindowFromTable(wid);
34636400
VZ
2078 if (window)
2079 {
2080 wxMouseEvent wxevent(0);
2081 if (wxTranslateMouseEvent(wxevent, window, wid, event))
2082 {
2083 window->GetEventHandler()->ProcessEvent(wxevent);
2084 }
2085 }
a91b47e8 2086
34636400 2087 // TODO: probably the key to allowing default behaviour to happen. Say we
96be256b 2088 // set a m_doDefault flag to false at the start of this function. Then in
34636400 2089 // e.g. wxWindow::OnMouseEvent we can call Default() which sets this flag to
96be256b 2090 // true, indicating that default processing can happen. Thus, behaviour can
34636400
VZ
2091 // appear to be overridden just by adding an event handler and not calling
2092 // wxWindow::OnWhatever. ALSO, maybe we can use this instead of the current
2093 // way of handling drawing area events, to simplify things.
2094 *continueToDispatch = True;
2095}
a91b47e8 2096
34636400
VZ
2097static void wxScrollBarCallback(Widget scrollbar,
2098 XtPointer clientData,
311227c3 2099 XmScrollBarCallbackStruct *cbs)
34636400 2100{
34636400 2101 wxWindow *win = wxGetWindowFromTable(scrollbar);
29014baa
VZ
2102 wxCHECK_RET( win, _T("invalid widget in scrollbar callback") );
2103
a4588fd1 2104 wxOrientation orientation = (wxOrientation)wxPtrToUInt(clientData);
a91b47e8 2105
34636400
VZ
2106 wxEventType eventType = wxEVT_NULL;
2107 switch (cbs->reason)
2108 {
2109 case XmCR_INCREMENT:
2110 {
311227c3 2111 eventType = wxEVT_SCROLLWIN_LINEDOWN;
34636400
VZ
2112 break;
2113 }
2114 case XmCR_DECREMENT:
2115 {
311227c3 2116 eventType = wxEVT_SCROLLWIN_LINEUP;
34636400
VZ
2117 break;
2118 }
2119 case XmCR_DRAG:
2120 {
311227c3 2121 eventType = wxEVT_SCROLLWIN_THUMBTRACK;
34636400
VZ
2122 break;
2123 }
2124 case XmCR_VALUE_CHANGED:
2125 {
bdeca1d1 2126 eventType = wxEVT_SCROLLWIN_THUMBRELEASE;
34636400
VZ
2127 break;
2128 }
2129 case XmCR_PAGE_INCREMENT:
2130 {
311227c3 2131 eventType = wxEVT_SCROLLWIN_PAGEDOWN;
34636400
VZ
2132 break;
2133 }
2134 case XmCR_PAGE_DECREMENT:
2135 {
311227c3 2136 eventType = wxEVT_SCROLLWIN_PAGEUP;
34636400
VZ
2137 break;
2138 }
2139 case XmCR_TO_TOP:
2140 {
311227c3 2141 eventType = wxEVT_SCROLLWIN_TOP;
34636400
VZ
2142 break;
2143 }
2144 case XmCR_TO_BOTTOM:
2145 {
311227c3 2146 eventType = wxEVT_SCROLLWIN_BOTTOM;
34636400
VZ
2147 break;
2148 }
2149 default:
2150 {
2151 // Should never get here
2152 wxFAIL_MSG("Unknown scroll event.");
2153 break;
2154 }
2155 }
a91b47e8 2156
311227c3
MB
2157 wxScrollWinEvent event(eventType,
2158 cbs->value,
148b44a1 2159 orientation);
311227c3 2160 event.SetEventObject( win );
34636400
VZ
2161 win->GetEventHandler()->ProcessEvent(event);
2162}
a91b47e8 2163
34636400
VZ
2164// For repainting arbitrary windows
2165void wxUniversalRepaintProc(Widget w, XtPointer WXUNUSED(c_data), XEvent *event, char *)
2166{
34636400
VZ
2167 wxWindow* win = wxGetWindowFromTable(w);
2168 if (!win)
2169 return;
a91b47e8 2170
e1bce3ca 2171 switch ( event->type )
50414e24 2172 {
e1bce3ca 2173 case Expose:
34636400 2174 {
148b44a1
MB
2175 win->AddUpdateRect(event->xexpose.x, event->xexpose.y,
2176 event->xexpose.width, event->xexpose.height);
2177
3f97d339 2178 if ( event->xexpose.count == 0 )
34636400
VZ
2179 {
2180 win->DoPaint();
af0bb3b1
VZ
2181 }
2182
34636400
VZ
2183 break;
2184 }
50414e24
JS
2185 }
2186}
2187
34636400
VZ
2188// ----------------------------------------------------------------------------
2189// TranslateXXXEvent() functions
2190// ----------------------------------------------------------------------------
2191
a8680e3e 2192bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win,
2a23a89d 2193 Widget widget, const XEvent *xevent)
02e8b2f9 2194{
2d120f83
JS
2195 switch (xevent->xany.type)
2196 {
a8680e3e
MB
2197 case EnterNotify:
2198 case LeaveNotify:
2199#if 0
2200 fprintf(stderr, "Widget 0x%p <-> window %p (%s), %s\n",
2201 (WXWidget)widget, win, win->GetClassInfo()->GetClassName(),
2202 (xevent->xany.type == EnterNotify ? "ENTER" : "LEAVE"));
2203#endif
1e8abce5
MB
2204 case ButtonPress:
2205 case ButtonRelease:
2206 case MotionNotify:
02e8b2f9 2207 {
2a23a89d
MB
2208 int eventx = xevent->xbutton.x, eventy = xevent->xbutton.y;
2209
2d120f83 2210 wxEventType eventType = wxEVT_NULL;
34636400 2211
2d120f83
JS
2212 if (xevent->xany.type == LeaveNotify)
2213 {
a8680e3e
MB
2214 eventType = wxEVT_LEAVE_WINDOW;
2215 }
2216 if (xevent->xany.type == EnterNotify)
2217 {
2218 eventType = wxEVT_ENTER_WINDOW;
2d120f83
JS
2219 }
2220 else if (xevent->xany.type == MotionNotify)
2221 {
2222 eventType = wxEVT_MOTION;
2a23a89d
MB
2223
2224 if (xevent->xmotion.is_hint == NotifyHint)
2225 {
2226 Window root, child;
2227 int x_root, y_root;
2228 unsigned int state;
2229 Display *dpy = XtDisplay (widget);
2230
2231 XQueryPointer (dpy, XtWindow (widget),
2232 &root, &child,
2233 &x_root, &y_root, &eventx, &eventy, &state);
2234 }
2d120f83
JS
2235 }
2236 else if (xevent->xany.type == ButtonPress)
2237 {
1e8abce5
MB
2238 wxevent.SetTimestamp(xevent->xbutton.time);
2239 int button = 0;
2d120f83
JS
2240 if (xevent->xbutton.button == Button1)
2241 {
2242 eventType = wxEVT_LEFT_DOWN;
1e8abce5 2243 button = 1;
2d120f83
JS
2244 }
2245 else if (xevent->xbutton.button == Button2)
2246 {
2247 eventType = wxEVT_MIDDLE_DOWN;
1e8abce5 2248 button = 2;
2d120f83
JS
2249 }
2250 else if (xevent->xbutton.button == Button3)
2251 {
2252 eventType = wxEVT_RIGHT_DOWN;
1e8abce5
MB
2253 button = 3;
2254 }
2255
2256 // check for a double click
2257 //
eb6fa4b4 2258 long dclickTime = XtGetMultiClickTime(xevent->xany.display);
1e8abce5
MB
2259 long ts = wxevent.GetTimestamp();
2260
2261 int buttonLast = win->GetLastClickedButton();
2262 long lastTS = win->GetLastClickTime();
a8680e3e
MB
2263 if ( buttonLast && buttonLast == button &&
2264 (ts - lastTS) < dclickTime )
1e8abce5
MB
2265 {
2266 // I have a dclick
2267 win->SetLastClick(0, ts);
205c0389
VZ
2268 if ( eventType == wxEVT_LEFT_DOWN )
2269 eventType = wxEVT_LEFT_DCLICK;
2270 else if ( eventType == wxEVT_MIDDLE_DOWN )
2271 eventType = wxEVT_MIDDLE_DCLICK;
2272 else if ( eventType == wxEVT_RIGHT_DOWN )
2273 eventType = wxEVT_RIGHT_DCLICK;
1e8abce5
MB
2274 }
2275 else
2276 {
2277 // not fast enough or different button
2278 win->SetLastClick(button, ts);
2d120f83
JS
2279 }
2280 }
2281 else if (xevent->xany.type == ButtonRelease)
2282 {
2283 if (xevent->xbutton.button == Button1)
2284 {
2285 eventType = wxEVT_LEFT_UP;
2d120f83
JS
2286 }
2287 else if (xevent->xbutton.button == Button2)
2288 {
2289 eventType = wxEVT_MIDDLE_UP;
2d120f83
JS
2290 }
2291 else if (xevent->xbutton.button == Button3)
2292 {
2293 eventType = wxEVT_RIGHT_UP;
2d120f83 2294 }
a8680e3e 2295 else
96be256b 2296 return false;
2d120f83 2297 }
af0bb3b1
VZ
2298 else
2299 {
96be256b 2300 return false;
af0bb3b1 2301 }
34636400 2302
2d120f83 2303 wxevent.SetEventType(eventType);
34636400 2304
2d120f83
JS
2305 Position x1, y1;
2306 XtVaGetValues(widget, XmNx, &x1, XmNy, &y1, NULL);
34636400 2307
2d120f83
JS
2308 int x2, y2;
2309 win->GetPosition(&x2, &y2);
34636400 2310
77ffb593 2311 // The button x/y must be translated to wxWidgets
2d120f83
JS
2312 // window space - the widget might be a label or button,
2313 // within a form.
2314 int dx = 0;
2315 int dy = 0;
2316 if (widget != (Widget)win->GetMainWidget())
2317 {
2318 dx = x1;
2319 dy = y1;
2320 }
34636400 2321
2a23a89d
MB
2322 wxevent.m_x = eventx + dx;
2323 wxevent.m_y = eventy + dy;
34636400 2324
2d120f83 2325 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
34636400 2326 || (event_left_is_down (xevent)
2d120f83
JS
2327 && (eventType != wxEVT_LEFT_UP)));
2328 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
34636400 2329 || (event_middle_is_down (xevent)
2d120f83
JS
2330 && (eventType != wxEVT_MIDDLE_UP)));
2331 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
34636400 2332 || (event_right_is_down (xevent)
2d120f83 2333 && (eventType != wxEVT_RIGHT_UP)));
34636400 2334
355b4d3d
WS
2335 wxevent.m_shiftDown = (xevent->xbutton.state & ShiftMask) == ShiftMask;
2336 wxevent.m_controlDown = (xevent->xbutton.state & ControlMask) == ControlMask;
2337 wxevent.m_altDown = (xevent->xbutton.state & Mod3Mask) == Mod3Mask;
2338 wxevent.m_metaDown = (xevent->xbutton.state & Mod1Mask) == Mod1Mask;
1e8abce5
MB
2339
2340 wxevent.SetId(win->GetId());
2341 wxevent.SetEventObject(win);
2342
96be256b 2343 return true;
2d120f83 2344 }
02e8b2f9 2345 }
96be256b 2346 return false;
02e8b2f9
JS
2347}
2348
fc7ca9b3 2349bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win,
2a23a89d 2350 Widget WXUNUSED(widget), const XEvent *xevent)
02e8b2f9 2351{
2d120f83
JS
2352 switch (xevent->xany.type)
2353 {
02e8b2f9 2354 case KeyPress:
4a041f2f 2355 case KeyRelease:
2d120f83
JS
2356 {
2357 char buf[20];
34636400 2358
2d120f83 2359 KeySym keySym;
fc7ca9b3 2360 (void) XLookupString((XKeyEvent *)xevent, buf, 20, &keySym, NULL);
2d120f83 2361 int id = wxCharCodeXToWX (keySym);
2b5f62a0
VZ
2362 // id may be WXK_xxx code - these are outside ASCII range, so we
2363 // can't just use toupper() on id
2364 if (id >= 'a' && id <= 'z')
2365 id = toupper(id);
34636400 2366
2d120f83 2367 if (xevent->xkey.state & ShiftMask)
96be256b 2368 wxevent.m_shiftDown = true;
2d120f83 2369 if (xevent->xkey.state & ControlMask)
96be256b 2370 wxevent.m_controlDown = true;
2d120f83 2371 if (xevent->xkey.state & Mod3Mask)
96be256b 2372 wxevent.m_altDown = true;
2d120f83 2373 if (xevent->xkey.state & Mod1Mask)
96be256b 2374 wxevent.m_metaDown = true;
2d120f83
JS
2375 wxevent.SetEventObject(win);
2376 wxevent.m_keyCode = id;
2377 wxevent.SetTimestamp(xevent->xkey.time);
34636400 2378
2d120f83
JS
2379 wxevent.m_x = xevent->xbutton.x;
2380 wxevent.m_y = xevent->xbutton.y;
34636400 2381
2d120f83 2382 if (id > -1)
96be256b 2383 return true;
355b4d3d
WS
2384
2385 return false;
2d120f83 2386 }
02e8b2f9 2387 default:
2d120f83
JS
2388 break;
2389 }
96be256b 2390 return false;
02e8b2f9
JS
2391}
2392
34636400
VZ
2393// ----------------------------------------------------------------------------
2394// Colour stuff
2395// ----------------------------------------------------------------------------
2396
02e8b2f9 2397#define YAllocColor XAllocColor
0d57be45 2398XColor g_itemColors[5];
f516d986 2399int wxComputeColours (Display *display, const wxColour * back, const wxColour * fore)
02e8b2f9 2400{
2d120f83
JS
2401 int result;
2402 static XmColorProc colorProc;
34636400 2403
2d120f83 2404 result = wxNO_COLORS;
34636400 2405
2d120f83 2406 if (back)
02e8b2f9 2407 {
355b4d3d
WS
2408 g_itemColors[0].red = (unsigned short)(((long) back->Red ()) << 8);
2409 g_itemColors[0].green = (unsigned short)(((long) back->Green ()) << 8);
2410 g_itemColors[0].blue = (unsigned short)(((long) back->Blue ()) << 8);
2d120f83
JS
2411 g_itemColors[0].flags = DoRed | DoGreen | DoBlue;
2412 if (colorProc == (XmColorProc) NULL)
2413 {
2414 // Get a ptr to the actual function
2415 colorProc = XmSetColorCalculation ((XmColorProc) NULL);
2416 // And set it back to motif.
2417 XmSetColorCalculation (colorProc);
2418 }
2419 (*colorProc) (&g_itemColors[wxBACK_INDEX],
2420 &g_itemColors[wxFORE_INDEX],
2421 &g_itemColors[wxSELE_INDEX],
2422 &g_itemColors[wxTOPS_INDEX],
2423 &g_itemColors[wxBOTS_INDEX]);
2424 result = wxBACK_COLORS;
02e8b2f9 2425 }
2d120f83 2426 if (fore)
02e8b2f9 2427 {
355b4d3d
WS
2428 g_itemColors[wxFORE_INDEX].red = (unsigned short)(((long) fore->Red ()) << 8);
2429 g_itemColors[wxFORE_INDEX].green = (unsigned short)(((long) fore->Green ()) << 8);
2430 g_itemColors[wxFORE_INDEX].blue = (unsigned short)(((long) fore->Blue ()) << 8);
2d120f83
JS
2431 g_itemColors[wxFORE_INDEX].flags = DoRed | DoGreen | DoBlue;
2432 if (result == wxNO_COLORS)
2433 result = wxFORE_COLORS;
02e8b2f9 2434 }
34636400 2435
2d120f83
JS
2436 Display *dpy = display;
2437 Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy);
34636400 2438
2d120f83 2439 if (back)
02e8b2f9 2440 {
2d120f83
JS
2441 /* 5 Colours to allocate */
2442 for (int i = 0; i < 5; i++)
2443 if (!YAllocColor (dpy, cmap, &g_itemColors[i]))
2444 result = wxNO_COLORS;
02e8b2f9 2445 }
2d120f83 2446 else if (fore)
02e8b2f9 2447 {
2d120f83
JS
2448 /* Only 1 colour to allocate */
2449 if (!YAllocColor (dpy, cmap, &g_itemColors[wxFORE_INDEX]))
2450 result = wxNO_COLORS;
02e8b2f9 2451 }
34636400 2452
fc7ca9b3 2453 return result;
02e8b2f9
JS
2454}
2455
34636400
VZ
2456// Changes the foreground and background colours to be derived from the current
2457// background colour. To change the foreground colour, you must call
2458// SetForegroundColour explicitly.
0d57be45 2459void wxWindow::ChangeBackgroundColour()
02e8b2f9 2460{
34636400
VZ
2461 WXWidget mainWidget = GetMainWidget();
2462 if ( mainWidget )
a8680e3e 2463 wxDoChangeBackgroundColour(mainWidget, m_backgroundColour);
24490a1c
MB
2464 if ( m_scrolledWindow && mainWidget != m_scrolledWindow )
2465 wxDoChangeForegroundColour(m_scrolledWindow, m_backgroundColour);
0d57be45 2466}
02e8b2f9 2467
0d57be45
JS
2468void wxWindow::ChangeForegroundColour()
2469{
34636400
VZ
2470 WXWidget mainWidget = GetMainWidget();
2471 if ( mainWidget )
a8680e3e 2472 wxDoChangeForegroundColour(mainWidget, m_foregroundColour);
34636400 2473 if ( m_scrolledWindow && mainWidget != m_scrolledWindow )
a8680e3e 2474 wxDoChangeForegroundColour(m_scrolledWindow, m_foregroundColour);
02e8b2f9
JS
2475}
2476
af0bb3b1 2477bool wxWindow::SetBackgroundColour(const wxColour& col)
02e8b2f9 2478{
af0bb3b1 2479 if ( !wxWindowBase::SetBackgroundColour(col) )
96be256b 2480 return false;
af0bb3b1 2481
0d57be45 2482 ChangeBackgroundColour();
af0bb3b1 2483
96be256b 2484 return true;
0d57be45
JS
2485}
2486
af0bb3b1 2487bool wxWindow::SetForegroundColour(const wxColour& col)
0d57be45 2488{
af0bb3b1 2489 if ( !wxWindowBase::SetForegroundColour(col) )
96be256b 2490 return false;
af0bb3b1 2491
0d57be45 2492 ChangeForegroundColour();
af0bb3b1 2493
96be256b 2494 return true;
0d57be45
JS
2495}
2496
4b5f3fe6 2497void wxWindow::ChangeFont(bool keepOriginalSize)
0d57be45
JS
2498{
2499 // Note that this causes the widget to be resized back
2500 // to its original size! We therefore have to set the size
2501 // back again. TODO: a better way in Motif?
0d57be45 2502 Widget w = (Widget) GetLabelWidget(); // Usually the main widget
af0bb3b1 2503 if (w && m_font.Ok())
0d57be45
JS
2504 {
2505 int width, height, width1, height1;
2506 GetSize(& width, & height);
34636400 2507
105fbe1f 2508 wxDoChangeFont( w, m_font );
34636400 2509
0d57be45 2510 GetSize(& width1, & height1);
4b5f3fe6 2511 if (keepOriginalSize && (width != width1 || height != height1))
0d57be45 2512 {
9b5f1895 2513 SetSize(wxDefaultCoord, wxDefaultCoord, width, height);
0d57be45
JS
2514 }
2515 }
02e8b2f9 2516}
0d57be45 2517
105fbe1f
MB
2518// Post-creation
2519void wxWindow::PostCreation()
2520{
2521 ChangeFont();
2522 ChangeForegroundColour();
2523 ChangeBackgroundColour();
2524}
2525
2526// Pre-creation
2527void wxWindow::PreCreation()
2528{
2529 InheritAttributes();
2530}
2531
34636400
VZ
2532// ----------------------------------------------------------------------------
2533// global functions
2534// ----------------------------------------------------------------------------
0d57be45 2535
34636400 2536wxWindow *wxGetActiveWindow()
1f112209
JS
2537{
2538 // TODO
9b8f6fa2 2539 wxFAIL_MSG("Not implemented");
34636400 2540 return NULL;
1f112209
JS
2541}
2542
9806a47c
JS
2543/* static */
2544wxWindow *wxWindowBase::GetCapture()
2545{
2546 return (wxWindow *)g_captureWindow;
2547}
2548
2549
3723b7b1
JS
2550// Find the wxWindow at the current mouse position, returning the mouse
2551// position.
2e2a55b2 2552wxWindow* wxFindWindowAtPointer(wxPoint& pt)
3723b7b1 2553{
2e2a55b2
MW
2554 pt = wxGetMousePosition();
2555 return wxFindWindowAtPoint(pt);
3723b7b1
JS
2556}
2557
0cbc5287 2558void wxGetMouseState(int& rootX, int& rootY, unsigned& maskReturn)
3723b7b1 2559{
eb6fa4b4 2560 Display *display = wxGlobalDisplay();
59a12e90
JS
2561 Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
2562 Window rootReturn, childReturn;
0cbc5287 2563 int winX, winY;
59a12e90
JS
2564
2565 XQueryPointer (display,
2b5f62a0
VZ
2566 rootWindow,
2567 &rootReturn,
59a12e90
JS
2568 &childReturn,
2569 &rootX, &rootY, &winX, &winY, &maskReturn);
0cbc5287
MW
2570}
2571
2572// Get the current mouse position.
2573wxPoint wxGetMousePosition()
2574{
2575 int x, y;
2576 unsigned mask;
2577
2578 wxGetMouseState(x, y, mask);
2579 return wxPoint(x, y);
2580}
2581
2582wxMouseState wxGetMouseState()
2583{
2584 wxMouseState ms;
2585 int x, y;
2586 unsigned mask;
2587
2588 wxGetMouseState(x, y, mask);
2589
2590 ms.SetX(x);
2591 ms.SetY(y);
2592
2593 ms.SetLeftDown(mask & Button1Mask);
2594 ms.SetMiddleDown(mask & Button2Mask);
2595 ms.SetRightDown(mask & Button3Mask);
2596
2597 ms.SetControlDown(mask & ControlMask);
2598 ms.SetShiftDown(mask & ShiftMask);
af1a6227
MW
2599 ms.SetAltDown(mask & Mod3Mask);
2600 ms.SetMetaDown(mask & Mod1Mask);
0cbc5287
MW
2601
2602 return ms;
3723b7b1
JS
2603}
2604
9806a47c 2605
105fbe1f
MB
2606#if wxMOTIF_NEW_FONT_HANDLING
2607
2608#include <Xm/XmP.h>
2609
2610void wxGetTextExtent(const wxWindow* window, const wxString& str,
2611 int* width, int* height, int* ascent, int* descent)
2612{
2613 Arg args[2];
2614 int count = 0;
2615 XmRendition rendition = NULL;
2616 XmRenderTable table = NULL;
2617 Widget w = (Widget) window->GetLabelWidget();
2618
2619 XtVaGetValues( w, XmNrenderTable, &table, NULL );
2620 if (table == NULL)
2621 table = XmeGetDefaultRenderTable(w, XmTEXT_RENDER_TABLE);
2622
2623 rendition = XmRenderTableGetRendition( table, "" );
2624 XtSetArg( args[count], XmNfont, 0 ); ++count;
2625 XtSetArg( args[count], XmNfontType, 0 ); ++count;
2626 XmRenditionRetrieve( rendition, args, count );
2627
2628 if (args[1].value == XmFONT_IS_FONTSET)
2629 {
2630 XRectangle ink, logical;
2631 WXFontSet fset = (WXFontSet) args[0].value;
24bd6cb9 2632
105fbe1f
MB
2633 XmbTextExtents( (XFontSet)fset, str.c_str(), str.length(),
2634 &ink, &logical);
2635
2636 if( width ) *width = logical.width;
2637 if( height ) *height = logical.height;
24bd6cb9
JS
2638 if( ascent ) *ascent = -logical.y;
2639 if( descent ) *descent = logical.height + logical.y;
105fbe1f
MB
2640 }
2641 else
2642 {
2643 int direction, ascent2, descent2;
2644 XCharStruct overall;
2645 XFontStruct* fontStruct;
2646
2647 XmeRenderTableGetDefaultFont( table, &fontStruct );
2648 XTextExtents(fontStruct, (const char*)str.c_str(), str.length(),
2649 &direction, &ascent2, &descent2, &overall);
2650
2651 if ( width ) *width = overall.width;
2652 if ( height ) *height = ascent2 + descent2;
2653 if ( descent ) *descent = descent2;
2654 if ( ascent ) *ascent = ascent2;
2655 }
2656}
2657
2658#else // if !wxMOTIF_NEW_FONT_HANDLING
2659
2660void wxGetTextExtent(const wxWindow* window, const wxString& str,
2661 int* width, int* height, int* ascent, int* descent)
2662{
2663 XmFontList list = NULL;
2664 XmFontContext cxt;
2665 XmFontType type;
2666 Widget w = (Widget) window->GetLabelWidget();
2667
2668 XtVaGetValues( w, XmNfontList, &list, NULL );
2669 XmFontListInitFontContext( &cxt, list );
2670
2671 XmFontListEntry entry = XmFontListNextEntry( cxt );
2672 XmFontListFreeFontContext( cxt );
2673 XtPointer thing = XmFontListEntryGetFont( entry, &type );
2674
2675 if (type == XmFONT_IS_FONTSET)
2676 {
2677 XRectangle ink, logical;
24bd6cb9 2678
105fbe1f
MB
2679 XmbTextExtents( (XFontSet)thing, str.c_str(), str.length(),
2680 &ink, &logical);
2681
2682 if( width ) *width = logical.width;
2683 if( height ) *height = logical.height;
24bd6cb9
JS
2684 if( ascent ) *ascent = -logical.y;
2685 if( descent ) *descent = logical.height + logical.y;
105fbe1f
MB
2686 }
2687 else
2688 {
2689 int direction, ascent2, descent2;
2690 XCharStruct overall;
2691
2692 XTextExtents( (XFontStruct*)thing, (char*)(const char*)str.c_str(), str.length(),
2693 &direction, &ascent2, &descent2, &overall);
2694
2695 if ( width ) *width = overall.width;
2696 if ( height ) *height = ascent2 + descent2;
2697 if ( descent ) *descent = descent2;
2698 if ( ascent ) *ascent = ascent2;
2699 }
2700}
2701
2702#endif // !wxMOTIF_NEW_FONT_HANDLING
2703
34636400
VZ
2704// ----------------------------------------------------------------------------
2705// wxNoOptimize: switch off size optimization
2706// ----------------------------------------------------------------------------
88150e60 2707
af0bb3b1 2708int wxNoOptimize::ms_count = 0;