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 // 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 Window xwindow = (Window) GetMainWindow();
464
465 wxCHECK_RET( xwindow, wxT("invalid window") );
466
467 Display *xdisplay = wxGlobalDisplay();
468
469 GC xgc = XCreateGC( xdisplay, xwindow, 0, NULL );
470 XSetGraphicsExposures( xdisplay, xgc, True );
471
472 int s_x;
473 int s_y;
474 int cw;
475 int ch;
476 if (rect)
477 {
478 s_x = rect->x;
479 s_y = rect->y;
480 cw = rect->width;
481 ch = rect->height;
482 }
483 else
484 {
485 s_x = 0;
486 s_y = 0;
487 GetClientSize( &cw, &ch );
488 }
489
490 wxPoint offset = GetClientAreaOrigin();
491 s_x += offset.x;
492 s_y += offset.y;
493
494 int w = cw - abs(dx);
495 int h = ch - abs(dy);
496
497 if ((h < 0) || (w < 0))
498 {
499 Refresh();
500 }
501 else
502 {
503 wxRect rect;
504 if (dx < 0) rect.x = cw+dx; else rect.x = s_x;
505 if (dy < 0) rect.y = ch+dy; else rect.y = s_y;
506 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
507 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
508
509 int d_x = s_x;
510 int d_y = s_y;
511 if (dx < 0) s_x += -dx;
512 if (dy < 0) s_y += -dy;
513 if (dx > 0) d_x = dx;
514 if (dy > 0) d_y = dy;
515
516 XCopyArea( xdisplay, xwindow, xwindow, xgc, s_x, s_y, w, h, d_x, d_y );
517
518 // printf( "s_x %d s_y %d w %d h %d d_x %d d_y %d\n", s_x, s_y, w, h, d_x, d_y );
519
520 // printf( "rect %d %d %d %d\n", rect.x, rect.y, rect.width, rect.height );
521
522 m_updateRegion.Union( rect );
523 m_clearRegion.Union( rect );
524 }
525
526 XFreeGC( xdisplay, xgc );
527 }
528
529 // ---------------------------------------------------------------------------
530 // drag and drop
531 // ---------------------------------------------------------------------------
532
533 #if wxUSE_DRAG_AND_DROP
534
535 void wxWindowX11::SetDropTarget(wxDropTarget * WXUNUSED(pDropTarget))
536 {
537 // TODO
538 }
539
540 #endif
541
542 // Old style file-manager drag&drop
543 void wxWindowX11::DragAcceptFiles(bool WXUNUSED(accept))
544 {
545 // TODO
546 }
547
548 // ----------------------------------------------------------------------------
549 // tooltips
550 // ----------------------------------------------------------------------------
551
552 #if wxUSE_TOOLTIPS
553
554 void wxWindowX11::DoSetToolTip(wxToolTip * WXUNUSED(tooltip))
555 {
556 // TODO
557 }
558
559 #endif // wxUSE_TOOLTIPS
560
561 // ---------------------------------------------------------------------------
562 // moving and resizing
563 // ---------------------------------------------------------------------------
564
565 bool wxWindowX11::PreResize()
566 {
567 return TRUE;
568 }
569
570 // Get total size
571 void wxWindowX11::DoGetSize(int *x, int *y) const
572 {
573 Window xwindow = (Window) GetMainWindow();
574
575 wxCHECK_RET( xwindow, wxT("invalid window") );
576
577 XSync(wxGlobalDisplay(), False);
578 XWindowAttributes attr;
579 Status status = XGetWindowAttributes( wxGlobalDisplay(), xwindow, &attr );
580 wxASSERT(status);
581
582 if (status)
583 {
584 *x = attr.width /* + 2*m_borderSize */ ;
585 *y = attr.height /* + 2*m_borderSize */ ;
586 }
587 }
588
589 void wxWindowX11::DoGetPosition(int *x, int *y) const
590 {
591 Window window = (Window) m_mainWidget;
592 if (window)
593 {
594 XSync(wxGlobalDisplay(), False);
595 XWindowAttributes attr;
596 Status status = XGetWindowAttributes(wxGlobalDisplay(), window, & attr);
597 wxASSERT(status);
598
599 if (status)
600 {
601 *x = attr.x;
602 *y = attr.y;
603
604 // We may be faking the client origin. So a window that's really at (0, 30)
605 // may appear (to wxWin apps) to be at (0, 0).
606 if (GetParent())
607 {
608 wxPoint pt(GetParent()->GetClientAreaOrigin());
609 *x -= pt.x;
610 *y -= pt.y;
611 }
612 }
613 }
614 }
615
616 void wxWindowX11::DoScreenToClient(int *x, int *y) const
617 {
618 Display *display = wxGlobalDisplay();
619 Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display));
620 Window thisWindow = (Window) m_mainWidget;
621
622 Window childWindow;
623 int xx = *x;
624 int yy = *y;
625 XTranslateCoordinates(display, rootWindow, thisWindow, xx, yy, x, y, &childWindow);
626 }
627
628 void wxWindowX11::DoClientToScreen(int *x, int *y) const
629 {
630 Display *display = wxGlobalDisplay();
631 Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display));
632 Window thisWindow = (Window) m_mainWidget;
633
634 Window childWindow;
635 int xx = *x;
636 int yy = *y;
637 XTranslateCoordinates(display, thisWindow, rootWindow, xx, yy, x, y, &childWindow);
638 }
639
640
641 // Get size *available for subwindows* i.e. excluding menu bar etc.
642 void wxWindowX11::DoGetClientSize(int *x, int *y) const
643 {
644 Window window = (Window) m_mainWidget;
645
646 if (window)
647 {
648 XSync(wxGlobalDisplay(), False);
649 XWindowAttributes attr;
650 Status status = XGetWindowAttributes( wxGlobalDisplay(), window, &attr );
651 wxASSERT(status);
652
653 if (status)
654 {
655 *x = attr.width ;
656 *y = attr.height ;
657 }
658 }
659 }
660
661 void wxWindowX11::DoSetSize(int x, int y, int width, int height, int sizeFlags)
662 {
663 if (!GetMainWindow())
664 return;
665
666 XWindowChanges windowChanges;
667 windowChanges.x = 0;
668 windowChanges.y = 0;
669 windowChanges.width = 0;
670 windowChanges.height = 0;
671 windowChanges.stack_mode = 0;
672 int valueMask = 0;
673
674 if (x != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
675 {
676 int yy = 0;
677 AdjustForParentClientOrigin( x, yy, sizeFlags);
678 windowChanges.x = x;
679 valueMask |= CWX;
680 }
681 if (y != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
682 {
683 int xx = 0;
684 AdjustForParentClientOrigin( xx, y, sizeFlags);
685 windowChanges.y = y;
686 valueMask |= CWY;
687 }
688 if (width != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
689 {
690 windowChanges.width = width /* - m_borderSize*2 */;
691 if (windowChanges.width == 0)
692 windowChanges.width = 1;
693 valueMask |= CWWidth;
694 }
695 if (height != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
696 {
697 windowChanges.height = height /* -m_borderSize*2*/;
698 if (windowChanges.height == 0)
699 windowChanges.height = 1;
700 valueMask |= CWHeight;
701 }
702
703 XConfigureWindow(wxGlobalDisplay(), (Window) GetMainWindow(),
704 valueMask, & windowChanges);
705 XSync(wxGlobalDisplay(), False);
706 }
707
708 void wxWindowX11::DoSetClientSize(int width, int height)
709 {
710 if (!GetMainWindow())
711 return;
712
713 XWindowChanges windowChanges;
714 int valueMask = 0;
715
716 if (width != -1)
717 {
718 windowChanges.width = width ;
719 valueMask |= CWWidth;
720 }
721 if (height != -1)
722 {
723 windowChanges.height = height ;
724 valueMask |= CWHeight;
725 }
726 XConfigureWindow(wxGlobalDisplay(), (Window) GetMainWindow(),
727 valueMask, & windowChanges);
728 XSync(wxGlobalDisplay(), False);
729 }
730
731 // For implementation purposes - sometimes decorations make the client area
732 // smaller
733 wxPoint wxWindowX11::GetClientAreaOrigin() const
734 {
735 return wxPoint(0, 0);
736 }
737
738 // Makes an adjustment to the window position (for example, a frame that has
739 // a toolbar that it manages itself).
740 void wxWindowX11::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags)
741 {
742 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
743 {
744 wxPoint pt(GetParent()->GetClientAreaOrigin());
745 x += pt.x; y += pt.y;
746 }
747 }
748
749 void wxWindowX11::SetSizeHints(int minW, int minH, int maxW, int maxH, int incW, int incH)
750 {
751 m_minWidth = minW;
752 m_minHeight = minH;
753 m_maxWidth = maxW;
754 m_maxHeight = maxH;
755
756 XSizeHints sizeHints;
757 sizeHints.flags = 0;
758
759 if (minW > -1 && minH > -1)
760 {
761 sizeHints.flags |= PMinSize;
762 sizeHints.min_width = minW;
763 sizeHints.min_height = minH;
764 }
765 if (maxW > -1 && maxH > -1)
766 {
767 sizeHints.flags |= PMaxSize;
768 sizeHints.max_width = maxW;
769 sizeHints.max_height = maxH;
770 }
771 if (incW > -1 && incH > -1)
772 {
773 sizeHints.flags |= PResizeInc;
774 sizeHints.width_inc = incW;
775 sizeHints.height_inc = incH;
776 }
777
778 XSetWMNormalHints(wxGlobalDisplay(), (Window) GetMainWindow(), & sizeHints);
779 }
780
781 void wxWindowX11::DoMoveWindow(int x, int y, int width, int height)
782 {
783 DoSetSize(x, y, width, height);
784 }
785
786 // ---------------------------------------------------------------------------
787 // text metrics
788 // ---------------------------------------------------------------------------
789
790 int wxWindowX11::GetCharHeight() const
791 {
792 wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
793
794 WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, GetXDisplay());
795
796 int direction, ascent, descent;
797 XCharStruct overall;
798 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
799 &descent, &overall);
800
801 // return (overall.ascent + overall.descent);
802 return (ascent + descent);
803 }
804
805 int wxWindowX11::GetCharWidth() const
806 {
807 wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
808
809 WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, GetXDisplay());
810
811 int direction, ascent, descent;
812 XCharStruct overall;
813 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
814 &descent, &overall);
815
816 return overall.width;
817 }
818
819 void wxWindowX11::GetTextExtent(const wxString& string,
820 int *x, int *y,
821 int *descent, int *externalLeading,
822 const wxFont *theFont) const
823 {
824 wxFont fontToUse = m_font;
825 if (theFont) fontToUse = *theFont;
826
827 wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
828
829 WXFontStructPtr pFontStruct = fontToUse.GetFontStruct(1.0, GetXDisplay());
830
831 int direction, ascent, descent2;
832 XCharStruct overall;
833 int slen = string.Len();
834
835 #if 0
836 if (use16)
837 XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
838 &ascent, &descent2, &overall);
839 #endif
840
841 XTextExtents((XFontStruct*) pFontStruct, string.c_str(), slen,
842 &direction, &ascent, &descent2, &overall);
843
844 if ( x )
845 *x = (overall.width);
846 if ( y )
847 *y = (ascent + descent2);
848 if (descent)
849 *descent = descent2;
850 if (externalLeading)
851 *externalLeading = 0;
852
853 }
854
855 // ----------------------------------------------------------------------------
856 // painting
857 // ----------------------------------------------------------------------------
858
859 void wxWindowX11::Refresh(bool eraseBack, const wxRect *rect)
860 {
861 if (eraseBack)
862 {
863 if (rect)
864 {
865 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
866 m_clearRegion.Union( rect->x, rect->y, rect->width, rect->height );
867 }
868 else
869 {
870 int height,width;
871 GetSize( &width, &height );
872
873 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
874 m_clearRegion.Clear();
875 m_clearRegion.Union( 0, 0, width, height );
876 }
877 }
878
879 if (rect)
880 {
881 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
882 m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height );
883 }
884 else
885 {
886 int height,width;
887 GetSize( &width, &height );
888
889 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
890 m_updateRegion.Clear();
891 m_updateRegion.Union( 0, 0, width, height );
892 }
893 }
894
895 void wxWindowX11::Update()
896 {
897 if (!m_updateRegion.IsEmpty())
898 {
899 // Actually send erase and paint events.
900 X11SendPaintEvents();
901 }
902 }
903
904 void wxWindowX11::Clear()
905 {
906 wxClientDC dc((wxWindow*) this);
907 wxBrush brush(GetBackgroundColour(), wxSOLID);
908 dc.SetBackground(brush);
909 dc.Clear();
910 }
911
912 void wxWindowX11::X11SendPaintEvents()
913 {
914 m_clipPaintRegion = TRUE;
915
916 if (!m_clearRegion.IsEmpty())
917 {
918 wxWindowDC dc( (wxWindow*)this );
919 dc.SetClippingRegion( m_clearRegion );
920
921 wxEraseEvent erase_event( GetId(), &dc );
922 erase_event.SetEventObject( this );
923
924 if (!GetEventHandler()->ProcessEvent(erase_event))
925 {
926 printf( "Hallo!\n" );
927 Window xwindow = (Window) GetMainWindow();
928 Display *xdisplay = wxGlobalDisplay();
929 GC xgc = XCreateGC( xdisplay, xwindow, 0, NULL );
930 XSetFillStyle( xdisplay, xgc, FillSolid );
931 XSetForeground( xdisplay, xgc, m_backgroundColour.GetPixel() );
932 wxRegionIterator upd( m_clearRegion );
933 while (upd)
934 {
935 XFillRectangle( xdisplay, xwindow, xgc,
936 upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() );
937 upd ++;
938 }
939 }
940 m_clearRegion.Clear();
941 }
942
943 wxNcPaintEvent nc_paint_event( GetId() );
944 nc_paint_event.SetEventObject( this );
945 GetEventHandler()->ProcessEvent( nc_paint_event );
946
947 wxPaintEvent paint_event( GetId() );
948 paint_event.SetEventObject( this );
949 GetEventHandler()->ProcessEvent( paint_event );
950
951 m_updateRegion.Clear();
952
953 m_clipPaintRegion = FALSE;
954 }
955
956 // ----------------------------------------------------------------------------
957 // event handlers
958 // ----------------------------------------------------------------------------
959
960 // Responds to colour changes: passes event on to children.
961 void wxWindowX11::OnSysColourChanged(wxSysColourChangedEvent& event)
962 {
963 wxWindowList::Node *node = GetChildren().GetFirst();
964 while ( node )
965 {
966 // Only propagate to non-top-level windows
967 wxWindow *win = node->GetData();
968 if ( win->GetParent() )
969 {
970 wxSysColourChangedEvent event2;
971 event.m_eventObject = win;
972 win->GetEventHandler()->ProcessEvent(event2);
973 }
974
975 node = node->GetNext();
976 }
977 }
978
979 void wxWindowX11::OnInternalIdle()
980 {
981 // Update invalidated regions.
982 Update();
983
984 // This calls the UI-update mechanism (querying windows for
985 // menu/toolbar/control state information)
986 UpdateWindowUI();
987
988 // Set the input focus if couldn't do it before
989 if (m_needsInputFocus)
990 SetFocus();
991 }
992
993 // ----------------------------------------------------------------------------
994 // function which maintain the global hash table mapping Widgets to wxWindows
995 // ----------------------------------------------------------------------------
996
997 bool wxAddWindowToTable(Window w, wxWindow *win)
998 {
999 wxWindow *oldItem = NULL;
1000 if ((oldItem = (wxWindow *)wxWidgetHashTable->Get ((long) w)))
1001 {
1002 wxLogDebug("Widget table clash: new widget is %ld, %s",
1003 (long)w, win->GetClassInfo()->GetClassName());
1004 return FALSE;
1005 }
1006
1007 wxWidgetHashTable->Put((long) w, win);
1008
1009 wxLogTrace("widget", "XWindow 0x%08x <-> window %p (%s)",
1010 w, win, win->GetClassInfo()->GetClassName());
1011
1012 return TRUE;
1013 }
1014
1015 wxWindow *wxGetWindowFromTable(Window w)
1016 {
1017 return (wxWindow *)wxWidgetHashTable->Get((long) w);
1018 }
1019
1020 void wxDeleteWindowFromTable(Window w)
1021 {
1022 wxWidgetHashTable->Delete((long)w);
1023 }
1024
1025 // ----------------------------------------------------------------------------
1026 // add/remove window from the table
1027 // ----------------------------------------------------------------------------
1028
1029 // ----------------------------------------------------------------------------
1030 // X11-specific accessors
1031 // ----------------------------------------------------------------------------
1032
1033 // Get the underlying X window
1034 WXWindow wxWindowX11::GetXWindow() const
1035 {
1036 return GetMainWindow();
1037 }
1038
1039 // Get the underlying X display
1040 WXDisplay *wxWindowX11::GetXDisplay() const
1041 {
1042 return wxGetDisplay();
1043 }
1044
1045 WXWindow wxWindowX11::GetMainWindow() const
1046 {
1047 return m_mainWidget;
1048 }
1049
1050 // ----------------------------------------------------------------------------
1051 // TranslateXXXEvent() functions
1052 // ----------------------------------------------------------------------------
1053
1054 bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Window window, XEvent *xevent)
1055 {
1056 switch (xevent->xany.type)
1057 {
1058 case EnterNotify:
1059 case LeaveNotify:
1060 case ButtonPress:
1061 case ButtonRelease:
1062 case MotionNotify:
1063 {
1064 wxEventType eventType = wxEVT_NULL;
1065
1066 if (xevent->xany.type == EnterNotify)
1067 {
1068 //if (local_event.xcrossing.mode!=NotifyNormal)
1069 // return ; // Ignore grab events
1070 eventType = wxEVT_ENTER_WINDOW;
1071 // canvas->GetEventHandler()->OnSetFocus();
1072 }
1073 else if (xevent->xany.type == LeaveNotify)
1074 {
1075 //if (local_event.xcrossingr.mode!=NotifyNormal)
1076 // return ; // Ignore grab events
1077 eventType = wxEVT_LEAVE_WINDOW;
1078 // canvas->GetEventHandler()->OnKillFocus();
1079 }
1080 else if (xevent->xany.type == MotionNotify)
1081 {
1082 eventType = wxEVT_MOTION;
1083 }
1084 else if (xevent->xany.type == ButtonPress)
1085 {
1086 wxevent.SetTimestamp(xevent->xbutton.time);
1087 int button = 0;
1088 if (xevent->xbutton.button == Button1)
1089 {
1090 eventType = wxEVT_LEFT_DOWN;
1091 button = 1;
1092 }
1093 else if (xevent->xbutton.button == Button2)
1094 {
1095 eventType = wxEVT_MIDDLE_DOWN;
1096 button = 2;
1097 }
1098 else if (xevent->xbutton.button == Button3)
1099 {
1100 eventType = wxEVT_RIGHT_DOWN;
1101 button = 3;
1102 }
1103
1104 // check for a double click
1105 // TODO: where can we get this value from?
1106 //long dclickTime = XtGetMultiClickTime(wxGlobalDisplay());
1107 long dclickTime = 200;
1108 long ts = wxevent.GetTimestamp();
1109
1110 int buttonLast = win->GetLastClickedButton();
1111 long lastTS = win->GetLastClickTime();
1112 if ( buttonLast && buttonLast == button && (ts - lastTS) < dclickTime )
1113 {
1114 // I have a dclick
1115 win->SetLastClick(0, ts);
1116 if ( eventType == wxEVT_LEFT_DOWN )
1117 eventType = wxEVT_LEFT_DCLICK;
1118 else if ( eventType == wxEVT_MIDDLE_DOWN )
1119 eventType = wxEVT_MIDDLE_DCLICK;
1120 else if ( eventType == wxEVT_RIGHT_DOWN )
1121 eventType = wxEVT_RIGHT_DCLICK;
1122 }
1123 else
1124 {
1125 // not fast enough or different button
1126 win->SetLastClick(button, ts);
1127 }
1128 }
1129 else if (xevent->xany.type == ButtonRelease)
1130 {
1131 if (xevent->xbutton.button == Button1)
1132 {
1133 eventType = wxEVT_LEFT_UP;
1134 }
1135 else if (xevent->xbutton.button == Button2)
1136 {
1137 eventType = wxEVT_MIDDLE_UP;
1138 }
1139 else if (xevent->xbutton.button == Button3)
1140 {
1141 eventType = wxEVT_RIGHT_UP;
1142 }
1143 else return FALSE;
1144 }
1145 else
1146 {
1147 return FALSE;
1148 }
1149
1150 wxevent.SetEventType(eventType);
1151
1152 wxevent.m_x = xevent->xbutton.x;
1153 wxevent.m_y = xevent->xbutton.y;
1154
1155 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
1156 || (event_left_is_down (xevent)
1157 && (eventType != wxEVT_LEFT_UP)));
1158 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
1159 || (event_middle_is_down (xevent)
1160 && (eventType != wxEVT_MIDDLE_UP)));
1161 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
1162 || (event_right_is_down (xevent)
1163 && (eventType != wxEVT_RIGHT_UP)));
1164
1165 wxevent.m_shiftDown = xevent->xbutton.state & ShiftMask;
1166 wxevent.m_controlDown = xevent->xbutton.state & ControlMask;
1167 wxevent.m_altDown = xevent->xbutton.state & Mod3Mask;
1168 wxevent.m_metaDown = xevent->xbutton.state & Mod1Mask;
1169
1170 wxevent.SetId(win->GetId());
1171 wxevent.SetEventObject(win);
1172
1173 return TRUE;
1174 }
1175 }
1176 return FALSE;
1177 }
1178
1179 bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Window WXUNUSED(win), XEvent *xevent)
1180 {
1181 switch (xevent->xany.type)
1182 {
1183 case KeyPress:
1184 case KeyRelease:
1185 {
1186 char buf[20];
1187
1188 KeySym keySym;
1189 (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, NULL);
1190 int id = wxCharCodeXToWX (keySym);
1191
1192 if (xevent->xkey.state & ShiftMask)
1193 wxevent.m_shiftDown = TRUE;
1194 if (xevent->xkey.state & ControlMask)
1195 wxevent.m_controlDown = TRUE;
1196 if (xevent->xkey.state & Mod3Mask)
1197 wxevent.m_altDown = TRUE;
1198 if (xevent->xkey.state & Mod1Mask)
1199 wxevent.m_metaDown = TRUE;
1200 wxevent.SetEventObject(win);
1201 wxevent.m_keyCode = id;
1202 wxevent.SetTimestamp(xevent->xkey.time);
1203
1204 wxevent.m_x = xevent->xbutton.x;
1205 wxevent.m_y = xevent->xbutton.y;
1206
1207 if (id > -1)
1208 return TRUE;
1209 else
1210 return FALSE;
1211 break;
1212 }
1213 default:
1214 break;
1215 }
1216 return FALSE;
1217 }
1218
1219 // ----------------------------------------------------------------------------
1220 // Colour stuff
1221 // ----------------------------------------------------------------------------
1222
1223 bool wxWindowX11::SetBackgroundColour(const wxColour& col)
1224 {
1225 wxWindowBase::SetBackgroundColour(col);
1226
1227 Display *xdisplay = (Display*) wxGlobalDisplay();
1228 int xscreen = DefaultScreen( xdisplay );
1229 Colormap cm = DefaultColormap( xdisplay, xscreen );
1230
1231 m_backgroundColour.CalcPixel( (WXColormap) cm );
1232
1233 if (!GetMainWindow())
1234 return FALSE;
1235
1236 /*
1237 XSetWindowAttributes attrib;
1238 attrib.background_pixel = colour.GetPixel();
1239
1240 XChangeWindowAttributes(wxGlobalDisplay(),
1241 (Window) GetMainWindow(),
1242 CWBackPixel,
1243 & attrib);
1244 */
1245
1246 return TRUE;
1247 }
1248
1249 bool wxWindowX11::SetForegroundColour(const wxColour& col)
1250 {
1251 if ( !wxWindowBase::SetForegroundColour(col) )
1252 return FALSE;
1253
1254 return TRUE;
1255 }
1256
1257 // ----------------------------------------------------------------------------
1258 // global functions
1259 // ----------------------------------------------------------------------------
1260
1261 wxWindow *wxGetActiveWindow()
1262 {
1263 // TODO
1264 wxFAIL_MSG("Not implemented");
1265 return NULL;
1266 }
1267
1268 /* static */
1269 wxWindow *wxWindowBase::GetCapture()
1270 {
1271 return (wxWindow *)g_captureWindow;
1272 }
1273
1274
1275 // Find the wxWindow at the current mouse position, returning the mouse
1276 // position.
1277 wxWindow* wxFindWindowAtPointer(wxPoint& pt)
1278 {
1279 return wxFindWindowAtPoint(wxGetMousePosition());
1280 }
1281
1282 // Get the current mouse position.
1283 wxPoint wxGetMousePosition()
1284 {
1285 Display *display = wxGlobalDisplay();
1286 Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
1287 Window rootReturn, childReturn;
1288 int rootX, rootY, winX, winY;
1289 unsigned int maskReturn;
1290
1291 XQueryPointer (display,
1292 rootWindow,
1293 &rootReturn,
1294 &childReturn,
1295 &rootX, &rootY, &winX, &winY, &maskReturn);
1296 return wxPoint(rootX, rootY);
1297 }
1298
1299
1300 // ----------------------------------------------------------------------------
1301 // wxNoOptimize: switch off size optimization
1302 // ----------------------------------------------------------------------------
1303
1304 int wxNoOptimize::ms_count = 0;
1305