]> git.saurik.com Git - wxWidgets.git/blob - src/x11/window.cpp
wxX11:
[wxWidgets.git] / src / x11 / window.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: windows.cpp
3 // Purpose: wxWindow
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 17/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "window.h"
22 #endif
23
24 #include "wx/setup.h"
25 #include "wx/menu.h"
26 #include "wx/dc.h"
27 #include "wx/dcclient.h"
28 #include "wx/utils.h"
29 #include "wx/app.h"
30 #include "wx/panel.h"
31 #include "wx/layout.h"
32 #include "wx/dialog.h"
33 #include "wx/listbox.h"
34 #include "wx/button.h"
35 #include "wx/settings.h"
36 #include "wx/msgdlg.h"
37 #include "wx/frame.h"
38 #include "wx/scrolwin.h"
39 #include "wx/module.h"
40 #include "wx/menuitem.h"
41 #include "wx/log.h"
42
43 #if wxUSE_DRAG_AND_DROP
44 #include "wx/dnd.h"
45 #endif
46
47 #include "wx/x11/private.h"
48 #include "X11/Xutil.h"
49
50 #include <string.h>
51
52 // ----------------------------------------------------------------------------
53 // constants
54 // ----------------------------------------------------------------------------
55
56 static const int SCROLL_MARGIN = 4;
57
58 // ----------------------------------------------------------------------------
59 // global variables for this module
60 // ----------------------------------------------------------------------------
61
62 extern wxHashTable *wxWidgetHashTable;
63 static wxWindow* g_captureWindow = NULL;
64
65 // ----------------------------------------------------------------------------
66 // macros
67 // ----------------------------------------------------------------------------
68
69 #define event_left_is_down(x) ((x)->xbutton.state & Button1Mask)
70 #define event_middle_is_down(x) ((x)->xbutton.state & Button2Mask)
71 #define event_right_is_down(x) ((x)->xbutton.state & Button3Mask)
72
73 // ----------------------------------------------------------------------------
74 // event tables
75 // ----------------------------------------------------------------------------
76
77 IMPLEMENT_DYNAMIC_CLASS(wxWindowX11, wxWindowBase)
78
79 BEGIN_EVENT_TABLE(wxWindowX11, wxWindowBase)
80 EVT_SYS_COLOUR_CHANGED(wxWindowX11::OnSysColourChanged)
81 EVT_IDLE(wxWindowX11::OnIdle)
82 END_EVENT_TABLE()
83
84 // ============================================================================
85 // implementation
86 // ============================================================================
87
88 // ----------------------------------------------------------------------------
89 // helper functions
90 // ----------------------------------------------------------------------------
91
92 // ----------------------------------------------------------------------------
93 // constructors
94 // ----------------------------------------------------------------------------
95
96 void wxWindowX11::Init()
97 {
98 // generic initializations first
99 InitBase();
100
101 // X11-specific
102 // TODO: prune those that are no longer needed
103 m_needsRefresh = TRUE;
104 m_mainWidget = (WXWindow) 0;
105
106 m_winCaptured = FALSE;
107
108 m_isShown = TRUE;
109 m_isBeingDeleted = FALSE;
110
111 m_hScrollBar =
112 m_vScrollBar =
113 m_borderWidget =
114 m_scrolledWindow =
115 m_drawingArea = (WXWindow) 0;
116
117 m_hScroll =
118 m_vScroll = FALSE;
119
120 m_scrollPosX =
121 m_scrollPosY = 0;
122
123 m_lastTS = 0;
124 m_lastButton = 0;
125 m_canAddEventHandler = FALSE;
126
127 m_borderSize = 0;
128 }
129
130 // real construction (Init() must have been called before!)
131 bool wxWindowX11::Create(wxWindow *parent, wxWindowID id,
132 const wxPoint& pos,
133 const wxSize& size,
134 long style,
135 const wxString& name)
136 {
137 wxCHECK_MSG( parent, FALSE, "can't create wxWindow without parent" );
138
139 CreateBase(parent, id, pos, size, style, wxDefaultValidator, name);
140
141 if (parent)
142 parent->AddChild(this);
143
144 m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
145 m_foregroundColour = *wxBLACK;
146
147 // TODO: How to create more interesting borders?
148 // Will presumably have to create multiple windows.
149 if (style & wxSIMPLE_BORDER)
150 {
151 m_borderSize = 1;
152 } else if (style & wxSUNKEN_BORDER)
153 {
154 m_borderSize = 1;
155 } else if (style & wxRAISED_BORDER)
156 {
157 m_borderSize = 1;
158 }
159
160 int w = size.GetWidth();
161 int h = size.GetHeight();
162 int x = size.GetX();
163 int y = size.GetY();
164 if (w == -1) w = 20;
165 if (h == -1) h = 20;
166 if (x == -1) x = 0;
167 if (y == -1) y = 0;
168
169 int screen = DefaultScreen(wxGlobalDisplay());
170
171 Window parentWindow;
172 if (parent)
173 parentWindow = (Window) parent->GetClientWindow();
174 else
175 parentWindow = RootWindow(wxGlobalDisplay(), screen);
176
177 Window window = XCreateSimpleWindow(wxGlobalDisplay(), parentWindow,
178 x, y, w, h, m_borderSize,
179 m_backgroundColour.AllocColour(wxGlobalDisplay()),
180 m_foregroundColour.AllocColour(wxGlobalDisplay()));
181
182 // Select event types wanted
183 XSelectInput(wxGlobalDisplay(), window,
184 ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
185 ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask |
186 KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask |
187 PropertyChangeMask);
188
189 wxAddWindowToTable(window, (wxWindow*) this);
190
191 // If a subwindow, show.
192 // if (parent && !parent->IsKindOf(CLASSINFO(wxTopLevelWindowX11)) && parent->IsShown())
193 {
194 m_isShown = TRUE;
195 XMapWindow(wxGlobalDisplay(), window);
196 }
197
198 // Without this, the cursor may not be restored properly (e.g. in splitter
199 // sample).
200 SetCursor(*wxSTANDARD_CURSOR);
201 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
202 SetSize(pos.x, pos.y, size.x, size.y);
203
204 return TRUE;
205 }
206
207 // Destructor
208 wxWindowX11::~wxWindowX11()
209 {
210 if (g_captureWindow == this)
211 g_captureWindow = NULL;
212
213 m_isBeingDeleted = TRUE;
214
215 // X11-specific actions first
216 WXWindow wMain = GetMainWindow();
217 if ( wMain )
218 {
219 // Removes event handlers
220 //DetachWidget(wMain);
221 }
222
223 if ( m_parent )
224 m_parent->RemoveChild( this );
225
226 // TODO
227
228 #if 0
229 // If m_drawingArea, we're a fully-fledged window with drawing area,
230 // scrollbars etc. (what wxCanvas used to be)
231 if ( m_drawingArea )
232 {
233 // Destroy children before destroying self
234 DestroyChildren();
235
236 if (m_backingPixmap)
237 XFreePixmap (XtDisplay ((Widget) GetMainWidget()), (Pixmap) m_backingPixmap);
238
239 Widget w = (Widget) m_drawingArea;
240 wxDeleteWindowFromTable(w);
241
242 if (w)
243 {
244 XtDestroyWidget(w);
245 m_drawingArea = (WXWidget) 0;
246 }
247
248 // Only if we're _really_ a canvas (not a dialog box/panel)
249 if (m_scrolledWindow)
250 {
251 wxDeleteWindowFromTable((Widget) m_scrolledWindow);
252 }
253
254 if (m_hScrollBar)
255 {
256 wxDeleteWindowFromTable((Widget) m_hScrollBar);
257 XtUnmanageChild((Widget) m_hScrollBar);
258 }
259 if (m_vScrollBar)
260 {
261 wxDeleteWindowFromTable((Widget) m_vScrollBar);
262 XtUnmanageChild((Widget) m_vScrollBar);
263 }
264
265 if (m_hScrollBar)
266 XtDestroyWidget((Widget) m_hScrollBar);
267 if (m_vScrollBar)
268 XtDestroyWidget((Widget) m_vScrollBar);
269
270 UnmanageAndDestroy(m_scrolledWindow);
271
272 if (m_borderWidget)
273 {
274 XtDestroyWidget ((Widget) m_borderWidget);
275 m_borderWidget = (WXWidget) 0;
276 }
277 }
278 else // Why wasn't this here before? JACS 8/3/2000
279 #endif
280 DestroyChildren();
281
282
283 // Destroy the window
284 if (GetMainWindow())
285 {
286 XSelectInput(wxGlobalDisplay(), (Window) GetMainWindow(),
287 NoEventMask);
288 wxDeleteWindowFromTable((Window) GetMainWindow());
289 XDestroyWindow(wxGlobalDisplay(), (Window) GetMainWindow());
290 SetMainWindow((WXWindow) NULL);
291 }
292 }
293
294 // ----------------------------------------------------------------------------
295 // scrollbar management
296 // ----------------------------------------------------------------------------
297
298 // Helper function
299 void wxWindowX11::CreateScrollbar(wxOrientation orientation)
300 {
301 // TODO
302 #if 0
303 wxCHECK_RET( m_drawingArea, "this window can't have scrollbars" );
304
305 XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_NONE, NULL);
306
307 // Add scrollbars if required
308 if (orientation == wxHORIZONTAL)
309 {
310 Widget hScrollBar = XtVaCreateManagedWidget ("hsb",
311 xmScrollBarWidgetClass, (Widget) m_scrolledWindow,
312 XmNorientation, XmHORIZONTAL,
313 NULL);
314 XtAddCallback (hScrollBar, XmNvalueChangedCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
315 XtAddCallback (hScrollBar, XmNdragCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
316 XtAddCallback (hScrollBar, XmNincrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
317 XtAddCallback (hScrollBar, XmNdecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
318 XtAddCallback (hScrollBar, XmNpageIncrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
319 XtAddCallback (hScrollBar, XmNpageDecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
320 XtAddCallback (hScrollBar, XmNtoTopCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
321 XtAddCallback (hScrollBar, XmNtoBottomCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
322
323 XtVaSetValues (hScrollBar,
324 XmNincrement, 1,
325 XmNvalue, 0,
326 NULL);
327
328 m_hScrollBar = (WXWidget) hScrollBar;
329
330 wxColour backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
331 DoChangeBackgroundColour(m_hScrollBar, backgroundColour, TRUE);
332
333 XtRealizeWidget(hScrollBar);
334
335 XtVaSetValues((Widget) m_scrolledWindow,
336 XmNhorizontalScrollBar, (Widget) m_hScrollBar,
337 NULL);
338
339 m_hScroll = TRUE;
340
341 wxAddWindowToTable( hScrollBar, this );
342 }
343
344 if (orientation == wxVERTICAL)
345 {
346 Widget vScrollBar = XtVaCreateManagedWidget ("vsb",
347 xmScrollBarWidgetClass, (Widget) m_scrolledWindow,
348 XmNorientation, XmVERTICAL,
349 NULL);
350 XtAddCallback (vScrollBar, XmNvalueChangedCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
351 XtAddCallback (vScrollBar, XmNdragCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
352 XtAddCallback (vScrollBar, XmNincrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
353 XtAddCallback (vScrollBar, XmNdecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
354 XtAddCallback (vScrollBar, XmNpageIncrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
355 XtAddCallback (vScrollBar, XmNpageDecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
356 XtAddCallback (vScrollBar, XmNtoTopCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
357 XtAddCallback (vScrollBar, XmNtoBottomCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
358
359 XtVaSetValues (vScrollBar,
360 XmNincrement, 1,
361 XmNvalue, 0,
362 NULL);
363
364 m_vScrollBar = (WXWidget) vScrollBar;
365 wxColour backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
366 DoChangeBackgroundColour(m_vScrollBar, backgroundColour, TRUE);
367
368 XtRealizeWidget(vScrollBar);
369
370 XtVaSetValues((Widget) m_scrolledWindow,
371 XmNverticalScrollBar, (Widget) m_vScrollBar,
372 NULL);
373
374 m_vScroll = TRUE;
375
376 wxAddWindowToTable( vScrollBar, this );
377 }
378
379 XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_ANY, NULL);
380 #endif
381 }
382
383 void wxWindowX11::DestroyScrollbar(wxOrientation orientation)
384 {
385 // TODO
386 #if 0
387 wxCHECK_RET( m_drawingArea, "this window can't have scrollbars" );
388
389 XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_NONE, NULL);
390 // Add scrollbars if required
391 if (orientation == wxHORIZONTAL)
392 {
393 if (m_hScrollBar)
394 {
395 wxDeleteWindowFromTable((Widget)m_hScrollBar);
396 XtDestroyWidget((Widget) m_hScrollBar);
397 }
398 m_hScrollBar = (WXWidget) 0;
399 m_hScroll = FALSE;
400
401 XtVaSetValues((Widget) m_scrolledWindow,
402 XmNhorizontalScrollBar, (Widget) 0,
403 NULL);
404
405 }
406
407 if (orientation == wxVERTICAL)
408 {
409 if (m_vScrollBar)
410 {
411 wxDeleteWindowFromTable((Widget)m_vScrollBar);
412 XtDestroyWidget((Widget) m_vScrollBar);
413 }
414 m_vScrollBar = (WXWidget) 0;
415 m_vScroll = FALSE;
416
417 XtVaSetValues((Widget) m_scrolledWindow,
418 XmNverticalScrollBar, (Widget) 0,
419 NULL);
420
421 }
422 XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_ANY, NULL);
423 #endif
424 }
425
426 // ---------------------------------------------------------------------------
427 // basic operations
428 // ---------------------------------------------------------------------------
429
430 void wxWindowX11::SetFocus()
431 {
432 #if 0
433 Window wMain = (Window) GetMainWidget();
434 if (wMain)
435 {
436 XSetInputFocus(wxGlobalDisplay(), wMain, RevertToParent, CurrentTime);
437
438 XWMHints wmhints;
439 wmhints.flags = InputHint;
440 wmhints.input = True;
441 XSetWMHints(wxGlobalDisplay(), wMain, &wmhints)
442 }
443 #endif
444 }
445
446 // Get the window with the focus
447 wxWindow *wxWindowBase::FindFocus()
448 {
449 Window wFocus = (Window) 0;
450 int revert = 0;
451
452 XGetInputFocus(wxGlobalDisplay(), & wFocus, & revert);
453 if (wFocus)
454 {
455 wxWindow *win = NULL;
456 do
457 {
458 win = wxGetWindowFromTable(wFocus);
459 wFocus = wxGetWindowParent(wFocus);
460 } while (wFocus && !win);
461
462 return win;
463 }
464
465 return NULL;
466 }
467
468 // Enabling/disabling handled by event loop, and not sending events
469 // if disabled.
470 bool wxWindowX11::Enable(bool enable)
471 {
472 if ( !wxWindowBase::Enable(enable) )
473 return FALSE;
474
475 return TRUE;
476 }
477
478 bool wxWindowX11::Show(bool show)
479 {
480 if ( !wxWindowBase::Show(show) )
481 return FALSE;
482
483 Window xwin = (Window) GetXWindow();
484 Display *xdisp = (Display*) GetXDisplay();
485 if (show)
486 {
487 XMapWindow(xdisp, xwin);
488 }
489 else
490 {
491 XUnmapWindow(xdisp, xwin);
492 }
493
494 return TRUE;
495 }
496
497 // Raise the window to the top of the Z order
498 void wxWindowX11::Raise()
499 {
500 Window window = (Window) GetTopWindow();
501 if (window)
502 XRaiseWindow(wxGlobalDisplay(), window);
503 }
504
505 // Lower the window to the bottom of the Z order
506 void wxWindowX11::Lower()
507 {
508 Window window = (Window) GetTopWindow();
509 if (window)
510 XLowerWindow(wxGlobalDisplay(), window);
511 }
512
513 void wxWindowX11::DoCaptureMouse()
514 {
515 g_captureWindow = (wxWindow*) this;
516 if ( m_winCaptured )
517 return;
518
519 // TODO: should we also call XGrabButton, XGrabKeyboard?
520 if (GetMainWindow())
521 {
522 int res = XGrabPointer(wxGlobalDisplay(), (Window) GetMainWindow(),
523 FALSE,
524 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask,
525 GrabModeAsync,
526 GrabModeAsync,
527 None,
528 None, /* cursor */ // TODO: This may need to be set to the cursor of this window
529 CurrentTime);
530
531 if (res == GrabSuccess)
532 {
533 m_winCaptured = TRUE;
534 }
535 }
536 }
537
538 void wxWindowX11::DoReleaseMouse()
539 {
540 g_captureWindow = NULL;
541 if ( !m_winCaptured )
542 return;
543
544 Window wMain = (Window)GetMainWindow();
545
546 // TODO: should we also call XUngrabButton, XUngrabKeyboard?
547 if ( wMain )
548 XUngrabPointer(wxGlobalDisplay(), wMain);
549
550 m_winCaptured = FALSE;
551 }
552
553 bool wxWindowX11::SetFont(const wxFont& font)
554 {
555 if ( !wxWindowBase::SetFont(font) )
556 {
557 // nothing to do
558 return FALSE;
559 }
560
561 ChangeFont();
562
563 return TRUE;
564 }
565
566 bool wxWindowX11::SetCursor(const wxCursor& cursor)
567 {
568 if ( !wxWindowBase::SetCursor(cursor) )
569 {
570 // no change
571 return FALSE;
572 }
573
574 wxCursor* cursor2 = NULL;
575 if (m_cursor.Ok())
576 cursor2 = & m_cursor;
577 else
578 cursor2 = wxSTANDARD_CURSOR;
579
580 WXDisplay *dpy = GetXDisplay();
581 WXCursor x_cursor = cursor2->GetXCursor(dpy);
582
583 Window win = (Window) GetMainWindow();
584 XDefineCursor((Display*) dpy, win, (Cursor) x_cursor);
585
586 return TRUE;
587 }
588
589 // Coordinates relative to the window
590 void wxWindowX11::WarpPointer (int x, int y)
591 {
592 Window wClient = (Window) GetClientWindow();
593
594 XWarpPointer(wxGlobalDisplay(), None, wClient, 0, 0, 0, 0, x, y);
595 }
596
597 // ---------------------------------------------------------------------------
598 // scrolling stuff
599 // ---------------------------------------------------------------------------
600
601 int wxWindowX11::GetScrollPos(int orient) const
602 {
603 if (orient == wxHORIZONTAL)
604 return m_scrollPosX;
605 else
606 return m_scrollPosY;
607 }
608
609 // This now returns the whole range, not just the number of positions that we
610 // can scroll.
611 int wxWindowX11::GetScrollRange(int WXUNUSED(orient)) const
612 {
613 // TODO
614 return 0;
615 #if 0
616 Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
617 wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
618
619 int range;
620 XtVaGetValues(scrollBar, XmNmaximum, &range, NULL);
621 return range;
622 #endif
623 }
624
625 int wxWindowX11::GetScrollThumb(int orient) const
626 {
627 // TODO
628 return 0;
629
630 #if 0
631 Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
632 wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
633
634 int thumb;
635 XtVaGetValues(scrollBar, XmNsliderSize, &thumb, NULL);
636 return thumb;
637 #endif
638 }
639
640 void wxWindowX11::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
641 {
642 // TODO
643
644 #if 0
645 Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
646
647 if ( scrollBar )
648 {
649 XtVaSetValues (scrollBar, XmNvalue, pos, NULL);
650 }
651 #endif
652 SetInternalScrollPos((wxOrientation)orient, pos);
653 }
654
655 // New function that will replace some of the above.
656 void wxWindowX11::SetScrollbar(int WXUNUSED(orient), int WXUNUSED(pos), int WXUNUSED(thumbVisible),
657 int WXUNUSED(range), bool WXUNUSED(refresh))
658 {
659 // TODO
660 #if 0
661 int oldW, oldH;
662 GetSize(& oldW, & oldH);
663
664 if (range == 0)
665 range = 1;
666 if (thumbVisible == 0)
667 thumbVisible = 1;
668
669 if (thumbVisible > range)
670 thumbVisible = range;
671
672 // Save the old state to see if it changed
673 WXWidget oldScrollBar = GetScrollbar((wxOrientation)orient);
674
675 if (orient == wxHORIZONTAL)
676 {
677 if (thumbVisible == range)
678 {
679 if (m_hScrollBar)
680 DestroyScrollbar(wxHORIZONTAL);
681 }
682 else
683 {
684 if (!m_hScrollBar)
685 CreateScrollbar(wxHORIZONTAL);
686 }
687 }
688 if (orient == wxVERTICAL)
689 {
690 if (thumbVisible == range)
691 {
692 if (m_vScrollBar)
693 DestroyScrollbar(wxVERTICAL);
694 }
695 else
696 {
697 if (!m_vScrollBar)
698 CreateScrollbar(wxVERTICAL);
699 }
700 }
701 WXWidget newScrollBar = GetScrollbar((wxOrientation)orient);
702
703 if (oldScrollBar != newScrollBar)
704 {
705 // This is important! Without it, scrollbars misbehave badly.
706 XtUnrealizeWidget((Widget) m_scrolledWindow);
707 XmScrolledWindowSetAreas ((Widget) m_scrolledWindow, (Widget) m_hScrollBar, (Widget) m_vScrollBar, (Widget) m_drawingArea);
708 XtRealizeWidget((Widget) m_scrolledWindow);
709 XtManageChild((Widget) m_scrolledWindow);
710 }
711
712 if (newScrollBar)
713 {
714 XtVaSetValues((Widget) newScrollBar,
715 XmNvalue, pos,
716 XmNminimum, 0,
717 XmNmaximum, range,
718 XmNsliderSize, thumbVisible,
719 NULL);
720 }
721
722 SetInternalScrollPos((wxOrientation)orient, pos);
723
724 int newW, newH;
725 GetSize(& newW, & newH);
726
727 // Adjusting scrollbars can resize the canvas accidentally
728 if (newW != oldW || newH != oldH)
729 SetSize(-1, -1, oldW, oldH);
730 #endif
731 }
732
733 // Does a physical scroll
734 void wxWindowX11::ScrollWindow(int dx, int dy, const wxRect *rect)
735 {
736 int x, y, w, h;
737 if (rect)
738 {
739 // Use specified rectangle
740 x = rect->x; y = rect->y; w = rect->width; h = rect->height;
741 }
742 else
743 {
744 // Use whole client area
745 x = 0; y = 0;
746 GetClientSize(& w, & h);
747 }
748
749 wxNode *cnode = m_children.First();
750 while (cnode)
751 {
752 wxWindow *child = (wxWindow*) cnode->Data();
753 int sx = 0;
754 int sy = 0;
755 child->GetSize( &sx, &sy );
756 wxPoint pos( child->GetPosition() );
757 child->SetSize( pos.x + dx, pos.y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
758 cnode = cnode->Next();
759 }
760
761 int x1 = (dx >= 0) ? x : x - dx;
762 int y1 = (dy >= 0) ? y : y - dy;
763 int w1 = w - abs(dx);
764 int h1 = h - abs(dy);
765 int x2 = (dx >= 0) ? x + dx : x;
766 int y2 = (dy >= 0) ? y + dy : y;
767
768 wxClientDC dc((wxWindow*) this);
769
770 dc.SetLogicalFunction (wxCOPY);
771
772 Window window = (Window) GetMainWindow();
773 Display* display = wxGlobalDisplay();
774
775 XCopyArea(display, window, window, (GC) dc.GetGC(),
776 x1, y1, w1, h1, x2, y2);
777
778 dc.SetAutoSetting(TRUE);
779 wxBrush brush(GetBackgroundColour(), wxSOLID);
780 dc.SetBrush(brush); // FIXME: needed?
781
782 // We'll add rectangles to the list of update rectangles according to which
783 // bits we've exposed.
784 wxList updateRects;
785
786 if (dx > 0)
787 {
788 wxRect *rect = new wxRect;
789 rect->x = x;
790 rect->y = y;
791 rect->width = dx;
792 rect->height = h;
793
794 XFillRectangle(display, window,
795 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
796
797 rect->x = rect->x;
798 rect->y = rect->y;
799 rect->width = rect->width;
800 rect->height = rect->height;
801
802 updateRects.Append((wxObject*) rect);
803 }
804 else if (dx < 0)
805 {
806 wxRect *rect = new wxRect;
807
808 rect->x = x + w + dx;
809 rect->y = y;
810 rect->width = -dx;
811 rect->height = h;
812
813 XFillRectangle(display, window,
814 (GC) dc.GetGC(), rect->x, rect->y, rect->width,
815 rect->height);
816
817 rect->x = rect->x;
818 rect->y = rect->y;
819 rect->width = rect->width;
820 rect->height = rect->height;
821
822 updateRects.Append((wxObject*) rect);
823 }
824 if (dy > 0)
825 {
826 wxRect *rect = new wxRect;
827
828 rect->x = x;
829 rect->y = y;
830 rect->width = w;
831 rect->height = dy;
832
833 XFillRectangle(display, window,
834 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
835
836 rect->x = rect->x;
837 rect->y = rect->y;
838 rect->width = rect->width;
839 rect->height = rect->height;
840
841 updateRects.Append((wxObject*) rect);
842 }
843 else if (dy < 0)
844 {
845 wxRect *rect = new wxRect;
846
847 rect->x = x;
848 rect->y = y + h + dy;
849 rect->width = w;
850 rect->height = -dy;
851
852 XFillRectangle(display, window,
853 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
854
855 rect->x = rect->x;
856 rect->y = rect->y;
857 rect->width = rect->width;
858 rect->height = rect->height;
859
860 updateRects.Append((wxObject*) rect);
861 }
862 dc.SetBrush(wxNullBrush);
863
864 // Now send expose events
865
866 wxNode* node = updateRects.First();
867 while (node)
868 {
869 wxRect* rect = (wxRect*) node->Data();
870 XExposeEvent event;
871
872 event.type = Expose;
873 event.display = display;
874 event.send_event = True;
875 event.window = window;
876
877 event.x = rect->x;
878 event.y = rect->y;
879 event.width = rect->width;
880 event.height = rect->height;
881
882 event.count = 0;
883
884 XSendEvent(display, window, False, ExposureMask, (XEvent *)&event);
885
886 node = node->Next();
887
888 }
889
890 // Delete the update rects
891 node = updateRects.First();
892 while (node)
893 {
894 wxRect* rect = (wxRect*) node->Data();
895 delete rect;
896 node = node->Next();
897 }
898
899 // TODO
900
901 // XmUpdateDisplay((Widget) GetMainWidget());
902 }
903
904 // ---------------------------------------------------------------------------
905 // drag and drop
906 // ---------------------------------------------------------------------------
907
908 #if wxUSE_DRAG_AND_DROP
909
910 void wxWindowX11::SetDropTarget(wxDropTarget * WXUNUSED(pDropTarget))
911 {
912 // TODO
913 }
914
915 #endif
916
917 // Old style file-manager drag&drop
918 void wxWindowX11::DragAcceptFiles(bool WXUNUSED(accept))
919 {
920 // TODO
921 }
922
923 // ----------------------------------------------------------------------------
924 // tooltips
925 // ----------------------------------------------------------------------------
926
927 #if wxUSE_TOOLTIPS
928
929 void wxWindowX11::DoSetToolTip(wxToolTip * WXUNUSED(tooltip))
930 {
931 // TODO
932 }
933
934 #endif // wxUSE_TOOLTIPS
935
936 // ---------------------------------------------------------------------------
937 // moving and resizing
938 // ---------------------------------------------------------------------------
939
940 bool wxWindowX11::PreResize()
941 {
942 return TRUE;
943 }
944
945 // Get total size
946 void wxWindowX11::DoGetSize(int *x, int *y) const
947 {
948 Window window = (Window) GetTopWindow();
949 if (window)
950 {
951 XWindowAttributes attr;
952 Status status = XGetWindowAttributes(wxGlobalDisplay(), window, & attr);
953 wxASSERT(status);
954
955 if (status)
956 {
957 *x = attr.width + 2*m_borderSize;
958 *y = attr.height + 2*m_borderSize;
959 }
960 }
961 }
962
963 void wxWindowX11::DoGetPosition(int *x, int *y) const
964 {
965 Window window = (Window) GetTopWindow();
966 if (window)
967 {
968 XWindowAttributes attr;
969 Status status = XGetWindowAttributes(wxGlobalDisplay(), window, & attr);
970 wxASSERT(status);
971
972 if (status)
973 {
974 *x = attr.x;
975 *y = attr.y;
976
977 // We may be faking the client origin. So a window that's really at (0, 30)
978 // may appear (to wxWin apps) to be at (0, 0).
979 if (GetParent())
980 {
981 wxPoint pt(GetParent()->GetClientAreaOrigin());
982 *x -= pt.x;
983 *y -= pt.y;
984 }
985 }
986 }
987 }
988
989 void wxWindowX11::DoScreenToClient(int *x, int *y) const
990 {
991 Display *display = wxGlobalDisplay();
992 Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display));
993 Window thisWindow = (Window) GetClientWindow();
994
995 Window childWindow;
996 int xx = *x;
997 int yy = *y;
998 XTranslateCoordinates(display, rootWindow, thisWindow, xx, yy, x, y, &childWindow);
999 }
1000
1001 void wxWindowX11::DoClientToScreen(int *x, int *y) const
1002 {
1003 Display *display = wxGlobalDisplay();
1004 Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display));
1005 Window thisWindow = (Window) GetClientWindow();
1006
1007 Window childWindow;
1008 int xx = *x;
1009 int yy = *y;
1010 XTranslateCoordinates(display, thisWindow, rootWindow, xx, yy, x, y, &childWindow);
1011 }
1012
1013
1014 // Get size *available for subwindows* i.e. excluding menu bar etc.
1015 void wxWindowX11::DoGetClientSize(int *x, int *y) const
1016 {
1017 Window window = (Window) GetClientWindow();
1018
1019 if (window)
1020 {
1021 XWindowAttributes attr;
1022 Status status = XGetWindowAttributes(wxGlobalDisplay(), window, & attr);
1023 wxASSERT(status);
1024
1025 if (status)
1026 {
1027 *x = attr.width ;
1028 *y = attr.height ;
1029 }
1030 }
1031 }
1032
1033 void wxWindowX11::DoSetSize(int x, int y, int width, int height, int sizeFlags)
1034 {
1035 if (!GetMainWindow())
1036 return;
1037
1038 XWindowChanges windowChanges;
1039 int valueMask = 0;
1040
1041 if (x != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
1042 {
1043 windowChanges.x = x;
1044 valueMask |= CWX;
1045 }
1046 if (y != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
1047 {
1048 windowChanges.y = y;
1049 valueMask |= CWY;
1050 }
1051 if (width != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
1052 {
1053 windowChanges.width = width - m_borderSize*2;
1054 valueMask |= CWWidth;
1055 }
1056 if (height != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
1057 {
1058 windowChanges.height = height - m_borderSize*2;
1059 valueMask |= CWHeight;
1060 }
1061 AdjustForParentClientOrigin( x, y, sizeFlags);
1062
1063 XConfigureWindow(wxGlobalDisplay(), (Window) GetMainWindow(),
1064 valueMask, & windowChanges);
1065 }
1066
1067 void wxWindowX11::DoSetClientSize(int width, int height)
1068 {
1069 if (!GetMainWindow())
1070 return;
1071
1072 XWindowChanges windowChanges;
1073 int valueMask = 0;
1074
1075 if (width != -1)
1076 {
1077 windowChanges.width = width ;
1078 valueMask |= CWWidth;
1079 }
1080 if (height != -1)
1081 {
1082 windowChanges.height = height ;
1083 valueMask |= CWHeight;
1084 }
1085 XConfigureWindow(wxGlobalDisplay(), (Window) GetMainWindow(),
1086 valueMask, & windowChanges);
1087 }
1088
1089 // For implementation purposes - sometimes decorations make the client area
1090 // smaller
1091 wxPoint wxWindowX11::GetClientAreaOrigin() const
1092 {
1093 return wxPoint(0, 0);
1094 }
1095
1096 // Makes an adjustment to the window position (for example, a frame that has
1097 // a toolbar that it manages itself).
1098 void wxWindowX11::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags)
1099 {
1100 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
1101 {
1102 wxPoint pt(GetParent()->GetClientAreaOrigin());
1103 x += pt.x; y += pt.y;
1104 }
1105 }
1106
1107 void wxWindowX11::SetSizeHints(int minW, int minH, int maxW, int maxH, int incW, int incH)
1108 {
1109 m_minWidth = minW;
1110 m_minHeight = minH;
1111 m_maxWidth = maxW;
1112 m_maxHeight = maxH;
1113
1114 XSizeHints sizeHints;
1115 sizeHints.flags = 0;
1116
1117 if (minW > -1 && minH > -1)
1118 {
1119 sizeHints.flags |= PMinSize;
1120 sizeHints.min_width = minW;
1121 sizeHints.min_height = minH;
1122 }
1123 if (maxW > -1 && maxH > -1)
1124 {
1125 sizeHints.flags |= PMaxSize;
1126 sizeHints.max_width = maxW;
1127 sizeHints.max_height = maxH;
1128 }
1129 if (incW > -1 && incH > -1)
1130 {
1131 sizeHints.flags |= PResizeInc;
1132 sizeHints.width_inc = incW;
1133 sizeHints.height_inc = incH;
1134 }
1135
1136 XSetWMNormalHints(wxGlobalDisplay(), (Window) GetMainWindow(), & sizeHints);
1137 }
1138
1139 void wxWindowX11::DoMoveWindow(int x, int y, int width, int height)
1140 {
1141 DoSetSize(x, y, width, height);
1142 }
1143
1144 // ---------------------------------------------------------------------------
1145 // text metrics
1146 // ---------------------------------------------------------------------------
1147
1148 int wxWindowX11::GetCharHeight() const
1149 {
1150 wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
1151
1152 WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, GetXDisplay());
1153
1154 int direction, ascent, descent;
1155 XCharStruct overall;
1156 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1157 &descent, &overall);
1158
1159 // return (overall.ascent + overall.descent);
1160 return (ascent + descent);
1161 }
1162
1163 int wxWindowX11::GetCharWidth() const
1164 {
1165 wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
1166
1167 WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, GetXDisplay());
1168
1169 int direction, ascent, descent;
1170 XCharStruct overall;
1171 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1172 &descent, &overall);
1173
1174 return overall.width;
1175 }
1176
1177 void wxWindowX11::GetTextExtent(const wxString& string,
1178 int *x, int *y,
1179 int *descent, int *externalLeading,
1180 const wxFont *theFont) const
1181 {
1182 wxFont *fontToUse = (wxFont *)theFont;
1183 if (!fontToUse)
1184 fontToUse = (wxFont *) & m_font;
1185
1186 wxCHECK_RET( fontToUse->Ok(), "valid window font needed" );
1187
1188 WXFontStructPtr pFontStruct = theFont->GetFontStruct(1.0, GetXDisplay());
1189
1190 int direction, ascent, descent2;
1191 XCharStruct overall;
1192 int slen = string.Len();
1193
1194 #if 0
1195 if (use16)
1196 XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
1197 &ascent, &descent2, &overall);
1198 #endif
1199
1200 XTextExtents((XFontStruct*) pFontStruct, string, slen,
1201 &direction, &ascent, &descent2, &overall);
1202
1203 if ( x )
1204 *x = (overall.width);
1205 if ( y )
1206 *y = (ascent + descent2);
1207 if (descent)
1208 *descent = descent2;
1209 if (externalLeading)
1210 *externalLeading = 0;
1211
1212 }
1213
1214 // ----------------------------------------------------------------------------
1215 // painting
1216 // ----------------------------------------------------------------------------
1217
1218 void wxWindowX11::Refresh(bool eraseBack, const wxRect *rect)
1219 {
1220 m_needsRefresh = TRUE;
1221 Display *display = wxGlobalDisplay();
1222 Window thisWindow = (Window) GetMainWindow();
1223
1224 XExposeEvent dummyEvent;
1225 int width, height;
1226 GetSize(&width, &height);
1227
1228 dummyEvent.type = Expose;
1229 dummyEvent.display = display;
1230 dummyEvent.send_event = True;
1231 dummyEvent.window = thisWindow;
1232 if (rect)
1233 {
1234 dummyEvent.x = rect->x;
1235 dummyEvent.y = rect->y;
1236 dummyEvent.width = rect->width;
1237 dummyEvent.height = rect->height;
1238 }
1239 else
1240 {
1241 dummyEvent.x = 0;
1242 dummyEvent.y = 0;
1243 dummyEvent.width = width;
1244 dummyEvent.height = height;
1245 }
1246 dummyEvent.count = 0;
1247
1248 if (eraseBack)
1249 {
1250 wxClientDC dc((wxWindow*) this);
1251 wxBrush backgroundBrush(GetBackgroundColour(), wxSOLID);
1252 dc.SetBackground(backgroundBrush);
1253 if (rect)
1254 dc.Clear(*rect);
1255 else
1256 dc.Clear();
1257 }
1258
1259 XSendEvent(display, thisWindow, False, ExposureMask, (XEvent *)&dummyEvent);
1260 }
1261
1262 void wxWindowX11::Clear()
1263 {
1264 wxClientDC dc((wxWindow*) this);
1265 wxBrush brush(GetBackgroundColour(), wxSOLID);
1266 dc.SetBackground(brush);
1267 dc.Clear();
1268 }
1269
1270 void wxWindowX11::X11SendPaintEvents()
1271 {
1272 m_clipPaintRegion = TRUE;
1273
1274 if (!m_clearRegion.IsEmpty())
1275 {
1276 wxWindowDC dc( (wxWindow*)this );
1277 dc.SetClippingRegion( m_clearRegion );
1278
1279 wxEraseEvent erase_event( GetId(), &dc );
1280 erase_event.SetEventObject( this );
1281
1282 if (!GetEventHandler()->ProcessEvent(erase_event))
1283 {
1284 wxRegionIterator upd( m_clearRegion );
1285 while (upd)
1286 {
1287 // XClearArea( ... , upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() );
1288 upd ++;
1289 }
1290 }
1291 m_clearRegion.Clear();
1292 }
1293
1294 wxNcPaintEvent nc_paint_event( GetId() );
1295 nc_paint_event.SetEventObject( this );
1296 GetEventHandler()->ProcessEvent( nc_paint_event );
1297
1298 wxPaintEvent paint_event( GetId() );
1299 paint_event.SetEventObject( this );
1300 GetEventHandler()->ProcessEvent( paint_event );
1301
1302 m_clipPaintRegion = FALSE;
1303 }
1304
1305 // ----------------------------------------------------------------------------
1306 // event handlers
1307 // ----------------------------------------------------------------------------
1308
1309 // Responds to colour changes: passes event on to children.
1310 void wxWindowX11::OnSysColourChanged(wxSysColourChangedEvent& event)
1311 {
1312 wxWindowList::Node *node = GetChildren().GetFirst();
1313 while ( node )
1314 {
1315 // Only propagate to non-top-level windows
1316 wxWindow *win = node->GetData();
1317 if ( win->GetParent() )
1318 {
1319 wxSysColourChangedEvent event2;
1320 event.m_eventObject = win;
1321 win->GetEventHandler()->ProcessEvent(event2);
1322 }
1323
1324 node = node->GetNext();
1325 }
1326 }
1327
1328 void wxWindowX11::OnIdle(wxIdleEvent& WXUNUSED(event))
1329 {
1330 // This calls the UI-update mechanism (querying windows for
1331 // menu/toolbar/control state information)
1332 UpdateWindowUI();
1333 }
1334
1335 // ----------------------------------------------------------------------------
1336 // accelerators
1337 // ----------------------------------------------------------------------------
1338
1339 bool wxWindowX11::ProcessAccelerator(wxKeyEvent& event)
1340 {
1341 if (!m_acceleratorTable.Ok())
1342 return FALSE;
1343
1344 const wxAcceleratorEntry* entry = m_acceleratorTable.GetEntry(event);
1345 if (entry)
1346 {
1347 // Bingo, we have a match. Now find a control that matches the
1348 // entry command id.
1349
1350 // Need to go up to the top of the window hierarchy, since it might
1351 // be e.g. a menu item
1352 wxWindow* parent = (wxWindow*) this;
1353 while ( parent && !parent->IsTopLevel() )
1354 parent = parent->GetParent();
1355
1356 if (!parent)
1357 return FALSE;
1358
1359 wxFrame* frame = wxDynamicCast(parent, wxFrame);
1360 if ( frame )
1361 {
1362 // Try for a menu command
1363 if (frame->GetMenuBar())
1364 {
1365 wxMenuItem* item = frame->GetMenuBar()->FindItem(entry->GetCommand());
1366 if (item)
1367 {
1368 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, entry->GetCommand());
1369 commandEvent.SetEventObject(frame);
1370
1371 // If ProcessEvent returns TRUE (it was handled), then
1372 // the calling code will skip the event handling.
1373 return frame->GetEventHandler()->ProcessEvent(commandEvent);
1374 }
1375 }
1376 }
1377
1378 // Find a child matching the command id
1379 wxWindow* child = parent->FindWindow(entry->GetCommand());
1380
1381 // No such child
1382 if (!child)
1383 return FALSE;
1384
1385 // Now we process those kinds of windows that we can.
1386 // For now, only buttons.
1387 if ( wxDynamicCast(child, wxButton) )
1388 {
1389 wxCommandEvent commandEvent (wxEVT_COMMAND_BUTTON_CLICKED, child->GetId());
1390 commandEvent.SetEventObject(child);
1391 return child->GetEventHandler()->ProcessEvent(commandEvent);
1392 }
1393
1394 return FALSE;
1395
1396 }// if
1397
1398 // We didn't match the key event against an accelerator.
1399 return FALSE;
1400 }
1401
1402 // ============================================================================
1403 // X11-specific stuff from here on
1404 // ============================================================================
1405
1406 // ----------------------------------------------------------------------------
1407 // function which maintain the global hash table mapping Widgets to wxWindows
1408 // ----------------------------------------------------------------------------
1409
1410 bool wxAddWindowToTable(Window w, wxWindow *win)
1411 {
1412 wxWindow *oldItem = NULL;
1413 if ((oldItem = (wxWindow *)wxWidgetHashTable->Get ((long) w)))
1414 {
1415 wxLogDebug("Widget table clash: new widget is %ld, %s",
1416 (long)w, win->GetClassInfo()->GetClassName());
1417 return FALSE;
1418 }
1419
1420 wxWidgetHashTable->Put((long) w, win);
1421
1422 wxLogTrace("widget", "XWindow 0x%08x <-> window %p (%s)",
1423 w, win, win->GetClassInfo()->GetClassName());
1424
1425 return TRUE;
1426 }
1427
1428 wxWindow *wxGetWindowFromTable(Window w)
1429 {
1430 return (wxWindow *)wxWidgetHashTable->Get((long) w);
1431 }
1432
1433 void wxDeleteWindowFromTable(Window w)
1434 {
1435 wxWidgetHashTable->Delete((long)w);
1436 }
1437
1438 // ----------------------------------------------------------------------------
1439 // add/remove window from the table
1440 // ----------------------------------------------------------------------------
1441
1442 // ----------------------------------------------------------------------------
1443 // X11-specific accessors
1444 // ----------------------------------------------------------------------------
1445
1446 // Get the underlying X window
1447 WXWindow wxWindowX11::GetXWindow() const
1448 {
1449 return GetMainWindow();
1450 }
1451
1452 // Get the underlying X display
1453 WXDisplay *wxWindowX11::GetXDisplay() const
1454 {
1455 return wxGetDisplay();
1456 }
1457
1458 WXWindow wxWindowX11::GetMainWindow() const
1459 {
1460 if (m_drawingArea)
1461 return m_drawingArea;
1462 else
1463 return m_mainWidget;
1464 }
1465
1466 WXWindow wxWindowX11::GetClientWindow() const
1467 {
1468 if (m_drawingArea != (WXWindow) 0)
1469 return m_drawingArea;
1470 else
1471 return GetMainWindow();
1472 }
1473
1474 WXWindow wxWindowX11::GetTopWindow() const
1475 {
1476 return GetMainWindow();
1477 }
1478
1479 WXWindow wxWindowX11::GetLabelWindow() const
1480 {
1481 return GetMainWindow();
1482 }
1483
1484 // ----------------------------------------------------------------------------
1485 // callbacks
1486 // ----------------------------------------------------------------------------
1487
1488 // TODO: implement wxWindow scrollbar, presumably using wxScrollBar
1489 #if 0
1490 static void wxScrollBarCallback(Widget scrollbar,
1491 XtPointer clientData,
1492 XmScrollBarCallbackStruct *cbs)
1493 {
1494 wxWindow *win = wxGetWindowFromTable(scrollbar);
1495 int orientation = (int) clientData;
1496
1497 wxEventType eventType = wxEVT_NULL;
1498 switch (cbs->reason)
1499 {
1500 case XmCR_INCREMENT:
1501 {
1502 eventType = wxEVT_SCROLLWIN_LINEDOWN;
1503 break;
1504 }
1505 case XmCR_DECREMENT:
1506 {
1507 eventType = wxEVT_SCROLLWIN_LINEUP;
1508 break;
1509 }
1510 case XmCR_DRAG:
1511 {
1512 eventType = wxEVT_SCROLLWIN_THUMBTRACK;
1513 break;
1514 }
1515 case XmCR_VALUE_CHANGED:
1516 {
1517 eventType = wxEVT_SCROLLWIN_THUMBRELEASE;
1518 break;
1519 }
1520 case XmCR_PAGE_INCREMENT:
1521 {
1522 eventType = wxEVT_SCROLLWIN_PAGEDOWN;
1523 break;
1524 }
1525 case XmCR_PAGE_DECREMENT:
1526 {
1527 eventType = wxEVT_SCROLLWIN_PAGEUP;
1528 break;
1529 }
1530 case XmCR_TO_TOP:
1531 {
1532 eventType = wxEVT_SCROLLWIN_TOP;
1533 break;
1534 }
1535 case XmCR_TO_BOTTOM:
1536 {
1537 eventType = wxEVT_SCROLLWIN_BOTTOM;
1538 break;
1539 }
1540 default:
1541 {
1542 // Should never get here
1543 wxFAIL_MSG("Unknown scroll event.");
1544 break;
1545 }
1546 }
1547
1548 wxScrollWinEvent event(eventType,
1549 cbs->value,
1550 ((orientation == XmHORIZONTAL) ?
1551 wxHORIZONTAL : wxVERTICAL));
1552 event.SetEventObject( win );
1553 win->GetEventHandler()->ProcessEvent(event);
1554 }
1555 #endif
1556
1557 // ----------------------------------------------------------------------------
1558 // TranslateXXXEvent() functions
1559 // ----------------------------------------------------------------------------
1560
1561 bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Window window, XEvent *xevent)
1562 {
1563 switch (xevent->xany.type)
1564 {
1565 case EnterNotify:
1566 case LeaveNotify:
1567 case ButtonPress:
1568 case ButtonRelease:
1569 case MotionNotify:
1570 {
1571 wxEventType eventType = wxEVT_NULL;
1572
1573 if (xevent->xany.type == EnterNotify)
1574 {
1575 //if (local_event.xcrossing.mode!=NotifyNormal)
1576 // return ; // Ignore grab events
1577 eventType = wxEVT_ENTER_WINDOW;
1578 // canvas->GetEventHandler()->OnSetFocus();
1579 }
1580 else if (xevent->xany.type == LeaveNotify)
1581 {
1582 //if (local_event.xcrossingr.mode!=NotifyNormal)
1583 // return ; // Ignore grab events
1584 eventType = wxEVT_LEAVE_WINDOW;
1585 // canvas->GetEventHandler()->OnKillFocus();
1586 }
1587 else if (xevent->xany.type == MotionNotify)
1588 {
1589 eventType = wxEVT_MOTION;
1590 }
1591 else if (xevent->xany.type == ButtonPress)
1592 {
1593 wxevent.SetTimestamp(xevent->xbutton.time);
1594 int button = 0;
1595 if (xevent->xbutton.button == Button1)
1596 {
1597 eventType = wxEVT_LEFT_DOWN;
1598 button = 1;
1599 }
1600 else if (xevent->xbutton.button == Button2)
1601 {
1602 eventType = wxEVT_MIDDLE_DOWN;
1603 button = 2;
1604 }
1605 else if (xevent->xbutton.button == Button3)
1606 {
1607 eventType = wxEVT_RIGHT_DOWN;
1608 button = 3;
1609 }
1610
1611 // check for a double click
1612 // TODO: where can we get this value from?
1613 //long dclickTime = XtGetMultiClickTime(wxGlobalDisplay());
1614 long dclickTime = 200;
1615 long ts = wxevent.GetTimestamp();
1616
1617 int buttonLast = win->GetLastClickedButton();
1618 long lastTS = win->GetLastClickTime();
1619 if ( buttonLast && buttonLast == button && (ts - lastTS) < dclickTime )
1620 {
1621 // I have a dclick
1622 win->SetLastClick(0, ts);
1623 if ( eventType == wxEVT_LEFT_DOWN )
1624 eventType = wxEVT_LEFT_DCLICK;
1625 else if ( eventType == wxEVT_MIDDLE_DOWN )
1626 eventType = wxEVT_MIDDLE_DCLICK;
1627 else if ( eventType == wxEVT_RIGHT_DOWN )
1628 eventType = wxEVT_RIGHT_DCLICK;
1629 }
1630 else
1631 {
1632 // not fast enough or different button
1633 win->SetLastClick(button, ts);
1634 }
1635 }
1636 else if (xevent->xany.type == ButtonRelease)
1637 {
1638 if (xevent->xbutton.button == Button1)
1639 {
1640 eventType = wxEVT_LEFT_UP;
1641 }
1642 else if (xevent->xbutton.button == Button2)
1643 {
1644 eventType = wxEVT_MIDDLE_UP;
1645 }
1646 else if (xevent->xbutton.button == Button3)
1647 {
1648 eventType = wxEVT_RIGHT_UP;
1649 }
1650 else return FALSE;
1651 }
1652 else
1653 {
1654 return FALSE;
1655 }
1656
1657 wxevent.SetEventType(eventType);
1658
1659 wxevent.m_x = xevent->xbutton.x;
1660 wxevent.m_y = xevent->xbutton.y;
1661
1662 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
1663 || (event_left_is_down (xevent)
1664 && (eventType != wxEVT_LEFT_UP)));
1665 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
1666 || (event_middle_is_down (xevent)
1667 && (eventType != wxEVT_MIDDLE_UP)));
1668 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
1669 || (event_right_is_down (xevent)
1670 && (eventType != wxEVT_RIGHT_UP)));
1671
1672 wxevent.m_shiftDown = xevent->xbutton.state & ShiftMask;
1673 wxevent.m_controlDown = xevent->xbutton.state & ControlMask;
1674 wxevent.m_altDown = xevent->xbutton.state & Mod3Mask;
1675 wxevent.m_metaDown = xevent->xbutton.state & Mod1Mask;
1676
1677 wxevent.SetId(win->GetId());
1678 wxevent.SetEventObject(win);
1679
1680 return TRUE;
1681 }
1682 }
1683 return FALSE;
1684 }
1685
1686 bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Window WXUNUSED(win), XEvent *xevent)
1687 {
1688 switch (xevent->xany.type)
1689 {
1690 case KeyPress:
1691 case KeyRelease:
1692 {
1693 char buf[20];
1694
1695 KeySym keySym;
1696 (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, NULL);
1697 int id = wxCharCodeXToWX (keySym);
1698
1699 if (xevent->xkey.state & ShiftMask)
1700 wxevent.m_shiftDown = TRUE;
1701 if (xevent->xkey.state & ControlMask)
1702 wxevent.m_controlDown = TRUE;
1703 if (xevent->xkey.state & Mod3Mask)
1704 wxevent.m_altDown = TRUE;
1705 if (xevent->xkey.state & Mod1Mask)
1706 wxevent.m_metaDown = TRUE;
1707 wxevent.SetEventObject(win);
1708 wxevent.m_keyCode = id;
1709 wxevent.SetTimestamp(xevent->xkey.time);
1710
1711 wxevent.m_x = xevent->xbutton.x;
1712 wxevent.m_y = xevent->xbutton.y;
1713
1714 if (id > -1)
1715 return TRUE;
1716 else
1717 return FALSE;
1718 break;
1719 }
1720 default:
1721 break;
1722 }
1723 return FALSE;
1724 }
1725
1726 // ----------------------------------------------------------------------------
1727 // Colour stuff
1728 // ----------------------------------------------------------------------------
1729
1730 #if 0
1731
1732 #define YAllocColor XAllocColor
1733 XColor g_itemColors[5];
1734 int wxComputeColours (Display *display, wxColour * back, wxColour * fore)
1735 {
1736 int result;
1737 static XmColorProc colorProc;
1738
1739 result = wxNO_COLORS;
1740
1741 if (back)
1742 {
1743 g_itemColors[0].red = (((long) back->Red ()) << 8);
1744 g_itemColors[0].green = (((long) back->Green ()) << 8);
1745 g_itemColors[0].blue = (((long) back->Blue ()) << 8);
1746 g_itemColors[0].flags = DoRed | DoGreen | DoBlue;
1747 if (colorProc == (XmColorProc) NULL)
1748 {
1749 // Get a ptr to the actual function
1750 colorProc = XmSetColorCalculation ((XmColorProc) NULL);
1751 // And set it back to motif.
1752 XmSetColorCalculation (colorProc);
1753 }
1754 (*colorProc) (&g_itemColors[wxBACK_INDEX],
1755 &g_itemColors[wxFORE_INDEX],
1756 &g_itemColors[wxSELE_INDEX],
1757 &g_itemColors[wxTOPS_INDEX],
1758 &g_itemColors[wxBOTS_INDEX]);
1759 result = wxBACK_COLORS;
1760 }
1761 if (fore)
1762 {
1763 g_itemColors[wxFORE_INDEX].red = (((long) fore->Red ()) << 8);
1764 g_itemColors[wxFORE_INDEX].green = (((long) fore->Green ()) << 8);
1765 g_itemColors[wxFORE_INDEX].blue = (((long) fore->Blue ()) << 8);
1766 g_itemColors[wxFORE_INDEX].flags = DoRed | DoGreen | DoBlue;
1767 if (result == wxNO_COLORS)
1768 result = wxFORE_COLORS;
1769 }
1770
1771 Display *dpy = display;
1772 Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy);
1773
1774 if (back)
1775 {
1776 /* 5 Colours to allocate */
1777 for (int i = 0; i < 5; i++)
1778 if (!YAllocColor (dpy, cmap, &g_itemColors[i]))
1779 result = wxNO_COLORS;
1780 }
1781 else if (fore)
1782 {
1783 /* Only 1 colour to allocate */
1784 if (!YAllocColor (dpy, cmap, &g_itemColors[wxFORE_INDEX]))
1785 result = wxNO_COLORS;
1786 }
1787
1788 return (result);
1789
1790 }
1791 #endif
1792
1793 // Changes the foreground and background colours to be derived from the current
1794 // background colour. To change the foreground colour, you must call
1795 // SetForegroundColour explicitly.
1796 void wxWindowX11::ChangeBackgroundColour()
1797 {
1798 // TODO
1799 #if 0
1800 WXWidget mainWidget = GetMainWidget();
1801 if ( mainWidget )
1802 DoChangeBackgroundColour(mainWidget, m_backgroundColour);
1803 #endif
1804 }
1805
1806 void wxWindowX11::ChangeForegroundColour()
1807 {
1808 // TODO
1809 #if 0
1810 WXWidget mainWidget = GetMainWidget();
1811 if ( mainWidget )
1812 DoChangeForegroundColour(mainWidget, m_foregroundColour);
1813 if ( m_scrolledWindow && mainWidget != m_scrolledWindow )
1814 DoChangeForegroundColour(m_scrolledWindow, m_foregroundColour);
1815 #endif
1816 }
1817
1818 // Change a widget's foreground and background colours.
1819 void wxWindowX11::DoChangeForegroundColour(WXWindow widget, wxColour& foregroundColour)
1820 {
1821 // TODO
1822 #if 0
1823 // When should we specify the foreground, if it's calculated
1824 // by wxComputeColours?
1825 // Solution: say we start with the default (computed) foreground colour.
1826 // If we call SetForegroundColour explicitly for a control or window,
1827 // then the foreground is changed.
1828 // Therefore SetBackgroundColour computes the foreground colour, and
1829 // SetForegroundColour changes the foreground colour. The ordering is
1830 // important.
1831
1832 Widget w = (Widget)widget;
1833 XtVaSetValues(
1834 w,
1835 XmNforeground, foregroundColour.AllocColour(XtDisplay(w)),
1836 NULL
1837 );
1838 #endif
1839 }
1840
1841 void wxWindowX11::DoChangeBackgroundColour(WXWindow widget, wxColour& backgroundColour, bool changeArmColour)
1842 {
1843 // TODO
1844 #if 0
1845 wxComputeColours (XtDisplay((Widget) widget), & backgroundColour,
1846 (wxColour*) NULL);
1847
1848 XtVaSetValues ((Widget) widget,
1849 XmNbackground, g_itemColors[wxBACK_INDEX].pixel,
1850 XmNtopShadowColor, g_itemColors[wxTOPS_INDEX].pixel,
1851 XmNbottomShadowColor, g_itemColors[wxBOTS_INDEX].pixel,
1852 XmNforeground, g_itemColors[wxFORE_INDEX].pixel,
1853 NULL);
1854
1855 if (changeArmColour)
1856 XtVaSetValues ((Widget) widget,
1857 XmNarmColor, g_itemColors[wxSELE_INDEX].pixel,
1858 NULL);
1859 #endif
1860 }
1861
1862 bool wxWindowX11::SetBackgroundColour(const wxColour& col)
1863 {
1864 if ( !wxWindowBase::SetBackgroundColour(col) )
1865 return FALSE;
1866
1867 ChangeBackgroundColour();
1868
1869 return TRUE;
1870 }
1871
1872 bool wxWindowX11::SetForegroundColour(const wxColour& col)
1873 {
1874 if ( !wxWindowBase::SetForegroundColour(col) )
1875 return FALSE;
1876
1877 ChangeForegroundColour();
1878
1879 return TRUE;
1880 }
1881
1882 void wxWindowX11::ChangeFont(bool keepOriginalSize)
1883 {
1884 // TODO
1885 #if 0
1886 // Note that this causes the widget to be resized back
1887 // to its original size! We therefore have to set the size
1888 // back again. TODO: a better way in Motif?
1889 Widget w = (Widget) GetLabelWidget(); // Usually the main widget
1890 if (w && m_font.Ok())
1891 {
1892 int width, height, width1, height1;
1893 GetSize(& width, & height);
1894
1895 // lesstif 0.87 hangs here
1896 #ifndef LESSTIF_VERSION
1897 XtVaSetValues (w,
1898 XmNfontList, (XmFontList) m_font.GetFontList(1.0, XtDisplay(w)),
1899 NULL);
1900 #endif
1901
1902 GetSize(& width1, & height1);
1903 if (keepOriginalSize && (width != width1 || height != height1))
1904 {
1905 SetSize(-1, -1, width, height);
1906 }
1907 }
1908 #endif
1909 }
1910
1911 // ----------------------------------------------------------------------------
1912 // global functions
1913 // ----------------------------------------------------------------------------
1914
1915 wxWindow *wxGetActiveWindow()
1916 {
1917 // TODO
1918 wxFAIL_MSG("Not implemented");
1919 return NULL;
1920 }
1921
1922 /* static */
1923 wxWindow *wxWindowBase::GetCapture()
1924 {
1925 return (wxWindow *)g_captureWindow;
1926 }
1927
1928
1929 // Find the wxWindow at the current mouse position, returning the mouse
1930 // position.
1931 wxWindow* wxFindWindowAtPointer(wxPoint& pt)
1932 {
1933 return wxFindWindowAtPoint(wxGetMousePosition());
1934 }
1935
1936 // Get the current mouse position.
1937 wxPoint wxGetMousePosition()
1938 {
1939 Display *display = wxGlobalDisplay();
1940 Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
1941 Window rootReturn, childReturn;
1942 int rootX, rootY, winX, winY;
1943 unsigned int maskReturn;
1944
1945 XQueryPointer (display,
1946 rootWindow,
1947 &rootReturn,
1948 &childReturn,
1949 &rootX, &rootY, &winX, &winY, &maskReturn);
1950 return wxPoint(rootX, rootY);
1951 }
1952
1953
1954 // ----------------------------------------------------------------------------
1955 // wxNoOptimize: switch off size optimization
1956 // ----------------------------------------------------------------------------
1957
1958 int wxNoOptimize::ms_count = 0;
1959