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