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); // Is this really a good idea?
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 Window xwindow = (Window) GetMainWindow();
664
665 wxCHECK_RET( xwindow, wxT("invalid window") );
666
667 XWindowAttributes attr;
668 Status status = XGetWindowAttributes( wxGlobalDisplay(), xwindow, &attr );
669 wxCHECK_RET( status, wxT("invalid window attributes") );
670
671 int new_x = attr.x;
672 int new_y = attr.y;
673 int new_w = attr.width;
674 int new_h = attr.height;
675
676
677 if (x != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
678 {
679 int yy = 0;
680 AdjustForParentClientOrigin( x, yy, sizeFlags);
681 new_x = x;
682 }
683 if (y != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
684 {
685 int xx = 0;
686 AdjustForParentClientOrigin( xx, y, sizeFlags);
687 new_y = y;
688 }
689 if (width != -1)
690 {
691 new_w = width;
692 if (new_w <= 0)
693 new_w = 20;
694 }
695 if (height != -1)
696 {
697 new_h = height;
698 if (new_h <= 0)
699 new_h = 20;
700 }
701
702 DoMoveWindow( new_x, new_y, new_w, new_h );
703 }
704
705 void wxWindowX11::DoSetClientSize(int width, int height)
706 {
707 Window xwindow = (Window) GetMainWindow();
708
709 wxCHECK_RET( xwindow, wxT("invalid window") );
710
711 XWindowAttributes attr;
712 Status status = XGetWindowAttributes( wxGlobalDisplay(), xwindow, &attr );
713 wxCHECK_RET( status, wxT("invalid window attributes") );
714
715 int new_x = attr.x;
716 int new_y = attr.y;
717 int new_w = attr.width;
718 int new_h = attr.height;
719
720 if (width != -1)
721 new_w = width;
722
723 if (height != -1)
724 new_h = height;
725
726 DoMoveWindow( new_x, new_y, new_w, new_h );
727 }
728
729 // For implementation purposes - sometimes decorations make the client area
730 // smaller
731 wxPoint wxWindowX11::GetClientAreaOrigin() const
732 {
733 return wxPoint(0, 0);
734 }
735
736 // Makes an adjustment to the window position (for example, a frame that has
737 // a toolbar that it manages itself).
738 void wxWindowX11::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags)
739 {
740 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
741 {
742 wxPoint pt(GetParent()->GetClientAreaOrigin());
743 x += pt.x; y += pt.y;
744 }
745 }
746
747 void wxWindowX11::SetSizeHints(int minW, int minH, int maxW, int maxH, int incW, int incH)
748 {
749 m_minWidth = minW;
750 m_minHeight = minH;
751 m_maxWidth = maxW;
752 m_maxHeight = maxH;
753
754 XSizeHints sizeHints;
755 sizeHints.flags = 0;
756
757 if (minW > -1 && minH > -1)
758 {
759 sizeHints.flags |= PMinSize;
760 sizeHints.min_width = minW;
761 sizeHints.min_height = minH;
762 }
763 if (maxW > -1 && maxH > -1)
764 {
765 sizeHints.flags |= PMaxSize;
766 sizeHints.max_width = maxW;
767 sizeHints.max_height = maxH;
768 }
769 if (incW > -1 && incH > -1)
770 {
771 sizeHints.flags |= PResizeInc;
772 sizeHints.width_inc = incW;
773 sizeHints.height_inc = incH;
774 }
775
776 XSetWMNormalHints(wxGlobalDisplay(), (Window) GetMainWindow(), & sizeHints);
777 }
778
779 void wxWindowX11::DoMoveWindow(int x, int y, int width, int height)
780 {
781 Window xwindow = (Window) GetMainWindow();
782
783 wxCHECK_RET( xwindow, wxT("invalid window") );
784
785 XWindowChanges windowChanges;
786 windowChanges.x = x;
787 windowChanges.y = y;
788 windowChanges.width = width;
789 windowChanges.height = height;
790 windowChanges.stack_mode = 0;
791 int valueMask = CWX | CWY | CWWidth | CWHeight;
792
793 XConfigureWindow( wxGlobalDisplay(), xwindow, valueMask, &windowChanges );
794 }
795
796 // ---------------------------------------------------------------------------
797 // text metrics
798 // ---------------------------------------------------------------------------
799
800 int wxWindowX11::GetCharHeight() const
801 {
802 wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
803
804 WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, GetXDisplay());
805
806 int direction, ascent, descent;
807 XCharStruct overall;
808 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
809 &descent, &overall);
810
811 // return (overall.ascent + overall.descent);
812 return (ascent + descent);
813 }
814
815 int wxWindowX11::GetCharWidth() const
816 {
817 wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
818
819 WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, GetXDisplay());
820
821 int direction, ascent, descent;
822 XCharStruct overall;
823 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
824 &descent, &overall);
825
826 return overall.width;
827 }
828
829 void wxWindowX11::GetTextExtent(const wxString& string,
830 int *x, int *y,
831 int *descent, int *externalLeading,
832 const wxFont *theFont) const
833 {
834 wxFont fontToUse = m_font;
835 if (theFont) fontToUse = *theFont;
836
837 wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
838
839 WXFontStructPtr pFontStruct = fontToUse.GetFontStruct(1.0, GetXDisplay());
840
841 int direction, ascent, descent2;
842 XCharStruct overall;
843 int slen = string.Len();
844
845 #if 0
846 if (use16)
847 XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
848 &ascent, &descent2, &overall);
849 #endif
850
851 XTextExtents((XFontStruct*) pFontStruct, string.c_str(), slen,
852 &direction, &ascent, &descent2, &overall);
853
854 if ( x )
855 *x = (overall.width);
856 if ( y )
857 *y = (ascent + descent2);
858 if (descent)
859 *descent = descent2;
860 if (externalLeading)
861 *externalLeading = 0;
862
863 }
864
865 // ----------------------------------------------------------------------------
866 // painting
867 // ----------------------------------------------------------------------------
868
869 void wxWindowX11::Refresh(bool eraseBack, const wxRect *rect)
870 {
871 if (eraseBack)
872 {
873 if (rect)
874 {
875 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
876 m_clearRegion.Union( rect->x, rect->y, rect->width, rect->height );
877 }
878 else
879 {
880 int height,width;
881 GetSize( &width, &height );
882
883 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
884 m_clearRegion.Clear();
885 m_clearRegion.Union( 0, 0, width, height );
886 }
887 }
888
889 if (rect)
890 {
891 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
892 m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height );
893 }
894 else
895 {
896 int height,width;
897 GetSize( &width, &height );
898
899 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
900 m_updateRegion.Clear();
901 m_updateRegion.Union( 0, 0, width, height );
902 }
903 }
904
905 void wxWindowX11::Update()
906 {
907 if (!m_updateRegion.IsEmpty())
908 {
909 // Actually send erase and paint events.
910 X11SendPaintEvents();
911 }
912 }
913
914 void wxWindowX11::Clear()
915 {
916 wxClientDC dc((wxWindow*) this);
917 wxBrush brush(GetBackgroundColour(), wxSOLID);
918 dc.SetBackground(brush);
919 dc.Clear();
920 }
921
922 void wxWindowX11::X11SendPaintEvents()
923 {
924 m_clipPaintRegion = TRUE;
925
926 if (!m_clearRegion.IsEmpty())
927 {
928 wxWindowDC dc( (wxWindow*)this );
929 dc.SetClippingRegion( m_clearRegion );
930
931 wxEraseEvent erase_event( GetId(), &dc );
932 erase_event.SetEventObject( this );
933
934 if (!GetEventHandler()->ProcessEvent(erase_event))
935 {
936 Window xwindow = (Window) GetMainWindow();
937 Display *xdisplay = wxGlobalDisplay();
938 GC xgc = XCreateGC( xdisplay, xwindow, 0, NULL );
939 XSetFillStyle( xdisplay, xgc, FillSolid );
940 XSetForeground( xdisplay, xgc, m_backgroundColour.GetPixel() );
941 wxRegionIterator upd( m_clearRegion );
942 while (upd)
943 {
944 XFillRectangle( xdisplay, xwindow, xgc,
945 upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() );
946 upd ++;
947 }
948 XFreeGC( xdisplay, xgc );
949 }
950 m_clearRegion.Clear();
951 }
952
953 wxNcPaintEvent nc_paint_event( GetId() );
954 nc_paint_event.SetEventObject( this );
955 GetEventHandler()->ProcessEvent( nc_paint_event );
956
957 wxPaintEvent paint_event( GetId() );
958 paint_event.SetEventObject( this );
959 GetEventHandler()->ProcessEvent( paint_event );
960
961 m_updateRegion.Clear();
962
963 m_clipPaintRegion = FALSE;
964 }
965
966 // ----------------------------------------------------------------------------
967 // event handlers
968 // ----------------------------------------------------------------------------
969
970 // Responds to colour changes: passes event on to children.
971 void wxWindowX11::OnSysColourChanged(wxSysColourChangedEvent& event)
972 {
973 wxWindowList::Node *node = GetChildren().GetFirst();
974 while ( node )
975 {
976 // Only propagate to non-top-level windows
977 wxWindow *win = node->GetData();
978 if ( win->GetParent() )
979 {
980 wxSysColourChangedEvent event2;
981 event.m_eventObject = win;
982 win->GetEventHandler()->ProcessEvent(event2);
983 }
984
985 node = node->GetNext();
986 }
987 }
988
989 void wxWindowX11::OnInternalIdle()
990 {
991 // Update invalidated regions.
992 Update();
993
994 // This calls the UI-update mechanism (querying windows for
995 // menu/toolbar/control state information)
996 UpdateWindowUI();
997
998 // Set the input focus if couldn't do it before
999 if (m_needsInputFocus)
1000 SetFocus();
1001 }
1002
1003 // ----------------------------------------------------------------------------
1004 // function which maintain the global hash table mapping Widgets to wxWindows
1005 // ----------------------------------------------------------------------------
1006
1007 bool wxAddWindowToTable(Window w, wxWindow *win)
1008 {
1009 wxWindow *oldItem = NULL;
1010 if ((oldItem = (wxWindow *)wxWidgetHashTable->Get ((long) w)))
1011 {
1012 wxLogDebug("Widget table clash: new widget is %ld, %s",
1013 (long)w, win->GetClassInfo()->GetClassName());
1014 return FALSE;
1015 }
1016
1017 wxWidgetHashTable->Put((long) w, win);
1018
1019 wxLogTrace("widget", "XWindow 0x%08x <-> window %p (%s)",
1020 w, win, win->GetClassInfo()->GetClassName());
1021
1022 return TRUE;
1023 }
1024
1025 wxWindow *wxGetWindowFromTable(Window w)
1026 {
1027 return (wxWindow *)wxWidgetHashTable->Get((long) w);
1028 }
1029
1030 void wxDeleteWindowFromTable(Window w)
1031 {
1032 wxWidgetHashTable->Delete((long)w);
1033 }
1034
1035 // ----------------------------------------------------------------------------
1036 // add/remove window from the table
1037 // ----------------------------------------------------------------------------
1038
1039 // ----------------------------------------------------------------------------
1040 // X11-specific accessors
1041 // ----------------------------------------------------------------------------
1042
1043 // Get the underlying X window
1044 WXWindow wxWindowX11::GetXWindow() const
1045 {
1046 return GetMainWindow();
1047 }
1048
1049 // Get the underlying X display
1050 WXDisplay *wxWindowX11::GetXDisplay() const
1051 {
1052 return wxGetDisplay();
1053 }
1054
1055 WXWindow wxWindowX11::GetMainWindow() const
1056 {
1057 return m_mainWidget;
1058 }
1059
1060 // ----------------------------------------------------------------------------
1061 // TranslateXXXEvent() functions
1062 // ----------------------------------------------------------------------------
1063
1064 bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Window window, XEvent *xevent)
1065 {
1066 switch (xevent->xany.type)
1067 {
1068 case EnterNotify:
1069 case LeaveNotify:
1070 case ButtonPress:
1071 case ButtonRelease:
1072 case MotionNotify:
1073 {
1074 wxEventType eventType = wxEVT_NULL;
1075
1076 if (xevent->xany.type == EnterNotify)
1077 {
1078 //if (local_event.xcrossing.mode!=NotifyNormal)
1079 // return ; // Ignore grab events
1080 eventType = wxEVT_ENTER_WINDOW;
1081 // canvas->GetEventHandler()->OnSetFocus();
1082 }
1083 else if (xevent->xany.type == LeaveNotify)
1084 {
1085 //if (local_event.xcrossingr.mode!=NotifyNormal)
1086 // return ; // Ignore grab events
1087 eventType = wxEVT_LEAVE_WINDOW;
1088 // canvas->GetEventHandler()->OnKillFocus();
1089 }
1090 else if (xevent->xany.type == MotionNotify)
1091 {
1092 eventType = wxEVT_MOTION;
1093 }
1094 else if (xevent->xany.type == ButtonPress)
1095 {
1096 wxevent.SetTimestamp(xevent->xbutton.time);
1097 int button = 0;
1098 if (xevent->xbutton.button == Button1)
1099 {
1100 eventType = wxEVT_LEFT_DOWN;
1101 button = 1;
1102 }
1103 else if (xevent->xbutton.button == Button2)
1104 {
1105 eventType = wxEVT_MIDDLE_DOWN;
1106 button = 2;
1107 }
1108 else if (xevent->xbutton.button == Button3)
1109 {
1110 eventType = wxEVT_RIGHT_DOWN;
1111 button = 3;
1112 }
1113
1114 // check for a double click
1115 // TODO: where can we get this value from?
1116 //long dclickTime = XtGetMultiClickTime(wxGlobalDisplay());
1117 long dclickTime = 200;
1118 long ts = wxevent.GetTimestamp();
1119
1120 int buttonLast = win->GetLastClickedButton();
1121 long lastTS = win->GetLastClickTime();
1122 if ( buttonLast && buttonLast == button && (ts - lastTS) < dclickTime )
1123 {
1124 // I have a dclick
1125 win->SetLastClick(0, ts);
1126 if ( eventType == wxEVT_LEFT_DOWN )
1127 eventType = wxEVT_LEFT_DCLICK;
1128 else if ( eventType == wxEVT_MIDDLE_DOWN )
1129 eventType = wxEVT_MIDDLE_DCLICK;
1130 else if ( eventType == wxEVT_RIGHT_DOWN )
1131 eventType = wxEVT_RIGHT_DCLICK;
1132 }
1133 else
1134 {
1135 // not fast enough or different button
1136 win->SetLastClick(button, ts);
1137 }
1138 }
1139 else if (xevent->xany.type == ButtonRelease)
1140 {
1141 if (xevent->xbutton.button == Button1)
1142 {
1143 eventType = wxEVT_LEFT_UP;
1144 }
1145 else if (xevent->xbutton.button == Button2)
1146 {
1147 eventType = wxEVT_MIDDLE_UP;
1148 }
1149 else if (xevent->xbutton.button == Button3)
1150 {
1151 eventType = wxEVT_RIGHT_UP;
1152 }
1153 else return FALSE;
1154 }
1155 else
1156 {
1157 return FALSE;
1158 }
1159
1160 wxevent.SetEventType(eventType);
1161
1162 wxevent.m_x = xevent->xbutton.x;
1163 wxevent.m_y = xevent->xbutton.y;
1164
1165 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
1166 || (event_left_is_down (xevent)
1167 && (eventType != wxEVT_LEFT_UP)));
1168 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
1169 || (event_middle_is_down (xevent)
1170 && (eventType != wxEVT_MIDDLE_UP)));
1171 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
1172 || (event_right_is_down (xevent)
1173 && (eventType != wxEVT_RIGHT_UP)));
1174
1175 wxevent.m_shiftDown = xevent->xbutton.state & ShiftMask;
1176 wxevent.m_controlDown = xevent->xbutton.state & ControlMask;
1177 wxevent.m_altDown = xevent->xbutton.state & Mod3Mask;
1178 wxevent.m_metaDown = xevent->xbutton.state & Mod1Mask;
1179
1180 wxevent.SetId(win->GetId());
1181 wxevent.SetEventObject(win);
1182
1183 return TRUE;
1184 }
1185 }
1186 return FALSE;
1187 }
1188
1189 bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Window WXUNUSED(win), XEvent *xevent)
1190 {
1191 switch (xevent->xany.type)
1192 {
1193 case KeyPress:
1194 case KeyRelease:
1195 {
1196 char buf[20];
1197
1198 KeySym keySym;
1199 (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, NULL);
1200 int id = wxCharCodeXToWX (keySym);
1201
1202 if (xevent->xkey.state & ShiftMask)
1203 wxevent.m_shiftDown = TRUE;
1204 if (xevent->xkey.state & ControlMask)
1205 wxevent.m_controlDown = TRUE;
1206 if (xevent->xkey.state & Mod3Mask)
1207 wxevent.m_altDown = TRUE;
1208 if (xevent->xkey.state & Mod1Mask)
1209 wxevent.m_metaDown = TRUE;
1210 wxevent.SetEventObject(win);
1211 wxevent.m_keyCode = id;
1212 wxevent.SetTimestamp(xevent->xkey.time);
1213
1214 wxevent.m_x = xevent->xbutton.x;
1215 wxevent.m_y = xevent->xbutton.y;
1216
1217 if (id > -1)
1218 return TRUE;
1219 else
1220 return FALSE;
1221 break;
1222 }
1223 default:
1224 break;
1225 }
1226 return FALSE;
1227 }
1228
1229 // ----------------------------------------------------------------------------
1230 // Colour stuff
1231 // ----------------------------------------------------------------------------
1232
1233 bool wxWindowX11::SetBackgroundColour(const wxColour& col)
1234 {
1235 wxWindowBase::SetBackgroundColour(col);
1236
1237 Display *xdisplay = (Display*) wxGlobalDisplay();
1238 int xscreen = DefaultScreen( xdisplay );
1239 Colormap cm = DefaultColormap( xdisplay, xscreen );
1240
1241 m_backgroundColour.CalcPixel( (WXColormap) cm );
1242
1243 if (!GetMainWindow())
1244 return FALSE;
1245
1246 /*
1247 XSetWindowAttributes attrib;
1248 attrib.background_pixel = colour.GetPixel();
1249
1250 XChangeWindowAttributes(wxGlobalDisplay(),
1251 (Window) GetMainWindow(),
1252 CWBackPixel,
1253 & attrib);
1254 */
1255
1256 return TRUE;
1257 }
1258
1259 bool wxWindowX11::SetForegroundColour(const wxColour& col)
1260 {
1261 if ( !wxWindowBase::SetForegroundColour(col) )
1262 return FALSE;
1263
1264 return TRUE;
1265 }
1266
1267 // ----------------------------------------------------------------------------
1268 // global functions
1269 // ----------------------------------------------------------------------------
1270
1271 wxWindow *wxGetActiveWindow()
1272 {
1273 // TODO
1274 wxFAIL_MSG("Not implemented");
1275 return NULL;
1276 }
1277
1278 /* static */
1279 wxWindow *wxWindowBase::GetCapture()
1280 {
1281 return (wxWindow *)g_captureWindow;
1282 }
1283
1284
1285 // Find the wxWindow at the current mouse position, returning the mouse
1286 // position.
1287 wxWindow* wxFindWindowAtPointer(wxPoint& pt)
1288 {
1289 return wxFindWindowAtPoint(wxGetMousePosition());
1290 }
1291
1292 // Get the current mouse position.
1293 wxPoint wxGetMousePosition()
1294 {
1295 Display *display = wxGlobalDisplay();
1296 Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
1297 Window rootReturn, childReturn;
1298 int rootX, rootY, winX, winY;
1299 unsigned int maskReturn;
1300
1301 XQueryPointer (display,
1302 rootWindow,
1303 &rootReturn,
1304 &childReturn,
1305 &rootX, &rootY, &winX, &winY, &maskReturn);
1306 return wxPoint(rootX, rootY);
1307 }
1308
1309
1310 // ----------------------------------------------------------------------------
1311 // wxNoOptimize: switch off size optimization
1312 // ----------------------------------------------------------------------------
1313
1314 int wxNoOptimize::ms_count = 0;
1315