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