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