Unicode compilation fixes for wxX11
[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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
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, wxT("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, wxT("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, wxT("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, 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, 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::SendEraseEvents()
1167 {
1168 if (m_clearRegion.IsEmpty()) return;
1169
1170 wxClientDC dc( (wxWindow*)this );
1171 dc.SetClippingRegion( m_clearRegion );
1172
1173 wxEraseEvent erase_event( GetId(), &dc );
1174 erase_event.SetEventObject( this );
1175
1176 if (!GetEventHandler()->ProcessEvent(erase_event) )
1177 {
1178 Display *xdisplay = wxGlobalDisplay();
1179 Window xwindow = (Window) GetClientAreaWindow();
1180 XSetForeground( xdisplay, g_eraseGC, m_backgroundColour.GetPixel() );
1181
1182 wxRegionIterator upd( m_clearRegion );
1183 while (upd)
1184 {
1185 XFillRectangle( xdisplay, xwindow, g_eraseGC,
1186 upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() );
1187 upd ++;
1188 }
1189 }
1190
1191 m_clearRegion.Clear();
1192 }
1193
1194 void wxWindowX11::SendPaintEvents()
1195 {
1196 // wxLogDebug("SendPaintEvents: %s (%ld)", GetClassInfo()->GetClassName(), GetId());
1197
1198 m_clipPaintRegion = TRUE;
1199
1200 wxPaintEvent paint_event( GetId() );
1201 paint_event.SetEventObject( this );
1202 GetEventHandler()->ProcessEvent( paint_event );
1203
1204 m_updateRegion.Clear();
1205
1206 m_clipPaintRegion = FALSE;
1207 }
1208
1209 void wxWindowX11::SendNcPaintEvents()
1210 {
1211 wxWindow *window = (wxWindow*) this;
1212
1213 // All this for drawing the small square between the scrollbars.
1214 int width = 0;
1215 int height = 0;
1216 int x = 0;
1217 int y = 0;
1218 wxScrollBar *sb = window->GetScrollbar( wxHORIZONTAL );
1219 if (sb && sb->IsShown())
1220 {
1221 height = sb->GetSize().y;
1222 y = sb->GetPosition().y;
1223
1224 sb = window->GetScrollbar( wxVERTICAL );
1225 if (sb && sb->IsShown())
1226 {
1227 width = sb->GetSize().x;
1228 x = sb->GetPosition().x;
1229
1230 Display *xdisplay = wxGlobalDisplay();
1231 Window xwindow = (Window) GetMainWindow();
1232 Colormap cm = (Colormap) wxTheApp->GetMainColormap( wxGetDisplay() );
1233 wxColour colour = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE);
1234 colour.CalcPixel( (WXColormap) cm );
1235
1236 XSetForeground( xdisplay, g_eraseGC, colour.GetPixel() );
1237
1238 XFillRectangle( xdisplay, xwindow, g_eraseGC, x, y, width, height );
1239 }
1240 }
1241
1242 wxNcPaintEvent nc_paint_event( GetId() );
1243 nc_paint_event.SetEventObject( this );
1244 GetEventHandler()->ProcessEvent( nc_paint_event );
1245
1246 m_updateNcArea = FALSE;
1247 }
1248
1249 // ----------------------------------------------------------------------------
1250 // event handlers
1251 // ----------------------------------------------------------------------------
1252
1253 // Responds to colour changes: passes event on to children.
1254 void wxWindowX11::OnSysColourChanged(wxSysColourChangedEvent& event)
1255 {
1256 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
1257 while ( node )
1258 {
1259 // Only propagate to non-top-level windows
1260 wxWindow *win = node->GetData();
1261 if ( win->GetParent() )
1262 {
1263 wxSysColourChangedEvent event2;
1264 event.m_eventObject = win;
1265 win->GetEventHandler()->ProcessEvent(event2);
1266 }
1267
1268 node = node->GetNext();
1269 }
1270 }
1271
1272 // See handler for InFocus case in app.cpp for details.
1273 wxWindow* g_GettingFocus = NULL;
1274
1275 void wxWindowX11::OnInternalIdle()
1276 {
1277 // Update invalidated regions.
1278 Update();
1279
1280 // This calls the UI-update mechanism (querying windows for
1281 // menu/toolbar/control state information)
1282 if (wxUpdateUIEvent::CanUpdate((wxWindow*) this))
1283 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
1284
1285 // Set the input focus if couldn't do it before
1286 if (m_needsInputFocus)
1287 {
1288 #if 0
1289 wxString msg;
1290 msg.Printf("Setting focus for %s from OnInternalIdle\n", GetClassInfo()->GetClassName());
1291 printf(msg.c_str());
1292 #endif
1293 SetFocus();
1294
1295 // If it couldn't set the focus now, there's
1296 // no point in trying again.
1297 m_needsInputFocus = FALSE;
1298 }
1299 g_GettingFocus = NULL;
1300 }
1301
1302 // ----------------------------------------------------------------------------
1303 // function which maintain the global hash table mapping Widgets to wxWindows
1304 // ----------------------------------------------------------------------------
1305
1306 bool wxAddWindowToTable(Window w, wxWindow *win)
1307 {
1308 wxWindow *oldItem = NULL;
1309 if ((oldItem = (wxWindow *)wxWidgetHashTable->Get ((long) w)))
1310 {
1311 wxLogDebug( wxT("Widget table clash: new widget is %ld, %s"),
1312 (long)w, win->GetClassInfo()->GetClassName());
1313 return FALSE;
1314 }
1315
1316 wxWidgetHashTable->Put((long) w, win);
1317
1318 wxLogTrace( wxT("widget"), wxT("XWindow 0x%08x <-> window %p (%s)"),
1319 (unsigned int) w, win, win->GetClassInfo()->GetClassName());
1320
1321 return TRUE;
1322 }
1323
1324 wxWindow *wxGetWindowFromTable(Window w)
1325 {
1326 return (wxWindow *)wxWidgetHashTable->Get((long) w);
1327 }
1328
1329 void wxDeleteWindowFromTable(Window w)
1330 {
1331 wxWidgetHashTable->Delete((long)w);
1332 }
1333
1334 // ----------------------------------------------------------------------------
1335 // function which maintain the global hash table mapping client widgets
1336 // ----------------------------------------------------------------------------
1337
1338 bool wxAddClientWindowToTable(Window w, wxWindow *win)
1339 {
1340 wxWindow *oldItem = NULL;
1341 if ((oldItem = (wxWindow *)wxClientWidgetHashTable->Get ((long) w)))
1342 {
1343 wxLogDebug( wxT("Client window table clash: new window is %ld, %s"),
1344 (long)w, win->GetClassInfo()->GetClassName());
1345 return FALSE;
1346 }
1347
1348 wxClientWidgetHashTable->Put((long) w, win);
1349
1350 wxLogTrace( wxT("widget"), wxT("XWindow 0x%08x <-> window %p (%s)"),
1351 (unsigned int) w, win, win->GetClassInfo()->GetClassName());
1352
1353 return TRUE;
1354 }
1355
1356 wxWindow *wxGetClientWindowFromTable(Window w)
1357 {
1358 return (wxWindow *)wxClientWidgetHashTable->Get((long) w);
1359 }
1360
1361 void wxDeleteClientWindowFromTable(Window w)
1362 {
1363 wxClientWidgetHashTable->Delete((long)w);
1364 }
1365
1366 // ----------------------------------------------------------------------------
1367 // add/remove window from the table
1368 // ----------------------------------------------------------------------------
1369
1370 // ----------------------------------------------------------------------------
1371 // X11-specific accessors
1372 // ----------------------------------------------------------------------------
1373
1374 WXWindow wxWindowX11::GetMainWindow() const
1375 {
1376 return m_mainWindow;
1377 }
1378
1379 WXWindow wxWindowX11::GetClientAreaWindow() const
1380 {
1381 return m_clientWindow;
1382 }
1383
1384 // ----------------------------------------------------------------------------
1385 // TranslateXXXEvent() functions
1386 // ----------------------------------------------------------------------------
1387
1388 bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Window window, XEvent *xevent)
1389 {
1390 switch (XEventGetType(xevent))
1391 {
1392 case EnterNotify:
1393 case LeaveNotify:
1394 case ButtonPress:
1395 case ButtonRelease:
1396 case MotionNotify:
1397 {
1398 wxEventType eventType = wxEVT_NULL;
1399
1400 if (XEventGetType(xevent) == EnterNotify)
1401 {
1402 //if (local_event.xcrossing.mode!=NotifyNormal)
1403 // return ; // Ignore grab events
1404 eventType = wxEVT_ENTER_WINDOW;
1405 // canvas->GetEventHandler()->OnSetFocus();
1406 }
1407 else if (XEventGetType(xevent) == LeaveNotify)
1408 {
1409 //if (local_event.xcrossingr.mode!=NotifyNormal)
1410 // return ; // Ignore grab events
1411 eventType = wxEVT_LEAVE_WINDOW;
1412 // canvas->GetEventHandler()->OnKillFocus();
1413 }
1414 else if (XEventGetType(xevent) == MotionNotify)
1415 {
1416 eventType = wxEVT_MOTION;
1417 }
1418 else if (XEventGetType(xevent) == ButtonPress)
1419 {
1420 wxevent.SetTimestamp(XButtonEventGetTime(xevent));
1421 int button = 0;
1422 if (XButtonEventLChanged(xevent))
1423 {
1424 eventType = wxEVT_LEFT_DOWN;
1425 button = 1;
1426 }
1427 else if (XButtonEventMChanged(xevent))
1428 {
1429 eventType = wxEVT_MIDDLE_DOWN;
1430 button = 2;
1431 }
1432 else if (XButtonEventRChanged(xevent))
1433 {
1434 eventType = wxEVT_RIGHT_DOWN;
1435 button = 3;
1436 }
1437
1438 // check for a double click
1439 // TODO: where can we get this value from?
1440 //long dclickTime = XtGetMultiClickTime(wxGlobalDisplay());
1441 long dclickTime = 200;
1442 long ts = wxevent.GetTimestamp();
1443
1444 int buttonLast = win->GetLastClickedButton();
1445 long lastTS = win->GetLastClickTime();
1446 if ( buttonLast && buttonLast == button && (ts - lastTS) < dclickTime )
1447 {
1448 // I have a dclick
1449 win->SetLastClick(0, ts);
1450 if ( eventType == wxEVT_LEFT_DOWN )
1451 eventType = wxEVT_LEFT_DCLICK;
1452 else if ( eventType == wxEVT_MIDDLE_DOWN )
1453 eventType = wxEVT_MIDDLE_DCLICK;
1454 else if ( eventType == wxEVT_RIGHT_DOWN )
1455 eventType = wxEVT_RIGHT_DCLICK;
1456 }
1457 else
1458 {
1459 // not fast enough or different button
1460 win->SetLastClick(button, ts);
1461 }
1462 }
1463 else if (XEventGetType(xevent) == ButtonRelease)
1464 {
1465 if (XButtonEventLChanged(xevent))
1466 {
1467 eventType = wxEVT_LEFT_UP;
1468 }
1469 else if (XButtonEventMChanged(xevent))
1470 {
1471 eventType = wxEVT_MIDDLE_UP;
1472 }
1473 else if (XButtonEventRChanged(xevent))
1474 {
1475 eventType = wxEVT_RIGHT_UP;
1476 }
1477 else return FALSE;
1478 }
1479 else
1480 {
1481 return FALSE;
1482 }
1483
1484 wxevent.SetEventType(eventType);
1485
1486 wxevent.m_x = XButtonEventGetX(xevent);
1487 wxevent.m_y = XButtonEventGetY(xevent);
1488
1489 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
1490 || (XButtonEventLIsDown(xevent)
1491 && (eventType != wxEVT_LEFT_UP)));
1492 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
1493 || (XButtonEventMIsDown(xevent)
1494 && (eventType != wxEVT_MIDDLE_UP)));
1495 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
1496 || (XButtonEventRIsDown (xevent)
1497 && (eventType != wxEVT_RIGHT_UP)));
1498
1499 wxevent.m_shiftDown = XButtonEventShiftIsDown(xevent);
1500 wxevent.m_controlDown = XButtonEventCtrlIsDown(xevent);
1501 wxevent.m_altDown = XButtonEventAltIsDown(xevent);
1502 wxevent.m_metaDown = XButtonEventMetaIsDown(xevent);
1503
1504 wxevent.SetId(win->GetId());
1505 wxevent.SetEventObject(win);
1506
1507 return TRUE;
1508 }
1509 }
1510 return FALSE;
1511 }
1512
1513 bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Window WXUNUSED(win), XEvent *xevent, bool isAscii)
1514 {
1515 switch (XEventGetType(xevent))
1516 {
1517 case KeyPress:
1518 case KeyRelease:
1519 {
1520 char buf[20];
1521
1522 KeySym keySym;
1523 (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, NULL);
1524 int id = wxCharCodeXToWX (keySym);
1525 // id may be WXK_xxx code - these are outside ASCII range, so we
1526 // can't just use toupper() on id.
1527 // Only change this if we want the raw key that was pressed,
1528 // and don't change it if we want an ASCII value.
1529 if (!isAscii && (id >= 'a' && id <= 'z'))
1530 {
1531 id = id + 'A' - 'a';
1532 }
1533
1534 wxevent.m_shiftDown = XKeyEventShiftIsDown(xevent);
1535 wxevent.m_controlDown = XKeyEventCtrlIsDown(xevent);
1536 wxevent.m_altDown = XKeyEventAltIsDown(xevent);
1537 wxevent.m_metaDown = XKeyEventMetaIsDown(xevent);
1538 wxevent.SetEventObject(win);
1539 wxevent.m_keyCode = id;
1540 wxevent.SetTimestamp(XKeyEventGetTime(xevent));
1541
1542 wxevent.m_x = XKeyEventGetX(xevent);
1543 wxevent.m_y = XKeyEventGetY(xevent);
1544
1545 return id > -1;
1546 }
1547 default:
1548 break;
1549 }
1550 return FALSE;
1551 }
1552
1553 // ----------------------------------------------------------------------------
1554 // Colour stuff
1555 // ----------------------------------------------------------------------------
1556
1557 bool wxWindowX11::SetBackgroundColour(const wxColour& col)
1558 {
1559 wxWindowBase::SetBackgroundColour(col);
1560
1561 Display *xdisplay = (Display*) wxGlobalDisplay();
1562 int xscreen = DefaultScreen( xdisplay );
1563 Colormap cm = DefaultColormap( xdisplay, xscreen );
1564
1565 m_backgroundColour.CalcPixel( (WXColormap) cm );
1566
1567 // We don't set the background colour as we paint
1568 // the background ourselves.
1569 // XSetWindowBackground( xdisplay, (Window) m_clientWindow, m_backgroundColour.GetPixel() );
1570
1571 return TRUE;
1572 }
1573
1574 bool wxWindowX11::SetForegroundColour(const wxColour& col)
1575 {
1576 if ( !wxWindowBase::SetForegroundColour(col) )
1577 return FALSE;
1578
1579 return TRUE;
1580 }
1581
1582 // ----------------------------------------------------------------------------
1583 // global functions
1584 // ----------------------------------------------------------------------------
1585
1586 wxWindow *wxGetActiveWindow()
1587 {
1588 // TODO
1589 wxFAIL_MSG(wxT("Not implemented"));
1590 return NULL;
1591 }
1592
1593 /* static */
1594 wxWindow *wxWindowBase::GetCapture()
1595 {
1596 return (wxWindow *)g_captureWindow;
1597 }
1598
1599
1600 // Find the wxWindow at the current mouse position, returning the mouse
1601 // position.
1602 wxWindow* wxFindWindowAtPointer(wxPoint& pt)
1603 {
1604 return wxFindWindowAtPoint(wxGetMousePosition());
1605 }
1606
1607 // Get the current mouse position.
1608 wxPoint wxGetMousePosition()
1609 {
1610 #if wxUSE_NANOX
1611 /* TODO */
1612 return wxPoint(0, 0);
1613 #else
1614 Display *display = wxGlobalDisplay();
1615 Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
1616 Window rootReturn, childReturn;
1617 int rootX, rootY, winX, winY;
1618 unsigned int maskReturn;
1619
1620 XQueryPointer (display,
1621 rootWindow,
1622 &rootReturn,
1623 &childReturn,
1624 &rootX, &rootY, &winX, &winY, &maskReturn);
1625 return wxPoint(rootX, rootY);
1626 #endif
1627 }
1628
1629
1630 // ----------------------------------------------------------------------------
1631 // wxNoOptimize: switch off size optimization
1632 // ----------------------------------------------------------------------------
1633
1634 int wxNoOptimize::ms_count = 0;
1635
1636
1637 // ----------------------------------------------------------------------------
1638 // wxDCModule
1639 // ----------------------------------------------------------------------------
1640
1641 class wxWinModule : public wxModule
1642 {
1643 public:
1644 bool OnInit();
1645 void OnExit();
1646
1647 private:
1648 DECLARE_DYNAMIC_CLASS(wxWinModule)
1649 };
1650
1651 IMPLEMENT_DYNAMIC_CLASS(wxWinModule, wxModule)
1652
1653 bool wxWinModule::OnInit()
1654 {
1655 Display *xdisplay = wxGlobalDisplay();
1656 int xscreen = DefaultScreen( xdisplay );
1657 Window xroot = RootWindow( xdisplay, xscreen );
1658 g_eraseGC = XCreateGC( xdisplay, xroot, 0, NULL );
1659 XSetFillStyle( xdisplay, g_eraseGC, FillSolid );
1660
1661 return TRUE;
1662 }
1663
1664 void wxWinModule::OnExit()
1665 {
1666 Display *xdisplay = wxGlobalDisplay();
1667 XFreeGC( xdisplay, g_eraseGC );
1668 }
1669
1670