]> git.saurik.com Git - wxWidgets.git/blame - src/motif/window.cpp
fix wxStringOutputStream::Write() in Unicode build when the output overlaps a boundar...
[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{
9b135950 632 XtVaSetValues((Widget)GetMainWidget(), XmNtitle, label.mb_str(), NULL);
4bb6408c
JS
633}
634
34097680 635wxString wxWindow::GetLabel() const
4bb6408c 636{
34097680
WS
637 char *label;
638 XtVaGetValues((Widget)GetMainWidget(), XmNtitle, &label, NULL);
af0bb3b1 639
34097680 640 return wxString(label);
4bb6408c
JS
641}
642
4116c221 643void wxWindow::DoCaptureMouse()
4bb6408c 644{
9806a47c 645 g_captureWindow = this;
34636400 646 if ( m_winCaptured )
a4294b78 647 return;
34636400 648
af0bb3b1 649 Widget wMain = (Widget)GetMainWidget();
34636400 650 if ( wMain )
96be256b 651 XtAddGrab(wMain, True, False);
34636400 652
96be256b 653 m_winCaptured = true;
4bb6408c
JS
654}
655
4116c221 656void wxWindow::DoReleaseMouse()
4bb6408c 657{
9806a47c 658 g_captureWindow = NULL;
34636400
VZ
659 if ( !m_winCaptured )
660 return;
661
af0bb3b1 662 Widget wMain = (Widget)GetMainWidget();
34636400
VZ
663 if ( wMain )
664 XtRemoveGrab(wMain);
665
96be256b 666 m_winCaptured = false;
4bb6408c
JS
667}
668
34636400 669bool wxWindow::SetFont(const wxFont& font)
4bb6408c 670{
34636400
VZ
671 if ( !wxWindowBase::SetFont(font) )
672 {
673 // nothing to do
96be256b 674 return false;
34636400
VZ
675 }
676
677 ChangeFont();
678
96be256b 679 return true;
4bb6408c
JS
680}
681
34636400 682bool wxWindow::SetCursor(const wxCursor& cursor)
4bb6408c 683{
34636400 684 if ( !wxWindowBase::SetCursor(cursor) )
2d120f83 685 {
34636400 686 // no change
96be256b 687 return false;
2d120f83 688 }
4bb6408c 689
f6bcfd97
BP
690 // wxASSERT_MSG( m_cursor.Ok(),
691 // wxT("cursor must be valid after call to the base version"));
f516d986 692 const wxCursor* cursor2 = NULL;
f6bcfd97
BP
693 if (m_cursor.Ok())
694 cursor2 = & m_cursor;
695 else
696 cursor2 = wxSTANDARD_CURSOR;
4bb6408c 697
34636400 698 WXDisplay *dpy = GetXDisplay();
f6bcfd97 699 WXCursor x_cursor = cursor2->GetXCursor(dpy);
34636400
VZ
700
701 Widget w = (Widget) GetMainWidget();
702 Window win = XtWindow(w);
703 XDefineCursor((Display*) dpy, win, (Cursor) x_cursor);
af0bb3b1 704
96be256b 705 return true;
34636400
VZ
706}
707
708// Coordinates relative to the window
709void wxWindow::WarpPointer (int x, int y)
4bb6408c 710{
34636400
VZ
711 Widget wClient = (Widget)GetClientWidget();
712
713 XWarpPointer(XtDisplay(wClient), None, XtWindow(wClient), 0, 0, 0, 0, x, y);
4bb6408c
JS
714}
715
34636400
VZ
716// ---------------------------------------------------------------------------
717// scrolling stuff
718// ---------------------------------------------------------------------------
719
720int wxWindow::GetScrollPos(int orient) const
4bb6408c 721{
34636400
VZ
722 if (orient == wxHORIZONTAL)
723 return m_scrollPosX;
724 else
725 return m_scrollPosY;
726
727#if 0
728 Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar);
729 if (scrollBar)
2d120f83 730 {
34636400
VZ
731 int pos;
732 XtVaGetValues(scrollBar, XmNvalue, &pos, NULL);
733 return pos;
2d120f83 734 }
34636400
VZ
735 else
736 return 0;
737#endif // 0
2d120f83 738}
7fe7d506 739
34636400
VZ
740// This now returns the whole range, not just the number of positions that we
741// can scroll.
742int wxWindow::GetScrollRange(int orient) const
2d120f83 743{
af0bb3b1 744 Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
355b4d3d 745 // CE scintilla windows don't always have these scrollbars
34e8f097
CE
746 // and it tends to pile up a whole bunch of asserts
747 //wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
34636400 748
c4cb3d0f 749 int range = 0;
355b4d3d 750 if (scrollBar)
c4cb3d0f 751 XtVaGetValues(scrollBar, XmNmaximum, &range, NULL);
34636400 752 return range;
2d120f83 753}
4bb6408c 754
34636400 755int wxWindow::GetScrollThumb(int orient) const
4bb6408c 756{
af0bb3b1 757 Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
34e8f097 758 //wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
34636400 759
34e8f097
CE
760 int thumb = 0;
761 if (scrollBar)
762 XtVaGetValues(scrollBar, XmNsliderSize, &thumb, NULL);
34636400 763 return thumb;
4bb6408c
JS
764}
765
34636400 766void wxWindow::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
4bb6408c 767{
af0bb3b1 768 Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
34636400
VZ
769
770 if ( scrollBar )
4bb6408c 771 {
34636400 772 XtVaSetValues (scrollBar, XmNvalue, pos, NULL);
4bb6408c 773 }
34636400 774
af0bb3b1 775 SetInternalScrollPos((wxOrientation)orient, pos);
4bb6408c
JS
776}
777
34636400
VZ
778// New function that will replace some of the above.
779void wxWindow::SetScrollbar(int orient, int pos, int thumbVisible,
780 int range, bool WXUNUSED(refresh))
4bb6408c 781{
34636400
VZ
782 int oldW, oldH;
783 GetSize(& oldW, & oldH);
784
785 if (range == 0)
786 range = 1;
787 if (thumbVisible == 0)
788 thumbVisible = 1;
789
790 if (thumbVisible > range)
791 thumbVisible = range;
792
793 // Save the old state to see if it changed
af0bb3b1 794 WXWidget oldScrollBar = GetScrollbar((wxOrientation)orient);
34636400
VZ
795
796 if (orient == wxHORIZONTAL)
50414e24 797 {
34636400 798 if (thumbVisible == range)
2d120f83 799 {
34636400
VZ
800 if (m_hScrollBar)
801 DestroyScrollbar(wxHORIZONTAL);
2d120f83
JS
802 }
803 else
804 {
34636400
VZ
805 if (!m_hScrollBar)
806 CreateScrollbar(wxHORIZONTAL);
2d120f83 807 }
50414e24 808 }
34636400 809 if (orient == wxVERTICAL)
50414e24 810 {
34636400 811 if (thumbVisible == range)
2d120f83 812 {
34636400
VZ
813 if (m_vScrollBar)
814 DestroyScrollbar(wxVERTICAL);
2d120f83
JS
815 }
816 else
817 {
34636400
VZ
818 if (!m_vScrollBar)
819 CreateScrollbar(wxVERTICAL);
2d120f83 820 }
50414e24 821 }
af0bb3b1 822 WXWidget newScrollBar = GetScrollbar((wxOrientation)orient);
4bb6408c 823
88150e60 824 if (oldScrollBar != newScrollBar)
28ab302b 825 {
34636400 826 // This is important! Without it, scrollbars misbehave badly.
2d120f83
JS
827 XtUnrealizeWidget((Widget) m_scrolledWindow);
828 XmScrolledWindowSetAreas ((Widget) m_scrolledWindow, (Widget) m_hScrollBar, (Widget) m_vScrollBar, (Widget) m_drawingArea);
829 XtRealizeWidget((Widget) m_scrolledWindow);
830 XtManageChild((Widget) m_scrolledWindow);
28ab302b 831 }
34636400 832
88150e60 833 if (newScrollBar)
34636400 834 {
2d120f83
JS
835 XtVaSetValues((Widget) newScrollBar,
836 XmNvalue, pos,
837 XmNminimum, 0,
838 XmNmaximum, range,
839 XmNsliderSize, thumbVisible,
840 NULL);
34636400
VZ
841 }
842
af0bb3b1 843 SetInternalScrollPos((wxOrientation)orient, pos);
34636400 844
88150e60
JS
845 int newW, newH;
846 GetSize(& newW, & newH);
34636400 847
88150e60
JS
848 // Adjusting scrollbars can resize the canvas accidentally
849 if (newW != oldW || newH != oldH)
34097680 850 SetSize(wxDefaultCoord, wxDefaultCoord, oldW, oldH);
4bb6408c
JS
851}
852
853// Does a physical scroll
16e93305 854void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
4bb6408c 855{
2d120f83
JS
856 int x, y, w, h;
857 if (rect)
858 {
859 // Use specified rectangle
860 x = rect->x; y = rect->y; w = rect->width; h = rect->height;
861 }
862 else
863 {
864 // Use whole client area
865 x = 0; y = 0;
866 GetClientSize(& w, & h);
867 }
34636400
VZ
868
869 int x1 = (dx >= 0) ? x : x - dx;
2d120f83
JS
870 int y1 = (dy >= 0) ? y : y - dy;
871 int w1 = w - abs(dx);
872 int h1 = h - abs(dy);
873 int x2 = (dx >= 0) ? x + dx : x;
874 int y2 = (dy >= 0) ? y + dy : y;
34636400 875
2d120f83 876 wxClientDC dc(this);
34636400 877
2d120f83 878 dc.SetLogicalFunction (wxCOPY);
34636400 879
2d120f83
JS
880 Widget widget = (Widget) GetMainWidget();
881 Window window = XtWindow(widget);
882 Display* display = XtDisplay(widget);
34636400
VZ
883
884 XCopyArea(display, window, window, (GC) dc.GetGC(),
885 x1, y1, w1, h1, x2, y2);
886
96be256b 887 dc.SetAutoSetting(true);
2d120f83 888 wxBrush brush(GetBackgroundColour(), wxSOLID);
34636400
VZ
889 dc.SetBrush(brush); // FIXME: needed?
890
1807c27d 891 wxWindowList::compatibility_iterator cnode = m_children.GetFirst();
fc7ca9b3
MB
892 while (cnode)
893 {
894 wxWindow *child = cnode->GetData();
895 int sx = 0;
896 int sy = 0;
897 child->GetSize( &sx, &sy );
898 wxPoint pos( child->GetPosition() );
899 child->SetSize( pos.x + dx, pos.y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
900 cnode = cnode->GetNext();
901 }
902
34636400
VZ
903 // We'll add rectangles to the list of update rectangles according to which
904 // bits we've exposed.
2d120f83 905 wxList updateRects;
34636400 906
2d120f83
JS
907 if (dx > 0)
908 {
909 wxRect *rect = new wxRect;
910 rect->x = x;
911 rect->y = y;
912 rect->width = dx;
913 rect->height = h;
34636400 914
2d120f83
JS
915 XFillRectangle(display, window,
916 (GC) dc.GetGC(), 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
2d120f83
JS
934 XFillRectangle(display, window,
935 (GC) dc.GetGC(), rect->x, rect->y, rect->width,
936 rect->height);
34636400 937
2d120f83
JS
938 rect->x = rect->x;
939 rect->y = rect->y;
940 rect->width = rect->width;
941 rect->height = rect->height;
34636400 942
2d120f83
JS
943 updateRects.Append((wxObject*) rect);
944 }
945 if (dy > 0)
946 {
947 wxRect *rect = new wxRect;
34636400 948
2d120f83
JS
949 rect->x = x;
950 rect->y = y;
951 rect->width = w;
952 rect->height = dy;
34636400 953
2d120f83
JS
954 XFillRectangle(display, window,
955 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
34636400 956
2d120f83
JS
957 rect->x = rect->x;
958 rect->y = rect->y;
959 rect->width = rect->width;
960 rect->height = rect->height;
34636400 961
2d120f83
JS
962 updateRects.Append((wxObject*) rect);
963 }
964 else if (dy < 0)
965 {
966 wxRect *rect = new wxRect;
34636400 967
2d120f83
JS
968 rect->x = x;
969 rect->y = y + h + dy;
970 rect->width = w;
971 rect->height = -dy;
34636400 972
2d120f83
JS
973 XFillRectangle(display, window,
974 (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
34636400 975
2d120f83
JS
976 rect->x = rect->x;
977 rect->y = rect->y;
978 rect->width = rect->width;
979 rect->height = rect->height;
34636400 980
2d120f83
JS
981 updateRects.Append((wxObject*) rect);
982 }
983 dc.SetBrush(wxNullBrush);
34636400 984
2d120f83 985 // Now send expose events
34636400 986
1807c27d 987 wxList::compatibility_iterator node = updateRects.GetFirst();
2d120f83
JS
988 while (node)
989 {
1bc822df 990 wxRect* rect = (wxRect*) node->GetData();
2d120f83 991 XExposeEvent event;
34636400 992
2d120f83
JS
993 event.type = Expose;
994 event.display = display;
995 event.send_event = True;
996 event.window = window;
34636400 997
2d120f83
JS
998 event.x = rect->x;
999 event.y = rect->y;
1000 event.width = rect->width;
1001 event.height = rect->height;
34636400 1002
2d120f83 1003 event.count = 0;
34636400 1004
2d120f83 1005 XSendEvent(display, window, False, ExposureMask, (XEvent *)&event);
34636400 1006
1bc822df 1007 node = node->GetNext();
34636400 1008
2d120f83 1009 }
34636400 1010
2d120f83 1011 // Delete the update rects
1bc822df 1012 node = updateRects.GetFirst();
2d120f83
JS
1013 while (node)
1014 {
1bc822df 1015 wxRect* rect = (wxRect*) node->GetData();
2d120f83 1016 delete rect;
1bc822df 1017 node = node->GetNext();
2d120f83 1018 }
a91b47e8
JS
1019
1020 XmUpdateDisplay((Widget) GetMainWidget());
4bb6408c
JS
1021}
1022
34636400
VZ
1023// ---------------------------------------------------------------------------
1024// drag and drop
1025// ---------------------------------------------------------------------------
4ce81a75 1026
34636400 1027#if wxUSE_DRAG_AND_DROP
4ce81a75 1028
34636400 1029void wxWindow::SetDropTarget(wxDropTarget * WXUNUSED(pDropTarget))
4ce81a75 1030{
34636400 1031 // TODO
4bb6408c
JS
1032}
1033
34636400
VZ
1034#endif
1035
1036// Old style file-manager drag&drop
1037void wxWindow::DragAcceptFiles(bool WXUNUSED(accept))
4bb6408c 1038{
34636400 1039 // TODO
4bb6408c
JS
1040}
1041
34636400
VZ
1042// ----------------------------------------------------------------------------
1043// tooltips
1044// ----------------------------------------------------------------------------
1045
1046#if wxUSE_TOOLTIPS
1047
1048void wxWindow::DoSetToolTip(wxToolTip * WXUNUSED(tooltip))
4bb6408c 1049{
34636400 1050 // TODO
4bb6408c
JS
1051}
1052
34636400
VZ
1053#endif // wxUSE_TOOLTIPS
1054
ee31c392
VZ
1055// ----------------------------------------------------------------------------
1056// popup menus
1057// ----------------------------------------------------------------------------
1058
7e1bcfa8
MB
1059#if wxUSE_MENUS
1060
ee31c392
VZ
1061bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
1062{
34097680 1063 if ( x == wxDefaultCoord && y == wxDefaultCoord )
971562cb
VS
1064 {
1065 wxPoint mouse = ScreenToClient(wxGetMousePosition());
1066 x = mouse.x; y = mouse.y;
1067 }
1068
ee31c392
VZ
1069 Widget widget = (Widget) GetMainWidget();
1070
1071 /* The menuId field seems to be usused, so we'll use it to
1072 indicate whether a menu is popped up or not:
1073 0: Not currently created as a popup
1074 -1: Created as a popup, but not active
1075 1: Active popup.
1076 */
1077
1078 if (menu->GetParent() && (menu->GetId() != -1))
96be256b 1079 return false;
ee31c392 1080
7e1bcfa8
MB
1081 if (menu->GetMainWidget())
1082 {
96be256b 1083 menu->DestroyMenu(true);
ee31c392
VZ
1084 }
1085
1086 menu->SetId(1); /* Mark as popped-up */
51c9a5db 1087 menu->CreateMenu(NULL, widget, menu, 0);
ee31c392
VZ
1088 menu->SetInvokingWindow(this);
1089
1090 menu->UpdateUI();
1091
1092 // menu->SetParent(parent);
1093 // parent->children->Append(menu); // Store menu for later deletion
1094
1095 Widget menuWidget = (Widget) menu->GetMainWidget();
1096
1097 int rootX = 0;
1098 int rootY = 0;
1099
1100 int deviceX = x;
1101 int deviceY = y;
1102 /*
1103 if (this->IsKindOf(CLASSINFO(wxCanvas)))
1104 {
1105 wxCanvas *canvas = (wxCanvas *) this;
1106 deviceX = canvas->GetDC ()->LogicalToDeviceX (x);
1107 deviceY = canvas->GetDC ()->LogicalToDeviceY (y);
1108 }
1109 */
1110
1111 Display *display = XtDisplay (widget);
1112 Window rootWindow = RootWindowOfScreen (XtScreen((Widget)widget));
1113 Window thisWindow = XtWindow (widget);
1114 Window childWindow;
1115 XTranslateCoordinates (display, thisWindow, rootWindow, (int) deviceX, (int) deviceY,
1116 &rootX, &rootY, &childWindow);
1117
1118 XButtonPressedEvent event;
1119 event.type = ButtonPress;
1120 event.button = 1;
1121
1122 event.x = deviceX;
1123 event.y = deviceY;
1124
1125 event.x_root = rootX;
1126 event.y_root = rootY;
1127
1128 XmMenuPosition (menuWidget, &event);
1129 XtManageChild (menuWidget);
1130
2b5f62a0 1131 // The ID of a pop-up menu is 1 when active, and is set to 0 by the
e41e1385 1132 // idle-time destroy routine.
2b5f62a0 1133 // Waiting until this ID changes causes this function to block until
e41e1385
JS
1134 // the menu has been dismissed and the widgets cleaned up.
1135 // In other words, once this routine returns, it is safe to delete
1136 // the menu object.
1137 // Ian Brown <ian.brown@printsoft.de>
e41e1385 1138
7e1bcfa8 1139 wxEventLoop evtLoop;
e41e1385 1140
7e1bcfa8
MB
1141 while (menu->GetId() == 1)
1142 {
1143 wxDoEventLoopIteration( evtLoop );
e41e1385 1144 }
7e1bcfa8 1145
96be256b 1146 return true;
ee31c392
VZ
1147}
1148
7e1bcfa8
MB
1149#endif
1150
34636400
VZ
1151// ---------------------------------------------------------------------------
1152// moving and resizing
1153// ---------------------------------------------------------------------------
4bb6408c 1154
34636400 1155bool wxWindow::PreResize()
4bb6408c 1156{
96be256b 1157 return true;
4bb6408c
JS
1158}
1159
34636400 1160// Get total size
af0bb3b1 1161void wxWindow::DoGetSize(int *x, int *y) const
4bb6408c 1162{
fc7ca9b3
MB
1163 Widget widget = (Widget)( !m_drawingArea ? GetTopWidget() :
1164 ( m_borderWidget ? m_borderWidget :
1165 m_scrolledWindow ? m_scrolledWindow :
1166 m_drawingArea ) );
34636400 1167 Dimension xx, yy;
fc7ca9b3 1168
105fbe1f
MB
1169 if (widget)
1170 XtVaGetValues( widget,
1171 XmNwidth, &xx,
1172 XmNheight, &yy,
1173 NULL );
1174 if(x) *x = widget ? xx : -1;
1175 if(y) *y = widget ? yy : -1;
4bb6408c
JS
1176}
1177
af0bb3b1 1178void wxWindow::DoGetPosition(int *x, int *y) const
4bb6408c 1179{
fc7ca9b3
MB
1180 Widget widget = (Widget)
1181 ( m_drawingArea ?
355b4d3d 1182 ( m_borderWidget ? m_borderWidget : m_scrolledWindow ) :
fc7ca9b3
MB
1183 GetTopWidget() );
1184
34636400
VZ
1185 Position xx, yy;
1186 XtVaGetValues(widget, XmNx, &xx, XmNy, &yy, NULL);
b59bf2db 1187
34636400
VZ
1188 // We may be faking the client origin. So a window that's really at (0, 30)
1189 // may appear (to wxWin apps) to be at (0, 0).
1190 if (GetParent())
b59bf2db 1191 {
34636400 1192 wxPoint pt(GetParent()->GetClientAreaOrigin());
355b4d3d
WS
1193 xx = (Position)(xx - pt.x);
1194 yy = (Position)(yy - pt.y);
b59bf2db 1195 }
34636400 1196
fc7ca9b3
MB
1197 if(x) *x = xx;
1198 if(y) *y = yy;
4bb6408c
JS
1199}
1200
af0bb3b1 1201void wxWindow::DoScreenToClient(int *x, int *y) const
4bb6408c 1202{
34636400
VZ
1203 Widget widget = (Widget) GetClientWidget();
1204 Display *display = XtDisplay((Widget) GetMainWidget());
1205 Window rootWindow = RootWindowOfScreen(XtScreen(widget));
1206 Window thisWindow = XtWindow(widget);
1207
1208 Window childWindow;
c5c01214
VZ
1209 int xx = x ? *x : 0;
1210 int yy = y ? *y : 0;
1211 XTranslateCoordinates(display, rootWindow, thisWindow,
1212 xx, yy, x ? x : &xx, y ? y : &yy,
1213 &childWindow);
4bb6408c
JS
1214}
1215
af0bb3b1 1216void wxWindow::DoClientToScreen(int *x, int *y) const
4bb6408c 1217{
34636400
VZ
1218 Widget widget = (Widget) GetClientWidget();
1219 Display *display = XtDisplay(widget);
1220 Window rootWindow = RootWindowOfScreen(XtScreen(widget));
1221 Window thisWindow = XtWindow(widget);
1222
1223 Window childWindow;
c5c01214
VZ
1224 int xx = x ? *x : 0;
1225 int yy = y ? *y : 0;
1226 XTranslateCoordinates(display, thisWindow, rootWindow,
1227 xx, yy, x ? x : &xx, y ? y : &yy,
1228 &childWindow);
4bb6408c
JS
1229}
1230
34636400
VZ
1231
1232// Get size *available for subwindows* i.e. excluding menu bar etc.
af0bb3b1 1233void wxWindow::DoGetClientSize(int *x, int *y) const
4fabb575 1234{
34636400
VZ
1235 Widget widget = (Widget) GetClientWidget();
1236 Dimension xx, yy;
1237 XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL);
f6fb552e 1238 if(x) *x = xx; if(y) *y = yy;
4fabb575
JS
1239}
1240
34636400 1241void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags)
37c997b4 1242{
96be256b 1243 DoSetSizeIntr(x, y, width, height, sizeFlags, false);
37c997b4
MB
1244}
1245
1246void wxWindow::DoSetSizeIntr(int x, int y, int width, int height,
1247 int sizeFlags, bool fromCtor)
4bb6408c 1248{
34636400 1249 // A bit of optimization to help sort out the flickers.
9577d302 1250 int oldX = -1, oldY = -1, oldW = -1, oldH = -1;
32d4c30a 1251
37c997b4
MB
1252 if( !fromCtor )
1253 {
1254 GetSize(& oldW, & oldH);
1255 GetPosition(& oldX, & oldY);
1256 }
34636400 1257
105fbe1f
MB
1258 if (x == -1)
1259 x = oldX;
1260 if (x == -1)
1261 x = oldY;
1262
9d9b7755
VZ
1263 if ( !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
1264 {
9fd8f2dd
MB
1265 if ( width == -1 )
1266 width = oldW;
1267 if ( height == -1 )
1268 height = oldH;
9d9b7755 1269 }
34636400 1270
34097680 1271 wxSize size(wxDefaultSize);
7e1bcfa8 1272 if ( width <= 0 )
fc7ca9b3 1273 {
66f8b9ac 1274 if ( ( sizeFlags & wxSIZE_AUTO_WIDTH ) && !fromCtor )
fc7ca9b3
MB
1275 {
1276 size = DoGetBestSize();
1277 width = size.x;
1278 }
1279 else
1280 {
1281 width = oldW;
1282 }
1283 }
34636400 1284
fc7ca9b3 1285 if ( height == -1 )
02800301 1286 {
66f8b9ac 1287 if( ( sizeFlags & wxSIZE_AUTO_HEIGHT ) && !fromCtor )
fc7ca9b3
MB
1288 {
1289 if( size.x == -1 ) size = DoGetBestSize();
1290 height = size.y;
1291 }
1292 else
1293 {
1294 height = oldH;
1295 }
34636400
VZ
1296 }
1297
fc7ca9b3
MB
1298 if ( x != oldX || y != oldY || width != oldW || height != oldH
1299 || !wxNoOptimize::CanOptimize() )
34636400 1300 {
9d9b7755
VZ
1301 if (m_drawingArea)
1302 {
fc7ca9b3
MB
1303 int flags = 0;
1304
9fd8f2dd 1305 if (x != oldX)
fc7ca9b3
MB
1306 flags |= wxMOVE_X;
1307
9fd8f2dd 1308 if (y != oldY)
fc7ca9b3
MB
1309 flags |= wxMOVE_Y;
1310
1311 if (width > 0)
1312 flags |= wxMOVE_WIDTH;
1313
1314 if (height > 0)
1315 flags |= wxMOVE_HEIGHT;
1316
1317 int xx = x; int yy = y;
1318 AdjustForParentClientOrigin(xx, yy, sizeFlags);
1319 if( !fromCtor )
1320 DoMoveWindow( xx, yy, width, height );
1321 else
1322 DoMoveWindowIntr( xx, yy, width, height, flags );
1323
9d9b7755
VZ
1324 return;
1325 }
34636400 1326
9d9b7755
VZ
1327 Widget widget = (Widget) GetTopWidget();
1328 if (!widget)
1329 return;
34636400 1330
9d9b7755
VZ
1331 bool managed = XtIsManaged( widget );
1332 if (managed)
1333 XtUnmanageChild(widget);
34636400 1334
9d9b7755
VZ
1335 int xx = x;
1336 int yy = y;
1337 AdjustForParentClientOrigin(xx, yy, sizeFlags);
1338
1339 DoMoveWindow(xx, yy, width, height);
34636400 1340
9d9b7755
VZ
1341 if (managed)
1342 XtManageChild(widget);
9d9b7755 1343 }
4bb6408c
JS
1344}
1345
34636400 1346void wxWindow::DoSetClientSize(int width, int height)
4bb6408c 1347{
34636400 1348 if (m_drawingArea)
4bb6408c 1349 {
fc7ca9b3
MB
1350 Widget drawingArea = (Widget) m_drawingArea;
1351
1352 XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
1353
1354 if (width > -1)
1355 XtVaSetValues(drawingArea, XmNwidth, width, NULL);
1356 if (height > -1)
1357 XtVaSetValues(drawingArea, XmNheight, height, NULL);
1358
1359 XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
34636400 1360 return;
4bb6408c 1361 }
34636400
VZ
1362
1363 Widget widget = (Widget) GetTopWidget();
1364
1365 if (width > -1)
1366 XtVaSetValues(widget, XmNwidth, width, NULL);
1367 if (height > -1)
1368 XtVaSetValues(widget, XmNheight, height, NULL);
4bb6408c
JS
1369}
1370
fc7ca9b3
MB
1371void wxWindow::DoMoveWindowIntr(int xx, int yy, int w, int h,
1372 int flags)
9d9b7755 1373{
37c997b4 1374 if (m_drawingArea)
fc7ca9b3
MB
1375 {
1376 Widget drawingArea = (Widget) m_drawingArea;
1377 Widget borderOrScrolled = m_borderWidget ?
1378 (Widget) m_borderWidget :
1379 (Widget) m_scrolledWindow;
1380
1381 bool managed = XtIsManaged(borderOrScrolled);
fc7ca9b3
MB
1382 if (managed)
1383 XtUnmanageChild (borderOrScrolled);
1384 XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
1385
1386 if (flags & wxMOVE_X)
1387 XtVaSetValues (borderOrScrolled,
1388 XmNx, xx,
1389 NULL);
1390 if (flags & wxMOVE_Y)
1391 XtVaSetValues (borderOrScrolled,
1392 XmNy, yy,
1393 NULL);
1394
1395 if (flags & wxMOVE_WIDTH)
1396 {
1397 if (m_borderWidget)
1398 {
1399 XtVaSetValues ((Widget) m_borderWidget, XmNwidth, w, NULL);
1400 short thick, margin;
1401 XtVaGetValues ((Widget) m_borderWidget,
1402 XmNshadowThickness, &thick,
1403 XmNmarginWidth, &margin,
1404 NULL);
1405 w -= 2 * (thick + margin);
1406 }
37c997b4 1407
88793548 1408 if( w < 1 ) w = 1;
fc7ca9b3
MB
1409 XtVaSetValues ((Widget) m_scrolledWindow, XmNwidth, w, NULL);
1410 }
d9d3622e 1411
fc7ca9b3
MB
1412 if (flags & wxMOVE_HEIGHT)
1413 {
1414 if (m_borderWidget)
1415 {
1416 XtVaSetValues ((Widget) m_borderWidget, XmNheight, h, NULL);
1417 short thick, margin;
1418 XtVaGetValues ((Widget) m_borderWidget,
1419 XmNshadowThickness, &thick,
1420 XmNmarginHeight, &margin,
1421 NULL);
1422 h -= 2 * (thick + margin);
1423 }
1424
88793548 1425 if( h < 1 ) h = 1;
fc7ca9b3
MB
1426 XtVaSetValues ((Widget) m_scrolledWindow, XmNheight, h, NULL);
1427 }
1428
1429 if (managed)
1430 XtManageChild (borderOrScrolled);
1431 XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
1432 }
1433 else
1434 {
1435 if( w < 1 ) w = 1;
1436 if( h < 1 ) h = 1;
1437
1438 XtVaSetValues((Widget)GetTopWidget(),
1439 XmNx, xx,
1440 XmNy, yy,
1441 XmNwidth, w,
1442 XmNheight, h,
1443 NULL);
1444 }
1445}
1446
1447void wxWindow::DoMoveWindow(int x, int y, int width, int height)
1448{
1449 DoMoveWindowIntr (x, y, width, height,
1450 wxMOVE_X|wxMOVE_Y|wxMOVE_WIDTH|wxMOVE_HEIGHT);
9d9b7755
VZ
1451}
1452
34636400
VZ
1453// ---------------------------------------------------------------------------
1454// text metrics
1455// ---------------------------------------------------------------------------
1456
1457int wxWindow::GetCharHeight() const
4bb6408c 1458{
996994c7 1459 int height;
355b4d3d 1460
105fbe1f
MB
1461 if (m_font.Ok())
1462 wxGetTextExtent (GetXDisplay(), m_font, 1.0,
1463 "x", NULL, &height, NULL, NULL);
1464 else
1465 wxGetTextExtent (this, "x", NULL, &height, NULL, NULL);
34636400 1466
996994c7 1467 return height;
4bb6408c
JS
1468}
1469
34636400 1470int wxWindow::GetCharWidth() const
4bb6408c 1471{
996994c7 1472 int width;
355b4d3d 1473
105fbe1f
MB
1474 if (m_font.Ok())
1475 wxGetTextExtent (GetXDisplay(), m_font, 1.0,
1476 "x", &width, NULL, NULL, NULL);
1477 else
1478 wxGetTextExtent (this, "x", &width, NULL, NULL, NULL);
34636400 1479
996994c7 1480 return width;
4bb6408c
JS
1481}
1482
34636400
VZ
1483void wxWindow::GetTextExtent(const wxString& string,
1484 int *x, int *y,
1485 int *descent, int *externalLeading,
1486 const wxFont *theFont) const
4bb6408c 1487{
996994c7 1488 const wxFont *fontToUse = theFont ? theFont : &m_font;
34636400 1489
34636400
VZ
1490 if (externalLeading)
1491 *externalLeading = 0;
105fbe1f
MB
1492 if (fontToUse->Ok())
1493 wxGetTextExtent (GetXDisplay(), *fontToUse, 1.0,
1494 string, x, y, NULL, descent);
1495 else
1496 wxGetTextExtent (this, string, x, y, NULL, descent);
4bb6408c
JS
1497}
1498
34636400
VZ
1499// ----------------------------------------------------------------------------
1500// painting
1501// ----------------------------------------------------------------------------
4bb6408c 1502
148b44a1
MB
1503void wxWindow::AddUpdateRect(int x, int y, int w, int h)
1504{
1505 m_updateRegion.Union( x, y, w, h );
1506}
1507
34636400 1508void wxWindow::Refresh(bool eraseBack, const wxRect *rect)
4bb6408c 1509{
105fbe1f
MB
1510 Widget widget = (Widget) GetMainWidget();
1511 if (!widget)
1512 return;
96be256b 1513 m_needsRefresh = true;
105fbe1f
MB
1514 Display *display = XtDisplay(widget);
1515 Window thisWindow = XtWindow(widget);
34636400
VZ
1516
1517 XExposeEvent dummyEvent;
1518 int width, height;
1519 GetSize(&width, &height);
1520
1521 dummyEvent.type = Expose;
1522 dummyEvent.display = display;
1523 dummyEvent.send_event = True;
1524 dummyEvent.window = thisWindow;
1525 if (rect)
2d120f83 1526 {
34636400
VZ
1527 dummyEvent.x = rect->x;
1528 dummyEvent.y = rect->y;
1529 dummyEvent.width = rect->width;
1530 dummyEvent.height = rect->height;
2d120f83
JS
1531 }
1532 else
1533 {
34636400
VZ
1534 dummyEvent.x = 0;
1535 dummyEvent.y = 0;
1536 dummyEvent.width = width;
1537 dummyEvent.height = height;
2d120f83 1538 }
34636400 1539 dummyEvent.count = 0;
4bb6408c 1540
34636400 1541 if (eraseBack)
2d120f83 1542 {
34636400
VZ
1543 wxClientDC dc(this);
1544 wxBrush backgroundBrush(GetBackgroundColour(), wxSOLID);
1545 dc.SetBackground(backgroundBrush);
1546 if (rect)
1547 dc.Clear(*rect);
1548 else
1549 dc.Clear();
2d120f83 1550 }
4bb6408c 1551
34636400 1552 XSendEvent(display, thisWindow, False, ExposureMask, (XEvent *)&dummyEvent);
4bb6408c
JS
1553}
1554
34636400 1555void wxWindow::DoPaint()
4bb6408c 1556{
34636400
VZ
1557 //TODO : make a temporary gc so we can do the XCopyArea below
1558 if (m_backingPixmap && !m_needsRefresh)
4bb6408c 1559 {
34636400 1560 wxPaintDC dc(this);
4bb6408c 1561
34636400 1562 GC tempGC = (GC) dc.GetBackingGC();
4bb6408c 1563
34636400 1564 Widget widget = (Widget) GetMainWidget();
4bb6408c 1565
34636400
VZ
1566 int scrollPosX = 0;
1567 int scrollPosY = 0;
4bb6408c 1568
34636400
VZ
1569 // We have to test whether it's a wxScrolledWindow (hack!) because
1570 // otherwise we don't know how many pixels have been scrolled. We might
1571 // solve this in the future by defining virtual wxWindow functions to get
1572 // the scroll position in pixels. Or, each kind of scrolled window has to
77ffb593 1573 // implement backing stores itself, using generic wxWidgets code.
34636400
VZ
1574 wxScrolledWindow* scrolledWindow = wxDynamicCast(this, wxScrolledWindow);
1575 if ( scrolledWindow )
1576 {
1577 int x, y;
1578 scrolledWindow->CalcScrolledPosition(0, 0, &x, &y);
1579
1580 scrollPosX = - x;
1581 scrollPosY = - y;
1582 }
1583
1584 // TODO: This could be optimized further by only copying the areas in the
1585 // current update region.
1586
1587 // Only blit the part visible in the client area. The backing pixmap
1588 // always starts at 0, 0 but we may be looking at only a portion of it.
1589 wxSize clientArea = GetClientSize();
1590 int toBlitX = m_pixmapWidth - scrollPosX;
1591 int toBlitY = m_pixmapHeight - scrollPosY;
1592
1593 // Copy whichever is samller, the amount of pixmap we have to copy,
1594 // or the size of the client area.
1595 toBlitX = wxMin(toBlitX, clientArea.x);
1596 toBlitY = wxMin(toBlitY, clientArea.y);
1597
1598 // Make sure we're not negative
1599 toBlitX = wxMax(0, toBlitX);
1600 toBlitY = wxMax(0, toBlitY);
1601
1602 XCopyArea
1603 (
1604 XtDisplay(widget),
1605 (Pixmap) m_backingPixmap,
1606 XtWindow (widget),
1607 tempGC,
1608 scrollPosX, scrollPosY, // Start at the scroll position
1609 toBlitX, toBlitY, // How much of the pixmap to copy
1610 0, 0 // Destination
1611 );
1612 }
1613 else
4bb6408c 1614 {
fc7ca9b3 1615 wxWindowDC dc(this);
34636400 1616 // Set an erase event first
fc7ca9b3 1617 wxEraseEvent eraseEvent(GetId(), &dc);
34636400
VZ
1618 eraseEvent.SetEventObject(this);
1619 GetEventHandler()->ProcessEvent(eraseEvent);
1620
1621 wxPaintEvent event(GetId());
1622 event.SetEventObject(this);
1623 GetEventHandler()->ProcessEvent(event);
1624
96be256b 1625 m_needsRefresh = false;
4bb6408c 1626 }
4bb6408c
JS
1627}
1628
34636400
VZ
1629// ----------------------------------------------------------------------------
1630// event handlers
1631// ----------------------------------------------------------------------------
1632
1633// Responds to colour changes: passes event on to children.
1634void wxWindow::OnSysColourChanged(wxSysColourChangedEvent& event)
4bb6408c 1635{
1807c27d 1636 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
34636400 1637 while ( node )
4bb6408c 1638 {
34636400
VZ
1639 // Only propagate to non-top-level windows
1640 wxWindow *win = node->GetData();
1641 if ( win->GetParent() )
2d120f83 1642 {
34636400 1643 wxSysColourChangedEvent event2;
687706f5 1644 event.SetEventObject(win);
34636400 1645 win->GetEventHandler()->ProcessEvent(event2);
2d120f83 1646 }
4bb6408c 1647
34636400 1648 node = node->GetNext();
2d120f83 1649 }
4bb6408c
JS
1650}
1651
e39af974 1652void wxWindow::OnInternalIdle()
4bb6408c 1653{
34636400
VZ
1654 // This calls the UI-update mechanism (querying windows for
1655 // menu/toolbar/control state information)
e39af974
JS
1656 if (wxUpdateUIEvent::CanUpdate(this))
1657 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
4bb6408c
JS
1658}
1659
34636400
VZ
1660// ----------------------------------------------------------------------------
1661// accelerators
1662// ----------------------------------------------------------------------------
4bb6408c 1663
34636400 1664bool wxWindow::ProcessAccelerator(wxKeyEvent& event)
4bb6408c 1665{
7e1bcfa8 1666#if wxUSE_ACCEL
34636400 1667 if (!m_acceleratorTable.Ok())
96be256b 1668 return false;
4bb6408c 1669
34636400
VZ
1670 int count = m_acceleratorTable.GetCount();
1671 wxAcceleratorEntry* entries = m_acceleratorTable.GetEntries();
1672 int i;
1673 for (i = 0; i < count; i++)
2d120f83 1674 {
34636400
VZ
1675 wxAcceleratorEntry* entry = & (entries[i]);
1676 if (entry->MatchesEvent(event))
1677 {
f6045f99 1678 // Bingo, we have a match. Now find a control that matches the
2b5f62a0 1679 // entry command id.
4bb6408c 1680
34636400
VZ
1681 // Need to go up to the top of the window hierarchy, since it might
1682 // be e.g. a menu item
1683 wxWindow* parent = this;
1684 while ( parent && !parent->IsTopLevel() )
1685 parent = parent->GetParent();
4bb6408c 1686
34636400 1687 if (!parent)
96be256b 1688 return false;
4bb6408c 1689
34636400
VZ
1690 wxFrame* frame = wxDynamicCast(parent, wxFrame);
1691 if ( frame )
1692 {
7e1bcfa8 1693#if wxUSE_MENUS
34636400
VZ
1694 // Try for a menu command
1695 if (frame->GetMenuBar())
1696 {
c71830c3 1697 wxMenuItem* item = frame->GetMenuBar()->FindItem(entry->GetCommand());
34636400
VZ
1698 if (item)
1699 {
1700 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, entry->GetCommand());
1701 commandEvent.SetEventObject(frame);
4bb6408c 1702
96be256b 1703 // If ProcessEvent returns true (it was handled), then
34636400
VZ
1704 // the calling code will skip the event handling.
1705 return frame->GetEventHandler()->ProcessEvent(commandEvent);
1706 }
1707 }
7e1bcfa8 1708#endif
34636400 1709 }
3dd4e4e0 1710
34636400
VZ
1711 // Find a child matching the command id
1712 wxWindow* child = parent->FindWindow(entry->GetCommand());
3dd4e4e0 1713
34636400
VZ
1714 // No such child
1715 if (!child)
96be256b 1716 return false;
3dd4e4e0 1717
34636400
VZ
1718 // Now we process those kinds of windows that we can.
1719 // For now, only buttons.
1720 if ( wxDynamicCast(child, wxButton) )
1721 {
1722 wxCommandEvent commandEvent (wxEVT_COMMAND_BUTTON_CLICKED, child->GetId());
1723 commandEvent.SetEventObject(child);
1724 return child->GetEventHandler()->ProcessEvent(commandEvent);
1725 }
3dd4e4e0 1726
96be256b 1727 return false;
34636400
VZ
1728 } // matches event
1729 }// for
7e1bcfa8 1730#endif
4bb6408c 1731
34636400 1732 // We didn't match the key event against an accelerator.
96be256b 1733 return false;
4bb6408c
JS
1734}
1735
34636400
VZ
1736// ============================================================================
1737// Motif-specific stuff from here on
1738// ============================================================================
1739
1740// ----------------------------------------------------------------------------
77ffb593 1741// function which maintain the global hash table mapping Widgets to wxWidgets
34636400
VZ
1742// ----------------------------------------------------------------------------
1743
1744bool wxAddWindowToTable(Widget w, wxWindow *win)
4bb6408c 1745{
e1bce3ca
VZ
1746 const long key = (long)w;
1747 if ( wxWidgetHashTable->Get(key))
2d120f83 1748 {
34636400 1749 wxLogDebug("Widget table clash: new widget is %ld, %s",
e1bce3ca 1750 key, win->GetClassInfo()->GetClassName());
96be256b 1751 return false;
2d120f83 1752 }
4bb6408c 1753
e1bce3ca 1754 wxWidgetHashTable->Put(key, win);
4bb6408c 1755
1bc822df 1756 wxLogTrace("widget", "Widget 0x%p <-> window %p (%s)",
e1bce3ca 1757 w, win, win->GetClassInfo()->GetClassName());
31528cd3 1758
96be256b 1759 return true;
4bb6408c
JS
1760}
1761
34636400 1762wxWindow *wxGetWindowFromTable(Widget w)
4bb6408c 1763{
33caefb3 1764 return (wxWindow *)wxWidgetHashTable->Get((long) w);
4bb6408c
JS
1765}
1766
34636400 1767void wxDeleteWindowFromTable(Widget w)
4bb6408c 1768{
fc7ca9b3
MB
1769 wxLogTrace("widget", "Widget 0x%p", (WXWidget)w);
1770
33caefb3 1771 wxWidgetHashTable->Delete((long)w);
4bb6408c
JS
1772}
1773
34636400
VZ
1774// ----------------------------------------------------------------------------
1775// add/remove window from the table
1776// ----------------------------------------------------------------------------
4bb6408c 1777
34636400 1778// Add to hash table, add event handler
af111fc3 1779bool wxWindow::AttachWidget (wxWindow* WXUNUSED(parent), WXWidget mainWidget,
34636400 1780 WXWidget formWidget, int x, int y, int width, int height)
4bb6408c 1781{
34636400 1782 wxAddWindowToTable((Widget) mainWidget, this);
a8680e3e
MB
1783 XtAddEventHandler( (Widget) mainWidget,
1784 ButtonPressMask | ButtonReleaseMask
1785 | PointerMotionMask,
1786 False,
1787 wxPanelItemEventHandler,
1788 (XtPointer) this);
4bb6408c 1789
34636400
VZ
1790 if (!formWidget)
1791 {
1792 XtTranslations ptr;
1793 XtOverrideTranslations ((Widget) mainWidget,
1794 ptr = XtParseTranslationTable ("<Configure>: resize()"));
1795 XtFree ((char *) ptr);
1796 }
4bb6408c 1797
34636400
VZ
1798 // Some widgets have a parent form widget, e.g. wxRadioBox
1799 if (formWidget)
1800 {
1801 if (!wxAddWindowToTable((Widget) formWidget, this))
96be256b 1802 return false;
4bb6408c 1803
34636400
VZ
1804 XtTranslations ptr;
1805 XtOverrideTranslations ((Widget) formWidget,
1806 ptr = XtParseTranslationTable ("<Configure>: resize()"));
1807 XtFree ((char *) ptr);
1808 }
4bb6408c 1809
24490a1c
MB
1810 if (x == -1)
1811 x = 0;
1812 if (y == -1)
1813 y = 0;
1814 DoSetSize (x, y, width, height, wxSIZE_USE_EXISTING);
4bb6408c 1815
f9204363 1816 return true;
4bb6408c
JS
1817}
1818
34636400
VZ
1819// Remove event handler, remove from hash table
1820bool wxWindow::DetachWidget(WXWidget widget)
4bb6408c 1821{
a8680e3e
MB
1822 XtRemoveEventHandler( (Widget) widget,
1823 ButtonPressMask | ButtonReleaseMask
1824 | PointerMotionMask,
1825 False,
1826 wxPanelItemEventHandler,
1827 (XtPointer)this);
4bb6408c 1828
34636400 1829 wxDeleteWindowFromTable((Widget) widget);
96be256b 1830 return true;
4bb6408c
JS
1831}
1832
34636400
VZ
1833// ----------------------------------------------------------------------------
1834// Motif-specific accessors
1835// ----------------------------------------------------------------------------
2d120f83 1836
1807c27d
MB
1837WXWindow wxWindow::GetClientXWindow() const
1838{
1839 Widget wMain = (Widget)GetClientWidget();
1840 if ( wMain )
1841 return (WXWindow) XtWindow(wMain);
1842 else
1843 return (WXWindow) 0;
1844}
1845
34636400 1846// Get the underlying X window
4bb6408c
JS
1847WXWindow wxWindow::GetXWindow() const
1848{
af0bb3b1 1849 Widget wMain = (Widget)GetMainWidget();
34636400
VZ
1850 if ( wMain )
1851 return (WXWindow) XtWindow(wMain);
ad813b00
JS
1852 else
1853 return (WXWindow) 0;
4bb6408c
JS
1854}
1855
34636400 1856// Get the underlying X display
4bb6408c
JS
1857WXDisplay *wxWindow::GetXDisplay() const
1858{
af0bb3b1 1859 Widget wMain = (Widget)GetMainWidget();
34636400
VZ
1860 if ( wMain )
1861 return (WXDisplay*) XtDisplay(wMain);
ad813b00
JS
1862 else
1863 return (WXDisplay*) NULL;
4bb6408c
JS
1864}
1865
1866WXWidget wxWindow::GetMainWidget() const
1867{
50414e24 1868 if (m_drawingArea)
2d120f83 1869 return m_drawingArea;
50414e24 1870 else
2d120f83 1871 return m_mainWidget;
50414e24
JS
1872}
1873
1874WXWidget wxWindow::GetClientWidget() const
1875{
1876 if (m_drawingArea != (WXWidget) 0)
1877 return m_drawingArea;
1878 else
02e8b2f9
JS
1879 return GetMainWidget();
1880}
1881
1882WXWidget wxWindow::GetTopWidget() const
1883{
1884 return GetMainWidget();
4bb6408c
JS
1885}
1886
34636400
VZ
1887WXWidget wxWindow::GetLabelWidget() const
1888{
1889 return GetMainWidget();
1890}
1891
1892// ----------------------------------------------------------------------------
1893// Motif callbacks
1894// ----------------------------------------------------------------------------
1895
1896// All widgets should have this as their resize proc.
1897// OnSize sent to wxWindow via client data.
66f8b9ac
MB
1898void wxWidgetResizeProc(Widget w, XConfigureEvent *WXUNUSED(event),
1899 String WXUNUSED(args)[], int *WXUNUSED(num_args))
34636400
VZ
1900{
1901 wxWindow *win = wxGetWindowFromTable(w);
1902 if (!win)
1903 return;
1904
1905 if (win->PreResize())
1906 {
355b4d3d
WS
1907 wxSize newSize(win->GetSize());
1908 wxSizeEvent sizeEvent(newSize, win->GetId());
34636400
VZ
1909 sizeEvent.SetEventObject(win);
1910 win->GetEventHandler()->ProcessEvent(sizeEvent);
1911 }
1912}
1913
1914static void wxCanvasRepaintProc(Widget drawingArea,
1915 XtPointer clientData,
1916 XmDrawingAreaCallbackStruct * cbs)
50414e24 1917{
34636400 1918 if (!wxGetWindowFromTable(drawingArea))
2d120f83 1919 return;
34636400 1920
50414e24 1921 XEvent * event = cbs->event;
55acd85e 1922 wxWindow * win = (wxWindow *) clientData;
34636400 1923
50414e24
JS
1924 switch (event->type)
1925 {
2d120f83 1926 case Expose:
55acd85e 1927 {
6970c7b9
MB
1928 win->AddUpdateRect(event->xexpose.x, event->xexpose.y,
1929 event->xexpose.width, event->xexpose.height);
148b44a1 1930
55acd85e
JS
1931 if (event -> xexpose.count == 0)
1932 {
a91b47e8 1933 win->DoPaint();
55acd85e
JS
1934 }
1935 break;
1936 }
50414e24 1937 }
50414e24
JS
1938}
1939
1940// Unable to deal with Enter/Leave without a separate EventHandler (Motif 1.1.4)
34636400 1941static void wxCanvasEnterLeave(Widget drawingArea,
af111fc3 1942 XtPointer WXUNUSED(clientData),
34636400 1943 XCrossingEvent * event)
50414e24 1944{
2d120f83
JS
1945 XmDrawingAreaCallbackStruct cbs;
1946 XEvent ev;
34636400 1947
2d120f83 1948 ((XCrossingEvent &) ev) = *event;
34636400 1949
2d120f83
JS
1950 cbs.reason = XmCR_INPUT;
1951 cbs.event = &ev;
34636400
VZ
1952
1953 wxCanvasInputEvent(drawingArea, (XtPointer) NULL, &cbs);
50414e24
JS
1954}
1955
1956// Fix to make it work under Motif 1.0 (!)
da494b40
MB
1957static void wxCanvasMotionEvent (Widget WXUNUSED(drawingArea),
1958 XButtonEvent *WXUNUSED(event))
50414e24 1959{
34636400 1960#if XmVersion <= 1000
2d120f83
JS
1961 XmDrawingAreaCallbackStruct cbs;
1962 XEvent ev;
34636400 1963
2d120f83
JS
1964 ev = *((XEvent *) event);
1965 cbs.reason = XmCR_INPUT;
1966 cbs.event = &ev;
34636400 1967
2d120f83 1968 wxCanvasInputEvent (drawingArea, (XtPointer) NULL, &cbs);
34636400 1969#endif // XmVersion <= 1000
50414e24
JS
1970}
1971
34636400 1972static void wxCanvasInputEvent(Widget drawingArea,
af111fc3 1973 XtPointer WXUNUSED(data),
34636400 1974 XmDrawingAreaCallbackStruct * cbs)
50414e24 1975{
34636400 1976 wxWindow *canvas = wxGetWindowFromTable(drawingArea);
2a23a89d 1977 XEvent* xevent = cbs->event;
34636400 1978
2d120f83 1979 if (canvas==NULL)
34636400
VZ
1980 return;
1981
2d120f83
JS
1982 if (cbs->reason != XmCR_INPUT)
1983 return;
34636400 1984
2a23a89d 1985 switch (xevent->xany.type)
50414e24
JS
1986 {
1987 case EnterNotify:
1988 case LeaveNotify:
1989 case ButtonPress:
1990 case ButtonRelease:
1991 case MotionNotify:
2d120f83 1992 {
2a23a89d
MB
1993 wxMouseEvent wxevent(0);
1994 if (wxTranslateMouseEvent(wxevent, canvas, drawingArea, xevent))
e700df04 1995 {
2a23a89d 1996 canvas->GetEventHandler()->ProcessEvent(wxevent);
e700df04 1997 }
e700df04 1998 break;
2a23a89d 1999 }
50414e24 2000 case KeyPress:
50414e24 2001 {
2b5f62a0 2002 wxKeyEvent event (wxEVT_CHAR);
2a23a89d 2003 if (wxTranslateKeyEvent (event, canvas, (Widget) 0, xevent))
2d120f83
JS
2004 {
2005 // Implement wxFrame::OnCharHook by checking ancestor.
66f8b9ac
MB
2006 wxWindow *parent = canvas;
2007 while (parent && !parent->IsTopLevel())
2d120f83 2008 parent = parent->GetParent();
34636400 2009
2d120f83
JS
2010 if (parent)
2011 {
2012 event.SetEventType(wxEVT_CHAR_HOOK);
2013 if (parent->GetEventHandler()->ProcessEvent(event))
2014 return;
2d120f83 2015 }
a91b47e8
JS
2016
2017 // For simplicity, OnKeyDown is the same as OnChar
2018 // TODO: filter modifier key presses from OnChar
2019 event.SetEventType(wxEVT_KEY_DOWN);
2020
2021 // Only process OnChar if OnKeyDown didn't swallow it
2022 if (!canvas->GetEventHandler()->ProcessEvent (event))
2023 {
66f8b9ac
MB
2024 event.SetEventType(wxEVT_CHAR);
2025 canvas->GetEventHandler()->ProcessEvent (event);
2026 }
2d120f83
JS
2027 }
2028 break;
2029 }
2030 case KeyRelease:
2031 {
2d120f83 2032 wxKeyEvent event (wxEVT_KEY_UP);
2a23a89d 2033 if (wxTranslateKeyEvent (event, canvas, (Widget) 0, xevent))
2d120f83
JS
2034 {
2035 canvas->GetEventHandler()->ProcessEvent (event);
2036 }
2037 break;
50414e24 2038 }
50414e24 2039 case FocusIn:
2d120f83 2040 {
2a23a89d 2041 if (xevent->xfocus.detail != NotifyPointer)
2d120f83
JS
2042 {
2043 wxFocusEvent event(wxEVT_SET_FOCUS, canvas->GetId());
2044 event.SetEventObject(canvas);
2045 canvas->GetEventHandler()->ProcessEvent(event);
2046 }
2047 break;
50414e24 2048 }
50414e24 2049 case FocusOut:
2d120f83 2050 {
2a23a89d 2051 if (xevent->xfocus.detail != NotifyPointer)
2d120f83
JS
2052 {
2053 wxFocusEvent event(wxEVT_KILL_FOCUS, canvas->GetId());
2054 event.SetEventObject(canvas);
2055 canvas->GetEventHandler()->ProcessEvent(event);
2056 }
2057 break;
2058 }
50414e24 2059 default:
2d120f83 2060 break;
50414e24
JS
2061 }
2062}
2063
34636400 2064static void wxPanelItemEventHandler(Widget wid,
af111fc3 2065 XtPointer WXUNUSED(client_data),
34636400
VZ
2066 XEvent* event,
2067 Boolean *continueToDispatch)
50414e24 2068{
34636400 2069 // Widget can be a label or the actual widget.
a91b47e8 2070
af0bb3b1 2071 wxWindow *window = wxGetWindowFromTable(wid);
34636400
VZ
2072 if (window)
2073 {
2074 wxMouseEvent wxevent(0);
2075 if (wxTranslateMouseEvent(wxevent, window, wid, event))
2076 {
2077 window->GetEventHandler()->ProcessEvent(wxevent);
2078 }
2079 }
a91b47e8 2080
34636400 2081 // TODO: probably the key to allowing default behaviour to happen. Say we
96be256b 2082 // set a m_doDefault flag to false at the start of this function. Then in
34636400 2083 // e.g. wxWindow::OnMouseEvent we can call Default() which sets this flag to
96be256b 2084 // true, indicating that default processing can happen. Thus, behaviour can
34636400
VZ
2085 // appear to be overridden just by adding an event handler and not calling
2086 // wxWindow::OnWhatever. ALSO, maybe we can use this instead of the current
2087 // way of handling drawing area events, to simplify things.
2088 *continueToDispatch = True;
2089}
a91b47e8 2090
34636400
VZ
2091static void wxScrollBarCallback(Widget scrollbar,
2092 XtPointer clientData,
311227c3 2093 XmScrollBarCallbackStruct *cbs)
34636400 2094{
34636400 2095 wxWindow *win = wxGetWindowFromTable(scrollbar);
29014baa
VZ
2096 wxCHECK_RET( win, _T("invalid widget in scrollbar callback") );
2097
a4588fd1 2098 wxOrientation orientation = (wxOrientation)wxPtrToUInt(clientData);
a91b47e8 2099
34636400
VZ
2100 wxEventType eventType = wxEVT_NULL;
2101 switch (cbs->reason)
2102 {
2103 case XmCR_INCREMENT:
2104 {
311227c3 2105 eventType = wxEVT_SCROLLWIN_LINEDOWN;
34636400
VZ
2106 break;
2107 }
2108 case XmCR_DECREMENT:
2109 {
311227c3 2110 eventType = wxEVT_SCROLLWIN_LINEUP;
34636400
VZ
2111 break;
2112 }
2113 case XmCR_DRAG:
2114 {
311227c3 2115 eventType = wxEVT_SCROLLWIN_THUMBTRACK;
34636400
VZ
2116 break;
2117 }
2118 case XmCR_VALUE_CHANGED:
2119 {
bdeca1d1 2120 eventType = wxEVT_SCROLLWIN_THUMBRELEASE;
34636400
VZ
2121 break;
2122 }
2123 case XmCR_PAGE_INCREMENT:
2124 {
311227c3 2125 eventType = wxEVT_SCROLLWIN_PAGEDOWN;
34636400
VZ
2126 break;
2127 }
2128 case XmCR_PAGE_DECREMENT:
2129 {
311227c3 2130 eventType = wxEVT_SCROLLWIN_PAGEUP;
34636400
VZ
2131 break;
2132 }
2133 case XmCR_TO_TOP:
2134 {
311227c3 2135 eventType = wxEVT_SCROLLWIN_TOP;
34636400
VZ
2136 break;
2137 }
2138 case XmCR_TO_BOTTOM:
2139 {
311227c3 2140 eventType = wxEVT_SCROLLWIN_BOTTOM;
34636400
VZ
2141 break;
2142 }
2143 default:
2144 {
2145 // Should never get here
2146 wxFAIL_MSG("Unknown scroll event.");
2147 break;
2148 }
2149 }
a91b47e8 2150
311227c3
MB
2151 wxScrollWinEvent event(eventType,
2152 cbs->value,
148b44a1 2153 orientation);
311227c3 2154 event.SetEventObject( win );
34636400
VZ
2155 win->GetEventHandler()->ProcessEvent(event);
2156}
a91b47e8 2157
34636400
VZ
2158// For repainting arbitrary windows
2159void wxUniversalRepaintProc(Widget w, XtPointer WXUNUSED(c_data), XEvent *event, char *)
2160{
34636400
VZ
2161 wxWindow* win = wxGetWindowFromTable(w);
2162 if (!win)
2163 return;
a91b47e8 2164
e1bce3ca 2165 switch ( event->type )
50414e24 2166 {
e1bce3ca 2167 case Expose:
34636400 2168 {
148b44a1
MB
2169 win->AddUpdateRect(event->xexpose.x, event->xexpose.y,
2170 event->xexpose.width, event->xexpose.height);
2171
3f97d339 2172 if ( event->xexpose.count == 0 )
34636400
VZ
2173 {
2174 win->DoPaint();
af0bb3b1
VZ
2175 }
2176
34636400
VZ
2177 break;
2178 }
50414e24
JS
2179 }
2180}
2181
34636400
VZ
2182// ----------------------------------------------------------------------------
2183// TranslateXXXEvent() functions
2184// ----------------------------------------------------------------------------
2185
a8680e3e 2186bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win,
2a23a89d 2187 Widget widget, const XEvent *xevent)
02e8b2f9 2188{
2d120f83
JS
2189 switch (xevent->xany.type)
2190 {
a8680e3e
MB
2191 case EnterNotify:
2192 case LeaveNotify:
2193#if 0
2194 fprintf(stderr, "Widget 0x%p <-> window %p (%s), %s\n",
2195 (WXWidget)widget, win, win->GetClassInfo()->GetClassName(),
2196 (xevent->xany.type == EnterNotify ? "ENTER" : "LEAVE"));
2197#endif
1e8abce5
MB
2198 case ButtonPress:
2199 case ButtonRelease:
2200 case MotionNotify:
02e8b2f9 2201 {
2a23a89d
MB
2202 int eventx = xevent->xbutton.x, eventy = xevent->xbutton.y;
2203
2d120f83 2204 wxEventType eventType = wxEVT_NULL;
34636400 2205
2d120f83
JS
2206 if (xevent->xany.type == LeaveNotify)
2207 {
a8680e3e
MB
2208 eventType = wxEVT_LEAVE_WINDOW;
2209 }
2210 if (xevent->xany.type == EnterNotify)
2211 {
2212 eventType = wxEVT_ENTER_WINDOW;
2d120f83
JS
2213 }
2214 else if (xevent->xany.type == MotionNotify)
2215 {
2216 eventType = wxEVT_MOTION;
2a23a89d
MB
2217
2218 if (xevent->xmotion.is_hint == NotifyHint)
2219 {
2220 Window root, child;
2221 int x_root, y_root;
2222 unsigned int state;
2223 Display *dpy = XtDisplay (widget);
2224
2225 XQueryPointer (dpy, XtWindow (widget),
2226 &root, &child,
2227 &x_root, &y_root, &eventx, &eventy, &state);
2228 }
2d120f83
JS
2229 }
2230 else if (xevent->xany.type == ButtonPress)
2231 {
1e8abce5
MB
2232 wxevent.SetTimestamp(xevent->xbutton.time);
2233 int button = 0;
2d120f83
JS
2234 if (xevent->xbutton.button == Button1)
2235 {
2236 eventType = wxEVT_LEFT_DOWN;
1e8abce5 2237 button = 1;
2d120f83
JS
2238 }
2239 else if (xevent->xbutton.button == Button2)
2240 {
2241 eventType = wxEVT_MIDDLE_DOWN;
1e8abce5 2242 button = 2;
2d120f83
JS
2243 }
2244 else if (xevent->xbutton.button == Button3)
2245 {
2246 eventType = wxEVT_RIGHT_DOWN;
1e8abce5
MB
2247 button = 3;
2248 }
2249
2250 // check for a double click
2251 //
eb6fa4b4 2252 long dclickTime = XtGetMultiClickTime(xevent->xany.display);
1e8abce5
MB
2253 long ts = wxevent.GetTimestamp();
2254
2255 int buttonLast = win->GetLastClickedButton();
2256 long lastTS = win->GetLastClickTime();
a8680e3e
MB
2257 if ( buttonLast && buttonLast == button &&
2258 (ts - lastTS) < dclickTime )
1e8abce5
MB
2259 {
2260 // I have a dclick
2261 win->SetLastClick(0, ts);
205c0389
VZ
2262 if ( eventType == wxEVT_LEFT_DOWN )
2263 eventType = wxEVT_LEFT_DCLICK;
2264 else if ( eventType == wxEVT_MIDDLE_DOWN )
2265 eventType = wxEVT_MIDDLE_DCLICK;
2266 else if ( eventType == wxEVT_RIGHT_DOWN )
2267 eventType = wxEVT_RIGHT_DCLICK;
1e8abce5
MB
2268 }
2269 else
2270 {
2271 // not fast enough or different button
2272 win->SetLastClick(button, ts);
2d120f83
JS
2273 }
2274 }
2275 else if (xevent->xany.type == ButtonRelease)
2276 {
2277 if (xevent->xbutton.button == Button1)
2278 {
2279 eventType = wxEVT_LEFT_UP;
2d120f83
JS
2280 }
2281 else if (xevent->xbutton.button == Button2)
2282 {
2283 eventType = wxEVT_MIDDLE_UP;
2d120f83
JS
2284 }
2285 else if (xevent->xbutton.button == Button3)
2286 {
2287 eventType = wxEVT_RIGHT_UP;
2d120f83 2288 }
a8680e3e 2289 else
96be256b 2290 return false;
2d120f83 2291 }
af0bb3b1
VZ
2292 else
2293 {
96be256b 2294 return false;
af0bb3b1 2295 }
34636400 2296
2d120f83 2297 wxevent.SetEventType(eventType);
34636400 2298
2d120f83
JS
2299 Position x1, y1;
2300 XtVaGetValues(widget, XmNx, &x1, XmNy, &y1, NULL);
34636400 2301
2d120f83
JS
2302 int x2, y2;
2303 win->GetPosition(&x2, &y2);
34636400 2304
77ffb593 2305 // The button x/y must be translated to wxWidgets
2d120f83
JS
2306 // window space - the widget might be a label or button,
2307 // within a form.
2308 int dx = 0;
2309 int dy = 0;
2310 if (widget != (Widget)win->GetMainWidget())
2311 {
2312 dx = x1;
2313 dy = y1;
2314 }
34636400 2315
2a23a89d
MB
2316 wxevent.m_x = eventx + dx;
2317 wxevent.m_y = eventy + dy;
34636400 2318
2d120f83 2319 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
34636400 2320 || (event_left_is_down (xevent)
2d120f83
JS
2321 && (eventType != wxEVT_LEFT_UP)));
2322 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
34636400 2323 || (event_middle_is_down (xevent)
2d120f83
JS
2324 && (eventType != wxEVT_MIDDLE_UP)));
2325 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
34636400 2326 || (event_right_is_down (xevent)
2d120f83 2327 && (eventType != wxEVT_RIGHT_UP)));
34636400 2328
355b4d3d
WS
2329 wxevent.m_shiftDown = (xevent->xbutton.state & ShiftMask) == ShiftMask;
2330 wxevent.m_controlDown = (xevent->xbutton.state & ControlMask) == ControlMask;
2331 wxevent.m_altDown = (xevent->xbutton.state & Mod3Mask) == Mod3Mask;
2332 wxevent.m_metaDown = (xevent->xbutton.state & Mod1Mask) == Mod1Mask;
1e8abce5
MB
2333
2334 wxevent.SetId(win->GetId());
2335 wxevent.SetEventObject(win);
2336
96be256b 2337 return true;
2d120f83 2338 }
02e8b2f9 2339 }
96be256b 2340 return false;
02e8b2f9
JS
2341}
2342
fc7ca9b3 2343bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win,
2a23a89d 2344 Widget WXUNUSED(widget), const XEvent *xevent)
02e8b2f9 2345{
2d120f83
JS
2346 switch (xevent->xany.type)
2347 {
02e8b2f9 2348 case KeyPress:
4a041f2f 2349 case KeyRelease:
2d120f83
JS
2350 {
2351 char buf[20];
34636400 2352
2d120f83 2353 KeySym keySym;
fc7ca9b3 2354 (void) XLookupString((XKeyEvent *)xevent, buf, 20, &keySym, NULL);
2d120f83 2355 int id = wxCharCodeXToWX (keySym);
2b5f62a0
VZ
2356 // id may be WXK_xxx code - these are outside ASCII range, so we
2357 // can't just use toupper() on id
2358 if (id >= 'a' && id <= 'z')
2359 id = toupper(id);
34636400 2360
2d120f83 2361 if (xevent->xkey.state & ShiftMask)
96be256b 2362 wxevent.m_shiftDown = true;
2d120f83 2363 if (xevent->xkey.state & ControlMask)
96be256b 2364 wxevent.m_controlDown = true;
2d120f83 2365 if (xevent->xkey.state & Mod3Mask)
96be256b 2366 wxevent.m_altDown = true;
2d120f83 2367 if (xevent->xkey.state & Mod1Mask)
96be256b 2368 wxevent.m_metaDown = true;
2d120f83
JS
2369 wxevent.SetEventObject(win);
2370 wxevent.m_keyCode = id;
2371 wxevent.SetTimestamp(xevent->xkey.time);
34636400 2372
2d120f83
JS
2373 wxevent.m_x = xevent->xbutton.x;
2374 wxevent.m_y = xevent->xbutton.y;
34636400 2375
2d120f83 2376 if (id > -1)
96be256b 2377 return true;
355b4d3d
WS
2378
2379 return false;
2d120f83 2380 }
02e8b2f9 2381 default:
2d120f83
JS
2382 break;
2383 }
96be256b 2384 return false;
02e8b2f9
JS
2385}
2386
34636400
VZ
2387// ----------------------------------------------------------------------------
2388// Colour stuff
2389// ----------------------------------------------------------------------------
2390
02e8b2f9 2391#define YAllocColor XAllocColor
0d57be45 2392XColor g_itemColors[5];
f516d986 2393int wxComputeColours (Display *display, const wxColour * back, const wxColour * fore)
02e8b2f9 2394{
2d120f83
JS
2395 int result;
2396 static XmColorProc colorProc;
34636400 2397
2d120f83 2398 result = wxNO_COLORS;
34636400 2399
2d120f83 2400 if (back)
02e8b2f9 2401 {
355b4d3d
WS
2402 g_itemColors[0].red = (unsigned short)(((long) back->Red ()) << 8);
2403 g_itemColors[0].green = (unsigned short)(((long) back->Green ()) << 8);
2404 g_itemColors[0].blue = (unsigned short)(((long) back->Blue ()) << 8);
2d120f83
JS
2405 g_itemColors[0].flags = DoRed | DoGreen | DoBlue;
2406 if (colorProc == (XmColorProc) NULL)
2407 {
2408 // Get a ptr to the actual function
2409 colorProc = XmSetColorCalculation ((XmColorProc) NULL);
2410 // And set it back to motif.
2411 XmSetColorCalculation (colorProc);
2412 }
2413 (*colorProc) (&g_itemColors[wxBACK_INDEX],
2414 &g_itemColors[wxFORE_INDEX],
2415 &g_itemColors[wxSELE_INDEX],
2416 &g_itemColors[wxTOPS_INDEX],
2417 &g_itemColors[wxBOTS_INDEX]);
2418 result = wxBACK_COLORS;
02e8b2f9 2419 }
2d120f83 2420 if (fore)
02e8b2f9 2421 {
355b4d3d
WS
2422 g_itemColors[wxFORE_INDEX].red = (unsigned short)(((long) fore->Red ()) << 8);
2423 g_itemColors[wxFORE_INDEX].green = (unsigned short)(((long) fore->Green ()) << 8);
2424 g_itemColors[wxFORE_INDEX].blue = (unsigned short)(((long) fore->Blue ()) << 8);
2d120f83
JS
2425 g_itemColors[wxFORE_INDEX].flags = DoRed | DoGreen | DoBlue;
2426 if (result == wxNO_COLORS)
2427 result = wxFORE_COLORS;
02e8b2f9 2428 }
34636400 2429
2d120f83
JS
2430 Display *dpy = display;
2431 Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy);
34636400 2432
2d120f83 2433 if (back)
02e8b2f9 2434 {
2d120f83
JS
2435 /* 5 Colours to allocate */
2436 for (int i = 0; i < 5; i++)
2437 if (!YAllocColor (dpy, cmap, &g_itemColors[i]))
2438 result = wxNO_COLORS;
02e8b2f9 2439 }
2d120f83 2440 else if (fore)
02e8b2f9 2441 {
2d120f83
JS
2442 /* Only 1 colour to allocate */
2443 if (!YAllocColor (dpy, cmap, &g_itemColors[wxFORE_INDEX]))
2444 result = wxNO_COLORS;
02e8b2f9 2445 }
34636400 2446
fc7ca9b3 2447 return result;
02e8b2f9
JS
2448}
2449
34636400
VZ
2450// Changes the foreground and background colours to be derived from the current
2451// background colour. To change the foreground colour, you must call
2452// SetForegroundColour explicitly.
0d57be45 2453void wxWindow::ChangeBackgroundColour()
02e8b2f9 2454{
34636400
VZ
2455 WXWidget mainWidget = GetMainWidget();
2456 if ( mainWidget )
a8680e3e 2457 wxDoChangeBackgroundColour(mainWidget, m_backgroundColour);
24490a1c
MB
2458 if ( m_scrolledWindow && mainWidget != m_scrolledWindow )
2459 wxDoChangeForegroundColour(m_scrolledWindow, m_backgroundColour);
0d57be45 2460}
02e8b2f9 2461
0d57be45
JS
2462void wxWindow::ChangeForegroundColour()
2463{
34636400
VZ
2464 WXWidget mainWidget = GetMainWidget();
2465 if ( mainWidget )
a8680e3e 2466 wxDoChangeForegroundColour(mainWidget, m_foregroundColour);
34636400 2467 if ( m_scrolledWindow && mainWidget != m_scrolledWindow )
a8680e3e 2468 wxDoChangeForegroundColour(m_scrolledWindow, m_foregroundColour);
02e8b2f9
JS
2469}
2470
af0bb3b1 2471bool wxWindow::SetBackgroundColour(const wxColour& col)
02e8b2f9 2472{
af0bb3b1 2473 if ( !wxWindowBase::SetBackgroundColour(col) )
96be256b 2474 return false;
af0bb3b1 2475
0d57be45 2476 ChangeBackgroundColour();
af0bb3b1 2477
96be256b 2478 return true;
0d57be45
JS
2479}
2480
af0bb3b1 2481bool wxWindow::SetForegroundColour(const wxColour& col)
0d57be45 2482{
af0bb3b1 2483 if ( !wxWindowBase::SetForegroundColour(col) )
96be256b 2484 return false;
af0bb3b1 2485
0d57be45 2486 ChangeForegroundColour();
af0bb3b1 2487
96be256b 2488 return true;
0d57be45
JS
2489}
2490
4b5f3fe6 2491void wxWindow::ChangeFont(bool keepOriginalSize)
0d57be45
JS
2492{
2493 // Note that this causes the widget to be resized back
2494 // to its original size! We therefore have to set the size
2495 // back again. TODO: a better way in Motif?
0d57be45 2496 Widget w = (Widget) GetLabelWidget(); // Usually the main widget
af0bb3b1 2497 if (w && m_font.Ok())
0d57be45
JS
2498 {
2499 int width, height, width1, height1;
2500 GetSize(& width, & height);
34636400 2501
105fbe1f 2502 wxDoChangeFont( w, m_font );
34636400 2503
0d57be45 2504 GetSize(& width1, & height1);
4b5f3fe6 2505 if (keepOriginalSize && (width != width1 || height != height1))
0d57be45 2506 {
9b5f1895 2507 SetSize(wxDefaultCoord, wxDefaultCoord, width, height);
0d57be45
JS
2508 }
2509 }
02e8b2f9 2510}
0d57be45 2511
105fbe1f
MB
2512// Post-creation
2513void wxWindow::PostCreation()
2514{
2515 ChangeFont();
2516 ChangeForegroundColour();
2517 ChangeBackgroundColour();
2518}
2519
2520// Pre-creation
2521void wxWindow::PreCreation()
2522{
2523 InheritAttributes();
2524}
2525
34636400
VZ
2526// ----------------------------------------------------------------------------
2527// global functions
2528// ----------------------------------------------------------------------------
0d57be45 2529
34636400 2530wxWindow *wxGetActiveWindow()
1f112209
JS
2531{
2532 // TODO
9b8f6fa2 2533 wxFAIL_MSG("Not implemented");
34636400 2534 return NULL;
1f112209
JS
2535}
2536
9806a47c
JS
2537/* static */
2538wxWindow *wxWindowBase::GetCapture()
2539{
2540 return (wxWindow *)g_captureWindow;
2541}
2542
2543
3723b7b1
JS
2544// Find the wxWindow at the current mouse position, returning the mouse
2545// position.
2e2a55b2 2546wxWindow* wxFindWindowAtPointer(wxPoint& pt)
3723b7b1 2547{
2e2a55b2
MW
2548 pt = wxGetMousePosition();
2549 return wxFindWindowAtPoint(pt);
3723b7b1
JS
2550}
2551
0cbc5287 2552void wxGetMouseState(int& rootX, int& rootY, unsigned& maskReturn)
3723b7b1 2553{
eb6fa4b4 2554 Display *display = wxGlobalDisplay();
59a12e90
JS
2555 Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
2556 Window rootReturn, childReturn;
0cbc5287 2557 int winX, winY;
59a12e90
JS
2558
2559 XQueryPointer (display,
2b5f62a0
VZ
2560 rootWindow,
2561 &rootReturn,
59a12e90
JS
2562 &childReturn,
2563 &rootX, &rootY, &winX, &winY, &maskReturn);
0cbc5287
MW
2564}
2565
2566// Get the current mouse position.
2567wxPoint wxGetMousePosition()
2568{
2569 int x, y;
2570 unsigned mask;
2571
2572 wxGetMouseState(x, y, mask);
2573 return wxPoint(x, y);
2574}
2575
2576wxMouseState wxGetMouseState()
2577{
2578 wxMouseState ms;
2579 int x, y;
2580 unsigned mask;
2581
2582 wxGetMouseState(x, y, mask);
2583
2584 ms.SetX(x);
2585 ms.SetY(y);
2586
2587 ms.SetLeftDown(mask & Button1Mask);
2588 ms.SetMiddleDown(mask & Button2Mask);
2589 ms.SetRightDown(mask & Button3Mask);
2590
2591 ms.SetControlDown(mask & ControlMask);
2592 ms.SetShiftDown(mask & ShiftMask);
af1a6227
MW
2593 ms.SetAltDown(mask & Mod3Mask);
2594 ms.SetMetaDown(mask & Mod1Mask);
0cbc5287
MW
2595
2596 return ms;
3723b7b1
JS
2597}
2598
9806a47c 2599
105fbe1f
MB
2600#if wxMOTIF_NEW_FONT_HANDLING
2601
2602#include <Xm/XmP.h>
2603
2604void wxGetTextExtent(const wxWindow* window, const wxString& str,
2605 int* width, int* height, int* ascent, int* descent)
2606{
2607 Arg args[2];
2608 int count = 0;
2609 XmRendition rendition = NULL;
2610 XmRenderTable table = NULL;
2611 Widget w = (Widget) window->GetLabelWidget();
2612
2613 XtVaGetValues( w, XmNrenderTable, &table, NULL );
2614 if (table == NULL)
2615 table = XmeGetDefaultRenderTable(w, XmTEXT_RENDER_TABLE);
2616
2617 rendition = XmRenderTableGetRendition( table, "" );
2618 XtSetArg( args[count], XmNfont, 0 ); ++count;
2619 XtSetArg( args[count], XmNfontType, 0 ); ++count;
2620 XmRenditionRetrieve( rendition, args, count );
2621
2622 if (args[1].value == XmFONT_IS_FONTSET)
2623 {
2624 XRectangle ink, logical;
2625 WXFontSet fset = (WXFontSet) args[0].value;
2626
2627 XmbTextExtents( (XFontSet)fset, str.c_str(), str.length(),
2628 &ink, &logical);
2629
2630 if( width ) *width = logical.width;
2631 if( height ) *height = logical.height;
2632 if( ascent ) *ascent = -logical.y;
2633 if( descent ) *descent = logical.height + logical.y;
2634 }
2635 else
2636 {
2637 int direction, ascent2, descent2;
2638 XCharStruct overall;
2639 XFontStruct* fontStruct;
2640
2641 XmeRenderTableGetDefaultFont( table, &fontStruct );
2642 XTextExtents(fontStruct, (const char*)str.c_str(), str.length(),
2643 &direction, &ascent2, &descent2, &overall);
2644
2645 if ( width ) *width = overall.width;
2646 if ( height ) *height = ascent2 + descent2;
2647 if ( descent ) *descent = descent2;
2648 if ( ascent ) *ascent = ascent2;
2649 }
2650}
2651
2652#else // if !wxMOTIF_NEW_FONT_HANDLING
2653
2654void wxGetTextExtent(const wxWindow* window, const wxString& str,
2655 int* width, int* height, int* ascent, int* descent)
2656{
2657 XmFontList list = NULL;
2658 XmFontContext cxt;
2659 XmFontType type;
2660 Widget w = (Widget) window->GetLabelWidget();
2661
2662 XtVaGetValues( w, XmNfontList, &list, NULL );
2663 XmFontListInitFontContext( &cxt, list );
2664
2665 XmFontListEntry entry = XmFontListNextEntry( cxt );
2666 XmFontListFreeFontContext( cxt );
2667 XtPointer thing = XmFontListEntryGetFont( entry, &type );
2668
2669 if (type == XmFONT_IS_FONTSET)
2670 {
2671 XRectangle ink, logical;
2672
2673 XmbTextExtents( (XFontSet)thing, str.c_str(), str.length(),
2674 &ink, &logical);
2675
2676 if( width ) *width = logical.width;
2677 if( height ) *height = logical.height;
2678 if( ascent ) *ascent = -logical.y;
2679 if( descent ) *descent = logical.height + logical.y;
2680 }
2681 else
2682 {
2683 int direction, ascent2, descent2;
2684 XCharStruct overall;
2685
2686 XTextExtents( (XFontStruct*)thing, (char*)(const char*)str.c_str(), str.length(),
2687 &direction, &ascent2, &descent2, &overall);
2688
2689 if ( width ) *width = overall.width;
2690 if ( height ) *height = ascent2 + descent2;
2691 if ( descent ) *descent = descent2;
2692 if ( ascent ) *ascent = ascent2;
2693 }
2694}
2695
2696#endif // !wxMOTIF_NEW_FONT_HANDLING
2697
34636400
VZ
2698// ----------------------------------------------------------------------------
2699// wxNoOptimize: switch off size optimization
2700// ----------------------------------------------------------------------------
88150e60 2701
af0bb3b1 2702int wxNoOptimize::ms_count = 0;