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