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