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