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