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