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