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