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