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