]> git.saurik.com Git - wxWidgets.git/blame - src/x11/window.cpp
New positioning code, eliminating a lot of extra, unnecessary methods
[wxWidgets.git] / src / x11 / window.cpp
CommitLineData
83df96d6
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: windows.cpp
3// Purpose: wxWindow
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#ifdef __GNUG__
21 #pragma implementation "window.h"
22#endif
23
83df96d6
JS
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/module.h"
40#include "wx/menuitem.h"
41#include "wx/log.h"
42
43#if wxUSE_DRAG_AND_DROP
44 #include "wx/dnd.h"
45#endif
46
bc797f4c 47#include "wx/x11/private.h"
7266b672 48#include "X11/Xutil.h"
83df96d6
JS
49
50#include <string.h>
51
52// ----------------------------------------------------------------------------
53// constants
54// ----------------------------------------------------------------------------
55
56static const int SCROLL_MARGIN = 4;
57
58// ----------------------------------------------------------------------------
59// global variables for this module
60// ----------------------------------------------------------------------------
61
62extern wxHashTable *wxWidgetHashTable;
63static wxWindow* g_captureWindow = NULL;
64
83df96d6
JS
65// ----------------------------------------------------------------------------
66// macros
67// ----------------------------------------------------------------------------
68
69#define event_left_is_down(x) ((x)->xbutton.state & Button1Mask)
70#define event_middle_is_down(x) ((x)->xbutton.state & Button2Mask)
71#define event_right_is_down(x) ((x)->xbutton.state & Button3Mask)
72
73// ----------------------------------------------------------------------------
74// event tables
75// ----------------------------------------------------------------------------
76
bc797f4c 77IMPLEMENT_DYNAMIC_CLASS(wxWindowX11, wxWindowBase)
83df96d6 78
bc797f4c
JS
79BEGIN_EVENT_TABLE(wxWindowX11, wxWindowBase)
80 EVT_SYS_COLOUR_CHANGED(wxWindowX11::OnSysColourChanged)
81 EVT_IDLE(wxWindowX11::OnIdle)
82END_EVENT_TABLE()
83df96d6
JS
83
84// ============================================================================
85// implementation
86// ============================================================================
87
88// ----------------------------------------------------------------------------
89// helper functions
90// ----------------------------------------------------------------------------
91
83df96d6
JS
92// ----------------------------------------------------------------------------
93// constructors
94// ----------------------------------------------------------------------------
95
bc797f4c 96void wxWindowX11::Init()
83df96d6
JS
97{
98 // generic initializations first
99 InitBase();
100
7266b672 101 // X11-specific
b513212d 102 // TODO: prune those that are no longer needed
83df96d6 103 m_needsRefresh = TRUE;
7266b672 104 m_mainWidget = (WXWindow) 0;
83df96d6
JS
105
106 m_button1Pressed =
107 m_button2Pressed =
108 m_button3Pressed = FALSE;
109
110 m_winCaptured = FALSE;
111
112 m_isShown = TRUE;
113 m_isBeingDeleted = FALSE;
114
115 m_hScrollBar =
116 m_vScrollBar =
117 m_borderWidget =
118 m_scrolledWindow =
7266b672 119 m_drawingArea = (WXWindow) 0;
83df96d6
JS
120
121 m_hScroll =
122 m_vScroll = FALSE;
123
124 m_scrollPosX =
125 m_scrollPosY = 0;
126
127 m_backingPixmap = (WXPixmap) 0;
128 m_pixmapWidth =
129 m_pixmapHeight = 0;
130
131 m_pixmapOffsetX =
132 m_pixmapOffsetY = 0;
133
134 m_lastTS = 0;
135 m_lastButton = 0;
136 m_canAddEventHandler = FALSE;
b513212d
JS
137
138 m_borderSize = 0;
83df96d6
JS
139}
140
141// real construction (Init() must have been called before!)
bc797f4c 142bool wxWindowX11::Create(wxWindow *parent, wxWindowID id,
83df96d6
JS
143 const wxPoint& pos,
144 const wxSize& size,
145 long style,
146 const wxString& name)
147{
148 wxCHECK_MSG( parent, FALSE, "can't create wxWindow without parent" );
149
150 CreateBase(parent, id, pos, size, style, wxDefaultValidator, name);
151
b513212d
JS
152 if (parent)
153 parent->AddChild(this);
83df96d6
JS
154
155 m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
156 m_foregroundColour = *wxBLACK;
157
b513212d
JS
158 // TODO: How to create more interesting borders?
159 // Will presumably have to create multiple windows.
83df96d6
JS
160 if (style & wxSIMPLE_BORDER)
161 {
b513212d 162 m_borderSize = 1;
83df96d6
JS
163 } else if (style & wxSUNKEN_BORDER)
164 {
b513212d 165 m_borderSize = 1;
83df96d6
JS
166 } else if (style & wxRAISED_BORDER)
167 {
b513212d 168 m_borderSize = 1;
83df96d6
JS
169 }
170
b513212d
JS
171 int w = size.GetWidth();
172 int h = size.GetHeight();
173 int x = size.GetX();
174 int y = size.GetY();
175 int h = size.GetHeight();
176 if (w == -1) w = 10;
177 if (h == -1) h = 10;
178 if (x == -1) x = 0;
179 if (y == -1) y = 0;
83df96d6 180
b513212d
JS
181 int innerWidth = w - 2*m_borderSize;
182 int innerHeight = h - 2*m_borderSize;
183
184 int screen = DefaultScreen(wxGlobalDisplay());
185
186 Window parentWindow;
187 if (parent)
188 parentWindow = (Window) parent->GetClientWindow();
189 else
190 parentWindow = RootWindow(wxGlobalDisplay(), screen);
191
192 Widget window = XCreateSimpleWindow(wxGlobalDisplay(),
193 x, y, innerWidth, innerHeight, borderWidth,
194 m_backgroundColour.AllocColour(wxGlobalDisplay()),
195 m_foregroundColour.AllocColour(wxGlobalDisplay()));
196
197 // Select event types wanted
198 XSelectInput(wxGlobalDisplay(), window,
199 ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
200 ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask |
201 KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask |
202 PropertyChangeMask);
203
204 m_mainWindow = (WXWindow) window;
205
206 wxAddWindowToTable(window, (wxWindow*) this);
207
208 // If a subwindow, show.
209 if (parent && !parent->IsKindOf(CLASSINFO(wxTopLevelWindowX11)) && parent->IsShown())
210 {
211 m_isShown = TRUE;
212 XMapWindow(wxGlobalDisplay(), window);
213 }
83df96d6
JS
214
215 // Without this, the cursor may not be restored properly (e.g. in splitter
216 // sample).
217 SetCursor(*wxSTANDARD_CURSOR);
218 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
219 SetSize(pos.x, pos.y, size.x, size.y);
220
221 return TRUE;
222}
223
224// Destructor
7266b672 225wxWindowX11::~wxWindowX11()
83df96d6
JS
226{
227 if (g_captureWindow == this)
228 g_captureWindow = NULL;
229
230 m_isBeingDeleted = TRUE;
231
7266b672 232 // X11-specific actions first
bc797f4c 233 WXWindow wMain = GetMainWindow();
83df96d6
JS
234 if ( wMain )
235 {
236 // Removes event handlers
bc797f4c 237 //DetachWidget(wMain);
83df96d6
JS
238 }
239
240 ClearUpdateRects();
241
242 if ( m_parent )
243 m_parent->RemoveChild( this );
244
bc797f4c
JS
245 // TODO
246
247#if 0
83df96d6
JS
248 // If m_drawingArea, we're a fully-fledged window with drawing area,
249 // scrollbars etc. (what wxCanvas used to be)
250 if ( m_drawingArea )
251 {
252 // Destroy children before destroying self
253 DestroyChildren();
254
255 if (m_backingPixmap)
256 XFreePixmap (XtDisplay ((Widget) GetMainWidget()), (Pixmap) m_backingPixmap);
257
258 Widget w = (Widget) m_drawingArea;
259 wxDeleteWindowFromTable(w);
260
261 if (w)
262 {
263 XtDestroyWidget(w);
264 m_drawingArea = (WXWidget) 0;
265 }
266
267 // Only if we're _really_ a canvas (not a dialog box/panel)
268 if (m_scrolledWindow)
269 {
270 wxDeleteWindowFromTable((Widget) m_scrolledWindow);
271 }
272
273 if (m_hScrollBar)
274 {
275 wxDeleteWindowFromTable((Widget) m_hScrollBar);
276 XtUnmanageChild((Widget) m_hScrollBar);
277 }
278 if (m_vScrollBar)
279 {
280 wxDeleteWindowFromTable((Widget) m_vScrollBar);
281 XtUnmanageChild((Widget) m_vScrollBar);
282 }
283
284 if (m_hScrollBar)
285 XtDestroyWidget((Widget) m_hScrollBar);
286 if (m_vScrollBar)
287 XtDestroyWidget((Widget) m_vScrollBar);
288
289 UnmanageAndDestroy(m_scrolledWindow);
290
291 if (m_borderWidget)
292 {
293 XtDestroyWidget ((Widget) m_borderWidget);
294 m_borderWidget = (WXWidget) 0;
295 }
296 }
297 else // Why wasn't this here before? JACS 8/3/2000
bc797f4c 298#endif
83df96d6
JS
299 DestroyChildren();
300
301
302 // Destroy the window
bc797f4c
JS
303 if (GetMainWindow())
304 {
b513212d
JS
305 XSelectInput(wxGlobalDisplay(), (Window) GetMainWindow(),
306 NoEventMask);
307 wxDeleteWindowFromTable((Window) GetMainWindow());
308 XDestroyWindow((Window) GetMainWindow());
bc797f4c 309 SetMainWindow((WXWindow) NULL);
83df96d6
JS
310 }
311}
312
313// ----------------------------------------------------------------------------
314// scrollbar management
315// ----------------------------------------------------------------------------
316
317// Helper function
bc797f4c 318void wxWindowX11::CreateScrollbar(wxOrientation orientation)
83df96d6 319{
bc797f4c
JS
320 // TODO
321#if 0
83df96d6
JS
322 wxCHECK_RET( m_drawingArea, "this window can't have scrollbars" );
323
324 XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_NONE, NULL);
325
326 // Add scrollbars if required
327 if (orientation == wxHORIZONTAL)
328 {
329 Widget hScrollBar = XtVaCreateManagedWidget ("hsb",
330 xmScrollBarWidgetClass, (Widget) m_scrolledWindow,
331 XmNorientation, XmHORIZONTAL,
332 NULL);
333 XtAddCallback (hScrollBar, XmNvalueChangedCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
334 XtAddCallback (hScrollBar, XmNdragCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
335 XtAddCallback (hScrollBar, XmNincrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
336 XtAddCallback (hScrollBar, XmNdecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
337 XtAddCallback (hScrollBar, XmNpageIncrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
338 XtAddCallback (hScrollBar, XmNpageDecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
339 XtAddCallback (hScrollBar, XmNtoTopCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
340 XtAddCallback (hScrollBar, XmNtoBottomCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
341
342 XtVaSetValues (hScrollBar,
343 XmNincrement, 1,
344 XmNvalue, 0,
345 NULL);
346
347 m_hScrollBar = (WXWidget) hScrollBar;
348
349 wxColour backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
350 DoChangeBackgroundColour(m_hScrollBar, backgroundColour, TRUE);
351
352 XtRealizeWidget(hScrollBar);
353
354 XtVaSetValues((Widget) m_scrolledWindow,
355 XmNhorizontalScrollBar, (Widget) m_hScrollBar,
356 NULL);
357
358 m_hScroll = TRUE;
359
360 wxAddWindowToTable( hScrollBar, this );
361 }
362
363 if (orientation == wxVERTICAL)
364 {
365 Widget vScrollBar = XtVaCreateManagedWidget ("vsb",
366 xmScrollBarWidgetClass, (Widget) m_scrolledWindow,
367 XmNorientation, XmVERTICAL,
368 NULL);
369 XtAddCallback (vScrollBar, XmNvalueChangedCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
370 XtAddCallback (vScrollBar, XmNdragCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
371 XtAddCallback (vScrollBar, XmNincrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
372 XtAddCallback (vScrollBar, XmNdecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
373 XtAddCallback (vScrollBar, XmNpageIncrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
374 XtAddCallback (vScrollBar, XmNpageDecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
375 XtAddCallback (vScrollBar, XmNtoTopCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
376 XtAddCallback (vScrollBar, XmNtoBottomCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
377
378 XtVaSetValues (vScrollBar,
379 XmNincrement, 1,
380 XmNvalue, 0,
381 NULL);
382
383 m_vScrollBar = (WXWidget) vScrollBar;
384 wxColour backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
385 DoChangeBackgroundColour(m_vScrollBar, backgroundColour, TRUE);
386
387 XtRealizeWidget(vScrollBar);
388
389 XtVaSetValues((Widget) m_scrolledWindow,
390 XmNverticalScrollBar, (Widget) m_vScrollBar,
391 NULL);
392
393 m_vScroll = TRUE;
394
395 wxAddWindowToTable( vScrollBar, this );
396 }
397
398 XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_ANY, NULL);
bc797f4c 399#endif
83df96d6
JS
400}
401
bc797f4c 402void wxWindowX11::DestroyScrollbar(wxOrientation orientation)
83df96d6 403{
bc797f4c
JS
404 // TODO
405#if 0
83df96d6
JS
406 wxCHECK_RET( m_drawingArea, "this window can't have scrollbars" );
407
408 XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_NONE, NULL);
409 // Add scrollbars if required
410 if (orientation == wxHORIZONTAL)
411 {
412 if (m_hScrollBar)
413 {
414 wxDeleteWindowFromTable((Widget)m_hScrollBar);
415 XtDestroyWidget((Widget) m_hScrollBar);
416 }
417 m_hScrollBar = (WXWidget) 0;
418 m_hScroll = FALSE;
419
420 XtVaSetValues((Widget) m_scrolledWindow,
421 XmNhorizontalScrollBar, (Widget) 0,
422 NULL);
423
424 }
425
426 if (orientation == wxVERTICAL)
427 {
428 if (m_vScrollBar)
429 {
430 wxDeleteWindowFromTable((Widget)m_vScrollBar);
431 XtDestroyWidget((Widget) m_vScrollBar);
432 }
433 m_vScrollBar = (WXWidget) 0;
434 m_vScroll = FALSE;
435
436 XtVaSetValues((Widget) m_scrolledWindow,
437 XmNverticalScrollBar, (Widget) 0,
438 NULL);
439
440 }
441 XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_ANY, NULL);
bc797f4c 442#endif
83df96d6
JS
443}
444
445// ---------------------------------------------------------------------------
446// basic operations
447// ---------------------------------------------------------------------------
448
bc797f4c 449void wxWindowX11::SetFocus()
83df96d6 450{
b513212d
JS
451 Window wMain = (Window) GetMainWidget();
452 if (wMain)
453 {
454 XSetInputFocus(wxGlobalDisplay(), wMain, RevertToParent, CurrentTime);
455
456 XWMHints wmhints;
457 wmhints.flags = InputHint;
458 wmhints.input = True;
459 XSetWMHints(wxGlobalDisplay(), wMain, &wmhints)
460 }
83df96d6
JS
461}
462
463// Get the window with the focus
464wxWindow *wxWindowBase::FindFocus()
465{
b513212d
JS
466 Window wFocus = (Window) 0;
467 int revert = 0;
bc797f4c 468
b513212d
JS
469 XGetInputFocus(wxGlobalDisplay(), & wFocus, & revert);
470 if (wFocus)
83df96d6 471 {
b513212d
JS
472 wxWindow *win = NULL;
473 do
83df96d6 474 {
b513212d
JS
475 win = wxGetWindowFromTable(wFocus);
476 wFocus = wxGetWindowParent(wFocus);
477 } while (wFocus && !win);
478
479 return win;
83df96d6
JS
480 }
481
b513212d 482 return NULL;
83df96d6
JS
483}
484
b513212d
JS
485// Enabling/disabling handled by event loop, and not sending events
486// if disabled.
bc797f4c 487bool wxWindowX11::Enable(bool enable)
83df96d6
JS
488{
489 if ( !wxWindowBase::Enable(enable) )
490 return FALSE;
b513212d 491
83df96d6
JS
492 return TRUE;
493}
494
bc797f4c 495bool wxWindowX11::Show(bool show)
83df96d6
JS
496{
497 if ( !wxWindowBase::Show(show) )
498 return FALSE;
499
83df96d6
JS
500 Window xwin = (Window) GetXWindow();
501 Display *xdisp = (Display*) GetXDisplay();
502 if (show)
b513212d 503 {
83df96d6 504 XMapWindow(xdisp, xwin);
b513212d 505 }
83df96d6 506 else
b513212d 507 {
83df96d6 508 XUnmapWindow(xdisp, xwin);
b513212d 509 }
83df96d6
JS
510
511 return TRUE;
512}
513
514// Raise the window to the top of the Z order
bc797f4c 515void wxWindowX11::Raise()
83df96d6 516{
7266b672 517 Window window = (Window) GetTopWindow();
bc797f4c 518 if (window)
b513212d 519 XRaiseWindow(wxGlobalDisplay(), window);
83df96d6
JS
520}
521
522// Lower the window to the bottom of the Z order
bc797f4c 523void wxWindowX11::Lower()
83df96d6 524{
7266b672 525 Window window = (Window) GetTopWindow();
bc797f4c 526 if (window)
b513212d 527 XLowerWindow(wxGlobalDisplay(), window);
83df96d6
JS
528}
529
bc797f4c 530void wxWindowX11::DoCaptureMouse()
83df96d6 531{
7266b672 532 g_captureWindow = (wxWindow*) this;
83df96d6
JS
533 if ( m_winCaptured )
534 return;
535
b513212d
JS
536 // TODO: should we also call XGrabButton, XGrabKeyboard?
537 if (GetMainWindow())
538 {
539 int res = XGrabPointer(wxGlobalDisplay(), (Window) GetMainWindow(),
540 FALSE,
541 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask,
542 GrabModeAsync,
543 GrabModeAsync,
544 None,
545 None, /* cursor */ // TODO: This may need to be set to the cursor of this window
546 CurrentTime);
547
548 if (res == GrabSuccess)
549 {
550 m_winCaptured = TRUE;
551 }
552 }
83df96d6
JS
553}
554
bc797f4c 555void wxWindowX11::DoReleaseMouse()
83df96d6
JS
556{
557 g_captureWindow = NULL;
558 if ( !m_winCaptured )
559 return;
560
561 Widget wMain = (Widget)GetMainWidget();
b513212d
JS
562
563 // TODO: should we also call XUngrabButton, XUngrabKeyboard?
83df96d6 564 if ( wMain )
b513212d 565 XUngrabPointer(wxGlobalDisplay(), wMain);
83df96d6
JS
566
567 m_winCaptured = FALSE;
568}
569
bc797f4c 570bool wxWindowX11::SetFont(const wxFont& font)
83df96d6
JS
571{
572 if ( !wxWindowBase::SetFont(font) )
573 {
574 // nothing to do
575 return FALSE;
576 }
577
578 ChangeFont();
579
580 return TRUE;
581}
582
bc797f4c 583bool wxWindowX11::SetCursor(const wxCursor& cursor)
83df96d6
JS
584{
585 if ( !wxWindowBase::SetCursor(cursor) )
586 {
587 // no change
588 return FALSE;
589 }
590
83df96d6
JS
591 wxCursor* cursor2 = NULL;
592 if (m_cursor.Ok())
593 cursor2 = & m_cursor;
594 else
595 cursor2 = wxSTANDARD_CURSOR;
596
597 WXDisplay *dpy = GetXDisplay();
598 WXCursor x_cursor = cursor2->GetXCursor(dpy);
599
bc797f4c 600 Window win = (Window) GetMainWindow();
83df96d6
JS
601 XDefineCursor((Display*) dpy, win, (Cursor) x_cursor);
602
603 return TRUE;
604}
605
606// Coordinates relative to the window
bc797f4c 607void wxWindowX11::WarpPointer (int x, int y)
83df96d6 608{
bc797f4c 609 Window wClient = (Window) GetClientWindow();
83df96d6 610
b513212d 611 XWarpPointer(wxGlobalDisplay(), None, wClient, 0, 0, 0, 0, x, y);
83df96d6
JS
612}
613
614// ---------------------------------------------------------------------------
615// scrolling stuff
616// ---------------------------------------------------------------------------
617
bc797f4c 618int wxWindowX11::GetScrollPos(int orient) const
83df96d6
JS
619{
620 if (orient == wxHORIZONTAL)
621 return m_scrollPosX;
622 else
623 return m_scrollPosY;
83df96d6
JS
624}
625
626// This now returns the whole range, not just the number of positions that we
627// can scroll.
bc797f4c 628int wxWindowX11::GetScrollRange(int WXUNUSED(orient)) const
83df96d6 629{
bc797f4c
JS
630 // TODO
631 return 0;
632#if 0
83df96d6
JS
633 Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
634 wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
635
636 int range;
637 XtVaGetValues(scrollBar, XmNmaximum, &range, NULL);
638 return range;
bc797f4c 639#endif
83df96d6
JS
640}
641
bc797f4c 642int wxWindowX11::GetScrollThumb(int orient) const
83df96d6 643{
bc797f4c
JS
644 // TODO
645 return 0;
646
647#if 0
83df96d6
JS
648 Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
649 wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
650
651 int thumb;
652 XtVaGetValues(scrollBar, XmNsliderSize, &thumb, NULL);
653 return thumb;
bc797f4c 654#endif
83df96d6
JS
655}
656
7266b672 657void wxWindowX11::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
83df96d6 658{
bc797f4c
JS
659 // TODO
660
661#if 0
83df96d6
JS
662 Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
663
664 if ( scrollBar )
665 {
666 XtVaSetValues (scrollBar, XmNvalue, pos, NULL);
667 }
bc797f4c 668#endif
83df96d6
JS
669 SetInternalScrollPos((wxOrientation)orient, pos);
670}
671
672// New function that will replace some of the above.
bc797f4c
JS
673void wxWindowX11::SetScrollbar(int WXUNUSED(orient), int WXUNUSED(pos), int WXUNUSED(thumbVisible),
674 int WXUNUSED(range), bool WXUNUSED(refresh))
83df96d6 675{
bc797f4c
JS
676 // TODO
677#if 0
83df96d6
JS
678 int oldW, oldH;
679 GetSize(& oldW, & oldH);
680
681 if (range == 0)
682 range = 1;
683 if (thumbVisible == 0)
684 thumbVisible = 1;
685
686 if (thumbVisible > range)
687 thumbVisible = range;
688
689 // Save the old state to see if it changed
690 WXWidget oldScrollBar = GetScrollbar((wxOrientation)orient);
691
692 if (orient == wxHORIZONTAL)
693 {
694 if (thumbVisible == range)
695 {
696 if (m_hScrollBar)
697 DestroyScrollbar(wxHORIZONTAL);
698 }
699 else
700 {
701 if (!m_hScrollBar)
702 CreateScrollbar(wxHORIZONTAL);
703 }
704 }
705 if (orient == wxVERTICAL)
706 {
707 if (thumbVisible == range)
708 {
709 if (m_vScrollBar)
710 DestroyScrollbar(wxVERTICAL);
711 }
712 else
713 {
714 if (!m_vScrollBar)
715 CreateScrollbar(wxVERTICAL);
716 }
717 }
718 WXWidget newScrollBar = GetScrollbar((wxOrientation)orient);
719
720 if (oldScrollBar != newScrollBar)
721 {
722 // This is important! Without it, scrollbars misbehave badly.
723 XtUnrealizeWidget((Widget) m_scrolledWindow);
724 XmScrolledWindowSetAreas ((Widget) m_scrolledWindow, (Widget) m_hScrollBar, (Widget) m_vScrollBar, (Widget) m_drawingArea);
725 XtRealizeWidget((Widget) m_scrolledWindow);
726 XtManageChild((Widget) m_scrolledWindow);
727 }
728
729 if (newScrollBar)
730 {
731 XtVaSetValues((Widget) newScrollBar,
732 XmNvalue, pos,
733 XmNminimum, 0,
734 XmNmaximum, range,
735 XmNsliderSize, thumbVisible,
736 NULL);
737 }
738
739 SetInternalScrollPos((wxOrientation)orient, pos);
740
741 int newW, newH;
742 GetSize(& newW, & newH);
743
744 // Adjusting scrollbars can resize the canvas accidentally
745 if (newW != oldW || newH != oldH)
746 SetSize(-1, -1, oldW, oldH);
bc797f4c 747#endif
83df96d6
JS
748}
749
750// Does a physical scroll
bc797f4c 751void wxWindowX11::ScrollWindow(int dx, int dy, const wxRect *rect)
83df96d6
JS
752{
753 int x, y, w, h;
754 if (rect)
755 {
756 // Use specified rectangle
757 x = rect->x; y = rect->y; w = rect->width; h = rect->height;
758 }
759 else
760 {
761 // Use whole client area
762 x = 0; y = 0;
763 GetClientSize(& w, & h);
764 }
bc797f4c 765
83df96d6
JS
766 wxNode *cnode = m_children.First();
767 while (cnode)
768 {
769 wxWindow *child = (wxWindow*) cnode->Data();
bc797f4c
JS
770 int sx = 0;
771 int sy = 0;
772 child->GetSize( &sx, &sy );
83df96d6 773 wxPoint pos( child->GetPosition() );
bc797f4c
JS
774 child->SetSize( pos.x + dx, pos.y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
775 cnode = cnode->Next();
83df96d6 776 }
bc797f4c 777
83df96d6
JS
778 int x1 = (dx >= 0) ? x : x - dx;
779 int y1 = (dy >= 0) ? y : y - dy;
780 int w1 = w - abs(dx);
781 int h1 = h - abs(dy);
782 int x2 = (dx >= 0) ? x + dx : x;
783 int y2 = (dy >= 0) ? y + dy : y;
bc797f4c 784
7266b672 785 wxClientDC dc((wxWindow*) this);
bc797f4c 786
83df96d6 787 dc.SetLogicalFunction (wxCOPY);
bc797f4c
JS
788
789 Window window = (Window) GetMainWindow();
b513212d 790 Display* display = wxGlobalDisplay();
bc797f4c 791
83df96d6 792 XCopyArea(display, window, window, (GC) dc.GetGC(),
bc797f4c
JS
793 x1, y1, w1, h1, x2, y2);
794
83df96d6
JS
795 dc.SetAutoSetting(TRUE);
796 wxBrush brush(GetBackgroundColour(), wxSOLID);
797 dc.SetBrush(brush); // FIXME: needed?
bc797f4c 798
83df96d6
JS
799 // We'll add rectangles to the list of update rectangles according to which
800 // bits we've exposed.
801 wxList updateRects;
bc797f4c 802
83df96d6
JS
803 if (dx > 0)
804 {
805 wxRect *rect = new wxRect;
806 rect->x = x;
807 rect->y = y;
808 rect->width = dx;
809 rect->height = h;
bc797f4c 810
83df96d6
JS
811 XFillRectangle(display, window,
812 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
bc797f4c 813
83df96d6
JS
814 rect->x = rect->x;
815 rect->y = rect->y;
816 rect->width = rect->width;
817 rect->height = rect->height;
bc797f4c 818
83df96d6
JS
819 updateRects.Append((wxObject*) rect);
820 }
821 else if (dx < 0)
822 {
823 wxRect *rect = new wxRect;
bc797f4c 824
83df96d6
JS
825 rect->x = x + w + dx;
826 rect->y = y;
827 rect->width = -dx;
828 rect->height = h;
bc797f4c 829
83df96d6
JS
830 XFillRectangle(display, window,
831 (GC) dc.GetGC(), rect->x, rect->y, rect->width,
832 rect->height);
bc797f4c 833
83df96d6
JS
834 rect->x = rect->x;
835 rect->y = rect->y;
836 rect->width = rect->width;
837 rect->height = rect->height;
bc797f4c 838
83df96d6
JS
839 updateRects.Append((wxObject*) rect);
840 }
841 if (dy > 0)
842 {
843 wxRect *rect = new wxRect;
bc797f4c 844
83df96d6
JS
845 rect->x = x;
846 rect->y = y;
847 rect->width = w;
848 rect->height = dy;
bc797f4c 849
83df96d6
JS
850 XFillRectangle(display, window,
851 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
bc797f4c 852
83df96d6
JS
853 rect->x = rect->x;
854 rect->y = rect->y;
855 rect->width = rect->width;
856 rect->height = rect->height;
bc797f4c 857
83df96d6
JS
858 updateRects.Append((wxObject*) rect);
859 }
860 else if (dy < 0)
861 {
862 wxRect *rect = new wxRect;
bc797f4c 863
83df96d6
JS
864 rect->x = x;
865 rect->y = y + h + dy;
866 rect->width = w;
867 rect->height = -dy;
bc797f4c 868
83df96d6
JS
869 XFillRectangle(display, window,
870 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
bc797f4c 871
83df96d6
JS
872 rect->x = rect->x;
873 rect->y = rect->y;
874 rect->width = rect->width;
875 rect->height = rect->height;
bc797f4c 876
83df96d6
JS
877 updateRects.Append((wxObject*) rect);
878 }
879 dc.SetBrush(wxNullBrush);
bc797f4c 880
83df96d6 881 // Now send expose events
bc797f4c 882
83df96d6
JS
883 wxNode* node = updateRects.First();
884 while (node)
885 {
886 wxRect* rect = (wxRect*) node->Data();
887 XExposeEvent event;
bc797f4c 888
83df96d6
JS
889 event.type = Expose;
890 event.display = display;
891 event.send_event = True;
892 event.window = window;
bc797f4c 893
83df96d6
JS
894 event.x = rect->x;
895 event.y = rect->y;
896 event.width = rect->width;
897 event.height = rect->height;
bc797f4c 898
83df96d6 899 event.count = 0;
bc797f4c 900
83df96d6 901 XSendEvent(display, window, False, ExposureMask, (XEvent *)&event);
bc797f4c 902
83df96d6 903 node = node->Next();
bc797f4c 904
83df96d6 905 }
bc797f4c 906
83df96d6
JS
907 // Delete the update rects
908 node = updateRects.First();
909 while (node)
910 {
911 wxRect* rect = (wxRect*) node->Data();
912 delete rect;
913 node = node->Next();
914 }
bc797f4c
JS
915
916 // TODO
83df96d6 917
bc797f4c 918 // XmUpdateDisplay((Widget) GetMainWidget());
83df96d6
JS
919}
920
921// ---------------------------------------------------------------------------
922// drag and drop
923// ---------------------------------------------------------------------------
924
925#if wxUSE_DRAG_AND_DROP
926
bc797f4c 927void wxWindowX11::SetDropTarget(wxDropTarget * WXUNUSED(pDropTarget))
83df96d6
JS
928{
929 // TODO
930}
931
932#endif
933
934// Old style file-manager drag&drop
bc797f4c 935void wxWindowX11::DragAcceptFiles(bool WXUNUSED(accept))
83df96d6
JS
936{
937 // TODO
938}
939
940// ----------------------------------------------------------------------------
941// tooltips
942// ----------------------------------------------------------------------------
943
944#if wxUSE_TOOLTIPS
945
bc797f4c 946void wxWindowX11::DoSetToolTip(wxToolTip * WXUNUSED(tooltip))
83df96d6
JS
947{
948 // TODO
949}
950
951#endif // wxUSE_TOOLTIPS
952
83df96d6
JS
953// ---------------------------------------------------------------------------
954// moving and resizing
955// ---------------------------------------------------------------------------
956
bc797f4c 957bool wxWindowX11::PreResize()
83df96d6
JS
958{
959 return TRUE;
960}
961
962// Get total size
bc797f4c 963void wxWindowX11::DoGetSize(int *x, int *y) const
83df96d6 964{
b513212d
JS
965 Window window = (Window) GetTopWindow();
966 if (window)
83df96d6 967 {
b513212d
JS
968 XWindowAttributes attr;
969 Status status = XGetWindowAttributes(wxGlobalDisplay(), window, & attr);
970 wxASSERT(status);
971
972 if (status)
973 {
974 *x = attr.width + 2*m_borderSize;
975 *y = attr.height + 2*m_borderSize;
976 }
83df96d6 977 }
83df96d6
JS
978}
979
bc797f4c 980void wxWindowX11::DoGetPosition(int *x, int *y) const
83df96d6 981{
b513212d
JS
982 Window window = (Window) GetTopWindow();
983 if (window)
83df96d6 984 {
b513212d
JS
985 XWindowAttributes attr;
986 Status status = XGetWindowAttributes(wxGlobalDisplay(), window, & attr);
987 wxASSERT(status);
988
989 if (status)
990 {
991 *x = attr.x;
992 *y = attr.y;
993
994 // We may be faking the client origin. So a window that's really at (0, 30)
995 // may appear (to wxWin apps) to be at (0, 0).
996 if (GetParent())
997 {
998 wxPoint pt(GetParent()->GetClientAreaOrigin());
999 *x -= pt.x;
1000 *y -= pt.y;
1001 }
1002 }
83df96d6 1003 }
83df96d6
JS
1004}
1005
bc797f4c 1006void wxWindowX11::DoScreenToClient(int *x, int *y) const
83df96d6 1007{
b513212d 1008 Display *display = wxGlobalDisplay();
bc797f4c
JS
1009 Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display));
1010 Window thisWindow = (Window) GetClientWindow();
83df96d6
JS
1011
1012 Window childWindow;
1013 int xx = *x;
1014 int yy = *y;
1015 XTranslateCoordinates(display, rootWindow, thisWindow, xx, yy, x, y, &childWindow);
1016}
1017
bc797f4c 1018void wxWindowX11::DoClientToScreen(int *x, int *y) const
83df96d6 1019{
b513212d 1020 Display *display = wxGlobalDisplay();
bc797f4c
JS
1021 Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display));
1022 Window thisWindow = (Window) GetClientWindow();
83df96d6
JS
1023
1024 Window childWindow;
1025 int xx = *x;
1026 int yy = *y;
1027 XTranslateCoordinates(display, thisWindow, rootWindow, xx, yy, x, y, &childWindow);
1028}
1029
1030
1031// Get size *available for subwindows* i.e. excluding menu bar etc.
bc797f4c 1032void wxWindowX11::DoGetClientSize(int *x, int *y) const
83df96d6 1033{
b513212d
JS
1034 Window window = (Window) GetClientWindow();
1035
1036 if (window)
1037 {
1038 XWindowAttributes attr;
1039 Status status = XGetWindowAttributes(wxGlobalDisplay(), window, & attr);
1040 wxASSERT(status);
1041
1042 if (status)
1043 {
1044 *x = attr.width ;
1045 *y = attr.height ;
1046 }
1047 }
83df96d6
JS
1048}
1049
bc797f4c 1050void wxWindowX11::DoSetSize(int x, int y, int width, int height, int sizeFlags)
83df96d6 1051{
b513212d
JS
1052 if (!GetMainWindow())
1053 return;
83df96d6 1054
b513212d
JS
1055 XWindowChanges windowChanges;
1056 int valueMask = 0;
1057
1058 if (x != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
83df96d6 1059 {
b513212d
JS
1060 windowChanges.x = x;
1061 valueMask |= CWX;
83df96d6 1062 }
b513212d 1063 if (y != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
83df96d6 1064 {
b513212d
JS
1065 windowChanges.y = y;
1066 valueMask |= CWY;
83df96d6 1067 }
b513212d 1068 if (width != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
83df96d6 1069 {
b513212d
JS
1070 windowChanges.width = width - m_borderSize*2;
1071 valueMask |= CWWidth;
83df96d6 1072 }
b513212d
JS
1073 if (height != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
1074 {
1075 windowChanges.height = height - m_borderSize*2;
1076 valueMask |= CWHeight;
1077 }
1078 AdjustForParentClientOrigin(valueMask.x, valueMask.y, sizeFlags);
1079
1080 XConfigureWindow(wxGlobalDisplay(), (Window) GetMainWindow(),
1081 valueMask, & windowChanges);
83df96d6
JS
1082}
1083
bc797f4c 1084void wxWindowX11::DoSetClientSize(int width, int height)
83df96d6 1085{
b513212d 1086 if (!GetMainWindow())
83df96d6 1087 return;
83df96d6 1088
b513212d
JS
1089 XWindowChanges windowChanges;
1090 int valueMask = 0;
83df96d6 1091
b513212d
JS
1092 if (width != -1)
1093 {
1094 windowChanges.width = width ;
1095 valueMask |= CWWidth;
1096 }
1097 if (height != -1)
1098 {
1099 windowChanges.height = height ;
1100 valueMask |= CWHeight;
1101 }
1102 XConfigureWindow(wxGlobalDisplay(), (Window) GetMainWindow(),
1103 valueMask, & windowChanges);
83df96d6
JS
1104}
1105
1106// For implementation purposes - sometimes decorations make the client area
1107// smaller
bc797f4c 1108wxPoint wxWindowX11::GetClientAreaOrigin() const
83df96d6
JS
1109{
1110 return wxPoint(0, 0);
1111}
1112
1113// Makes an adjustment to the window position (for example, a frame that has
1114// a toolbar that it manages itself).
bc797f4c 1115void wxWindowX11::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags)
83df96d6
JS
1116{
1117 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
1118 {
1119 wxPoint pt(GetParent()->GetClientAreaOrigin());
1120 x += pt.x; y += pt.y;
1121 }
1122}
1123
bc797f4c 1124void wxWindowX11::SetSizeHints(int minW, int minH, int maxW, int maxH, int incW, int incH)
83df96d6
JS
1125{
1126 m_minWidth = minW;
1127 m_minHeight = minH;
1128 m_maxWidth = maxW;
1129 m_maxHeight = maxH;
1130
b513212d
JS
1131 XSizeHints sizeHints;
1132 sizeHints.flags = 0;
1133
1134 if (minW > -1 && minH > -1)
83df96d6 1135 {
b513212d
JS
1136 sizeHints.flags |= PMinSize;
1137 sizeHints.min_width = minW;
1138 sizeHints.min_height = minH;
1139 }
1140 if (maxW > -1 && maxH > -1)
1141 {
1142 sizeHints.flags |= PMaxSize;
1143 sizeHints.max_width = maxW;
1144 sizeHints.max_height = maxH;
1145 }
1146 if (incW > -1 && incH > -1)
1147 {
1148 sizeHints.flags |= PResizeInc;
1149 sizeHints.width_inc = incW;
1150 sizeHints.height_inc = incH;
83df96d6
JS
1151 }
1152
b513212d 1153 XSetWMNormalHints(wxGlobalDisplay(), (Window) GetMainWindow(), & sizeHints)
83df96d6
JS
1154}
1155
bc797f4c 1156void wxWindowX11::DoMoveWindow(int x, int y, int width, int height)
83df96d6 1157{
b513212d 1158 DoSetSize(x, y, width, height);
83df96d6
JS
1159}
1160
1161// ---------------------------------------------------------------------------
1162// text metrics
1163// ---------------------------------------------------------------------------
1164
bc797f4c 1165int wxWindowX11::GetCharHeight() const
83df96d6
JS
1166{
1167 wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
1168
1169 WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, GetXDisplay());
1170
1171 int direction, ascent, descent;
1172 XCharStruct overall;
1173 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1174 &descent, &overall);
1175
1176 // return (overall.ascent + overall.descent);
1177 return (ascent + descent);
1178}
1179
bc797f4c 1180int wxWindowX11::GetCharWidth() const
83df96d6
JS
1181{
1182 wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
1183
1184 WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, GetXDisplay());
1185
1186 int direction, ascent, descent;
1187 XCharStruct overall;
1188 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1189 &descent, &overall);
1190
1191 return overall.width;
1192}
1193
bc797f4c 1194void wxWindowX11::GetTextExtent(const wxString& string,
83df96d6
JS
1195 int *x, int *y,
1196 int *descent, int *externalLeading,
1197 const wxFont *theFont) const
1198{
1199 wxFont *fontToUse = (wxFont *)theFont;
1200 if (!fontToUse)
1201 fontToUse = (wxFont *) & m_font;
1202
1203 wxCHECK_RET( fontToUse->Ok(), "valid window font needed" );
1204
1205 WXFontStructPtr pFontStruct = theFont->GetFontStruct(1.0, GetXDisplay());
1206
1207 int direction, ascent, descent2;
1208 XCharStruct overall;
1209 int slen = string.Len();
1210
1211#if 0
1212 if (use16)
1213 XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
1214 &ascent, &descent2, &overall);
1215#endif
1216
1217 XTextExtents((XFontStruct*) pFontStruct, string, slen,
1218 &direction, &ascent, &descent2, &overall);
1219
1220 if ( x )
1221 *x = (overall.width);
1222 if ( y )
1223 *y = (ascent + descent2);
1224 if (descent)
1225 *descent = descent2;
1226 if (externalLeading)
1227 *externalLeading = 0;
1228
1229}
1230
1231// ----------------------------------------------------------------------------
1232// painting
1233// ----------------------------------------------------------------------------
1234
bc797f4c 1235void wxWindowX11::Refresh(bool eraseBack, const wxRect *rect)
83df96d6
JS
1236{
1237 m_needsRefresh = TRUE;
b513212d 1238 Display *display = wxGlobalDisplay();
7266b672 1239 Window thisWindow = (Window) GetMainWindow();
83df96d6
JS
1240
1241 XExposeEvent dummyEvent;
1242 int width, height;
1243 GetSize(&width, &height);
1244
1245 dummyEvent.type = Expose;
1246 dummyEvent.display = display;
1247 dummyEvent.send_event = True;
1248 dummyEvent.window = thisWindow;
1249 if (rect)
1250 {
1251 dummyEvent.x = rect->x;
1252 dummyEvent.y = rect->y;
1253 dummyEvent.width = rect->width;
1254 dummyEvent.height = rect->height;
1255 }
1256 else
1257 {
1258 dummyEvent.x = 0;
1259 dummyEvent.y = 0;
1260 dummyEvent.width = width;
1261 dummyEvent.height = height;
1262 }
1263 dummyEvent.count = 0;
1264
1265 if (eraseBack)
1266 {
7266b672 1267 wxClientDC dc((wxWindow*) this);
83df96d6
JS
1268 wxBrush backgroundBrush(GetBackgroundColour(), wxSOLID);
1269 dc.SetBackground(backgroundBrush);
1270 if (rect)
1271 dc.Clear(*rect);
1272 else
1273 dc.Clear();
1274 }
1275
1276 XSendEvent(display, thisWindow, False, ExposureMask, (XEvent *)&dummyEvent);
1277}
1278
bc797f4c 1279void wxWindowX11::Clear()
83df96d6 1280{
7266b672 1281 wxClientDC dc((wxWindow*) this);
83df96d6
JS
1282 wxBrush brush(GetBackgroundColour(), wxSOLID);
1283 dc.SetBackground(brush);
1284 dc.Clear();
1285}
1286
bc797f4c 1287void wxWindowX11::ClearUpdateRects()
83df96d6
JS
1288{
1289 wxRectList::Node* node = m_updateRects.GetFirst();
1290 while (node)
1291 {
1292 wxRect* rect = node->GetData();
1293 delete rect;
1294 node = node->GetNext();
1295 }
1296
1297 m_updateRects.Clear();
1298}
1299
bc797f4c 1300void wxWindowX11::DoPaint()
83df96d6 1301{
bc797f4c
JS
1302 // Set an erase event first
1303 wxEraseEvent eraseEvent(GetId());
1304 eraseEvent.SetEventObject(this);
1305 GetEventHandler()->ProcessEvent(eraseEvent);
1306
1307 wxPaintEvent event(GetId());
1308 event.SetEventObject(this);
1309 GetEventHandler()->ProcessEvent(event);
1310
1311 m_needsRefresh = FALSE;
83df96d6
JS
1312}
1313
1314// ----------------------------------------------------------------------------
1315// event handlers
1316// ----------------------------------------------------------------------------
1317
1318// Responds to colour changes: passes event on to children.
bc797f4c 1319void wxWindowX11::OnSysColourChanged(wxSysColourChangedEvent& event)
83df96d6
JS
1320{
1321 wxWindowList::Node *node = GetChildren().GetFirst();
1322 while ( node )
1323 {
1324 // Only propagate to non-top-level windows
1325 wxWindow *win = node->GetData();
1326 if ( win->GetParent() )
1327 {
1328 wxSysColourChangedEvent event2;
1329 event.m_eventObject = win;
1330 win->GetEventHandler()->ProcessEvent(event2);
1331 }
1332
1333 node = node->GetNext();
1334 }
1335}
1336
bc797f4c 1337void wxWindowX11::OnIdle(wxIdleEvent& WXUNUSED(event))
83df96d6
JS
1338{
1339 // This calls the UI-update mechanism (querying windows for
1340 // menu/toolbar/control state information)
1341 UpdateWindowUI();
1342}
1343
1344// ----------------------------------------------------------------------------
1345// accelerators
1346// ----------------------------------------------------------------------------
1347
bc797f4c 1348bool wxWindowX11::ProcessAccelerator(wxKeyEvent& event)
83df96d6
JS
1349{
1350 if (!m_acceleratorTable.Ok())
1351 return FALSE;
1352
7266b672
JS
1353 const wxAcceleratorEntry* entry = m_acceleratorTable.GetEntry(event);
1354 if (entry)
83df96d6 1355 {
83df96d6
JS
1356 // Bingo, we have a match. Now find a control that matches the
1357 // entry command id.
1358
1359 // Need to go up to the top of the window hierarchy, since it might
1360 // be e.g. a menu item
7266b672 1361 wxWindow* parent = (wxWindow*) this;
83df96d6
JS
1362 while ( parent && !parent->IsTopLevel() )
1363 parent = parent->GetParent();
1364
1365 if (!parent)
1366 return FALSE;
1367
1368 wxFrame* frame = wxDynamicCast(parent, wxFrame);
1369 if ( frame )
1370 {
1371 // Try for a menu command
1372 if (frame->GetMenuBar())
1373 {
1374 wxMenuItem* item = frame->GetMenuBar()->FindItem(entry->GetCommand());
1375 if (item)
1376 {
1377 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, entry->GetCommand());
1378 commandEvent.SetEventObject(frame);
1379
1380 // If ProcessEvent returns TRUE (it was handled), then
1381 // the calling code will skip the event handling.
1382 return frame->GetEventHandler()->ProcessEvent(commandEvent);
1383 }
1384 }
1385 }
1386
1387 // Find a child matching the command id
1388 wxWindow* child = parent->FindWindow(entry->GetCommand());
1389
1390 // No such child
1391 if (!child)
1392 return FALSE;
1393
1394 // Now we process those kinds of windows that we can.
1395 // For now, only buttons.
1396 if ( wxDynamicCast(child, wxButton) )
1397 {
1398 wxCommandEvent commandEvent (wxEVT_COMMAND_BUTTON_CLICKED, child->GetId());
1399 commandEvent.SetEventObject(child);
1400 return child->GetEventHandler()->ProcessEvent(commandEvent);
1401 }
1402
1403 return FALSE;
7266b672
JS
1404
1405 }// if
83df96d6
JS
1406
1407 // We didn't match the key event against an accelerator.
1408 return FALSE;
1409}
1410
1411// ============================================================================
bc797f4c 1412// X11-specific stuff from here on
83df96d6
JS
1413// ============================================================================
1414
1415// ----------------------------------------------------------------------------
1416// function which maintain the global hash table mapping Widgets to wxWindows
1417// ----------------------------------------------------------------------------
1418
bc797f4c 1419bool wxAddWindowToTable(Window w, wxWindow *win)
83df96d6
JS
1420{
1421 wxWindow *oldItem = NULL;
1422 if ((oldItem = (wxWindow *)wxWidgetHashTable->Get ((long) w)))
1423 {
1424 wxLogDebug("Widget table clash: new widget is %ld, %s",
1425 (long)w, win->GetClassInfo()->GetClassName());
1426 return FALSE;
1427 }
1428
1429 wxWidgetHashTable->Put((long) w, win);
1430
bc797f4c 1431 wxLogTrace("widget", "XWindow 0x%08x <-> window %p (%s)",
83df96d6
JS
1432 w, win, win->GetClassInfo()->GetClassName());
1433
1434 return TRUE;
1435}
1436
bc797f4c 1437wxWindow *wxGetWindowFromTable(Window w)
83df96d6
JS
1438{
1439 return (wxWindow *)wxWidgetHashTable->Get((long) w);
1440}
1441
bc797f4c 1442void wxDeleteWindowFromTable(Window w)
83df96d6
JS
1443{
1444 wxWidgetHashTable->Delete((long)w);
1445}
1446
1447// ----------------------------------------------------------------------------
1448// add/remove window from the table
1449// ----------------------------------------------------------------------------
1450
83df96d6 1451// ----------------------------------------------------------------------------
bc797f4c 1452// X11-specific accessors
83df96d6
JS
1453// ----------------------------------------------------------------------------
1454
1455// Get the underlying X window
bc797f4c 1456WXWindow wxWindowX11::GetXWindow() const
83df96d6 1457{
bc797f4c 1458 return GetMainWindow();
83df96d6
JS
1459}
1460
1461// Get the underlying X display
bc797f4c 1462WXDisplay *wxWindowX11::GetXDisplay() const
83df96d6 1463{
bc797f4c 1464 return wxGetDisplay();
83df96d6
JS
1465}
1466
bc797f4c 1467WXWindow wxWindowX11::GetMainWindow() const
83df96d6
JS
1468{
1469 if (m_drawingArea)
1470 return m_drawingArea;
1471 else
1472 return m_mainWidget;
1473}
1474
7266b672 1475WXWindow wxWindowX11::GetClientWindow() const
83df96d6 1476{
bc797f4c 1477 if (m_drawingArea != (WXWindow) 0)
83df96d6
JS
1478 return m_drawingArea;
1479 else
bc797f4c 1480 return GetMainWindow();
83df96d6
JS
1481}
1482
bc797f4c 1483WXWindow wxWindowX11::GetTopWindow() const
83df96d6 1484{
bc797f4c 1485 return GetMainWindow();
83df96d6
JS
1486}
1487
bc797f4c 1488WXWindow wxWindowX11::GetLabelWindow() const
83df96d6 1489{
bc797f4c 1490 return GetMainWindow();
83df96d6
JS
1491}
1492
1493// ----------------------------------------------------------------------------
bc797f4c 1494// callbacks
83df96d6
JS
1495// ----------------------------------------------------------------------------
1496
1b0fb34b 1497// TODO: implement wxWindow scrollbar, presumably using wxScrollBar
83df96d6 1498#if 0
83df96d6
JS
1499static void wxScrollBarCallback(Widget scrollbar,
1500 XtPointer clientData,
1501 XmScrollBarCallbackStruct *cbs)
1502{
1503 wxWindow *win = wxGetWindowFromTable(scrollbar);
1504 int orientation = (int) clientData;
1505
1506 wxEventType eventType = wxEVT_NULL;
1507 switch (cbs->reason)
1508 {
1509 case XmCR_INCREMENT:
1510 {
1511 eventType = wxEVT_SCROLLWIN_LINEDOWN;
1512 break;
1513 }
1514 case XmCR_DECREMENT:
1515 {
1516 eventType = wxEVT_SCROLLWIN_LINEUP;
1517 break;
1518 }
1519 case XmCR_DRAG:
1520 {
1521 eventType = wxEVT_SCROLLWIN_THUMBTRACK;
1522 break;
1523 }
1524 case XmCR_VALUE_CHANGED:
1525 {
1526 eventType = wxEVT_SCROLLWIN_THUMBRELEASE;
1527 break;
1528 }
1529 case XmCR_PAGE_INCREMENT:
1530 {
1531 eventType = wxEVT_SCROLLWIN_PAGEDOWN;
1532 break;
1533 }
1534 case XmCR_PAGE_DECREMENT:
1535 {
1536 eventType = wxEVT_SCROLLWIN_PAGEUP;
1537 break;
1538 }
1539 case XmCR_TO_TOP:
1540 {
1541 eventType = wxEVT_SCROLLWIN_TOP;
1542 break;
1543 }
1544 case XmCR_TO_BOTTOM:
1545 {
1546 eventType = wxEVT_SCROLLWIN_BOTTOM;
1547 break;
1548 }
1549 default:
1550 {
1551 // Should never get here
1552 wxFAIL_MSG("Unknown scroll event.");
1553 break;
1554 }
1555 }
1556
1557 wxScrollWinEvent event(eventType,
1558 cbs->value,
1559 ((orientation == XmHORIZONTAL) ?
1560 wxHORIZONTAL : wxVERTICAL));
1561 event.SetEventObject( win );
1562 win->GetEventHandler()->ProcessEvent(event);
1563}
bc797f4c 1564#endif
1b0fb34b 1565
83df96d6
JS
1566// ----------------------------------------------------------------------------
1567// TranslateXXXEvent() functions
1568// ----------------------------------------------------------------------------
1569
1b0fb34b 1570bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Window window, XEvent *xevent)
83df96d6
JS
1571{
1572 switch (xevent->xany.type)
1573 {
1b0fb34b
JS
1574 case EnterNotify:
1575 case LeaveNotify:
83df96d6
JS
1576 case ButtonPress:
1577 case ButtonRelease:
1578 case MotionNotify:
1579 {
1580 wxEventType eventType = wxEVT_NULL;
1581
1b0fb34b 1582 if (xevent->xany.type == EnterNotify)
83df96d6 1583 {
1b0fb34b
JS
1584 //if (local_event.xcrossing.mode!=NotifyNormal)
1585 // return ; // Ignore grab events
1586 eventType = wxEVT_ENTER_WINDOW;
1587 // canvas->GetEventHandler()->OnSetFocus();
1588 }
1589 else if (xevent->xany.type == LeaveNotify)
1590 {
1591 //if (local_event.xcrossingr.mode!=NotifyNormal)
1592 // return ; // Ignore grab events
1593 eventType = wxEVT_LEAVE_WINDOW;
1594 // canvas->GetEventHandler()->OnKillFocus();
83df96d6
JS
1595 }
1596 else if (xevent->xany.type == MotionNotify)
1597 {
1598 eventType = wxEVT_MOTION;
1599 }
1600 else if (xevent->xany.type == ButtonPress)
1601 {
1602 wxevent.SetTimestamp(xevent->xbutton.time);
1603 int button = 0;
1604 if (xevent->xbutton.button == Button1)
1605 {
1606 eventType = wxEVT_LEFT_DOWN;
1607 win->SetButton1(TRUE);
1608 button = 1;
1609 }
1610 else if (xevent->xbutton.button == Button2)
1611 {
1612 eventType = wxEVT_MIDDLE_DOWN;
1613 win->SetButton2(TRUE);
1614 button = 2;
1615 }
1616 else if (xevent->xbutton.button == Button3)
1617 {
1618 eventType = wxEVT_RIGHT_DOWN;
1619 win->SetButton3(TRUE);
1620 button = 3;
1621 }
1622
1623 // check for a double click
1b0fb34b 1624 // TODO: where can we get this value from?
b513212d 1625 //long dclickTime = XtGetMultiClickTime(wxGlobalDisplay());
7266b672 1626 long dclickTime = 200;
83df96d6
JS
1627 long ts = wxevent.GetTimestamp();
1628
1629 int buttonLast = win->GetLastClickedButton();
1630 long lastTS = win->GetLastClickTime();
1631 if ( buttonLast && buttonLast == button && (ts - lastTS) < dclickTime )
1632 {
1633 // I have a dclick
1634 win->SetLastClick(0, ts);
1635 if ( eventType == wxEVT_LEFT_DOWN )
1636 eventType = wxEVT_LEFT_DCLICK;
1637 else if ( eventType == wxEVT_MIDDLE_DOWN )
1638 eventType = wxEVT_MIDDLE_DCLICK;
1639 else if ( eventType == wxEVT_RIGHT_DOWN )
1640 eventType = wxEVT_RIGHT_DCLICK;
1641 }
1642 else
1643 {
1644 // not fast enough or different button
1645 win->SetLastClick(button, ts);
1646 }
1647 }
1648 else if (xevent->xany.type == ButtonRelease)
1649 {
1650 if (xevent->xbutton.button == Button1)
1651 {
1652 eventType = wxEVT_LEFT_UP;
1653 win->SetButton1(FALSE);
1654 }
1655 else if (xevent->xbutton.button == Button2)
1656 {
1657 eventType = wxEVT_MIDDLE_UP;
1658 win->SetButton2(FALSE);
1659 }
1660 else if (xevent->xbutton.button == Button3)
1661 {
1662 eventType = wxEVT_RIGHT_UP;
1663 win->SetButton3(FALSE);
1664 }
1665 else return FALSE;
1666 }
1667 else
1668 {
1669 return FALSE;
1670 }
1671
1672 wxevent.SetEventType(eventType);
1673
1b0fb34b
JS
1674 wxevent.m_x = xevent->xbutton.x;
1675 wxevent.m_y = xevent->xbutton.y;
83df96d6
JS
1676
1677 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
1678 || (event_left_is_down (xevent)
1679 && (eventType != wxEVT_LEFT_UP)));
1680 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
1681 || (event_middle_is_down (xevent)
1682 && (eventType != wxEVT_MIDDLE_UP)));
1683 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
1684 || (event_right_is_down (xevent)
1685 && (eventType != wxEVT_RIGHT_UP)));
1686
1687 wxevent.m_shiftDown = xevent->xbutton.state & ShiftMask;
1688 wxevent.m_controlDown = xevent->xbutton.state & ControlMask;
1689 wxevent.m_altDown = xevent->xbutton.state & Mod3Mask;
1690 wxevent.m_metaDown = xevent->xbutton.state & Mod1Mask;
1691
1692 wxevent.SetId(win->GetId());
1693 wxevent.SetEventObject(win);
1694
1695 return TRUE;
1696 }
1697 }
1698 return FALSE;
1699}
1700
7eaac9f5 1701bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Window WXUNUSED(win), XEvent *xevent)
83df96d6
JS
1702{
1703 switch (xevent->xany.type)
1704 {
1705 case KeyPress:
1706 case KeyRelease:
1707 {
1708 char buf[20];
1709
1710 KeySym keySym;
83df96d6
JS
1711 (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, NULL);
1712 int id = wxCharCodeXToWX (keySym);
1713
1714 if (xevent->xkey.state & ShiftMask)
1715 wxevent.m_shiftDown = TRUE;
1716 if (xevent->xkey.state & ControlMask)
1717 wxevent.m_controlDown = TRUE;
1718 if (xevent->xkey.state & Mod3Mask)
1719 wxevent.m_altDown = TRUE;
1720 if (xevent->xkey.state & Mod1Mask)
1721 wxevent.m_metaDown = TRUE;
1722 wxevent.SetEventObject(win);
1723 wxevent.m_keyCode = id;
1724 wxevent.SetTimestamp(xevent->xkey.time);
1725
1726 wxevent.m_x = xevent->xbutton.x;
1727 wxevent.m_y = xevent->xbutton.y;
1728
1729 if (id > -1)
1730 return TRUE;
1731 else
1732 return FALSE;
1733 break;
1734 }
1735 default:
1736 break;
1737 }
1738 return FALSE;
1739}
1740
1741// ----------------------------------------------------------------------------
1742// Colour stuff
1743// ----------------------------------------------------------------------------
1744
bc797f4c
JS
1745#if 0
1746
83df96d6
JS
1747#define YAllocColor XAllocColor
1748XColor g_itemColors[5];
1749int wxComputeColours (Display *display, wxColour * back, wxColour * fore)
1750{
1751 int result;
1752 static XmColorProc colorProc;
1753
1754 result = wxNO_COLORS;
1755
1756 if (back)
1757 {
1758 g_itemColors[0].red = (((long) back->Red ()) << 8);
1759 g_itemColors[0].green = (((long) back->Green ()) << 8);
1760 g_itemColors[0].blue = (((long) back->Blue ()) << 8);
1761 g_itemColors[0].flags = DoRed | DoGreen | DoBlue;
1762 if (colorProc == (XmColorProc) NULL)
1763 {
1764 // Get a ptr to the actual function
1765 colorProc = XmSetColorCalculation ((XmColorProc) NULL);
1766 // And set it back to motif.
1767 XmSetColorCalculation (colorProc);
1768 }
1769 (*colorProc) (&g_itemColors[wxBACK_INDEX],
1770 &g_itemColors[wxFORE_INDEX],
1771 &g_itemColors[wxSELE_INDEX],
1772 &g_itemColors[wxTOPS_INDEX],
1773 &g_itemColors[wxBOTS_INDEX]);
1774 result = wxBACK_COLORS;
1775 }
1776 if (fore)
1777 {
1778 g_itemColors[wxFORE_INDEX].red = (((long) fore->Red ()) << 8);
1779 g_itemColors[wxFORE_INDEX].green = (((long) fore->Green ()) << 8);
1780 g_itemColors[wxFORE_INDEX].blue = (((long) fore->Blue ()) << 8);
1781 g_itemColors[wxFORE_INDEX].flags = DoRed | DoGreen | DoBlue;
1782 if (result == wxNO_COLORS)
1783 result = wxFORE_COLORS;
1784 }
1785
1786 Display *dpy = display;
1787 Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy);
1788
1789 if (back)
1790 {
1791 /* 5 Colours to allocate */
1792 for (int i = 0; i < 5; i++)
1793 if (!YAllocColor (dpy, cmap, &g_itemColors[i]))
1794 result = wxNO_COLORS;
1795 }
1796 else if (fore)
1797 {
1798 /* Only 1 colour to allocate */
1799 if (!YAllocColor (dpy, cmap, &g_itemColors[wxFORE_INDEX]))
1800 result = wxNO_COLORS;
1801 }
1802
1803 return (result);
1804
1805}
bc797f4c 1806#endif
83df96d6
JS
1807
1808// Changes the foreground and background colours to be derived from the current
1809// background colour. To change the foreground colour, you must call
1810// SetForegroundColour explicitly.
bc797f4c 1811void wxWindowX11::ChangeBackgroundColour()
83df96d6 1812{
bc797f4c
JS
1813 // TODO
1814#if 0
83df96d6
JS
1815 WXWidget mainWidget = GetMainWidget();
1816 if ( mainWidget )
1817 DoChangeBackgroundColour(mainWidget, m_backgroundColour);
83df96d6
JS
1818#endif
1819}
1820
bc797f4c 1821void wxWindowX11::ChangeForegroundColour()
83df96d6 1822{
bc797f4c
JS
1823 // TODO
1824#if 0
83df96d6
JS
1825 WXWidget mainWidget = GetMainWidget();
1826 if ( mainWidget )
1827 DoChangeForegroundColour(mainWidget, m_foregroundColour);
1828 if ( m_scrolledWindow && mainWidget != m_scrolledWindow )
1829 DoChangeForegroundColour(m_scrolledWindow, m_foregroundColour);
bc797f4c 1830#endif
83df96d6
JS
1831}
1832
1833// Change a widget's foreground and background colours.
bc797f4c 1834void wxWindowX11::DoChangeForegroundColour(WXWindow widget, wxColour& foregroundColour)
83df96d6 1835{
bc797f4c
JS
1836 // TODO
1837#if 0
83df96d6
JS
1838 // When should we specify the foreground, if it's calculated
1839 // by wxComputeColours?
1840 // Solution: say we start with the default (computed) foreground colour.
1841 // If we call SetForegroundColour explicitly for a control or window,
1842 // then the foreground is changed.
1843 // Therefore SetBackgroundColour computes the foreground colour, and
1844 // SetForegroundColour changes the foreground colour. The ordering is
1845 // important.
1846
1847 Widget w = (Widget)widget;
1848 XtVaSetValues(
1849 w,
1850 XmNforeground, foregroundColour.AllocColour(XtDisplay(w)),
1851 NULL
1852 );
bc797f4c 1853#endif
83df96d6
JS
1854}
1855
bc797f4c 1856void wxWindowX11::DoChangeBackgroundColour(WXWindow widget, wxColour& backgroundColour, bool changeArmColour)
83df96d6 1857{
bc797f4c
JS
1858 // TODO
1859#if 0
83df96d6
JS
1860 wxComputeColours (XtDisplay((Widget) widget), & backgroundColour,
1861 (wxColour*) NULL);
1862
1863 XtVaSetValues ((Widget) widget,
1864 XmNbackground, g_itemColors[wxBACK_INDEX].pixel,
1865 XmNtopShadowColor, g_itemColors[wxTOPS_INDEX].pixel,
1866 XmNbottomShadowColor, g_itemColors[wxBOTS_INDEX].pixel,
1867 XmNforeground, g_itemColors[wxFORE_INDEX].pixel,
1868 NULL);
1869
1870 if (changeArmColour)
1871 XtVaSetValues ((Widget) widget,
1872 XmNarmColor, g_itemColors[wxSELE_INDEX].pixel,
1873 NULL);
bc797f4c 1874#endif
83df96d6
JS
1875}
1876
bc797f4c 1877bool wxWindowX11::SetBackgroundColour(const wxColour& col)
83df96d6
JS
1878{
1879 if ( !wxWindowBase::SetBackgroundColour(col) )
1880 return FALSE;
1881
1882 ChangeBackgroundColour();
1883
1884 return TRUE;
1885}
1886
bc797f4c 1887bool wxWindowX11::SetForegroundColour(const wxColour& col)
83df96d6
JS
1888{
1889 if ( !wxWindowBase::SetForegroundColour(col) )
1890 return FALSE;
1891
1892 ChangeForegroundColour();
1893
1894 return TRUE;
1895}
1896
bc797f4c 1897void wxWindowX11::ChangeFont(bool keepOriginalSize)
83df96d6 1898{
bc797f4c
JS
1899 // TODO
1900#if 0
83df96d6
JS
1901 // Note that this causes the widget to be resized back
1902 // to its original size! We therefore have to set the size
1903 // back again. TODO: a better way in Motif?
1904 Widget w = (Widget) GetLabelWidget(); // Usually the main widget
1905 if (w && m_font.Ok())
1906 {
1907 int width, height, width1, height1;
1908 GetSize(& width, & height);
1909
1910 // lesstif 0.87 hangs here
1911#ifndef LESSTIF_VERSION
1912 XtVaSetValues (w,
1913 XmNfontList, (XmFontList) m_font.GetFontList(1.0, XtDisplay(w)),
1914 NULL);
1915#endif
1916
1917 GetSize(& width1, & height1);
1918 if (keepOriginalSize && (width != width1 || height != height1))
1919 {
1920 SetSize(-1, -1, width, height);
1921 }
1922 }
bc797f4c 1923#endif
83df96d6
JS
1924}
1925
1926// ----------------------------------------------------------------------------
1927// global functions
1928// ----------------------------------------------------------------------------
1929
1930wxWindow *wxGetActiveWindow()
1931{
1932 // TODO
1933 wxFAIL_MSG("Not implemented");
1934 return NULL;
1935}
1936
1937/* static */
1938wxWindow *wxWindowBase::GetCapture()
1939{
1940 return (wxWindow *)g_captureWindow;
1941}
1942
1943
1944// Find the wxWindow at the current mouse position, returning the mouse
1945// position.
1946wxWindow* wxFindWindowAtPointer(wxPoint& pt)
1947{
1948 return wxFindWindowAtPoint(wxGetMousePosition());
1949}
1950
1951// Get the current mouse position.
1952wxPoint wxGetMousePosition()
1953{
b513212d 1954 Display *display = wxGlobalDisplay();
83df96d6
JS
1955 Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
1956 Window rootReturn, childReturn;
1957 int rootX, rootY, winX, winY;
1958 unsigned int maskReturn;
1959
1960 XQueryPointer (display,
1961 rootWindow,
1962 &rootReturn,
1963 &childReturn,
1964 &rootX, &rootY, &winX, &winY, &maskReturn);
1965 return wxPoint(rootX, rootY);
1966}
1967
1968
1969// ----------------------------------------------------------------------------
1970// wxNoOptimize: switch off size optimization
1971// ----------------------------------------------------------------------------
1972
1973int wxNoOptimize::ms_count = 0;
1974