Small changes to wxX11
[wxWidgets.git] / src / x11 / window.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: windows.cpp
3 // Purpose: wxWindow
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 17/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "window.h"
22 #endif
23
24 #include "wx/setup.h"
25 #include "wx/menu.h"
26 #include "wx/dc.h"
27 #include "wx/dcclient.h"
28 #include "wx/utils.h"
29 #include "wx/app.h"
30 #include "wx/panel.h"
31 #include "wx/layout.h"
32 #include "wx/dialog.h"
33 #include "wx/listbox.h"
34 #include "wx/button.h"
35 #include "wx/settings.h"
36 #include "wx/msgdlg.h"
37 #include "wx/frame.h"
38 #include "wx/scrolwin.h"
39 #include "wx/module.h"
40 #include "wx/menuitem.h"
41 #include "wx/log.h"
42
43 #if wxUSE_DRAG_AND_DROP
44 #include "wx/dnd.h"
45 #endif
46
47 #include "wx/x11/private.h"
48 #include "X11/Xutil.h"
49
50 #include <string.h>
51
52 // ----------------------------------------------------------------------------
53 // constants
54 // ----------------------------------------------------------------------------
55
56 static const int SCROLL_MARGIN = 4;
57
58 // ----------------------------------------------------------------------------
59 // global variables for this module
60 // ----------------------------------------------------------------------------
61
62 extern wxHashTable *wxWidgetHashTable;
63 static wxWindow* g_captureWindow = NULL;
64
65 // ----------------------------------------------------------------------------
66 // macros
67 // ----------------------------------------------------------------------------
68
69 #define event_left_is_down(x) ((x)->xbutton.state & Button1Mask)
70 #define event_middle_is_down(x) ((x)->xbutton.state & Button2Mask)
71 #define event_right_is_down(x) ((x)->xbutton.state & Button3Mask)
72
73 // ----------------------------------------------------------------------------
74 // event tables
75 // ----------------------------------------------------------------------------
76
77 IMPLEMENT_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 ShiftMask, LockMask, Control-Mask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask.,
330 GrabModeAsync,
331 GrabModeAsync,
332 CurrentTime);
333
334 if (res != GrabSuccess)
335 {
336 wxLogDebug("Failed to grab keyboard.");
337 XUngrabPointer(wxGlobalDisplay(), CurrentTime);
338 XUngrabButton(wxGlobalDisplay(), AnyButton, AnyModifier,
339 (Window) GetMainWindow());
340 return;
341 }
342
343 m_winCaptured = TRUE;
344 }
345 }
346
347 void wxWindowX11::DoReleaseMouse()
348 {
349 g_captureWindow = NULL;
350 if ( !m_winCaptured )
351 return;
352
353 Window wMain = (Window)GetMainWindow();
354
355 if ( wMain )
356 {
357 XUngrabPointer(wxGlobalDisplay(), wMain);
358 XUngrabButton(wxGlobalDisplay(), AnyButton, AnyModifier,
359 wMain);
360 XUngrabKeyboard(wxGlobalDisplay(), CurrentTime);
361 }
362
363 m_winCaptured = FALSE;
364 }
365
366 bool wxWindowX11::SetFont(const wxFont& font)
367 {
368 if ( !wxWindowBase::SetFont(font) )
369 {
370 // nothing to do
371 return FALSE;
372 }
373
374 return TRUE;
375 }
376
377 bool wxWindowX11::SetCursor(const wxCursor& cursor)
378 {
379 if ( !wxWindowBase::SetCursor(cursor) )
380 {
381 // no change
382 return FALSE;
383 }
384
385 wxCursor* cursor2 = NULL;
386 if (m_cursor.Ok())
387 cursor2 = & m_cursor;
388 else
389 cursor2 = wxSTANDARD_CURSOR;
390
391 WXDisplay *dpy = GetXDisplay();
392 WXCursor x_cursor = cursor2->GetXCursor(dpy);
393
394 Window win = (Window) GetMainWindow();
395 XDefineCursor((Display*) dpy, win, (Cursor) x_cursor);
396
397 return TRUE;
398 }
399
400 // Coordinates relative to the window
401 void wxWindowX11::WarpPointer (int x, int y)
402 {
403 if (m_mainWidget)
404 XWarpPointer( wxGlobalDisplay(), None, (Window) m_mainWidget, 0, 0, 0, 0, x, y);
405 }
406
407 // Does a physical scroll
408 void wxWindowX11::ScrollWindow(int dx, int dy, const wxRect *rect)
409 {
410 int x, y, w, h;
411 if (rect)
412 {
413 // Use specified rectangle
414 x = rect->x; y = rect->y; w = rect->width; h = rect->height;
415 }
416 else
417 {
418 // Use whole client area
419 x = 0; y = 0;
420 GetClientSize(& w, & h);
421 }
422
423 wxNode *cnode = m_children.First();
424 while (cnode)
425 {
426 wxWindow *child = (wxWindow*) cnode->Data();
427 int sx = 0;
428 int sy = 0;
429 child->GetSize( &sx, &sy );
430 wxPoint pos( child->GetPosition() );
431 child->SetSize( pos.x + dx, pos.y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
432 cnode = cnode->Next();
433 }
434
435 int x1 = (dx >= 0) ? x : x - dx;
436 int y1 = (dy >= 0) ? y : y - dy;
437 int w1 = w - abs(dx);
438 int h1 = h - abs(dy);
439 int x2 = (dx >= 0) ? x + dx : x;
440 int y2 = (dy >= 0) ? y + dy : y;
441
442 wxClientDC dc((wxWindow*) this);
443
444 dc.SetLogicalFunction (wxCOPY);
445
446 Window window = (Window) GetMainWindow();
447 Display* display = wxGlobalDisplay();
448
449 XCopyArea(display, window, window, (GC) dc.GetGC(),
450 x1, y1, w1, h1, x2, y2);
451
452 dc.SetAutoSetting(TRUE);
453 wxBrush brush(GetBackgroundColour(), wxSOLID);
454 dc.SetBrush(brush); // FIXME: needed?
455
456 // We'll add rectangles to the list of update rectangles according to which
457 // bits we've exposed.
458 wxList updateRects;
459
460 if (dx > 0)
461 {
462 wxRect *rect = new wxRect;
463 rect->x = x;
464 rect->y = y;
465 rect->width = dx;
466 rect->height = h;
467
468 XFillRectangle(display, window,
469 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
470
471 rect->x = rect->x;
472 rect->y = rect->y;
473 rect->width = rect->width;
474 rect->height = rect->height;
475
476 updateRects.Append((wxObject*) rect);
477 }
478 else if (dx < 0)
479 {
480 wxRect *rect = new wxRect;
481
482 rect->x = x + w + dx;
483 rect->y = y;
484 rect->width = -dx;
485 rect->height = h;
486
487 XFillRectangle(display, window,
488 (GC) dc.GetGC(), rect->x, rect->y, rect->width,
489 rect->height);
490
491 rect->x = rect->x;
492 rect->y = rect->y;
493 rect->width = rect->width;
494 rect->height = rect->height;
495
496 updateRects.Append((wxObject*) rect);
497 }
498 if (dy > 0)
499 {
500 wxRect *rect = new wxRect;
501
502 rect->x = x;
503 rect->y = y;
504 rect->width = w;
505 rect->height = dy;
506
507 XFillRectangle(display, window,
508 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
509
510 rect->x = rect->x;
511 rect->y = rect->y;
512 rect->width = rect->width;
513 rect->height = rect->height;
514
515 updateRects.Append((wxObject*) rect);
516 }
517 else if (dy < 0)
518 {
519 wxRect *rect = new wxRect;
520
521 rect->x = x;
522 rect->y = y + h + dy;
523 rect->width = w;
524 rect->height = -dy;
525
526 XFillRectangle(display, window,
527 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
528
529 rect->x = rect->x;
530 rect->y = rect->y;
531 rect->width = rect->width;
532 rect->height = rect->height;
533
534 updateRects.Append((wxObject*) rect);
535 }
536 dc.SetBrush(wxNullBrush);
537
538 // Now send expose events
539
540 wxNode* node = updateRects.First();
541 while (node)
542 {
543 wxRect* rect = (wxRect*) node->Data();
544 XExposeEvent event;
545
546 event.type = Expose;
547 event.display = display;
548 event.send_event = True;
549 event.window = window;
550
551 event.x = rect->x;
552 event.y = rect->y;
553 event.width = rect->width;
554 event.height = rect->height;
555
556 event.count = 0;
557
558 XSendEvent(display, window, False, ExposureMask, (XEvent *)&event);
559
560 node = node->Next();
561
562 }
563
564 // Delete the update rects
565 node = updateRects.First();
566 while (node)
567 {
568 wxRect* rect = (wxRect*) node->Data();
569 delete rect;
570 node = node->Next();
571 }
572
573 // TODO
574
575 // XmUpdateDisplay((Widget) GetMainWidget());
576 }
577
578 // ---------------------------------------------------------------------------
579 // drag and drop
580 // ---------------------------------------------------------------------------
581
582 #if wxUSE_DRAG_AND_DROP
583
584 void wxWindowX11::SetDropTarget(wxDropTarget * WXUNUSED(pDropTarget))
585 {
586 // TODO
587 }
588
589 #endif
590
591 // Old style file-manager drag&drop
592 void wxWindowX11::DragAcceptFiles(bool WXUNUSED(accept))
593 {
594 // TODO
595 }
596
597 // ----------------------------------------------------------------------------
598 // tooltips
599 // ----------------------------------------------------------------------------
600
601 #if wxUSE_TOOLTIPS
602
603 void wxWindowX11::DoSetToolTip(wxToolTip * WXUNUSED(tooltip))
604 {
605 // TODO
606 }
607
608 #endif // wxUSE_TOOLTIPS
609
610 // ---------------------------------------------------------------------------
611 // moving and resizing
612 // ---------------------------------------------------------------------------
613
614 bool wxWindowX11::PreResize()
615 {
616 return TRUE;
617 }
618
619 // Get total size
620 void wxWindowX11::DoGetSize(int *x, int *y) const
621 {
622 Window window = (Window) m_mainWidget;
623 if (window)
624 {
625 XWindowAttributes attr;
626 Status status = XGetWindowAttributes(wxGlobalDisplay(), window, & attr);
627 wxASSERT(status);
628
629 if (status)
630 {
631 *x = attr.width /* + 2*m_borderSize */ ;
632 *y = attr.height /* + 2*m_borderSize */ ;
633 }
634 }
635 }
636
637 void wxWindowX11::DoGetPosition(int *x, int *y) const
638 {
639 Window window = (Window) m_mainWidget;
640 if (window)
641 {
642 XWindowAttributes attr;
643 Status status = XGetWindowAttributes(wxGlobalDisplay(), window, & attr);
644 wxASSERT(status);
645
646 if (status)
647 {
648 *x = attr.x;
649 *y = attr.y;
650
651 // We may be faking the client origin. So a window that's really at (0, 30)
652 // may appear (to wxWin apps) to be at (0, 0).
653 if (GetParent())
654 {
655 wxPoint pt(GetParent()->GetClientAreaOrigin());
656 *x -= pt.x;
657 *y -= pt.y;
658 }
659 }
660 }
661 }
662
663 void wxWindowX11::DoScreenToClient(int *x, int *y) const
664 {
665 Display *display = wxGlobalDisplay();
666 Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display));
667 Window thisWindow = (Window) m_mainWidget;
668
669 Window childWindow;
670 int xx = *x;
671 int yy = *y;
672 XTranslateCoordinates(display, rootWindow, thisWindow, xx, yy, x, y, &childWindow);
673 }
674
675 void wxWindowX11::DoClientToScreen(int *x, int *y) const
676 {
677 Display *display = wxGlobalDisplay();
678 Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display));
679 Window thisWindow = (Window) m_mainWidget;
680
681 Window childWindow;
682 int xx = *x;
683 int yy = *y;
684 XTranslateCoordinates(display, thisWindow, rootWindow, xx, yy, x, y, &childWindow);
685 }
686
687
688 // Get size *available for subwindows* i.e. excluding menu bar etc.
689 void wxWindowX11::DoGetClientSize(int *x, int *y) const
690 {
691 Window window = (Window) m_mainWidget;
692
693 if (window)
694 {
695 XWindowAttributes attr;
696 Status status = XGetWindowAttributes(wxGlobalDisplay(), window, & attr);
697 wxASSERT(status);
698
699 if (status)
700 {
701 *x = attr.width ;
702 *y = attr.height ;
703 }
704 }
705 }
706
707 void wxWindowX11::DoSetSize(int x, int y, int width, int height, int sizeFlags)
708 {
709 if (!GetMainWindow())
710 return;
711
712 XWindowChanges windowChanges;
713 int valueMask = 0;
714
715 if (x != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
716 {
717 windowChanges.x = x;
718 valueMask |= CWX;
719 }
720 if (y != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
721 {
722 windowChanges.y = y;
723 valueMask |= CWY;
724 }
725 if (width != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
726 {
727 windowChanges.width = width /* - m_borderSize*2 */;
728 valueMask |= CWWidth;
729 }
730 if (height != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
731 {
732 windowChanges.height = height /* -m_borderSize*2*/;
733 valueMask |= CWHeight;
734 }
735 AdjustForParentClientOrigin( x, y, sizeFlags);
736
737 XConfigureWindow(wxGlobalDisplay(), (Window) GetMainWindow(),
738 valueMask, & windowChanges);
739 }
740
741 void wxWindowX11::DoSetClientSize(int width, int height)
742 {
743 if (!GetMainWindow())
744 return;
745
746 XWindowChanges windowChanges;
747 int valueMask = 0;
748
749 if (width != -1)
750 {
751 windowChanges.width = width ;
752 valueMask |= CWWidth;
753 }
754 if (height != -1)
755 {
756 windowChanges.height = height ;
757 valueMask |= CWHeight;
758 }
759 XConfigureWindow(wxGlobalDisplay(), (Window) GetMainWindow(),
760 valueMask, & windowChanges);
761 }
762
763 // For implementation purposes - sometimes decorations make the client area
764 // smaller
765 wxPoint wxWindowX11::GetClientAreaOrigin() const
766 {
767 return wxPoint(0, 0);
768 }
769
770 // Makes an adjustment to the window position (for example, a frame that has
771 // a toolbar that it manages itself).
772 void wxWindowX11::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags)
773 {
774 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
775 {
776 wxPoint pt(GetParent()->GetClientAreaOrigin());
777 x += pt.x; y += pt.y;
778 }
779 }
780
781 void wxWindowX11::SetSizeHints(int minW, int minH, int maxW, int maxH, int incW, int incH)
782 {
783 m_minWidth = minW;
784 m_minHeight = minH;
785 m_maxWidth = maxW;
786 m_maxHeight = maxH;
787
788 XSizeHints sizeHints;
789 sizeHints.flags = 0;
790
791 if (minW > -1 && minH > -1)
792 {
793 sizeHints.flags |= PMinSize;
794 sizeHints.min_width = minW;
795 sizeHints.min_height = minH;
796 }
797 if (maxW > -1 && maxH > -1)
798 {
799 sizeHints.flags |= PMaxSize;
800 sizeHints.max_width = maxW;
801 sizeHints.max_height = maxH;
802 }
803 if (incW > -1 && incH > -1)
804 {
805 sizeHints.flags |= PResizeInc;
806 sizeHints.width_inc = incW;
807 sizeHints.height_inc = incH;
808 }
809
810 XSetWMNormalHints(wxGlobalDisplay(), (Window) GetMainWindow(), & sizeHints);
811 }
812
813 void wxWindowX11::DoMoveWindow(int x, int y, int width, int height)
814 {
815 DoSetSize(x, y, width, height);
816 }
817
818 // ---------------------------------------------------------------------------
819 // text metrics
820 // ---------------------------------------------------------------------------
821
822 int wxWindowX11::GetCharHeight() const
823 {
824 wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
825
826 WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, GetXDisplay());
827
828 int direction, ascent, descent;
829 XCharStruct overall;
830 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
831 &descent, &overall);
832
833 // return (overall.ascent + overall.descent);
834 return (ascent + descent);
835 }
836
837 int wxWindowX11::GetCharWidth() const
838 {
839 wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
840
841 WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, GetXDisplay());
842
843 int direction, ascent, descent;
844 XCharStruct overall;
845 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
846 &descent, &overall);
847
848 return overall.width;
849 }
850
851 void wxWindowX11::GetTextExtent(const wxString& string,
852 int *x, int *y,
853 int *descent, int *externalLeading,
854 const wxFont *theFont) const
855 {
856 wxFont *fontToUse = (wxFont *)theFont;
857 if (!fontToUse)
858 fontToUse = (wxFont *) & m_font;
859
860 wxCHECK_RET( fontToUse->Ok(), "valid window font needed" );
861
862 WXFontStructPtr pFontStruct = theFont->GetFontStruct(1.0, GetXDisplay());
863
864 int direction, ascent, descent2;
865 XCharStruct overall;
866 int slen = string.Len();
867
868 #if 0
869 if (use16)
870 XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
871 &ascent, &descent2, &overall);
872 #endif
873
874 XTextExtents((XFontStruct*) pFontStruct, string, slen,
875 &direction, &ascent, &descent2, &overall);
876
877 if ( x )
878 *x = (overall.width);
879 if ( y )
880 *y = (ascent + descent2);
881 if (descent)
882 *descent = descent2;
883 if (externalLeading)
884 *externalLeading = 0;
885
886 }
887
888 // ----------------------------------------------------------------------------
889 // painting
890 // ----------------------------------------------------------------------------
891
892 void wxWindowX11::Refresh(bool eraseBack, const wxRect *rect)
893 {
894 if (eraseBack)
895 {
896 if (rect)
897 {
898 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
899 m_clearRegion.Union( rect->x, rect->y, rect->width, rect->height );
900 }
901 else
902 {
903 int height,width;
904 GetSize( &width, &height );
905
906 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
907 m_clearRegion.Clear();
908 m_clearRegion.Union( 0, 0, width, height );
909 }
910 }
911
912 if (rect)
913 {
914 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
915 m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height );
916 }
917 else
918 {
919 int height,width;
920 GetSize( &width, &height );
921
922 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
923 m_updateRegion.Clear();
924 m_updateRegion.Union( 0, 0, width, height );
925 }
926
927 // Actually don't schedule yet..
928 Update();
929 }
930
931 void wxWindowX11::Update()
932 {
933 if (!m_updateRegion.IsEmpty())
934 {
935 X11SendPaintEvents();
936 }
937 }
938
939 void wxWindowX11::Clear()
940 {
941 wxClientDC dc((wxWindow*) this);
942 wxBrush brush(GetBackgroundColour(), wxSOLID);
943 dc.SetBackground(brush);
944 dc.Clear();
945 }
946
947 void wxWindowX11::X11SendPaintEvents()
948 {
949 m_clipPaintRegion = TRUE;
950
951 if (!m_clearRegion.IsEmpty())
952 {
953 wxWindowDC dc( (wxWindow*)this );
954 dc.SetClippingRegion( m_clearRegion );
955
956 wxEraseEvent erase_event( GetId(), &dc );
957 erase_event.SetEventObject( this );
958
959 if (!GetEventHandler()->ProcessEvent(erase_event))
960 {
961 wxRegionIterator upd( m_clearRegion );
962 while (upd)
963 {
964 // XClearArea( ... , upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() );
965 upd ++;
966 }
967 }
968 m_clearRegion.Clear();
969 }
970
971 wxNcPaintEvent nc_paint_event( GetId() );
972 nc_paint_event.SetEventObject( this );
973 GetEventHandler()->ProcessEvent( nc_paint_event );
974
975 wxPaintEvent paint_event( GetId() );
976 paint_event.SetEventObject( this );
977 GetEventHandler()->ProcessEvent( paint_event );
978
979 m_clipPaintRegion = FALSE;
980 }
981
982 // ----------------------------------------------------------------------------
983 // event handlers
984 // ----------------------------------------------------------------------------
985
986 // Responds to colour changes: passes event on to children.
987 void wxWindowX11::OnSysColourChanged(wxSysColourChangedEvent& event)
988 {
989 wxWindowList::Node *node = GetChildren().GetFirst();
990 while ( node )
991 {
992 // Only propagate to non-top-level windows
993 wxWindow *win = node->GetData();
994 if ( win->GetParent() )
995 {
996 wxSysColourChangedEvent event2;
997 event.m_eventObject = win;
998 win->GetEventHandler()->ProcessEvent(event2);
999 }
1000
1001 node = node->GetNext();
1002 }
1003 }
1004
1005 void wxWindowX11::OnIdle(wxIdleEvent& WXUNUSED(event))
1006 {
1007 // This calls the UI-update mechanism (querying windows for
1008 // menu/toolbar/control state information)
1009 UpdateWindowUI();
1010 }
1011
1012 // ----------------------------------------------------------------------------
1013 // function which maintain the global hash table mapping Widgets to wxWindows
1014 // ----------------------------------------------------------------------------
1015
1016 bool wxAddWindowToTable(Window w, wxWindow *win)
1017 {
1018 wxWindow *oldItem = NULL;
1019 if ((oldItem = (wxWindow *)wxWidgetHashTable->Get ((long) w)))
1020 {
1021 wxLogDebug("Widget table clash: new widget is %ld, %s",
1022 (long)w, win->GetClassInfo()->GetClassName());
1023 return FALSE;
1024 }
1025
1026 wxWidgetHashTable->Put((long) w, win);
1027
1028 wxLogTrace("widget", "XWindow 0x%08x <-> window %p (%s)",
1029 w, win, win->GetClassInfo()->GetClassName());
1030
1031 return TRUE;
1032 }
1033
1034 wxWindow *wxGetWindowFromTable(Window w)
1035 {
1036 return (wxWindow *)wxWidgetHashTable->Get((long) w);
1037 }
1038
1039 void wxDeleteWindowFromTable(Window w)
1040 {
1041 wxWidgetHashTable->Delete((long)w);
1042 }
1043
1044 // ----------------------------------------------------------------------------
1045 // add/remove window from the table
1046 // ----------------------------------------------------------------------------
1047
1048 // ----------------------------------------------------------------------------
1049 // X11-specific accessors
1050 // ----------------------------------------------------------------------------
1051
1052 // Get the underlying X window
1053 WXWindow wxWindowX11::GetXWindow() const
1054 {
1055 return GetMainWindow();
1056 }
1057
1058 // Get the underlying X display
1059 WXDisplay *wxWindowX11::GetXDisplay() const
1060 {
1061 return wxGetDisplay();
1062 }
1063
1064 WXWindow wxWindowX11::GetMainWindow() const
1065 {
1066 return m_mainWidget;
1067 }
1068
1069 // ----------------------------------------------------------------------------
1070 // TranslateXXXEvent() functions
1071 // ----------------------------------------------------------------------------
1072
1073 bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Window window, XEvent *xevent)
1074 {
1075 switch (xevent->xany.type)
1076 {
1077 case EnterNotify:
1078 case LeaveNotify:
1079 case ButtonPress:
1080 case ButtonRelease:
1081 case MotionNotify:
1082 {
1083 wxEventType eventType = wxEVT_NULL;
1084
1085 if (xevent->xany.type == EnterNotify)
1086 {
1087 //if (local_event.xcrossing.mode!=NotifyNormal)
1088 // return ; // Ignore grab events
1089 eventType = wxEVT_ENTER_WINDOW;
1090 // canvas->GetEventHandler()->OnSetFocus();
1091 }
1092 else if (xevent->xany.type == LeaveNotify)
1093 {
1094 //if (local_event.xcrossingr.mode!=NotifyNormal)
1095 // return ; // Ignore grab events
1096 eventType = wxEVT_LEAVE_WINDOW;
1097 // canvas->GetEventHandler()->OnKillFocus();
1098 }
1099 else if (xevent->xany.type == MotionNotify)
1100 {
1101 eventType = wxEVT_MOTION;
1102 }
1103 else if (xevent->xany.type == ButtonPress)
1104 {
1105 wxevent.SetTimestamp(xevent->xbutton.time);
1106 int button = 0;
1107 if (xevent->xbutton.button == Button1)
1108 {
1109 eventType = wxEVT_LEFT_DOWN;
1110 button = 1;
1111 }
1112 else if (xevent->xbutton.button == Button2)
1113 {
1114 eventType = wxEVT_MIDDLE_DOWN;
1115 button = 2;
1116 }
1117 else if (xevent->xbutton.button == Button3)
1118 {
1119 eventType = wxEVT_RIGHT_DOWN;
1120 button = 3;
1121 }
1122
1123 // check for a double click
1124 // TODO: where can we get this value from?
1125 //long dclickTime = XtGetMultiClickTime(wxGlobalDisplay());
1126 long dclickTime = 200;
1127 long ts = wxevent.GetTimestamp();
1128
1129 int buttonLast = win->GetLastClickedButton();
1130 long lastTS = win->GetLastClickTime();
1131 if ( buttonLast && buttonLast == button && (ts - lastTS) < dclickTime )
1132 {
1133 // I have a dclick
1134 win->SetLastClick(0, ts);
1135 if ( eventType == wxEVT_LEFT_DOWN )
1136 eventType = wxEVT_LEFT_DCLICK;
1137 else if ( eventType == wxEVT_MIDDLE_DOWN )
1138 eventType = wxEVT_MIDDLE_DCLICK;
1139 else if ( eventType == wxEVT_RIGHT_DOWN )
1140 eventType = wxEVT_RIGHT_DCLICK;
1141 }
1142 else
1143 {
1144 // not fast enough or different button
1145 win->SetLastClick(button, ts);
1146 }
1147 }
1148 else if (xevent->xany.type == ButtonRelease)
1149 {
1150 if (xevent->xbutton.button == Button1)
1151 {
1152 eventType = wxEVT_LEFT_UP;
1153 }
1154 else if (xevent->xbutton.button == Button2)
1155 {
1156 eventType = wxEVT_MIDDLE_UP;
1157 }
1158 else if (xevent->xbutton.button == Button3)
1159 {
1160 eventType = wxEVT_RIGHT_UP;
1161 }
1162 else return FALSE;
1163 }
1164 else
1165 {
1166 return FALSE;
1167 }
1168
1169 wxevent.SetEventType(eventType);
1170
1171 wxevent.m_x = xevent->xbutton.x;
1172 wxevent.m_y = xevent->xbutton.y;
1173
1174 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
1175 || (event_left_is_down (xevent)
1176 && (eventType != wxEVT_LEFT_UP)));
1177 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
1178 || (event_middle_is_down (xevent)
1179 && (eventType != wxEVT_MIDDLE_UP)));
1180 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
1181 || (event_right_is_down (xevent)
1182 && (eventType != wxEVT_RIGHT_UP)));
1183
1184 wxevent.m_shiftDown = xevent->xbutton.state & ShiftMask;
1185 wxevent.m_controlDown = xevent->xbutton.state & ControlMask;
1186 wxevent.m_altDown = xevent->xbutton.state & Mod3Mask;
1187 wxevent.m_metaDown = xevent->xbutton.state & Mod1Mask;
1188
1189 wxevent.SetId(win->GetId());
1190 wxevent.SetEventObject(win);
1191
1192 return TRUE;
1193 }
1194 }
1195 return FALSE;
1196 }
1197
1198 bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Window WXUNUSED(win), XEvent *xevent)
1199 {
1200 switch (xevent->xany.type)
1201 {
1202 case KeyPress:
1203 case KeyRelease:
1204 {
1205 char buf[20];
1206
1207 KeySym keySym;
1208 (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, NULL);
1209 int id = wxCharCodeXToWX (keySym);
1210
1211 if (xevent->xkey.state & ShiftMask)
1212 wxevent.m_shiftDown = TRUE;
1213 if (xevent->xkey.state & ControlMask)
1214 wxevent.m_controlDown = TRUE;
1215 if (xevent->xkey.state & Mod3Mask)
1216 wxevent.m_altDown = TRUE;
1217 if (xevent->xkey.state & Mod1Mask)
1218 wxevent.m_metaDown = TRUE;
1219 wxevent.SetEventObject(win);
1220 wxevent.m_keyCode = id;
1221 wxevent.SetTimestamp(xevent->xkey.time);
1222
1223 wxevent.m_x = xevent->xbutton.x;
1224 wxevent.m_y = xevent->xbutton.y;
1225
1226 if (id > -1)
1227 return TRUE;
1228 else
1229 return FALSE;
1230 break;
1231 }
1232 default:
1233 break;
1234 }
1235 return FALSE;
1236 }
1237
1238 // ----------------------------------------------------------------------------
1239 // Colour stuff
1240 // ----------------------------------------------------------------------------
1241
1242 #if 0
1243
1244 #define YAllocColor XAllocColor
1245 XColor g_itemColors[5];
1246 int wxComputeColours (Display *display, wxColour * back, wxColour * fore)
1247 {
1248 int result;
1249 static XmColorProc colorProc;
1250
1251 result = wxNO_COLORS;
1252
1253 if (back)
1254 {
1255 g_itemColors[0].red = (((long) back->Red ()) << 8);
1256 g_itemColors[0].green = (((long) back->Green ()) << 8);
1257 g_itemColors[0].blue = (((long) back->Blue ()) << 8);
1258 g_itemColors[0].flags = DoRed | DoGreen | DoBlue;
1259 if (colorProc == (XmColorProc) NULL)
1260 {
1261 // Get a ptr to the actual function
1262 colorProc = XmSetColorCalculation ((XmColorProc) NULL);
1263 // And set it back to motif.
1264 XmSetColorCalculation (colorProc);
1265 }
1266 (*colorProc) (&g_itemColors[wxBACK_INDEX],
1267 &g_itemColors[wxFORE_INDEX],
1268 &g_itemColors[wxSELE_INDEX],
1269 &g_itemColors[wxTOPS_INDEX],
1270 &g_itemColors[wxBOTS_INDEX]);
1271 result = wxBACK_COLORS;
1272 }
1273 if (fore)
1274 {
1275 g_itemColors[wxFORE_INDEX].red = (((long) fore->Red ()) << 8);
1276 g_itemColors[wxFORE_INDEX].green = (((long) fore->Green ()) << 8);
1277 g_itemColors[wxFORE_INDEX].blue = (((long) fore->Blue ()) << 8);
1278 g_itemColors[wxFORE_INDEX].flags = DoRed | DoGreen | DoBlue;
1279 if (result == wxNO_COLORS)
1280 result = wxFORE_COLORS;
1281 }
1282
1283 Display *dpy = display;
1284 Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy);
1285
1286 if (back)
1287 {
1288 /* 5 Colours to allocate */
1289 for (int i = 0; i < 5; i++)
1290 if (!YAllocColor (dpy, cmap, &g_itemColors[i]))
1291 result = wxNO_COLORS;
1292 }
1293 else if (fore)
1294 {
1295 /* Only 1 colour to allocate */
1296 if (!YAllocColor (dpy, cmap, &g_itemColors[wxFORE_INDEX]))
1297 result = wxNO_COLORS;
1298 }
1299
1300 return (result);
1301
1302 }
1303 #endif
1304
1305 bool wxWindowX11::SetBackgroundColour(const wxColour& col)
1306 {
1307 if ( !wxWindowBase::SetBackgroundColour(col) )
1308 return FALSE;
1309
1310 if (!GetMainWindow())
1311 return FALSE;
1312
1313 XSetWindowAttributes attrib;
1314 attrib.background_pixel = col.AllocColour(wxGlobalDisplay());
1315
1316 XChangeWindowAttributes(wxGlobalDisplay(),
1317 (Window) GetMainWindow(),
1318 CWBackPixel,
1319 & attrib);
1320
1321 return TRUE;
1322 }
1323
1324 bool wxWindowX11::SetForegroundColour(const wxColour& col)
1325 {
1326 if ( !wxWindowBase::SetForegroundColour(col) )
1327 return FALSE;
1328
1329 return TRUE;
1330 }
1331
1332 // ----------------------------------------------------------------------------
1333 // global functions
1334 // ----------------------------------------------------------------------------
1335
1336 wxWindow *wxGetActiveWindow()
1337 {
1338 // TODO
1339 wxFAIL_MSG("Not implemented");
1340 return NULL;
1341 }
1342
1343 /* static */
1344 wxWindow *wxWindowBase::GetCapture()
1345 {
1346 return (wxWindow *)g_captureWindow;
1347 }
1348
1349
1350 // Find the wxWindow at the current mouse position, returning the mouse
1351 // position.
1352 wxWindow* wxFindWindowAtPointer(wxPoint& pt)
1353 {
1354 return wxFindWindowAtPoint(wxGetMousePosition());
1355 }
1356
1357 // Get the current mouse position.
1358 wxPoint wxGetMousePosition()
1359 {
1360 Display *display = wxGlobalDisplay();
1361 Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
1362 Window rootReturn, childReturn;
1363 int rootX, rootY, winX, winY;
1364 unsigned int maskReturn;
1365
1366 XQueryPointer (display,
1367 rootWindow,
1368 &rootReturn,
1369 &childReturn,
1370 &rootX, &rootY, &winX, &winY, &maskReturn);
1371 return wxPoint(rootX, rootY);
1372 }
1373
1374
1375 // ----------------------------------------------------------------------------
1376 // wxNoOptimize: switch off size optimization
1377 // ----------------------------------------------------------------------------
1378
1379 int wxNoOptimize::ms_count = 0;
1380