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