]> git.saurik.com Git - wxWidgets.git/blame - src/motif/window.cpp
Don't take hidden wxGrid row/columns into account when auto-sizing.
[wxWidgets.git] / src / motif / window.cpp
CommitLineData
4bb6408c 1/////////////////////////////////////////////////////////////////////////////
25466131 2// Name: src/motif/window.cpp
4bb6408c
JS
3// Purpose: wxWindow
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
4bb6408c 7// Copyright: (c) Julian Smart
65571936 8// Licence: wxWindows licence
4bb6408c
JS
9/////////////////////////////////////////////////////////////////////////////
10
34636400
VZ
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
1248b41f
MB
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
32d4c30a
WS
22#ifndef WX_PRECOMP
23 #include "wx/hash.h"
e4db172a 24 #include "wx/log.h"
670f9935 25 #include "wx/app.h"
de6185e2 26 #include "wx/utils.h"
76b49cf4 27 #include "wx/frame.h"
da80ae71 28 #include "wx/dc.h"
ed4b0fdc 29 #include "wx/dcclient.h"
f1e01716 30 #include "wx/button.h"
3b3dc801 31 #include "wx/menu.h"
9eddec69 32 #include "wx/settings.h"
1ab440bc 33 #include "wx/scrolwin.h"
ed2fbeb8 34 #include "wx/layout.h"
25466131 35 #include "wx/menuitem.h"
02761f6c 36 #include "wx/module.h"
32d4c30a
WS
37#endif
38
7e1bcfa8 39#include "wx/evtloop.h"
10c49955 40#include "wx/unix/utilsx11.h"
4bb6408c 41
47d67540 42#if wxUSE_DRAG_AND_DROP
34636400 43 #include "wx/dnd.h"
4bb6408c
JS
44#endif
45
fc7ca9b3 46// DoSetSizeIntr and DoMoveWindowIntr
37c997b4
MB
47// PROBLEM:
48// under Motif composite controls (such as wxCalendarCtrl or generic wxSpinCtrl
96be256b 49// did not work and/or segfaulted because
37c997b4
MB
50// 1) wxWindow::Create calls SetSize,
51// which results in a call to DoSetSize much earlier than in the other ports
52// 2) if wxWindow::Create is called (wxControl::Create calls it)
53// then DoSetSize is never called, causing layout problems in composite
54// controls
55//
56// SOLUTION:
57// 1) don't call SetSize, DoSetSize, DoMoveWindow, DoGetPosition,
58// DoSetPosition directly or indirectly from wxWindow::Create
fc7ca9b3 59// 2) call DoMoveWindow from DoSetSize, allowing controls to override it
37c997b4 60
338dd992 61#ifdef __VMS__
02761f6c 62 #pragma message disable nosimpint
338dd992 63#endif
4bb6408c 64#include <Xm/Xm.h>
50414e24
JS
65
66#include <Xm/DrawingA.h>
67#include <Xm/ScrolledW.h>
68#include <Xm/ScrollBar.h>
69#include <Xm/Frame.h>
70#include <Xm/Label.h>
ee31c392 71#include <Xm/RowColumn.h> // for XmMenuPosition
338dd992 72#ifdef __VMS__
02761f6c 73 #pragma message enable nosimpint
338dd992 74#endif
50414e24 75
4bb6408c 76#include "wx/motif/private.h"
fce127d7 77#include "wx/motif/dcclient.h"
4bb6408c
JS
78
79#include <string.h>
80
34636400
VZ
81// ----------------------------------------------------------------------------
82// global variables for this module
83// ----------------------------------------------------------------------------
84
33caefb3 85extern wxHashTable *wxWidgetHashTable;
9806a47c
JS
86static wxWindow* g_captureWindow = NULL;
87
34636400
VZ
88
89// ----------------------------------------------------------------------------
90// private functions
91// ----------------------------------------------------------------------------
92
93static void wxCanvasRepaintProc(Widget, XtPointer, XmDrawingAreaCallbackStruct * cbs);
94static void wxCanvasInputEvent(Widget drawingArea, XtPointer data, XmDrawingAreaCallbackStruct * cbs);
95static void wxCanvasMotionEvent(Widget, XButtonEvent * event);
96static void wxCanvasEnterLeave(Widget drawingArea, XtPointer clientData, XCrossingEvent * event);
8aa04e8b 97static void wxScrollBarCallback(Widget widget, XtPointer clientData,
311227c3 98 XmScrollBarCallbackStruct *cbs);
34636400
VZ
99static void wxPanelItemEventHandler(Widget wid,
100 XtPointer client_data,
101 XEvent* event,
102 Boolean *continueToDispatch);
103
104// unused for now
105#if 0
106
107// Helper function for 16-bit fonts
108static int str16len(const char *s)
109{
110 int count = 0;
111
112 while (s[0] && s[1]) {
113 count++;
114 s += 2;
115 }
116
117 return count;
118}
119
120#endif // 0
121
122// ----------------------------------------------------------------------------
123// macros
124// ----------------------------------------------------------------------------
50414e24
JS
125
126#define event_left_is_down(x) ((x)->xbutton.state & Button1Mask)
127#define event_middle_is_down(x) ((x)->xbutton.state & Button2Mask)
128#define event_right_is_down(x) ((x)->xbutton.state & Button3Mask)
129
34636400
VZ
130// ----------------------------------------------------------------------------
131// event tables
132// ----------------------------------------------------------------------------
4bb6408c 133
8e877c19 134 BEGIN_EVENT_TABLE(wxWindow, wxWindowBase)
34636400 135 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
34636400 136 END_EVENT_TABLE()
4bb6408c 137
34636400
VZ
138// ============================================================================
139// implementation
140// ============================================================================
4bb6408c 141
34636400
VZ
142// ----------------------------------------------------------------------------
143// helper functions
144// ----------------------------------------------------------------------------
4bb6408c 145
34636400 146void wxWindow::UnmanageAndDestroy(WXWidget widget)
4bb6408c 147{
34636400
VZ
148 Widget w = (Widget)widget;
149 if ( w )
4bb6408c 150 {
34636400
VZ
151 XtUnmanageChild(w);
152 XtDestroyWidget(w);
4bb6408c 153 }
4bb6408c
JS
154}
155
b9ecc16a 156bool wxWindow::MapOrUnmap(WXWidget widget, bool domap)
4bb6408c 157{
34636400
VZ
158 Widget w = (Widget)widget;
159 if ( !w )
96be256b 160 return false;
34636400 161
882b1d8d
MB
162 // Rationale: a lot of common operations (including but not
163 // limited to moving, resizing and appending items to a listbox)
164 // unmamange the widget, do their work, then manage it again.
165 // This means that, for example adding an item to a listbox will show it,
166 // or that most controls are shown every time they are moved or resized!
167 XtSetMappedWhenManaged( w, domap );
168
28169f14
MB
169 // if the widget is not unmanaged, it still intercepts
170 // mouse events, even if it is not mapped (and hence invisible)
b9ecc16a 171 if ( domap )
28169f14
MB
172 {
173 XtManageChild(w);
882b1d8d 174 // XtMapWidget(w);
28169f14 175 }
34636400 176 else
28169f14 177 {
28169f14 178 XtUnmanageChild(w);
882b1d8d 179 // XtUnmapWidget(w);
28169f14 180 }
34636400 181
96be256b 182 return true;
4bb6408c
JS
183}
184
34636400
VZ
185// ----------------------------------------------------------------------------
186// constructors
187// ----------------------------------------------------------------------------
188
189void wxWindow::Init()
4bb6408c 190{
50414e24 191 // Motif-specific
96be256b 192 m_needsRefresh = true;
50414e24 193 m_mainWidget = (WXWidget) 0;
34636400 194
96be256b 195 m_winCaptured = false;
34636400 196
96be256b 197 m_isShown = true;
355b4d3d 198
34636400
VZ
199 m_hScrollBar =
200 m_vScrollBar =
201 m_borderWidget =
202 m_scrolledWindow =
50414e24 203 m_drawingArea = (WXWidget) 0;
34636400 204
34636400
VZ
205 m_scrollPosX =
206 m_scrollPosY = 0;
207
50414e24 208 m_backingPixmap = (WXPixmap) 0;
34636400 209 m_pixmapWidth =
50414e24 210 m_pixmapHeight = 0;
34636400
VZ
211
212 m_pixmapOffsetX =
50414e24 213 m_pixmapOffsetY = 0;
34636400
VZ
214
215 m_lastTS = 0;
216 m_lastButton = 0;
34636400
VZ
217}
218
219// real construction (Init() must have been called before!)
220bool wxWindow::Create(wxWindow *parent, wxWindowID id,
221 const wxPoint& pos,
222 const wxSize& size,
223 long style,
224 const wxString& name)
225{
cce69fec
JS
226 // Get default border
227 wxBorder border = GetBorder(style);
228 style &= ~wxBORDER_MASK;
229 style |= border;
230
96be256b 231 wxCHECK_MSG( parent, false, "can't create wxWindow without parent" );
34636400 232
813c20a6 233 CreateBase(parent, id, pos, size, style, wxDefaultValidator, name);
34636400
VZ
234
235 parent->AddChild(this);
105fbe1f 236 PreCreation();
34636400 237
50414e24
JS
238 //// TODO: we should probably optimize by only creating a
239 //// a drawing area if we have one or more scrollbars (wxVSCROLL/wxHSCROLL).
240 //// But for now, let's simplify things by always creating the
241 //// drawing area, since otherwise the translations are different.
34636400 242
2d120f83 243 // New translations for getting mouse motion feedback
f1db433a 244 static const String translations = wxMOTIF_STR(
34636400 245"<Btn1Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
2d120f83
JS
246<Btn2Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
247<Btn3Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
248<BtnMotion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
249<Btn1Down>: DrawingAreaInput() ManagerGadgetArm()\n\
250<Btn2Down>: DrawingAreaInput() ManagerGadgetArm()\n\
251<Btn3Down>: DrawingAreaInput() ManagerGadgetArm()\n\
252<Btn1Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
253<Btn2Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
254<Btn3Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
255<Motion>: wxCanvasMotionEvent() DrawingAreaInput()\n\
256<EnterWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
257<LeaveWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
f1db433a 258<Key>: DrawingAreaInput()");
34636400 259
2d120f83 260 XtActionsRec actions[1];
f1db433a 261 actions[0].string = wxMOTIF_STR("wxCanvasMotionEvent");
2d120f83
JS
262 actions[0].proc = (XtActionProc) wxCanvasMotionEvent;
263 XtAppAddActions ((XtAppContext) wxTheApp->GetAppContext(), actions, 1);
34636400
VZ
264
265 Widget parentWidget = (Widget) parent->GetClientWidget();
6769d0cb 266 m_borderWidget = wxCreateBorderWidget( (WXWidget)parentWidget, style );
34636400
VZ
267
268 m_scrolledWindow = (WXWidget)XtVaCreateManagedWidget
269 (
270 "scrolledWindow",
271 xmScrolledWindowWidgetClass,
272 m_borderWidget ? (Widget) m_borderWidget
273 : parentWidget,
274 XmNresizePolicy, XmRESIZE_NONE,
275 XmNspacing, 0,
276 XmNscrollingPolicy, XmAPPLICATION_DEFINED,
277 //XmNscrollBarDisplayPolicy, XmAS_NEEDED,
278 NULL
279 );
280
281 XtTranslations ptr = XtParseTranslationTable(translations);
282 m_drawingArea = (WXWidget)XtVaCreateWidget
283 (
284 name,
285 xmDrawingAreaWidgetClass, (Widget) m_scrolledWindow,
286 XmNunitType, XmPIXELS,
287 // XmNresizePolicy, XmRESIZE_ANY,
288 XmNresizePolicy, XmRESIZE_NONE,
289 XmNmarginHeight, 0,
290 XmNmarginWidth, 0,
291 XmNtranslations, ptr,
292 NULL
293 );
294 XtFree((char *) ptr);
295
296#if 0
297 if (GetWindowStyleFlag() & wxOVERRIDE_KEY_TRANSLATIONS)
298 {
2d120f83
JS
299 ptr = XtParseTranslationTable ("<Key>: DrawingAreaInput()");
300 XtOverrideTranslations ((Widget) m_drawingArea, ptr);
301 XtFree ((char *) ptr);
34636400
VZ
302 }
303#endif // 0
304
2d120f83
JS
305 wxAddWindowToTable((Widget) m_drawingArea, this);
306 wxAddWindowToTable((Widget) m_scrolledWindow, this);
34636400
VZ
307
308 // This order is very important in Motif 1.2.1
2d120f83
JS
309 XtRealizeWidget ((Widget) m_scrolledWindow);
310 XtRealizeWidget ((Widget) m_drawingArea);
311 XtManageChild ((Widget) m_drawingArea);
34636400
VZ
312
313 ptr = XtParseTranslationTable("<Configure>: resize()");
314 XtOverrideTranslations((Widget) m_drawingArea, ptr);
50414e24 315 XtFree ((char *) ptr);
34636400 316
2d120f83
JS
317 XtAddCallback ((Widget) m_drawingArea, XmNexposeCallback, (XtCallbackProc) wxCanvasRepaintProc, (XtPointer) this);
318 XtAddCallback ((Widget) m_drawingArea, XmNinputCallback, (XtCallbackProc) wxCanvasInputEvent, (XtPointer) this);
34636400 319
34636400
VZ
320 XtAddEventHandler(
321 (Widget)m_drawingArea,
322 PointerMotionHintMask | EnterWindowMask |
323 LeaveWindowMask | FocusChangeMask,
324 False,
325 (XtEventHandler) wxCanvasEnterLeave,
326 (XtPointer) this
327 );
328
34636400
VZ
329 XmScrolledWindowSetAreas(
330 (Widget)m_scrolledWindow,
331 (Widget) 0, (Widget) 0,
332 (Widget) m_drawingArea);
333
105fbe1f
MB
334 PostCreation();
335
34636400
VZ
336 // Without this, the cursor may not be restored properly (e.g. in splitter
337 // sample).
2d120f83 338 SetCursor(*wxSTANDARD_CURSOR);
96be256b
MB
339 DoSetSizeIntr(pos.x, pos.y, size.x,size.y, wxSIZE_AUTO, true);
340 return true;
88150e60
JS
341}
342
34636400
VZ
343// Destructor
344wxWindow::~wxWindow()
345{
c6212a0c
VZ
346 SendDestroyEvent();
347
9806a47c 348 if (g_captureWindow == this)
2b5f62a0 349 g_captureWindow = NULL;
355b4d3d 350
34636400
VZ
351 // Motif-specific actions first
352 WXWidget wMain = GetMainWidget();
353 if ( wMain )
354 {
355 // Removes event handlers
356 DetachWidget(wMain);
357 }
358
34636400
VZ
359 // If m_drawingArea, we're a fully-fledged window with drawing area,
360 // scrollbars etc. (what wxCanvas used to be)
361 if ( m_drawingArea )
362 {
363 // Destroy children before destroying self
364 DestroyChildren();
365
366 if (m_backingPixmap)
367 XFreePixmap (XtDisplay ((Widget) GetMainWidget()), (Pixmap) m_backingPixmap);
368
369 Widget w = (Widget) m_drawingArea;
370 wxDeleteWindowFromTable(w);
371
372 if (w)
373 {
374 XtDestroyWidget(w);
2b5f62a0 375 m_drawingArea = (WXWidget) 0;
34636400
VZ
376 }
377
34636400
VZ
378 // Only if we're _really_ a canvas (not a dialog box/panel)
379 if (m_scrolledWindow)
380 {
381 wxDeleteWindowFromTable((Widget) m_scrolledWindow);
382 }
383
311227c3
MB
384 if (m_hScrollBar)
385 {
386 wxDeleteWindowFromTable((Widget) m_hScrollBar);
2b5f62a0 387 XtUnmanageChild((Widget) m_hScrollBar);
311227c3
MB
388 }
389 if (m_vScrollBar)
390 {
391 wxDeleteWindowFromTable((Widget) m_vScrollBar);
2b5f62a0 392 XtUnmanageChild((Widget) m_vScrollBar);
311227c3
MB
393 }
394
f0d5fc50 395 if (m_hScrollBar)
2b5f62a0 396 XtDestroyWidget((Widget) m_hScrollBar);
f0d5fc50 397 if (m_vScrollBar)
2b5f62a0 398 XtDestroyWidget((Widget) m_vScrollBar);
f0d5fc50 399
34636400
VZ
400 UnmanageAndDestroy(m_scrolledWindow);
401
402 if (m_borderWidget)
403 {
404 XtDestroyWidget ((Widget) m_borderWidget);
405 m_borderWidget = (WXWidget) 0;
406 }
407 }
7b28757f
JS
408 else // Why wasn't this here before? JACS 8/3/2000
409 DestroyChildren();
410
34636400
VZ
411
412 // Destroy the window
413 if (GetMainWidget())
414 {
415 // If this line (XtDestroyWidget) causes a crash, you may comment it out.
416 // Child widgets will get destroyed automatically when a frame
417 // or dialog is destroyed, but before that you may get some memory
418 // leaks and potential layout problems if you delete and then add
419 // child windows.
bdeca1d1
GRG
420
421 // GRG, Feb/2000: commented this out when adding support for
422 // wxSCROLL[WIN]_THUMBRELEASE events. Also it was reported
423 // that this call crashed wxMotif under OS/2, so it seems
424 // that leaving it out is the right thing to do.
b3ef4fb5
SN
425 // SN, Feb/2000: newgrid/griddemo shows why it is needed :-(
426 XtDestroyWidget((Widget) GetMainWidget());
34636400
VZ
427 SetMainWidget((WXWidget) NULL);
428 }
429}
430
431// ----------------------------------------------------------------------------
432// scrollbar management
433// ----------------------------------------------------------------------------
434
148b44a1
MB
435WXWidget wxWindow::DoCreateScrollBar(WXWidget parent,
436 wxOrientation orientation,
437 void (*callback)())
438{
439 int orient = ( orientation & wxHORIZONTAL ) ? XmHORIZONTAL : XmVERTICAL;
440 Widget sb =
441 XtVaCreateManagedWidget( "scrollBarWidget",
442 xmScrollBarWidgetClass, (Widget)parent,
443 XmNorientation, orient,
444 XmNincrement, 1,
445 XmNvalue, 0,
446 NULL );
447
448 XtPointer o = (XtPointer)orientation;
449 XtCallbackProc cb = (XtCallbackProc)callback;
450
451 XtAddCallback( sb, XmNvalueChangedCallback, cb, o );
452 XtAddCallback( sb, XmNdragCallback, cb, o );
453 XtAddCallback( sb, XmNincrementCallback, cb, o );
454 XtAddCallback( sb, XmNdecrementCallback, cb, o );
455 XtAddCallback( sb, XmNpageIncrementCallback, cb, o );
456 XtAddCallback( sb, XmNpageDecrementCallback, cb, o );
457 XtAddCallback( sb, XmNtoTopCallback, cb, o );
458 XtAddCallback( sb, XmNtoBottomCallback, cb, o );
459
460 return (WXWidget)sb;
461}
462
88150e60 463// Helper function
af0bb3b1 464void wxWindow::CreateScrollbar(wxOrientation orientation)
88150e60 465{
34636400
VZ
466 wxCHECK_RET( m_drawingArea, "this window can't have scrollbars" );
467
148b44a1
MB
468 XtVaSetValues( (Widget) m_scrolledWindow,
469 XmNresizePolicy, XmRESIZE_NONE,
470 NULL );
34636400 471
148b44a1 472 wxColour backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
2d120f83
JS
473 // Add scrollbars if required
474 if (orientation == wxHORIZONTAL)
475 {
148b44a1
MB
476 m_hScrollBar = DoCreateScrollBar( m_scrolledWindow, wxHORIZONTAL,
477 (void (*)())wxScrollBarCallback );
34636400 478
96be256b 479 wxDoChangeBackgroundColour(m_hScrollBar, backgroundColour, true);
34636400 480
148b44a1 481 XtRealizeWidget( (Widget)m_hScrollBar );
34636400 482
2d120f83
JS
483 XtVaSetValues((Widget) m_scrolledWindow,
484 XmNhorizontalScrollBar, (Widget) m_hScrollBar,
485 NULL);
34636400 486
148b44a1 487 wxAddWindowToTable( (Widget)m_hScrollBar, this );
2d120f83 488 }
148b44a1 489 else if (orientation == wxVERTICAL)
2d120f83 490 {
148b44a1
MB
491 m_vScrollBar = DoCreateScrollBar( m_scrolledWindow, wxVERTICAL,
492 (void (*)())wxScrollBarCallback );
34636400 493
96be256b 494 wxDoChangeBackgroundColour(m_vScrollBar, backgroundColour, true);
34636400 495
148b44a1 496 XtRealizeWidget((Widget)m_vScrollBar);
34636400 497
2d120f83
JS
498 XtVaSetValues((Widget) m_scrolledWindow,
499 XmNverticalScrollBar, (Widget) m_vScrollBar,
500 NULL);
34636400 501
148b44a1 502 wxAddWindowToTable( (Widget)m_vScrollBar, this );
2d120f83 503 }
34636400 504
148b44a1
MB
505 XtVaSetValues( (Widget) m_scrolledWindow,
506 XmNresizePolicy, XmRESIZE_ANY,
507 NULL );
88150e60 508}
34636400 509
af0bb3b1 510void wxWindow::DestroyScrollbar(wxOrientation orientation)
88150e60 511{
34636400
VZ
512 wxCHECK_RET( m_drawingArea, "this window can't have scrollbars" );
513
148b44a1
MB
514 XtVaSetValues((Widget) m_scrolledWindow,
515 XmNresizePolicy, XmRESIZE_NONE,
516 NULL);
517 String stringSB = orientation == wxHORIZONTAL ?
518 XmNhorizontalScrollBar : XmNverticalScrollBar;
519 WXWidget* widgetSB = orientation == wxHORIZONTAL ?
520 &m_hScrollBar : &m_vScrollBar;
34636400 521
148b44a1 522 if( *widgetSB )
2d120f83 523 {
148b44a1
MB
524 wxDeleteWindowFromTable( (Widget)*widgetSB );
525 XtDestroyWidget( (Widget)*widgetSB );
526 *widgetSB = (WXWidget)NULL;
527 }
34636400 528
148b44a1
MB
529 XtVaSetValues( (Widget)m_scrolledWindow,
530 stringSB, (Widget) 0,
531 NULL );
34636400 532
148b44a1
MB
533 XtVaSetValues((Widget) m_scrolledWindow,
534 XmNresizePolicy, XmRESIZE_ANY,
535 NULL);
4bb6408c
JS
536}
537
34636400
VZ
538// ---------------------------------------------------------------------------
539// basic operations
540// ---------------------------------------------------------------------------
541
4bb6408c
JS
542void wxWindow::SetFocus()
543{
34636400
VZ
544 Widget wMain = (Widget) GetMainWidget();
545 XmProcessTraversal(wMain, XmTRAVERSE_CURRENT);
2d120f83 546 XmProcessTraversal((Widget) GetMainWidget(), XmTRAVERSE_CURRENT);
4bb6408c
JS
547}
548
34636400 549// Get the window with the focus
0fe02759 550wxWindow *wxWindowBase::DoFindFocus()
4bb6408c 551{
34636400
VZ
552 // TODO Problems:
553 // (1) Can there be multiple focussed widgets in an application?
554 // In which case we need to find the top-level window that's
555 // currently active.
556 // (2) The widget with the focus may not be in the widget table
557 // depending on which widgets I put in the table
d3b9f782 558 wxWindow *winFocus = NULL;
1807c27d 559 for ( wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
34636400
VZ
560 node;
561 node = node->GetNext() )
2d120f83 562 {
34636400
VZ
563 wxWindow *win = node->GetData();
564
565 Widget w = XmGetFocusWidget ((Widget) win->GetTopWidget());
566
567 if (w != (Widget) NULL)
568 {
569 winFocus = wxGetWindowFromTable(w);
570 if ( winFocus )
571 break;
572 }
2d120f83 573 }
4bb6408c 574
34636400 575 return winFocus;
4bb6408c
JS
576}
577
af0bb3b1 578bool wxWindow::Enable(bool enable)
4bb6408c 579{
34636400 580 if ( !wxWindowBase::Enable(enable) )
96be256b 581 return false;
4bb6408c 582
af0bb3b1 583 Widget wMain = (Widget)GetMainWidget();
34636400
VZ
584 if ( wMain )
585 {
586 XtSetSensitive(wMain, enable);
587 XmUpdateDisplay(wMain);
588 }
589
96be256b 590 return true;
4bb6408c
JS
591}
592
34636400 593bool wxWindow::Show(bool show)
4bb6408c 594{
34636400 595 if ( !wxWindowBase::Show(show) )
96be256b 596 return false;
34636400
VZ
597
598 if (m_borderWidget || m_scrolledWindow)
2d120f83 599 {
34636400 600 MapOrUnmap(m_borderWidget ? m_borderWidget : m_scrolledWindow, show);
882b1d8d 601 // MapOrUnmap(m_drawingArea, show);
2d120f83
JS
602 }
603 else
34636400
VZ
604 {
605 if ( !MapOrUnmap(GetTopWidget(), show) )
606 MapOrUnmap(GetMainWidget(), show);
607 }
608
96be256b 609 return true;
34636400 610}
4bb6408c 611
34636400
VZ
612// Raise the window to the top of the Z order
613void wxWindow::Raise()
4bb6408c 614{
34636400
VZ
615 Widget wTop = (Widget) GetTopWidget();
616 Window window = XtWindow(wTop);
617 XRaiseWindow(XtDisplay(wTop), window);
4bb6408c
JS
618}
619
34636400
VZ
620// Lower the window to the bottom of the Z order
621void wxWindow::Lower()
622{
623 Widget wTop = (Widget) GetTopWidget();
624 Window window = XtWindow(wTop);
625 XLowerWindow(XtDisplay(wTop), window);
626}
4bb6408c 627
34097680 628void wxWindow::SetLabel(const wxString& label)
4bb6408c 629{
6991087b
VS
630 XtVaSetValues((Widget)GetMainWidget(), XmNtitle,
631 (const char*)label.mb_str(), NULL);
4bb6408c
JS
632}
633
34097680 634wxString wxWindow::GetLabel() const
4bb6408c 635{
4871d342 636 char *label = NULL;
34097680 637 XtVaGetValues((Widget)GetMainWidget(), XmNtitle, &label, NULL);
af0bb3b1 638
34097680 639 return wxString(label);
4bb6408c
JS
640}
641
4116c221 642void wxWindow::DoCaptureMouse()
4bb6408c 643{
9806a47c 644 g_captureWindow = this;
34636400 645 if ( m_winCaptured )
a4294b78 646 return;
34636400 647
af0bb3b1 648 Widget wMain = (Widget)GetMainWidget();
34636400 649 if ( wMain )
96be256b 650 XtAddGrab(wMain, True, False);
34636400 651
96be256b 652 m_winCaptured = true;
4bb6408c
JS
653}
654
4116c221 655void wxWindow::DoReleaseMouse()
4bb6408c 656{
9806a47c 657 g_captureWindow = NULL;
34636400
VZ
658 if ( !m_winCaptured )
659 return;
660
af0bb3b1 661 Widget wMain = (Widget)GetMainWidget();
34636400
VZ
662 if ( wMain )
663 XtRemoveGrab(wMain);
664
96be256b 665 m_winCaptured = false;
4bb6408c
JS
666}
667
34636400 668bool wxWindow::SetFont(const wxFont& font)
4bb6408c 669{
34636400
VZ
670 if ( !wxWindowBase::SetFont(font) )
671 {
672 // nothing to do
96be256b 673 return false;
34636400
VZ
674 }
675
676 ChangeFont();
677
96be256b 678 return true;
4bb6408c
JS
679}
680
34636400 681bool wxWindow::SetCursor(const wxCursor& cursor)
4bb6408c 682{
34636400 683 if ( !wxWindowBase::SetCursor(cursor) )
2d120f83 684 {
34636400 685 // no change
96be256b 686 return false;
2d120f83 687 }
4bb6408c 688
a1b806b9 689 // wxASSERT_MSG( m_cursor.IsOk(),
f6bcfd97 690 // wxT("cursor must be valid after call to the base version"));
f516d986 691 const wxCursor* cursor2 = NULL;
a1b806b9 692 if (m_cursor.IsOk())
f6bcfd97
BP
693 cursor2 = & m_cursor;
694 else
695 cursor2 = wxSTANDARD_CURSOR;
4bb6408c 696
34636400 697 WXDisplay *dpy = GetXDisplay();
f6bcfd97 698 WXCursor x_cursor = cursor2->GetXCursor(dpy);
34636400
VZ
699
700 Widget w = (Widget) GetMainWidget();
701 Window win = XtWindow(w);
702 XDefineCursor((Display*) dpy, win, (Cursor) x_cursor);
af0bb3b1 703
96be256b 704 return true;
34636400
VZ
705}
706
707// Coordinates relative to the window
708void wxWindow::WarpPointer (int x, int y)
4bb6408c 709{
34636400
VZ
710 Widget wClient = (Widget)GetClientWidget();
711
712 XWarpPointer(XtDisplay(wClient), None, XtWindow(wClient), 0, 0, 0, 0, x, y);
4bb6408c
JS
713}
714
34636400
VZ
715// ---------------------------------------------------------------------------
716// scrolling stuff
717// ---------------------------------------------------------------------------
718
719int wxWindow::GetScrollPos(int orient) const
4bb6408c 720{
34636400
VZ
721 if (orient == wxHORIZONTAL)
722 return m_scrollPosX;
723 else
724 return m_scrollPosY;
725
726#if 0
727 Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar);
728 if (scrollBar)
2d120f83 729 {
34636400
VZ
730 int pos;
731 XtVaGetValues(scrollBar, XmNvalue, &pos, NULL);
732 return pos;
2d120f83 733 }
34636400
VZ
734 else
735 return 0;
736#endif // 0
2d120f83 737}
7fe7d506 738
34636400
VZ
739// This now returns the whole range, not just the number of positions that we
740// can scroll.
741int wxWindow::GetScrollRange(int orient) const
2d120f83 742{
af0bb3b1 743 Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
355b4d3d 744 // CE scintilla windows don't always have these scrollbars
34e8f097
CE
745 // and it tends to pile up a whole bunch of asserts
746 //wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
34636400 747
c4cb3d0f 748 int range = 0;
355b4d3d 749 if (scrollBar)
c4cb3d0f 750 XtVaGetValues(scrollBar, XmNmaximum, &range, NULL);
34636400 751 return range;
2d120f83 752}
4bb6408c 753
34636400 754int wxWindow::GetScrollThumb(int orient) const
4bb6408c 755{
af0bb3b1 756 Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
34e8f097 757 //wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
34636400 758
34e8f097
CE
759 int thumb = 0;
760 if (scrollBar)
761 XtVaGetValues(scrollBar, XmNsliderSize, &thumb, NULL);
34636400 762 return thumb;
4bb6408c
JS
763}
764
34636400 765void wxWindow::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
4bb6408c 766{
af0bb3b1 767 Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
34636400
VZ
768
769 if ( scrollBar )
4bb6408c 770 {
34636400 771 XtVaSetValues (scrollBar, XmNvalue, pos, NULL);
4bb6408c 772 }
34636400 773
af0bb3b1 774 SetInternalScrollPos((wxOrientation)orient, pos);
4bb6408c
JS
775}
776
34636400
VZ
777// New function that will replace some of the above.
778void wxWindow::SetScrollbar(int orient, int pos, int thumbVisible,
779 int range, bool WXUNUSED(refresh))
4bb6408c 780{
34636400
VZ
781 int oldW, oldH;
782 GetSize(& oldW, & oldH);
783
784 if (range == 0)
785 range = 1;
786 if (thumbVisible == 0)
787 thumbVisible = 1;
788
789 if (thumbVisible > range)
790 thumbVisible = range;
791
792 // Save the old state to see if it changed
af0bb3b1 793 WXWidget oldScrollBar = GetScrollbar((wxOrientation)orient);
34636400
VZ
794
795 if (orient == wxHORIZONTAL)
50414e24 796 {
34636400 797 if (thumbVisible == range)
2d120f83 798 {
34636400
VZ
799 if (m_hScrollBar)
800 DestroyScrollbar(wxHORIZONTAL);
2d120f83
JS
801 }
802 else
803 {
34636400
VZ
804 if (!m_hScrollBar)
805 CreateScrollbar(wxHORIZONTAL);
2d120f83 806 }
50414e24 807 }
34636400 808 if (orient == wxVERTICAL)
50414e24 809 {
34636400 810 if (thumbVisible == range)
2d120f83 811 {
34636400
VZ
812 if (m_vScrollBar)
813 DestroyScrollbar(wxVERTICAL);
2d120f83
JS
814 }
815 else
816 {
34636400
VZ
817 if (!m_vScrollBar)
818 CreateScrollbar(wxVERTICAL);
2d120f83 819 }
50414e24 820 }
af0bb3b1 821 WXWidget newScrollBar = GetScrollbar((wxOrientation)orient);
4bb6408c 822
88150e60 823 if (oldScrollBar != newScrollBar)
28ab302b 824 {
34636400 825 // This is important! Without it, scrollbars misbehave badly.
2d120f83
JS
826 XtUnrealizeWidget((Widget) m_scrolledWindow);
827 XmScrolledWindowSetAreas ((Widget) m_scrolledWindow, (Widget) m_hScrollBar, (Widget) m_vScrollBar, (Widget) m_drawingArea);
828 XtRealizeWidget((Widget) m_scrolledWindow);
829 XtManageChild((Widget) m_scrolledWindow);
28ab302b 830 }
34636400 831
88150e60 832 if (newScrollBar)
34636400 833 {
2d120f83
JS
834 XtVaSetValues((Widget) newScrollBar,
835 XmNvalue, pos,
836 XmNminimum, 0,
837 XmNmaximum, range,
838 XmNsliderSize, thumbVisible,
839 NULL);
34636400
VZ
840 }
841
af0bb3b1 842 SetInternalScrollPos((wxOrientation)orient, pos);
34636400 843
88150e60
JS
844 int newW, newH;
845 GetSize(& newW, & newH);
34636400 846
88150e60
JS
847 // Adjusting scrollbars can resize the canvas accidentally
848 if (newW != oldW || newH != oldH)
34097680 849 SetSize(wxDefaultCoord, wxDefaultCoord, oldW, oldH);
4bb6408c
JS
850}
851
852// Does a physical scroll
16e93305 853void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
4bb6408c 854{
2d120f83
JS
855 int x, y, w, h;
856 if (rect)
857 {
858 // Use specified rectangle
859 x = rect->x; y = rect->y; w = rect->width; h = rect->height;
860 }
861 else
862 {
863 // Use whole client area
864 x = 0; y = 0;
865 GetClientSize(& w, & h);
866 }
34636400
VZ
867
868 int x1 = (dx >= 0) ? x : x - dx;
2d120f83
JS
869 int y1 = (dy >= 0) ? y : y - dy;
870 int w1 = w - abs(dx);
871 int h1 = h - abs(dy);
872 int x2 = (dx >= 0) ? x + dx : x;
873 int y2 = (dy >= 0) ? y + dy : y;
34636400 874
2d120f83 875 wxClientDC dc(this);
fce127d7
VZ
876 wxClientDCImpl * const
877 dcimpl = static_cast<wxClientDCImpl *>(dc.GetImpl());
878 GC const gc = (GC) dcimpl->GetGC();
34636400 879
2d120f83 880 dc.SetLogicalFunction (wxCOPY);
34636400 881
2d120f83
JS
882 Widget widget = (Widget) GetMainWidget();
883 Window window = XtWindow(widget);
884 Display* display = XtDisplay(widget);
34636400 885
fce127d7 886 XCopyArea(display, window, window, gc, x1, y1, w1, h1, x2, y2);
34636400 887
fce127d7 888 dcimpl->SetAutoSetting(true);
2d120f83 889 wxBrush brush(GetBackgroundColour(), wxSOLID);
34636400
VZ
890 dc.SetBrush(brush); // FIXME: needed?
891
1807c27d 892 wxWindowList::compatibility_iterator cnode = m_children.GetFirst();
fc7ca9b3
MB
893 while (cnode)
894 {
895 wxWindow *child = cnode->GetData();
896 int sx = 0;
897 int sy = 0;
898 child->GetSize( &sx, &sy );
899 wxPoint pos( child->GetPosition() );
900 child->SetSize( pos.x + dx, pos.y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
901 cnode = cnode->GetNext();
902 }
903
34636400
VZ
904 // We'll add rectangles to the list of update rectangles according to which
905 // bits we've exposed.
2d120f83 906 wxList updateRects;
34636400 907
2d120f83
JS
908 if (dx > 0)
909 {
910 wxRect *rect = new wxRect;
911 rect->x = x;
912 rect->y = y;
913 rect->width = dx;
914 rect->height = h;
34636400 915
fce127d7 916 XFillRectangle(display, window, gc, rect->x, rect->y, rect->width, rect->height);
34636400 917
2d120f83
JS
918 rect->x = rect->x;
919 rect->y = rect->y;
920 rect->width = rect->width;
921 rect->height = rect->height;
34636400 922
2d120f83
JS
923 updateRects.Append((wxObject*) rect);
924 }
925 else if (dx < 0)
926 {
927 wxRect *rect = new wxRect;
34636400 928
2d120f83
JS
929 rect->x = x + w + dx;
930 rect->y = y;
931 rect->width = -dx;
932 rect->height = h;
34636400 933
fce127d7 934 XFillRectangle(display, window, gc, rect->x, rect->y, rect->width, rect->height);
34636400 935
2d120f83
JS
936 rect->x = rect->x;
937 rect->y = rect->y;
938 rect->width = rect->width;
939 rect->height = rect->height;
34636400 940
2d120f83
JS
941 updateRects.Append((wxObject*) rect);
942 }
943 if (dy > 0)
944 {
945 wxRect *rect = new wxRect;
34636400 946
2d120f83
JS
947 rect->x = x;
948 rect->y = y;
949 rect->width = w;
950 rect->height = dy;
34636400 951
fce127d7 952 XFillRectangle(display, window, gc, rect->x, rect->y, rect->width, rect->height);
34636400 953
2d120f83
JS
954 rect->x = rect->x;
955 rect->y = rect->y;
956 rect->width = rect->width;
957 rect->height = rect->height;
34636400 958
2d120f83
JS
959 updateRects.Append((wxObject*) rect);
960 }
961 else if (dy < 0)
962 {
963 wxRect *rect = new wxRect;
34636400 964
2d120f83
JS
965 rect->x = x;
966 rect->y = y + h + dy;
967 rect->width = w;
968 rect->height = -dy;
34636400 969
fce127d7 970 XFillRectangle(display, window, gc, rect->x, rect->y, rect->width, rect->height);
34636400 971
2d120f83
JS
972 rect->x = rect->x;
973 rect->y = rect->y;
974 rect->width = rect->width;
975 rect->height = rect->height;
34636400 976
2d120f83
JS
977 updateRects.Append((wxObject*) rect);
978 }
979 dc.SetBrush(wxNullBrush);
34636400 980
2d120f83 981 // Now send expose events
34636400 982
1807c27d 983 wxList::compatibility_iterator node = updateRects.GetFirst();
2d120f83
JS
984 while (node)
985 {
1bc822df 986 wxRect* rect = (wxRect*) node->GetData();
2d120f83 987 XExposeEvent event;
34636400 988
2d120f83
JS
989 event.type = Expose;
990 event.display = display;
991 event.send_event = True;
992 event.window = window;
34636400 993
2d120f83
JS
994 event.x = rect->x;
995 event.y = rect->y;
996 event.width = rect->width;
997 event.height = rect->height;
34636400 998
2d120f83 999 event.count = 0;
34636400 1000
2d120f83 1001 XSendEvent(display, window, False, ExposureMask, (XEvent *)&event);
34636400 1002
1bc822df 1003 node = node->GetNext();
34636400 1004
2d120f83 1005 }
34636400 1006
2d120f83 1007 // Delete the update rects
1bc822df 1008 node = updateRects.GetFirst();
2d120f83
JS
1009 while (node)
1010 {
1bc822df 1011 wxRect* rect = (wxRect*) node->GetData();
2d120f83 1012 delete rect;
1bc822df 1013 node = node->GetNext();
2d120f83 1014 }
a91b47e8
JS
1015
1016 XmUpdateDisplay((Widget) GetMainWidget());
4bb6408c
JS
1017}
1018
34636400
VZ
1019// ---------------------------------------------------------------------------
1020// drag and drop
1021// ---------------------------------------------------------------------------
4ce81a75 1022
34636400 1023#if wxUSE_DRAG_AND_DROP
4ce81a75 1024
34636400 1025void wxWindow::SetDropTarget(wxDropTarget * WXUNUSED(pDropTarget))
4ce81a75 1026{
34636400 1027 // TODO
4bb6408c
JS
1028}
1029
34636400
VZ
1030#endif
1031
1032// Old style file-manager drag&drop
1033void wxWindow::DragAcceptFiles(bool WXUNUSED(accept))
4bb6408c 1034{
34636400 1035 // TODO
4bb6408c
JS
1036}
1037
34636400
VZ
1038// ----------------------------------------------------------------------------
1039// tooltips
1040// ----------------------------------------------------------------------------
1041
1042#if wxUSE_TOOLTIPS
1043
1044void wxWindow::DoSetToolTip(wxToolTip * WXUNUSED(tooltip))
4bb6408c 1045{
34636400 1046 // TODO
4bb6408c
JS
1047}
1048
34636400
VZ
1049#endif // wxUSE_TOOLTIPS
1050
ee31c392
VZ
1051// ----------------------------------------------------------------------------
1052// popup menus
1053// ----------------------------------------------------------------------------
1054
7e1bcfa8
MB
1055#if wxUSE_MENUS
1056
ee31c392
VZ
1057bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
1058{
34097680 1059 if ( x == wxDefaultCoord && y == wxDefaultCoord )
971562cb
VS
1060 {
1061 wxPoint mouse = ScreenToClient(wxGetMousePosition());
1062 x = mouse.x; y = mouse.y;
1063 }
1064
ee31c392
VZ
1065 Widget widget = (Widget) GetMainWidget();
1066
1067 /* The menuId field seems to be usused, so we'll use it to
1068 indicate whether a menu is popped up or not:
1069 0: Not currently created as a popup
1070 -1: Created as a popup, but not active
1071 1: Active popup.
1072 */
1073
1074 if (menu->GetParent() && (menu->GetId() != -1))
96be256b 1075 return false;
ee31c392 1076
7e1bcfa8
MB
1077 if (menu->GetMainWidget())
1078 {
96be256b 1079 menu->DestroyMenu(true);
ee31c392
VZ
1080 }
1081
1082 menu->SetId(1); /* Mark as popped-up */
51c9a5db 1083 menu->CreateMenu(NULL, widget, menu, 0);
ee31c392
VZ
1084
1085 menu->UpdateUI();
1086
1087 // menu->SetParent(parent);
1088 // parent->children->Append(menu); // Store menu for later deletion
1089
1090 Widget menuWidget = (Widget) menu->GetMainWidget();
1091
1092 int rootX = 0;
1093 int rootY = 0;
1094
1095 int deviceX = x;
1096 int deviceY = y;
1097 /*
1098 if (this->IsKindOf(CLASSINFO(wxCanvas)))
1099 {
1100 wxCanvas *canvas = (wxCanvas *) this;
1101 deviceX = canvas->GetDC ()->LogicalToDeviceX (x);
1102 deviceY = canvas->GetDC ()->LogicalToDeviceY (y);
1103 }
1104 */
1105
1106 Display *display = XtDisplay (widget);
1107 Window rootWindow = RootWindowOfScreen (XtScreen((Widget)widget));
1108 Window thisWindow = XtWindow (widget);
1109 Window childWindow;
1110 XTranslateCoordinates (display, thisWindow, rootWindow, (int) deviceX, (int) deviceY,
1111 &rootX, &rootY, &childWindow);
1112
1113 XButtonPressedEvent event;
1114 event.type = ButtonPress;
1115 event.button = 1;
1116
1117 event.x = deviceX;
1118 event.y = deviceY;
1119
1120 event.x_root = rootX;
1121 event.y_root = rootY;
1122
1123 XmMenuPosition (menuWidget, &event);
1124 XtManageChild (menuWidget);
1125
2b5f62a0 1126 // The ID of a pop-up menu is 1 when active, and is set to 0 by the
e41e1385 1127 // idle-time destroy routine.
2b5f62a0 1128 // Waiting until this ID changes causes this function to block until
e41e1385
JS
1129 // the menu has been dismissed and the widgets cleaned up.
1130 // In other words, once this routine returns, it is safe to delete
1131 // the menu object.
1132 // Ian Brown <ian.brown@printsoft.de>
e41e1385 1133
7e1bcfa8 1134 wxEventLoop evtLoop;
e41e1385 1135
7e1bcfa8
MB
1136 while (menu->GetId() == 1)
1137 {
1138 wxDoEventLoopIteration( evtLoop );
e41e1385 1139 }
7e1bcfa8 1140
96be256b 1141 return true;
ee31c392
VZ
1142}
1143
7e1bcfa8
MB
1144#endif
1145
34636400
VZ
1146// ---------------------------------------------------------------------------
1147// moving and resizing
1148// ---------------------------------------------------------------------------
4bb6408c 1149
34636400 1150bool wxWindow::PreResize()
4bb6408c 1151{
96be256b 1152 return true;
4bb6408c
JS
1153}
1154
34636400 1155// Get total size
af0bb3b1 1156void wxWindow::DoGetSize(int *x, int *y) const
4bb6408c 1157{
fc7ca9b3
MB
1158 Widget widget = (Widget)( !m_drawingArea ? GetTopWidget() :
1159 ( m_borderWidget ? m_borderWidget :
1160 m_scrolledWindow ? m_scrolledWindow :
1161 m_drawingArea ) );
34636400 1162 Dimension xx, yy;
fc7ca9b3 1163
105fbe1f
MB
1164 if (widget)
1165 XtVaGetValues( widget,
1166 XmNwidth, &xx,
1167 XmNheight, &yy,
1168 NULL );
24bd6cb9 1169 if(x) *x = widget ? xx : -1;
105fbe1f 1170 if(y) *y = widget ? yy : -1;
4bb6408c
JS
1171}
1172
af0bb3b1 1173void wxWindow::DoGetPosition(int *x, int *y) const
4bb6408c 1174{
fc7ca9b3
MB
1175 Widget widget = (Widget)
1176 ( m_drawingArea ?
355b4d3d 1177 ( m_borderWidget ? m_borderWidget : m_scrolledWindow ) :
fc7ca9b3
MB
1178 GetTopWidget() );
1179
34636400
VZ
1180 Position xx, yy;
1181 XtVaGetValues(widget, XmNx, &xx, XmNy, &yy, NULL);
b59bf2db 1182
34636400
VZ
1183 // We may be faking the client origin. So a window that's really at (0, 30)
1184 // may appear (to wxWin apps) to be at (0, 0).
1185 if (GetParent())
b59bf2db 1186 {
34636400 1187 wxPoint pt(GetParent()->GetClientAreaOrigin());
355b4d3d
WS
1188 xx = (Position)(xx - pt.x);
1189 yy = (Position)(yy - pt.y);
b59bf2db 1190 }
34636400 1191
fc7ca9b3
MB
1192 if(x) *x = xx;
1193 if(y) *y = yy;
4bb6408c
JS
1194}
1195
af0bb3b1 1196void wxWindow::DoScreenToClient(int *x, int *y) const
4bb6408c 1197{
34636400
VZ
1198 Widget widget = (Widget) GetClientWidget();
1199 Display *display = XtDisplay((Widget) GetMainWidget());
1200 Window rootWindow = RootWindowOfScreen(XtScreen(widget));
1201 Window thisWindow = XtWindow(widget);
1202
1203 Window childWindow;
c5c01214
VZ
1204 int xx = x ? *x : 0;
1205 int yy = y ? *y : 0;
1206 XTranslateCoordinates(display, rootWindow, thisWindow,
1207 xx, yy, x ? x : &xx, y ? y : &yy,
1208 &childWindow);
4bb6408c
JS
1209}
1210
af0bb3b1 1211void wxWindow::DoClientToScreen(int *x, int *y) const
4bb6408c 1212{
34636400
VZ
1213 Widget widget = (Widget) GetClientWidget();
1214 Display *display = XtDisplay(widget);
1215 Window rootWindow = RootWindowOfScreen(XtScreen(widget));
1216 Window thisWindow = XtWindow(widget);
1217
1218 Window childWindow;
c5c01214
VZ
1219 int xx = x ? *x : 0;
1220 int yy = y ? *y : 0;
1221 XTranslateCoordinates(display, thisWindow, rootWindow,
1222 xx, yy, x ? x : &xx, y ? y : &yy,
1223 &childWindow);
4bb6408c
JS
1224}
1225
34636400
VZ
1226
1227// Get size *available for subwindows* i.e. excluding menu bar etc.
af0bb3b1 1228void wxWindow::DoGetClientSize(int *x, int *y) const
4fabb575 1229{
34636400
VZ
1230 Widget widget = (Widget) GetClientWidget();
1231 Dimension xx, yy;
1232 XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL);
f6fb552e 1233 if(x) *x = xx; if(y) *y = yy;
4fabb575
JS
1234}
1235
34636400 1236void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags)
37c997b4 1237{
96be256b 1238 DoSetSizeIntr(x, y, width, height, sizeFlags, false);
37c997b4
MB
1239}
1240
1241void wxWindow::DoSetSizeIntr(int x, int y, int width, int height,
1242 int sizeFlags, bool fromCtor)
4bb6408c 1243{
34636400 1244 // A bit of optimization to help sort out the flickers.
9577d302 1245 int oldX = -1, oldY = -1, oldW = -1, oldH = -1;
32d4c30a 1246
37c997b4
MB
1247 if( !fromCtor )
1248 {
1249 GetSize(& oldW, & oldH);
1250 GetPosition(& oldX, & oldY);
1251 }
34636400 1252
105fbe1f
MB
1253 if (x == -1)
1254 x = oldX;
1255 if (x == -1)
1256 x = oldY;
1257
9d9b7755
VZ
1258 if ( !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
1259 {
9fd8f2dd
MB
1260 if ( width == -1 )
1261 width = oldW;
1262 if ( height == -1 )
1263 height = oldH;
9d9b7755 1264 }
34636400 1265
34097680 1266 wxSize size(wxDefaultSize);
7e1bcfa8 1267 if ( width <= 0 )
fc7ca9b3 1268 {
66f8b9ac 1269 if ( ( sizeFlags & wxSIZE_AUTO_WIDTH ) && !fromCtor )
fc7ca9b3
MB
1270 {
1271 size = DoGetBestSize();
1272 width = size.x;
1273 }
1274 else
1275 {
1276 width = oldW;
1277 }
1278 }
34636400 1279
fc7ca9b3 1280 if ( height == -1 )
02800301 1281 {
66f8b9ac 1282 if( ( sizeFlags & wxSIZE_AUTO_HEIGHT ) && !fromCtor )
fc7ca9b3
MB
1283 {
1284 if( size.x == -1 ) size = DoGetBestSize();
1285 height = size.y;
1286 }
1287 else
1288 {
1289 height = oldH;
1290 }
34636400
VZ
1291 }
1292
fc7ca9b3
MB
1293 if ( x != oldX || y != oldY || width != oldW || height != oldH
1294 || !wxNoOptimize::CanOptimize() )
34636400 1295 {
9d9b7755
VZ
1296 if (m_drawingArea)
1297 {
fc7ca9b3
MB
1298 int flags = 0;
1299
9fd8f2dd 1300 if (x != oldX)
fc7ca9b3
MB
1301 flags |= wxMOVE_X;
1302
9fd8f2dd 1303 if (y != oldY)
fc7ca9b3
MB
1304 flags |= wxMOVE_Y;
1305
1306 if (width > 0)
1307 flags |= wxMOVE_WIDTH;
1308
1309 if (height > 0)
1310 flags |= wxMOVE_HEIGHT;
1311
1312 int xx = x; int yy = y;
1313 AdjustForParentClientOrigin(xx, yy, sizeFlags);
1314 if( !fromCtor )
1315 DoMoveWindow( xx, yy, width, height );
1316 else
1317 DoMoveWindowIntr( xx, yy, width, height, flags );
1318
9d9b7755
VZ
1319 return;
1320 }
34636400 1321
9d9b7755
VZ
1322 Widget widget = (Widget) GetTopWidget();
1323 if (!widget)
1324 return;
34636400 1325
9d9b7755
VZ
1326 bool managed = XtIsManaged( widget );
1327 if (managed)
1328 XtUnmanageChild(widget);
34636400 1329
9d9b7755
VZ
1330 int xx = x;
1331 int yy = y;
1332 AdjustForParentClientOrigin(xx, yy, sizeFlags);
1333
1334 DoMoveWindow(xx, yy, width, height);
34636400 1335
9d9b7755
VZ
1336 if (managed)
1337 XtManageChild(widget);
9d9b7755 1338 }
4bb6408c
JS
1339}
1340
34636400 1341void wxWindow::DoSetClientSize(int width, int height)
4bb6408c 1342{
34636400 1343 if (m_drawingArea)
4bb6408c 1344 {
fc7ca9b3
MB
1345 Widget drawingArea = (Widget) m_drawingArea;
1346
1347 XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
1348
1349 if (width > -1)
1350 XtVaSetValues(drawingArea, XmNwidth, width, NULL);
1351 if (height > -1)
1352 XtVaSetValues(drawingArea, XmNheight, height, NULL);
1353
1354 XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
34636400 1355 return;
4bb6408c 1356 }
34636400
VZ
1357
1358 Widget widget = (Widget) GetTopWidget();
1359
1360 if (width > -1)
1361 XtVaSetValues(widget, XmNwidth, width, NULL);
1362 if (height > -1)
1363 XtVaSetValues(widget, XmNheight, height, NULL);
4bb6408c
JS
1364}
1365
fc7ca9b3
MB
1366void wxWindow::DoMoveWindowIntr(int xx, int yy, int w, int h,
1367 int flags)
9d9b7755 1368{
37c997b4 1369 if (m_drawingArea)
fc7ca9b3
MB
1370 {
1371 Widget drawingArea = (Widget) m_drawingArea;
1372 Widget borderOrScrolled = m_borderWidget ?
1373 (Widget) m_borderWidget :
1374 (Widget) m_scrolledWindow;
1375
1376 bool managed = XtIsManaged(borderOrScrolled);
fc7ca9b3
MB
1377 if (managed)
1378 XtUnmanageChild (borderOrScrolled);
1379 XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
1380
1381 if (flags & wxMOVE_X)
1382 XtVaSetValues (borderOrScrolled,
1383 XmNx, xx,
1384 NULL);
1385 if (flags & wxMOVE_Y)
1386 XtVaSetValues (borderOrScrolled,
1387 XmNy, yy,
1388 NULL);
1389
1390 if (flags & wxMOVE_WIDTH)
1391 {
1392 if (m_borderWidget)
1393 {
1394 XtVaSetValues ((Widget) m_borderWidget, XmNwidth, w, NULL);
1395 short thick, margin;
1396 XtVaGetValues ((Widget) m_borderWidget,
1397 XmNshadowThickness, &thick,
1398 XmNmarginWidth, &margin,
1399 NULL);
1400 w -= 2 * (thick + margin);
1401 }
37c997b4 1402
88793548 1403 if( w < 1 ) w = 1;
fc7ca9b3
MB
1404 XtVaSetValues ((Widget) m_scrolledWindow, XmNwidth, w, NULL);
1405 }
d9d3622e 1406
fc7ca9b3
MB
1407 if (flags & wxMOVE_HEIGHT)
1408 {
1409 if (m_borderWidget)
1410 {
1411 XtVaSetValues ((Widget) m_borderWidget, XmNheight, h, NULL);
1412 short thick, margin;
1413 XtVaGetValues ((Widget) m_borderWidget,
1414 XmNshadowThickness, &thick,
1415 XmNmarginHeight, &margin,
1416 NULL);
1417 h -= 2 * (thick + margin);
1418 }
1419
88793548 1420 if( h < 1 ) h = 1;
fc7ca9b3
MB
1421 XtVaSetValues ((Widget) m_scrolledWindow, XmNheight, h, NULL);
1422 }
1423
1424 if (managed)
1425 XtManageChild (borderOrScrolled);
1426 XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
1427 }
1428 else
1429 {
1430 if( w < 1 ) w = 1;
1431 if( h < 1 ) h = 1;
1432
1433 XtVaSetValues((Widget)GetTopWidget(),
1434 XmNx, xx,
1435 XmNy, yy,
1436 XmNwidth, w,
1437 XmNheight, h,
1438 NULL);
1439 }
1440}
1441
1442void wxWindow::DoMoveWindow(int x, int y, int width, int height)
1443{
1444 DoMoveWindowIntr (x, y, width, height,
1445 wxMOVE_X|wxMOVE_Y|wxMOVE_WIDTH|wxMOVE_HEIGHT);
9d9b7755
VZ
1446}
1447
34636400
VZ
1448// ---------------------------------------------------------------------------
1449// text metrics
1450// ---------------------------------------------------------------------------
1451
1452int wxWindow::GetCharHeight() const
4bb6408c 1453{
996994c7 1454 int height;
355b4d3d 1455
a1b806b9 1456 if (m_font.IsOk())
105fbe1f
MB
1457 wxGetTextExtent (GetXDisplay(), m_font, 1.0,
1458 "x", NULL, &height, NULL, NULL);
1459 else
1460 wxGetTextExtent (this, "x", NULL, &height, NULL, NULL);
34636400 1461
996994c7 1462 return height;
4bb6408c
JS
1463}
1464
34636400 1465int wxWindow::GetCharWidth() const
4bb6408c 1466{
996994c7 1467 int width;
355b4d3d 1468
a1b806b9 1469 if (m_font.IsOk())
105fbe1f
MB
1470 wxGetTextExtent (GetXDisplay(), m_font, 1.0,
1471 "x", &width, NULL, NULL, NULL);
1472 else
1473 wxGetTextExtent (this, "x", &width, NULL, NULL, NULL);
34636400 1474
996994c7 1475 return width;
4bb6408c
JS
1476}
1477
6de70470
VZ
1478void wxWindow::DoGetTextExtent(const wxString& string,
1479 int *x, int *y,
1480 int *descent,
1481 int *externalLeading,
1482 const wxFont *theFont) const
4bb6408c 1483{
996994c7 1484 const wxFont *fontToUse = theFont ? theFont : &m_font;
34636400 1485
34636400
VZ
1486 if (externalLeading)
1487 *externalLeading = 0;
a1b806b9 1488 if (fontToUse->IsOk())
105fbe1f
MB
1489 wxGetTextExtent (GetXDisplay(), *fontToUse, 1.0,
1490 string, x, y, NULL, descent);
1491 else
1492 wxGetTextExtent (this, string, x, y, NULL, descent);
4bb6408c
JS
1493}
1494
34636400
VZ
1495// ----------------------------------------------------------------------------
1496// painting
1497// ----------------------------------------------------------------------------
4bb6408c 1498
148b44a1
MB
1499void wxWindow::AddUpdateRect(int x, int y, int w, int h)
1500{
1501 m_updateRegion.Union( x, y, w, h );
1502}
1503
34636400 1504void wxWindow::Refresh(bool eraseBack, const wxRect *rect)
4bb6408c 1505{
105fbe1f
MB
1506 Widget widget = (Widget) GetMainWidget();
1507 if (!widget)
1508 return;
96be256b 1509 m_needsRefresh = true;
105fbe1f
MB
1510 Display *display = XtDisplay(widget);
1511 Window thisWindow = XtWindow(widget);
34636400
VZ
1512
1513 XExposeEvent dummyEvent;
1514 int width, height;
1515 GetSize(&width, &height);
1516
1517 dummyEvent.type = Expose;
1518 dummyEvent.display = display;
1519 dummyEvent.send_event = True;
1520 dummyEvent.window = thisWindow;
1521 if (rect)
2d120f83 1522 {
34636400
VZ
1523 dummyEvent.x = rect->x;
1524 dummyEvent.y = rect->y;
1525 dummyEvent.width = rect->width;
1526 dummyEvent.height = rect->height;
2d120f83
JS
1527 }
1528 else
1529 {
34636400
VZ
1530 dummyEvent.x = 0;
1531 dummyEvent.y = 0;
1532 dummyEvent.width = width;
1533 dummyEvent.height = height;
2d120f83 1534 }
34636400 1535 dummyEvent.count = 0;
4bb6408c 1536
34636400 1537 if (eraseBack)
2d120f83 1538 {
34636400
VZ
1539 wxClientDC dc(this);
1540 wxBrush backgroundBrush(GetBackgroundColour(), wxSOLID);
1541 dc.SetBackground(backgroundBrush);
fce127d7
VZ
1542
1543 wxClientDCImpl * const
1544 dcimpl = static_cast<wxClientDCImpl *>(dc.GetImpl());
34636400 1545 if (rect)
fce127d7 1546 dcimpl->Clear(*rect);
34636400 1547 else
fce127d7 1548 dcimpl->Clear();
2d120f83 1549 }
4bb6408c 1550
34636400 1551 XSendEvent(display, thisWindow, False, ExposureMask, (XEvent *)&dummyEvent);
4bb6408c
JS
1552}
1553
34636400 1554void wxWindow::DoPaint()
4bb6408c 1555{
34636400
VZ
1556 //TODO : make a temporary gc so we can do the XCopyArea below
1557 if (m_backingPixmap && !m_needsRefresh)
4bb6408c 1558 {
34636400 1559 wxPaintDC dc(this);
4bb6408c 1560
fce127d7
VZ
1561 wxPaintDCImpl * const
1562 dcimpl = static_cast<wxPaintDCImpl *>(dc.GetImpl());
1563
1564 GC tempGC = (GC) dcimpl->GetBackingGC();
4bb6408c 1565
34636400 1566 Widget widget = (Widget) GetMainWidget();
4bb6408c 1567
34636400
VZ
1568 int scrollPosX = 0;
1569 int scrollPosY = 0;
4bb6408c 1570
34636400
VZ
1571 // We have to test whether it's a wxScrolledWindow (hack!) because
1572 // otherwise we don't know how many pixels have been scrolled. We might
1573 // solve this in the future by defining virtual wxWindow functions to get
1574 // the scroll position in pixels. Or, each kind of scrolled window has to
77ffb593 1575 // implement backing stores itself, using generic wxWidgets code.
34636400
VZ
1576 wxScrolledWindow* scrolledWindow = wxDynamicCast(this, wxScrolledWindow);
1577 if ( scrolledWindow )
1578 {
1579 int x, y;
1580 scrolledWindow->CalcScrolledPosition(0, 0, &x, &y);
1581
1582 scrollPosX = - x;
1583 scrollPosY = - y;
1584 }
1585
1586 // TODO: This could be optimized further by only copying the areas in the
1587 // current update region.
1588
1589 // Only blit the part visible in the client area. The backing pixmap
1590 // always starts at 0, 0 but we may be looking at only a portion of it.
1591 wxSize clientArea = GetClientSize();
1592 int toBlitX = m_pixmapWidth - scrollPosX;
1593 int toBlitY = m_pixmapHeight - scrollPosY;
1594
1595 // Copy whichever is samller, the amount of pixmap we have to copy,
1596 // or the size of the client area.
1597 toBlitX = wxMin(toBlitX, clientArea.x);
1598 toBlitY = wxMin(toBlitY, clientArea.y);
1599
1600 // Make sure we're not negative
1601 toBlitX = wxMax(0, toBlitX);
1602 toBlitY = wxMax(0, toBlitY);
1603
1604 XCopyArea
1605 (
1606 XtDisplay(widget),
1607 (Pixmap) m_backingPixmap,
1608 XtWindow (widget),
1609 tempGC,
1610 scrollPosX, scrollPosY, // Start at the scroll position
1611 toBlitX, toBlitY, // How much of the pixmap to copy
1612 0, 0 // Destination
1613 );
1614 }
1615 else
4bb6408c 1616 {
fc7ca9b3 1617 wxWindowDC dc(this);
34636400 1618 // Set an erase event first
fc7ca9b3 1619 wxEraseEvent eraseEvent(GetId(), &dc);
34636400 1620 eraseEvent.SetEventObject(this);
937013e0 1621 HandleWindowEvent(eraseEvent);
34636400
VZ
1622
1623 wxPaintEvent event(GetId());
1624 event.SetEventObject(this);
937013e0 1625 HandleWindowEvent(event);
34636400 1626
96be256b 1627 m_needsRefresh = false;
4bb6408c 1628 }
4bb6408c
JS
1629}
1630
34636400
VZ
1631// ----------------------------------------------------------------------------
1632// event handlers
1633// ----------------------------------------------------------------------------
1634
1635// Responds to colour changes: passes event on to children.
1636void wxWindow::OnSysColourChanged(wxSysColourChangedEvent& event)
4bb6408c 1637{
1807c27d 1638 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
34636400 1639 while ( node )
4bb6408c 1640 {
34636400
VZ
1641 // Only propagate to non-top-level windows
1642 wxWindow *win = node->GetData();
1643 if ( win->GetParent() )
2d120f83 1644 {
34636400 1645 wxSysColourChangedEvent event2;
687706f5 1646 event.SetEventObject(win);
937013e0 1647 win->HandleWindowEvent(event2);
2d120f83 1648 }
4bb6408c 1649
34636400 1650 node = node->GetNext();
2d120f83 1651 }
4bb6408c
JS
1652}
1653
34636400
VZ
1654// ----------------------------------------------------------------------------
1655// accelerators
1656// ----------------------------------------------------------------------------
4bb6408c 1657
34636400 1658bool wxWindow::ProcessAccelerator(wxKeyEvent& event)
4bb6408c 1659{
7e1bcfa8 1660#if wxUSE_ACCEL
a1b806b9 1661 if (!m_acceleratorTable.IsOk())
96be256b 1662 return false;
4bb6408c 1663
34636400
VZ
1664 int count = m_acceleratorTable.GetCount();
1665 wxAcceleratorEntry* entries = m_acceleratorTable.GetEntries();
1666 int i;
1667 for (i = 0; i < count; i++)
2d120f83 1668 {
34636400
VZ
1669 wxAcceleratorEntry* entry = & (entries[i]);
1670 if (entry->MatchesEvent(event))
1671 {
f6045f99 1672 // Bingo, we have a match. Now find a control that matches the
2b5f62a0 1673 // entry command id.
4bb6408c 1674
34636400
VZ
1675 // Need to go up to the top of the window hierarchy, since it might
1676 // be e.g. a menu item
1677 wxWindow* parent = this;
1678 while ( parent && !parent->IsTopLevel() )
1679 parent = parent->GetParent();
4bb6408c 1680
34636400 1681 if (!parent)
96be256b 1682 return false;
4bb6408c 1683
34636400
VZ
1684 wxFrame* frame = wxDynamicCast(parent, wxFrame);
1685 if ( frame )
1686 {
7e1bcfa8 1687#if wxUSE_MENUS
34636400
VZ
1688 // Try for a menu command
1689 if (frame->GetMenuBar())
1690 {
c71830c3 1691 wxMenuItem* item = frame->GetMenuBar()->FindItem(entry->GetCommand());
34636400
VZ
1692 if (item)
1693 {
ce7fe42e 1694 wxCommandEvent commandEvent(wxEVT_MENU, entry->GetCommand());
34636400 1695 commandEvent.SetEventObject(frame);
4bb6408c 1696
96be256b 1697 // If ProcessEvent returns true (it was handled), then
34636400 1698 // the calling code will skip the event handling.
937013e0 1699 return frame->HandleWindowEvent(commandEvent);
34636400
VZ
1700 }
1701 }
7e1bcfa8 1702#endif
34636400 1703 }
3dd4e4e0 1704
34636400
VZ
1705 // Find a child matching the command id
1706 wxWindow* child = parent->FindWindow(entry->GetCommand());
3dd4e4e0 1707
34636400
VZ
1708 // No such child
1709 if (!child)
96be256b 1710 return false;
3dd4e4e0 1711
34636400
VZ
1712 // Now we process those kinds of windows that we can.
1713 // For now, only buttons.
1714 if ( wxDynamicCast(child, wxButton) )
1715 {
ce7fe42e 1716 wxCommandEvent commandEvent (wxEVT_BUTTON, child->GetId());
34636400 1717 commandEvent.SetEventObject(child);
937013e0 1718 return child->HandleWindowEvent(commandEvent);
34636400 1719 }
3dd4e4e0 1720
96be256b 1721 return false;
34636400
VZ
1722 } // matches event
1723 }// for
7e1bcfa8 1724#endif
4bb6408c 1725
34636400 1726 // We didn't match the key event against an accelerator.
96be256b 1727 return false;
4bb6408c
JS
1728}
1729
34636400
VZ
1730// ============================================================================
1731// Motif-specific stuff from here on
1732// ============================================================================
1733
1734// ----------------------------------------------------------------------------
77ffb593 1735// function which maintain the global hash table mapping Widgets to wxWidgets
34636400
VZ
1736// ----------------------------------------------------------------------------
1737
1738bool wxAddWindowToTable(Widget w, wxWindow *win)
4bb6408c 1739{
e1bce3ca
VZ
1740 const long key = (long)w;
1741 if ( wxWidgetHashTable->Get(key))
2d120f83 1742 {
34636400 1743 wxLogDebug("Widget table clash: new widget is %ld, %s",
e1bce3ca 1744 key, win->GetClassInfo()->GetClassName());
96be256b 1745 return false;
2d120f83 1746 }
4bb6408c 1747
e1bce3ca 1748 wxWidgetHashTable->Put(key, win);
4bb6408c 1749
1bc822df 1750 wxLogTrace("widget", "Widget 0x%p <-> window %p (%s)",
e1bce3ca 1751 w, win, win->GetClassInfo()->GetClassName());
31528cd3 1752
96be256b 1753 return true;
4bb6408c
JS
1754}
1755
34636400 1756wxWindow *wxGetWindowFromTable(Widget w)
4bb6408c 1757{
33caefb3 1758 return (wxWindow *)wxWidgetHashTable->Get((long) w);
4bb6408c
JS
1759}
1760
34636400 1761void wxDeleteWindowFromTable(Widget w)
4bb6408c 1762{
fc7ca9b3
MB
1763 wxLogTrace("widget", "Widget 0x%p", (WXWidget)w);
1764
33caefb3 1765 wxWidgetHashTable->Delete((long)w);
4bb6408c
JS
1766}
1767
34636400
VZ
1768// ----------------------------------------------------------------------------
1769// add/remove window from the table
1770// ----------------------------------------------------------------------------
4bb6408c 1771
34636400 1772// Add to hash table, add event handler
af111fc3 1773bool wxWindow::AttachWidget (wxWindow* WXUNUSED(parent), WXWidget mainWidget,
34636400 1774 WXWidget formWidget, int x, int y, int width, int height)
4bb6408c 1775{
34636400 1776 wxAddWindowToTable((Widget) mainWidget, this);
a8680e3e
MB
1777 XtAddEventHandler( (Widget) mainWidget,
1778 ButtonPressMask | ButtonReleaseMask
1779 | PointerMotionMask,
1780 False,
1781 wxPanelItemEventHandler,
1782 (XtPointer) this);
4bb6408c 1783
34636400
VZ
1784 if (!formWidget)
1785 {
1786 XtTranslations ptr;
1787 XtOverrideTranslations ((Widget) mainWidget,
1788 ptr = XtParseTranslationTable ("<Configure>: resize()"));
1789 XtFree ((char *) ptr);
1790 }
4bb6408c 1791
34636400
VZ
1792 // Some widgets have a parent form widget, e.g. wxRadioBox
1793 if (formWidget)
1794 {
1795 if (!wxAddWindowToTable((Widget) formWidget, this))
96be256b 1796 return false;
4bb6408c 1797
34636400
VZ
1798 XtTranslations ptr;
1799 XtOverrideTranslations ((Widget) formWidget,
1800 ptr = XtParseTranslationTable ("<Configure>: resize()"));
1801 XtFree ((char *) ptr);
1802 }
4bb6408c 1803
24490a1c
MB
1804 if (x == -1)
1805 x = 0;
1806 if (y == -1)
1807 y = 0;
1808 DoSetSize (x, y, width, height, wxSIZE_USE_EXISTING);
4bb6408c 1809
f9204363 1810 return true;
4bb6408c
JS
1811}
1812
34636400
VZ
1813// Remove event handler, remove from hash table
1814bool wxWindow::DetachWidget(WXWidget widget)
4bb6408c 1815{
a8680e3e
MB
1816 XtRemoveEventHandler( (Widget) widget,
1817 ButtonPressMask | ButtonReleaseMask
1818 | PointerMotionMask,
1819 False,
1820 wxPanelItemEventHandler,
1821 (XtPointer)this);
4bb6408c 1822
34636400 1823 wxDeleteWindowFromTable((Widget) widget);
96be256b 1824 return true;
4bb6408c
JS
1825}
1826
34636400
VZ
1827// ----------------------------------------------------------------------------
1828// Motif-specific accessors
1829// ----------------------------------------------------------------------------
2d120f83 1830
1807c27d
MB
1831WXWindow wxWindow::GetClientXWindow() const
1832{
1833 Widget wMain = (Widget)GetClientWidget();
1834 if ( wMain )
1835 return (WXWindow) XtWindow(wMain);
1836 else
1837 return (WXWindow) 0;
1838}
1839
34636400 1840// Get the underlying X window
4bb6408c
JS
1841WXWindow wxWindow::GetXWindow() const
1842{
af0bb3b1 1843 Widget wMain = (Widget)GetMainWidget();
34636400
VZ
1844 if ( wMain )
1845 return (WXWindow) XtWindow(wMain);
ad813b00
JS
1846 else
1847 return (WXWindow) 0;
4bb6408c
JS
1848}
1849
34636400 1850// Get the underlying X display
4bb6408c
JS
1851WXDisplay *wxWindow::GetXDisplay() const
1852{
af0bb3b1 1853 Widget wMain = (Widget)GetMainWidget();
34636400
VZ
1854 if ( wMain )
1855 return (WXDisplay*) XtDisplay(wMain);
ad813b00 1856 else
d3b9f782 1857 return NULL;
4bb6408c
JS
1858}
1859
1860WXWidget wxWindow::GetMainWidget() const
1861{
50414e24 1862 if (m_drawingArea)
2d120f83 1863 return m_drawingArea;
50414e24 1864 else
2d120f83 1865 return m_mainWidget;
50414e24
JS
1866}
1867
1868WXWidget wxWindow::GetClientWidget() const
1869{
1870 if (m_drawingArea != (WXWidget) 0)
1871 return m_drawingArea;
1872 else
02e8b2f9
JS
1873 return GetMainWidget();
1874}
1875
1876WXWidget wxWindow::GetTopWidget() const
1877{
1878 return GetMainWidget();
4bb6408c
JS
1879}
1880
34636400
VZ
1881WXWidget wxWindow::GetLabelWidget() const
1882{
1883 return GetMainWidget();
1884}
1885
1886// ----------------------------------------------------------------------------
1887// Motif callbacks
1888// ----------------------------------------------------------------------------
1889
1890// All widgets should have this as their resize proc.
1891// OnSize sent to wxWindow via client data.
66f8b9ac
MB
1892void wxWidgetResizeProc(Widget w, XConfigureEvent *WXUNUSED(event),
1893 String WXUNUSED(args)[], int *WXUNUSED(num_args))
34636400
VZ
1894{
1895 wxWindow *win = wxGetWindowFromTable(w);
1896 if (!win)
1897 return;
1898
1899 if (win->PreResize())
1900 {
355b4d3d
WS
1901 wxSize newSize(win->GetSize());
1902 wxSizeEvent sizeEvent(newSize, win->GetId());
34636400 1903 sizeEvent.SetEventObject(win);
937013e0 1904 win->HandleWindowEvent(sizeEvent);
34636400
VZ
1905 }
1906}
1907
1908static void wxCanvasRepaintProc(Widget drawingArea,
1909 XtPointer clientData,
1910 XmDrawingAreaCallbackStruct * cbs)
50414e24 1911{
34636400 1912 if (!wxGetWindowFromTable(drawingArea))
2d120f83 1913 return;
34636400 1914
50414e24 1915 XEvent * event = cbs->event;
55acd85e 1916 wxWindow * win = (wxWindow *) clientData;
34636400 1917
50414e24
JS
1918 switch (event->type)
1919 {
2d120f83 1920 case Expose:
55acd85e 1921 {
6970c7b9
MB
1922 win->AddUpdateRect(event->xexpose.x, event->xexpose.y,
1923 event->xexpose.width, event->xexpose.height);
148b44a1 1924
55acd85e
JS
1925 if (event -> xexpose.count == 0)
1926 {
a91b47e8 1927 win->DoPaint();
55acd85e
JS
1928 }
1929 break;
1930 }
50414e24 1931 }
50414e24
JS
1932}
1933
1934// Unable to deal with Enter/Leave without a separate EventHandler (Motif 1.1.4)
34636400 1935static void wxCanvasEnterLeave(Widget drawingArea,
af111fc3 1936 XtPointer WXUNUSED(clientData),
34636400 1937 XCrossingEvent * event)
50414e24 1938{
2d120f83
JS
1939 XmDrawingAreaCallbackStruct cbs;
1940 XEvent ev;
34636400 1941
2d120f83 1942 ((XCrossingEvent &) ev) = *event;
34636400 1943
2d120f83
JS
1944 cbs.reason = XmCR_INPUT;
1945 cbs.event = &ev;
34636400
VZ
1946
1947 wxCanvasInputEvent(drawingArea, (XtPointer) NULL, &cbs);
50414e24
JS
1948}
1949
1950// Fix to make it work under Motif 1.0 (!)
da494b40
MB
1951static void wxCanvasMotionEvent (Widget WXUNUSED(drawingArea),
1952 XButtonEvent *WXUNUSED(event))
50414e24 1953{
34636400 1954#if XmVersion <= 1000
2d120f83
JS
1955 XmDrawingAreaCallbackStruct cbs;
1956 XEvent ev;
34636400 1957
2d120f83
JS
1958 ev = *((XEvent *) event);
1959 cbs.reason = XmCR_INPUT;
1960 cbs.event = &ev;
34636400 1961
2d120f83 1962 wxCanvasInputEvent (drawingArea, (XtPointer) NULL, &cbs);
34636400 1963#endif // XmVersion <= 1000
50414e24
JS
1964}
1965
34636400 1966static void wxCanvasInputEvent(Widget drawingArea,
af111fc3 1967 XtPointer WXUNUSED(data),
34636400 1968 XmDrawingAreaCallbackStruct * cbs)
50414e24 1969{
34636400 1970 wxWindow *canvas = wxGetWindowFromTable(drawingArea);
2a23a89d 1971 XEvent* xevent = cbs->event;
34636400 1972
2d120f83 1973 if (canvas==NULL)
34636400
VZ
1974 return;
1975
2d120f83
JS
1976 if (cbs->reason != XmCR_INPUT)
1977 return;
34636400 1978
2a23a89d 1979 switch (xevent->xany.type)
50414e24
JS
1980 {
1981 case EnterNotify:
1982 case LeaveNotify:
1983 case ButtonPress:
1984 case ButtonRelease:
1985 case MotionNotify:
2d120f83 1986 {
2a23a89d
MB
1987 wxMouseEvent wxevent(0);
1988 if (wxTranslateMouseEvent(wxevent, canvas, drawingArea, xevent))
e700df04 1989 {
937013e0 1990 canvas->HandleWindowEvent(wxevent);
e700df04 1991 }
e700df04 1992 break;
2a23a89d 1993 }
50414e24 1994 case KeyPress:
50414e24 1995 {
2b5f62a0 1996 wxKeyEvent event (wxEVT_CHAR);
2a23a89d 1997 if (wxTranslateKeyEvent (event, canvas, (Widget) 0, xevent))
2d120f83
JS
1998 {
1999 // Implement wxFrame::OnCharHook by checking ancestor.
66f8b9ac
MB
2000 wxWindow *parent = canvas;
2001 while (parent && !parent->IsTopLevel())
2d120f83 2002 parent = parent->GetParent();
34636400 2003
2d120f83
JS
2004 if (parent)
2005 {
2006 event.SetEventType(wxEVT_CHAR_HOOK);
937013e0 2007 if (parent->HandleWindowEvent(event))
2d120f83 2008 return;
2d120f83 2009 }
a91b47e8
JS
2010
2011 // For simplicity, OnKeyDown is the same as OnChar
2012 // TODO: filter modifier key presses from OnChar
2013 event.SetEventType(wxEVT_KEY_DOWN);
2014
2015 // Only process OnChar if OnKeyDown didn't swallow it
937013e0 2016 if (!canvas->HandleWindowEvent (event))
a91b47e8 2017 {
66f8b9ac 2018 event.SetEventType(wxEVT_CHAR);
937013e0 2019 canvas->HandleWindowEvent (event);
66f8b9ac 2020 }
2d120f83
JS
2021 }
2022 break;
2023 }
2024 case KeyRelease:
2025 {
2d120f83 2026 wxKeyEvent event (wxEVT_KEY_UP);
2a23a89d 2027 if (wxTranslateKeyEvent (event, canvas, (Widget) 0, xevent))
2d120f83 2028 {
937013e0 2029 canvas->HandleWindowEvent (event);
2d120f83
JS
2030 }
2031 break;
50414e24 2032 }
50414e24 2033 case FocusIn:
2d120f83 2034 {
2a23a89d 2035 if (xevent->xfocus.detail != NotifyPointer)
2d120f83
JS
2036 {
2037 wxFocusEvent event(wxEVT_SET_FOCUS, canvas->GetId());
2038 event.SetEventObject(canvas);
937013e0 2039 canvas->HandleWindowEvent(event);
2d120f83
JS
2040 }
2041 break;
50414e24 2042 }
50414e24 2043 case FocusOut:
2d120f83 2044 {
2a23a89d 2045 if (xevent->xfocus.detail != NotifyPointer)
2d120f83
JS
2046 {
2047 wxFocusEvent event(wxEVT_KILL_FOCUS, canvas->GetId());
2048 event.SetEventObject(canvas);
937013e0 2049 canvas->HandleWindowEvent(event);
2d120f83
JS
2050 }
2051 break;
2052 }
50414e24 2053 default:
2d120f83 2054 break;
50414e24
JS
2055 }
2056}
2057
34636400 2058static void wxPanelItemEventHandler(Widget wid,
af111fc3 2059 XtPointer WXUNUSED(client_data),
34636400
VZ
2060 XEvent* event,
2061 Boolean *continueToDispatch)
50414e24 2062{
34636400 2063 // Widget can be a label or the actual widget.
a91b47e8 2064
af0bb3b1 2065 wxWindow *window = wxGetWindowFromTable(wid);
34636400
VZ
2066 if (window)
2067 {
2068 wxMouseEvent wxevent(0);
2069 if (wxTranslateMouseEvent(wxevent, window, wid, event))
2070 {
937013e0 2071 window->HandleWindowEvent(wxevent);
34636400
VZ
2072 }
2073 }
a91b47e8 2074
34636400 2075 // TODO: probably the key to allowing default behaviour to happen. Say we
96be256b 2076 // set a m_doDefault flag to false at the start of this function. Then in
34636400 2077 // e.g. wxWindow::OnMouseEvent we can call Default() which sets this flag to
96be256b 2078 // true, indicating that default processing can happen. Thus, behaviour can
34636400
VZ
2079 // appear to be overridden just by adding an event handler and not calling
2080 // wxWindow::OnWhatever. ALSO, maybe we can use this instead of the current
2081 // way of handling drawing area events, to simplify things.
2082 *continueToDispatch = True;
2083}
a91b47e8 2084
34636400
VZ
2085static void wxScrollBarCallback(Widget scrollbar,
2086 XtPointer clientData,
311227c3 2087 XmScrollBarCallbackStruct *cbs)
34636400 2088{
34636400 2089 wxWindow *win = wxGetWindowFromTable(scrollbar);
9a83f860 2090 wxCHECK_RET( win, wxT("invalid widget in scrollbar callback") );
29014baa 2091
a4588fd1 2092 wxOrientation orientation = (wxOrientation)wxPtrToUInt(clientData);
a91b47e8 2093
34636400
VZ
2094 wxEventType eventType = wxEVT_NULL;
2095 switch (cbs->reason)
2096 {
2097 case XmCR_INCREMENT:
2098 {
311227c3 2099 eventType = wxEVT_SCROLLWIN_LINEDOWN;
34636400
VZ
2100 break;
2101 }
2102 case XmCR_DECREMENT:
2103 {
311227c3 2104 eventType = wxEVT_SCROLLWIN_LINEUP;
34636400
VZ
2105 break;
2106 }
2107 case XmCR_DRAG:
2108 {
311227c3 2109 eventType = wxEVT_SCROLLWIN_THUMBTRACK;
34636400
VZ
2110 break;
2111 }
2112 case XmCR_VALUE_CHANGED:
2113 {
bdeca1d1 2114 eventType = wxEVT_SCROLLWIN_THUMBRELEASE;
34636400
VZ
2115 break;
2116 }
2117 case XmCR_PAGE_INCREMENT:
2118 {
311227c3 2119 eventType = wxEVT_SCROLLWIN_PAGEDOWN;
34636400
VZ
2120 break;
2121 }
2122 case XmCR_PAGE_DECREMENT:
2123 {
311227c3 2124 eventType = wxEVT_SCROLLWIN_PAGEUP;
34636400
VZ
2125 break;
2126 }
2127 case XmCR_TO_TOP:
2128 {
311227c3 2129 eventType = wxEVT_SCROLLWIN_TOP;
34636400
VZ
2130 break;
2131 }
2132 case XmCR_TO_BOTTOM:
2133 {
311227c3 2134 eventType = wxEVT_SCROLLWIN_BOTTOM;
34636400
VZ
2135 break;
2136 }
2137 default:
2138 {
2139 // Should never get here
2140 wxFAIL_MSG("Unknown scroll event.");
2141 break;
2142 }
2143 }
a91b47e8 2144
311227c3
MB
2145 wxScrollWinEvent event(eventType,
2146 cbs->value,
148b44a1 2147 orientation);
311227c3 2148 event.SetEventObject( win );
937013e0 2149 win->HandleWindowEvent(event);
34636400 2150}
a91b47e8 2151
34636400
VZ
2152// For repainting arbitrary windows
2153void wxUniversalRepaintProc(Widget w, XtPointer WXUNUSED(c_data), XEvent *event, char *)
2154{
34636400
VZ
2155 wxWindow* win = wxGetWindowFromTable(w);
2156 if (!win)
2157 return;
a91b47e8 2158
e1bce3ca 2159 switch ( event->type )
50414e24 2160 {
e1bce3ca 2161 case Expose:
34636400 2162 {
148b44a1
MB
2163 win->AddUpdateRect(event->xexpose.x, event->xexpose.y,
2164 event->xexpose.width, event->xexpose.height);
2165
3f97d339 2166 if ( event->xexpose.count == 0 )
34636400
VZ
2167 {
2168 win->DoPaint();
af0bb3b1
VZ
2169 }
2170
34636400
VZ
2171 break;
2172 }
50414e24
JS
2173 }
2174}
2175
34636400
VZ
2176// ----------------------------------------------------------------------------
2177// TranslateXXXEvent() functions
2178// ----------------------------------------------------------------------------
2179
a8680e3e 2180bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win,
2a23a89d 2181 Widget widget, const XEvent *xevent)
02e8b2f9 2182{
2d120f83
JS
2183 switch (xevent->xany.type)
2184 {
a8680e3e
MB
2185 case EnterNotify:
2186 case LeaveNotify:
2187#if 0
2188 fprintf(stderr, "Widget 0x%p <-> window %p (%s), %s\n",
2189 (WXWidget)widget, win, win->GetClassInfo()->GetClassName(),
2190 (xevent->xany.type == EnterNotify ? "ENTER" : "LEAVE"));
2191#endif
1e8abce5
MB
2192 case ButtonPress:
2193 case ButtonRelease:
2194 case MotionNotify:
02e8b2f9 2195 {
2a23a89d
MB
2196 int eventx = xevent->xbutton.x, eventy = xevent->xbutton.y;
2197
2d120f83 2198 wxEventType eventType = wxEVT_NULL;
34636400 2199
2d120f83
JS
2200 if (xevent->xany.type == LeaveNotify)
2201 {
a8680e3e
MB
2202 eventType = wxEVT_LEAVE_WINDOW;
2203 }
2204 if (xevent->xany.type == EnterNotify)
2205 {
2206 eventType = wxEVT_ENTER_WINDOW;
2d120f83
JS
2207 }
2208 else if (xevent->xany.type == MotionNotify)
2209 {
2210 eventType = wxEVT_MOTION;
2a23a89d
MB
2211
2212 if (xevent->xmotion.is_hint == NotifyHint)
2213 {
2214 Window root, child;
2215 int x_root, y_root;
2216 unsigned int state;
2217 Display *dpy = XtDisplay (widget);
2218
2219 XQueryPointer (dpy, XtWindow (widget),
2220 &root, &child,
2221 &x_root, &y_root, &eventx, &eventy, &state);
2222 }
2d120f83
JS
2223 }
2224 else if (xevent->xany.type == ButtonPress)
2225 {
1e8abce5
MB
2226 wxevent.SetTimestamp(xevent->xbutton.time);
2227 int button = 0;
2d120f83
JS
2228 if (xevent->xbutton.button == Button1)
2229 {
2230 eventType = wxEVT_LEFT_DOWN;
1e8abce5 2231 button = 1;
2d120f83
JS
2232 }
2233 else if (xevent->xbutton.button == Button2)
2234 {
2235 eventType = wxEVT_MIDDLE_DOWN;
1e8abce5 2236 button = 2;
2d120f83
JS
2237 }
2238 else if (xevent->xbutton.button == Button3)
2239 {
2240 eventType = wxEVT_RIGHT_DOWN;
1e8abce5
MB
2241 button = 3;
2242 }
2243
2244 // check for a double click
2245 //
eb6fa4b4 2246 long dclickTime = XtGetMultiClickTime(xevent->xany.display);
1e8abce5
MB
2247 long ts = wxevent.GetTimestamp();
2248
2249 int buttonLast = win->GetLastClickedButton();
2250 long lastTS = win->GetLastClickTime();
a8680e3e
MB
2251 if ( buttonLast && buttonLast == button &&
2252 (ts - lastTS) < dclickTime )
1e8abce5
MB
2253 {
2254 // I have a dclick
2255 win->SetLastClick(0, ts);
205c0389
VZ
2256 if ( eventType == wxEVT_LEFT_DOWN )
2257 eventType = wxEVT_LEFT_DCLICK;
2258 else if ( eventType == wxEVT_MIDDLE_DOWN )
2259 eventType = wxEVT_MIDDLE_DCLICK;
2260 else if ( eventType == wxEVT_RIGHT_DOWN )
2261 eventType = wxEVT_RIGHT_DCLICK;
1e8abce5
MB
2262 }
2263 else
2264 {
2265 // not fast enough or different button
2266 win->SetLastClick(button, ts);
2d120f83
JS
2267 }
2268 }
2269 else if (xevent->xany.type == ButtonRelease)
2270 {
2271 if (xevent->xbutton.button == Button1)
2272 {
2273 eventType = wxEVT_LEFT_UP;
2d120f83
JS
2274 }
2275 else if (xevent->xbutton.button == Button2)
2276 {
2277 eventType = wxEVT_MIDDLE_UP;
2d120f83
JS
2278 }
2279 else if (xevent->xbutton.button == Button3)
2280 {
2281 eventType = wxEVT_RIGHT_UP;
2d120f83 2282 }
a8680e3e 2283 else
96be256b 2284 return false;
2d120f83 2285 }
af0bb3b1
VZ
2286 else
2287 {
96be256b 2288 return false;
af0bb3b1 2289 }
34636400 2290
2d120f83 2291 wxevent.SetEventType(eventType);
34636400 2292
2d120f83
JS
2293 Position x1, y1;
2294 XtVaGetValues(widget, XmNx, &x1, XmNy, &y1, NULL);
34636400 2295
2d120f83
JS
2296 int x2, y2;
2297 win->GetPosition(&x2, &y2);
34636400 2298
77ffb593 2299 // The button x/y must be translated to wxWidgets
2d120f83
JS
2300 // window space - the widget might be a label or button,
2301 // within a form.
2302 int dx = 0;
2303 int dy = 0;
2304 if (widget != (Widget)win->GetMainWidget())
2305 {
2306 dx = x1;
2307 dy = y1;
2308 }
34636400 2309
2a23a89d
MB
2310 wxevent.m_x = eventx + dx;
2311 wxevent.m_y = eventy + dy;
34636400 2312
2d120f83 2313 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
34636400 2314 || (event_left_is_down (xevent)
2d120f83
JS
2315 && (eventType != wxEVT_LEFT_UP)));
2316 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
34636400 2317 || (event_middle_is_down (xevent)
2d120f83
JS
2318 && (eventType != wxEVT_MIDDLE_UP)));
2319 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
34636400 2320 || (event_right_is_down (xevent)
2d120f83 2321 && (eventType != wxEVT_RIGHT_UP)));
34636400 2322
355b4d3d
WS
2323 wxevent.m_shiftDown = (xevent->xbutton.state & ShiftMask) == ShiftMask;
2324 wxevent.m_controlDown = (xevent->xbutton.state & ControlMask) == ControlMask;
2325 wxevent.m_altDown = (xevent->xbutton.state & Mod3Mask) == Mod3Mask;
2326 wxevent.m_metaDown = (xevent->xbutton.state & Mod1Mask) == Mod1Mask;
1e8abce5
MB
2327
2328 wxevent.SetId(win->GetId());
2329 wxevent.SetEventObject(win);
2330
96be256b 2331 return true;
2d120f83 2332 }
02e8b2f9 2333 }
96be256b 2334 return false;
02e8b2f9
JS
2335}
2336
fc7ca9b3 2337bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win,
2a23a89d 2338 Widget WXUNUSED(widget), const XEvent *xevent)
02e8b2f9 2339{
2d120f83
JS
2340 switch (xevent->xany.type)
2341 {
02e8b2f9 2342 case KeyPress:
4a041f2f 2343 case KeyRelease:
2d120f83
JS
2344 {
2345 char buf[20];
34636400 2346
2d120f83 2347 KeySym keySym;
fc7ca9b3 2348 (void) XLookupString((XKeyEvent *)xevent, buf, 20, &keySym, NULL);
2d120f83 2349 int id = wxCharCodeXToWX (keySym);
2b5f62a0
VZ
2350 // id may be WXK_xxx code - these are outside ASCII range, so we
2351 // can't just use toupper() on id
2352 if (id >= 'a' && id <= 'z')
2353 id = toupper(id);
34636400 2354
2d120f83 2355 if (xevent->xkey.state & ShiftMask)
96be256b 2356 wxevent.m_shiftDown = true;
2d120f83 2357 if (xevent->xkey.state & ControlMask)
96be256b 2358 wxevent.m_controlDown = true;
2d120f83 2359 if (xevent->xkey.state & Mod3Mask)
96be256b 2360 wxevent.m_altDown = true;
2d120f83 2361 if (xevent->xkey.state & Mod1Mask)
96be256b 2362 wxevent.m_metaDown = true;
2d120f83
JS
2363 wxevent.SetEventObject(win);
2364 wxevent.m_keyCode = id;
2365 wxevent.SetTimestamp(xevent->xkey.time);
34636400 2366
2d120f83
JS
2367 wxevent.m_x = xevent->xbutton.x;
2368 wxevent.m_y = xevent->xbutton.y;
34636400 2369
2d120f83 2370 if (id > -1)
96be256b 2371 return true;
355b4d3d
WS
2372
2373 return false;
2d120f83 2374 }
02e8b2f9 2375 default:
2d120f83
JS
2376 break;
2377 }
96be256b 2378 return false;
02e8b2f9
JS
2379}
2380
34636400
VZ
2381// ----------------------------------------------------------------------------
2382// Colour stuff
2383// ----------------------------------------------------------------------------
2384
02e8b2f9 2385#define YAllocColor XAllocColor
0d57be45 2386XColor g_itemColors[5];
f516d986 2387int wxComputeColours (Display *display, const wxColour * back, const wxColour * fore)
02e8b2f9 2388{
2d120f83
JS
2389 int result;
2390 static XmColorProc colorProc;
34636400 2391
2d120f83 2392 result = wxNO_COLORS;
34636400 2393
2d120f83 2394 if (back)
02e8b2f9 2395 {
355b4d3d
WS
2396 g_itemColors[0].red = (unsigned short)(((long) back->Red ()) << 8);
2397 g_itemColors[0].green = (unsigned short)(((long) back->Green ()) << 8);
2398 g_itemColors[0].blue = (unsigned short)(((long) back->Blue ()) << 8);
2d120f83
JS
2399 g_itemColors[0].flags = DoRed | DoGreen | DoBlue;
2400 if (colorProc == (XmColorProc) NULL)
2401 {
2402 // Get a ptr to the actual function
2403 colorProc = XmSetColorCalculation ((XmColorProc) NULL);
2404 // And set it back to motif.
2405 XmSetColorCalculation (colorProc);
2406 }
2407 (*colorProc) (&g_itemColors[wxBACK_INDEX],
2408 &g_itemColors[wxFORE_INDEX],
2409 &g_itemColors[wxSELE_INDEX],
2410 &g_itemColors[wxTOPS_INDEX],
2411 &g_itemColors[wxBOTS_INDEX]);
2412 result = wxBACK_COLORS;
02e8b2f9 2413 }
2d120f83 2414 if (fore)
02e8b2f9 2415 {
355b4d3d
WS
2416 g_itemColors[wxFORE_INDEX].red = (unsigned short)(((long) fore->Red ()) << 8);
2417 g_itemColors[wxFORE_INDEX].green = (unsigned short)(((long) fore->Green ()) << 8);
2418 g_itemColors[wxFORE_INDEX].blue = (unsigned short)(((long) fore->Blue ()) << 8);
2d120f83
JS
2419 g_itemColors[wxFORE_INDEX].flags = DoRed | DoGreen | DoBlue;
2420 if (result == wxNO_COLORS)
2421 result = wxFORE_COLORS;
02e8b2f9 2422 }
34636400 2423
2d120f83
JS
2424 Display *dpy = display;
2425 Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy);
34636400 2426
2d120f83 2427 if (back)
02e8b2f9 2428 {
2d120f83
JS
2429 /* 5 Colours to allocate */
2430 for (int i = 0; i < 5; i++)
2431 if (!YAllocColor (dpy, cmap, &g_itemColors[i]))
2432 result = wxNO_COLORS;
02e8b2f9 2433 }
2d120f83 2434 else if (fore)
02e8b2f9 2435 {
2d120f83
JS
2436 /* Only 1 colour to allocate */
2437 if (!YAllocColor (dpy, cmap, &g_itemColors[wxFORE_INDEX]))
2438 result = wxNO_COLORS;
02e8b2f9 2439 }
34636400 2440
fc7ca9b3 2441 return result;
02e8b2f9
JS
2442}
2443
34636400
VZ
2444// Changes the foreground and background colours to be derived from the current
2445// background colour. To change the foreground colour, you must call
2446// SetForegroundColour explicitly.
0d57be45 2447void wxWindow::ChangeBackgroundColour()
02e8b2f9 2448{
34636400
VZ
2449 WXWidget mainWidget = GetMainWidget();
2450 if ( mainWidget )
a8680e3e 2451 wxDoChangeBackgroundColour(mainWidget, m_backgroundColour);
24490a1c
MB
2452 if ( m_scrolledWindow && mainWidget != m_scrolledWindow )
2453 wxDoChangeForegroundColour(m_scrolledWindow, m_backgroundColour);
0d57be45 2454}
02e8b2f9 2455
0d57be45
JS
2456void wxWindow::ChangeForegroundColour()
2457{
34636400
VZ
2458 WXWidget mainWidget = GetMainWidget();
2459 if ( mainWidget )
a8680e3e 2460 wxDoChangeForegroundColour(mainWidget, m_foregroundColour);
34636400 2461 if ( m_scrolledWindow && mainWidget != m_scrolledWindow )
a8680e3e 2462 wxDoChangeForegroundColour(m_scrolledWindow, m_foregroundColour);
02e8b2f9
JS
2463}
2464
af0bb3b1 2465bool wxWindow::SetBackgroundColour(const wxColour& col)
02e8b2f9 2466{
af0bb3b1 2467 if ( !wxWindowBase::SetBackgroundColour(col) )
96be256b 2468 return false;
af0bb3b1 2469
0d57be45 2470 ChangeBackgroundColour();
af0bb3b1 2471
96be256b 2472 return true;
0d57be45
JS
2473}
2474
af0bb3b1 2475bool wxWindow::SetForegroundColour(const wxColour& col)
0d57be45 2476{
af0bb3b1 2477 if ( !wxWindowBase::SetForegroundColour(col) )
96be256b 2478 return false;
af0bb3b1 2479
0d57be45 2480 ChangeForegroundColour();
af0bb3b1 2481
96be256b 2482 return true;
0d57be45
JS
2483}
2484
4b5f3fe6 2485void wxWindow::ChangeFont(bool keepOriginalSize)
0d57be45
JS
2486{
2487 // Note that this causes the widget to be resized back
2488 // to its original size! We therefore have to set the size
2489 // back again. TODO: a better way in Motif?
0d57be45 2490 Widget w = (Widget) GetLabelWidget(); // Usually the main widget
a1b806b9 2491 if (w && m_font.IsOk())
0d57be45
JS
2492 {
2493 int width, height, width1, height1;
2494 GetSize(& width, & height);
34636400 2495
105fbe1f 2496 wxDoChangeFont( w, m_font );
34636400 2497
0d57be45 2498 GetSize(& width1, & height1);
4b5f3fe6 2499 if (keepOriginalSize && (width != width1 || height != height1))
0d57be45 2500 {
9b5f1895 2501 SetSize(wxDefaultCoord, wxDefaultCoord, width, height);
0d57be45
JS
2502 }
2503 }
02e8b2f9 2504}
0d57be45 2505
105fbe1f
MB
2506// Post-creation
2507void wxWindow::PostCreation()
2508{
2509 ChangeFont();
2510 ChangeForegroundColour();
2511 ChangeBackgroundColour();
2512}
2513
2514// Pre-creation
2515void wxWindow::PreCreation()
2516{
2517 InheritAttributes();
2518}
2519
34636400
VZ
2520// ----------------------------------------------------------------------------
2521// global functions
2522// ----------------------------------------------------------------------------
0d57be45 2523
34636400 2524wxWindow *wxGetActiveWindow()
1f112209
JS
2525{
2526 // TODO
9b8f6fa2 2527 wxFAIL_MSG("Not implemented");
34636400 2528 return NULL;
1f112209
JS
2529}
2530
9806a47c
JS
2531/* static */
2532wxWindow *wxWindowBase::GetCapture()
2533{
2534 return (wxWindow *)g_captureWindow;
2535}
2536
2537
3723b7b1
JS
2538// Find the wxWindow at the current mouse position, returning the mouse
2539// position.
2e2a55b2 2540wxWindow* wxFindWindowAtPointer(wxPoint& pt)
3723b7b1 2541{
2e2a55b2
MW
2542 pt = wxGetMousePosition();
2543 return wxFindWindowAtPoint(pt);
3723b7b1
JS
2544}
2545
0cbc5287 2546void wxGetMouseState(int& rootX, int& rootY, unsigned& maskReturn)
3723b7b1 2547{
eb6fa4b4 2548 Display *display = wxGlobalDisplay();
59a12e90
JS
2549 Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
2550 Window rootReturn, childReturn;
0cbc5287 2551 int winX, winY;
59a12e90
JS
2552
2553 XQueryPointer (display,
2b5f62a0
VZ
2554 rootWindow,
2555 &rootReturn,
59a12e90
JS
2556 &childReturn,
2557 &rootX, &rootY, &winX, &winY, &maskReturn);
0cbc5287
MW
2558}
2559
2560// Get the current mouse position.
2561wxPoint wxGetMousePosition()
2562{
2563 int x, y;
2564 unsigned mask;
2565
2566 wxGetMouseState(x, y, mask);
2567 return wxPoint(x, y);
2568}
2569
2570wxMouseState wxGetMouseState()
2571{
2572 wxMouseState ms;
2573 int x, y;
2574 unsigned mask;
2575
2576 wxGetMouseState(x, y, mask);
2577
2578 ms.SetX(x);
2579 ms.SetY(y);
2580
2581 ms.SetLeftDown(mask & Button1Mask);
2582 ms.SetMiddleDown(mask & Button2Mask);
2583 ms.SetRightDown(mask & Button3Mask);
2584
2585 ms.SetControlDown(mask & ControlMask);
2586 ms.SetShiftDown(mask & ShiftMask);
af1a6227
MW
2587 ms.SetAltDown(mask & Mod3Mask);
2588 ms.SetMetaDown(mask & Mod1Mask);
0cbc5287
MW
2589
2590 return ms;
3723b7b1
JS
2591}
2592
9806a47c 2593
105fbe1f
MB
2594#if wxMOTIF_NEW_FONT_HANDLING
2595
2596#include <Xm/XmP.h>
2597
2598void wxGetTextExtent(const wxWindow* window, const wxString& str,
2599 int* width, int* height, int* ascent, int* descent)
2600{
2601 Arg args[2];
2602 int count = 0;
2603 XmRendition rendition = NULL;
2604 XmRenderTable table = NULL;
2605 Widget w = (Widget) window->GetLabelWidget();
2606
2607 XtVaGetValues( w, XmNrenderTable, &table, NULL );
2608 if (table == NULL)
2609 table = XmeGetDefaultRenderTable(w, XmTEXT_RENDER_TABLE);
2610
2611 rendition = XmRenderTableGetRendition( table, "" );
2612 XtSetArg( args[count], XmNfont, 0 ); ++count;
2613 XtSetArg( args[count], XmNfontType, 0 ); ++count;
2614 XmRenditionRetrieve( rendition, args, count );
2615
2616 if (args[1].value == XmFONT_IS_FONTSET)
2617 {
2618 XRectangle ink, logical;
2619 WXFontSet fset = (WXFontSet) args[0].value;
24bd6cb9 2620
105fbe1f
MB
2621 XmbTextExtents( (XFontSet)fset, str.c_str(), str.length(),
2622 &ink, &logical);
2623
2624 if( width ) *width = logical.width;
2625 if( height ) *height = logical.height;
24bd6cb9
JS
2626 if( ascent ) *ascent = -logical.y;
2627 if( descent ) *descent = logical.height + logical.y;
105fbe1f
MB
2628 }
2629 else
2630 {
2631 int direction, ascent2, descent2;
2632 XCharStruct overall;
2633 XFontStruct* fontStruct;
2634
2635 XmeRenderTableGetDefaultFont( table, &fontStruct );
2636 XTextExtents(fontStruct, (const char*)str.c_str(), str.length(),
2637 &direction, &ascent2, &descent2, &overall);
2638
2639 if ( width ) *width = overall.width;
2640 if ( height ) *height = ascent2 + descent2;
2641 if ( descent ) *descent = descent2;
2642 if ( ascent ) *ascent = ascent2;
2643 }
2644}
2645
2646#else // if !wxMOTIF_NEW_FONT_HANDLING
2647
2648void wxGetTextExtent(const wxWindow* window, const wxString& str,
2649 int* width, int* height, int* ascent, int* descent)
2650{
2651 XmFontList list = NULL;
2652 XmFontContext cxt;
2653 XmFontType type;
2654 Widget w = (Widget) window->GetLabelWidget();
2655
2656 XtVaGetValues( w, XmNfontList, &list, NULL );
2657 XmFontListInitFontContext( &cxt, list );
2658
2659 XmFontListEntry entry = XmFontListNextEntry( cxt );
2660 XmFontListFreeFontContext( cxt );
2661 XtPointer thing = XmFontListEntryGetFont( entry, &type );
2662
2663 if (type == XmFONT_IS_FONTSET)
2664 {
2665 XRectangle ink, logical;
24bd6cb9 2666
105fbe1f
MB
2667 XmbTextExtents( (XFontSet)thing, str.c_str(), str.length(),
2668 &ink, &logical);
2669
2670 if( width ) *width = logical.width;
2671 if( height ) *height = logical.height;
24bd6cb9
JS
2672 if( ascent ) *ascent = -logical.y;
2673 if( descent ) *descent = logical.height + logical.y;
105fbe1f
MB
2674 }
2675 else
2676 {
2677 int direction, ascent2, descent2;
2678 XCharStruct overall;
2679
2680 XTextExtents( (XFontStruct*)thing, (char*)(const char*)str.c_str(), str.length(),
2681 &direction, &ascent2, &descent2, &overall);
2682
2683 if ( width ) *width = overall.width;
2684 if ( height ) *height = ascent2 + descent2;
2685 if ( descent ) *descent = descent2;
2686 if ( ascent ) *ascent = ascent2;
2687 }
2688}
2689
2690#endif // !wxMOTIF_NEW_FONT_HANDLING
2691
34636400
VZ
2692// ----------------------------------------------------------------------------
2693// wxNoOptimize: switch off size optimization
2694// ----------------------------------------------------------------------------
88150e60 2695
af0bb3b1 2696int wxNoOptimize::ms_count = 0;