]> git.saurik.com Git - wxWidgets.git/blame - src/motif/window.cpp
Add bmpmotif.cpp to descrip.mms.
[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
b9ecc16a 175 if ( domap )
34636400
VZ
176 XtMapWidget(w);
177 else
178 XtUnmapWidget(w);
179
b9ecc16a
MB
180 // Rationale: a lot of common operations (including but not
181 // limited to moving, resizing and appending items to a listbox)
182 // unmamange the widget, do their work, then manage it again.
183 // This means that, for example adding an item to a listbox will show it,
184 // or that most controls are shown every time they are moved or resized!
185 XtSetMappedWhenManaged( w, domap );
186
4bb6408c
JS
187 return TRUE;
188}
189
34636400
VZ
190// ----------------------------------------------------------------------------
191// constructors
192// ----------------------------------------------------------------------------
193
194void wxWindow::Init()
4bb6408c 195{
34636400
VZ
196 // generic initializations first
197 InitBase();
198
50414e24 199 // Motif-specific
a91b47e8 200 m_needsRefresh = TRUE;
50414e24 201 m_mainWidget = (WXWidget) 0;
34636400
VZ
202
203 m_button1Pressed =
204 m_button2Pressed =
50414e24 205 m_button3Pressed = FALSE;
34636400 206
50414e24 207 m_winCaptured = FALSE;
34636400 208
50414e24 209 m_isShown = TRUE;
3ab377bd
MB
210 m_isBeingDeleted = FALSE;
211
34636400
VZ
212 m_hScrollBar =
213 m_vScrollBar =
214 m_borderWidget =
215 m_scrolledWindow =
50414e24 216 m_drawingArea = (WXWidget) 0;
34636400
VZ
217
218 m_hScroll =
50414e24 219 m_vScroll = FALSE;
34636400
VZ
220
221 m_scrollPosX =
222 m_scrollPosY = 0;
223
50414e24 224 m_backingPixmap = (WXPixmap) 0;
34636400 225 m_pixmapWidth =
50414e24 226 m_pixmapHeight = 0;
34636400
VZ
227
228 m_pixmapOffsetX =
50414e24 229 m_pixmapOffsetY = 0;
34636400
VZ
230
231 m_lastTS = 0;
232 m_lastButton = 0;
233 m_canAddEventHandler = FALSE;
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);
2d120f83
JS
381 DoChangeBackgroundColour(m_scrolledWindow, backgroundColour, TRUE);
382 DoChangeBackgroundColour(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);
2d120f83 532 DoChangeBackgroundColour(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
2d120f83 540 m_hScroll = TRUE;
311227c3
MB
541
542 wxAddWindowToTable( hScrollBar, this );
2d120f83 543 }
34636400 544
2d120f83
JS
545 if (orientation == wxVERTICAL)
546 {
547 Widget vScrollBar = XtVaCreateManagedWidget ("vsb",
548 xmScrollBarWidgetClass, (Widget) m_scrolledWindow,
549 XmNorientation, XmVERTICAL,
550 NULL);
bdeca1d1 551 XtAddCallback (vScrollBar, XmNvalueChangedCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
2d120f83
JS
552 XtAddCallback (vScrollBar, XmNdragCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
553 XtAddCallback (vScrollBar, XmNincrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
554 XtAddCallback (vScrollBar, XmNdecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
555 XtAddCallback (vScrollBar, XmNpageIncrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
556 XtAddCallback (vScrollBar, XmNpageDecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
557 XtAddCallback (vScrollBar, XmNtoTopCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
558 XtAddCallback (vScrollBar, XmNtoBottomCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
34636400 559
2d120f83
JS
560 XtVaSetValues (vScrollBar,
561 XmNincrement, 1,
562 XmNvalue, 0,
563 NULL);
34636400 564
2d120f83 565 m_vScrollBar = (WXWidget) vScrollBar;
a756f210 566 wxColour backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
2d120f83 567 DoChangeBackgroundColour(m_vScrollBar, backgroundColour, TRUE);
34636400 568
2d120f83 569 XtRealizeWidget(vScrollBar);
34636400 570
2d120f83
JS
571 XtVaSetValues((Widget) m_scrolledWindow,
572 XmNverticalScrollBar, (Widget) m_vScrollBar,
573 NULL);
34636400 574
2d120f83 575 m_vScroll = TRUE;
311227c3
MB
576
577 wxAddWindowToTable( vScrollBar, this );
2d120f83 578 }
34636400 579
2d120f83 580 XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_ANY, NULL);
88150e60 581}
34636400 582
af0bb3b1 583void wxWindow::DestroyScrollbar(wxOrientation orientation)
88150e60 584{
34636400
VZ
585 wxCHECK_RET( m_drawingArea, "this window can't have scrollbars" );
586
2d120f83
JS
587 XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_NONE, NULL);
588 // Add scrollbars if required
589 if (orientation == wxHORIZONTAL)
590 {
591 if (m_hScrollBar)
592 {
311227c3 593 wxDeleteWindowFromTable((Widget)m_hScrollBar);
2d120f83
JS
594 XtDestroyWidget((Widget) m_hScrollBar);
595 }
596 m_hScrollBar = (WXWidget) 0;
597 m_hScroll = FALSE;
34636400 598
2d120f83
JS
599 XtVaSetValues((Widget) m_scrolledWindow,
600 XmNhorizontalScrollBar, (Widget) 0,
601 NULL);
34636400 602
2d120f83 603 }
34636400 604
2d120f83
JS
605 if (orientation == wxVERTICAL)
606 {
607 if (m_vScrollBar)
608 {
311227c3 609 wxDeleteWindowFromTable((Widget)m_vScrollBar);
2d120f83
JS
610 XtDestroyWidget((Widget) m_vScrollBar);
611 }
612 m_vScrollBar = (WXWidget) 0;
a059bcd2 613 m_vScroll = FALSE;
34636400 614
2d120f83
JS
615 XtVaSetValues((Widget) m_scrolledWindow,
616 XmNverticalScrollBar, (Widget) 0,
617 NULL);
34636400 618
2d120f83
JS
619 }
620 XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_ANY, NULL);
4bb6408c
JS
621}
622
34636400
VZ
623// ---------------------------------------------------------------------------
624// basic operations
625// ---------------------------------------------------------------------------
626
4bb6408c
JS
627void wxWindow::SetFocus()
628{
34636400
VZ
629 Widget wMain = (Widget) GetMainWidget();
630 XmProcessTraversal(wMain, XmTRAVERSE_CURRENT);
2d120f83 631 XmProcessTraversal((Widget) GetMainWidget(), XmTRAVERSE_CURRENT);
4bb6408c
JS
632}
633
34636400 634// Get the window with the focus
af0bb3b1 635wxWindow *wxWindowBase::FindFocus()
4bb6408c 636{
34636400
VZ
637 // TODO Problems:
638 // (1) Can there be multiple focussed widgets in an application?
639 // In which case we need to find the top-level window that's
640 // currently active.
641 // (2) The widget with the focus may not be in the widget table
642 // depending on which widgets I put in the table
643 wxWindow *winFocus = (wxWindow *)NULL;
644 for ( wxWindowList::Node *node = wxTopLevelWindows.GetFirst();
645 node;
646 node = node->GetNext() )
2d120f83 647 {
34636400
VZ
648 wxWindow *win = node->GetData();
649
650 Widget w = XmGetFocusWidget ((Widget) win->GetTopWidget());
651
652 if (w != (Widget) NULL)
653 {
654 winFocus = wxGetWindowFromTable(w);
655 if ( winFocus )
656 break;
657 }
2d120f83 658 }
4bb6408c 659
34636400 660 return winFocus;
4bb6408c
JS
661}
662
af0bb3b1 663bool wxWindow::Enable(bool enable)
4bb6408c 664{
34636400
VZ
665 if ( !wxWindowBase::Enable(enable) )
666 return FALSE;
4bb6408c 667
af0bb3b1 668 Widget wMain = (Widget)GetMainWidget();
34636400
VZ
669 if ( wMain )
670 {
671 XtSetSensitive(wMain, enable);
672 XmUpdateDisplay(wMain);
673 }
674
675 return TRUE;
4bb6408c
JS
676}
677
34636400 678bool wxWindow::Show(bool show)
4bb6408c 679{
34636400
VZ
680 if ( !wxWindowBase::Show(show) )
681 return FALSE;
682
683 if (m_borderWidget || m_scrolledWindow)
2d120f83 684 {
34636400
VZ
685 MapOrUnmap(m_drawingArea, show);
686 MapOrUnmap(m_borderWidget ? m_borderWidget : m_scrolledWindow, show);
2d120f83
JS
687 }
688 else
34636400
VZ
689 {
690 if ( !MapOrUnmap(GetTopWidget(), show) )
691 MapOrUnmap(GetMainWidget(), show);
692 }
693
34636400
VZ
694 return TRUE;
695}
4bb6408c 696
34636400
VZ
697// Raise the window to the top of the Z order
698void wxWindow::Raise()
4bb6408c 699{
34636400
VZ
700 Widget wTop = (Widget) GetTopWidget();
701 Window window = XtWindow(wTop);
702 XRaiseWindow(XtDisplay(wTop), window);
4bb6408c
JS
703}
704
34636400
VZ
705// Lower the window to the bottom of the Z order
706void wxWindow::Lower()
707{
708 Widget wTop = (Widget) GetTopWidget();
709 Window window = XtWindow(wTop);
710 XLowerWindow(XtDisplay(wTop), window);
711}
4bb6408c 712
af0bb3b1 713void wxWindow::SetTitle(const wxString& title)
4bb6408c 714{
af0bb3b1 715 XtVaSetValues((Widget)GetMainWidget(), XmNtitle, title.c_str(), NULL);
4bb6408c
JS
716}
717
34636400 718wxString wxWindow::GetTitle() const
4bb6408c 719{
af0bb3b1
VZ
720 char *title;
721 XtVaGetValues((Widget)GetMainWidget(), XmNtitle, &title, NULL);
722
723 return wxString(title);
4bb6408c
JS
724}
725
4116c221 726void wxWindow::DoCaptureMouse()
4bb6408c 727{
9806a47c 728 g_captureWindow = this;
34636400 729 if ( m_winCaptured )
a4294b78 730 return;
34636400 731
af0bb3b1 732 Widget wMain = (Widget)GetMainWidget();
34636400
VZ
733 if ( wMain )
734 XtAddGrab(wMain, TRUE, FALSE);
735
736 m_winCaptured = TRUE;
4bb6408c
JS
737}
738
4116c221 739void wxWindow::DoReleaseMouse()
4bb6408c 740{
9806a47c 741 g_captureWindow = NULL;
34636400
VZ
742 if ( !m_winCaptured )
743 return;
744
af0bb3b1 745 Widget wMain = (Widget)GetMainWidget();
34636400
VZ
746 if ( wMain )
747 XtRemoveGrab(wMain);
748
749 m_winCaptured = FALSE;
4bb6408c
JS
750}
751
34636400 752bool wxWindow::SetFont(const wxFont& font)
4bb6408c 753{
34636400
VZ
754 if ( !wxWindowBase::SetFont(font) )
755 {
756 // nothing to do
757 return FALSE;
758 }
759
760 ChangeFont();
761
762 return TRUE;
4bb6408c
JS
763}
764
34636400 765bool wxWindow::SetCursor(const wxCursor& cursor)
4bb6408c 766{
34636400 767 if ( !wxWindowBase::SetCursor(cursor) )
2d120f83 768 {
34636400
VZ
769 // no change
770 return FALSE;
2d120f83 771 }
4bb6408c 772
f6bcfd97
BP
773 // wxASSERT_MSG( m_cursor.Ok(),
774 // wxT("cursor must be valid after call to the base version"));
775 wxCursor* cursor2 = NULL;
776 if (m_cursor.Ok())
777 cursor2 = & m_cursor;
778 else
779 cursor2 = wxSTANDARD_CURSOR;
4bb6408c 780
34636400 781 WXDisplay *dpy = GetXDisplay();
f6bcfd97 782 WXCursor x_cursor = cursor2->GetXCursor(dpy);
34636400
VZ
783
784 Widget w = (Widget) GetMainWidget();
785 Window win = XtWindow(w);
786 XDefineCursor((Display*) dpy, win, (Cursor) x_cursor);
af0bb3b1
VZ
787
788 return TRUE;
34636400
VZ
789}
790
791// Coordinates relative to the window
792void wxWindow::WarpPointer (int x, int y)
4bb6408c 793{
34636400
VZ
794 Widget wClient = (Widget)GetClientWidget();
795
796 XWarpPointer(XtDisplay(wClient), None, XtWindow(wClient), 0, 0, 0, 0, x, y);
4bb6408c
JS
797}
798
34636400
VZ
799// ---------------------------------------------------------------------------
800// scrolling stuff
801// ---------------------------------------------------------------------------
802
803int wxWindow::GetScrollPos(int orient) const
4bb6408c 804{
34636400
VZ
805 if (orient == wxHORIZONTAL)
806 return m_scrollPosX;
807 else
808 return m_scrollPosY;
809
810#if 0
811 Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar);
812 if (scrollBar)
2d120f83 813 {
34636400
VZ
814 int pos;
815 XtVaGetValues(scrollBar, XmNvalue, &pos, NULL);
816 return pos;
2d120f83 817 }
34636400
VZ
818 else
819 return 0;
820#endif // 0
2d120f83 821}
7fe7d506 822
34636400
VZ
823// This now returns the whole range, not just the number of positions that we
824// can scroll.
825int wxWindow::GetScrollRange(int orient) const
2d120f83 826{
af0bb3b1 827 Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
34636400
VZ
828 wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
829
c4cb3d0f
JS
830 int range = 0;
831 if (scrollBar)
832 XtVaGetValues(scrollBar, XmNmaximum, &range, NULL);
34636400 833 return range;
2d120f83 834}
4bb6408c 835
34636400 836int wxWindow::GetScrollThumb(int orient) const
4bb6408c 837{
af0bb3b1 838 Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
34636400
VZ
839 wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
840
841 int thumb;
842 XtVaGetValues(scrollBar, XmNsliderSize, &thumb, NULL);
843 return thumb;
4bb6408c
JS
844}
845
34636400 846void wxWindow::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
4bb6408c 847{
af0bb3b1 848 Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
34636400
VZ
849
850 if ( scrollBar )
4bb6408c 851 {
34636400 852 XtVaSetValues (scrollBar, XmNvalue, pos, NULL);
4bb6408c 853 }
34636400 854
af0bb3b1 855 SetInternalScrollPos((wxOrientation)orient, pos);
4bb6408c
JS
856}
857
34636400
VZ
858// New function that will replace some of the above.
859void wxWindow::SetScrollbar(int orient, int pos, int thumbVisible,
860 int range, bool WXUNUSED(refresh))
4bb6408c 861{
34636400
VZ
862 int oldW, oldH;
863 GetSize(& oldW, & oldH);
864
865 if (range == 0)
866 range = 1;
867 if (thumbVisible == 0)
868 thumbVisible = 1;
869
870 if (thumbVisible > range)
871 thumbVisible = range;
872
873 // Save the old state to see if it changed
af0bb3b1 874 WXWidget oldScrollBar = GetScrollbar((wxOrientation)orient);
34636400
VZ
875
876 if (orient == wxHORIZONTAL)
50414e24 877 {
34636400 878 if (thumbVisible == range)
2d120f83 879 {
34636400
VZ
880 if (m_hScrollBar)
881 DestroyScrollbar(wxHORIZONTAL);
2d120f83
JS
882 }
883 else
884 {
34636400
VZ
885 if (!m_hScrollBar)
886 CreateScrollbar(wxHORIZONTAL);
2d120f83 887 }
50414e24 888 }
34636400 889 if (orient == wxVERTICAL)
50414e24 890 {
34636400 891 if (thumbVisible == range)
2d120f83 892 {
34636400
VZ
893 if (m_vScrollBar)
894 DestroyScrollbar(wxVERTICAL);
2d120f83
JS
895 }
896 else
897 {
34636400
VZ
898 if (!m_vScrollBar)
899 CreateScrollbar(wxVERTICAL);
2d120f83 900 }
50414e24 901 }
af0bb3b1 902 WXWidget newScrollBar = GetScrollbar((wxOrientation)orient);
4bb6408c 903
88150e60 904 if (oldScrollBar != newScrollBar)
28ab302b 905 {
34636400 906 // This is important! Without it, scrollbars misbehave badly.
2d120f83
JS
907 XtUnrealizeWidget((Widget) m_scrolledWindow);
908 XmScrolledWindowSetAreas ((Widget) m_scrolledWindow, (Widget) m_hScrollBar, (Widget) m_vScrollBar, (Widget) m_drawingArea);
909 XtRealizeWidget((Widget) m_scrolledWindow);
910 XtManageChild((Widget) m_scrolledWindow);
28ab302b 911 }
34636400 912
88150e60 913 if (newScrollBar)
34636400 914 {
2d120f83
JS
915 XtVaSetValues((Widget) newScrollBar,
916 XmNvalue, pos,
917 XmNminimum, 0,
918 XmNmaximum, range,
919 XmNsliderSize, thumbVisible,
920 NULL);
34636400
VZ
921 }
922
af0bb3b1 923 SetInternalScrollPos((wxOrientation)orient, pos);
34636400 924
88150e60
JS
925 int newW, newH;
926 GetSize(& newW, & newH);
34636400 927
88150e60
JS
928 // Adjusting scrollbars can resize the canvas accidentally
929 if (newW != oldW || newH != oldH)
930 SetSize(-1, -1, oldW, oldH);
4bb6408c
JS
931}
932
933// Does a physical scroll
16e93305 934void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
4bb6408c 935{
2d120f83
JS
936 int x, y, w, h;
937 if (rect)
938 {
939 // Use specified rectangle
940 x = rect->x; y = rect->y; w = rect->width; h = rect->height;
941 }
942 else
943 {
944 // Use whole client area
945 x = 0; y = 0;
946 GetClientSize(& w, & h);
947 }
34636400
VZ
948
949 int x1 = (dx >= 0) ? x : x - dx;
2d120f83
JS
950 int y1 = (dy >= 0) ? y : y - dy;
951 int w1 = w - abs(dx);
952 int h1 = h - abs(dy);
953 int x2 = (dx >= 0) ? x + dx : x;
954 int y2 = (dy >= 0) ? y + dy : y;
34636400 955
2d120f83 956 wxClientDC dc(this);
34636400 957
2d120f83 958 dc.SetLogicalFunction (wxCOPY);
34636400 959
2d120f83
JS
960 Widget widget = (Widget) GetMainWidget();
961 Window window = XtWindow(widget);
962 Display* display = XtDisplay(widget);
34636400
VZ
963
964 XCopyArea(display, window, window, (GC) dc.GetGC(),
965 x1, y1, w1, h1, x2, y2);
966
2d120f83
JS
967 dc.SetAutoSetting(TRUE);
968 wxBrush brush(GetBackgroundColour(), wxSOLID);
34636400
VZ
969 dc.SetBrush(brush); // FIXME: needed?
970
fc7ca9b3
MB
971 wxWindowList::Node *cnode = m_children.GetFirst();
972 while (cnode)
973 {
974 wxWindow *child = cnode->GetData();
975 int sx = 0;
976 int sy = 0;
977 child->GetSize( &sx, &sy );
978 wxPoint pos( child->GetPosition() );
979 child->SetSize( pos.x + dx, pos.y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
980 cnode = cnode->GetNext();
981 }
982
34636400
VZ
983 // We'll add rectangles to the list of update rectangles according to which
984 // bits we've exposed.
2d120f83 985 wxList updateRects;
34636400 986
2d120f83
JS
987 if (dx > 0)
988 {
989 wxRect *rect = new wxRect;
990 rect->x = x;
991 rect->y = y;
992 rect->width = dx;
993 rect->height = h;
34636400 994
2d120f83
JS
995 XFillRectangle(display, window,
996 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
34636400 997
2d120f83
JS
998 rect->x = rect->x;
999 rect->y = rect->y;
1000 rect->width = rect->width;
1001 rect->height = rect->height;
34636400 1002
2d120f83
JS
1003 updateRects.Append((wxObject*) rect);
1004 }
1005 else if (dx < 0)
1006 {
1007 wxRect *rect = new wxRect;
34636400 1008
2d120f83
JS
1009 rect->x = x + w + dx;
1010 rect->y = y;
1011 rect->width = -dx;
1012 rect->height = h;
34636400 1013
2d120f83
JS
1014 XFillRectangle(display, window,
1015 (GC) dc.GetGC(), rect->x, rect->y, rect->width,
1016 rect->height);
34636400 1017
2d120f83
JS
1018 rect->x = rect->x;
1019 rect->y = rect->y;
1020 rect->width = rect->width;
1021 rect->height = rect->height;
34636400 1022
2d120f83
JS
1023 updateRects.Append((wxObject*) rect);
1024 }
1025 if (dy > 0)
1026 {
1027 wxRect *rect = new wxRect;
34636400 1028
2d120f83
JS
1029 rect->x = x;
1030 rect->y = y;
1031 rect->width = w;
1032 rect->height = dy;
34636400 1033
2d120f83
JS
1034 XFillRectangle(display, window,
1035 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
34636400 1036
2d120f83
JS
1037 rect->x = rect->x;
1038 rect->y = rect->y;
1039 rect->width = rect->width;
1040 rect->height = rect->height;
34636400 1041
2d120f83
JS
1042 updateRects.Append((wxObject*) rect);
1043 }
1044 else if (dy < 0)
1045 {
1046 wxRect *rect = new wxRect;
34636400 1047
2d120f83
JS
1048 rect->x = x;
1049 rect->y = y + h + dy;
1050 rect->width = w;
1051 rect->height = -dy;
34636400 1052
2d120f83
JS
1053 XFillRectangle(display, window,
1054 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
34636400 1055
2d120f83
JS
1056 rect->x = rect->x;
1057 rect->y = rect->y;
1058 rect->width = rect->width;
1059 rect->height = rect->height;
34636400 1060
2d120f83
JS
1061 updateRects.Append((wxObject*) rect);
1062 }
1063 dc.SetBrush(wxNullBrush);
34636400 1064
2d120f83 1065 // Now send expose events
34636400 1066
1bc822df 1067 wxList::Node* node = updateRects.GetFirst();
2d120f83
JS
1068 while (node)
1069 {
1bc822df 1070 wxRect* rect = (wxRect*) node->GetData();
2d120f83 1071 XExposeEvent event;
34636400 1072
2d120f83
JS
1073 event.type = Expose;
1074 event.display = display;
1075 event.send_event = True;
1076 event.window = window;
34636400 1077
2d120f83
JS
1078 event.x = rect->x;
1079 event.y = rect->y;
1080 event.width = rect->width;
1081 event.height = rect->height;
34636400 1082
2d120f83 1083 event.count = 0;
34636400 1084
2d120f83 1085 XSendEvent(display, window, False, ExposureMask, (XEvent *)&event);
34636400 1086
1bc822df 1087 node = node->GetNext();
34636400 1088
2d120f83 1089 }
34636400 1090
2d120f83 1091 // Delete the update rects
1bc822df 1092 node = updateRects.GetFirst();
2d120f83
JS
1093 while (node)
1094 {
1bc822df 1095 wxRect* rect = (wxRect*) node->GetData();
2d120f83 1096 delete rect;
1bc822df 1097 node = node->GetNext();
2d120f83 1098 }
a91b47e8
JS
1099
1100 XmUpdateDisplay((Widget) GetMainWidget());
4bb6408c
JS
1101}
1102
34636400
VZ
1103// ---------------------------------------------------------------------------
1104// drag and drop
1105// ---------------------------------------------------------------------------
4ce81a75 1106
34636400 1107#if wxUSE_DRAG_AND_DROP
4ce81a75 1108
34636400 1109void wxWindow::SetDropTarget(wxDropTarget * WXUNUSED(pDropTarget))
4ce81a75 1110{
34636400 1111 // TODO
4bb6408c
JS
1112}
1113
34636400
VZ
1114#endif
1115
1116// Old style file-manager drag&drop
1117void wxWindow::DragAcceptFiles(bool WXUNUSED(accept))
4bb6408c 1118{
34636400 1119 // TODO
4bb6408c
JS
1120}
1121
34636400
VZ
1122// ----------------------------------------------------------------------------
1123// tooltips
1124// ----------------------------------------------------------------------------
1125
1126#if wxUSE_TOOLTIPS
1127
1128void wxWindow::DoSetToolTip(wxToolTip * WXUNUSED(tooltip))
4bb6408c 1129{
34636400 1130 // TODO
4bb6408c
JS
1131}
1132
34636400
VZ
1133#endif // wxUSE_TOOLTIPS
1134
ee31c392
VZ
1135// ----------------------------------------------------------------------------
1136// popup menus
1137// ----------------------------------------------------------------------------
1138
7e1bcfa8
MB
1139#if wxUSE_MENUS
1140
ee31c392
VZ
1141bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
1142{
1143 Widget widget = (Widget) GetMainWidget();
1144
1145 /* The menuId field seems to be usused, so we'll use it to
1146 indicate whether a menu is popped up or not:
1147 0: Not currently created as a popup
1148 -1: Created as a popup, but not active
1149 1: Active popup.
1150 */
1151
1152 if (menu->GetParent() && (menu->GetId() != -1))
1153 return FALSE;
1154
7e1bcfa8
MB
1155 if (menu->GetMainWidget())
1156 {
ee31c392
VZ
1157 menu->DestroyMenu(TRUE);
1158 }
1159
1160 menu->SetId(1); /* Mark as popped-up */
1161 menu->CreateMenu(NULL, widget, menu);
1162 menu->SetInvokingWindow(this);
1163
1164 menu->UpdateUI();
1165
1166 // menu->SetParent(parent);
1167 // parent->children->Append(menu); // Store menu for later deletion
1168
1169 Widget menuWidget = (Widget) menu->GetMainWidget();
1170
1171 int rootX = 0;
1172 int rootY = 0;
1173
1174 int deviceX = x;
1175 int deviceY = y;
1176 /*
1177 if (this->IsKindOf(CLASSINFO(wxCanvas)))
1178 {
1179 wxCanvas *canvas = (wxCanvas *) this;
1180 deviceX = canvas->GetDC ()->LogicalToDeviceX (x);
1181 deviceY = canvas->GetDC ()->LogicalToDeviceY (y);
1182 }
1183 */
1184
1185 Display *display = XtDisplay (widget);
1186 Window rootWindow = RootWindowOfScreen (XtScreen((Widget)widget));
1187 Window thisWindow = XtWindow (widget);
1188 Window childWindow;
1189 XTranslateCoordinates (display, thisWindow, rootWindow, (int) deviceX, (int) deviceY,
1190 &rootX, &rootY, &childWindow);
1191
1192 XButtonPressedEvent event;
1193 event.type = ButtonPress;
1194 event.button = 1;
1195
1196 event.x = deviceX;
1197 event.y = deviceY;
1198
1199 event.x_root = rootX;
1200 event.y_root = rootY;
1201
1202 XmMenuPosition (menuWidget, &event);
1203 XtManageChild (menuWidget);
1204
2b5f62a0 1205 // The ID of a pop-up menu is 1 when active, and is set to 0 by the
e41e1385 1206 // idle-time destroy routine.
2b5f62a0 1207 // Waiting until this ID changes causes this function to block until
e41e1385
JS
1208 // the menu has been dismissed and the widgets cleaned up.
1209 // In other words, once this routine returns, it is safe to delete
1210 // the menu object.
1211 // Ian Brown <ian.brown@printsoft.de>
e41e1385 1212
7e1bcfa8 1213 wxEventLoop evtLoop;
e41e1385 1214
7e1bcfa8
MB
1215 while (menu->GetId() == 1)
1216 {
1217 wxDoEventLoopIteration( evtLoop );
e41e1385 1218 }
7e1bcfa8 1219
ee31c392
VZ
1220 return TRUE;
1221}
1222
7e1bcfa8
MB
1223#endif
1224
34636400
VZ
1225// ---------------------------------------------------------------------------
1226// moving and resizing
1227// ---------------------------------------------------------------------------
4bb6408c 1228
34636400 1229bool wxWindow::PreResize()
4bb6408c 1230{
2d120f83 1231 return TRUE;
4bb6408c
JS
1232}
1233
34636400 1234// Get total size
af0bb3b1 1235void wxWindow::DoGetSize(int *x, int *y) const
4bb6408c 1236{
fc7ca9b3
MB
1237 Widget widget = (Widget)( !m_drawingArea ? GetTopWidget() :
1238 ( m_borderWidget ? m_borderWidget :
1239 m_scrolledWindow ? m_scrolledWindow :
1240 m_drawingArea ) );
34636400 1241 Dimension xx, yy;
fc7ca9b3
MB
1242
1243 XtVaGetValues( widget,
1244 XmNwidth, &xx,
1245 XmNheight, &yy,
1246 NULL );
1247 if(x) *x = xx;
1248 if(y) *y = yy;
4bb6408c
JS
1249}
1250
af0bb3b1 1251void wxWindow::DoGetPosition(int *x, int *y) const
4bb6408c 1252{
fc7ca9b3
MB
1253 Widget widget = (Widget)
1254 ( m_drawingArea ?
1255 ( m_borderWidget ? m_borderWidget : m_scrolledWindow ) :
1256 GetTopWidget() );
1257
34636400
VZ
1258 Position xx, yy;
1259 XtVaGetValues(widget, XmNx, &xx, XmNy, &yy, NULL);
b59bf2db 1260
34636400
VZ
1261 // We may be faking the client origin. So a window that's really at (0, 30)
1262 // may appear (to wxWin apps) to be at (0, 0).
1263 if (GetParent())
b59bf2db 1264 {
34636400
VZ
1265 wxPoint pt(GetParent()->GetClientAreaOrigin());
1266 xx -= pt.x;
1267 yy -= pt.y;
b59bf2db 1268 }
34636400 1269
fc7ca9b3
MB
1270 if(x) *x = xx;
1271 if(y) *y = yy;
4bb6408c
JS
1272}
1273
af0bb3b1 1274void wxWindow::DoScreenToClient(int *x, int *y) const
4bb6408c 1275{
34636400
VZ
1276 Widget widget = (Widget) GetClientWidget();
1277 Display *display = XtDisplay((Widget) GetMainWidget());
1278 Window rootWindow = RootWindowOfScreen(XtScreen(widget));
1279 Window thisWindow = XtWindow(widget);
1280
1281 Window childWindow;
1282 int xx = *x;
1283 int yy = *y;
1284 XTranslateCoordinates(display, rootWindow, thisWindow, xx, yy, x, y, &childWindow);
4bb6408c
JS
1285}
1286
af0bb3b1 1287void wxWindow::DoClientToScreen(int *x, int *y) const
4bb6408c 1288{
34636400
VZ
1289 Widget widget = (Widget) GetClientWidget();
1290 Display *display = XtDisplay(widget);
1291 Window rootWindow = RootWindowOfScreen(XtScreen(widget));
1292 Window thisWindow = XtWindow(widget);
1293
1294 Window childWindow;
1295 int xx = *x;
1296 int yy = *y;
1297 XTranslateCoordinates(display, thisWindow, rootWindow, xx, yy, x, y, &childWindow);
4bb6408c
JS
1298}
1299
34636400
VZ
1300
1301// Get size *available for subwindows* i.e. excluding menu bar etc.
af0bb3b1 1302void wxWindow::DoGetClientSize(int *x, int *y) const
4fabb575 1303{
34636400
VZ
1304 Widget widget = (Widget) GetClientWidget();
1305 Dimension xx, yy;
1306 XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL);
f6fb552e 1307 if(x) *x = xx; if(y) *y = yy;
4fabb575
JS
1308}
1309
34636400 1310void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags)
37c997b4
MB
1311{
1312 DoSetSizeIntr(x, y, width, height, sizeFlags, FALSE);
1313}
1314
1315void wxWindow::DoSetSizeIntr(int x, int y, int width, int height,
1316 int sizeFlags, bool fromCtor)
4bb6408c 1317{
34636400 1318 // A bit of optimization to help sort out the flickers.
bf5c9d34 1319 int oldX = -1, oldY = -1, oldW = -1, oldH = -1;
37c997b4
MB
1320 if( !fromCtor )
1321 {
1322 GetSize(& oldW, & oldH);
1323 GetPosition(& oldX, & oldY);
1324 }
34636400 1325
9d9b7755
VZ
1326 if ( !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
1327 {
1328 if ( x == -1 )
1329 x = oldX;
1330 if ( y == -1 )
1331 y = oldY;
1332 }
34636400 1333
fc7ca9b3 1334 wxSize size(-1, -1);
7e1bcfa8 1335 if ( width <= 0 )
fc7ca9b3
MB
1336 {
1337 if ( sizeFlags & wxSIZE_AUTO_WIDTH && !fromCtor )
1338 {
1339 size = DoGetBestSize();
1340 width = size.x;
1341 }
1342 else
1343 {
1344 width = oldW;
1345 }
1346 }
34636400 1347
fc7ca9b3 1348 if ( height == -1 )
02800301 1349 {
fc7ca9b3
MB
1350 if( sizeFlags & wxSIZE_AUTO_HEIGHT && !fromCtor )
1351 {
1352 if( size.x == -1 ) size = DoGetBestSize();
1353 height = size.y;
1354 }
1355 else
1356 {
1357 height = oldH;
1358 }
34636400
VZ
1359 }
1360
fc7ca9b3
MB
1361 if ( x != oldX || y != oldY || width != oldW || height != oldH
1362 || !wxNoOptimize::CanOptimize() )
34636400 1363 {
9d9b7755
VZ
1364 if (m_drawingArea)
1365 {
fc7ca9b3
MB
1366 int flags = 0;
1367
1368 if (x > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
1369 flags |= wxMOVE_X;
1370
1371 if (y > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
1372 flags |= wxMOVE_Y;
1373
1374 if (width > 0)
1375 flags |= wxMOVE_WIDTH;
1376
1377 if (height > 0)
1378 flags |= wxMOVE_HEIGHT;
1379
1380 int xx = x; int yy = y;
1381 AdjustForParentClientOrigin(xx, yy, sizeFlags);
1382 if( !fromCtor )
1383 DoMoveWindow( xx, yy, width, height );
1384 else
1385 DoMoveWindowIntr( xx, yy, width, height, flags );
1386
9d9b7755
VZ
1387 return;
1388 }
34636400 1389
9d9b7755
VZ
1390 Widget widget = (Widget) GetTopWidget();
1391 if (!widget)
1392 return;
34636400 1393
9d9b7755
VZ
1394 bool managed = XtIsManaged( widget );
1395 if (managed)
1396 XtUnmanageChild(widget);
34636400 1397
9d9b7755
VZ
1398 int xx = x;
1399 int yy = y;
1400 AdjustForParentClientOrigin(xx, yy, sizeFlags);
1401
1402 DoMoveWindow(xx, yy, width, height);
34636400 1403
9d9b7755
VZ
1404 if (managed)
1405 XtManageChild(widget);
9d9b7755 1406 }
4bb6408c
JS
1407}
1408
34636400 1409void wxWindow::DoSetClientSize(int width, int height)
4bb6408c 1410{
34636400 1411 if (m_drawingArea)
4bb6408c 1412 {
fc7ca9b3
MB
1413 Widget drawingArea = (Widget) m_drawingArea;
1414
1415 XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
1416
1417 if (width > -1)
1418 XtVaSetValues(drawingArea, XmNwidth, width, NULL);
1419 if (height > -1)
1420 XtVaSetValues(drawingArea, XmNheight, height, NULL);
1421
1422 XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
34636400 1423 return;
4bb6408c 1424 }
34636400
VZ
1425
1426 Widget widget = (Widget) GetTopWidget();
1427
1428 if (width > -1)
1429 XtVaSetValues(widget, XmNwidth, width, NULL);
1430 if (height > -1)
1431 XtVaSetValues(widget, XmNheight, height, NULL);
4bb6408c
JS
1432}
1433
34636400
VZ
1434// For implementation purposes - sometimes decorations make the client area
1435// smaller
1436wxPoint wxWindow::GetClientAreaOrigin() const
02e8b2f9 1437{
34636400 1438 return wxPoint(0, 0);
02e8b2f9
JS
1439}
1440
34636400 1441void wxWindow::SetSizeHints(int minW, int minH, int maxW, int maxH, int incW, int incH)
4bb6408c 1442{
34636400
VZ
1443 m_minWidth = minW;
1444 m_minHeight = minH;
1445 m_maxWidth = maxW;
1446 m_maxHeight = maxH;
1447
1448 wxFrame *frame = wxDynamicCast(this, wxFrame);
1449 if ( !frame )
2d120f83 1450 {
34636400
VZ
1451 // TODO what about dialogs?
1452 return;
2d120f83 1453 }
4bb6408c 1454
34636400
VZ
1455 Widget widget = (Widget) frame->GetShellWidget();
1456
1457 if (minW > -1)
1458 XtVaSetValues(widget, XmNminWidth, minW, NULL);
1459 if (minH > -1)
1460 XtVaSetValues(widget, XmNminHeight, minH, NULL);
1461 if (maxW > -1)
1462 XtVaSetValues(widget, XmNmaxWidth, maxW, NULL);
1463 if (maxH > -1)
1464 XtVaSetValues(widget, XmNmaxHeight, maxH, NULL);
1465 if (incW > -1)
1466 XtVaSetValues(widget, XmNwidthInc, incW, NULL);
1467 if (incH > -1)
1468 XtVaSetValues(widget, XmNheightInc, incH, NULL);
4bb6408c
JS
1469}
1470
fc7ca9b3
MB
1471void wxWindow::DoMoveWindowIntr(int xx, int yy, int w, int h,
1472 int flags)
9d9b7755 1473{
37c997b4 1474 if (m_drawingArea)
fc7ca9b3
MB
1475 {
1476 Widget drawingArea = (Widget) m_drawingArea;
1477 Widget borderOrScrolled = m_borderWidget ?
1478 (Widget) m_borderWidget :
1479 (Widget) m_scrolledWindow;
1480
1481 bool managed = XtIsManaged(borderOrScrolled);
1482
1483 if (managed)
1484 XtUnmanageChild (borderOrScrolled);
1485 XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
1486
1487 if (flags & wxMOVE_X)
1488 XtVaSetValues (borderOrScrolled,
1489 XmNx, xx,
1490 NULL);
1491 if (flags & wxMOVE_Y)
1492 XtVaSetValues (borderOrScrolled,
1493 XmNy, yy,
1494 NULL);
1495
1496 if (flags & wxMOVE_WIDTH)
1497 {
1498 if (m_borderWidget)
1499 {
1500 XtVaSetValues ((Widget) m_borderWidget, XmNwidth, w, NULL);
1501 short thick, margin;
1502 XtVaGetValues ((Widget) m_borderWidget,
1503 XmNshadowThickness, &thick,
1504 XmNmarginWidth, &margin,
1505 NULL);
1506 w -= 2 * (thick + margin);
1507 }
37c997b4 1508
fc7ca9b3
MB
1509 XtVaSetValues ((Widget) m_scrolledWindow, XmNwidth, w, NULL);
1510 }
d9d3622e 1511
fc7ca9b3
MB
1512 if (flags & wxMOVE_HEIGHT)
1513 {
1514 if (m_borderWidget)
1515 {
1516 XtVaSetValues ((Widget) m_borderWidget, XmNheight, h, NULL);
1517 short thick, margin;
1518 XtVaGetValues ((Widget) m_borderWidget,
1519 XmNshadowThickness, &thick,
1520 XmNmarginHeight, &margin,
1521 NULL);
1522 h -= 2 * (thick + margin);
1523 }
1524
1525 XtVaSetValues ((Widget) m_scrolledWindow, XmNheight, h, NULL);
1526 }
1527
1528 if (managed)
1529 XtManageChild (borderOrScrolled);
1530 XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
1531 }
1532 else
1533 {
1534 if( w < 1 ) w = 1;
1535 if( h < 1 ) h = 1;
1536
1537 XtVaSetValues((Widget)GetTopWidget(),
1538 XmNx, xx,
1539 XmNy, yy,
1540 XmNwidth, w,
1541 XmNheight, h,
1542 NULL);
1543 }
1544}
1545
1546void wxWindow::DoMoveWindow(int x, int y, int width, int height)
1547{
1548 DoMoveWindowIntr (x, y, width, height,
1549 wxMOVE_X|wxMOVE_Y|wxMOVE_WIDTH|wxMOVE_HEIGHT);
9d9b7755
VZ
1550}
1551
34636400
VZ
1552// ---------------------------------------------------------------------------
1553// text metrics
1554// ---------------------------------------------------------------------------
1555
1556int wxWindow::GetCharHeight() const
4bb6408c 1557{
af0bb3b1 1558 wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
34636400 1559
af0bb3b1 1560 WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, GetXDisplay());
34636400
VZ
1561
1562 int direction, ascent, descent;
1563 XCharStruct overall;
1564 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1565 &descent, &overall);
1566
1567 // return (overall.ascent + overall.descent);
1568 return (ascent + descent);
4bb6408c
JS
1569}
1570
34636400 1571int wxWindow::GetCharWidth() const
4bb6408c 1572{
af0bb3b1 1573 wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
34636400 1574
af0bb3b1 1575 WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, GetXDisplay());
34636400
VZ
1576
1577 int direction, ascent, descent;
1578 XCharStruct overall;
1579 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1580 &descent, &overall);
1581
1582 return overall.width;
4bb6408c
JS
1583}
1584
34636400
VZ
1585void wxWindow::GetTextExtent(const wxString& string,
1586 int *x, int *y,
1587 int *descent, int *externalLeading,
1588 const wxFont *theFont) const
4bb6408c 1589{
34636400
VZ
1590 wxFont *fontToUse = (wxFont *)theFont;
1591 if (!fontToUse)
af0bb3b1 1592 fontToUse = (wxFont *) & m_font;
34636400 1593
af0bb3b1 1594 wxCHECK_RET( fontToUse->Ok(), "valid window font needed" );
8e877c19 1595
37c997b4 1596 WXFontStructPtr pFontStruct = fontToUse->GetFontStruct(1.0, GetXDisplay());
34636400
VZ
1597
1598 int direction, ascent, descent2;
1599 XCharStruct overall;
8e877c19 1600 int slen = string.Len();
34636400
VZ
1601
1602#if 0
1603 if (use16)
1604 XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
1605 &ascent, &descent2, &overall);
1606#endif
1607
1608 XTextExtents((XFontStruct*) pFontStruct, string, slen,
1609 &direction, &ascent, &descent2, &overall);
1610
1611 if ( x )
1612 *x = (overall.width);
1613 if ( y )
1614 *y = (ascent + descent2);
1615 if (descent)
1616 *descent = descent2;
1617 if (externalLeading)
1618 *externalLeading = 0;
8e877c19 1619
4bb6408c
JS
1620}
1621
34636400
VZ
1622// ----------------------------------------------------------------------------
1623// painting
1624// ----------------------------------------------------------------------------
4bb6408c 1625
34636400 1626void wxWindow::Refresh(bool eraseBack, const wxRect *rect)
4bb6408c 1627{
34636400
VZ
1628 m_needsRefresh = TRUE;
1629 Display *display = XtDisplay((Widget) GetMainWidget());
1630 Window thisWindow = XtWindow((Widget) GetMainWidget());
1631
1632 XExposeEvent dummyEvent;
1633 int width, height;
1634 GetSize(&width, &height);
1635
1636 dummyEvent.type = Expose;
1637 dummyEvent.display = display;
1638 dummyEvent.send_event = True;
1639 dummyEvent.window = thisWindow;
1640 if (rect)
2d120f83 1641 {
34636400
VZ
1642 dummyEvent.x = rect->x;
1643 dummyEvent.y = rect->y;
1644 dummyEvent.width = rect->width;
1645 dummyEvent.height = rect->height;
2d120f83
JS
1646 }
1647 else
1648 {
34636400
VZ
1649 dummyEvent.x = 0;
1650 dummyEvent.y = 0;
1651 dummyEvent.width = width;
1652 dummyEvent.height = height;
2d120f83 1653 }
34636400 1654 dummyEvent.count = 0;
4bb6408c 1655
34636400 1656 if (eraseBack)
2d120f83 1657 {
34636400
VZ
1658 wxClientDC dc(this);
1659 wxBrush backgroundBrush(GetBackgroundColour(), wxSOLID);
1660 dc.SetBackground(backgroundBrush);
1661 if (rect)
1662 dc.Clear(*rect);
1663 else
1664 dc.Clear();
2d120f83 1665 }
4bb6408c 1666
34636400 1667 XSendEvent(display, thisWindow, False, ExposureMask, (XEvent *)&dummyEvent);
4bb6408c
JS
1668}
1669
34636400 1670void wxWindow::Clear()
4bb6408c 1671{
34636400
VZ
1672 wxClientDC dc(this);
1673 wxBrush brush(GetBackgroundColour(), wxSOLID);
1674 dc.SetBackground(brush);
1675 dc.Clear();
4bb6408c
JS
1676}
1677
34636400 1678void wxWindow::ClearUpdateRects()
4bb6408c 1679{
af0bb3b1 1680 wxRectList::Node* node = m_updateRects.GetFirst();
2d120f83
JS
1681 while (node)
1682 {
af0bb3b1 1683 wxRect* rect = node->GetData();
34636400 1684 delete rect;
af0bb3b1 1685 node = node->GetNext();
2d120f83 1686 }
af0bb3b1 1687
34636400 1688 m_updateRects.Clear();
4bb6408c
JS
1689}
1690
34636400 1691void wxWindow::DoPaint()
4bb6408c 1692{
34636400
VZ
1693 //TODO : make a temporary gc so we can do the XCopyArea below
1694 if (m_backingPixmap && !m_needsRefresh)
4bb6408c 1695 {
34636400 1696 wxPaintDC dc(this);
4bb6408c 1697
34636400 1698 GC tempGC = (GC) dc.GetBackingGC();
4bb6408c 1699
34636400 1700 Widget widget = (Widget) GetMainWidget();
4bb6408c 1701
34636400
VZ
1702 int scrollPosX = 0;
1703 int scrollPosY = 0;
4bb6408c 1704
34636400
VZ
1705 // We have to test whether it's a wxScrolledWindow (hack!) because
1706 // otherwise we don't know how many pixels have been scrolled. We might
1707 // solve this in the future by defining virtual wxWindow functions to get
1708 // the scroll position in pixels. Or, each kind of scrolled window has to
1709 // implement backing stores itself, using generic wxWindows code.
1710 wxScrolledWindow* scrolledWindow = wxDynamicCast(this, wxScrolledWindow);
1711 if ( scrolledWindow )
1712 {
1713 int x, y;
1714 scrolledWindow->CalcScrolledPosition(0, 0, &x, &y);
1715
1716 scrollPosX = - x;
1717 scrollPosY = - y;
1718 }
1719
1720 // TODO: This could be optimized further by only copying the areas in the
1721 // current update region.
1722
1723 // Only blit the part visible in the client area. The backing pixmap
1724 // always starts at 0, 0 but we may be looking at only a portion of it.
1725 wxSize clientArea = GetClientSize();
1726 int toBlitX = m_pixmapWidth - scrollPosX;
1727 int toBlitY = m_pixmapHeight - scrollPosY;
1728
1729 // Copy whichever is samller, the amount of pixmap we have to copy,
1730 // or the size of the client area.
1731 toBlitX = wxMin(toBlitX, clientArea.x);
1732 toBlitY = wxMin(toBlitY, clientArea.y);
1733
1734 // Make sure we're not negative
1735 toBlitX = wxMax(0, toBlitX);
1736 toBlitY = wxMax(0, toBlitY);
1737
1738 XCopyArea
1739 (
1740 XtDisplay(widget),
1741 (Pixmap) m_backingPixmap,
1742 XtWindow (widget),
1743 tempGC,
1744 scrollPosX, scrollPosY, // Start at the scroll position
1745 toBlitX, toBlitY, // How much of the pixmap to copy
1746 0, 0 // Destination
1747 );
1748 }
1749 else
4bb6408c 1750 {
fc7ca9b3 1751 wxWindowDC dc(this);
34636400 1752 // Set an erase event first
fc7ca9b3 1753 wxEraseEvent eraseEvent(GetId(), &dc);
34636400
VZ
1754 eraseEvent.SetEventObject(this);
1755 GetEventHandler()->ProcessEvent(eraseEvent);
1756
1757 wxPaintEvent event(GetId());
1758 event.SetEventObject(this);
1759 GetEventHandler()->ProcessEvent(event);
1760
1761 m_needsRefresh = FALSE;
4bb6408c 1762 }
4bb6408c
JS
1763}
1764
34636400
VZ
1765// ----------------------------------------------------------------------------
1766// event handlers
1767// ----------------------------------------------------------------------------
1768
1769// Responds to colour changes: passes event on to children.
1770void wxWindow::OnSysColourChanged(wxSysColourChangedEvent& event)
4bb6408c 1771{
34636400
VZ
1772 wxWindowList::Node *node = GetChildren().GetFirst();
1773 while ( node )
4bb6408c 1774 {
34636400
VZ
1775 // Only propagate to non-top-level windows
1776 wxWindow *win = node->GetData();
1777 if ( win->GetParent() )
2d120f83 1778 {
34636400
VZ
1779 wxSysColourChangedEvent event2;
1780 event.m_eventObject = win;
1781 win->GetEventHandler()->ProcessEvent(event2);
2d120f83 1782 }
4bb6408c 1783
34636400 1784 node = node->GetNext();
2d120f83 1785 }
4bb6408c
JS
1786}
1787
af111fc3 1788void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event))
4bb6408c 1789{
34636400
VZ
1790 // This calls the UI-update mechanism (querying windows for
1791 // menu/toolbar/control state information)
1792 UpdateWindowUI();
4bb6408c
JS
1793}
1794
34636400
VZ
1795// ----------------------------------------------------------------------------
1796// accelerators
1797// ----------------------------------------------------------------------------
4bb6408c 1798
34636400 1799bool wxWindow::ProcessAccelerator(wxKeyEvent& event)
4bb6408c 1800{
7e1bcfa8 1801#if wxUSE_ACCEL
34636400
VZ
1802 if (!m_acceleratorTable.Ok())
1803 return FALSE;
4bb6408c 1804
34636400
VZ
1805 int count = m_acceleratorTable.GetCount();
1806 wxAcceleratorEntry* entries = m_acceleratorTable.GetEntries();
1807 int i;
1808 for (i = 0; i < count; i++)
2d120f83 1809 {
34636400
VZ
1810 wxAcceleratorEntry* entry = & (entries[i]);
1811 if (entry->MatchesEvent(event))
1812 {
f6045f99 1813 // Bingo, we have a match. Now find a control that matches the
2b5f62a0 1814 // entry command id.
4bb6408c 1815
34636400
VZ
1816 // Need to go up to the top of the window hierarchy, since it might
1817 // be e.g. a menu item
1818 wxWindow* parent = this;
1819 while ( parent && !parent->IsTopLevel() )
1820 parent = parent->GetParent();
4bb6408c 1821
34636400
VZ
1822 if (!parent)
1823 return FALSE;
4bb6408c 1824
34636400
VZ
1825 wxFrame* frame = wxDynamicCast(parent, wxFrame);
1826 if ( frame )
1827 {
7e1bcfa8 1828#if wxUSE_MENUS
34636400
VZ
1829 // Try for a menu command
1830 if (frame->GetMenuBar())
1831 {
c71830c3 1832 wxMenuItem* item = frame->GetMenuBar()->FindItem(entry->GetCommand());
34636400
VZ
1833 if (item)
1834 {
1835 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, entry->GetCommand());
1836 commandEvent.SetEventObject(frame);
4bb6408c 1837
34636400
VZ
1838 // If ProcessEvent returns TRUE (it was handled), then
1839 // the calling code will skip the event handling.
1840 return frame->GetEventHandler()->ProcessEvent(commandEvent);
1841 }
1842 }
7e1bcfa8 1843#endif
34636400 1844 }
3dd4e4e0 1845
34636400
VZ
1846 // Find a child matching the command id
1847 wxWindow* child = parent->FindWindow(entry->GetCommand());
3dd4e4e0 1848
34636400
VZ
1849 // No such child
1850 if (!child)
1851 return FALSE;
3dd4e4e0 1852
34636400
VZ
1853 // Now we process those kinds of windows that we can.
1854 // For now, only buttons.
1855 if ( wxDynamicCast(child, wxButton) )
1856 {
1857 wxCommandEvent commandEvent (wxEVT_COMMAND_BUTTON_CLICKED, child->GetId());
1858 commandEvent.SetEventObject(child);
1859 return child->GetEventHandler()->ProcessEvent(commandEvent);
1860 }
3dd4e4e0 1861
34636400
VZ
1862 return FALSE;
1863 } // matches event
1864 }// for
7e1bcfa8 1865#endif
4bb6408c 1866
34636400
VZ
1867 // We didn't match the key event against an accelerator.
1868 return FALSE;
4bb6408c
JS
1869}
1870
34636400
VZ
1871// ============================================================================
1872// Motif-specific stuff from here on
1873// ============================================================================
1874
1875// ----------------------------------------------------------------------------
1876// function which maintain the global hash table mapping Widgets to wxWindows
1877// ----------------------------------------------------------------------------
1878
1879bool wxAddWindowToTable(Widget w, wxWindow *win)
4bb6408c 1880{
34636400 1881 wxWindow *oldItem = NULL;
33caefb3 1882 if ((oldItem = (wxWindow *)wxWidgetHashTable->Get ((long) w)))
2d120f83 1883 {
34636400
VZ
1884 wxLogDebug("Widget table clash: new widget is %ld, %s",
1885 (long)w, win->GetClassInfo()->GetClassName());
1886 return FALSE;
2d120f83 1887 }
4bb6408c 1888
33caefb3 1889 wxWidgetHashTable->Put((long) w, win);
4bb6408c 1890
1bc822df
MB
1891 wxLogTrace("widget", "Widget 0x%p <-> window %p (%s)",
1892 (WXWidget)w, win, win->GetClassInfo()->GetClassName());
31528cd3 1893
34636400 1894 return TRUE;
4bb6408c
JS
1895}
1896
34636400 1897wxWindow *wxGetWindowFromTable(Widget w)
4bb6408c 1898{
33caefb3 1899 return (wxWindow *)wxWidgetHashTable->Get((long) w);
4bb6408c
JS
1900}
1901
34636400 1902void wxDeleteWindowFromTable(Widget w)
4bb6408c 1903{
fc7ca9b3
MB
1904 wxLogTrace("widget", "Widget 0x%p", (WXWidget)w);
1905
33caefb3 1906 wxWidgetHashTable->Delete((long)w);
4bb6408c
JS
1907}
1908
34636400
VZ
1909// ----------------------------------------------------------------------------
1910// add/remove window from the table
1911// ----------------------------------------------------------------------------
4bb6408c 1912
34636400 1913// Add to hash table, add event handler
af111fc3 1914bool wxWindow::AttachWidget (wxWindow* WXUNUSED(parent), WXWidget mainWidget,
34636400 1915 WXWidget formWidget, int x, int y, int width, int height)
4bb6408c 1916{
34636400
VZ
1917 wxAddWindowToTable((Widget) mainWidget, this);
1918 if (CanAddEventHandler())
1919 {
1920 XtAddEventHandler((Widget) mainWidget,
1921 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, // | KeyPressMask,
1922 False,
1923 wxPanelItemEventHandler,
1924 (XtPointer) this);
1925 }
4bb6408c 1926
34636400
VZ
1927 if (!formWidget)
1928 {
1929 XtTranslations ptr;
1930 XtOverrideTranslations ((Widget) mainWidget,
1931 ptr = XtParseTranslationTable ("<Configure>: resize()"));
1932 XtFree ((char *) ptr);
1933 }
4bb6408c 1934
34636400
VZ
1935 // Some widgets have a parent form widget, e.g. wxRadioBox
1936 if (formWidget)
1937 {
1938 if (!wxAddWindowToTable((Widget) formWidget, this))
1939 return FALSE;
4bb6408c 1940
34636400
VZ
1941 XtTranslations ptr;
1942 XtOverrideTranslations ((Widget) formWidget,
1943 ptr = XtParseTranslationTable ("<Configure>: resize()"));
1944 XtFree ((char *) ptr);
1945 }
4bb6408c 1946
34636400
VZ
1947 if (x == -1)
1948 x = 0;
1949 if (y == -1)
1950 y = 0;
1951 SetSize (x, y, width, height);
4bb6408c 1952
34636400 1953 return TRUE;
4bb6408c
JS
1954}
1955
34636400
VZ
1956// Remove event handler, remove from hash table
1957bool wxWindow::DetachWidget(WXWidget widget)
4bb6408c 1958{
34636400 1959 if (CanAddEventHandler())
4bb6408c 1960 {
34636400
VZ
1961 XtRemoveEventHandler((Widget) widget,
1962 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, // | KeyPressMask,
1963 False,
1964 wxPanelItemEventHandler,
1965 (XtPointer)this);
4bb6408c 1966 }
4bb6408c 1967
34636400 1968 wxDeleteWindowFromTable((Widget) widget);
2d120f83 1969 return TRUE;
4bb6408c
JS
1970}
1971
34636400
VZ
1972// ----------------------------------------------------------------------------
1973// Motif-specific accessors
1974// ----------------------------------------------------------------------------
2d120f83 1975
34636400 1976// Get the underlying X window
4bb6408c
JS
1977WXWindow wxWindow::GetXWindow() const
1978{
af0bb3b1 1979 Widget wMain = (Widget)GetMainWidget();
34636400
VZ
1980 if ( wMain )
1981 return (WXWindow) XtWindow(wMain);
ad813b00
JS
1982 else
1983 return (WXWindow) 0;
4bb6408c
JS
1984}
1985
34636400 1986// Get the underlying X display
4bb6408c
JS
1987WXDisplay *wxWindow::GetXDisplay() const
1988{
af0bb3b1 1989 Widget wMain = (Widget)GetMainWidget();
34636400
VZ
1990 if ( wMain )
1991 return (WXDisplay*) XtDisplay(wMain);
ad813b00
JS
1992 else
1993 return (WXDisplay*) NULL;
4bb6408c
JS
1994}
1995
1996WXWidget wxWindow::GetMainWidget() const
1997{
50414e24 1998 if (m_drawingArea)
2d120f83 1999 return m_drawingArea;
50414e24 2000 else
2d120f83 2001 return m_mainWidget;
50414e24
JS
2002}
2003
2004WXWidget wxWindow::GetClientWidget() const
2005{
2006 if (m_drawingArea != (WXWidget) 0)
2007 return m_drawingArea;
2008 else
02e8b2f9
JS
2009 return GetMainWidget();
2010}
2011
2012WXWidget wxWindow::GetTopWidget() const
2013{
2014 return GetMainWidget();
4bb6408c
JS
2015}
2016
34636400
VZ
2017WXWidget wxWindow::GetLabelWidget() const
2018{
2019 return GetMainWidget();
2020}
2021
2022// ----------------------------------------------------------------------------
2023// Motif callbacks
2024// ----------------------------------------------------------------------------
2025
2026// All widgets should have this as their resize proc.
2027// OnSize sent to wxWindow via client data.
af111fc3 2028void wxWidgetResizeProc(Widget w, XConfigureEvent *WXUNUSED(event), String WXUNUSED(args)[], int *WXUNUSED(num_args))
34636400
VZ
2029{
2030 wxWindow *win = wxGetWindowFromTable(w);
2031 if (!win)
2032 return;
2033
2034 if (win->PreResize())
2035 {
2036 int width, height;
2037 win->GetSize(&width, &height);
2038 wxSizeEvent sizeEvent(wxSize(width, height), win->GetId());
2039 sizeEvent.SetEventObject(win);
2040 win->GetEventHandler()->ProcessEvent(sizeEvent);
2041 }
2042}
2043
2044static void wxCanvasRepaintProc(Widget drawingArea,
2045 XtPointer clientData,
2046 XmDrawingAreaCallbackStruct * cbs)
50414e24 2047{
34636400 2048 if (!wxGetWindowFromTable(drawingArea))
2d120f83 2049 return;
34636400 2050
50414e24 2051 XEvent * event = cbs->event;
55acd85e 2052 wxWindow * win = (wxWindow *) clientData;
34636400 2053
50414e24
JS
2054 switch (event->type)
2055 {
2d120f83 2056 case Expose:
55acd85e 2057 {
6970c7b9
MB
2058 win->AddUpdateRect(event->xexpose.x, event->xexpose.y,
2059 event->xexpose.width, event->xexpose.height);
2060
55acd85e
JS
2061 if (event -> xexpose.count == 0)
2062 {
a91b47e8 2063 win->DoPaint();
55acd85e
JS
2064 win->ClearUpdateRects();
2065 }
2066 break;
2067 }
50414e24 2068 }
50414e24
JS
2069}
2070
2071// Unable to deal with Enter/Leave without a separate EventHandler (Motif 1.1.4)
34636400 2072static void wxCanvasEnterLeave(Widget drawingArea,
af111fc3 2073 XtPointer WXUNUSED(clientData),
34636400 2074 XCrossingEvent * event)
50414e24 2075{
2d120f83
JS
2076 XmDrawingAreaCallbackStruct cbs;
2077 XEvent ev;
34636400 2078
2d120f83 2079 ((XCrossingEvent &) ev) = *event;
34636400 2080
2d120f83
JS
2081 cbs.reason = XmCR_INPUT;
2082 cbs.event = &ev;
34636400
VZ
2083
2084 wxCanvasInputEvent(drawingArea, (XtPointer) NULL, &cbs);
50414e24
JS
2085}
2086
2087// Fix to make it work under Motif 1.0 (!)
da494b40
MB
2088static void wxCanvasMotionEvent (Widget WXUNUSED(drawingArea),
2089 XButtonEvent *WXUNUSED(event))
50414e24 2090{
34636400 2091#if XmVersion <= 1000
2d120f83
JS
2092 XmDrawingAreaCallbackStruct cbs;
2093 XEvent ev;
34636400 2094
2d120f83
JS
2095 ev = *((XEvent *) event);
2096 cbs.reason = XmCR_INPUT;
2097 cbs.event = &ev;
34636400 2098
2d120f83 2099 wxCanvasInputEvent (drawingArea, (XtPointer) NULL, &cbs);
34636400 2100#endif // XmVersion <= 1000
50414e24
JS
2101}
2102
34636400 2103static void wxCanvasInputEvent(Widget drawingArea,
af111fc3 2104 XtPointer WXUNUSED(data),
34636400 2105 XmDrawingAreaCallbackStruct * cbs)
50414e24 2106{
34636400 2107 wxWindow *canvas = wxGetWindowFromTable(drawingArea);
2d120f83 2108 XEvent local_event;
34636400 2109
2d120f83 2110 if (canvas==NULL)
34636400
VZ
2111 return;
2112
2d120f83
JS
2113 if (cbs->reason != XmCR_INPUT)
2114 return;
34636400
VZ
2115
2116 local_event = *(cbs->event); // We must keep a copy!
2117
2d120f83 2118 switch (local_event.xany.type)
50414e24
JS
2119 {
2120 case EnterNotify:
2121 case LeaveNotify:
2122 case ButtonPress:
2123 case ButtonRelease:
2124 case MotionNotify:
2d120f83 2125 {
1e8abce5
MB
2126 // FIXME: most of this mouse event code is more or less
2127 // duplicated in wxTranslateMouseEvent
2128 //
2d120f83 2129 wxEventType eventType = wxEVT_NULL;
34636400 2130
2d120f83
JS
2131 if (local_event.xany.type == EnterNotify)
2132 {
2133 //if (local_event.xcrossing.mode!=NotifyNormal)
2134 // return ; // Ignore grab events
2135 eventType = wxEVT_ENTER_WINDOW;
2136 // canvas->GetEventHandler()->OnSetFocus();
2137 }
2138 else if (local_event.xany.type == LeaveNotify)
2139 {
1e8abce5 2140 //if (local_event.xcrossingr.mode!=NotifyNormal)
2d120f83
JS
2141 // return ; // Ignore grab events
2142 eventType = wxEVT_LEAVE_WINDOW;
2143 // canvas->GetEventHandler()->OnKillFocus();
2144 }
2145 else if (local_event.xany.type == MotionNotify)
2146 {
2147 eventType = wxEVT_MOTION;
2d120f83 2148 }
34636400 2149
2d120f83
JS
2150 else if (local_event.xany.type == ButtonPress)
2151 {
2152 if (local_event.xbutton.button == Button1)
2153 {
2154 eventType = wxEVT_LEFT_DOWN;
af0bb3b1 2155 canvas->SetButton1(TRUE);
2d120f83
JS
2156 }
2157 else if (local_event.xbutton.button == Button2)
2158 {
2159 eventType = wxEVT_MIDDLE_DOWN;
af0bb3b1 2160 canvas->SetButton2(TRUE);
2d120f83
JS
2161 }
2162 else if (local_event.xbutton.button == Button3)
2163 {
2164 eventType = wxEVT_RIGHT_DOWN;
af0bb3b1 2165 canvas->SetButton3(TRUE);
2d120f83
JS
2166 }
2167 }
2168 else if (local_event.xany.type == ButtonRelease)
2169 {
2170 if (local_event.xbutton.button == Button1)
2171 {
2172 eventType = wxEVT_LEFT_UP;
af0bb3b1 2173 canvas->SetButton1(FALSE);
2d120f83
JS
2174 }
2175 else if (local_event.xbutton.button == Button2)
2176 {
2177 eventType = wxEVT_MIDDLE_UP;
af0bb3b1 2178 canvas->SetButton2(FALSE);
2d120f83
JS
2179 }
2180 else if (local_event.xbutton.button == Button3)
2181 {
2182 eventType = wxEVT_RIGHT_UP;
af0bb3b1 2183 canvas->SetButton3(FALSE);
2d120f83
JS
2184 }
2185 }
34636400 2186
2d120f83 2187 wxMouseEvent wxevent (eventType);
34636400 2188
2d120f83 2189 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
34636400 2190 || (event_left_is_down (&local_event)
2d120f83
JS
2191 && (eventType != wxEVT_LEFT_UP)));
2192 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
34636400 2193 || (event_middle_is_down (&local_event)
2d120f83
JS
2194 && (eventType != wxEVT_MIDDLE_UP)));
2195 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
34636400 2196 || (event_right_is_down (&local_event)
2d120f83 2197 && (eventType != wxEVT_RIGHT_UP)));
34636400 2198
2d120f83
JS
2199 wxevent.m_shiftDown = local_event.xbutton.state & ShiftMask;
2200 wxevent.m_controlDown = local_event.xbutton.state & ControlMask;
2201 wxevent.m_altDown = local_event.xbutton.state & Mod3Mask;
2202 wxevent.m_metaDown = local_event.xbutton.state & Mod1Mask;
2203 wxevent.SetTimestamp(local_event.xbutton.time);
34636400 2204
a16a9bf3 2205 if ( eventType == wxEVT_MOTION )
1afe597e
VZ
2206 {
2207 if (local_event.xmotion.is_hint == NotifyHint)
2208 {
2209 Window root, child;
2210 Display *dpy = XtDisplay (drawingArea);
2211
2212 XQueryPointer (dpy, XtWindow (drawingArea),
2213 &root, &child,
2214 &local_event.xmotion.x_root,
2215 &local_event.xmotion.y_root,
2216 &local_event.xmotion.x,
2217 &local_event.xmotion.y,
2218 &local_event.xmotion.state);
2219 }
2220 else
2221 {
2222 }
2223 }
2224
2d120f83
JS
2225 // Now check if we need to translate this event into a double click
2226 if (TRUE) // canvas->doubleClickAllowed)
2227 {
2228 if (wxevent.ButtonDown())
2229 {
34636400
VZ
2230 long dclickTime = XtGetMultiClickTime((Display*) wxGetDisplay());
2231
2d120f83
JS
2232 // get button and time-stamp
2233 int button = 0;
af0bb3b1
VZ
2234 if (wxevent.LeftDown())
2235 button = 1;
2236 else if (wxevent.MiddleDown())
2237 button = 2;
2238 else if (wxevent.RightDown())
2239 button = 3;
2d120f83 2240 long ts = wxevent.GetTimestamp();
af0bb3b1 2241
2d120f83 2242 // check, if single or double click
af0bb3b1
VZ
2243 int buttonLast = canvas->GetLastClickedButton();
2244 long lastTS = canvas->GetLastClickTime();
2245 if ( buttonLast && buttonLast == button && (ts - lastTS) < dclickTime )
2d120f83
JS
2246 {
2247 // I have a dclick
af0bb3b1 2248 canvas->SetLastClick(0, ts);
cce442ba
VZ
2249
2250 wxEventType typeDouble;
2251 if ( eventType == wxEVT_LEFT_DOWN )
2252 typeDouble = wxEVT_LEFT_DCLICK;
2253 else if ( eventType == wxEVT_MIDDLE_DOWN )
2254 typeDouble = wxEVT_MIDDLE_DCLICK;
2255 else if ( eventType == wxEVT_RIGHT_DOWN )
2256 typeDouble = wxEVT_RIGHT_DCLICK;
2257 else
2258 typeDouble = wxEVT_NULL;
2259
2260 if ( typeDouble != wxEVT_NULL )
2d120f83 2261 {
cce442ba 2262 wxevent.SetEventType(typeDouble);
2d120f83 2263 }
2d120f83
JS
2264 }
2265 else
2266 {
2267 // not fast enough or different button
af0bb3b1 2268 canvas->SetLastClick(button, ts);
2d120f83
JS
2269 }
2270 }
2271 }
34636400 2272
2d120f83
JS
2273 wxevent.SetId(canvas->GetId());
2274 wxevent.SetEventObject(canvas);
2275 wxevent.m_x = local_event.xbutton.x;
2276 wxevent.m_y = local_event.xbutton.y;
2277 canvas->GetEventHandler()->ProcessEvent (wxevent);
34636400 2278#if 0
2d120f83 2279 if (eventType == wxEVT_ENTER_WINDOW ||
34636400
VZ
2280 eventType == wxEVT_LEAVE_WINDOW ||
2281 eventType == wxEVT_MOTION
2282 )
2283 return;
2284#endif // 0
2d120f83 2285 break;
50414e24
JS
2286 }
2287 case KeyPress:
50414e24 2288 {
2b5f62a0
VZ
2289 wxKeyEvent event (wxEVT_CHAR);
2290 if (wxTranslateKeyEvent (event, canvas, (Widget) 0, &local_event))
2d120f83
JS
2291 {
2292 // Implement wxFrame::OnCharHook by checking ancestor.
2293 wxWindow *parent = canvas->GetParent();
2294 while (parent && !parent->IsKindOf(CLASSINFO(wxFrame)))
2295 parent = parent->GetParent();
34636400 2296
2d120f83
JS
2297 if (parent)
2298 {
2299 event.SetEventType(wxEVT_CHAR_HOOK);
2300 if (parent->GetEventHandler()->ProcessEvent(event))
2301 return;
2d120f83 2302 }
a91b47e8
JS
2303
2304 // For simplicity, OnKeyDown is the same as OnChar
2305 // TODO: filter modifier key presses from OnChar
2306 event.SetEventType(wxEVT_KEY_DOWN);
2307
2308 // Only process OnChar if OnKeyDown didn't swallow it
2309 if (!canvas->GetEventHandler()->ProcessEvent (event))
2310 {
2311 event.SetEventType(wxEVT_CHAR);
2312 canvas->GetEventHandler()->ProcessEvent (event);
34636400 2313 }
2d120f83
JS
2314 }
2315 break;
2316 }
2317 case KeyRelease:
2318 {
2d120f83 2319 wxKeyEvent event (wxEVT_KEY_UP);
2b5f62a0 2320 if (wxTranslateKeyEvent (event, canvas, (Widget) 0, &local_event))
2d120f83
JS
2321 {
2322 canvas->GetEventHandler()->ProcessEvent (event);
2323 }
2324 break;
50414e24 2325 }
50414e24 2326 case FocusIn:
2d120f83
JS
2327 {
2328 if (local_event.xfocus.detail != NotifyPointer)
2329 {
2330 wxFocusEvent event(wxEVT_SET_FOCUS, canvas->GetId());
2331 event.SetEventObject(canvas);
2332 canvas->GetEventHandler()->ProcessEvent(event);
2333 }
2334 break;
50414e24 2335 }
50414e24 2336 case FocusOut:
2d120f83
JS
2337 {
2338 if (local_event.xfocus.detail != NotifyPointer)
2339 {
2340 wxFocusEvent event(wxEVT_KILL_FOCUS, canvas->GetId());
2341 event.SetEventObject(canvas);
2342 canvas->GetEventHandler()->ProcessEvent(event);
2343 }
2344 break;
2345 }
50414e24 2346 default:
2d120f83 2347 break;
50414e24
JS
2348 }
2349}
2350
34636400 2351static void wxPanelItemEventHandler(Widget wid,
af111fc3 2352 XtPointer WXUNUSED(client_data),
34636400
VZ
2353 XEvent* event,
2354 Boolean *continueToDispatch)
50414e24 2355{
34636400 2356 // Widget can be a label or the actual widget.
a91b47e8 2357
af0bb3b1 2358 wxWindow *window = wxGetWindowFromTable(wid);
34636400
VZ
2359 if (window)
2360 {
2361 wxMouseEvent wxevent(0);
2362 if (wxTranslateMouseEvent(wxevent, window, wid, event))
2363 {
2364 window->GetEventHandler()->ProcessEvent(wxevent);
2365 }
2366 }
a91b47e8 2367
34636400
VZ
2368 // TODO: probably the key to allowing default behaviour to happen. Say we
2369 // set a m_doDefault flag to FALSE at the start of this function. Then in
2370 // e.g. wxWindow::OnMouseEvent we can call Default() which sets this flag to
2371 // TRUE, indicating that default processing can happen. Thus, behaviour can
2372 // appear to be overridden just by adding an event handler and not calling
2373 // wxWindow::OnWhatever. ALSO, maybe we can use this instead of the current
2374 // way of handling drawing area events, to simplify things.
2375 *continueToDispatch = True;
2376}
a91b47e8 2377
34636400
VZ
2378static void wxScrollBarCallback(Widget scrollbar,
2379 XtPointer clientData,
311227c3 2380 XmScrollBarCallbackStruct *cbs)
34636400 2381{
34636400
VZ
2382 wxWindow *win = wxGetWindowFromTable(scrollbar);
2383 int orientation = (int) clientData;
a91b47e8 2384
34636400
VZ
2385 wxEventType eventType = wxEVT_NULL;
2386 switch (cbs->reason)
2387 {
2388 case XmCR_INCREMENT:
2389 {
311227c3 2390 eventType = wxEVT_SCROLLWIN_LINEDOWN;
34636400
VZ
2391 break;
2392 }
2393 case XmCR_DECREMENT:
2394 {
311227c3 2395 eventType = wxEVT_SCROLLWIN_LINEUP;
34636400
VZ
2396 break;
2397 }
2398 case XmCR_DRAG:
2399 {
311227c3 2400 eventType = wxEVT_SCROLLWIN_THUMBTRACK;
34636400
VZ
2401 break;
2402 }
2403 case XmCR_VALUE_CHANGED:
2404 {
bdeca1d1 2405 eventType = wxEVT_SCROLLWIN_THUMBRELEASE;
34636400
VZ
2406 break;
2407 }
2408 case XmCR_PAGE_INCREMENT:
2409 {
311227c3 2410 eventType = wxEVT_SCROLLWIN_PAGEDOWN;
34636400
VZ
2411 break;
2412 }
2413 case XmCR_PAGE_DECREMENT:
2414 {
311227c3 2415 eventType = wxEVT_SCROLLWIN_PAGEUP;
34636400
VZ
2416 break;
2417 }
2418 case XmCR_TO_TOP:
2419 {
311227c3 2420 eventType = wxEVT_SCROLLWIN_TOP;
34636400
VZ
2421 break;
2422 }
2423 case XmCR_TO_BOTTOM:
2424 {
311227c3 2425 eventType = wxEVT_SCROLLWIN_BOTTOM;
34636400
VZ
2426 break;
2427 }
2428 default:
2429 {
2430 // Should never get here
2431 wxFAIL_MSG("Unknown scroll event.");
2432 break;
2433 }
2434 }
a91b47e8 2435
311227c3
MB
2436 wxScrollWinEvent event(eventType,
2437 cbs->value,
2438 ((orientation == XmHORIZONTAL) ?
2439 wxHORIZONTAL : wxVERTICAL));
2440 event.SetEventObject( win );
34636400
VZ
2441 win->GetEventHandler()->ProcessEvent(event);
2442}
a91b47e8 2443
34636400
VZ
2444// For repainting arbitrary windows
2445void wxUniversalRepaintProc(Widget w, XtPointer WXUNUSED(c_data), XEvent *event, char *)
2446{
2447 Window window;
2448 Display *display;
a91b47e8 2449
34636400
VZ
2450 wxWindow* win = wxGetWindowFromTable(w);
2451 if (!win)
2452 return;
a91b47e8 2453
34636400 2454 switch(event -> type)
50414e24 2455 {
af0bb3b1 2456 case Expose:
34636400
VZ
2457 {
2458 window = (Window) win -> GetXWindow();
2459 display = (Display *) win -> GetXDisplay();
a91b47e8 2460
34636400
VZ
2461 if (event -> xexpose.count == 0)
2462 {
2463 win->DoPaint();
2464
2465 win->ClearUpdateRects();
2466 }
af0bb3b1
VZ
2467 else
2468 {
2469 win->AddUpdateRect(event->xexpose.x, event->xexpose.y,
2470 event->xexpose.width, event->xexpose.height);
2471 }
2472
34636400
VZ
2473 break;
2474 }
50414e24
JS
2475 }
2476}
2477
34636400
VZ
2478// ----------------------------------------------------------------------------
2479// TranslateXXXEvent() functions
2480// ----------------------------------------------------------------------------
2481
02e8b2f9
JS
2482bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Widget widget, XEvent *xevent)
2483{
2d120f83
JS
2484 switch (xevent->xany.type)
2485 {
1e8abce5
MB
2486 case EnterNotify: // never received here - yes ? MB
2487 case LeaveNotify: // never received here - yes ? MB
2488 case ButtonPress:
2489 case ButtonRelease:
2490 case MotionNotify:
02e8b2f9 2491 {
2d120f83 2492 wxEventType eventType = wxEVT_NULL;
34636400 2493
1e8abce5
MB
2494 // FIXME: this is never true I think - MB
2495 //
2d120f83
JS
2496 if (xevent->xany.type == LeaveNotify)
2497 {
af0bb3b1
VZ
2498 win->SetButton1(FALSE);
2499 win->SetButton2(FALSE);
2500 win->SetButton3(FALSE);
2d120f83
JS
2501 return FALSE;
2502 }
2503 else if (xevent->xany.type == MotionNotify)
2504 {
2505 eventType = wxEVT_MOTION;
2506 }
2507 else if (xevent->xany.type == ButtonPress)
2508 {
1e8abce5
MB
2509 wxevent.SetTimestamp(xevent->xbutton.time);
2510 int button = 0;
2d120f83
JS
2511 if (xevent->xbutton.button == Button1)
2512 {
2513 eventType = wxEVT_LEFT_DOWN;
af0bb3b1 2514 win->SetButton1(TRUE);
1e8abce5 2515 button = 1;
2d120f83
JS
2516 }
2517 else if (xevent->xbutton.button == Button2)
2518 {
2519 eventType = wxEVT_MIDDLE_DOWN;
af0bb3b1 2520 win->SetButton2(TRUE);
1e8abce5 2521 button = 2;
2d120f83
JS
2522 }
2523 else if (xevent->xbutton.button == Button3)
2524 {
2525 eventType = wxEVT_RIGHT_DOWN;
af0bb3b1 2526 win->SetButton3(TRUE);
1e8abce5
MB
2527 button = 3;
2528 }
2529
2530 // check for a double click
2531 //
2532 long dclickTime = XtGetMultiClickTime((Display*) wxGetDisplay());
2533 long ts = wxevent.GetTimestamp();
2534
2535 int buttonLast = win->GetLastClickedButton();
2536 long lastTS = win->GetLastClickTime();
2537 if ( buttonLast && buttonLast == button && (ts - lastTS) < dclickTime )
2538 {
2539 // I have a dclick
2540 win->SetLastClick(0, ts);
205c0389
VZ
2541 if ( eventType == wxEVT_LEFT_DOWN )
2542 eventType = wxEVT_LEFT_DCLICK;
2543 else if ( eventType == wxEVT_MIDDLE_DOWN )
2544 eventType = wxEVT_MIDDLE_DCLICK;
2545 else if ( eventType == wxEVT_RIGHT_DOWN )
2546 eventType = wxEVT_RIGHT_DCLICK;
1e8abce5
MB
2547 }
2548 else
2549 {
2550 // not fast enough or different button
2551 win->SetLastClick(button, ts);
2d120f83
JS
2552 }
2553 }
2554 else if (xevent->xany.type == ButtonRelease)
2555 {
2556 if (xevent->xbutton.button == Button1)
2557 {
2558 eventType = wxEVT_LEFT_UP;
af0bb3b1 2559 win->SetButton1(FALSE);
2d120f83
JS
2560 }
2561 else if (xevent->xbutton.button == Button2)
2562 {
2563 eventType = wxEVT_MIDDLE_UP;
af0bb3b1 2564 win->SetButton2(FALSE);
2d120f83
JS
2565 }
2566 else if (xevent->xbutton.button == Button3)
2567 {
2568 eventType = wxEVT_RIGHT_UP;
af0bb3b1 2569 win->SetButton3(FALSE);
2d120f83
JS
2570 }
2571 else return FALSE;
2572 }
af0bb3b1
VZ
2573 else
2574 {
2575 return FALSE;
2576 }
34636400 2577
2d120f83 2578 wxevent.SetEventType(eventType);
34636400 2579
2d120f83
JS
2580 Position x1, y1;
2581 XtVaGetValues(widget, XmNx, &x1, XmNy, &y1, NULL);
34636400 2582
2d120f83
JS
2583 int x2, y2;
2584 win->GetPosition(&x2, &y2);
34636400 2585
2d120f83
JS
2586 // The button x/y must be translated to wxWindows
2587 // window space - the widget might be a label or button,
2588 // within a form.
2589 int dx = 0;
2590 int dy = 0;
2591 if (widget != (Widget)win->GetMainWidget())
2592 {
2593 dx = x1;
2594 dy = y1;
2595 }
34636400 2596
2d120f83
JS
2597 wxevent.m_x = xevent->xbutton.x + dx;
2598 wxevent.m_y = xevent->xbutton.y + dy;
34636400 2599
2d120f83 2600 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
34636400 2601 || (event_left_is_down (xevent)
2d120f83
JS
2602 && (eventType != wxEVT_LEFT_UP)));
2603 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
34636400 2604 || (event_middle_is_down (xevent)
2d120f83
JS
2605 && (eventType != wxEVT_MIDDLE_UP)));
2606 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
34636400 2607 || (event_right_is_down (xevent)
2d120f83 2608 && (eventType != wxEVT_RIGHT_UP)));
34636400 2609
2d120f83
JS
2610 wxevent.m_shiftDown = xevent->xbutton.state & ShiftMask;
2611 wxevent.m_controlDown = xevent->xbutton.state & ControlMask;
1e8abce5
MB
2612 wxevent.m_altDown = xevent->xbutton.state & Mod3Mask;
2613 wxevent.m_metaDown = xevent->xbutton.state & Mod1Mask;
2614
2615 wxevent.SetId(win->GetId());
2616 wxevent.SetEventObject(win);
2617
2d120f83
JS
2618 return TRUE;
2619 }
02e8b2f9 2620 }
2d120f83 2621 return FALSE;
02e8b2f9
JS
2622}
2623
fc7ca9b3
MB
2624bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win,
2625 Widget WXUNUSED(widget), XEvent *xevent)
02e8b2f9 2626{
2d120f83
JS
2627 switch (xevent->xany.type)
2628 {
02e8b2f9 2629 case KeyPress:
4a041f2f 2630 case KeyRelease:
2d120f83
JS
2631 {
2632 char buf[20];
34636400 2633
2d120f83 2634 KeySym keySym;
fc7ca9b3 2635 (void) XLookupString((XKeyEvent *)xevent, buf, 20, &keySym, NULL);
2d120f83 2636 int id = wxCharCodeXToWX (keySym);
2b5f62a0
VZ
2637 // id may be WXK_xxx code - these are outside ASCII range, so we
2638 // can't just use toupper() on id
2639 if (id >= 'a' && id <= 'z')
2640 id = toupper(id);
34636400 2641
2d120f83
JS
2642 if (xevent->xkey.state & ShiftMask)
2643 wxevent.m_shiftDown = TRUE;
2644 if (xevent->xkey.state & ControlMask)
2645 wxevent.m_controlDown = TRUE;
2646 if (xevent->xkey.state & Mod3Mask)
2647 wxevent.m_altDown = TRUE;
2648 if (xevent->xkey.state & Mod1Mask)
2649 wxevent.m_metaDown = TRUE;
2650 wxevent.SetEventObject(win);
2651 wxevent.m_keyCode = id;
2652 wxevent.SetTimestamp(xevent->xkey.time);
34636400 2653
2d120f83
JS
2654 wxevent.m_x = xevent->xbutton.x;
2655 wxevent.m_y = xevent->xbutton.y;
34636400 2656
2d120f83
JS
2657 if (id > -1)
2658 return TRUE;
2659 else
2660 return FALSE;
2661 break;
2662 }
02e8b2f9 2663 default:
2d120f83
JS
2664 break;
2665 }
2666 return FALSE;
02e8b2f9
JS
2667}
2668
34636400
VZ
2669// ----------------------------------------------------------------------------
2670// Colour stuff
2671// ----------------------------------------------------------------------------
2672
02e8b2f9 2673#define YAllocColor XAllocColor
0d57be45
JS
2674XColor g_itemColors[5];
2675int wxComputeColours (Display *display, wxColour * back, wxColour * fore)
02e8b2f9 2676{
2d120f83
JS
2677 int result;
2678 static XmColorProc colorProc;
34636400 2679
2d120f83 2680 result = wxNO_COLORS;
34636400 2681
2d120f83 2682 if (back)
02e8b2f9 2683 {
2d120f83
JS
2684 g_itemColors[0].red = (((long) back->Red ()) << 8);
2685 g_itemColors[0].green = (((long) back->Green ()) << 8);
2686 g_itemColors[0].blue = (((long) back->Blue ()) << 8);
2687 g_itemColors[0].flags = DoRed | DoGreen | DoBlue;
2688 if (colorProc == (XmColorProc) NULL)
2689 {
2690 // Get a ptr to the actual function
2691 colorProc = XmSetColorCalculation ((XmColorProc) NULL);
2692 // And set it back to motif.
2693 XmSetColorCalculation (colorProc);
2694 }
2695 (*colorProc) (&g_itemColors[wxBACK_INDEX],
2696 &g_itemColors[wxFORE_INDEX],
2697 &g_itemColors[wxSELE_INDEX],
2698 &g_itemColors[wxTOPS_INDEX],
2699 &g_itemColors[wxBOTS_INDEX]);
2700 result = wxBACK_COLORS;
02e8b2f9 2701 }
2d120f83 2702 if (fore)
02e8b2f9 2703 {
2d120f83
JS
2704 g_itemColors[wxFORE_INDEX].red = (((long) fore->Red ()) << 8);
2705 g_itemColors[wxFORE_INDEX].green = (((long) fore->Green ()) << 8);
2706 g_itemColors[wxFORE_INDEX].blue = (((long) fore->Blue ()) << 8);
2707 g_itemColors[wxFORE_INDEX].flags = DoRed | DoGreen | DoBlue;
2708 if (result == wxNO_COLORS)
2709 result = wxFORE_COLORS;
02e8b2f9 2710 }
34636400 2711
2d120f83
JS
2712 Display *dpy = display;
2713 Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy);
34636400 2714
2d120f83 2715 if (back)
02e8b2f9 2716 {
2d120f83
JS
2717 /* 5 Colours to allocate */
2718 for (int i = 0; i < 5; i++)
2719 if (!YAllocColor (dpy, cmap, &g_itemColors[i]))
2720 result = wxNO_COLORS;
02e8b2f9 2721 }
2d120f83 2722 else if (fore)
02e8b2f9 2723 {
2d120f83
JS
2724 /* Only 1 colour to allocate */
2725 if (!YAllocColor (dpy, cmap, &g_itemColors[wxFORE_INDEX]))
2726 result = wxNO_COLORS;
02e8b2f9 2727 }
34636400 2728
fc7ca9b3 2729 return result;
02e8b2f9
JS
2730}
2731
34636400
VZ
2732// Changes the foreground and background colours to be derived from the current
2733// background colour. To change the foreground colour, you must call
2734// SetForegroundColour explicitly.
0d57be45 2735void wxWindow::ChangeBackgroundColour()
02e8b2f9 2736{
34636400
VZ
2737 WXWidget mainWidget = GetMainWidget();
2738 if ( mainWidget )
2739 DoChangeBackgroundColour(mainWidget, m_backgroundColour);
0d57be45 2740}
02e8b2f9 2741
0d57be45
JS
2742void wxWindow::ChangeForegroundColour()
2743{
34636400
VZ
2744 WXWidget mainWidget = GetMainWidget();
2745 if ( mainWidget )
2746 DoChangeForegroundColour(mainWidget, m_foregroundColour);
2747 if ( m_scrolledWindow && mainWidget != m_scrolledWindow )
88150e60 2748 DoChangeForegroundColour(m_scrolledWindow, m_foregroundColour);
0d57be45 2749}
02e8b2f9 2750
0d57be45 2751// Change a widget's foreground and background colours.
e1aae528
MB
2752void wxWindow::DoChangeForegroundColour(WXWidget widget,
2753 wxColour& foregroundColour)
0d57be45 2754{
e1aae528 2755 wxDoChangeForegroundColour( widget, foregroundColour );
0d57be45
JS
2756}
2757
e1aae528
MB
2758void wxWindow::DoChangeBackgroundColour(WXWidget widget,
2759 wxColour& backgroundColour,
2760 bool changeArmColour)
0d57be45 2761{
e1aae528 2762 wxDoChangeBackgroundColour( widget, backgroundColour, changeArmColour );
02e8b2f9
JS
2763}
2764
af0bb3b1 2765bool wxWindow::SetBackgroundColour(const wxColour& col)
02e8b2f9 2766{
af0bb3b1
VZ
2767 if ( !wxWindowBase::SetBackgroundColour(col) )
2768 return FALSE;
2769
0d57be45 2770 ChangeBackgroundColour();
af0bb3b1
VZ
2771
2772 return TRUE;
0d57be45
JS
2773}
2774
af0bb3b1 2775bool wxWindow::SetForegroundColour(const wxColour& col)
0d57be45 2776{
af0bb3b1
VZ
2777 if ( !wxWindowBase::SetForegroundColour(col) )
2778 return FALSE;
2779
0d57be45 2780 ChangeForegroundColour();
af0bb3b1
VZ
2781
2782 return TRUE;
0d57be45
JS
2783}
2784
4b5f3fe6 2785void wxWindow::ChangeFont(bool keepOriginalSize)
0d57be45
JS
2786{
2787 // Note that this causes the widget to be resized back
2788 // to its original size! We therefore have to set the size
2789 // back again. TODO: a better way in Motif?
0d57be45 2790 Widget w = (Widget) GetLabelWidget(); // Usually the main widget
af0bb3b1 2791 if (w && m_font.Ok())
0d57be45
JS
2792 {
2793 int width, height, width1, height1;
2794 GetSize(& width, & height);
34636400 2795
e1aae528 2796 wxDoChangeFont( GetLabelWidget(), m_font );
34636400 2797
0d57be45 2798 GetSize(& width1, & height1);
4b5f3fe6 2799 if (keepOriginalSize && (width != width1 || height != height1))
0d57be45
JS
2800 {
2801 SetSize(-1, -1, width, height);
2802 }
2803 }
02e8b2f9 2804}
0d57be45 2805
34636400
VZ
2806// ----------------------------------------------------------------------------
2807// global functions
2808// ----------------------------------------------------------------------------
0d57be45 2809
34636400 2810wxWindow *wxGetActiveWindow()
1f112209
JS
2811{
2812 // TODO
9b8f6fa2 2813 wxFAIL_MSG("Not implemented");
34636400 2814 return NULL;
1f112209
JS
2815}
2816
9806a47c
JS
2817/* static */
2818wxWindow *wxWindowBase::GetCapture()
2819{
2820 return (wxWindow *)g_captureWindow;
2821}
2822
2823
3723b7b1
JS
2824// Find the wxWindow at the current mouse position, returning the mouse
2825// position.
2826wxWindow* wxFindWindowAtPointer(wxPoint& pt)
2827{
57591e0e 2828 return wxFindWindowAtPoint(wxGetMousePosition());
3723b7b1
JS
2829}
2830
2831// Get the current mouse position.
2832wxPoint wxGetMousePosition()
2833{
59a12e90
JS
2834 Display *display = (Display*) wxGetDisplay();
2835 Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
2836 Window rootReturn, childReturn;
2837 int rootX, rootY, winX, winY;
2838 unsigned int maskReturn;
2839
2840 XQueryPointer (display,
2b5f62a0
VZ
2841 rootWindow,
2842 &rootReturn,
59a12e90
JS
2843 &childReturn,
2844 &rootX, &rootY, &winX, &winY, &maskReturn);
2845 return wxPoint(rootX, rootY);
3723b7b1
JS
2846}
2847
9806a47c 2848
34636400
VZ
2849// ----------------------------------------------------------------------------
2850// wxNoOptimize: switch off size optimization
2851// ----------------------------------------------------------------------------
88150e60 2852
af0bb3b1 2853int wxNoOptimize::ms_count = 0;
311227c3 2854