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