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