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