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