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