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