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