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