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