]> git.saurik.com Git - wxWidgets.git/blame - src/motif/window.cpp
Solved wxMotif scrolling display problem; added wxImageModule;
[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
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "window.h"
14#endif
15
16#include "wx/setup.h"
17#include "wx/menu.h"
18#include "wx/dc.h"
19#include "wx/dcclient.h"
20#include "wx/utils.h"
21#include "wx/app.h"
22#include "wx/panel.h"
23#include "wx/layout.h"
24#include "wx/dialog.h"
25#include "wx/listbox.h"
26#include "wx/button.h"
27#include "wx/settings.h"
28#include "wx/msgdlg.h"
29#include "wx/frame.h"
a91b47e8 30#include "wx/scrolwin.h"
4bb6408c
JS
31
32#include "wx/menuitem.h"
33#include "wx/log.h"
34
47d67540 35#if wxUSE_DRAG_AND_DROP
4bb6408c
JS
36#include "wx/dnd.h"
37#endif
38
39#include <Xm/Xm.h>
50414e24
JS
40
41#include <Xm/DrawingA.h>
42#include <Xm/ScrolledW.h>
43#include <Xm/ScrollBar.h>
44#include <Xm/Frame.h>
45#include <Xm/Label.h>
46
4bb6408c
JS
47#include "wx/motif/private.h"
48
49#include <string.h>
50
50414e24
JS
51#define SCROLL_MARGIN 4
52void wxCanvasRepaintProc (Widget, XtPointer, XmDrawingAreaCallbackStruct * cbs);
53void wxCanvasInputEvent (Widget drawingArea, XtPointer data, XmDrawingAreaCallbackStruct * cbs);
54void wxCanvasMotionEvent (Widget, XButtonEvent * event);
55void wxCanvasEnterLeave (Widget drawingArea, XtPointer clientData, XCrossingEvent * event);
8aa04e8b 56static void wxScrollBarCallback(Widget widget, XtPointer clientData,
2d120f83 57 XmScaleCallbackStruct *cbs);
02e8b2f9
JS
58void wxPanelItemEventHandler (Widget wid,
59 XtPointer client_data,
60 XEvent* event,
61 Boolean *continueToDispatch);
50414e24
JS
62
63#define event_left_is_down(x) ((x)->xbutton.state & Button1Mask)
64#define event_middle_is_down(x) ((x)->xbutton.state & Button2Mask)
65#define event_right_is_down(x) ((x)->xbutton.state & Button3Mask)
66
4bb6408c
JS
67extern wxList wxPendingDelete;
68
69#if !USE_SHARED_LIBRARY
70IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxEvtHandler)
71
72BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
2d120f83
JS
73EVT_CHAR(wxWindow::OnChar)
74EVT_KEY_DOWN(wxWindow::OnKeyDown)
75EVT_KEY_UP(wxWindow::OnKeyUp)
76EVT_ERASE_BACKGROUND(wxWindow::OnEraseBackground)
77EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
78EVT_INIT_DIALOG(wxWindow::OnInitDialog)
79EVT_IDLE(wxWindow::OnIdle)
4bb6408c
JS
80END_EVENT_TABLE()
81
82#endif
83
84
85// Constructor
86wxWindow::wxWindow()
87{
88 // Generic
89 m_windowId = 0;
90 m_windowStyle = 0;
91 m_windowParent = NULL;
92 m_windowEventHandler = this;
93 m_windowName = "";
94 m_windowCursor = *wxSTANDARD_CURSOR;
95 m_children = new wxList;
96 m_constraints = NULL;
97 m_constraintsInvolvedIn = NULL;
98 m_windowSizer = NULL;
99 m_sizerParent = NULL;
100 m_autoLayout = FALSE;
101 m_windowValidator = NULL;
102 m_defaultItem = NULL;
103 m_returnCode = 0;
104 m_caretWidth = 0; m_caretHeight = 0;
105 m_caretEnabled = FALSE;
106 m_caretShown = FALSE;
fd71308f
JS
107 // m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW) ; ;
108 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE) ;
4bb6408c 109 m_foregroundColour = *wxBLACK;
2d120f83 110
47d67540 111#if wxUSE_DRAG_AND_DROP
4bb6408c
JS
112 m_pDropTarget = NULL;
113#endif
3dd4e4e0
JS
114 m_clientObject = (wxClientData*) NULL;
115 m_clientData = NULL;
2d120f83 116
50414e24 117 /// Motif-specific
a91b47e8 118 m_needsRefresh = TRUE;
4bb6408c
JS
119 m_mainWidget = (WXWidget) 0;
120 m_button1Pressed = FALSE;
121 m_button2Pressed = FALSE;
122 m_button3Pressed = FALSE;
123 m_winCaptured = FALSE;
124 m_isShown = TRUE;
50414e24
JS
125 m_hScrollBar = (WXWidget) 0;
126 m_vScrollBar = (WXWidget) 0;
127 m_borderWidget = (WXWidget) 0;
128 m_scrolledWindow = (WXWidget) 0;
129 m_drawingArea = (WXWidget) 0;
130 m_hScroll = FALSE;
131 m_vScroll = FALSE;
50414e24
JS
132 m_backingPixmap = (WXPixmap) 0;
133 m_pixmapWidth = 0;
134 m_pixmapHeight = 0;
135 m_pixmapOffsetX = 0;
136 m_pixmapOffsetY = 0;
137 m_lastTS = 0;
138 m_lastButton = 0;
02e8b2f9 139 m_canAddEventHandler = FALSE;
47bc1060
JS
140 m_scrollPosX = 0;
141 m_scrollPosY = 0;
4bb6408c
JS
142}
143
144// Destructor
145wxWindow::~wxWindow()
146{
1f916a19
JS
147 // Remove potential dangling pointer
148 if (GetParent() && GetParent()->IsKindOf(CLASSINFO(wxPanel)))
149 {
150 wxPanel* panel = (wxPanel*) GetParent();
151 if (panel->GetLastFocus() == this)
152 panel->SetLastFocus((wxWindow*) NULL);
153 }
154
f97c9854 155 //// Motif-specific
2d120f83 156
f97c9854
JS
157 if (GetMainWidget())
158 DetachWidget(GetMainWidget()); // Removes event handlers
2d120f83 159
f97c9854
JS
160 // If m_drawingArea, we're a fully-fledged window with drawing area, scrollbars etc. (what wxCanvas used to be)
161 if (m_drawingArea)
162 {
163 // Destroy children before destroying self
164 DestroyChildren();
2d120f83 165
f97c9854 166 if (m_backingPixmap)
2d120f83
JS
167 XFreePixmap (XtDisplay ((Widget) GetMainWidget()), (Pixmap) m_backingPixmap);
168
f97c9854
JS
169 Widget w = (Widget) m_drawingArea;
170 wxDeleteWindowFromTable(w);
2d120f83 171
f97c9854
JS
172 if (w)
173 XtDestroyWidget(w);
174 m_mainWidget = (WXWidget) 0;
2d120f83 175
f97c9854
JS
176 // Only if we're _really_ a canvas (not a dialog box/panel)
177 if (m_scrolledWindow)
178 {
179 wxDeleteWindowFromTable((Widget) m_scrolledWindow);
180 }
2d120f83 181
f97c9854
JS
182 if (m_hScrollBar)
183 {
184 XtUnmanageChild ((Widget) m_hScrollBar);
185 XtDestroyWidget ((Widget) m_hScrollBar);
186 }
187 if (m_vScrollBar)
188 {
189 XtUnmanageChild ((Widget) m_vScrollBar);
190 XtDestroyWidget ((Widget) m_vScrollBar);
191 }
192 if (m_scrolledWindow)
193 {
194 XtUnmanageChild ((Widget) m_scrolledWindow);
195 XtDestroyWidget ((Widget) m_scrolledWindow);
196 }
2d120f83 197
f97c9854
JS
198 if (m_borderWidget)
199 {
200 XtDestroyWidget ((Widget) m_borderWidget);
201 m_borderWidget = (WXWidget) 0;
202 }
50414e24 203 }
2d120f83 204
f97c9854 205 //// Generic stuff
2d120f83
JS
206
207 // Have to delete constraints/sizer FIRST otherwise
208 // sizers may try to look at deleted windows as they
209 // delete themselves.
47d67540 210#if wxUSE_CONSTRAINTS
4bb6408c
JS
211 DeleteRelatedConstraints();
212 if (m_constraints)
213 {
214 // This removes any dangling pointers to this window
215 // in other windows' constraintsInvolvedIn lists.
216 UnsetConstraints(m_constraints);
217 delete m_constraints;
218 m_constraints = NULL;
219 }
220 if (m_windowSizer)
221 {
222 delete m_windowSizer;
223 m_windowSizer = NULL;
224 }
225 // If this is a child of a sizer, remove self from parent
226 if (m_sizerParent)
227 m_sizerParent->RemoveChild((wxWindow *)this);
228#endif
2d120f83 229
4bb6408c
JS
230 if (m_windowParent)
231 m_windowParent->RemoveChild(this);
2d120f83 232
4bb6408c 233 DestroyChildren();
2d120f83 234
4bb6408c
JS
235 // Destroy the window
236 if (GetMainWidget())
237 {
2d120f83
JS
238 wxDeleteWindowFromTable((Widget) GetMainWidget());
239 XtDestroyWidget((Widget) GetMainWidget());
240 SetMainWidget((WXWidget) NULL);
4bb6408c 241 }
2d120f83 242
4bb6408c
JS
243 delete m_children;
244 m_children = NULL;
2d120f83 245
4bb6408c
JS
246 // Just in case the window has been Closed, but
247 // we're then deleting immediately: don't leave
248 // dangling pointers.
249 wxPendingDelete.DeleteObject(this);
2d120f83 250
3dd4e4e0
JS
251 if ( m_windowValidator ) delete m_windowValidator;
252 if (m_clientObject) delete m_clientObject;
2d120f83 253
55acd85e 254 ClearUpdateRects();
4bb6408c
JS
255}
256
257// Destroy the window (delayed, if a managed window)
258bool wxWindow::Destroy()
259{
260 delete this;
261 return TRUE;
262}
263
264// Constructor
265bool wxWindow::Create(wxWindow *parent, wxWindowID id,
2d120f83
JS
266 const wxPoint& pos,
267 const wxSize& size,
268 long style,
269 const wxString& name)
4bb6408c
JS
270{
271 // Generic
272 m_windowId = 0;
273 m_windowStyle = 0;
274 m_windowParent = NULL;
275 m_windowEventHandler = this;
276 m_windowName = "";
277 m_windowCursor = *wxSTANDARD_CURSOR;
278 m_constraints = NULL;
279 m_constraintsInvolvedIn = NULL;
280 m_windowSizer = NULL;
281 m_sizerParent = NULL;
282 m_autoLayout = FALSE;
283 m_windowValidator = NULL;
47d67540 284#if wxUSE_DRAG_AND_DROP
4bb6408c
JS
285 m_pDropTarget = NULL;
286#endif
4bb6408c
JS
287 m_caretWidth = 0; m_caretHeight = 0;
288 m_caretEnabled = FALSE;
289 m_caretShown = FALSE;
290 m_minSizeX = -1;
291 m_minSizeY = -1;
292 m_maxSizeX = -1;
293 m_maxSizeY = -1;
294 m_defaultItem = NULL;
295 m_windowParent = NULL;
3dd4e4e0
JS
296 m_clientObject = (wxClientData*) NULL;
297 m_clientData = NULL;
2d120f83 298
50414e24 299 // Motif-specific
a91b47e8 300 m_needsRefresh = TRUE;
02e8b2f9 301 m_canAddEventHandler = FALSE;
50414e24
JS
302 m_mainWidget = (WXWidget) 0;
303 m_button1Pressed = FALSE;
304 m_button2Pressed = FALSE;
305 m_button3Pressed = FALSE;
306 m_winCaptured = FALSE;
307 m_isShown = TRUE;
308 m_hScrollBar = (WXWidget) 0;
309 m_vScrollBar = (WXWidget) 0;
310 m_borderWidget = (WXWidget) 0;
311 m_scrolledWindow = (WXWidget) 0;
312 m_drawingArea = (WXWidget) 0;
313 m_hScroll = FALSE;
314 m_vScroll = FALSE;
50414e24
JS
315 m_backingPixmap = (WXPixmap) 0;
316 m_pixmapWidth = 0;
317 m_pixmapHeight = 0;
318 m_pixmapOffsetX = 0;
319 m_pixmapOffsetY = 0;
47bc1060
JS
320 m_scrollPosX = 0;
321 m_scrollPosY = 0;
2d120f83 322
4bb6408c
JS
323 if (!parent)
324 return FALSE;
2d120f83 325
4bb6408c 326 if (parent) parent->AddChild(this);
2d120f83 327
4bb6408c 328 m_returnCode = 0;
2d120f83 329
4bb6408c 330 SetName(name);
2d120f83 331
4bb6408c 332 if ( id == -1 )
2d120f83 333 m_windowId = (int)NewControlId();
4bb6408c 334 else
2d120f83
JS
335 m_windowId = id;
336
fd71308f
JS
337 // m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW) ; ;
338 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE) ;
4bb6408c 339 m_foregroundColour = *wxBLACK;
2d120f83 340
4bb6408c 341 m_windowStyle = style;
2d120f83 342
4bb6408c 343 if ( id == -1 )
2d120f83 344 m_windowId = (int)NewControlId();
4bb6408c 345 else
2d120f83
JS
346 m_windowId = id;
347
50414e24
JS
348 //// TODO: we should probably optimize by only creating a
349 //// a drawing area if we have one or more scrollbars (wxVSCROLL/wxHSCROLL).
350 //// But for now, let's simplify things by always creating the
351 //// drawing area, since otherwise the translations are different.
2d120f83
JS
352
353 // New translations for getting mouse motion feedback
354 String translations =
355 "<Btn1Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
356<Btn2Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
357<Btn3Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
358<BtnMotion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
359<Btn1Down>: DrawingAreaInput() ManagerGadgetArm()\n\
360<Btn2Down>: DrawingAreaInput() ManagerGadgetArm()\n\
361<Btn3Down>: DrawingAreaInput() ManagerGadgetArm()\n\
362<Btn1Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
363<Btn2Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
364<Btn3Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
365<Motion>: wxCanvasMotionEvent() DrawingAreaInput()\n\
366<EnterWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
367<LeaveWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
368<Key>: DrawingAreaInput()";
369
370 XtActionsRec actions[1];
371 actions[0].string = "wxCanvasMotionEvent";
372 actions[0].proc = (XtActionProc) wxCanvasMotionEvent;
373 XtAppAddActions ((XtAppContext) wxTheApp->GetAppContext(), actions, 1);
374
375 Widget parentWidget = (Widget) parent->GetClientWidget();
376 if (style & wxBORDER)
377 m_borderWidget = (WXWidget) XtVaCreateManagedWidget ("canvasBorder",
378 xmFrameWidgetClass, parentWidget,
379 XmNshadowType, XmSHADOW_IN,
380 NULL);
381
382 m_scrolledWindow = (WXWidget) XtVaCreateManagedWidget ("scrolledWindow",
383 xmScrolledWindowWidgetClass, m_borderWidget ? (Widget) m_borderWidget : parentWidget,
384 XmNresizePolicy, XmRESIZE_NONE,
385 XmNspacing, 0,
386 XmNscrollingPolicy, XmAPPLICATION_DEFINED,
387 // XmNscrollBarDisplayPolicy, XmAS_NEEDED,
388 NULL);
389
390 XtTranslations ptr;
391 m_drawingArea = (WXWidget) XtVaCreateWidget ((char*) (const char*) name,
392 xmDrawingAreaWidgetClass, (Widget) m_scrolledWindow,
393 XmNunitType, XmPIXELS,
394 // XmNresizePolicy, XmRESIZE_ANY,
395 XmNresizePolicy, XmRESIZE_NONE,
396 XmNmarginHeight, 0,
397 XmNmarginWidth, 0,
398 XmNtranslations, ptr = XtParseTranslationTable (translations),
399 NULL);
400 /*
401 if (GetWindowStyleFlag() & wxOVERRIDE_KEY_TRANSLATIONS)
402 {
403 XtFree ((char *) ptr);
404 ptr = XtParseTranslationTable ("<Key>: DrawingAreaInput()");
405 XtOverrideTranslations ((Widget) m_drawingArea, ptr);
406 XtFree ((char *) ptr);
407 }
408 */
409
410 wxAddWindowToTable((Widget) m_drawingArea, this);
411 wxAddWindowToTable((Widget) m_scrolledWindow, this);
412
413 /*
414 * This order is very important in Motif 1.2.1
415 *
416 */
417
418 XtRealizeWidget ((Widget) m_scrolledWindow);
419 XtRealizeWidget ((Widget) m_drawingArea);
420 XtManageChild ((Widget) m_drawingArea);
421
422 XtOverrideTranslations ((Widget) m_drawingArea,
423 ptr = XtParseTranslationTable ("<Configure>: resize()"));
50414e24 424 XtFree ((char *) ptr);
2d120f83
JS
425
426 XtAddCallback ((Widget) m_drawingArea, XmNexposeCallback, (XtCallbackProc) wxCanvasRepaintProc, (XtPointer) this);
427 XtAddCallback ((Widget) m_drawingArea, XmNinputCallback, (XtCallbackProc) wxCanvasInputEvent, (XtPointer) this);
428
429 /* TODO?
430 display = XtDisplay (scrolledWindow);
431 xwindow = XtWindow (drawingArea);
432 */
433
434 XtAddEventHandler ((Widget) m_drawingArea, PointerMotionHintMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask,
435 False, (XtEventHandler) wxCanvasEnterLeave, (XtPointer) this);
436
437 // Scrolled widget needs to have its colour changed or we get
438 // a little blue square where the scrollbars abutt
439 wxColour backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE);
440 DoChangeBackgroundColour(m_scrolledWindow, backgroundColour, TRUE);
441 DoChangeBackgroundColour(m_drawingArea, backgroundColour, TRUE);
442
443 XmScrolledWindowSetAreas ((Widget) m_scrolledWindow, (Widget) 0, (Widget) 0, (Widget) m_drawingArea);
444
445 /*
446 if (m_hScrollBar)
447 XtRealizeWidget ((Widget) m_hScrollBar);
448 if (m_vScrollBar)
449 XtRealizeWidget ((Widget) m_vScrollBar);
450 */
451
452 // Without this, the cursor may not be restored properly
453 // (e.g. in splitter sample).
454 SetCursor(*wxSTANDARD_CURSOR);
455 SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
456 SetSize(pos.x, pos.y, size.x, size.y);
457
458 return TRUE;
88150e60
JS
459}
460
461// Helper function
462void wxWindow::CreateScrollbar(int orientation)
463{
2d120f83
JS
464 if (!m_drawingArea)
465 return;
466
467 XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_NONE, NULL);
468
469 // Add scrollbars if required
470 if (orientation == wxHORIZONTAL)
471 {
472 Widget hScrollBar = XtVaCreateManagedWidget ("hsb",
473 xmScrollBarWidgetClass, (Widget) m_scrolledWindow,
474 XmNorientation, XmHORIZONTAL,
475 NULL);
476 // XtAddCallback (hScrollBar, XmNvalueChangedCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
477 XtAddCallback (hScrollBar, XmNdragCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
478 XtAddCallback (hScrollBar, XmNincrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
479 XtAddCallback (hScrollBar, XmNdecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
480 XtAddCallback (hScrollBar, XmNpageIncrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
481 XtAddCallback (hScrollBar, XmNpageDecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
482 XtAddCallback (hScrollBar, XmNtoTopCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
483 XtAddCallback (hScrollBar, XmNtoBottomCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
484
485 XtVaSetValues (hScrollBar,
486 XmNincrement, 1,
487 XmNvalue, 0,
488 NULL);
489
490 m_hScrollBar = (WXWidget) hScrollBar;
491
492 wxColour backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE);
493 DoChangeBackgroundColour(m_hScrollBar, backgroundColour, TRUE);
494
495 XtRealizeWidget(hScrollBar);
496
497 XtVaSetValues((Widget) m_scrolledWindow,
498 XmNhorizontalScrollBar, (Widget) m_hScrollBar,
499 NULL);
500
501 m_hScroll = TRUE;
502 }
503
504 if (orientation == wxVERTICAL)
505 {
506 Widget vScrollBar = XtVaCreateManagedWidget ("vsb",
507 xmScrollBarWidgetClass, (Widget) m_scrolledWindow,
508 XmNorientation, XmVERTICAL,
509 NULL);
510 // XtAddCallback (vScrollBar, XmNvalueChangedCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
511 XtAddCallback (vScrollBar, XmNdragCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
512 XtAddCallback (vScrollBar, XmNincrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
513 XtAddCallback (vScrollBar, XmNdecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
514 XtAddCallback (vScrollBar, XmNpageIncrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
515 XtAddCallback (vScrollBar, XmNpageDecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
516 XtAddCallback (vScrollBar, XmNtoTopCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
517 XtAddCallback (vScrollBar, XmNtoBottomCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
518
519 XtVaSetValues (vScrollBar,
520 XmNincrement, 1,
521 XmNvalue, 0,
522 NULL);
523
524 m_vScrollBar = (WXWidget) vScrollBar;
525 wxColour backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE);
526 DoChangeBackgroundColour(m_vScrollBar, backgroundColour, TRUE);
527
528 XtRealizeWidget(vScrollBar);
529
530 XtVaSetValues((Widget) m_scrolledWindow,
531 XmNverticalScrollBar, (Widget) m_vScrollBar,
532 NULL);
533
534 m_vScroll = TRUE;
535 }
536
537 XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_ANY, NULL);
88150e60
JS
538}
539void wxWindow::DestroyScrollbar(int orientation)
540{
2d120f83
JS
541 if (!m_drawingArea)
542 return;
543
544 XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_NONE, NULL);
545 // Add scrollbars if required
546 if (orientation == wxHORIZONTAL)
547 {
548 if (m_hScrollBar)
549 {
550 XtDestroyWidget((Widget) m_hScrollBar);
551 }
552 m_hScrollBar = (WXWidget) 0;
553 m_hScroll = FALSE;
554
555 XtVaSetValues((Widget) m_scrolledWindow,
556 XmNhorizontalScrollBar, (Widget) 0,
557 NULL);
558
559 }
560
561 if (orientation == wxVERTICAL)
562 {
563 if (m_vScrollBar)
564 {
565 XtDestroyWidget((Widget) m_vScrollBar);
566 }
567 m_vScrollBar = (WXWidget) 0;
568 m_vScroll = TRUE;
569
570 XtVaSetValues((Widget) m_scrolledWindow,
571 XmNverticalScrollBar, (Widget) 0,
572 NULL);
573
574 }
575 XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_ANY, NULL);
4bb6408c
JS
576}
577
578void wxWindow::SetFocus()
579{
2d120f83
JS
580 XmProcessTraversal((Widget) GetMainWidget(), XmTRAVERSE_CURRENT);
581 XmProcessTraversal((Widget) GetMainWidget(), XmTRAVERSE_CURRENT);
4bb6408c
JS
582}
583
584void wxWindow::Enable(bool enable)
585{
2d120f83
JS
586 if (GetMainWidget())
587 {
588 XtSetSensitive((Widget) GetMainWidget(), enable);
589 XmUpdateDisplay((Widget) GetMainWidget());
590 }
4bb6408c
JS
591}
592
593void wxWindow::CaptureMouse()
594{
2d120f83
JS
595 if (m_winCaptured)
596 return;
4bb6408c 597
2d120f83
JS
598 if (GetMainWidget())
599 XtAddGrab((Widget) GetMainWidget(), TRUE, FALSE);
600
601 m_winCaptured = TRUE;
4bb6408c
JS
602}
603
604void wxWindow::ReleaseMouse()
605{
2d120f83
JS
606 if (!m_winCaptured)
607 return;
4bb6408c 608
2d120f83
JS
609 if (GetMainWidget())
610 XtRemoveGrab((Widget) GetMainWidget());
611 m_winCaptured = FALSE;
4bb6408c
JS
612}
613
614// Push/pop event handler (i.e. allow a chain of event handlers
615// be searched)
616void wxWindow::PushEventHandler(wxEvtHandler *handler)
617{
2d120f83
JS
618 handler->SetNextHandler(GetEventHandler());
619 SetEventHandler(handler);
4bb6408c
JS
620}
621
622wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
623{
2d120f83
JS
624 if ( GetEventHandler() )
625 {
626 wxEvtHandler *handlerA = GetEventHandler();
627 wxEvtHandler *handlerB = handlerA->GetNextHandler();
628 handlerA->SetNextHandler(NULL);
629 SetEventHandler(handlerB);
630 if ( deleteHandler )
631 {
632 delete handlerA;
633 return NULL;
634 }
635 else
636 return handlerA;
637 }
638 else
639 return NULL;
4bb6408c
JS
640}
641
47d67540 642#if wxUSE_DRAG_AND_DROP
4bb6408c
JS
643
644void wxWindow::SetDropTarget(wxDropTarget *pDropTarget)
645{
2d120f83
JS
646 if ( m_pDropTarget != 0 ) {
647 delete m_pDropTarget;
648 }
649
650 m_pDropTarget = pDropTarget;
651 if ( m_pDropTarget != 0 )
652 {
653 // TODO
654 }
4bb6408c
JS
655}
656
657#endif
658
659// Old style file-manager drag&drop
660void wxWindow::DragAcceptFiles(bool accept)
661{
662 // TODO
663}
664
665// Get total size
666void wxWindow::GetSize(int *x, int *y) const
667{
2d120f83
JS
668 if (m_drawingArea)
669 {
670 CanvasGetSize(x, y);
671 return;
672 }
673
674 Widget widget = (Widget) GetTopWidget();
675 Dimension xx, yy;
676 XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL);
677 *x = xx; *y = yy;
4bb6408c
JS
678}
679
680void wxWindow::GetPosition(int *x, int *y) const
681{
a4294b78
JS
682 if (m_drawingArea)
683 {
684 CanvasGetPosition(x, y);
685 return;
686 }
687 Widget widget = (Widget) GetTopWidget();
688 Position xx, yy;
689 XtVaGetValues(widget, XmNx, &xx, XmNy, &yy, NULL);
2d120f83 690
a4294b78
JS
691 // We may be faking the client origin.
692 // So a window that's really at (0, 30) may appear
693 // (to wxWin apps) to be at (0, 0).
694 if (GetParent())
695 {
696 wxPoint pt(GetParent()->GetClientAreaOrigin());
697 xx -= pt.x;
698 yy -= pt.y;
699 }
2d120f83 700
a4294b78 701 *x = xx; *y = yy;
4bb6408c
JS
702}
703
704void wxWindow::ScreenToClient(int *x, int *y) const
705{
2d120f83
JS
706 Widget widget = (Widget) GetClientWidget();
707 Display *display = XtDisplay((Widget) GetMainWidget());
708 Window rootWindow = RootWindowOfScreen(XtScreen(widget));
709 Window thisWindow = XtWindow(widget);
710
711 Window childWindow;
712 int xx = *x;
713 int yy = *y;
714 XTranslateCoordinates(display, rootWindow, thisWindow, xx, yy, x, y, &childWindow);
4bb6408c
JS
715}
716
717void wxWindow::ClientToScreen(int *x, int *y) const
718{
2d120f83
JS
719 Widget widget = (Widget) GetClientWidget();
720 Display *display = XtDisplay(widget);
721 Window rootWindow = RootWindowOfScreen(XtScreen(widget));
722 Window thisWindow = XtWindow(widget);
723
724 Window childWindow;
725 int xx = *x;
726 int yy = *y;
727 XTranslateCoordinates(display, thisWindow, rootWindow, xx, yy, x, y, &childWindow);
4bb6408c
JS
728}
729
730void wxWindow::SetCursor(const wxCursor& cursor)
731{
2d120f83
JS
732 m_windowCursor = cursor;
733 if (m_windowCursor.Ok())
734 {
735 WXDisplay *dpy = GetXDisplay();
736 WXCursor x_cursor = ((wxCursor&)cursor).GetXCursor(dpy);
737
738 Widget w = (Widget) GetMainWidget();
739 Window win = XtWindow(w);
740 XDefineCursor((Display*) dpy, win, (Cursor) x_cursor);
741 }
4bb6408c
JS
742}
743
744
745// Get size *available for subwindows* i.e. excluding menu bar etc.
746void wxWindow::GetClientSize(int *x, int *y) const
747{
2d120f83
JS
748 Widget widget = (Widget) GetClientWidget();
749 Dimension xx, yy;
750 XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL);
751 *x = xx; *y = yy;
4bb6408c
JS
752}
753
754void wxWindow::SetSize(int x, int y, int width, int height, int sizeFlags)
755{
2d120f83
JS
756 // A bit of optimization to help sort out the flickers.
757 int oldX, oldY, oldW, oldH;
758 GetSize(& oldW, & oldH);
759 GetPosition(& oldX, & oldY);
760
761 bool useOldPos = FALSE;
762 bool useOldSize = FALSE;
763
764 if ((x == -1) && (x == -1) && ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0))
765 useOldPos = TRUE;
766 else if (x == oldX && y == oldY)
767 useOldPos = TRUE;
768
769 if ((width == -1) && (height == -1))
770 useOldSize = TRUE;
771 else if (width == oldW && height == oldH)
772 useOldSize = TRUE;
773
774 if (!wxNoOptimize::CanOptimize())
775 {
776 useOldSize = FALSE; useOldPos = FALSE;
777 }
778
779 if (useOldPos && useOldSize)
780 return;
781
782 if (m_drawingArea)
783 {
784 CanvasSetSize(x, y, width, height, sizeFlags);
785 return;
786 }
787 Widget widget = (Widget) GetTopWidget();
788 if (!widget)
789 return;
790
791 bool managed = XtIsManaged( widget );
792 if (managed)
793 XtUnmanageChild(widget);
794
795 int xx = x; int yy = y;
796 AdjustForParentClientOrigin(xx, yy, sizeFlags);
797
798 if (!useOldPos)
799 {
800 if (x > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
801 XtVaSetValues(widget, XmNx, xx, NULL);
802 if (y > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
803 XtVaSetValues(widget, XmNy, yy, NULL);
804 }
805 if (!useOldSize)
806 {
807 if (width > -1)
808 XtVaSetValues(widget, XmNwidth, width, NULL);
809 if (height > -1)
810 XtVaSetValues(widget, XmNheight, height, NULL);
811 }
812
813 if (managed)
814 XtManageChild(widget);
815
816 // How about this bit. Maybe we don't need to generate size events
817 // all the time -- they'll be generated when the window is sized anyway.
818 /*
819 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
820 sizeEvent.SetEventObject(this);
821
822 GetEventHandler()->ProcessEvent(sizeEvent);
823 */
824}
7fe7d506 825
2d120f83
JS
826void wxWindow::SetClientSize(int width, int height)
827{
828 if (m_drawingArea)
829 {
830 CanvasSetClientSize(width, height);
831 return;
832 }
833
834 Widget widget = (Widget) GetTopWidget();
835
836 if (width > -1)
837 XtVaSetValues(widget, XmNwidth, width, NULL);
838 if (height > -1)
839 XtVaSetValues(widget, XmNheight, height, NULL);
840
841 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
842 sizeEvent.SetEventObject(this);
843
844 GetEventHandler()->ProcessEvent(sizeEvent);
845}
4bb6408c
JS
846
847// For implementation purposes - sometimes decorations make the client area
848// smaller
849wxPoint wxWindow::GetClientAreaOrigin() const
850{
851 return wxPoint(0, 0);
852}
853
854// Makes an adjustment to the window position (for example, a frame that has
855// a toolbar that it manages itself).
856void wxWindow::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags)
857{
858 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
859 {
860 wxPoint pt(GetParent()->GetClientAreaOrigin());
861 x += pt.x; y += pt.y;
862 }
863}
864
865bool wxWindow::Show(bool show)
866{
50414e24
JS
867 if (show)
868 {
2d120f83
JS
869 if (m_borderWidget || m_scrolledWindow)
870 {
871 if (m_drawingArea)
872 XtMapWidget((Widget) m_drawingArea);
873 XtMapWidget(m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
874 }
875 else
876 {
877 WXWidget topWidget = GetTopWidget();
878 if (GetTopWidget())
879 XtMapWidget((Widget) GetTopWidget());
880 else if (GetMainWidget())
881 XtMapWidget((Widget) GetMainWidget());
882 }
50414e24
JS
883 }
884 else
885 {
2d120f83
JS
886 if (m_borderWidget || m_scrolledWindow)
887 {
888 if (m_drawingArea)
889 XtUnmapWidget((Widget) m_drawingArea);
890 XtUnmapWidget(m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
891 }
892 else
893 {
894 if (GetTopWidget())
895 XtUnmapWidget((Widget) GetTopWidget());
896 else if (GetMainWidget())
897 XtUnmapWidget((Widget) GetMainWidget());
898 }
50414e24 899 }
2d120f83
JS
900
901 /*
4bb6408c
JS
902 Window xwin = (Window) GetXWindow();
903 Display *xdisp = (Display*) GetXDisplay();
904 if (show)
2d120f83 905 XMapWindow(xdisp, xwin);
4bb6408c 906 else
2d120f83
JS
907 XUnmapWindow(xdisp, xwin);
908 */
909
4bb6408c 910 m_isShown = show;
2d120f83 911
4bb6408c
JS
912 return TRUE;
913}
914
915bool wxWindow::IsShown() const
916{
917 return m_isShown;
918}
919
920int wxWindow::GetCharHeight() const
921{
2d120f83
JS
922 if (!m_windowFont.Ok())
923 return 0;
924
925 WXFontStructPtr pFontStruct = m_windowFont.GetFontStruct(1.0, GetXDisplay());
926
927 int direction, ascent, descent;
928 XCharStruct overall;
929 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
47bc1060 930 &descent, &overall);
2d120f83
JS
931 // return (overall.ascent + overall.descent);
932 return (ascent + descent);
4bb6408c
JS
933}
934
935int wxWindow::GetCharWidth() const
936{
2d120f83
JS
937 if (!m_windowFont.Ok())
938 return 0;
939
940 WXFontStructPtr pFontStruct = m_windowFont.GetFontStruct(1.0, GetXDisplay());
941
942 int direction, ascent, descent;
943 XCharStruct overall;
944 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
47bc1060 945 &descent, &overall);
2d120f83 946 return overall.width;
47bc1060
JS
947}
948
949/* Helper function for 16-bit fonts */
950static int str16len(const char *s)
951{
2d120f83
JS
952 int count = 0;
953
954 while (s[0] && s[1]) {
955 count++;
956 s += 2;
957 }
958
959 return count;
4bb6408c
JS
960}
961
962void wxWindow::GetTextExtent(const wxString& string, int *x, int *y,
2d120f83 963 int *descent, int *externalLeading, const wxFont *theFont, bool use16) const
4bb6408c 964{
2d120f83
JS
965 wxFont *fontToUse = (wxFont *)theFont;
966 if (!fontToUse)
967 fontToUse = (wxFont *) & m_windowFont;
968
969 if (!fontToUse->Ok())
970 return;
971
972 WXFontStructPtr pFontStruct = theFont->GetFontStruct(1.0, GetXDisplay());
973
974 int direction, ascent, descent2;
975 XCharStruct overall;
976 int slen;
977
978 if (use16) slen = str16len(string); else slen = strlen(string);
979
980 if (use16)
981 XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
982 &ascent, &descent2, &overall);
983 else
984 XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) string, slen, &direction,
985 &ascent, &descent2, &overall);
986
987 *x = (overall.width);
988 *y = (ascent + descent2);
989 if (descent)
990 *descent = descent2;
991 if (externalLeading)
992 *externalLeading = 0;
4bb6408c
JS
993}
994
16e93305 995void wxWindow::Refresh(bool eraseBack, const wxRect *rect)
4bb6408c 996{
a91b47e8 997 m_needsRefresh = TRUE;
4bb6408c
JS
998 Display *display = XtDisplay((Widget) GetMainWidget());
999 Window thisWindow = XtWindow((Widget) GetMainWidget());
2d120f83 1000
4bb6408c
JS
1001 XExposeEvent dummyEvent;
1002 int width, height;
1003 GetSize(&width, &height);
2d120f83 1004
4bb6408c
JS
1005 dummyEvent.type = Expose;
1006 dummyEvent.display = display;
1007 dummyEvent.send_event = True;
1008 dummyEvent.window = thisWindow;
1009 if (rect)
1010 {
2d120f83
JS
1011 dummyEvent.x = rect->x;
1012 dummyEvent.y = rect->y;
1013 dummyEvent.width = rect->width;
1014 dummyEvent.height = rect->height;
4bb6408c
JS
1015 }
1016 else
1017 {
2d120f83
JS
1018 dummyEvent.x = 0;
1019 dummyEvent.y = 0;
1020 dummyEvent.width = width;
1021 dummyEvent.height = height;
4bb6408c
JS
1022 }
1023 dummyEvent.count = 0;
2d120f83 1024
4bb6408c
JS
1025 if (eraseBack)
1026 {
1027 wxClientDC dc(this);
e97f20a0
JS
1028 wxBrush backgroundBrush(GetBackgroundColour(), wxSOLID);
1029 dc.SetBackground(backgroundBrush);
a367b9b3 1030 if (rect)
2d120f83 1031 dc.Clear(*rect);
a367b9b3 1032 else
2d120f83 1033 dc.Clear();
4bb6408c 1034 }
2d120f83 1035
4bb6408c
JS
1036 XSendEvent(display, thisWindow, False, ExposureMask, (XEvent *)&dummyEvent);
1037}
1038
1039// Responds to colour changes: passes event on to children.
1040void wxWindow::OnSysColourChanged(wxSysColourChangedEvent& event)
1041{
c0ed460c 1042 wxNode *node = GetChildren().First();
4bb6408c
JS
1043 while ( node )
1044 {
1045 // Only propagate to non-top-level windows
1046 wxWindow *win = (wxWindow *)node->Data();
1047 if ( win->GetParent() )
1048 {
1049 wxSysColourChangedEvent event2;
1050 event.m_eventObject = win;
1051 win->GetEventHandler()->ProcessEvent(event2);
1052 }
2d120f83 1053
4bb6408c
JS
1054 node = node->Next();
1055 }
1056}
1057
1058// This can be called by the app (or wxWindows) to do default processing for the current
1059// event. Save message/event info in wxWindow so they can be used in this function.
1060long wxWindow::Default()
1061{
1062 // TODO
1063 return 0;
1064}
1065
1066void wxWindow::InitDialog()
1067{
2d120f83
JS
1068 wxInitDialogEvent event(GetId());
1069 event.SetEventObject( this );
1070 GetEventHandler()->ProcessEvent(event);
4bb6408c
JS
1071}
1072
1073// Default init dialog behaviour is to transfer data to window
1074void wxWindow::OnInitDialog(wxInitDialogEvent& event)
1075{
2d120f83 1076 TransferDataToWindow();
4bb6408c
JS
1077}
1078
1079// Caret manipulation
1080void wxWindow::CreateCaret(int w, int h)
1081{
2d120f83
JS
1082 m_caretWidth = w;
1083 m_caretHeight = h;
1084 m_caretEnabled = TRUE;
4bb6408c
JS
1085}
1086
1087void wxWindow::CreateCaret(const wxBitmap *WXUNUSED(bitmap))
1088{
1089 // TODO
1090}
1091
1092void wxWindow::ShowCaret(bool show)
1093{
1094 // TODO
1095}
1096
1097void wxWindow::DestroyCaret()
1098{
1099 // TODO
1100 m_caretEnabled = FALSE;
1101}
1102
1103void wxWindow::SetCaretPos(int x, int y)
1104{
1105 // TODO
1106}
1107
1108void wxWindow::GetCaretPos(int *x, int *y) const
1109{
1110 // TODO
1111}
1112
1113wxWindow *wxGetActiveWindow()
1114{
1115 // TODO
1116 return NULL;
1117}
1118
1119void wxWindow::SetSizeHints(int minW, int minH, int maxW, int maxH, int incW, int incH)
1120{
1121 m_minSizeX = minW;
1122 m_minSizeY = minH;
1123 m_maxSizeX = maxW;
1124 m_maxSizeY = maxH;
2d120f83 1125
4bb6408c 1126 if (!this->IsKindOf(CLASSINFO(wxFrame)))
2d120f83
JS
1127 return;
1128
4bb6408c 1129 wxFrame *frame = (wxFrame *)this;
47bc1060 1130 Widget widget = (Widget) frame->GetShellWidget();
2d120f83 1131
4bb6408c 1132 if (minW > -1)
2d120f83 1133 XtVaSetValues(widget, XmNminWidth, minW, NULL);
4bb6408c 1134 if (minH > -1)
2d120f83 1135 XtVaSetValues(widget, XmNminHeight, minH, NULL);
4bb6408c 1136 if (maxW > -1)
2d120f83 1137 XtVaSetValues(widget, XmNmaxWidth, maxW, NULL);
4bb6408c 1138 if (maxH > -1)
2d120f83 1139 XtVaSetValues(widget, XmNmaxHeight, maxH, NULL);
4bb6408c 1140 if (incW > -1)
2d120f83 1141 XtVaSetValues(widget, XmNwidthInc, incW, NULL);
4bb6408c 1142 if (incH > -1)
2d120f83 1143 XtVaSetValues(widget, XmNheightInc, incH, NULL);
4bb6408c
JS
1144}
1145
1146void wxWindow::Centre(int direction)
1147{
2d120f83
JS
1148 int x, y, width, height, panel_width, panel_height, new_x, new_y;
1149
1150 wxWindow *father = (wxWindow *)GetParent();
1151 if (!father)
1152 return;
1153
1154 father->GetClientSize(&panel_width, &panel_height);
1155 GetSize(&width, &height);
1156 GetPosition(&x, &y);
1157
1158 new_x = -1;
1159 new_y = -1;
1160
1161 if (direction & wxHORIZONTAL)
1162 new_x = (int)((panel_width - width)/2);
1163
1164 if (direction & wxVERTICAL)
1165 new_y = (int)((panel_height - height)/2);
1166
1167 SetSize(new_x, new_y, -1, -1);
1168
4bb6408c
JS
1169}
1170
1171// Coordinates relative to the window
50414e24 1172void wxWindow::WarpPointer (int x, int y)
4bb6408c 1173{
2d120f83 1174 XWarpPointer (XtDisplay((Widget) GetClientWidget()), None, XtWindow((Widget) GetClientWidget()), 0, 0, 0, 0, x, y);
4bb6408c
JS
1175}
1176
1177void wxWindow::OnEraseBackground(wxEraseEvent& event)
1178{
1179 // TODO
1180 Default();
1181}
1182
1183int wxWindow::GetScrollPos(int orient) const
1184{
47bc1060
JS
1185 if (orient == wxHORIZONTAL)
1186 return m_scrollPosX;
1187 else
1188 return m_scrollPosY;
2d120f83
JS
1189 /*
1190 Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar);
1191 if (scrollBar)
1192 {
47bc1060
JS
1193 int pos;
1194 XtVaGetValues(scrollBar,
2d120f83 1195 XmNvalue, &pos, NULL);
47bc1060 1196 return pos;
2d120f83
JS
1197 }
1198 else
47bc1060 1199 return 0;
2d120f83 1200 */
4bb6408c
JS
1201}
1202
1203// This now returns the whole range, not just the number
1204// of positions that we can scroll.
1205int wxWindow::GetScrollRange(int orient) const
1206{
2d120f83
JS
1207 Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar);
1208 if (scrollBar)
1209 {
47bc1060
JS
1210 int range;
1211 XtVaGetValues(scrollBar,
1212 XmNmaximum, &range, NULL);
1213 return range;
1214 }
1215 else
1216 return 0;
4bb6408c
JS
1217}
1218
1219int wxWindow::GetScrollThumb(int orient) const
1220{
2d120f83
JS
1221 Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar);
1222 if (scrollBar)
1223 {
47bc1060
JS
1224 int thumb;
1225 XtVaGetValues(scrollBar,
1226 XmNsliderSize, &thumb, NULL);
1227 return thumb;
1228 }
1229 else
1230 return 0;
4bb6408c
JS
1231}
1232
47bc1060 1233void wxWindow::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
4bb6408c 1234{
2d120f83
JS
1235 Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar);
1236 if (scrollBar)
1237 {
1238 XtVaSetValues (scrollBar,
1239 XmNvalue, pos,
1240 NULL);
1241 }
1242 if (orient == wxHORIZONTAL)
1243 m_scrollPosX = pos;
1244 else
1245 m_scrollPosY = pos;
1246
4bb6408c
JS
1247}
1248
1249// New function that will replace some of the above.
1250void wxWindow::SetScrollbar(int orient, int pos, int thumbVisible,
2d120f83 1251 int range, bool WXUNUSED(refresh))
4bb6408c 1252{
88150e60
JS
1253 int oldW, oldH;
1254 GetSize(& oldW, & oldH);
2d120f83 1255
47bc1060 1256 if (range == 0)
2d120f83 1257 range = 1;
47bc1060 1258 if (thumbVisible == 0)
2d120f83
JS
1259 thumbVisible = 1;
1260
28ab302b 1261 if (thumbVisible > range)
2d120f83
JS
1262 thumbVisible = range;
1263
88150e60
JS
1264 // Save the old state to see if it changed
1265 WXWidget oldScrollBar = ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar );
2d120f83 1266
47bc1060 1267 if (orient == wxHORIZONTAL)
28ab302b 1268 {
88150e60
JS
1269 if (thumbVisible == range)
1270 {
1271 if (m_hScrollBar)
2d120f83
JS
1272 DestroyScrollbar(wxHORIZONTAL);
1273 }
28ab302b 1274 else
88150e60
JS
1275 {
1276 if (!m_hScrollBar)
2d120f83 1277 CreateScrollbar(wxHORIZONTAL);
88150e60 1278 }
28ab302b 1279 }
88150e60 1280 if (orient == wxVERTICAL)
28ab302b 1281 {
88150e60
JS
1282 if (thumbVisible == range)
1283 {
1284 if (m_vScrollBar)
2d120f83
JS
1285 DestroyScrollbar(wxVERTICAL);
1286 }
28ab302b 1287 else
88150e60
JS
1288 {
1289 if (!m_vScrollBar)
2d120f83 1290 CreateScrollbar(wxVERTICAL);
88150e60 1291 }
28ab302b 1292 }
88150e60 1293 WXWidget newScrollBar = ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar );
2d120f83 1294
88150e60 1295 if (oldScrollBar != newScrollBar)
28ab302b 1296 {
2d120f83
JS
1297 // This is important! Without it, scrollbars misbehave
1298 // badly.
1299 XtUnrealizeWidget((Widget) m_scrolledWindow);
1300 XmScrolledWindowSetAreas ((Widget) m_scrolledWindow, (Widget) m_hScrollBar, (Widget) m_vScrollBar, (Widget) m_drawingArea);
1301 XtRealizeWidget((Widget) m_scrolledWindow);
1302 XtManageChild((Widget) m_scrolledWindow);
28ab302b 1303 }
2d120f83 1304
88150e60 1305 if (newScrollBar)
2d120f83
JS
1306 XtVaSetValues((Widget) newScrollBar,
1307 XmNvalue, pos,
1308 XmNminimum, 0,
1309 XmNmaximum, range,
1310 XmNsliderSize, thumbVisible,
1311 NULL);
1312
88150e60
JS
1313 if (orient == wxHORIZONTAL)
1314 m_scrollPosX = pos;
28ab302b 1315 else
88150e60 1316 m_scrollPosY = pos;
2d120f83 1317
88150e60
JS
1318 int newW, newH;
1319 GetSize(& newW, & newH);
2d120f83 1320
88150e60
JS
1321 // Adjusting scrollbars can resize the canvas accidentally
1322 if (newW != oldW || newH != oldH)
1323 SetSize(-1, -1, oldW, oldH);
4bb6408c
JS
1324}
1325
1326// Does a physical scroll
16e93305 1327void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
4bb6408c 1328{
2d120f83
JS
1329 // cerr << "Scrolling. delta = " << dx << ", " << dy << endl;
1330 int x, y, w, h;
1331 if (rect)
1332 {
1333 // Use specified rectangle
1334 x = rect->x; y = rect->y; w = rect->width; h = rect->height;
1335 }
1336 else
1337 {
1338 // Use whole client area
1339 x = 0; y = 0;
1340 GetClientSize(& w, & h);
1341 }
1342
1343 int x1 = (dx >= 0) ? x : x - dx ;
1344 int y1 = (dy >= 0) ? y : y - dy;
1345 int w1 = w - abs(dx);
1346 int h1 = h - abs(dy);
1347 int x2 = (dx >= 0) ? x + dx : x;
1348 int y2 = (dy >= 0) ? y + dy : y;
1349
1350 wxClientDC dc(this);
1351
1352 dc.SetLogicalFunction (wxCOPY);
1353
1354 Widget widget = (Widget) GetMainWidget();
1355 Window window = XtWindow(widget);
1356 Display* display = XtDisplay(widget);
1357
1358 XCopyArea(display, window,
1359 window, (GC) dc.GetGC(),
1360 x1, y1,
1361 w1, h1,
1362 x2, y2);
1363
1364 dc.SetAutoSetting(TRUE);
1365 wxBrush brush(GetBackgroundColour(), wxSOLID);
1366 dc.SetBrush(brush); // ??
1367
1368 // We'll add rectangles to the list of update rectangles
1369 // according to which bits we've exposed.
1370 wxList updateRects;
1371
1372 if (dx > 0)
1373 {
1374 wxRect *rect = new wxRect;
1375 rect->x = x;
1376 rect->y = y;
1377 rect->width = dx;
1378 rect->height = h;
1379
1380 XFillRectangle(display, window,
1381 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
1382
1383 rect->x = rect->x;
1384 rect->y = rect->y;
1385 rect->width = rect->width;
1386 rect->height = rect->height;
1387
1388 updateRects.Append((wxObject*) rect);
1389 }
1390 else if (dx < 0)
1391 {
1392 wxRect *rect = new wxRect;
1393
1394 rect->x = x + w + dx;
1395 rect->y = y;
1396 rect->width = -dx;
1397 rect->height = h;
1398
1399 XFillRectangle(display, window,
1400 (GC) dc.GetGC(), rect->x, rect->y, rect->width,
1401 rect->height);
1402
1403 rect->x = rect->x;
1404 rect->y = rect->y;
1405 rect->width = rect->width;
1406 rect->height = rect->height;
1407
1408 updateRects.Append((wxObject*) rect);
1409 }
1410 if (dy > 0)
1411 {
1412 wxRect *rect = new wxRect;
1413
1414 rect->x = x;
1415 rect->y = y;
1416 rect->width = w;
1417 rect->height = dy;
1418
1419 XFillRectangle(display, window,
1420 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
1421
1422 rect->x = rect->x;
1423 rect->y = rect->y;
1424 rect->width = rect->width;
1425 rect->height = rect->height;
1426
1427 updateRects.Append((wxObject*) rect);
1428 }
1429 else if (dy < 0)
1430 {
1431 wxRect *rect = new wxRect;
1432
1433 rect->x = x;
1434 rect->y = y + h + dy;
1435 rect->width = w;
1436 rect->height = -dy;
1437
1438 XFillRectangle(display, window,
1439 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
1440
1441 rect->x = rect->x;
1442 rect->y = rect->y;
1443 rect->width = rect->width;
1444 rect->height = rect->height;
1445
1446 updateRects.Append((wxObject*) rect);
1447 }
1448 dc.SetBrush(wxNullBrush);
1449
1450 // Now send expose events
1451
1452 wxNode* node = updateRects.First();
1453 while (node)
1454 {
1455 wxRect* rect = (wxRect*) node->Data();
1456 XExposeEvent event;
1457
1458 event.type = Expose;
1459 event.display = display;
1460 event.send_event = True;
1461 event.window = window;
1462
1463 event.x = rect->x;
1464 event.y = rect->y;
1465 event.width = rect->width;
1466 event.height = rect->height;
1467
1468 event.count = 0;
1469
1470 XSendEvent(display, window, False, ExposureMask, (XEvent *)&event);
1471
1472 node = node->Next();
1473
1474 }
1475
1476 // Delete the update rects
1477 node = updateRects.First();
1478 while (node)
1479 {
1480 wxRect* rect = (wxRect*) node->Data();
1481 delete rect;
1482 node = node->Next();
1483 }
a91b47e8
JS
1484
1485 XmUpdateDisplay((Widget) GetMainWidget());
4bb6408c
JS
1486}
1487
4bb6408c
JS
1488void wxWindow::OnChar(wxKeyEvent& event)
1489{
a91b47e8 1490 event.Skip();
4ce81a75 1491/* ??
2d120f83
JS
1492if ( event.KeyCode() == WXK_TAB ) {
1493// propagate the TABs to the parent - it's up to it to decide what
1494// to do with it
1495if ( GetParent() ) {
1496if ( GetParent()->ProcessEvent(event) )
1497return;
1498}
1499}
1500 */
4ce81a75
JS
1501}
1502
1503void wxWindow::OnKeyDown(wxKeyEvent& event)
1504{
a91b47e8 1505 event.Skip();
4ce81a75
JS
1506}
1507
1508void wxWindow::OnKeyUp(wxKeyEvent& event)
1509{
a91b47e8 1510 event.Skip();
4bb6408c
JS
1511}
1512
1513void wxWindow::OnPaint(wxPaintEvent& event)
1514{
2d120f83 1515 Default();
4bb6408c
JS
1516}
1517
1518bool wxWindow::IsEnabled() const
1519{
47bc1060
JS
1520 // TODO. Is this right?
1521 // return XtGetSensitive((Widget) GetMainWidget());
4bb6408c
JS
1522 return FALSE;
1523}
1524
1525// Dialog support: override these and call
1526// base class members to add functionality
1527// that can't be done using validators.
1528// NOTE: these functions assume that controls
1529// are direct children of this window, not grandchildren
1530// or other levels of descendant.
1531
1532// Transfer values to controls. If returns FALSE,
1533// it's an application error (pops up a dialog)
1534bool wxWindow::TransferDataToWindow()
1535{
2d120f83
JS
1536 wxNode *node = GetChildren().First();
1537 while ( node )
1538 {
1539 wxWindow *child = (wxWindow *)node->Data();
1540 if ( child->GetValidator() &&
1541 !child->GetValidator()->TransferToWindow() )
1542 {
1543 wxLogError("Could not transfer data to window.");
1544 return FALSE;
1545 }
1546
1547 node = node->Next();
1548 }
1549 return TRUE;
4bb6408c
JS
1550}
1551
1552// Transfer values from controls. If returns FALSE,
1553// validation failed: don't quit
1554bool wxWindow::TransferDataFromWindow()
1555{
2d120f83
JS
1556 wxNode *node = GetChildren().First();
1557 while ( node )
1558 {
1559 wxWindow *child = (wxWindow *)node->Data();
1560 if ( child->GetValidator() && !child->GetValidator()->TransferFromWindow() )
1561 {
1562 return FALSE;
1563 }
1564
1565 node = node->Next();
1566 }
1567 return TRUE;
4bb6408c
JS
1568}
1569
1570bool wxWindow::Validate()
1571{
2d120f83
JS
1572 wxNode *node = GetChildren().First();
1573 while ( node )
1574 {
1575 wxWindow *child = (wxWindow *)node->Data();
1576 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this) )
1577 {
1578 return FALSE;
1579 }
1580
1581 node = node->Next();
1582 }
1583 return TRUE;
4bb6408c
JS
1584}
1585
1586// Get the window with the focus
1587wxWindow *wxWindow::FindFocus()
1588{
1589 // TODO
1590 return NULL;
1591}
1592
1593void wxWindow::AddChild(wxWindow *child)
1594{
c0ed460c 1595 GetChildren().Append(child);
4bb6408c
JS
1596 child->m_windowParent = this;
1597}
1598
1599void wxWindow::RemoveChild(wxWindow *child)
1600{
c0ed460c 1601 GetChildren().DeleteObject(child);
4bb6408c
JS
1602 child->m_windowParent = NULL;
1603}
1604
4fabb575
JS
1605// Reparents this window to have the new parent.
1606bool wxWindow::Reparent(wxWindow* WXUNUSED(parent))
1607{
1608 // For now, we indicate that this isn't implemented.
1609 return FALSE;
1610}
1611
4bb6408c
JS
1612void wxWindow::DestroyChildren()
1613{
c0ed460c 1614 wxNode *node = GetChildren().First();
02800301
JS
1615 while (node)
1616 {
2d120f83
JS
1617 wxNode* next = node->Next();
1618 wxWindow* child = (wxWindow*) node->Data();
1619 delete child;
1620 node = next;
02800301 1621 }
c0ed460c 1622 GetChildren().Clear();
02800301 1623#if 0
4bb6408c 1624 wxNode *node;
c0ed460c 1625 while ((node = GetChildren().First()) != (wxNode *)NULL) {
2d120f83
JS
1626 wxWindow *child;
1627 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL) {
1628 delete child;
1629 if ( GetChildren().Member(child) )
1630 delete node;
1631 }
4bb6408c 1632 } /* while */
02800301 1633#endif
4bb6408c
JS
1634}
1635
1636void wxWindow::MakeModal(bool modal)
1637{
2d120f83
JS
1638 // Disable all other windows
1639 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
4bb6408c 1640 {
2d120f83
JS
1641 wxNode *node = wxTopLevelWindows.First();
1642 while (node)
1643 {
1644 wxWindow *win = (wxWindow *)node->Data();
1645 if (win != this)
1646 win->Enable(!modal);
1647
1648 node = node->Next();
1649 }
4bb6408c 1650 }
4bb6408c
JS
1651}
1652
02e8b2f9
JS
1653// If nothing defined for this, try the parent.
1654// E.g. we may be a button loaded from a resource, with no callback function
1655// defined.
1656void wxWindow::OnCommand(wxWindow& win, wxCommandEvent& event)
1657{
2d120f83
JS
1658 if (GetEventHandler()->ProcessEvent(event) )
1659 return;
1660 if (m_windowParent)
1661 m_windowParent->GetEventHandler()->OnCommand(win, event);
02e8b2f9
JS
1662}
1663
4bb6408c
JS
1664void wxWindow::SetConstraints(wxLayoutConstraints *c)
1665{
2d120f83
JS
1666 if (m_constraints)
1667 {
1668 UnsetConstraints(m_constraints);
1669 delete m_constraints;
1670 }
1671 m_constraints = c;
1672 if (m_constraints)
1673 {
1674 // Make sure other windows know they're part of a 'meaningful relationship'
1675 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
1676 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1677 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
1678 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1679 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
1680 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1681 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
1682 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1683 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
1684 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1685 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
1686 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1687 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
1688 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1689 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
1690 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1691 }
4bb6408c
JS
1692}
1693
1694// This removes any dangling pointers to this window
1695// in other windows' constraintsInvolvedIn lists.
1696void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
1697{
2d120f83
JS
1698 if (c)
1699 {
1700 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
1701 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
1702 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
1703 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
1704 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
1705 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
1706 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
1707 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
1708 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
1709 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
1710 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
1711 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
1712 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
1713 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
1714 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
1715 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
1716 }
4bb6408c
JS
1717}
1718
1719// Back-pointer to other windows we're involved with, so if we delete
1720// this window, we must delete any constraints we're involved with.
1721void wxWindow::AddConstraintReference(wxWindow *otherWin)
1722{
2d120f83
JS
1723 if (!m_constraintsInvolvedIn)
1724 m_constraintsInvolvedIn = new wxList;
1725 if (!m_constraintsInvolvedIn->Member(otherWin))
1726 m_constraintsInvolvedIn->Append(otherWin);
4bb6408c
JS
1727}
1728
1729// REMOVE back-pointer to other windows we're involved with.
1730void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
1731{
2d120f83
JS
1732 if (m_constraintsInvolvedIn)
1733 m_constraintsInvolvedIn->DeleteObject(otherWin);
4bb6408c
JS
1734}
1735
1736// Reset any constraints that mention this window
1737void wxWindow::DeleteRelatedConstraints()
1738{
2d120f83 1739 if (m_constraintsInvolvedIn)
4bb6408c 1740 {
2d120f83
JS
1741 wxNode *node = m_constraintsInvolvedIn->First();
1742 while (node)
1743 {
1744 wxWindow *win = (wxWindow *)node->Data();
1745 wxNode *next = node->Next();
1746 wxLayoutConstraints *constr = win->GetConstraints();
1747
1748 // Reset any constraints involving this window
1749 if (constr)
1750 {
1751 constr->left.ResetIfWin((wxWindow *)this);
1752 constr->top.ResetIfWin((wxWindow *)this);
1753 constr->right.ResetIfWin((wxWindow *)this);
1754 constr->bottom.ResetIfWin((wxWindow *)this);
1755 constr->width.ResetIfWin((wxWindow *)this);
1756 constr->height.ResetIfWin((wxWindow *)this);
1757 constr->centreX.ResetIfWin((wxWindow *)this);
1758 constr->centreY.ResetIfWin((wxWindow *)this);
1759 }
1760 delete node;
1761 node = next;
1762 }
1763 delete m_constraintsInvolvedIn;
1764 m_constraintsInvolvedIn = NULL;
4bb6408c 1765 }
4bb6408c
JS
1766}
1767
1768void wxWindow::SetSizer(wxSizer *sizer)
1769{
2d120f83
JS
1770 m_windowSizer = sizer;
1771 if (sizer)
1772 sizer->SetSizerParent((wxWindow *)this);
4bb6408c
JS
1773}
1774
1775/*
2d120f83
JS
1776* New version
1777*/
4bb6408c
JS
1778
1779bool wxWindow::Layout()
1780{
2d120f83
JS
1781 if (GetConstraints())
1782 {
1783 int w, h;
1784 GetClientSize(&w, &h);
1785 GetConstraints()->width.SetValue(w);
1786 GetConstraints()->height.SetValue(h);
1787 }
1788
1789 // If top level (one sizer), evaluate the sizer's constraints.
1790 if (GetSizer())
1791 {
1792 int noChanges;
1793 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
1794 GetSizer()->LayoutPhase1(&noChanges);
1795 GetSizer()->LayoutPhase2(&noChanges);
1796 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
1797 return TRUE;
1798 }
1799 else
1800 {
1801 // Otherwise, evaluate child constraints
1802 ResetConstraints(); // Mark all constraints as unevaluated
1803 DoPhase(1); // Just one phase need if no sizers involved
1804 DoPhase(2);
1805 SetConstraintSizes(); // Recursively set the real window sizes
1806 }
1807 return TRUE;
4bb6408c
JS
1808}
1809
1810
1811// Do a phase of evaluating constraints:
1812// the default behaviour. wxSizers may do a similar
1813// thing, but also impose their own 'constraints'
1814// and order the evaluation differently.
1815bool wxWindow::LayoutPhase1(int *noChanges)
1816{
2d120f83
JS
1817 wxLayoutConstraints *constr = GetConstraints();
1818 if (constr)
1819 {
1820 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
1821 }
1822 else
1823 return TRUE;
4bb6408c
JS
1824}
1825
1826bool wxWindow::LayoutPhase2(int *noChanges)
1827{
2d120f83
JS
1828 *noChanges = 0;
1829
1830 // Layout children
1831 DoPhase(1);
1832 DoPhase(2);
1833 return TRUE;
4bb6408c
JS
1834}
1835
1836// Do a phase of evaluating child constraints
1837bool wxWindow::DoPhase(int phase)
1838{
2d120f83
JS
1839 int noIterations = 0;
1840 int maxIterations = 500;
1841 int noChanges = 1;
1842 int noFailures = 0;
1843 wxList succeeded;
1844 while ((noChanges > 0) && (noIterations < maxIterations))
4bb6408c 1845 {
2d120f83
JS
1846 noChanges = 0;
1847 noFailures = 0;
1848 wxNode *node = GetChildren().First();
1849 while (node)
4bb6408c 1850 {
2d120f83
JS
1851 wxWindow *child = (wxWindow *)node->Data();
1852 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
4bb6408c 1853 {
2d120f83
JS
1854 wxLayoutConstraints *constr = child->GetConstraints();
1855 if (constr)
1856 {
1857 if (succeeded.Member(child))
1858 {
1859 }
1860 else
1861 {
1862 int tempNoChanges = 0;
1863 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
1864 noChanges += tempNoChanges;
1865 if (success)
1866 {
1867 succeeded.Append(child);
1868 }
1869 }
1870 }
4bb6408c 1871 }
2d120f83 1872 node = node->Next();
4bb6408c 1873 }
2d120f83 1874 noIterations ++;
4bb6408c 1875 }
2d120f83 1876 return TRUE;
4bb6408c
JS
1877}
1878
1879void wxWindow::ResetConstraints()
1880{
2d120f83
JS
1881 wxLayoutConstraints *constr = GetConstraints();
1882 if (constr)
1883 {
1884 constr->left.SetDone(FALSE);
1885 constr->top.SetDone(FALSE);
1886 constr->right.SetDone(FALSE);
1887 constr->bottom.SetDone(FALSE);
1888 constr->width.SetDone(FALSE);
1889 constr->height.SetDone(FALSE);
1890 constr->centreX.SetDone(FALSE);
1891 constr->centreY.SetDone(FALSE);
1892 }
1893 wxNode *node = GetChildren().First();
1894 while (node)
1895 {
1896 wxWindow *win = (wxWindow *)node->Data();
1897 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
1898 win->ResetConstraints();
1899 node = node->Next();
1900 }
4bb6408c
JS
1901}
1902
1903// Need to distinguish between setting the 'fake' size for
1904// windows and sizers, and setting the real values.
1905void wxWindow::SetConstraintSizes(bool recurse)
1906{
2d120f83
JS
1907 wxLayoutConstraints *constr = GetConstraints();
1908 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
1909 constr->width.GetDone() && constr->height.GetDone())
4bb6408c 1910 {
2d120f83
JS
1911 int x = constr->left.GetValue();
1912 int y = constr->top.GetValue();
1913 int w = constr->width.GetValue();
1914 int h = constr->height.GetValue();
1915
1916 // If we don't want to resize this window, just move it...
1917 if ((constr->width.GetRelationship() != wxAsIs) ||
1918 (constr->height.GetRelationship() != wxAsIs))
1919 {
1920 // Calls Layout() recursively. AAAGH. How can we stop that.
1921 // Simply take Layout() out of non-top level OnSizes.
1922 SizerSetSize(x, y, w, h);
1923 }
1924 else
1925 {
1926 SizerMove(x, y);
1927 }
4bb6408c 1928 }
2d120f83 1929 else if (constr)
4bb6408c 1930 {
2d120f83
JS
1931 char *windowClass = this->GetClassInfo()->GetClassName();
1932
1933 wxString winName;
1934 if (GetName() == "")
1935 winName = "unnamed";
1936 else
1937 winName = GetName();
1938 wxDebugMsg("Constraint(s) not satisfied for window of type %s, name %s:\n", (const char *)windowClass, (const char *)winName);
1939 if (!constr->left.GetDone())
1940 wxDebugMsg(" unsatisfied 'left' constraint.\n");
1941 if (!constr->right.GetDone())
1942 wxDebugMsg(" unsatisfied 'right' constraint.\n");
1943 if (!constr->width.GetDone())
1944 wxDebugMsg(" unsatisfied 'width' constraint.\n");
1945 if (!constr->height.GetDone())
1946 wxDebugMsg(" unsatisfied 'height' constraint.\n");
1947 wxDebugMsg("Please check constraints: try adding AsIs() constraints.\n");
4bb6408c 1948 }
2d120f83
JS
1949
1950 if (recurse)
4bb6408c 1951 {
2d120f83
JS
1952 wxNode *node = GetChildren().First();
1953 while (node)
1954 {
1955 wxWindow *win = (wxWindow *)node->Data();
1956 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
1957 win->SetConstraintSizes();
1958 node = node->Next();
1959 }
4bb6408c 1960 }
4bb6408c
JS
1961}
1962
1963// This assumes that all sizers are 'on' the same
1964// window, i.e. the parent of this window.
1965void wxWindow::TransformSizerToActual(int *x, int *y) const
1966{
2d120f83
JS
1967 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
1968 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
1969 return;
4bb6408c 1970
2d120f83
JS
1971 int xp, yp;
1972 m_sizerParent->GetPosition(&xp, &yp);
1973 m_sizerParent->TransformSizerToActual(&xp, &yp);
1974 *x += xp;
1975 *y += yp;
4bb6408c
JS
1976}
1977
1978void wxWindow::SizerSetSize(int x, int y, int w, int h)
1979{
2d120f83
JS
1980 int xx = x;
1981 int yy = y;
1982 TransformSizerToActual(&xx, &yy);
1983 SetSize(xx, yy, w, h);
4bb6408c
JS
1984}
1985
1986void wxWindow::SizerMove(int x, int y)
1987{
2d120f83
JS
1988 int xx = x;
1989 int yy = y;
1990 TransformSizerToActual(&xx, &yy);
1991 Move(xx, yy);
4bb6408c
JS
1992}
1993
1994// Only set the size/position of the constraint (if any)
1995void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
1996{
2d120f83
JS
1997 wxLayoutConstraints *constr = GetConstraints();
1998 if (constr)
4bb6408c 1999 {
2d120f83
JS
2000 if (x != -1)
2001 {
2002 constr->left.SetValue(x);
2003 constr->left.SetDone(TRUE);
2004 }
2005 if (y != -1)
2006 {
2007 constr->top.SetValue(y);
2008 constr->top.SetDone(TRUE);
2009 }
2010 if (w != -1)
2011 {
2012 constr->width.SetValue(w);
2013 constr->width.SetDone(TRUE);
2014 }
2015 if (h != -1)
2016 {
2017 constr->height.SetValue(h);
2018 constr->height.SetDone(TRUE);
2019 }
4bb6408c 2020 }
4bb6408c
JS
2021}
2022
2023void wxWindow::MoveConstraint(int x, int y)
2024{
2d120f83
JS
2025 wxLayoutConstraints *constr = GetConstraints();
2026 if (constr)
4bb6408c 2027 {
2d120f83
JS
2028 if (x != -1)
2029 {
2030 constr->left.SetValue(x);
2031 constr->left.SetDone(TRUE);
2032 }
2033 if (y != -1)
2034 {
2035 constr->top.SetValue(y);
2036 constr->top.SetDone(TRUE);
2037 }
4bb6408c 2038 }
4bb6408c
JS
2039}
2040
2041void wxWindow::GetSizeConstraint(int *w, int *h) const
2042{
2d120f83
JS
2043 wxLayoutConstraints *constr = GetConstraints();
2044 if (constr)
2045 {
2046 *w = constr->width.GetValue();
2047 *h = constr->height.GetValue();
2048 }
2049 else
2050 GetSize(w, h);
4bb6408c
JS
2051}
2052
2053void wxWindow::GetClientSizeConstraint(int *w, int *h) const
2054{
2d120f83
JS
2055 wxLayoutConstraints *constr = GetConstraints();
2056 if (constr)
2057 {
2058 *w = constr->width.GetValue();
2059 *h = constr->height.GetValue();
2060 }
2061 else
2062 GetClientSize(w, h);
4bb6408c
JS
2063}
2064
2065void wxWindow::GetPositionConstraint(int *x, int *y) const
2066{
2d120f83
JS
2067 wxLayoutConstraints *constr = GetConstraints();
2068 if (constr)
2069 {
2070 *x = constr->left.GetValue();
2071 *y = constr->top.GetValue();
2072 }
2073 else
2074 GetPosition(x, y);
4bb6408c
JS
2075}
2076
2077bool wxWindow::Close(bool force)
2078{
2d120f83
JS
2079 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
2080 event.SetEventObject(this);
e3065973 2081#if WXWIN_COMPATIBILITY
2d120f83 2082 event.SetForce(force);
e3065973
JS
2083#endif
2084 event.SetCanVeto(!force);
2d120f83
JS
2085
2086 return GetEventHandler()->ProcessEvent(event);
4bb6408c
JS
2087}
2088
2089wxObject* wxWindow::GetChild(int number) const
2090{
2d120f83
JS
2091 // Return a pointer to the Nth object in the window
2092 wxNode *node = GetChildren().First();
2093 int n = number;
2094 while (node && n--)
2095 node = node->Next() ;
2096 if (node)
2097 {
2098 wxObject *obj = (wxObject *)node->Data();
2099 return(obj) ;
2100 }
2101 else
2102 return NULL ;
4bb6408c
JS
2103}
2104
2105void wxWindow::OnDefaultAction(wxControl *initiatingItem)
2106{
2107 // Obsolete function
2108}
2109
2110void wxWindow::Clear()
2111{
e97f20a0 2112 wxClientDC dc(this);
4bb6408c
JS
2113 wxBrush brush(GetBackgroundColour(), wxSOLID);
2114 dc.SetBackground(brush);
2115 dc.Clear();
2116}
2117
2118// Fits the panel around the items
2119void wxWindow::Fit()
2120{
2d120f83
JS
2121 int maxX = 0;
2122 int maxY = 0;
2123 wxNode *node = GetChildren().First();
2124 while ( node )
2125 {
2126 wxWindow *win = (wxWindow *)node->Data();
2127 int wx, wy, ww, wh;
2128 win->GetPosition(&wx, &wy);
2129 win->GetSize(&ww, &wh);
2130 if ( wx + ww > maxX )
2131 maxX = wx + ww;
2132 if ( wy + wh > maxY )
2133 maxY = wy + wh;
2134
2135 node = node->Next();
2136 }
2137 SetClientSize(maxX + 5, maxY + 5);
4bb6408c
JS
2138}
2139
2140void wxWindow::SetValidator(const wxValidator& validator)
2141{
2d120f83
JS
2142 if ( m_windowValidator )
2143 delete m_windowValidator;
2144 m_windowValidator = validator.Clone();
2145
2146 if ( m_windowValidator )
2147 m_windowValidator->SetWindow(this) ;
3dd4e4e0
JS
2148}
2149
2150void wxWindow::SetClientObject( wxClientData *data )
2151{
2d120f83
JS
2152 if (m_clientObject) delete m_clientObject;
2153 m_clientObject = data;
3dd4e4e0
JS
2154}
2155
2156wxClientData *wxWindow::GetClientObject()
2157{
2d120f83 2158 return m_clientObject;
3dd4e4e0
JS
2159}
2160
2161void wxWindow::SetClientData( void *data )
2162{
2d120f83 2163 m_clientData = data;
3dd4e4e0
JS
2164}
2165
2166void *wxWindow::GetClientData()
2167{
2d120f83 2168 return m_clientData;
4bb6408c
JS
2169}
2170
2171// Find a window by id or name
2172wxWindow *wxWindow::FindWindow(long id)
2173{
2d120f83
JS
2174 if ( GetId() == id)
2175 return this;
2176
2177 wxNode *node = GetChildren().First();
2178 while ( node )
2179 {
2180 wxWindow *child = (wxWindow *)node->Data();
2181 wxWindow *found = child->FindWindow(id);
2182 if ( found )
2183 return found;
2184 node = node->Next();
2185 }
2186 return NULL;
4bb6408c
JS
2187}
2188
2189wxWindow *wxWindow::FindWindow(const wxString& name)
2190{
2d120f83
JS
2191 if ( GetName() == name)
2192 return this;
2193
2194 wxNode *node = GetChildren().First();
2195 while ( node )
2196 {
2197 wxWindow *child = (wxWindow *)node->Data();
2198 wxWindow *found = child->FindWindow(name);
2199 if ( found )
2200 return found;
2201 node = node->Next();
2202 }
2203 return NULL;
4bb6408c
JS
2204}
2205
2206void wxWindow::OnIdle(wxIdleEvent& event)
2207{
4bb6408c
JS
2208 // This calls the UI-update mechanism (querying windows for
2209 // menu/toolbar/control state information)
0d57be45 2210 UpdateWindowUI();
4bb6408c
JS
2211}
2212
2213// Raise the window to the top of the Z order
2214void wxWindow::Raise()
2215{
02e8b2f9
JS
2216 Window window = XtWindow((Widget) GetTopWidget());
2217 XRaiseWindow(XtDisplay((Widget) GetTopWidget()), window);
4bb6408c
JS
2218}
2219
2220// Lower the window to the bottom of the Z order
2221void wxWindow::Lower()
2222{
02e8b2f9
JS
2223 Window window = XtWindow((Widget) GetTopWidget());
2224 XLowerWindow(XtDisplay((Widget) GetTopWidget()), window);
4bb6408c
JS
2225}
2226
2227bool wxWindow::AcceptsFocus() const
2228{
2d120f83 2229 return IsShown() && IsEnabled();
4bb6408c
JS
2230}
2231
2232// Update region access
55acd85e 2233wxRegion& wxWindow::GetUpdateRegion() const
4bb6408c 2234{
55acd85e 2235 return (wxRegion&) m_updateRegion;
4bb6408c
JS
2236}
2237
2238bool wxWindow::IsExposed(int x, int y, int w, int h) const
2239{
2240 return (m_updateRegion.Contains(x, y, w, h) != wxOutRegion);
2241}
2242
2243bool wxWindow::IsExposed(const wxPoint& pt) const
2244{
2245 return (m_updateRegion.Contains(pt) != wxOutRegion);
2246}
2247
2248bool wxWindow::IsExposed(const wxRect& rect) const
2249{
2250 return (m_updateRegion.Contains(rect) != wxOutRegion);
2251}
2252
2253/*
2d120f83
JS
2254* Allocates control IDs
2255*/
4bb6408c
JS
2256
2257int wxWindow::NewControlId()
2258{
2259 static int s_controlId = 0;
2260 s_controlId ++;
2261 return s_controlId;
2262}
2263
2264void wxWindow::SetAcceleratorTable(const wxAcceleratorTable& accel)
2265{
2266 m_acceleratorTable = accel;
2267}
2268
2269// All widgets should have this as their resize proc.
2270// OnSize sent to wxWindow via client data.
2271void wxWidgetResizeProc(Widget w, XConfigureEvent *event, String args[], int *num_args)
2272{
2273 wxWindow *win = (wxWindow *)wxWidgetHashTable->Get((long)w);
2274 if (!win)
2275 return;
2d120f83 2276
4bb6408c
JS
2277 if (win->PreResize())
2278 {
2279 int width, height;
2280 win->GetSize(&width, &height);
2281 wxSizeEvent sizeEvent(wxSize(width, height), win->GetId());
2282 sizeEvent.SetEventObject(win);
2283 win->GetEventHandler()->ProcessEvent(sizeEvent);
2284 }
2285}
2286
2287bool wxAddWindowToTable(Widget w, wxWindow *win)
2288{
2d120f83
JS
2289 wxWindow *oldItem = NULL;
2290 // printf("Adding widget %ld, name = %s\n", w, win->GetClassInfo()->GetClassName());
2291 if ((oldItem = (wxWindow *)wxWidgetHashTable->Get ((long) w)))
2292 {
2293 wxLogError("Widget table clash: new widget is %ld, %s", (long)w, win->GetClassInfo()->GetClassName());
2294 return FALSE;
2295 }
2296
2297 wxWidgetHashTable->Put ((long) w, win);
2298 return TRUE;
4bb6408c
JS
2299}
2300
2301wxWindow *wxGetWindowFromTable(Widget w)
2302{
2d120f83 2303 return (wxWindow *)wxWidgetHashTable->Get ((long) w);
4bb6408c
JS
2304}
2305
2306void wxDeleteWindowFromTable(Widget w)
2307{
2d120f83 2308 wxWidgetHashTable->Delete((long)w);
4bb6408c 2309}
2d120f83 2310
4bb6408c
JS
2311// Get the underlying X window and display
2312WXWindow wxWindow::GetXWindow() const
2313{
50414e24 2314 return (WXWindow) XtWindow((Widget) GetMainWidget());
4bb6408c
JS
2315}
2316
2317WXDisplay *wxWindow::GetXDisplay() const
2318{
50414e24 2319 return (WXDisplay*) XtDisplay((Widget) GetMainWidget());
4bb6408c
JS
2320}
2321
2322WXWidget wxWindow::GetMainWidget() const
2323{
50414e24 2324 if (m_drawingArea)
2d120f83 2325 return m_drawingArea;
50414e24 2326 else
2d120f83 2327 return m_mainWidget;
50414e24
JS
2328}
2329
2330WXWidget wxWindow::GetClientWidget() const
2331{
2332 if (m_drawingArea != (WXWidget) 0)
2333 return m_drawingArea;
2334 else
02e8b2f9
JS
2335 return GetMainWidget();
2336}
2337
2338WXWidget wxWindow::GetTopWidget() const
2339{
2340 return GetMainWidget();
4bb6408c
JS
2341}
2342
50414e24 2343void wxCanvasRepaintProc (Widget drawingArea, XtPointer clientData,
2d120f83 2344 XmDrawingAreaCallbackStruct * cbs)
50414e24
JS
2345{
2346 if (!wxWidgetHashTable->Get ((long) (Widget) drawingArea))
2d120f83
JS
2347 return;
2348
50414e24 2349 XEvent * event = cbs->event;
55acd85e
JS
2350 wxWindow * win = (wxWindow *) clientData;
2351 Display * display = (Display *) win->GetXDisplay();
2d120f83 2352
50414e24
JS
2353 switch (event->type)
2354 {
2d120f83 2355 case Expose:
55acd85e
JS
2356 {
2357 wxRect* rect = new wxRect(event->xexpose.x, event->xexpose.y,
2d120f83
JS
2358 event->xexpose.width, event->xexpose.height);
2359 /*
2360 cout << "Expose proc. wxRect: " << rect->x << ", " << rect->y << ", ";
2361 cout << rect->width << ", " << rect->height << "\n\n";
2362 */
2363
55acd85e 2364 win->m_updateRects.Append((wxObject*) rect);
2d120f83 2365
55acd85e
JS
2366 if (event -> xexpose.count == 0)
2367 {
a91b47e8 2368 /*
55acd85e
JS
2369 wxPaintEvent event(win->GetId());
2370 event.SetEventObject(win);
2371 win->GetEventHandler()->ProcessEvent(event);
a91b47e8 2372 */
2d120f83 2373
a91b47e8 2374 win->DoPaint();
55acd85e
JS
2375 win->ClearUpdateRects();
2376 }
2377 break;
2378 }
2d120f83 2379 default:
55acd85e 2380 {
2d120f83
JS
2381 cout << "\n\nNew Event ! is = " << event -> type << "\n";
2382 break;
55acd85e 2383 }
50414e24 2384 }
50414e24
JS
2385}
2386
2387// Unable to deal with Enter/Leave without a separate EventHandler (Motif 1.1.4)
2388void
2389wxCanvasEnterLeave (Widget drawingArea, XtPointer clientData, XCrossingEvent * event)
2390{
2d120f83
JS
2391 XmDrawingAreaCallbackStruct cbs;
2392 XEvent ev;
2393
2394 //if (event->mode!=NotifyNormal)
2395 // return ;
2396
2397 // ev = *((XEvent *) event); // Causes Purify error (copying too many bytes)
2398 ((XCrossingEvent &) ev) = *event;
2399
2400 cbs.reason = XmCR_INPUT;
2401 cbs.event = &ev;
2402
2403 wxCanvasInputEvent (drawingArea, (XtPointer) NULL, &cbs);
50414e24
JS
2404}
2405
2406// Fix to make it work under Motif 1.0 (!)
2407void wxCanvasMotionEvent (Widget drawingArea, XButtonEvent * event)
2408{
2409#if XmVersion<=1000
2d120f83
JS
2410
2411 XmDrawingAreaCallbackStruct cbs;
2412 XEvent ev;
2413
2414 //ev.xbutton = *event;
2415 ev = *((XEvent *) event);
2416 cbs.reason = XmCR_INPUT;
2417 cbs.event = &ev;
2418
2419 wxCanvasInputEvent (drawingArea, (XtPointer) NULL, &cbs);
50414e24
JS
2420#endif
2421}
2422
2423void wxCanvasInputEvent (Widget drawingArea, XtPointer data, XmDrawingAreaCallbackStruct * cbs)
2424{
2d120f83
JS
2425 wxWindow *canvas = (wxWindow *) wxWidgetHashTable->Get ((long) (Widget) drawingArea);
2426 XEvent local_event;
2427
2428 if (canvas==NULL)
2429 return ;
2430
2431 if (cbs->reason != XmCR_INPUT)
2432 return;
2433
2434 local_event = *(cbs->event); // We must keep a copy!
2435
f57fe24c
JS
2436 /*
2437 switch (local_event.xany.type)
2d120f83
JS
2438 {
2439 case EnterNotify:
2440 cout << "EnterNotify\n";
2441 break;
2442 case LeaveNotify:
2443 cout << "LeaveNotify\n";
2444 break;
2445 case ButtonPress:
2446 cout << "ButtonPress\n";
2447 break;
2448 case ButtonRelease:
2449 cout << "ButtonRelease\n";
2450 break;
2451 case MotionNotify:
2452 cout << "MotionNotify\n";
2453 break;
2454 default:
2455 cout << "Something else\n";
2456 break;
f57fe24c 2457 }
2d120f83
JS
2458 */
2459
2460 switch (local_event.xany.type)
50414e24
JS
2461 {
2462 case EnterNotify:
2463 case LeaveNotify:
2464 case ButtonPress:
2465 case ButtonRelease:
2466 case MotionNotify:
2d120f83
JS
2467 {
2468 wxEventType eventType = wxEVT_NULL;
2469
2470 if (local_event.xany.type == EnterNotify)
2471 {
2472 //if (local_event.xcrossing.mode!=NotifyNormal)
2473 // return ; // Ignore grab events
2474 eventType = wxEVT_ENTER_WINDOW;
2475 // canvas->GetEventHandler()->OnSetFocus();
2476 }
2477 else if (local_event.xany.type == LeaveNotify)
2478 {
2479 //if (local_event.xcrossing.mode!=NotifyNormal)
2480 // return ; // Ignore grab events
2481 eventType = wxEVT_LEAVE_WINDOW;
2482 // canvas->GetEventHandler()->OnKillFocus();
2483 }
2484 else if (local_event.xany.type == MotionNotify)
2485 {
2486 eventType = wxEVT_MOTION;
2487 if (local_event.xmotion.is_hint == NotifyHint)
2488 {
2489 Window root, child;
2490 Display *dpy = XtDisplay (drawingArea);
2491
2492 XQueryPointer (dpy, XtWindow (drawingArea),
2493 &root, &child,
2494 &local_event.xmotion.x_root,
2495 &local_event.xmotion.y_root,
2496 &local_event.xmotion.x,
2497 &local_event.xmotion.y,
2498 &local_event.xmotion.state);
2499 }
2500 else
2501 {
2502 }
2503 }
2504
2505 else if (local_event.xany.type == ButtonPress)
2506 {
2507 if (local_event.xbutton.button == Button1)
2508 {
2509 eventType = wxEVT_LEFT_DOWN;
2510 canvas->m_button1Pressed = TRUE;
2511 }
2512 else if (local_event.xbutton.button == Button2)
2513 {
2514 eventType = wxEVT_MIDDLE_DOWN;
2515 canvas->m_button2Pressed = TRUE;
2516 }
2517 else if (local_event.xbutton.button == Button3)
2518 {
2519 eventType = wxEVT_RIGHT_DOWN;
2520 canvas->m_button3Pressed = TRUE;
2521 }
2522 }
2523 else if (local_event.xany.type == ButtonRelease)
2524 {
2525 if (local_event.xbutton.button == Button1)
2526 {
2527 eventType = wxEVT_LEFT_UP;
2528 canvas->m_button1Pressed = FALSE;
2529 }
2530 else if (local_event.xbutton.button == Button2)
2531 {
2532 eventType = wxEVT_MIDDLE_UP;
2533 canvas->m_button2Pressed = FALSE;
2534 }
2535 else if (local_event.xbutton.button == Button3)
2536 {
2537 eventType = wxEVT_RIGHT_UP;
2538 canvas->m_button3Pressed = FALSE;
2539 }
2540 }
2541
2542 wxMouseEvent wxevent (eventType);
2543 wxevent.m_eventHandle = (char *) &local_event;
2544
2545 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
2546 || (event_left_is_down (&local_event)
2547 && (eventType != wxEVT_LEFT_UP)));
2548 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
2549 || (event_middle_is_down (&local_event)
2550 && (eventType != wxEVT_MIDDLE_UP)));
2551 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
2552 || (event_right_is_down (&local_event)
2553 && (eventType != wxEVT_RIGHT_UP)));
2554
2555 wxevent.m_shiftDown = local_event.xbutton.state & ShiftMask;
2556 wxevent.m_controlDown = local_event.xbutton.state & ControlMask;
2557 wxevent.m_altDown = local_event.xbutton.state & Mod3Mask;
2558 wxevent.m_metaDown = local_event.xbutton.state & Mod1Mask;
2559 wxevent.SetTimestamp(local_event.xbutton.time);
2560
2561 // Now check if we need to translate this event into a double click
2562 if (TRUE) // canvas->doubleClickAllowed)
2563 {
2564 if (wxevent.ButtonDown())
2565 {
2566 long dclickTime = XtGetMultiClickTime((Display*) wxGetDisplay()) ;
2567
2568 // get button and time-stamp
2569 int button = 0;
2570 if (wxevent.LeftDown()) button = 1;
2571 else if (wxevent.MiddleDown()) button = 2;
2572 else if (wxevent.RightDown()) button = 3;
2573 long ts = wxevent.GetTimestamp();
2574 // check, if single or double click
2575 if (canvas->m_lastButton && canvas->m_lastButton==button && (ts - canvas->m_lastTS) < dclickTime)
2576 {
2577 // I have a dclick
2578 canvas->m_lastButton = 0;
2579 switch ( eventType )
2580 {
2581 case wxEVT_LEFT_DOWN:
2582 wxevent.SetEventType(wxEVT_LEFT_DCLICK);
2583 break;
2584 case wxEVT_MIDDLE_DOWN:
2585 wxevent.SetEventType(wxEVT_MIDDLE_DCLICK);
2586 break;
2587 case wxEVT_RIGHT_DOWN:
2588 wxevent.SetEventType(wxEVT_RIGHT_DCLICK);
2589 break;
2590
2591 default :
2592 break;
2593 }
2594
2595 }
2596 else
2597 {
2598 // not fast enough or different button
2599 canvas->m_lastTS = ts;
2600 canvas->m_lastButton = button;
2601 }
2602 }
2603 }
2604
2605 wxevent.SetId(canvas->GetId());
2606 wxevent.SetEventObject(canvas);
2607 wxevent.m_x = local_event.xbutton.x;
2608 wxevent.m_y = local_event.xbutton.y;
2609 canvas->GetEventHandler()->ProcessEvent (wxevent);
2610 /*
2611 if (eventType == wxEVT_ENTER_WINDOW ||
2612 eventType == wxEVT_LEAVE_WINDOW ||
2613 eventType == wxEVT_MOTION
2614 )
2615 return;
2616 */
2617 break;
50414e24
JS
2618 }
2619 case KeyPress:
50414e24 2620 {
2d120f83
JS
2621 KeySym keySym;
2622 // XComposeStatus compose;
2623 // (void) XLookupString ((XKeyEvent *) & local_event, wxBuffer, 20, &keySym, &compose);
2624 (void) XLookupString ((XKeyEvent *) & local_event, wxBuffer, 20, &keySym, NULL);
2625 int id = wxCharCodeXToWX (keySym);
2626
2627 wxEventType eventType = wxEVT_CHAR;
50414e24 2628
2d120f83
JS
2629 wxKeyEvent event (eventType);
2630
2631 if (local_event.xkey.state & ShiftMask)
2632 event.m_shiftDown = TRUE;
2633 if (local_event.xkey.state & ControlMask)
2634 event.m_controlDown = TRUE;
2635 if (local_event.xkey.state & Mod3Mask)
2636 event.m_altDown = TRUE;
2637 if (local_event.xkey.state & Mod1Mask)
2638 event.m_metaDown = TRUE;
2639 event.SetEventObject(canvas);
2640 event.m_keyCode = id;
2641 event.SetTimestamp(local_event.xkey.time);
2642
2643 if (id > -1)
2644 {
2645 // Implement wxFrame::OnCharHook by checking ancestor.
2646 wxWindow *parent = canvas->GetParent();
2647 while (parent && !parent->IsKindOf(CLASSINFO(wxFrame)))
2648 parent = parent->GetParent();
2649
2650 if (parent)
2651 {
2652 event.SetEventType(wxEVT_CHAR_HOOK);
2653 if (parent->GetEventHandler()->ProcessEvent(event))
2654 return;
2d120f83 2655 }
a91b47e8
JS
2656
2657 // For simplicity, OnKeyDown is the same as OnChar
2658 // TODO: filter modifier key presses from OnChar
2659 event.SetEventType(wxEVT_KEY_DOWN);
2660
2661 // Only process OnChar if OnKeyDown didn't swallow it
2662 if (!canvas->GetEventHandler()->ProcessEvent (event))
2663 {
2664 event.SetEventType(wxEVT_CHAR);
2665 canvas->GetEventHandler()->ProcessEvent (event);
2666 }
2d120f83
JS
2667 }
2668 break;
2669 }
2670 case KeyRelease:
2671 {
2672 KeySym keySym;
2673 (void) XLookupString ((XKeyEvent *) & local_event, wxBuffer, 20, &keySym, NULL);
2674 int id = wxCharCodeXToWX (keySym);
2675
2676 wxKeyEvent event (wxEVT_KEY_UP);
2677
2678 if (local_event.xkey.state & ShiftMask)
2679 event.m_shiftDown = TRUE;
2680 if (local_event.xkey.state & ControlMask)
2681 event.m_controlDown = TRUE;
2682 if (local_event.xkey.state & Mod3Mask)
2683 event.m_altDown = TRUE;
2684 if (local_event.xkey.state & Mod1Mask)
2685 event.m_metaDown = TRUE;
2686 event.SetEventObject(canvas);
2687 event.m_keyCode = id;
2688 event.SetTimestamp(local_event.xkey.time);
2689
2690 if (id > -1)
2691 {
2692 canvas->GetEventHandler()->ProcessEvent (event);
2693 }
2694 break;
50414e24 2695 }
50414e24 2696 case FocusIn:
2d120f83
JS
2697 {
2698 if (local_event.xfocus.detail != NotifyPointer)
2699 {
2700 wxFocusEvent event(wxEVT_SET_FOCUS, canvas->GetId());
2701 event.SetEventObject(canvas);
2702 canvas->GetEventHandler()->ProcessEvent(event);
2703 }
2704 break;
50414e24 2705 }
50414e24 2706 case FocusOut:
2d120f83
JS
2707 {
2708 if (local_event.xfocus.detail != NotifyPointer)
2709 {
2710 wxFocusEvent event(wxEVT_KILL_FOCUS, canvas->GetId());
2711 event.SetEventObject(canvas);
2712 canvas->GetEventHandler()->ProcessEvent(event);
2713 }
2714 break;
2715 }
50414e24 2716 default:
2d120f83 2717 break;
50414e24
JS
2718 }
2719}
2720
2721void wxWindow::DoPaint()
2722{
2d120f83 2723 //TODO : make a temporary gc so we can do the XCopyArea below
a91b47e8 2724 if (m_backingPixmap && !m_needsRefresh)
50414e24 2725 {
a91b47e8
JS
2726 wxPaintDC dc(this);
2727
2728 GC tempGC = (GC) dc.GetBackingGC();
2729
2730 Widget widget = (Widget) GetMainWidget();
2731
2732 int scrollPosX = 0;
2733 int scrollPosY = 0;
2734
2735 // We have to test whether it's a wxScrolledWindow (hack!)
2736 // because otherwise we don't know how many pixels have been
2737 // scrolled. We might solve this in the future by defining
2738 // virtual wxWindow functions to get the scroll position in pixels.
2739 // Or, each kind of scrolled window has to implement backing
2740 // stores itself, using generic wxWindows code.
2741 if (this->IsKindOf(CLASSINFO(wxScrolledWindow)))
2742 {
2743 wxScrolledWindow* scrolledWindow = (wxScrolledWindow*) this;
2744 int x, y;
2745 scrolledWindow->CalcScrolledPosition(0, 0, & x, & y);
2746
2747 scrollPosX = - x;
2748 scrollPosY = - y;
2749 }
2750
2751 // TODO: This could be optimized further by only copying the
2752 // areas in the current update region.
2753
2754 // Only blit the part visible in the client area. The backing pixmap
2755 // always starts at 0, 0 but we may be looking at only a portion of it.
2756 wxSize clientArea = GetClientSize();
2757 int toBlitX = m_pixmapWidth - scrollPosX;
2758 int toBlitY = m_pixmapHeight - scrollPosY;
2759
2760 // Copy whichever is samller, the amount of pixmap we have to copy,
2761 // or the size of the client area.
2762 toBlitX = wxMin(toBlitX, clientArea.x);
2763 toBlitY = wxMin(toBlitY, clientArea.y);
2764
2765 // Make sure we're not negative
2766 toBlitX = wxMax(0, toBlitX);
2767 toBlitY = wxMax(0, toBlitY);
2768
2769 XCopyArea (XtDisplay (widget), (Pixmap) m_backingPixmap, XtWindow (widget), tempGC,
2770 scrollPosX, scrollPosY, // Start at the scroll position
2771 toBlitX, toBlitY, // How much of the pixmap to copy
2772 0, 0); // Destination
50414e24 2773 }
2d120f83 2774 else
50414e24 2775 {
a91b47e8
JS
2776 // Set an erase event first
2777 wxEraseEvent eraseEvent(GetId());
2778 eraseEvent.SetEventObject(this);
2779 GetEventHandler()->ProcessEvent(eraseEvent);
2780
50414e24
JS
2781 wxPaintEvent event(GetId());
2782 event.SetEventObject(this);
2783 GetEventHandler()->ProcessEvent(event);
a91b47e8
JS
2784
2785 m_needsRefresh = FALSE;
50414e24
JS
2786 }
2787}
2788
2789// SetSize, but as per old wxCanvas (with drawing widget etc.)
2790void wxWindow::CanvasSetSize (int x, int y, int w, int h, int sizeFlags)
2791{
2d120f83
JS
2792 // A bit of optimization to help sort out the flickers.
2793 int oldX, oldY, oldW, oldH;
2794 GetSize(& oldW, & oldH);
2795 GetPosition(& oldX, & oldY);
2796
2797 bool useOldPos = FALSE;
2798 bool useOldSize = FALSE;
2799
2800 if ((x == -1) && (x == -1) && ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0))
2801 useOldPos = TRUE;
2802 else if (x == oldX && y == oldY)
2803 useOldPos = TRUE;
2804
2805 if ((w == -1) && (h == -1))
2806 useOldSize = TRUE;
2807 else if (w == oldW && h == oldH)
2808 useOldSize = TRUE;
2809
2810 if (!wxNoOptimize::CanOptimize())
50414e24 2811 {
2d120f83 2812 useOldSize = FALSE; useOldPos = FALSE;
50414e24 2813 }
2d120f83
JS
2814
2815 if (useOldPos && useOldSize)
2816 return;
2817
2818 Widget drawingArea = (Widget) m_drawingArea;
2819 bool managed = XtIsManaged(m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
2820
2821 if (managed)
2822 XtUnmanageChild (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
2823 XtVaSetValues((Widget) m_drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
2824
2825 int xx = x; int yy = y;
2826 AdjustForParentClientOrigin(xx, yy, sizeFlags);
2827
2828 if (!useOldPos)
50414e24 2829 {
2d120f83
JS
2830 if (x > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
2831 {
2832 XtVaSetValues (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow,
2833 XmNx, xx, NULL);
2834 }
2835
2836 if (y > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
2837 {
2838 XtVaSetValues (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow,
2839 XmNy, yy, NULL);
2840 }
50414e24 2841 }
2d120f83
JS
2842
2843 if (!useOldSize)
50414e24 2844 {
2d120f83
JS
2845
2846 if (w > -1)
2847 {
2848 if (m_borderWidget)
2849 {
2850 XtVaSetValues ((Widget) m_borderWidget, XmNwidth, w, NULL);
2851 short thick, margin;
2852 XtVaGetValues ((Widget) m_borderWidget,
2853 XmNshadowThickness, &thick,
2854 XmNmarginWidth, &margin,
2855 NULL);
2856 w -= 2 * (thick + margin);
2857 }
2858
2859 XtVaSetValues ((Widget) m_scrolledWindow, XmNwidth, w, NULL);
2860
2861 Dimension spacing;
2862 Widget sbar;
2863 XtVaGetValues ((Widget) m_scrolledWindow,
2864 XmNspacing, &spacing,
2865 XmNverticalScrollBar, &sbar,
2866 NULL);
2867 Dimension wsbar;
2868 if (sbar)
2869 XtVaGetValues (sbar, XmNwidth, &wsbar, NULL);
2870 else
2871 wsbar = 0;
2872
2873 w -= (spacing + wsbar);
2874
2875 // XtVaSetValues ((Widget) m_drawingArea, XmNwidth, w, NULL);
2876 }
2877 if (h > -1)
2878 {
2879 if (m_borderWidget)
2880 {
2881 XtVaSetValues ((Widget) m_borderWidget, XmNheight, h, NULL);
2882 short thick, margin;
2883 XtVaGetValues ((Widget) m_borderWidget,
2884 XmNshadowThickness, &thick,
2885 XmNmarginHeight, &margin,
2886 NULL);
2887 h -= 2 * (thick + margin);
2888 }
2889
2890 XtVaSetValues ((Widget) m_scrolledWindow, XmNheight, h, NULL);
2891
2892 Dimension spacing;
2893 Widget sbar;
2894 XtVaGetValues ((Widget) m_scrolledWindow,
2895 XmNspacing, &spacing,
2896 XmNhorizontalScrollBar, &sbar,
2897 NULL);
2898 Dimension wsbar;
2899 if (sbar)
2900 XtVaGetValues (sbar, XmNheight, &wsbar, NULL);
2901 else
2902 wsbar = 0;
2903
2904 h -= (spacing + wsbar);
2905
2906 // XtVaSetValues ((Widget) m_drawingArea, XmNheight, h, NULL);
2907
2908 }
50414e24 2909 }
2d120f83
JS
2910
2911 if (managed)
2912 XtManageChild (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
2913 XtVaSetValues((Widget) m_drawingArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
2914
2915 /*
2916 int ww, hh;
2917 GetClientSize (&ww, &hh);
2918 wxSizeEvent sizeEvent(wxSize(ww, hh), GetId());
2919 sizeEvent.SetEventObject(this);
2920
2921 GetEventHandler()->ProcessEvent(sizeEvent);
2922 */
2923
50414e24
JS
2924}
2925
2926void wxWindow::CanvasSetClientSize (int w, int h)
2927{
2d120f83
JS
2928 Widget drawingArea = (Widget) m_drawingArea;
2929
2930 XtVaSetValues((Widget) m_drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
2931
2932 if (w > -1)
2933 XtVaSetValues ((Widget) m_drawingArea, XmNwidth, w, NULL);
2934 if (h > -1)
2935 XtVaSetValues ((Widget) m_drawingArea, XmNheight, h, NULL);
2936 /* TODO: is this necessary?
2937 allowRepainting = FALSE;
2938
2939 XSync (XtDisplay (drawingArea), FALSE);
2940 XEvent event;
2941 while (XtAppPending (wxTheApp->appContext))
2942 {
2943 XFlush (XtDisplay (drawingArea));
2944 XtAppNextEvent (wxTheApp->appContext, &event);
2945 XtDispatchEvent (&event);
2946 }
2947 */
2948
2949 XtVaSetValues((Widget) m_drawingArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
2950
2951 /* TODO
2952 allowRepainting = TRUE;
2953 DoRefresh ();
2954 */
2955
2956 /*
2957 wxSizeEvent sizeEvent(wxSize(w, h), GetId());
2958 sizeEvent.SetEventObject(this);
2959
2960 GetEventHandler()->ProcessEvent(sizeEvent);
50414e24 2961 */
50414e24
JS
2962}
2963
2964void wxWindow::CanvasGetClientSize (int *w, int *h) const
2965{
2d120f83
JS
2966 // Must return the same thing that was set via SetClientSize
2967 Dimension xx, yy;
2968 XtVaGetValues ((Widget) m_drawingArea, XmNwidth, &xx, XmNheight, &yy, NULL);
2969 *w = xx;
2970 *h = yy;
50414e24
JS
2971}
2972
2973void wxWindow::CanvasGetSize (int *w, int *h) const
2974{
2d120f83
JS
2975 Dimension xx, yy;
2976 if ((Widget) m_borderWidget)
2977 XtVaGetValues ((Widget) m_borderWidget, XmNwidth, &xx, XmNheight, &yy, NULL);
2978 else if ((Widget) m_scrolledWindow)
2979 XtVaGetValues ((Widget) m_scrolledWindow, XmNwidth, &xx, XmNheight, &yy, NULL);
2980 else
2981 XtVaGetValues ((Widget) m_drawingArea, XmNwidth, &xx, XmNheight, &yy, NULL);
2982
2983 *w = xx;
2984 *h = yy;
50414e24
JS
2985}
2986
2987void wxWindow::CanvasGetPosition (int *x, int *y) const
2988{
a4294b78
JS
2989 Position xx, yy;
2990 XtVaGetValues (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow, XmNx, &xx, XmNy, &yy, NULL);
2d120f83 2991
a4294b78
JS
2992 // We may be faking the client origin.
2993 // So a window that's really at (0, 30) may appear
2994 // (to wxWin apps) to be at (0, 0).
2995 if (GetParent())
2996 {
2997 wxPoint pt(GetParent()->GetClientAreaOrigin());
2998 xx -= pt.x;
2999 yy -= pt.y;
3000 }
2d120f83 3001
a4294b78
JS
3002 *x = xx;
3003 *y = yy;
50414e24 3004}
02e8b2f9
JS
3005
3006// Add to hash table, add event handler
3007bool wxWindow::AttachWidget (wxWindow* parent, WXWidget mainWidget,
2d120f83 3008 WXWidget formWidget, int x, int y, int width, int height)
02e8b2f9
JS
3009{
3010 wxAddWindowToTable((Widget) mainWidget, this);
3011 if (CanAddEventHandler())
3012 {
3013 XtAddEventHandler((Widget) mainWidget,
2d120f83
JS
3014 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, // | KeyPressMask,
3015 False,
3016 wxPanelItemEventHandler,
3017 (XtPointer) this);
02e8b2f9 3018 }
2d120f83 3019
02e8b2f9
JS
3020 if (!formWidget)
3021 {
3022 XtTranslations ptr;
3023 XtOverrideTranslations ((Widget) mainWidget,
2d120f83 3024 ptr = XtParseTranslationTable ("<Configure>: resize()"));
02e8b2f9
JS
3025 XtFree ((char *) ptr);
3026 }
2d120f83 3027
02e8b2f9
JS
3028 // Some widgets have a parent form widget, e.g. wxRadioBox
3029 if (formWidget)
3030 {
2d120f83
JS
3031 if (!wxAddWindowToTable((Widget) formWidget, this))
3032 return FALSE;
3033
3034 XtTranslations ptr;
3035 XtOverrideTranslations ((Widget) formWidget,
3036 ptr = XtParseTranslationTable ("<Configure>: resize()"));
3037 XtFree ((char *) ptr);
02e8b2f9 3038 }
2d120f83 3039
02e8b2f9 3040 if (x == -1)
2d120f83 3041 x = 0;
02e8b2f9 3042 if (y == -1)
2d120f83 3043 y = 0;
02e8b2f9 3044 SetSize (x, y, width, height);
2d120f83 3045
02e8b2f9
JS
3046 return TRUE;
3047}
3048
3049// Remove event handler, remove from hash table
3050bool wxWindow::DetachWidget(WXWidget widget)
3051{
3052 if (CanAddEventHandler())
3053 {
2d120f83
JS
3054 XtRemoveEventHandler((Widget) widget,
3055 ButtonPressMask | ButtonReleaseMask | PointerMotionMask, // | KeyPressMask,
3056 False,
3057 wxPanelItemEventHandler,
3058 (XtPointer)this);
02e8b2f9 3059 }
2d120f83 3060
02e8b2f9
JS
3061 wxDeleteWindowFromTable((Widget) widget);
3062 return TRUE;
3063}
3064
3065void wxPanelItemEventHandler (Widget wid,
3066 XtPointer client_data,
3067 XEvent* event,
3068 Boolean *continueToDispatch)
3069{
2d120f83
JS
3070 // Widget can be a label or the actual widget.
3071
3072 wxWindow *window = (wxWindow *)wxWidgetHashTable->Get((long)wid);
3073 if (window)
02e8b2f9 3074 {
2d120f83
JS
3075 wxMouseEvent wxevent(0);
3076 if (wxTranslateMouseEvent(wxevent, window, wid, event))
3077 {
3078 window->GetEventHandler()->ProcessEvent(wxevent);
3079 }
02e8b2f9 3080 }
2d120f83
JS
3081 // TODO: probably the key to allowing default behaviour
3082 // to happen.
3083 // Say we set a m_doDefault flag to FALSE at the start of this
3084 // function. Then in e.g. wxWindow::OnMouseEvent we can
3085 // call Default() which sets this flag to TRUE, indicating
3086 // that default processing can happen. Thus, behaviour can appear
3087 // to be overridden just by adding an event handler and not calling
3088 // wxWindow::OnWhatever.
3089 // ALSO, maybe we can use this instead of the current way of handling
3090 // drawing area events, to simplify things.
3091 *continueToDispatch = True;
02e8b2f9
JS
3092}
3093
8aa04e8b 3094static void wxScrollBarCallback(Widget scrollbar, XtPointer clientData,
2d120f83 3095 XmScaleCallbackStruct *cbs)
47bc1060
JS
3096{
3097 Widget scrolledWindow = XtParent (scrollbar);
3098 wxWindow *win = (wxWindow *) wxWidgetHashTable->Get ((long) scrolledWindow);
3099 int orientation = (int) clientData;
2d120f83 3100
47bc1060
JS
3101 wxEventType eventType = wxEVT_NULL;
3102 switch (cbs->reason)
3103 {
2d120f83 3104 case XmCR_INCREMENT:
47bc1060
JS
3105 {
3106 eventType = wxEVT_SCROLL_LINEDOWN;
3107 break;
3108 }
2d120f83 3109 case XmCR_DECREMENT:
47bc1060
JS
3110 {
3111 eventType = wxEVT_SCROLL_LINEUP;
3112 break;
3113 }
2d120f83 3114 case XmCR_DRAG:
47bc1060
JS
3115 {
3116 eventType = wxEVT_SCROLL_THUMBTRACK;
3117 break;
3118 }
2d120f83 3119 case XmCR_VALUE_CHANGED:
47bc1060
JS
3120 {
3121 // TODO: Should this be intercepted too, or will it cause
3122 // duplicate events?
3123 eventType = wxEVT_SCROLL_THUMBTRACK;
3124 break;
3125 }
2d120f83 3126 case XmCR_PAGE_INCREMENT:
47bc1060
JS
3127 {
3128 eventType = wxEVT_SCROLL_PAGEDOWN;
3129 break;
3130 }
2d120f83 3131 case XmCR_PAGE_DECREMENT:
47bc1060
JS
3132 {
3133 eventType = wxEVT_SCROLL_PAGEUP;
3134 break;
3135 }
2d120f83 3136 case XmCR_TO_TOP:
47bc1060
JS
3137 {
3138 eventType = wxEVT_SCROLL_TOP;
3139 break;
3140 }
2d120f83 3141 case XmCR_TO_BOTTOM:
47bc1060
JS
3142 {
3143 eventType = wxEVT_SCROLL_BOTTOM;
3144 break;
3145 }
2d120f83 3146 default:
47bc1060
JS
3147 {
3148 // Should never get here
3149 wxFAIL_MSG("Unknown scroll event.");
3150 break;
3151 }
3152 }
2d120f83 3153
47bc1060
JS
3154 wxScrollEvent event(eventType, win->GetId());
3155 event.SetEventObject(win);
3156 event.SetPosition(cbs->value);
3157 event.SetOrientation( (orientation == XmHORIZONTAL) ? wxHORIZONTAL : wxVERTICAL );
2d120f83 3158
47bc1060
JS
3159 win->GetEventHandler()->ProcessEvent(event);
3160}
3161
02e8b2f9
JS
3162bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Widget widget, XEvent *xevent)
3163{
2d120f83
JS
3164 switch (xevent->xany.type)
3165 {
02e8b2f9
JS
3166 case EnterNotify:
3167 case LeaveNotify:
3168 case ButtonPress:
3169 case ButtonRelease:
3170 case MotionNotify:
02e8b2f9 3171 {
2d120f83
JS
3172 wxEventType eventType = wxEVT_NULL;
3173
3174 if (xevent->xany.type == LeaveNotify)
3175 {
3176 win->m_button1Pressed = FALSE;
3177 win->m_button2Pressed = FALSE;
3178 win->m_button3Pressed = FALSE;
3179 return FALSE;
3180 }
3181 else if (xevent->xany.type == MotionNotify)
3182 {
3183 eventType = wxEVT_MOTION;
3184 }
3185 else if (xevent->xany.type == ButtonPress)
3186 {
3187 if (xevent->xbutton.button == Button1)
3188 {
3189 eventType = wxEVT_LEFT_DOWN;
3190 win->m_button1Pressed = TRUE;
3191 }
3192 else if (xevent->xbutton.button == Button2)
3193 {
3194 eventType = wxEVT_MIDDLE_DOWN;
3195 win->m_button2Pressed = TRUE;
3196 }
3197 else if (xevent->xbutton.button == Button3)
3198 {
3199 eventType = wxEVT_RIGHT_DOWN;
3200 win->m_button3Pressed = TRUE;
3201 }
3202 }
3203 else if (xevent->xany.type == ButtonRelease)
3204 {
3205 if (xevent->xbutton.button == Button1)
3206 {
3207 eventType = wxEVT_LEFT_UP;
3208 win->m_button1Pressed = FALSE;
3209 }
3210 else if (xevent->xbutton.button == Button2)
3211 {
3212 eventType = wxEVT_MIDDLE_UP;
3213 win->m_button2Pressed = FALSE;
3214 }
3215 else if (xevent->xbutton.button == Button3)
3216 {
3217 eventType = wxEVT_RIGHT_UP;
3218 win->m_button3Pressed = FALSE;
3219 }
3220 else return FALSE;
3221 }
3222 else return FALSE;
3223
3224 wxevent.m_eventHandle = (char *)xevent;
3225 wxevent.SetEventType(eventType);
3226
3227 Position x1, y1;
3228 XtVaGetValues(widget, XmNx, &x1, XmNy, &y1, NULL);
3229
3230 int x2, y2;
3231 win->GetPosition(&x2, &y2);
3232
3233 // The button x/y must be translated to wxWindows
3234 // window space - the widget might be a label or button,
3235 // within a form.
3236 int dx = 0;
3237 int dy = 0;
3238 if (widget != (Widget)win->GetMainWidget())
3239 {
3240 dx = x1;
3241 dy = y1;
3242 }
3243
3244 wxevent.m_x = xevent->xbutton.x + dx;
3245 wxevent.m_y = xevent->xbutton.y + dy;
3246
3247 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
3248 || (event_left_is_down (xevent)
3249 && (eventType != wxEVT_LEFT_UP)));
3250 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
3251 || (event_middle_is_down (xevent)
3252 && (eventType != wxEVT_MIDDLE_UP)));
3253 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
3254 || (event_right_is_down (xevent)
3255 && (eventType != wxEVT_RIGHT_UP)));
3256
3257 wxevent.m_shiftDown = xevent->xbutton.state & ShiftMask;
3258 wxevent.m_controlDown = xevent->xbutton.state & ControlMask;
3259 return TRUE;
3260 }
02e8b2f9 3261 }
2d120f83 3262 return FALSE;
02e8b2f9
JS
3263}
3264
3265bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Widget widget, XEvent *xevent)
3266{
2d120f83
JS
3267 switch (xevent->xany.type)
3268 {
02e8b2f9 3269 case KeyPress:
2d120f83
JS
3270 {
3271 char buf[20];
3272
3273 KeySym keySym;
3274 // XComposeStatus compose;
3275 // (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, &compose);
3276 (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, NULL);
3277 int id = wxCharCodeXToWX (keySym);
3278
3279 if (xevent->xkey.state & ShiftMask)
3280 wxevent.m_shiftDown = TRUE;
3281 if (xevent->xkey.state & ControlMask)
3282 wxevent.m_controlDown = TRUE;
3283 if (xevent->xkey.state & Mod3Mask)
3284 wxevent.m_altDown = TRUE;
3285 if (xevent->xkey.state & Mod1Mask)
3286 wxevent.m_metaDown = TRUE;
3287 wxevent.SetEventObject(win);
3288 wxevent.m_keyCode = id;
3289 wxevent.SetTimestamp(xevent->xkey.time);
3290
3291 wxevent.m_x = xevent->xbutton.x;
3292 wxevent.m_y = xevent->xbutton.y;
3293
3294 if (id > -1)
3295 return TRUE;
3296 else
3297 return FALSE;
3298 break;
3299 }
02e8b2f9 3300 default:
2d120f83
JS
3301 break;
3302 }
3303 return FALSE;
02e8b2f9
JS
3304}
3305
02e8b2f9 3306#define YAllocColor XAllocColor
0d57be45
JS
3307XColor g_itemColors[5];
3308int wxComputeColours (Display *display, wxColour * back, wxColour * fore)
02e8b2f9 3309{
2d120f83
JS
3310 int result;
3311 static XmColorProc colorProc;
3312
3313 result = wxNO_COLORS;
3314
3315 if (back)
02e8b2f9 3316 {
2d120f83
JS
3317 g_itemColors[0].red = (((long) back->Red ()) << 8);
3318 g_itemColors[0].green = (((long) back->Green ()) << 8);
3319 g_itemColors[0].blue = (((long) back->Blue ()) << 8);
3320 g_itemColors[0].flags = DoRed | DoGreen | DoBlue;
3321 if (colorProc == (XmColorProc) NULL)
3322 {
3323 // Get a ptr to the actual function
3324 colorProc = XmSetColorCalculation ((XmColorProc) NULL);
3325 // And set it back to motif.
3326 XmSetColorCalculation (colorProc);
3327 }
3328 (*colorProc) (&g_itemColors[wxBACK_INDEX],
3329 &g_itemColors[wxFORE_INDEX],
3330 &g_itemColors[wxSELE_INDEX],
3331 &g_itemColors[wxTOPS_INDEX],
3332 &g_itemColors[wxBOTS_INDEX]);
3333 result = wxBACK_COLORS;
02e8b2f9 3334 }
2d120f83 3335 if (fore)
02e8b2f9 3336 {
2d120f83
JS
3337 g_itemColors[wxFORE_INDEX].red = (((long) fore->Red ()) << 8);
3338 g_itemColors[wxFORE_INDEX].green = (((long) fore->Green ()) << 8);
3339 g_itemColors[wxFORE_INDEX].blue = (((long) fore->Blue ()) << 8);
3340 g_itemColors[wxFORE_INDEX].flags = DoRed | DoGreen | DoBlue;
3341 if (result == wxNO_COLORS)
3342 result = wxFORE_COLORS;
02e8b2f9 3343 }
2d120f83
JS
3344
3345 Display *dpy = display;
3346 Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy);
3347
3348 if (back)
02e8b2f9 3349 {
2d120f83
JS
3350 /* 5 Colours to allocate */
3351 for (int i = 0; i < 5; i++)
3352 if (!YAllocColor (dpy, cmap, &g_itemColors[i]))
3353 result = wxNO_COLORS;
02e8b2f9 3354 }
2d120f83 3355 else if (fore)
02e8b2f9 3356 {
2d120f83
JS
3357 /* Only 1 colour to allocate */
3358 if (!YAllocColor (dpy, cmap, &g_itemColors[wxFORE_INDEX]))
3359 result = wxNO_COLORS;
02e8b2f9 3360 }
2d120f83
JS
3361
3362 return (result);
3363
02e8b2f9
JS
3364}
3365
0d57be45
JS
3366// Changes the foreground and background colours to be derived
3367// from the current background colour.
3368// To change the foreground colour, you must call SetForegroundColour
3369// explicitly.
3370void wxWindow::ChangeBackgroundColour()
02e8b2f9 3371{
0d57be45
JS
3372 if (GetMainWidget())
3373 DoChangeBackgroundColour(GetMainWidget(), m_backgroundColour);
2d120f83 3374
b412f9be
JS
3375 // This not necessary
3376#if 0
2d120f83 3377
88150e60 3378 if (m_scrolledWindow && (GetMainWidget() != m_scrolledWindow))
b412f9be 3379 {
88150e60 3380 DoChangeBackgroundColour(m_scrolledWindow, m_backgroundColour);
b412f9be
JS
3381 // Have to set the scrollbar colours back since
3382 // the scrolled window seemed to change them
3383 wxColour backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE) ;
2d120f83 3384
b412f9be 3385 if (m_hScrollBar)
2d120f83 3386 DoChangeBackgroundColour(m_hScrollBar, backgroundColour);
b412f9be 3387 if (m_vScrollBar)
2d120f83 3388 DoChangeBackgroundColour(m_vScrollBar, backgroundColour);
b412f9be
JS
3389 }
3390#endif
0d57be45 3391}
02e8b2f9 3392
0d57be45
JS
3393void wxWindow::ChangeForegroundColour()
3394{
3395 if (GetMainWidget())
3396 DoChangeForegroundColour(GetMainWidget(), m_foregroundColour);
88150e60
JS
3397 if (m_scrolledWindow && (GetMainWidget() != m_scrolledWindow))
3398 DoChangeForegroundColour(m_scrolledWindow, m_foregroundColour);
0d57be45 3399}
02e8b2f9 3400
0d57be45
JS
3401// Change a widget's foreground and background colours.
3402
0d57be45
JS
3403void wxWindow::DoChangeForegroundColour(WXWidget widget, wxColour& foregroundColour)
3404{
2d120f83
JS
3405 // When should we specify the foreground, if it's calculated
3406 // by wxComputeColours?
3407 // Solution: say we start with the default (computed) foreground colour.
3408 // If we call SetForegroundColour explicitly for a control or window,
3409 // then the foreground is changed.
3410 // Therefore SetBackgroundColour computes the foreground colour, and
3411 // SetForegroundColour changes the foreground colour. The ordering is
3412 // important.
3413
3414 XtVaSetValues ((Widget) widget,
3415 XmNforeground, foregroundColour.AllocColour(XtDisplay((Widget) widget)),
3416 NULL);
0d57be45
JS
3417}
3418
3419void wxWindow::DoChangeBackgroundColour(WXWidget widget, wxColour& backgroundColour, bool changeArmColour)
3420{
2d120f83
JS
3421 wxComputeColours (XtDisplay((Widget) widget), & backgroundColour,
3422 (wxColour*) NULL);
3423
0d57be45 3424 XtVaSetValues ((Widget) widget,
2d120f83
JS
3425 XmNbackground, g_itemColors[wxBACK_INDEX].pixel,
3426 XmNtopShadowColor, g_itemColors[wxTOPS_INDEX].pixel,
3427 XmNbottomShadowColor, g_itemColors[wxBOTS_INDEX].pixel,
3428 XmNforeground, g_itemColors[wxFORE_INDEX].pixel,
3429 NULL);
3430
3431 if (changeArmColour)
3432 XtVaSetValues ((Widget) widget,
3433 XmNarmColor, g_itemColors[wxSELE_INDEX].pixel,
3434 NULL);
02e8b2f9
JS
3435}
3436
0d57be45 3437void wxWindow::SetBackgroundColour(const wxColour& col)
02e8b2f9 3438{
0d57be45
JS
3439 m_backgroundColour = col;
3440 ChangeBackgroundColour();
3441}
3442
3443void wxWindow::SetForegroundColour(const wxColour& col)
3444{
3445 m_foregroundColour = col;
3446 ChangeForegroundColour();
3447}
3448
4b5f3fe6 3449void wxWindow::ChangeFont(bool keepOriginalSize)
0d57be45
JS
3450{
3451 // Note that this causes the widget to be resized back
3452 // to its original size! We therefore have to set the size
3453 // back again. TODO: a better way in Motif?
0d57be45
JS
3454 Widget w = (Widget) GetLabelWidget(); // Usually the main widget
3455 if (w && m_windowFont.Ok())
3456 {
3457 int width, height, width1, height1;
3458 GetSize(& width, & height);
2d120f83
JS
3459
3460 // lesstif 0.87 hangs here
32c69f2c 3461#ifndef LESSTIF_VERSION
0d57be45 3462 XtVaSetValues (w,
2d120f83
JS
3463 XmNfontList, (XmFontList) m_windowFont.GetFontList(1.0, XtDisplay(w)),
3464 NULL);
32c69f2c 3465#endif
2d120f83 3466
0d57be45 3467 GetSize(& width1, & height1);
4b5f3fe6 3468 if (keepOriginalSize && (width != width1 || height != height1))
0d57be45
JS
3469 {
3470 SetSize(-1, -1, width, height);
3471 }
3472 }
02e8b2f9 3473}
0d57be45
JS
3474
3475void wxWindow::SetFont(const wxFont& font)
3476{
3477 m_windowFont = font;
3478 ChangeFont();
3479}
3480
1f112209
JS
3481void wxWindow::SetToolTip(const wxString& tooltip)
3482{
3483 // TODO
3484}
3485
55acd85e
JS
3486void wxWindow::ClearUpdateRects()
3487{
3488 wxNode* node = m_updateRects.First();
3489 while (node)
3490 {
3491 wxRect* rect = (wxRect*) node->Data();
3492 delete rect;
3493 node = node->Next();
3494 }
3495 m_updateRects.Clear();
3496}
8aa04e8b
JS
3497
3498bool wxWindow::ProcessAccelerator(wxKeyEvent& event)
3499{
3500 if (!m_acceleratorTable.Ok())
3501 return FALSE;
2d120f83 3502
8aa04e8b
JS
3503 int count = m_acceleratorTable.GetCount();
3504 wxAcceleratorEntry* entries = m_acceleratorTable.GetEntries();
3505 int i;
3506 for (i = 0; i < count; i++)
3507 {
3508 wxAcceleratorEntry* entry = & (entries[i]);
3509 if (entry->MatchesEvent(event))
3510 {
3511 // Bingo, we have a match. Now find a control
3512 // that matches the entry command id.
2d120f83 3513
8aa04e8b
JS
3514 // Need to go up to the top of the window hierarchy,
3515 // since it might be e.g. a menu item
3516 wxWindow* parent = this;
3517 while (parent && !parent->IsKindOf(CLASSINFO(wxFrame)) && !parent->IsKindOf(CLASSINFO(wxDialog)))
3518 parent = parent->GetParent();
2d120f83 3519
8aa04e8b
JS
3520 if (!parent)
3521 return FALSE;
2d120f83 3522
8aa04e8b
JS
3523 if (parent->IsKindOf(CLASSINFO(wxFrame)))
3524 {
3525 // Try for a menu command
3526 wxFrame* frame = (wxFrame*) parent;
3527 if (frame->GetMenuBar())
3528 {
3529 wxMenuItem* item = frame->GetMenuBar()->FindItemForId(entry->GetCommand());
3530 if (item)
3531 {
3532 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, entry->GetCommand());
3533 commandEvent.SetEventObject(frame);
2d120f83 3534
8aa04e8b
JS
3535 // If ProcessEvent returns TRUE (it was handled), then
3536 // the calling code will skip the event handling.
3537 return frame->GetEventHandler()->ProcessEvent(commandEvent);
3538 }
3539 }
3540 }
2d120f83 3541
8aa04e8b
JS
3542 // Find a child matching the command id
3543 wxWindow* child = parent->FindWindow(entry->GetCommand());
2d120f83 3544
8aa04e8b
JS
3545 // No such child
3546 if (!child)
3547 return FALSE;
2d120f83 3548
8aa04e8b
JS
3549 // Now we process those kinds of windows that we can.
3550 // For now, only buttons.
3551 if (child->IsKindOf(CLASSINFO(wxButton)))
3552 {
3553 wxCommandEvent commandEvent (wxEVT_COMMAND_BUTTON_CLICKED, child->GetId());
3554 commandEvent.SetEventObject(child);
3555 return child->GetEventHandler()->ProcessEvent(commandEvent);
3556 }
2d120f83 3557
8aa04e8b
JS
3558 return FALSE;
3559 } // matches event
3560 }// for
2d120f83 3561
8aa04e8b
JS
3562 // We didn't match the key event against an accelerator.
3563 return FALSE;
3564}
3565
88150e60 3566/*
2d120f83
JS
3567* wxNoOptimize: switch off size optimization
3568*/
88150e60
JS
3569
3570int wxNoOptimize::m_count = 0;
3571
3572wxNoOptimize::wxNoOptimize()
3573{
2d120f83 3574 m_count ++;
88150e60
JS
3575}
3576
3577wxNoOptimize::~wxNoOptimize()
3578{
2d120f83 3579 m_count --;
88150e60
JS
3580}
3581
3582bool wxNoOptimize::CanOptimize()
3583{
2d120f83 3584 return (m_count == 0);
88150e60
JS
3585}
3586