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