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