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