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