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