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