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