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