Removed some debug code from window headers; added some debug
[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_ABSTRACT_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 m_mainWidget = (WXWindow) 0;
103
104 m_winCaptured = FALSE;
105
106 m_isShown = TRUE;
107 m_isBeingDeleted = FALSE;
108
109 m_lastTS = 0;
110 m_lastButton = 0;
111 }
112
113 // real construction (Init() must have been called before!)
114 bool wxWindowX11::Create(wxWindow *parent, wxWindowID id,
115 const wxPoint& pos,
116 const wxSize& size,
117 long style,
118 const wxString& name)
119 {
120 wxCHECK_MSG( parent, FALSE, "can't create wxWindow without parent" );
121
122 CreateBase(parent, id, pos, size, style, wxDefaultValidator, name);
123
124 parent->AddChild(this);
125
126 int w = size.GetWidth();
127 int h = size.GetHeight();
128 int x = size.GetX();
129 int y = size.GetY();
130 if (w == -1) w = 20;
131 if (h == -1) h = 20;
132 if (x == -1) x = 0;
133 if (y == -1) y = 0;
134
135 Display *xdisplay = (Display*) wxGlobalDisplay();
136 int xscreen = DefaultScreen( xdisplay );
137 Colormap cm = DefaultColormap( xdisplay, xscreen );
138
139 m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
140 m_backgroundColour.CalcPixel( (WXColormap) cm );
141 m_hasBgCol = TRUE;
142
143 m_foregroundColour = *wxBLACK;
144 m_foregroundColour.CalcPixel( (WXColormap) cm );
145
146
147 Window parentWindow = (Window) parent->GetMainWindow();
148
149 Window window = XCreateSimpleWindow(
150 xdisplay, parentWindow,
151 x, y, w, h, 0,
152 m_backgroundColour.GetPixel(),
153 m_backgroundColour.GetPixel() );
154
155 m_mainWidget = (WXWindow) window;
156
157 // Select event types wanted
158 XSelectInput(wxGlobalDisplay(), window,
159 ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
160 ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask |
161 KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask |
162 PropertyChangeMask);
163
164 wxAddWindowToTable(window, (wxWindow*) this);
165
166 // Is a subwindow, so map immediately
167 m_isShown = TRUE;
168 XMapWindow(wxGlobalDisplay(), window);
169
170 // Without this, the cursor may not be restored properly (e.g. in splitter
171 // sample).
172 SetCursor(*wxSTANDARD_CURSOR);
173 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
174 SetSize(pos.x, pos.y, size.x, size.y);
175
176 return TRUE;
177 }
178
179 // Destructor
180 wxWindowX11::~wxWindowX11()
181 {
182 if (g_captureWindow == this)
183 g_captureWindow = NULL;
184
185 m_isBeingDeleted = TRUE;
186
187 // X11-specific actions first
188 Window main = (Window) m_mainWidget;
189 if ( main )
190 {
191 // Removes event handlers
192 //DetachWidget(main);
193 }
194
195 if (m_parent)
196 m_parent->RemoveChild( this );
197
198 DestroyChildren();
199
200 // Destroy the window
201 if (main)
202 {
203 XSelectInput( wxGlobalDisplay(), main, NoEventMask);
204 wxDeleteWindowFromTable( main );
205 XDestroyWindow( wxGlobalDisplay(), main );
206 m_mainWidget = NULL;
207 }
208 }
209
210 // ---------------------------------------------------------------------------
211 // basic operations
212 // ---------------------------------------------------------------------------
213
214 void wxWindowX11::SetFocus()
215 {
216 Window wMain = (Window) GetMainWindow();
217 if (wMain)
218 {
219 XSetInputFocus(wxGlobalDisplay(), wMain, RevertToParent, CurrentTime);
220
221 XWMHints wmhints;
222 wmhints.flags = InputHint;
223 wmhints.input = True;
224 XSetWMHints(wxGlobalDisplay(), wMain, &wmhints);
225 }
226 }
227
228 // Get the window with the focus
229 wxWindow *wxWindowBase::FindFocus()
230 {
231 Window wFocus = (Window) 0;
232 int revert = 0;
233
234 XGetInputFocus(wxGlobalDisplay(), & wFocus, & revert);
235 if (wFocus)
236 {
237 wxWindow *win = NULL;
238 do
239 {
240 win = wxGetWindowFromTable(wFocus);
241 wFocus = wxGetWindowParent(wFocus);
242 } while (wFocus && !win);
243
244 return win;
245 }
246
247 return NULL;
248 }
249
250 // Enabling/disabling handled by event loop, and not sending events
251 // if disabled.
252 bool wxWindowX11::Enable(bool enable)
253 {
254 if ( !wxWindowBase::Enable(enable) )
255 return FALSE;
256
257 return TRUE;
258 }
259
260 bool wxWindowX11::Show(bool show)
261 {
262 wxWindowBase::Show(show);
263
264 Window xwin = (Window) GetXWindow();
265 Display *xdisp = (Display*) GetXDisplay();
266 if (show)
267 {
268 wxString msg;
269 msg.Printf("Mapping window of type %s", GetClassInfo()->GetClassName());
270 wxLogDebug(msg);
271 XMapWindow(xdisp, xwin);
272 }
273 else
274 {
275 wxString msg;
276 msg.Printf("Unmapping window of type %s", GetClassInfo()->GetClassName());
277 wxLogDebug(msg);
278 XUnmapWindow(xdisp, xwin);
279 }
280
281 return TRUE;
282 }
283
284 // Raise the window to the top of the Z order
285 void wxWindowX11::Raise()
286 {
287 if (m_mainWidget)
288 XRaiseWindow( wxGlobalDisplay(), (Window) m_mainWidget );
289 }
290
291 // Lower the window to the bottom of the Z order
292 void wxWindowX11::Lower()
293 {
294 if (m_mainWidget)
295 XLowerWindow( wxGlobalDisplay(), (Window) m_mainWidget );
296 }
297
298 void wxWindowX11::DoCaptureMouse()
299 {
300 if ((g_captureWindow != NULL) && (g_captureWindow != this))
301 {
302 wxASSERT_MSG(FALSE, "Trying to capture before mouse released.");
303
304 // Core dump now
305 int *tmp = NULL;
306 (*tmp) = 1;
307 return;
308 }
309
310 if ( m_winCaptured )
311 return;
312
313 g_captureWindow = (wxWindow*) this;
314
315 if (GetMainWindow())
316 {
317 int res = XGrabPointer(wxGlobalDisplay(), (Window) GetMainWindow(),
318 FALSE,
319 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask,
320 GrabModeAsync,
321 GrabModeAsync,
322 None,
323 None, /* cursor */ // TODO: This may need to be set to the cursor of this window
324 CurrentTime);
325
326 if (res != GrabSuccess)
327 {
328 wxString msg;
329 msg.Printf("Failed to grab pointer for window %s", this->GetClassInfo()->GetClassName());
330 wxLogDebug(msg);
331 if (res == GrabNotViewable)
332 {
333 wxLogDebug("This is not a viewable window - perhaps not shown yet?");
334 }
335 g_captureWindow = NULL;
336 return;
337 }
338 wxLogDebug("Grabbed pointer");
339
340 #if 0
341 res = XGrabButton(wxGlobalDisplay(), AnyButton, AnyModifier,
342 (Window) GetMainWindow(),
343 FALSE,
344 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
345 GrabModeAsync,
346 GrabModeAsync,
347 None,
348 None);
349
350 if (res != GrabSuccess)
351 {
352 wxLogDebug("Failed to grab mouse buttons.");
353 XUngrabPointer(wxGlobalDisplay(), CurrentTime);
354 return;
355 }
356 #endif
357
358 #if 0
359 res = XGrabKeyboard(wxGlobalDisplay(), (Window) GetMainWindow(),
360 #if 0
361 ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask,
362 #else
363 FALSE,
364 #endif
365 GrabModeAsync,
366 GrabModeAsync,
367 CurrentTime);
368
369 if (res != GrabSuccess)
370 {
371 wxLogDebug("Failed to grab keyboard.");
372 XUngrabPointer(wxGlobalDisplay(), CurrentTime);
373 #if 0
374 XUngrabButton(wxGlobalDisplay(), AnyButton, AnyModifier,
375 (Window) GetMainWindow());
376 #endif
377 return;
378 }
379 #endif
380
381 m_winCaptured = TRUE;
382 }
383 }
384
385 void wxWindowX11::DoReleaseMouse()
386 {
387 g_captureWindow = NULL;
388 if ( !m_winCaptured )
389 return;
390
391 Window wMain = (Window)GetMainWindow();
392
393 if ( wMain )
394 {
395 XUngrabPointer(wxGlobalDisplay(), wMain);
396 #if 0
397 XUngrabButton(wxGlobalDisplay(), AnyButton, AnyModifier,
398 wMain);
399 XUngrabKeyboard(wxGlobalDisplay(), CurrentTime);
400 #endif
401 }
402 wxLogDebug("Ungrabbed pointer");
403
404 m_winCaptured = FALSE;
405 }
406
407 bool wxWindowX11::SetFont(const wxFont& font)
408 {
409 if ( !wxWindowBase::SetFont(font) )
410 {
411 // nothing to do
412 return FALSE;
413 }
414
415 return TRUE;
416 }
417
418 bool wxWindowX11::SetCursor(const wxCursor& cursor)
419 {
420 if ( !wxWindowBase::SetCursor(cursor) )
421 {
422 // no change
423 return FALSE;
424 }
425
426 wxCursor* cursor2 = NULL;
427 if (m_cursor.Ok())
428 cursor2 = & m_cursor;
429 else
430 cursor2 = wxSTANDARD_CURSOR;
431
432 WXDisplay *dpy = GetXDisplay();
433 WXCursor x_cursor = cursor2->GetXCursor(dpy);
434
435 Window win = (Window) GetMainWindow();
436 XDefineCursor((Display*) dpy, win, (Cursor) x_cursor);
437
438 return TRUE;
439 }
440
441 // Coordinates relative to the window
442 void wxWindowX11::WarpPointer (int x, int y)
443 {
444 if (m_mainWidget)
445 XWarpPointer( wxGlobalDisplay(), None, (Window) m_mainWidget, 0, 0, 0, 0, x, y);
446 }
447
448 // Does a physical scroll
449 void wxWindowX11::ScrollWindow(int dx, int dy, const wxRect *rect)
450 {
451 #if 0
452 int x, y, w, h;
453 if (rect)
454 {
455 // Use specified rectangle
456 x = rect->x; y = rect->y; w = rect->width; h = rect->height;
457 }
458 else
459 {
460 // Use whole client area
461 x = 0; y = 0;
462 GetClientSize(& w, & h);
463 }
464
465 wxNode *cnode = m_children.First();
466 while (cnode)
467 {
468 wxWindow *child = (wxWindow*) cnode->Data();
469 int sx = 0;
470 int sy = 0;
471 child->GetSize( &sx, &sy );
472 wxPoint pos( child->GetPosition() );
473 child->SetSize( pos.x + dx, pos.y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
474 cnode = cnode->Next();
475 }
476
477 int x1 = (dx >= 0) ? x : x - dx;
478 int y1 = (dy >= 0) ? y : y - dy;
479 int w1 = w - abs(dx);
480 int h1 = h - abs(dy);
481 int x2 = (dx >= 0) ? x + dx : x;
482 int y2 = (dy >= 0) ? y + dy : y;
483
484 wxClientDC dc((wxWindow*) this);
485
486 dc.SetLogicalFunction (wxCOPY);
487
488 Window window = (Window) GetMainWindow();
489 Display* display = wxGlobalDisplay();
490
491 XCopyArea(display, window, window, (GC) dc.GetGC(),
492 x1, y1, w1, h1, x2, y2);
493
494 dc.SetAutoSetting(TRUE);
495 wxBrush brush(GetBackgroundColour(), wxSOLID);
496 dc.SetBrush(brush); // FIXME: needed?
497
498 // We'll add rectangles to the list of update rectangles according to which
499 // bits we've exposed.
500 wxList updateRects;
501
502 if (dx > 0)
503 {
504 wxRect *rect = new wxRect;
505 rect->x = x;
506 rect->y = y;
507 rect->width = dx;
508 rect->height = h;
509
510 XFillRectangle(display, window,
511 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
512
513 rect->x = rect->x;
514 rect->y = rect->y;
515 rect->width = rect->width;
516 rect->height = rect->height;
517
518 updateRects.Append((wxObject*) rect);
519 }
520 else if (dx < 0)
521 {
522 wxRect *rect = new wxRect;
523
524 rect->x = x + w + dx;
525 rect->y = y;
526 rect->width = -dx;
527 rect->height = h;
528
529 XFillRectangle(display, window,
530 (GC) dc.GetGC(), rect->x, rect->y, rect->width,
531 rect->height);
532
533 rect->x = rect->x;
534 rect->y = rect->y;
535 rect->width = rect->width;
536 rect->height = rect->height;
537
538 updateRects.Append((wxObject*) rect);
539 }
540 if (dy > 0)
541 {
542 wxRect *rect = new wxRect;
543
544 rect->x = x;
545 rect->y = y;
546 rect->width = w;
547 rect->height = dy;
548
549 XFillRectangle(display, window,
550 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
551
552 rect->x = rect->x;
553 rect->y = rect->y;
554 rect->width = rect->width;
555 rect->height = rect->height;
556
557 updateRects.Append((wxObject*) rect);
558 }
559 else if (dy < 0)
560 {
561 wxRect *rect = new wxRect;
562
563 rect->x = x;
564 rect->y = y + h + dy;
565 rect->width = w;
566 rect->height = -dy;
567
568 XFillRectangle(display, window,
569 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
570
571 rect->x = rect->x;
572 rect->y = rect->y;
573 rect->width = rect->width;
574 rect->height = rect->height;
575
576 updateRects.Append((wxObject*) rect);
577 }
578 dc.SetBrush(wxNullBrush);
579
580 // Now send expose events
581
582 wxNode* node = updateRects.First();
583 while (node)
584 {
585 wxRect* rect = (wxRect*) node->Data();
586 XExposeEvent event;
587
588 event.type = Expose;
589 event.display = display;
590 event.send_event = True;
591 event.window = window;
592
593 event.x = rect->x;
594 event.y = rect->y;
595 event.width = rect->width;
596 event.height = rect->height;
597
598 event.count = 0;
599
600 XSendEvent(display, window, False, ExposureMask, (XEvent *)&event);
601
602 node = node->Next();
603
604 }
605
606 // Delete the update rects
607 node = updateRects.First();
608 while (node)
609 {
610 wxRect* rect = (wxRect*) node->Data();
611 delete rect;
612 node = node->Next();
613 }
614 #endif
615 }
616
617 // ---------------------------------------------------------------------------
618 // drag and drop
619 // ---------------------------------------------------------------------------
620
621 #if wxUSE_DRAG_AND_DROP
622
623 void wxWindowX11::SetDropTarget(wxDropTarget * WXUNUSED(pDropTarget))
624 {
625 // TODO
626 }
627
628 #endif
629
630 // Old style file-manager drag&drop
631 void wxWindowX11::DragAcceptFiles(bool WXUNUSED(accept))
632 {
633 // TODO
634 }
635
636 // ----------------------------------------------------------------------------
637 // tooltips
638 // ----------------------------------------------------------------------------
639
640 #if wxUSE_TOOLTIPS
641
642 void wxWindowX11::DoSetToolTip(wxToolTip * WXUNUSED(tooltip))
643 {
644 // TODO
645 }
646
647 #endif // wxUSE_TOOLTIPS
648
649 // ---------------------------------------------------------------------------
650 // moving and resizing
651 // ---------------------------------------------------------------------------
652
653 bool wxWindowX11::PreResize()
654 {
655 return TRUE;
656 }
657
658 // Get total size
659 void wxWindowX11::DoGetSize(int *x, int *y) const
660 {
661 Window window = (Window) m_mainWidget;
662 if (window)
663 {
664 XWindowAttributes attr;
665 Status status = XGetWindowAttributes(wxGlobalDisplay(), window, & attr);
666 wxASSERT(status);
667
668 if (status)
669 {
670 *x = attr.width /* + 2*m_borderSize */ ;
671 *y = attr.height /* + 2*m_borderSize */ ;
672 }
673 }
674 }
675
676 void wxWindowX11::DoGetPosition(int *x, int *y) const
677 {
678 Window window = (Window) m_mainWidget;
679 if (window)
680 {
681 XWindowAttributes attr;
682 Status status = XGetWindowAttributes(wxGlobalDisplay(), window, & attr);
683 wxASSERT(status);
684
685 if (status)
686 {
687 *x = attr.x;
688 *y = attr.y;
689
690 // We may be faking the client origin. So a window that's really at (0, 30)
691 // may appear (to wxWin apps) to be at (0, 0).
692 if (GetParent())
693 {
694 wxPoint pt(GetParent()->GetClientAreaOrigin());
695 *x -= pt.x;
696 *y -= pt.y;
697 }
698 }
699 }
700 }
701
702 void wxWindowX11::DoScreenToClient(int *x, int *y) const
703 {
704 Display *display = wxGlobalDisplay();
705 Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display));
706 Window thisWindow = (Window) m_mainWidget;
707
708 Window childWindow;
709 int xx = *x;
710 int yy = *y;
711 XTranslateCoordinates(display, rootWindow, thisWindow, xx, yy, x, y, &childWindow);
712 }
713
714 void wxWindowX11::DoClientToScreen(int *x, int *y) const
715 {
716 Display *display = wxGlobalDisplay();
717 Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display));
718 Window thisWindow = (Window) m_mainWidget;
719
720 Window childWindow;
721 int xx = *x;
722 int yy = *y;
723 XTranslateCoordinates(display, thisWindow, rootWindow, xx, yy, x, y, &childWindow);
724 }
725
726
727 // Get size *available for subwindows* i.e. excluding menu bar etc.
728 void wxWindowX11::DoGetClientSize(int *x, int *y) const
729 {
730 Window window = (Window) m_mainWidget;
731
732 if (window)
733 {
734 XWindowAttributes attr;
735 Status status = XGetWindowAttributes( wxGlobalDisplay(), window, &attr );
736 wxASSERT(status);
737
738 if (status)
739 {
740 *x = attr.width ;
741 *y = attr.height ;
742 }
743 }
744 }
745
746 void wxWindowX11::DoSetSize(int x, int y, int width, int height, int sizeFlags)
747 {
748 if (!GetMainWindow())
749 return;
750
751 XWindowChanges windowChanges;
752 int valueMask = 0;
753
754 if (x != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
755 {
756 int yy = 0;
757 AdjustForParentClientOrigin( x, yy, sizeFlags);
758 windowChanges.x = x;
759 valueMask |= CWX;
760 }
761 if (y != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
762 {
763 int xx = 0;
764 AdjustForParentClientOrigin( xx, y, sizeFlags);
765 windowChanges.y = y;
766 valueMask |= CWY;
767 }
768 if (width != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
769 {
770 windowChanges.width = width /* - m_borderSize*2 */;
771 valueMask |= CWWidth;
772 }
773 if (height != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
774 {
775 windowChanges.height = height /* -m_borderSize*2*/;
776 valueMask |= CWHeight;
777 }
778
779 XConfigureWindow(wxGlobalDisplay(), (Window) GetMainWindow(),
780 valueMask, & windowChanges);
781 }
782
783 void wxWindowX11::DoSetClientSize(int width, int height)
784 {
785 if (!GetMainWindow())
786 return;
787
788 XWindowChanges windowChanges;
789 int valueMask = 0;
790
791 if (width != -1)
792 {
793 windowChanges.width = width ;
794 valueMask |= CWWidth;
795 }
796 if (height != -1)
797 {
798 windowChanges.height = height ;
799 valueMask |= CWHeight;
800 }
801 XConfigureWindow(wxGlobalDisplay(), (Window) GetMainWindow(),
802 valueMask, & windowChanges);
803 }
804
805 // For implementation purposes - sometimes decorations make the client area
806 // smaller
807 wxPoint wxWindowX11::GetClientAreaOrigin() const
808 {
809 return wxPoint(0, 0);
810 }
811
812 // Makes an adjustment to the window position (for example, a frame that has
813 // a toolbar that it manages itself).
814 void wxWindowX11::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags)
815 {
816 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
817 {
818 wxPoint pt(GetParent()->GetClientAreaOrigin());
819 x += pt.x; y += pt.y;
820 }
821 }
822
823 void wxWindowX11::SetSizeHints(int minW, int minH, int maxW, int maxH, int incW, int incH)
824 {
825 m_minWidth = minW;
826 m_minHeight = minH;
827 m_maxWidth = maxW;
828 m_maxHeight = maxH;
829
830 XSizeHints sizeHints;
831 sizeHints.flags = 0;
832
833 if (minW > -1 && minH > -1)
834 {
835 sizeHints.flags |= PMinSize;
836 sizeHints.min_width = minW;
837 sizeHints.min_height = minH;
838 }
839 if (maxW > -1 && maxH > -1)
840 {
841 sizeHints.flags |= PMaxSize;
842 sizeHints.max_width = maxW;
843 sizeHints.max_height = maxH;
844 }
845 if (incW > -1 && incH > -1)
846 {
847 sizeHints.flags |= PResizeInc;
848 sizeHints.width_inc = incW;
849 sizeHints.height_inc = incH;
850 }
851
852 XSetWMNormalHints(wxGlobalDisplay(), (Window) GetMainWindow(), & sizeHints);
853 }
854
855 void wxWindowX11::DoMoveWindow(int x, int y, int width, int height)
856 {
857 DoSetSize(x, y, width, height);
858 }
859
860 // ---------------------------------------------------------------------------
861 // text metrics
862 // ---------------------------------------------------------------------------
863
864 int wxWindowX11::GetCharHeight() const
865 {
866 wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
867
868 WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, GetXDisplay());
869
870 int direction, ascent, descent;
871 XCharStruct overall;
872 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
873 &descent, &overall);
874
875 // return (overall.ascent + overall.descent);
876 return (ascent + descent);
877 }
878
879 int wxWindowX11::GetCharWidth() const
880 {
881 wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
882
883 WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, GetXDisplay());
884
885 int direction, ascent, descent;
886 XCharStruct overall;
887 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
888 &descent, &overall);
889
890 return overall.width;
891 }
892
893 void wxWindowX11::GetTextExtent(const wxString& string,
894 int *x, int *y,
895 int *descent, int *externalLeading,
896 const wxFont *theFont) const
897 {
898 wxFont *fontToUse = (wxFont *)theFont;
899 if (!fontToUse)
900 fontToUse = (wxFont *) & m_font;
901
902 wxCHECK_RET( fontToUse->Ok(), "valid window font needed" );
903
904 WXFontStructPtr pFontStruct = theFont->GetFontStruct(1.0, GetXDisplay());
905
906 int direction, ascent, descent2;
907 XCharStruct overall;
908 int slen = string.Len();
909
910 #if 0
911 if (use16)
912 XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
913 &ascent, &descent2, &overall);
914 #endif
915
916 XTextExtents((XFontStruct*) pFontStruct, string, slen,
917 &direction, &ascent, &descent2, &overall);
918
919 if ( x )
920 *x = (overall.width);
921 if ( y )
922 *y = (ascent + descent2);
923 if (descent)
924 *descent = descent2;
925 if (externalLeading)
926 *externalLeading = 0;
927
928 }
929
930 // ----------------------------------------------------------------------------
931 // painting
932 // ----------------------------------------------------------------------------
933
934 void wxWindowX11::Refresh(bool eraseBack, const wxRect *rect)
935 {
936 if (eraseBack)
937 {
938 if (rect)
939 {
940 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
941 m_clearRegion.Union( rect->x, rect->y, rect->width, rect->height );
942 }
943 else
944 {
945 int height,width;
946 GetSize( &width, &height );
947
948 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
949 m_clearRegion.Clear();
950 m_clearRegion.Union( 0, 0, width, height );
951 }
952 }
953
954 if (rect)
955 {
956 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
957 m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height );
958 }
959 else
960 {
961 int height,width;
962 GetSize( &width, &height );
963
964 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
965 m_updateRegion.Clear();
966 m_updateRegion.Union( 0, 0, width, height );
967 }
968
969 // Actually don't schedule yet..
970 Update();
971 }
972
973 void wxWindowX11::Update()
974 {
975 if (!m_updateRegion.IsEmpty())
976 {
977 X11SendPaintEvents();
978 }
979 }
980
981 void wxWindowX11::Clear()
982 {
983 wxClientDC dc((wxWindow*) this);
984 wxBrush brush(GetBackgroundColour(), wxSOLID);
985 dc.SetBackground(brush);
986 dc.Clear();
987 }
988
989 void wxWindowX11::X11SendPaintEvents()
990 {
991 m_clipPaintRegion = TRUE;
992
993 // if (!m_clearRegion.IsEmpty())
994 {
995 wxWindowDC dc( (wxWindow*)this );
996 dc.SetClippingRegion( m_clearRegion );
997
998 wxEraseEvent erase_event( GetId(), &dc );
999 erase_event.SetEventObject( this );
1000
1001 if (!GetEventHandler()->ProcessEvent(erase_event))
1002 {
1003 wxRegionIterator upd( m_clearRegion );
1004 while (upd)
1005 {
1006 XClearArea( wxGlobalDisplay(), (Window) m_mainWidget,
1007 upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight(), False );
1008 upd ++;
1009 }
1010 }
1011 m_clearRegion.Clear();
1012 }
1013
1014 wxNcPaintEvent nc_paint_event( GetId() );
1015 nc_paint_event.SetEventObject( this );
1016 GetEventHandler()->ProcessEvent( nc_paint_event );
1017
1018 wxPaintEvent paint_event( GetId() );
1019 paint_event.SetEventObject( this );
1020 GetEventHandler()->ProcessEvent( paint_event );
1021
1022 m_clipPaintRegion = FALSE;
1023 }
1024
1025 // ----------------------------------------------------------------------------
1026 // event handlers
1027 // ----------------------------------------------------------------------------
1028
1029 // Responds to colour changes: passes event on to children.
1030 void wxWindowX11::OnSysColourChanged(wxSysColourChangedEvent& event)
1031 {
1032 wxWindowList::Node *node = GetChildren().GetFirst();
1033 while ( node )
1034 {
1035 // Only propagate to non-top-level windows
1036 wxWindow *win = node->GetData();
1037 if ( win->GetParent() )
1038 {
1039 wxSysColourChangedEvent event2;
1040 event.m_eventObject = win;
1041 win->GetEventHandler()->ProcessEvent(event2);
1042 }
1043
1044 node = node->GetNext();
1045 }
1046 }
1047
1048 void wxWindowX11::OnIdle(wxIdleEvent& WXUNUSED(event))
1049 {
1050 // This calls the UI-update mechanism (querying windows for
1051 // menu/toolbar/control state information)
1052 UpdateWindowUI();
1053 }
1054
1055 // ----------------------------------------------------------------------------
1056 // function which maintain the global hash table mapping Widgets to wxWindows
1057 // ----------------------------------------------------------------------------
1058
1059 bool wxAddWindowToTable(Window w, wxWindow *win)
1060 {
1061 wxWindow *oldItem = NULL;
1062 if ((oldItem = (wxWindow *)wxWidgetHashTable->Get ((long) w)))
1063 {
1064 wxLogDebug("Widget table clash: new widget is %ld, %s",
1065 (long)w, win->GetClassInfo()->GetClassName());
1066 return FALSE;
1067 }
1068
1069 wxWidgetHashTable->Put((long) w, win);
1070
1071 wxLogTrace("widget", "XWindow 0x%08x <-> window %p (%s)",
1072 w, win, win->GetClassInfo()->GetClassName());
1073
1074 return TRUE;
1075 }
1076
1077 wxWindow *wxGetWindowFromTable(Window w)
1078 {
1079 return (wxWindow *)wxWidgetHashTable->Get((long) w);
1080 }
1081
1082 void wxDeleteWindowFromTable(Window w)
1083 {
1084 wxWidgetHashTable->Delete((long)w);
1085 }
1086
1087 // ----------------------------------------------------------------------------
1088 // add/remove window from the table
1089 // ----------------------------------------------------------------------------
1090
1091 // ----------------------------------------------------------------------------
1092 // X11-specific accessors
1093 // ----------------------------------------------------------------------------
1094
1095 // Get the underlying X window
1096 WXWindow wxWindowX11::GetXWindow() const
1097 {
1098 return GetMainWindow();
1099 }
1100
1101 // Get the underlying X display
1102 WXDisplay *wxWindowX11::GetXDisplay() const
1103 {
1104 return wxGetDisplay();
1105 }
1106
1107 WXWindow wxWindowX11::GetMainWindow() const
1108 {
1109 return m_mainWidget;
1110 }
1111
1112 // ----------------------------------------------------------------------------
1113 // TranslateXXXEvent() functions
1114 // ----------------------------------------------------------------------------
1115
1116 bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Window window, XEvent *xevent)
1117 {
1118 switch (xevent->xany.type)
1119 {
1120 case EnterNotify:
1121 case LeaveNotify:
1122 case ButtonPress:
1123 case ButtonRelease:
1124 case MotionNotify:
1125 {
1126 wxEventType eventType = wxEVT_NULL;
1127
1128 if (xevent->xany.type == EnterNotify)
1129 {
1130 //if (local_event.xcrossing.mode!=NotifyNormal)
1131 // return ; // Ignore grab events
1132 eventType = wxEVT_ENTER_WINDOW;
1133 // canvas->GetEventHandler()->OnSetFocus();
1134 }
1135 else if (xevent->xany.type == LeaveNotify)
1136 {
1137 //if (local_event.xcrossingr.mode!=NotifyNormal)
1138 // return ; // Ignore grab events
1139 eventType = wxEVT_LEAVE_WINDOW;
1140 // canvas->GetEventHandler()->OnKillFocus();
1141 }
1142 else if (xevent->xany.type == MotionNotify)
1143 {
1144 eventType = wxEVT_MOTION;
1145 }
1146 else if (xevent->xany.type == ButtonPress)
1147 {
1148 wxevent.SetTimestamp(xevent->xbutton.time);
1149 int button = 0;
1150 if (xevent->xbutton.button == Button1)
1151 {
1152 eventType = wxEVT_LEFT_DOWN;
1153 button = 1;
1154 }
1155 else if (xevent->xbutton.button == Button2)
1156 {
1157 eventType = wxEVT_MIDDLE_DOWN;
1158 button = 2;
1159 }
1160 else if (xevent->xbutton.button == Button3)
1161 {
1162 eventType = wxEVT_RIGHT_DOWN;
1163 button = 3;
1164 }
1165
1166 // check for a double click
1167 // TODO: where can we get this value from?
1168 //long dclickTime = XtGetMultiClickTime(wxGlobalDisplay());
1169 long dclickTime = 200;
1170 long ts = wxevent.GetTimestamp();
1171
1172 int buttonLast = win->GetLastClickedButton();
1173 long lastTS = win->GetLastClickTime();
1174 if ( buttonLast && buttonLast == button && (ts - lastTS) < dclickTime )
1175 {
1176 // I have a dclick
1177 win->SetLastClick(0, ts);
1178 if ( eventType == wxEVT_LEFT_DOWN )
1179 eventType = wxEVT_LEFT_DCLICK;
1180 else if ( eventType == wxEVT_MIDDLE_DOWN )
1181 eventType = wxEVT_MIDDLE_DCLICK;
1182 else if ( eventType == wxEVT_RIGHT_DOWN )
1183 eventType = wxEVT_RIGHT_DCLICK;
1184 }
1185 else
1186 {
1187 // not fast enough or different button
1188 win->SetLastClick(button, ts);
1189 }
1190 }
1191 else if (xevent->xany.type == ButtonRelease)
1192 {
1193 if (xevent->xbutton.button == Button1)
1194 {
1195 eventType = wxEVT_LEFT_UP;
1196 }
1197 else if (xevent->xbutton.button == Button2)
1198 {
1199 eventType = wxEVT_MIDDLE_UP;
1200 }
1201 else if (xevent->xbutton.button == Button3)
1202 {
1203 eventType = wxEVT_RIGHT_UP;
1204 }
1205 else return FALSE;
1206 }
1207 else
1208 {
1209 return FALSE;
1210 }
1211
1212 wxevent.SetEventType(eventType);
1213
1214 wxevent.m_x = xevent->xbutton.x;
1215 wxevent.m_y = xevent->xbutton.y;
1216
1217 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
1218 || (event_left_is_down (xevent)
1219 && (eventType != wxEVT_LEFT_UP)));
1220 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
1221 || (event_middle_is_down (xevent)
1222 && (eventType != wxEVT_MIDDLE_UP)));
1223 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
1224 || (event_right_is_down (xevent)
1225 && (eventType != wxEVT_RIGHT_UP)));
1226
1227 wxevent.m_shiftDown = xevent->xbutton.state & ShiftMask;
1228 wxevent.m_controlDown = xevent->xbutton.state & ControlMask;
1229 wxevent.m_altDown = xevent->xbutton.state & Mod3Mask;
1230 wxevent.m_metaDown = xevent->xbutton.state & Mod1Mask;
1231
1232 wxevent.SetId(win->GetId());
1233 wxevent.SetEventObject(win);
1234
1235 return TRUE;
1236 }
1237 }
1238 return FALSE;
1239 }
1240
1241 bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Window WXUNUSED(win), XEvent *xevent)
1242 {
1243 switch (xevent->xany.type)
1244 {
1245 case KeyPress:
1246 case KeyRelease:
1247 {
1248 char buf[20];
1249
1250 KeySym keySym;
1251 (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, NULL);
1252 int id = wxCharCodeXToWX (keySym);
1253
1254 if (xevent->xkey.state & ShiftMask)
1255 wxevent.m_shiftDown = TRUE;
1256 if (xevent->xkey.state & ControlMask)
1257 wxevent.m_controlDown = TRUE;
1258 if (xevent->xkey.state & Mod3Mask)
1259 wxevent.m_altDown = TRUE;
1260 if (xevent->xkey.state & Mod1Mask)
1261 wxevent.m_metaDown = TRUE;
1262 wxevent.SetEventObject(win);
1263 wxevent.m_keyCode = id;
1264 wxevent.SetTimestamp(xevent->xkey.time);
1265
1266 wxevent.m_x = xevent->xbutton.x;
1267 wxevent.m_y = xevent->xbutton.y;
1268
1269 if (id > -1)
1270 return TRUE;
1271 else
1272 return FALSE;
1273 break;
1274 }
1275 default:
1276 break;
1277 }
1278 return FALSE;
1279 }
1280
1281 // ----------------------------------------------------------------------------
1282 // Colour stuff
1283 // ----------------------------------------------------------------------------
1284
1285 #if 0
1286
1287 #define YAllocColor XAllocColor
1288 XColor g_itemColors[5];
1289 int wxComputeColours (Display *display, wxColour * back, wxColour * fore)
1290 {
1291 int result;
1292 static XmColorProc colorProc;
1293
1294 result = wxNO_COLORS;
1295
1296 if (back)
1297 {
1298 g_itemColors[0].red = (((long) back->Red ()) << 8);
1299 g_itemColors[0].green = (((long) back->Green ()) << 8);
1300 g_itemColors[0].blue = (((long) back->Blue ()) << 8);
1301 g_itemColors[0].flags = DoRed | DoGreen | DoBlue;
1302 if (colorProc == (XmColorProc) NULL)
1303 {
1304 // Get a ptr to the actual function
1305 colorProc = XmSetColorCalculation ((XmColorProc) NULL);
1306 // And set it back to motif.
1307 XmSetColorCalculation (colorProc);
1308 }
1309 (*colorProc) (&g_itemColors[wxBACK_INDEX],
1310 &g_itemColors[wxFORE_INDEX],
1311 &g_itemColors[wxSELE_INDEX],
1312 &g_itemColors[wxTOPS_INDEX],
1313 &g_itemColors[wxBOTS_INDEX]);
1314 result = wxBACK_COLORS;
1315 }
1316 if (fore)
1317 {
1318 g_itemColors[wxFORE_INDEX].red = (((long) fore->Red ()) << 8);
1319 g_itemColors[wxFORE_INDEX].green = (((long) fore->Green ()) << 8);
1320 g_itemColors[wxFORE_INDEX].blue = (((long) fore->Blue ()) << 8);
1321 g_itemColors[wxFORE_INDEX].flags = DoRed | DoGreen | DoBlue;
1322 if (result == wxNO_COLORS)
1323 result = wxFORE_COLORS;
1324 }
1325
1326 Display *dpy = display;
1327 Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy);
1328
1329 if (back)
1330 {
1331 /* 5 Colours to allocate */
1332 for (int i = 0; i < 5; i++)
1333 if (!YAllocColor (dpy, cmap, &g_itemColors[i]))
1334 result = wxNO_COLORS;
1335 }
1336 else if (fore)
1337 {
1338 /* Only 1 colour to allocate */
1339 if (!YAllocColor (dpy, cmap, &g_itemColors[wxFORE_INDEX]))
1340 result = wxNO_COLORS;
1341 }
1342
1343 return (result);
1344
1345 }
1346 #endif
1347
1348 bool wxWindowX11::SetBackgroundColour(const wxColour& col)
1349 {
1350 wxWindowBase::SetBackgroundColour(col);
1351
1352 if (!GetMainWindow())
1353 return FALSE;
1354
1355 Display *xdisplay = (Display*) wxGlobalDisplay();
1356 int xscreen = DefaultScreen( xdisplay );
1357 Colormap cm = DefaultColormap( xdisplay, xscreen );
1358
1359 wxColour colour( col );
1360 colour.CalcPixel( (WXColormap) cm );
1361
1362 XSetWindowAttributes attrib;
1363 attrib.background_pixel = colour.GetPixel();
1364
1365 XChangeWindowAttributes(wxGlobalDisplay(),
1366 (Window) GetMainWindow(),
1367 CWBackPixel,
1368 & attrib);
1369
1370 return TRUE;
1371 }
1372
1373 bool wxWindowX11::SetForegroundColour(const wxColour& col)
1374 {
1375 if ( !wxWindowBase::SetForegroundColour(col) )
1376 return FALSE;
1377
1378 return TRUE;
1379 }
1380
1381 // ----------------------------------------------------------------------------
1382 // global functions
1383 // ----------------------------------------------------------------------------
1384
1385 wxWindow *wxGetActiveWindow()
1386 {
1387 // TODO
1388 wxFAIL_MSG("Not implemented");
1389 return NULL;
1390 }
1391
1392 /* static */
1393 wxWindow *wxWindowBase::GetCapture()
1394 {
1395 return (wxWindow *)g_captureWindow;
1396 }
1397
1398
1399 // Find the wxWindow at the current mouse position, returning the mouse
1400 // position.
1401 wxWindow* wxFindWindowAtPointer(wxPoint& pt)
1402 {
1403 return wxFindWindowAtPoint(wxGetMousePosition());
1404 }
1405
1406 // Get the current mouse position.
1407 wxPoint wxGetMousePosition()
1408 {
1409 Display *display = wxGlobalDisplay();
1410 Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
1411 Window rootReturn, childReturn;
1412 int rootX, rootY, winX, winY;
1413 unsigned int maskReturn;
1414
1415 XQueryPointer (display,
1416 rootWindow,
1417 &rootReturn,
1418 &childReturn,
1419 &rootX, &rootY, &winX, &winY, &maskReturn);
1420 return wxPoint(rootX, rootY);
1421 }
1422
1423
1424 // ----------------------------------------------------------------------------
1425 // wxNoOptimize: switch off size optimization
1426 // ----------------------------------------------------------------------------
1427
1428 int wxNoOptimize::ms_count = 0;
1429