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