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