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