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