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