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