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