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