Include order is wxprec.h=>defs.h=>platform.h=>setup.h so remove explicit setup.h...
[wxWidgets.git] / src / x11 / window.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/x11/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 // for compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #if defined(__BORLANDC__)
16 #pragma hdrstop
17 #endif
18
19 // ============================================================================
20 // declarations
21 // ============================================================================
22
23 // ----------------------------------------------------------------------------
24 // headers
25 // ----------------------------------------------------------------------------
26
27 #include "wx/menu.h"
28 #include "wx/dc.h"
29 #include "wx/dcclient.h"
30 #include "wx/utils.h"
31 #include "wx/app.h"
32 #include "wx/panel.h"
33 #include "wx/layout.h"
34 #include "wx/dialog.h"
35 #include "wx/listbox.h"
36 #include "wx/button.h"
37 #include "wx/settings.h"
38 #include "wx/msgdlg.h"
39 #include "wx/frame.h"
40 #include "wx/scrolwin.h"
41 #include "wx/scrolbar.h"
42 #include "wx/module.h"
43 #include "wx/menuitem.h"
44 #include "wx/log.h"
45 #include "wx/fontutil.h"
46 #include "wx/univ/renderer.h"
47 #include "wx/hash.h"
48
49 #if wxUSE_DRAG_AND_DROP
50 #include "wx/dnd.h"
51 #endif
52
53 #include "wx/x11/private.h"
54 #include "X11/Xutil.h"
55
56 #if wxUSE_NANOX
57 // For wxGetLocalTime, used by XButtonEventGetTime
58 #include "wx/timer.h"
59 #endif
60
61 #include <string.h>
62
63 // ----------------------------------------------------------------------------
64 // global variables for this module
65 // ----------------------------------------------------------------------------
66
67 static wxWindow* g_captureWindow = NULL;
68 static GC g_eraseGC;
69
70 // ----------------------------------------------------------------------------
71 // macros
72 // ----------------------------------------------------------------------------
73
74 #define event_left_is_down(x) ((x)->xbutton.state & Button1Mask)
75 #define event_middle_is_down(x) ((x)->xbutton.state & Button2Mask)
76 #define event_right_is_down(x) ((x)->xbutton.state & Button3Mask)
77
78 // ----------------------------------------------------------------------------
79 // event tables
80 // ----------------------------------------------------------------------------
81
82 IMPLEMENT_ABSTRACT_CLASS(wxWindowX11, wxWindowBase)
83
84 BEGIN_EVENT_TABLE(wxWindowX11, wxWindowBase)
85 EVT_SYS_COLOUR_CHANGED(wxWindowX11::OnSysColourChanged)
86 END_EVENT_TABLE()
87
88 // ============================================================================
89 // implementation
90 // ============================================================================
91
92 // ----------------------------------------------------------------------------
93 // helper functions
94 // ----------------------------------------------------------------------------
95
96 // ----------------------------------------------------------------------------
97 // constructors
98 // ----------------------------------------------------------------------------
99
100 void wxWindowX11::Init()
101 {
102 // X11-specific
103 m_mainWindow = (WXWindow) 0;
104 m_clientWindow = (WXWindow) 0;
105 m_insertIntoMain = false;
106 m_updateNcArea = false;
107
108 m_winCaptured = false;
109 m_needsInputFocus = false;
110 m_isShown = true;
111 m_lastTS = 0;
112 m_lastButton = 0;
113 }
114
115 // real construction (Init() must have been called before!)
116 bool wxWindowX11::Create(wxWindow *parent, wxWindowID id,
117 const wxPoint& pos,
118 const wxSize& size,
119 long style,
120 const wxString& name)
121 {
122 wxCHECK_MSG( parent, false, wxT("can't create wxWindow without parent") );
123
124 CreateBase(parent, id, pos, size, style, wxDefaultValidator, name);
125
126 parent->AddChild(this);
127
128 Display *xdisplay = (Display*) wxGlobalDisplay();
129 int xscreen = DefaultScreen( xdisplay );
130 Visual *xvisual = DefaultVisual( xdisplay, xscreen );
131 Colormap cm = DefaultColormap( xdisplay, xscreen );
132
133 m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
134 m_backgroundColour.CalcPixel( (WXColormap) cm );
135
136 m_foregroundColour = *wxBLACK;
137 m_foregroundColour.CalcPixel( (WXColormap) cm );
138
139 Window xparent = (Window) parent->GetClientAreaWindow();
140
141 // Add window's own scrollbars to main window, not to client window
142 if (parent->GetInsertIntoMain())
143 {
144 // wxLogDebug( "Inserted into main: %s", GetName().c_str() );
145 xparent = (Window) parent->GetMainWindow();
146 }
147
148 // Size (not including the border) must be nonzero (or a Value error results)!
149 // Note: The Xlib manual doesn't mention this restriction of XCreateWindow.
150 wxSize size2(size);
151 if (size2.x <= 0)
152 size2.x = 20;
153 if (size2.y <= 0)
154 size2.y = 20;
155
156 wxPoint pos2(pos);
157 if (pos2.x == wxDefaultCoord)
158 pos2.x = 0;
159 if (pos2.y == wxDefaultCoord)
160 pos2.y = 0;
161
162 #if wxUSE_TWO_WINDOWS
163 bool need_two_windows =
164 ((( wxSUNKEN_BORDER | wxRAISED_BORDER | wxSIMPLE_BORDER | wxHSCROLL | wxVSCROLL ) & m_windowStyle) != 0);
165 #else
166 bool need_two_windows = false;
167 #endif
168
169 #if wxUSE_NANOX
170 long xattributes = 0;
171 #else
172 XSetWindowAttributes xattributes;
173 long xattributes_mask = 0;
174
175 xattributes_mask |= CWBackPixel;
176 xattributes.background_pixel = m_backgroundColour.GetPixel();
177
178 xattributes_mask |= CWBorderPixel;
179 xattributes.border_pixel = BlackPixel( xdisplay, xscreen );
180
181 xattributes_mask |= CWEventMask;
182 #endif
183
184 if (need_two_windows)
185 {
186 #if wxUSE_NANOX
187 long backColor, foreColor;
188 backColor = GR_RGB(m_backgroundColour.Red(), m_backgroundColour.Green(), m_backgroundColour.Blue());
189 foreColor = GR_RGB(m_foregroundColour.Red(), m_foregroundColour.Green(), m_foregroundColour.Blue());
190
191 Window xwindow = XCreateWindowWithColor( xdisplay, xparent, pos2.x, pos2.y, size2.x, size2.y,
192 0, 0, InputOutput, xvisual, backColor, foreColor);
193 XSelectInput( xdisplay, xwindow,
194 GR_EVENT_MASK_CLOSE_REQ | ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
195 ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask |
196 KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask |
197 PropertyChangeMask );
198
199 #else
200 // Normal X11
201 xattributes.event_mask =
202 ExposureMask | StructureNotifyMask | ColormapChangeMask;
203
204 Window xwindow = XCreateWindow( xdisplay, xparent, pos2.x, pos2.y, size2.x, size2.y,
205 0, DefaultDepth(xdisplay,xscreen), InputOutput, xvisual, xattributes_mask, &xattributes );
206
207 #endif
208
209 XSetWindowBackgroundPixmap( xdisplay, xwindow, None );
210
211 m_mainWindow = (WXWindow) xwindow;
212 wxAddWindowToTable( xwindow, (wxWindow*) this );
213
214 XMapWindow( xdisplay, xwindow );
215
216 #if !wxUSE_NANOX
217 xattributes.event_mask =
218 ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
219 ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask |
220 KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask |
221 PropertyChangeMask | VisibilityChangeMask ;
222
223 if (!HasFlag( wxFULL_REPAINT_ON_RESIZE ))
224 {
225 xattributes_mask |= CWBitGravity;
226 xattributes.bit_gravity = StaticGravity;
227 }
228 #endif
229
230 if (HasFlag( wxSUNKEN_BORDER) || HasFlag( wxRAISED_BORDER))
231 {
232 pos2.x = 2;
233 pos2.y = 2;
234 size2.x -= 4;
235 size2.y -= 4;
236 }
237 else if (HasFlag( wxSIMPLE_BORDER ))
238 {
239 pos2.x = 1;
240 pos2.y = 1;
241 size2.x -= 2;
242 size2.y -= 2;
243 }
244 else
245 {
246 pos2.x = 0;
247 pos2.y = 0;
248 }
249
250 // Make again sure the size is nonzero.
251 if (size2.x <= 0)
252 size2.x = 1;
253 if (size2.y <= 0)
254 size2.y = 1;
255
256 #if wxUSE_NANOX
257 backColor = GR_RGB(m_backgroundColour.Red(), m_backgroundColour.Green(), m_backgroundColour.Blue());
258 foreColor = GR_RGB(m_foregroundColour.Red(), m_foregroundColour.Green(), m_foregroundColour.Blue());
259
260 xwindow = XCreateWindowWithColor( xdisplay, xwindow, pos2.x, pos2.y, size2.x, size2.y,
261 0, 0, InputOutput, xvisual, backColor, foreColor);
262 XSelectInput( xdisplay, xwindow,
263 GR_EVENT_MASK_CLOSE_REQ | ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
264 ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask |
265 KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask |
266 PropertyChangeMask );
267
268 #else
269 xwindow = XCreateWindow( xdisplay, xwindow, pos2.x, pos2.y, size2.x, size2.y,
270 0, DefaultDepth(xdisplay,xscreen), InputOutput, xvisual, xattributes_mask, &xattributes );
271 #endif
272
273 XSetWindowBackgroundPixmap( xdisplay, xwindow, None );
274
275 m_clientWindow = (WXWindow) xwindow;
276 wxAddClientWindowToTable( xwindow, (wxWindow*) this );
277
278 XMapWindow( xdisplay, xwindow );
279 }
280 else
281 {
282 // wxLogDebug( "No two windows needed %s", GetName().c_str() );
283 #if wxUSE_NANOX
284 long backColor, foreColor;
285 backColor = GR_RGB(m_backgroundColour.Red(), m_backgroundColour.Green(), m_backgroundColour.Blue());
286 foreColor = GR_RGB(m_foregroundColour.Red(), m_foregroundColour.Green(), m_foregroundColour.Blue());
287
288 Window xwindow = XCreateWindowWithColor( xdisplay, xparent, pos2.x, pos2.y, size2.x, size2.y,
289 0, 0, InputOutput, xvisual, backColor, foreColor);
290 XSelectInput( xdisplay, xwindow,
291 GR_EVENT_MASK_CLOSE_REQ | ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
292 ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask |
293 KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask |
294 PropertyChangeMask );
295
296 #else
297 xattributes.event_mask =
298 ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
299 ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask |
300 KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask |
301 PropertyChangeMask | VisibilityChangeMask ;
302
303 if (!HasFlag( wxFULL_REPAINT_ON_RESIZE ))
304 {
305 xattributes_mask |= CWBitGravity;
306 xattributes.bit_gravity = NorthWestGravity;
307 }
308
309 Window xwindow = XCreateWindow( xdisplay, xparent, pos2.x, pos2.y, size2.x, size2.y,
310 0, DefaultDepth(xdisplay,xscreen), InputOutput, xvisual, xattributes_mask, &xattributes );
311 #endif
312
313 XSetWindowBackgroundPixmap( xdisplay, xwindow, None );
314
315 m_mainWindow = (WXWindow) xwindow;
316 m_clientWindow = m_mainWindow;
317 wxAddWindowToTable( xwindow, (wxWindow*) this );
318
319 XMapWindow( xdisplay, xwindow );
320 }
321
322 // Is a subwindow, so map immediately
323 m_isShown = true;
324
325 // Without this, the cursor may not be restored properly (e.g. in splitter
326 // sample).
327 SetCursor(*wxSTANDARD_CURSOR);
328 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
329
330 // Don't call this, it can have nasty repercussions for composite controls,
331 // for example
332 // SetSize(pos.x, pos.y, size.x, size.y);
333
334 return true;
335 }
336
337 // Destructor
338 wxWindowX11::~wxWindowX11()
339 {
340 SendDestroyEvent();
341
342 if (g_captureWindow == this)
343 g_captureWindow = NULL;
344
345 m_isBeingDeleted = true;
346
347 DestroyChildren();
348
349 if (m_clientWindow != m_mainWindow)
350 {
351 // Destroy the cleint window
352 Window xwindow = (Window) m_clientWindow;
353 wxDeleteClientWindowFromTable( xwindow );
354 XDestroyWindow( wxGlobalDisplay(), xwindow );
355 m_clientWindow = NULL;
356 }
357
358 // Destroy the window
359 Window xwindow = (Window) m_mainWindow;
360 wxDeleteWindowFromTable( xwindow );
361 XDestroyWindow( wxGlobalDisplay(), xwindow );
362 m_mainWindow = NULL;
363 }
364
365 // ---------------------------------------------------------------------------
366 // basic operations
367 // ---------------------------------------------------------------------------
368
369 void wxWindowX11::SetFocus()
370 {
371 Window xwindow = (Window) m_clientWindow;
372
373 wxCHECK_RET( xwindow, wxT("invalid window") );
374
375 // Don't assert; we might be trying to set the focus for a panel
376 // with only static controls, so the panel returns false from AcceptsFocus.
377 // The app should be not be expected to deal with this.
378 if (!AcceptsFocus())
379 return;
380
381 #if 0
382 if (GetName() == "scrollBar")
383 {
384 char *crash = NULL;
385 *crash = 0;
386 }
387 #endif
388
389 if (wxWindowIsVisible(xwindow))
390 {
391 wxLogTrace( _T("focus"), _T("wxWindowX11::SetFocus: %s"), GetClassInfo()->GetClassName());
392 // XSetInputFocus( wxGlobalDisplay(), xwindow, RevertToParent, CurrentTime );
393 XSetInputFocus( wxGlobalDisplay(), xwindow, RevertToNone, CurrentTime );
394 m_needsInputFocus = false;
395 }
396 else
397 {
398 m_needsInputFocus = true;
399 }
400 }
401
402 // Get the window with the focus
403 wxWindow *wxWindowBase::DoFindFocus()
404 {
405 Window xfocus = (Window) 0;
406 int revert = 0;
407
408 XGetInputFocus( wxGlobalDisplay(), &xfocus, &revert);
409 if (xfocus)
410 {
411 wxWindow *win = wxGetWindowFromTable( xfocus );
412 if (!win)
413 {
414 win = wxGetClientWindowFromTable( xfocus );
415 }
416
417 return win;
418 }
419
420 return NULL;
421 }
422
423 // Enabling/disabling handled by event loop, and not sending events
424 // if disabled.
425 bool wxWindowX11::Enable(bool enable)
426 {
427 if ( !wxWindowBase::Enable(enable) )
428 return false;
429
430 return true;
431 }
432
433 bool wxWindowX11::Show(bool show)
434 {
435 wxWindowBase::Show(show);
436
437 Window xwindow = (Window) m_mainWindow;
438 Display *xdisp = wxGlobalDisplay();
439 if (show)
440 {
441 // wxLogDebug( "Mapping window of type %s", GetName().c_str() );
442 XMapWindow(xdisp, xwindow);
443 }
444 else
445 {
446 // wxLogDebug( "Unmapping window of type %s", GetName().c_str() );
447 XUnmapWindow(xdisp, xwindow);
448 }
449
450 return true;
451 }
452
453 // Raise the window to the top of the Z order
454 void wxWindowX11::Raise()
455 {
456 if (m_mainWindow)
457 XRaiseWindow( wxGlobalDisplay(), (Window) m_mainWindow );
458 }
459
460 // Lower the window to the bottom of the Z order
461 void wxWindowX11::Lower()
462 {
463 if (m_mainWindow)
464 XLowerWindow( wxGlobalDisplay(), (Window) m_mainWindow );
465 }
466
467 void wxWindowX11::SetLabel(const wxString& WXUNUSED(label))
468 {
469 // TODO
470 }
471
472 wxString wxWindowX11::GetLabel() const
473 {
474 // TODO
475 return wxEmptyString;
476 }
477
478 void wxWindowX11::DoCaptureMouse()
479 {
480 if ((g_captureWindow != NULL) && (g_captureWindow != this))
481 {
482 wxASSERT_MSG(false, wxT("Trying to capture before mouse released."));
483
484 // Core dump now
485 int *tmp = NULL;
486 (*tmp) = 1;
487 return;
488 }
489
490 if (m_winCaptured)
491 return;
492
493 Window xwindow = (Window) m_clientWindow;
494
495 wxCHECK_RET( xwindow, wxT("invalid window") );
496
497 g_captureWindow = (wxWindow*) this;
498
499 if (xwindow)
500 {
501 int res = XGrabPointer(wxGlobalDisplay(), xwindow,
502 FALSE,
503 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask,
504 GrabModeAsync,
505 GrabModeAsync,
506 None,
507 None, /* cursor */ // TODO: This may need to be set to the cursor of this window
508 CurrentTime );
509
510 if (res != GrabSuccess)
511 {
512 wxString msg;
513 msg.Printf(wxT("Failed to grab pointer for window %s"), this->GetClassInfo()->GetClassName());
514 wxLogDebug(msg);
515 if (res == GrabNotViewable)
516 wxLogDebug( wxT("This is not a viewable window - perhaps not shown yet?") );
517
518 g_captureWindow = NULL;
519 return;
520 }
521
522 m_winCaptured = true;
523 }
524 }
525
526 void wxWindowX11::DoReleaseMouse()
527 {
528 g_captureWindow = NULL;
529
530 if ( !m_winCaptured )
531 return;
532
533 Window xwindow = (Window) m_clientWindow;
534
535 if (xwindow)
536 {
537 XUngrabPointer( wxGlobalDisplay(), CurrentTime );
538 }
539
540 // wxLogDebug( "Ungrabbed pointer in %s", GetName().c_str() );
541
542 m_winCaptured = false;
543 }
544
545 bool wxWindowX11::SetFont(const wxFont& font)
546 {
547 if ( !wxWindowBase::SetFont(font) )
548 {
549 // nothing to do
550 return false;
551 }
552
553 return true;
554 }
555
556 bool wxWindowX11::SetCursor(const wxCursor& cursor)
557 {
558 if ( !wxWindowBase::SetCursor(cursor) )
559 {
560 // no change
561 return false;
562 }
563
564 Window xwindow = (Window) m_clientWindow;
565
566 wxCHECK_MSG( xwindow, false, wxT("invalid window") );
567
568 wxCursor cursorToUse;
569 if (m_cursor.Ok())
570 cursorToUse = m_cursor;
571 else
572 cursorToUse = *wxSTANDARD_CURSOR;
573
574 Cursor xcursor = (Cursor) cursorToUse.GetCursor();
575
576 XDefineCursor( wxGlobalDisplay(), xwindow, xcursor );
577
578 return true;
579 }
580
581 // Coordinates relative to the window
582 void wxWindowX11::WarpPointer (int x, int y)
583 {
584 Window xwindow = (Window) m_clientWindow;
585
586 wxCHECK_RET( xwindow, wxT("invalid window") );
587
588 XWarpPointer( wxGlobalDisplay(), None, xwindow, 0, 0, 0, 0, x, y);
589 }
590
591 // Does a physical scroll
592 void wxWindowX11::ScrollWindow(int dx, int dy, const wxRect *rect)
593 {
594 // No scrolling requested.
595 if ((dx == 0) && (dy == 0)) return;
596
597 if (!m_updateRegion.IsEmpty())
598 {
599 m_updateRegion.Offset( dx, dy );
600
601 int cw = 0;
602 int ch = 0;
603 GetSize( &cw, &ch ); // GetClientSize() ??
604 m_updateRegion.Intersect( 0, 0, cw, ch );
605 }
606
607 if (!m_clearRegion.IsEmpty())
608 {
609 m_clearRegion.Offset( dx, dy );
610
611 int cw = 0;
612 int ch = 0;
613 GetSize( &cw, &ch ); // GetClientSize() ??
614 m_clearRegion.Intersect( 0, 0, cw, ch );
615 }
616
617 Window xwindow = (Window) GetClientAreaWindow();
618
619 wxCHECK_RET( xwindow, wxT("invalid window") );
620
621 Display *xdisplay = wxGlobalDisplay();
622
623 GC xgc = XCreateGC( xdisplay, xwindow, 0, NULL );
624 XSetGraphicsExposures( xdisplay, xgc, True );
625
626 int s_x = 0;
627 int s_y = 0;
628 int cw;
629 int ch;
630 if (rect)
631 {
632 s_x = rect->x;
633 s_y = rect->y;
634
635 cw = rect->width;
636 ch = rect->height;
637 }
638 else
639 {
640 s_x = 0;
641 s_y = 0;
642 GetClientSize( &cw, &ch );
643 }
644
645 #if wxUSE_TWO_WINDOWS
646 wxPoint offset( 0,0 );
647 #else
648 wxPoint offset = GetClientAreaOrigin();
649 s_x += offset.x;
650 s_y += offset.y;
651 #endif
652
653 int w = cw - abs(dx);
654 int h = ch - abs(dy);
655
656 if ((h < 0) || (w < 0))
657 {
658 Refresh();
659 }
660 else
661 {
662 wxRect rect;
663 if (dx < 0) rect.x = cw+dx + offset.x; else rect.x = s_x;
664 if (dy < 0) rect.y = ch+dy + offset.y; else rect.y = s_y;
665 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
666 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
667
668 int d_x = s_x;
669 int d_y = s_y;
670
671 if (dx < 0) s_x += -dx;
672 if (dy < 0) s_y += -dy;
673 if (dx > 0) d_x = dx + offset.x;
674 if (dy > 0) d_y = dy + offset.y;
675
676 XCopyArea( xdisplay, xwindow, xwindow, xgc, s_x, s_y, w, h, d_x, d_y );
677
678 // wxLogDebug( "Copy: s_x %d s_y %d w %d h %d d_x %d d_y %d", s_x, s_y, w, h, d_x, d_y );
679
680 // wxLogDebug( "Update: %d %d %d %d", rect.x, rect.y, rect.width, rect.height );
681
682 m_updateRegion.Union( rect );
683 m_clearRegion.Union( rect );
684 }
685
686 XFreeGC( xdisplay, xgc );
687
688 // Move Clients, but not the scrollbars
689 // FIXME: There may be a better method to move a lot of Windows within X11
690 wxScrollBar *sbH = ((wxWindow *) this)->GetScrollbar( wxHORIZONTAL );
691 wxScrollBar *sbV = ((wxWindow *) this)->GetScrollbar( wxVERTICAL );
692 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
693 while ( node )
694 {
695 // Only propagate to non-top-level windows
696 wxWindow *win = node->GetData();
697 if ( win->GetParent() && win != sbH && win != sbV )
698 {
699 wxPoint pos = win->GetPosition();
700 // Add the delta to the old Position
701 pos.x += dx;
702 pos.y += dy;
703 win->SetPosition(pos);
704 }
705 node = node->GetNext();
706 }
707 }
708
709 // ---------------------------------------------------------------------------
710 // drag and drop
711 // ---------------------------------------------------------------------------
712
713 #if wxUSE_DRAG_AND_DROP
714
715 void wxWindowX11::SetDropTarget(wxDropTarget * WXUNUSED(pDropTarget))
716 {
717 // TODO
718 }
719
720 #endif
721
722 // Old style file-manager drag&drop
723 void wxWindowX11::DragAcceptFiles(bool WXUNUSED(accept))
724 {
725 // TODO
726 }
727
728 // ----------------------------------------------------------------------------
729 // tooltips
730 // ----------------------------------------------------------------------------
731
732 #if wxUSE_TOOLTIPS
733
734 void wxWindowX11::DoSetToolTip(wxToolTip * WXUNUSED(tooltip))
735 {
736 // TODO
737 }
738
739 #endif // wxUSE_TOOLTIPS
740
741 // ---------------------------------------------------------------------------
742 // moving and resizing
743 // ---------------------------------------------------------------------------
744
745 bool wxWindowX11::PreResize()
746 {
747 return true;
748 }
749
750 // Get total size
751 void wxWindowX11::DoGetSize(int *x, int *y) const
752 {
753 Window xwindow = (Window) m_mainWindow;
754
755 wxCHECK_RET( xwindow, wxT("invalid window") );
756
757 //XSync(wxGlobalDisplay(), False);
758
759 XWindowAttributes attr;
760 Status status = XGetWindowAttributes( wxGlobalDisplay(), xwindow, &attr );
761 wxASSERT(status);
762
763 if (status)
764 {
765 *x = attr.width /* + 2*m_borderSize */ ;
766 *y = attr.height /* + 2*m_borderSize */ ;
767 }
768 }
769
770 void wxWindowX11::DoGetPosition(int *x, int *y) const
771 {
772 Window window = (Window) m_mainWindow;
773 if (window)
774 {
775 //XSync(wxGlobalDisplay(), False);
776 XWindowAttributes attr;
777 Status status = XGetWindowAttributes(wxGlobalDisplay(), window, & attr);
778 wxASSERT(status);
779
780 if (status)
781 {
782 *x = attr.x;
783 *y = attr.y;
784
785 // We may be faking the client origin. So a window that's really at (0, 30)
786 // may appear (to wxWin apps) to be at (0, 0).
787 if (GetParent())
788 {
789 wxPoint pt(GetParent()->GetClientAreaOrigin());
790 *x -= pt.x;
791 *y -= pt.y;
792 }
793 }
794 }
795 }
796
797 void wxWindowX11::DoScreenToClient(int *x, int *y) const
798 {
799 Display *display = wxGlobalDisplay();
800 Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display));
801 Window thisWindow = (Window) m_clientWindow;
802
803 Window childWindow;
804 int xx = *x;
805 int yy = *y;
806 XTranslateCoordinates(display, rootWindow, thisWindow, xx, yy, x, y, &childWindow);
807 }
808
809 void wxWindowX11::DoClientToScreen(int *x, int *y) const
810 {
811 Display *display = wxGlobalDisplay();
812 Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display));
813 Window thisWindow = (Window) m_clientWindow;
814
815 Window childWindow;
816 int xx = *x;
817 int yy = *y;
818 XTranslateCoordinates(display, thisWindow, rootWindow, xx, yy, x, y, &childWindow);
819 }
820
821
822 // Get size *available for subwindows* i.e. excluding menu bar etc.
823 void wxWindowX11::DoGetClientSize(int *x, int *y) const
824 {
825 Window window = (Window) m_mainWindow;
826
827 if (window)
828 {
829 XWindowAttributes attr;
830 Status status = XGetWindowAttributes( wxGlobalDisplay(), window, &attr );
831 wxASSERT(status);
832
833 if (status)
834 {
835 *x = attr.width ;
836 *y = attr.height ;
837 }
838 }
839 }
840
841 void wxWindowX11::DoSetSize(int x, int y, int width, int height, int sizeFlags)
842 {
843 // wxLogDebug("DoSetSize: %s (%ld) %d, %d %dx%d", GetClassInfo()->GetClassName(), GetId(), x, y, width, height);
844
845 Window xwindow = (Window) m_mainWindow;
846
847 wxCHECK_RET( xwindow, wxT("invalid window") );
848
849 XWindowAttributes attr;
850 Status status = XGetWindowAttributes( wxGlobalDisplay(), xwindow, &attr );
851 wxCHECK_RET( status, wxT("invalid window attributes") );
852
853 int new_x = attr.x;
854 int new_y = attr.y;
855 int new_w = attr.width;
856 int new_h = attr.height;
857
858 if (x != wxDefaultCoord || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
859 {
860 int yy = 0;
861 AdjustForParentClientOrigin( x, yy, sizeFlags);
862 new_x = x;
863 }
864 if (y != wxDefaultCoord || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
865 {
866 int xx = 0;
867 AdjustForParentClientOrigin( xx, y, sizeFlags);
868 new_y = y;
869 }
870 if (width != wxDefaultCoord)
871 {
872 new_w = width;
873 if (new_w <= 0)
874 new_w = 20;
875 }
876 if (height != wxDefaultCoord)
877 {
878 new_h = height;
879 if (new_h <= 0)
880 new_h = 20;
881 }
882
883 DoMoveWindow( new_x, new_y, new_w, new_h );
884 }
885
886 void wxWindowX11::DoSetClientSize(int width, int height)
887 {
888 // wxLogDebug("DoSetClientSize: %s (%ld) %dx%d", GetClassInfo()->GetClassName(), GetId(), width, height);
889
890 Window xwindow = (Window) m_mainWindow;
891
892 wxCHECK_RET( xwindow, wxT("invalid window") );
893
894 XResizeWindow( wxGlobalDisplay(), xwindow, width, height );
895
896 if (m_mainWindow != m_clientWindow)
897 {
898 xwindow = (Window) m_clientWindow;
899
900 wxWindow *window = (wxWindow*) this;
901 wxRenderer *renderer = window->GetRenderer();
902 if (renderer)
903 {
904 wxRect border = renderer->GetBorderDimensions( (wxBorder)(m_windowStyle & wxBORDER_MASK) );
905 width -= border.x + border.width;
906 height -= border.y + border.height;
907 }
908
909 XResizeWindow( wxGlobalDisplay(), xwindow, width, height );
910 }
911 }
912
913 void wxWindowX11::DoMoveWindow(int x, int y, int width, int height)
914 {
915 Window xwindow = (Window) m_mainWindow;
916
917 wxCHECK_RET( xwindow, wxT("invalid window") );
918
919 #if !wxUSE_NANOX
920
921 XMoveResizeWindow( wxGlobalDisplay(), xwindow, x, y, width, height );
922 if (m_mainWindow != m_clientWindow)
923 {
924 xwindow = (Window) m_clientWindow;
925
926 wxWindow *window = (wxWindow*) this;
927 wxRenderer *renderer = window->GetRenderer();
928 if (renderer)
929 {
930 wxRect border = renderer->GetBorderDimensions( (wxBorder)(m_windowStyle & wxBORDER_MASK) );
931 x = border.x;
932 y = border.y;
933 width -= border.x + border.width;
934 height -= border.y + border.height;
935 }
936 else
937 {
938 x = 0;
939 y = 0;
940 }
941
942 wxScrollBar *sb = window->GetScrollbar( wxHORIZONTAL );
943 if (sb && sb->IsShown())
944 {
945 wxSize size = sb->GetSize();
946 height -= size.y;
947 }
948 sb = window->GetScrollbar( wxVERTICAL );
949 if (sb && sb->IsShown())
950 {
951 wxSize size = sb->GetSize();
952 width -= size.x;
953 }
954
955 XMoveResizeWindow( wxGlobalDisplay(), xwindow, x, y, wxMax(1, width), wxMax(1, height) );
956 }
957
958 #else
959
960 XWindowChanges windowChanges;
961 windowChanges.x = x;
962 windowChanges.y = y;
963 windowChanges.width = width;
964 windowChanges.height = height;
965 windowChanges.stack_mode = 0;
966 int valueMask = CWX | CWY | CWWidth | CWHeight;
967
968 XConfigureWindow( wxGlobalDisplay(), xwindow, valueMask, &windowChanges );
969
970 #endif
971 }
972
973 void wxWindowX11::DoSetSizeHints(int minW, int minH, int maxW, int maxH, int incW, int incH)
974 {
975 m_minWidth = minW;
976 m_minHeight = minH;
977 m_maxWidth = maxW;
978 m_maxHeight = maxH;
979
980 #if !wxUSE_NANOX
981 XSizeHints sizeHints;
982 sizeHints.flags = 0;
983
984 if (minW > -1 && minH > -1)
985 {
986 sizeHints.flags |= PMinSize;
987 sizeHints.min_width = minW;
988 sizeHints.min_height = minH;
989 }
990 if (maxW > -1 && maxH > -1)
991 {
992 sizeHints.flags |= PMaxSize;
993 sizeHints.max_width = maxW;
994 sizeHints.max_height = maxH;
995 }
996 if (incW > -1 && incH > -1)
997 {
998 sizeHints.flags |= PResizeInc;
999 sizeHints.width_inc = incW;
1000 sizeHints.height_inc = incH;
1001 }
1002
1003 XSetWMNormalHints(wxGlobalDisplay(), (Window) m_mainWindow, &sizeHints );
1004 #endif
1005 }
1006
1007 // ---------------------------------------------------------------------------
1008 // text metrics
1009 // ---------------------------------------------------------------------------
1010
1011 int wxWindowX11::GetCharHeight() const
1012 {
1013 wxFont font(GetFont());
1014 wxCHECK_MSG( font.Ok(), 0, wxT("valid window font needed") );
1015
1016 #if wxUSE_UNICODE
1017 // There should be an easier way.
1018 PangoLayout *layout = pango_layout_new( wxTheApp->GetPangoContext() );
1019 pango_layout_set_font_description( layout, font.GetNativeFontInfo()->description );
1020 pango_layout_set_text(layout, "H", 1 );
1021 int w,h;
1022 pango_layout_get_pixel_size(layout, &w, &h);
1023 g_object_unref( G_OBJECT( layout ) );
1024
1025 return h;
1026 #else
1027 WXFontStructPtr pFontStruct = font.GetFontStruct(1.0, wxGlobalDisplay());
1028
1029 int direction, ascent, descent;
1030 XCharStruct overall;
1031 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1032 &descent, &overall);
1033
1034 // return (overall.ascent + overall.descent);
1035 return (ascent + descent);
1036 #endif
1037 }
1038
1039 int wxWindowX11::GetCharWidth() const
1040 {
1041 wxFont font(GetFont());
1042 wxCHECK_MSG( font.Ok(), 0, wxT("valid window font needed") );
1043
1044 #if wxUSE_UNICODE
1045 // There should be an easier way.
1046 PangoLayout *layout = pango_layout_new( wxTheApp->GetPangoContext() );
1047 pango_layout_set_font_description( layout, font.GetNativeFontInfo()->description );
1048 pango_layout_set_text(layout, "H", 1 );
1049 int w,h;
1050 pango_layout_get_pixel_size(layout, &w, &h);
1051 g_object_unref( G_OBJECT( layout ) );
1052
1053 return w;
1054 #else
1055 WXFontStructPtr pFontStruct = font.GetFontStruct(1.0, wxGlobalDisplay());
1056
1057 int direction, ascent, descent;
1058 XCharStruct overall;
1059 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1060 &descent, &overall);
1061
1062 return overall.width;
1063 #endif
1064 }
1065
1066 void wxWindowX11::GetTextExtent(const wxString& string,
1067 int *x, int *y,
1068 int *descent, int *externalLeading,
1069 const wxFont *theFont) const
1070 {
1071 wxFont fontToUse = GetFont();
1072 if (theFont) fontToUse = *theFont;
1073
1074 wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
1075
1076 if (string.empty())
1077 {
1078 if (x) (*x) = 0;
1079 if (y) (*y) = 0;
1080 return;
1081 }
1082
1083 #if wxUSE_UNICODE
1084 PangoLayout *layout = pango_layout_new( wxTheApp->GetPangoContext() );
1085
1086 PangoFontDescription *desc = fontToUse.GetNativeFontInfo()->description;
1087 pango_layout_set_font_description(layout, desc);
1088
1089 const wxCharBuffer data = wxConvUTF8.cWC2MB( string );
1090 pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
1091
1092 PangoLayoutLine *line = (PangoLayoutLine *)pango_layout_get_lines(layout)->data;
1093
1094
1095 PangoRectangle rect;
1096 pango_layout_line_get_extents(line, NULL, &rect);
1097
1098 if (x) (*x) = (wxCoord) (rect.width / PANGO_SCALE);
1099 if (y) (*y) = (wxCoord) (rect.height / PANGO_SCALE);
1100 if (descent)
1101 {
1102 // Do something about metrics here
1103 (*descent) = 0;
1104 }
1105 if (externalLeading) (*externalLeading) = 0; // ??
1106
1107 g_object_unref( G_OBJECT( layout ) );
1108 #else
1109 WXFontStructPtr pFontStruct = fontToUse.GetFontStruct(1.0, wxGlobalDisplay());
1110
1111 int direction, ascent, descent2;
1112 XCharStruct overall;
1113 int slen = string.Len();
1114
1115 XTextExtents((XFontStruct*) pFontStruct, (char*) string.c_str(), slen,
1116 &direction, &ascent, &descent2, &overall);
1117
1118 if ( x )
1119 *x = (overall.width);
1120 if ( y )
1121 *y = (ascent + descent2);
1122 if (descent)
1123 *descent = descent2;
1124 if (externalLeading)
1125 *externalLeading = 0;
1126 #endif
1127 }
1128
1129 // ----------------------------------------------------------------------------
1130 // painting
1131 // ----------------------------------------------------------------------------
1132
1133 void wxWindowX11::Refresh(bool eraseBack, const wxRect *rect)
1134 {
1135 if (eraseBack)
1136 {
1137 if (rect)
1138 {
1139 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
1140 m_clearRegion.Union( rect->x, rect->y, rect->width, rect->height );
1141 }
1142 else
1143 {
1144 int height,width;
1145 GetSize( &width, &height );
1146
1147 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
1148 m_clearRegion.Clear();
1149 m_clearRegion.Union( 0, 0, width, height );
1150 }
1151 }
1152
1153 if (rect)
1154 {
1155 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
1156 m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height );
1157 }
1158 else
1159 {
1160 int height,width;
1161 GetSize( &width, &height );
1162
1163 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
1164 m_updateRegion.Clear();
1165 m_updateRegion.Union( 0, 0, width, height );
1166 }
1167 }
1168
1169 void wxWindowX11::Update()
1170 {
1171 if (m_updateNcArea)
1172 {
1173 // wxLogDebug("wxWindowX11::UpdateNC: %s", GetClassInfo()->GetClassName());
1174 // Send nc paint events.
1175 SendNcPaintEvents();
1176 }
1177
1178 if (!m_updateRegion.IsEmpty())
1179 {
1180 // wxLogDebug("wxWindowX11::Update: %s", GetClassInfo()->GetClassName());
1181 // Actually send erase events.
1182 SendEraseEvents();
1183
1184 // Actually send paint events.
1185 SendPaintEvents();
1186 }
1187 }
1188
1189 void wxWindowX11::SendEraseEvents()
1190 {
1191 if (m_clearRegion.IsEmpty()) return;
1192
1193 wxClientDC dc( (wxWindow*)this );
1194 dc.SetClippingRegion( m_clearRegion );
1195
1196 wxEraseEvent erase_event( GetId(), &dc );
1197 erase_event.SetEventObject( this );
1198
1199 if (!GetEventHandler()->ProcessEvent(erase_event) )
1200 {
1201 Display *xdisplay = wxGlobalDisplay();
1202 Window xwindow = (Window) GetClientAreaWindow();
1203 XSetForeground( xdisplay, g_eraseGC, m_backgroundColour.GetPixel() );
1204
1205 wxRegionIterator upd( m_clearRegion );
1206 while (upd)
1207 {
1208 XFillRectangle( xdisplay, xwindow, g_eraseGC,
1209 upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() );
1210 upd ++;
1211 }
1212 }
1213
1214 m_clearRegion.Clear();
1215 }
1216
1217 void wxWindowX11::SendPaintEvents()
1218 {
1219 // wxLogDebug("SendPaintEvents: %s (%ld)", GetClassInfo()->GetClassName(), GetId());
1220
1221 m_clipPaintRegion = true;
1222
1223 wxPaintEvent paint_event( GetId() );
1224 paint_event.SetEventObject( this );
1225 GetEventHandler()->ProcessEvent( paint_event );
1226
1227 m_updateRegion.Clear();
1228
1229 m_clipPaintRegion = false;
1230 }
1231
1232 void wxWindowX11::SendNcPaintEvents()
1233 {
1234 wxWindow *window = (wxWindow*) this;
1235
1236 // All this for drawing the small square between the scrollbars.
1237 int width = 0;
1238 int height = 0;
1239 int x = 0;
1240 int y = 0;
1241 wxScrollBar *sb = window->GetScrollbar( wxHORIZONTAL );
1242 if (sb && sb->IsShown())
1243 {
1244 height = sb->GetSize().y;
1245 y = sb->GetPosition().y;
1246
1247 sb = window->GetScrollbar( wxVERTICAL );
1248 if (sb && sb->IsShown())
1249 {
1250 width = sb->GetSize().x;
1251 x = sb->GetPosition().x;
1252
1253 Display *xdisplay = wxGlobalDisplay();
1254 Window xwindow = (Window) GetMainWindow();
1255 Colormap cm = (Colormap) wxTheApp->GetMainColormap( wxGetDisplay() );
1256 wxColour colour = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE);
1257 colour.CalcPixel( (WXColormap) cm );
1258
1259 XSetForeground( xdisplay, g_eraseGC, colour.GetPixel() );
1260
1261 XFillRectangle( xdisplay, xwindow, g_eraseGC, x, y, width, height );
1262 }
1263 }
1264
1265 wxNcPaintEvent nc_paint_event( GetId() );
1266 nc_paint_event.SetEventObject( this );
1267 GetEventHandler()->ProcessEvent( nc_paint_event );
1268
1269 m_updateNcArea = false;
1270 }
1271
1272 // ----------------------------------------------------------------------------
1273 // event handlers
1274 // ----------------------------------------------------------------------------
1275
1276 // Responds to colour changes: passes event on to children.
1277 void wxWindowX11::OnSysColourChanged(wxSysColourChangedEvent& event)
1278 {
1279 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
1280 while ( node )
1281 {
1282 // Only propagate to non-top-level windows
1283 wxWindow *win = node->GetData();
1284 if ( win->GetParent() )
1285 {
1286 wxSysColourChangedEvent event2;
1287 event.SetEventObject(win);
1288 win->GetEventHandler()->ProcessEvent(event2);
1289 }
1290
1291 node = node->GetNext();
1292 }
1293 }
1294
1295 // See handler for InFocus case in app.cpp for details.
1296 wxWindow* g_GettingFocus = NULL;
1297
1298 void wxWindowX11::OnInternalIdle()
1299 {
1300 // Update invalidated regions.
1301 Update();
1302
1303 // This calls the UI-update mechanism (querying windows for
1304 // menu/toolbar/control state information)
1305 if (wxUpdateUIEvent::CanUpdate((wxWindow*) this))
1306 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
1307
1308 // Set the input focus if couldn't do it before
1309 if (m_needsInputFocus)
1310 {
1311 #if 0
1312 wxString msg;
1313 msg.Printf("Setting focus for %s from OnInternalIdle\n", GetClassInfo()->GetClassName());
1314 printf(msg.c_str());
1315 #endif
1316 SetFocus();
1317
1318 // If it couldn't set the focus now, there's
1319 // no point in trying again.
1320 m_needsInputFocus = false;
1321 }
1322 g_GettingFocus = NULL;
1323 }
1324
1325 // ----------------------------------------------------------------------------
1326 // function which maintain the global hash table mapping Widgets to wxWidgets
1327 // ----------------------------------------------------------------------------
1328
1329 static bool DoAddWindowToTable(wxWindowHash *hash, Window w, wxWindow *win)
1330 {
1331 if ( !hash->insert(wxWindowHash::value_type(w, win)).second )
1332 {
1333 wxLogDebug( wxT("Widget table clash: new widget is 0x%08x, %s"),
1334 (unsigned int)w, win->GetClassInfo()->GetClassName());
1335 return false;
1336 }
1337
1338 wxLogTrace( wxT("widget"), wxT("XWindow 0x%08x <-> window %p (%s)"),
1339 (unsigned int) w, win, win->GetClassInfo()->GetClassName());
1340
1341 return true;
1342 }
1343
1344 static inline wxWindow *DoGetWindowFromTable(wxWindowHash *hash, Window w)
1345 {
1346 wxWindowHash::iterator i = hash->find(w);
1347 return i == hash->end() ? NULL : i->second;
1348 }
1349
1350 static inline void DoDeleteWindowFromTable(wxWindowHash *hash, Window w)
1351 {
1352 wxLogTrace( wxT("widget"), wxT("XWindow 0x%08x deleted"), (unsigned int) w);
1353
1354 hash->erase(w);
1355 }
1356
1357 // ----------------------------------------------------------------------------
1358 // public wrappers
1359 // ----------------------------------------------------------------------------
1360
1361 bool wxAddWindowToTable(Window w, wxWindow *win)
1362 {
1363 return DoAddWindowToTable(wxWidgetHashTable, w, win);
1364 }
1365
1366 wxWindow *wxGetWindowFromTable(Window w)
1367 {
1368 return DoGetWindowFromTable(wxWidgetHashTable, w);
1369 }
1370
1371 void wxDeleteWindowFromTable(Window w)
1372 {
1373 DoDeleteWindowFromTable(wxWidgetHashTable, w);
1374 }
1375
1376 bool wxAddClientWindowToTable(Window w, wxWindow *win)
1377 {
1378 return DoAddWindowToTable(wxClientWidgetHashTable, w, win);
1379 }
1380
1381 wxWindow *wxGetClientWindowFromTable(Window w)
1382 {
1383 return DoGetWindowFromTable(wxClientWidgetHashTable, w);
1384 }
1385
1386 void wxDeleteClientWindowFromTable(Window w)
1387 {
1388 DoDeleteWindowFromTable(wxClientWidgetHashTable, w);
1389 }
1390
1391 // ----------------------------------------------------------------------------
1392 // X11-specific accessors
1393 // ----------------------------------------------------------------------------
1394
1395 WXWindow wxWindowX11::GetMainWindow() const
1396 {
1397 return m_mainWindow;
1398 }
1399
1400 WXWindow wxWindowX11::GetClientAreaWindow() const
1401 {
1402 return m_clientWindow;
1403 }
1404
1405 // ----------------------------------------------------------------------------
1406 // TranslateXXXEvent() functions
1407 // ----------------------------------------------------------------------------
1408
1409 bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Window window, XEvent *xevent)
1410 {
1411 switch (XEventGetType(xevent))
1412 {
1413 case EnterNotify:
1414 case LeaveNotify:
1415 case ButtonPress:
1416 case ButtonRelease:
1417 case MotionNotify:
1418 {
1419 wxEventType eventType = wxEVT_NULL;
1420
1421 if (XEventGetType(xevent) == EnterNotify)
1422 {
1423 //if (local_event.xcrossing.mode!=NotifyNormal)
1424 // return ; // Ignore grab events
1425 eventType = wxEVT_ENTER_WINDOW;
1426 // canvas->GetEventHandler()->OnSetFocus();
1427 }
1428 else if (XEventGetType(xevent) == LeaveNotify)
1429 {
1430 //if (local_event.xcrossingr.mode!=NotifyNormal)
1431 // return ; // Ignore grab events
1432 eventType = wxEVT_LEAVE_WINDOW;
1433 // canvas->GetEventHandler()->OnKillFocus();
1434 }
1435 else if (XEventGetType(xevent) == MotionNotify)
1436 {
1437 eventType = wxEVT_MOTION;
1438 }
1439 else if (XEventGetType(xevent) == ButtonPress)
1440 {
1441 wxevent.SetTimestamp(XButtonEventGetTime(xevent));
1442 int button = 0;
1443 if (XButtonEventLChanged(xevent))
1444 {
1445 eventType = wxEVT_LEFT_DOWN;
1446 button = 1;
1447 }
1448 else if (XButtonEventMChanged(xevent))
1449 {
1450 eventType = wxEVT_MIDDLE_DOWN;
1451 button = 2;
1452 }
1453 else if (XButtonEventRChanged(xevent))
1454 {
1455 eventType = wxEVT_RIGHT_DOWN;
1456 button = 3;
1457 }
1458
1459 // check for a double click
1460 // TODO: where can we get this value from?
1461 //long dclickTime = XtGetMultiClickTime(wxGlobalDisplay());
1462 long dclickTime = 200;
1463 long ts = wxevent.GetTimestamp();
1464
1465 int buttonLast = win->GetLastClickedButton();
1466 long lastTS = win->GetLastClickTime();
1467 if ( buttonLast && buttonLast == button && (ts - lastTS) < dclickTime )
1468 {
1469 // I have a dclick
1470 win->SetLastClick(0, ts);
1471 if ( eventType == wxEVT_LEFT_DOWN )
1472 eventType = wxEVT_LEFT_DCLICK;
1473 else if ( eventType == wxEVT_MIDDLE_DOWN )
1474 eventType = wxEVT_MIDDLE_DCLICK;
1475 else if ( eventType == wxEVT_RIGHT_DOWN )
1476 eventType = wxEVT_RIGHT_DCLICK;
1477 }
1478 else
1479 {
1480 // not fast enough or different button
1481 win->SetLastClick(button, ts);
1482 }
1483 }
1484 else if (XEventGetType(xevent) == ButtonRelease)
1485 {
1486 if (XButtonEventLChanged(xevent))
1487 {
1488 eventType = wxEVT_LEFT_UP;
1489 }
1490 else if (XButtonEventMChanged(xevent))
1491 {
1492 eventType = wxEVT_MIDDLE_UP;
1493 }
1494 else if (XButtonEventRChanged(xevent))
1495 {
1496 eventType = wxEVT_RIGHT_UP;
1497 }
1498 else return false;
1499 }
1500 else
1501 {
1502 return false;
1503 }
1504
1505 wxevent.SetEventType(eventType);
1506
1507 wxevent.m_x = XButtonEventGetX(xevent);
1508 wxevent.m_y = XButtonEventGetY(xevent);
1509
1510 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
1511 || (XButtonEventLIsDown(xevent)
1512 && (eventType != wxEVT_LEFT_UP)));
1513 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
1514 || (XButtonEventMIsDown(xevent)
1515 && (eventType != wxEVT_MIDDLE_UP)));
1516 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
1517 || (XButtonEventRIsDown (xevent)
1518 && (eventType != wxEVT_RIGHT_UP)));
1519
1520 wxevent.m_shiftDown = XButtonEventShiftIsDown(xevent);
1521 wxevent.m_controlDown = XButtonEventCtrlIsDown(xevent);
1522 wxevent.m_altDown = XButtonEventAltIsDown(xevent);
1523 wxevent.m_metaDown = XButtonEventMetaIsDown(xevent);
1524
1525 wxevent.SetId(win->GetId());
1526 wxevent.SetEventObject(win);
1527
1528 return true;
1529 }
1530 }
1531 return false;
1532 }
1533
1534 bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Window WXUNUSED(win), XEvent *xevent, bool isAscii)
1535 {
1536 switch (XEventGetType(xevent))
1537 {
1538 case KeyPress:
1539 case KeyRelease:
1540 {
1541 char buf[20];
1542
1543 KeySym keySym;
1544 (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, NULL);
1545 int id = wxCharCodeXToWX (keySym);
1546 // id may be WXK_xxx code - these are outside ASCII range, so we
1547 // can't just use toupper() on id.
1548 // Only change this if we want the raw key that was pressed,
1549 // and don't change it if we want an ASCII value.
1550 if (!isAscii && (id >= 'a' && id <= 'z'))
1551 {
1552 id = id + 'A' - 'a';
1553 }
1554
1555 wxevent.m_shiftDown = XKeyEventShiftIsDown(xevent);
1556 wxevent.m_controlDown = XKeyEventCtrlIsDown(xevent);
1557 wxevent.m_altDown = XKeyEventAltIsDown(xevent);
1558 wxevent.m_metaDown = XKeyEventMetaIsDown(xevent);
1559 wxevent.SetEventObject(win);
1560 wxevent.m_keyCode = id;
1561 wxevent.SetTimestamp(XKeyEventGetTime(xevent));
1562
1563 wxevent.m_x = XKeyEventGetX(xevent);
1564 wxevent.m_y = XKeyEventGetY(xevent);
1565
1566 return id > -1;
1567 }
1568 default:
1569 break;
1570 }
1571 return false;
1572 }
1573
1574 // ----------------------------------------------------------------------------
1575 // Colour stuff
1576 // ----------------------------------------------------------------------------
1577
1578 bool wxWindowX11::SetBackgroundColour(const wxColour& col)
1579 {
1580 wxWindowBase::SetBackgroundColour(col);
1581
1582 Display *xdisplay = (Display*) wxGlobalDisplay();
1583 int xscreen = DefaultScreen( xdisplay );
1584 Colormap cm = DefaultColormap( xdisplay, xscreen );
1585
1586 m_backgroundColour.CalcPixel( (WXColormap) cm );
1587
1588 // We don't set the background colour as we paint
1589 // the background ourselves.
1590 // XSetWindowBackground( xdisplay, (Window) m_clientWindow, m_backgroundColour.GetPixel() );
1591
1592 return true;
1593 }
1594
1595 bool wxWindowX11::SetForegroundColour(const wxColour& col)
1596 {
1597 if ( !wxWindowBase::SetForegroundColour(col) )
1598 return false;
1599
1600 return true;
1601 }
1602
1603 // ----------------------------------------------------------------------------
1604 // global functions
1605 // ----------------------------------------------------------------------------
1606
1607 wxWindow *wxGetActiveWindow()
1608 {
1609 // TODO
1610 wxFAIL_MSG(wxT("Not implemented"));
1611 return NULL;
1612 }
1613
1614 /* static */
1615 wxWindow *wxWindowBase::GetCapture()
1616 {
1617 return (wxWindow *)g_captureWindow;
1618 }
1619
1620
1621 // Find the wxWindow at the current mouse position, returning the mouse
1622 // position.
1623 wxWindow* wxFindWindowAtPointer(wxPoint& pt)
1624 {
1625 return wxFindWindowAtPoint(wxGetMousePosition());
1626 }
1627
1628 // Get the current mouse position.
1629 wxPoint wxGetMousePosition()
1630 {
1631 #if wxUSE_NANOX
1632 /* TODO */
1633 return wxPoint(0, 0);
1634 #else
1635 Display *display = wxGlobalDisplay();
1636 Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
1637 Window rootReturn, childReturn;
1638 int rootX, rootY, winX, winY;
1639 unsigned int maskReturn;
1640
1641 XQueryPointer (display,
1642 rootWindow,
1643 &rootReturn,
1644 &childReturn,
1645 &rootX, &rootY, &winX, &winY, &maskReturn);
1646 return wxPoint(rootX, rootY);
1647 #endif
1648 }
1649
1650
1651 // ----------------------------------------------------------------------------
1652 // wxNoOptimize: switch off size optimization
1653 // ----------------------------------------------------------------------------
1654
1655 int wxNoOptimize::ms_count = 0;
1656
1657
1658 // ----------------------------------------------------------------------------
1659 // wxDCModule
1660 // ----------------------------------------------------------------------------
1661
1662 class wxWinModule : public wxModule
1663 {
1664 public:
1665 bool OnInit();
1666 void OnExit();
1667
1668 private:
1669 DECLARE_DYNAMIC_CLASS(wxWinModule)
1670 };
1671
1672 IMPLEMENT_DYNAMIC_CLASS(wxWinModule, wxModule)
1673
1674 bool wxWinModule::OnInit()
1675 {
1676 Display *xdisplay = wxGlobalDisplay();
1677 int xscreen = DefaultScreen( xdisplay );
1678 Window xroot = RootWindow( xdisplay, xscreen );
1679 g_eraseGC = XCreateGC( xdisplay, xroot, 0, NULL );
1680 XSetFillStyle( xdisplay, g_eraseGC, FillSolid );
1681
1682 return true;
1683 }
1684
1685 void wxWinModule::OnExit()
1686 {
1687 Display *xdisplay = wxGlobalDisplay();
1688 XFreeGC( xdisplay, g_eraseGC );
1689 }