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