PageRenderTime 41ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/ExtLibs/wxWidgets/src/motif/window.cpp

https://bitbucket.org/lennonchan/cafu
C++ | 1717 lines | 1187 code | 310 blank | 220 comment | 185 complexity | b8e72136e050b1b4ac8aff2464e9fdc0 MD5 | raw file
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: src/motif/window.cpp
  3. // Purpose: wxWindow
  4. // Author: Julian Smart
  5. // Modified by:
  6. // Created: 17/09/98
  7. // RCS-ID: $Id$
  8. // Copyright: (c) Julian Smart
  9. // Licence: wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11. // ============================================================================
  12. // declarations
  13. // ============================================================================
  14. // ----------------------------------------------------------------------------
  15. // headers
  16. // ----------------------------------------------------------------------------
  17. // For compilers that support precompilation, includes "wx.h".
  18. #include "wx/wxprec.h"
  19. #ifndef WX_PRECOMP
  20. #include "wx/hash.h"
  21. #include "wx/log.h"
  22. #include "wx/app.h"
  23. #include "wx/utils.h"
  24. #include "wx/frame.h"
  25. #include "wx/dc.h"
  26. #include "wx/dcclient.h"
  27. #include "wx/button.h"
  28. #include "wx/menu.h"
  29. #include "wx/settings.h"
  30. #include "wx/scrolwin.h"
  31. #include "wx/layout.h"
  32. #include "wx/menuitem.h"
  33. #include "wx/module.h"
  34. #endif
  35. #include "wx/evtloop.h"
  36. #include "wx/unix/utilsx11.h"
  37. #if wxUSE_DRAG_AND_DROP
  38. #include "wx/dnd.h"
  39. #endif
  40. // DoSetSizeIntr and DoMoveWindowIntr
  41. // PROBLEM:
  42. // under Motif composite controls (such as wxCalendarCtrl or generic wxSpinCtrl
  43. // did not work and/or segfaulted because
  44. // 1) wxWindow::Create calls SetSize,
  45. // which results in a call to DoSetSize much earlier than in the other ports
  46. // 2) if wxWindow::Create is called (wxControl::Create calls it)
  47. // then DoSetSize is never called, causing layout problems in composite
  48. // controls
  49. //
  50. // SOLUTION:
  51. // 1) don't call SetSize, DoSetSize, DoMoveWindow, DoGetPosition,
  52. // DoSetPosition directly or indirectly from wxWindow::Create
  53. // 2) call DoMoveWindow from DoSetSize, allowing controls to override it
  54. #ifdef __VMS__
  55. #pragma message disable nosimpint
  56. #endif
  57. #include <Xm/Xm.h>
  58. #include <Xm/DrawingA.h>
  59. #include <Xm/ScrolledW.h>
  60. #include <Xm/ScrollBar.h>
  61. #include <Xm/Frame.h>
  62. #include <Xm/Label.h>
  63. #include <Xm/RowColumn.h> // for XmMenuPosition
  64. #ifdef __VMS__
  65. #pragma message enable nosimpint
  66. #endif
  67. #include "wx/motif/private.h"
  68. #include "wx/motif/dcclient.h"
  69. #include <string.h>
  70. // ----------------------------------------------------------------------------
  71. // global variables for this module
  72. // ----------------------------------------------------------------------------
  73. extern wxHashTable *wxWidgetHashTable;
  74. static wxWindow* g_captureWindow = NULL;
  75. // ----------------------------------------------------------------------------
  76. // private functions
  77. // ----------------------------------------------------------------------------
  78. static void wxCanvasRepaintProc(Widget, XtPointer, XmDrawingAreaCallbackStruct * cbs);
  79. static void wxCanvasInputEvent(Widget drawingArea, XtPointer data, XmDrawingAreaCallbackStruct * cbs);
  80. static void wxCanvasMotionEvent(Widget, XButtonEvent * event);
  81. static void wxCanvasEnterLeave(Widget drawingArea, XtPointer clientData, XCrossingEvent * event);
  82. static void wxScrollBarCallback(Widget widget, XtPointer clientData,
  83. XmScrollBarCallbackStruct *cbs);
  84. static void wxPanelItemEventHandler(Widget wid,
  85. XtPointer client_data,
  86. XEvent* event,
  87. Boolean *continueToDispatch);
  88. // unused for now
  89. #if 0
  90. // Helper function for 16-bit fonts
  91. static int str16len(const char *s)
  92. {
  93. int count = 0;
  94. while (s[0] && s[1]) {
  95. count++;
  96. s += 2;
  97. }
  98. return count;
  99. }
  100. #endif // 0
  101. // ----------------------------------------------------------------------------
  102. // macros
  103. // ----------------------------------------------------------------------------
  104. #define event_left_is_down(x) ((x)->xbutton.state & Button1Mask)
  105. #define event_middle_is_down(x) ((x)->xbutton.state & Button2Mask)
  106. #define event_right_is_down(x) ((x)->xbutton.state & Button3Mask)
  107. // ----------------------------------------------------------------------------
  108. // event tables
  109. // ----------------------------------------------------------------------------
  110. BEGIN_EVENT_TABLE(wxWindow, wxWindowBase)
  111. EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
  112. END_EVENT_TABLE()
  113. // ============================================================================
  114. // implementation
  115. // ============================================================================
  116. // ----------------------------------------------------------------------------
  117. // helper functions
  118. // ----------------------------------------------------------------------------
  119. void wxWindow::UnmanageAndDestroy(WXWidget widget)
  120. {
  121. Widget w = (Widget)widget;
  122. if ( w )
  123. {
  124. XtUnmanageChild(w);
  125. XtDestroyWidget(w);
  126. }
  127. }
  128. bool wxWindow::MapOrUnmap(WXWidget widget, bool domap)
  129. {
  130. Widget w = (Widget)widget;
  131. if ( !w )
  132. return false;
  133. // Rationale: a lot of common operations (including but not
  134. // limited to moving, resizing and appending items to a listbox)
  135. // unmamange the widget, do their work, then manage it again.
  136. // This means that, for example adding an item to a listbox will show it,
  137. // or that most controls are shown every time they are moved or resized!
  138. XtSetMappedWhenManaged( w, domap );
  139. // if the widget is not unmanaged, it still intercepts
  140. // mouse events, even if it is not mapped (and hence invisible)
  141. if ( domap )
  142. {
  143. XtManageChild(w);
  144. // XtMapWidget(w);
  145. }
  146. else
  147. {
  148. XtUnmanageChild(w);
  149. // XtUnmapWidget(w);
  150. }
  151. return true;
  152. }
  153. // ----------------------------------------------------------------------------
  154. // constructors
  155. // ----------------------------------------------------------------------------
  156. void wxWindow::Init()
  157. {
  158. // Motif-specific
  159. m_needsRefresh = true;
  160. m_mainWidget = (WXWidget) 0;
  161. m_winCaptured = false;
  162. m_isShown = true;
  163. m_hScrollBar =
  164. m_vScrollBar =
  165. m_borderWidget =
  166. m_scrolledWindow =
  167. m_drawingArea = (WXWidget) 0;
  168. m_scrollPosX =
  169. m_scrollPosY = 0;
  170. m_backingPixmap = (WXPixmap) 0;
  171. m_pixmapWidth =
  172. m_pixmapHeight = 0;
  173. m_pixmapOffsetX =
  174. m_pixmapOffsetY = 0;
  175. m_lastTS = 0;
  176. m_lastButton = 0;
  177. }
  178. // real construction (Init() must have been called before!)
  179. bool wxWindow::Create(wxWindow *parent, wxWindowID id,
  180. const wxPoint& pos,
  181. const wxSize& size,
  182. long style,
  183. const wxString& name)
  184. {
  185. // Get default border
  186. wxBorder border = GetBorder(style);
  187. style &= ~wxBORDER_MASK;
  188. style |= border;
  189. wxCHECK_MSG( parent, false, "can't create wxWindow without parent" );
  190. CreateBase(parent, id, pos, size, style, wxDefaultValidator, name);
  191. parent->AddChild(this);
  192. PreCreation();
  193. //// TODO: we should probably optimize by only creating a
  194. //// a drawing area if we have one or more scrollbars (wxVSCROLL/wxHSCROLL).
  195. //// But for now, let's simplify things by always creating the
  196. //// drawing area, since otherwise the translations are different.
  197. // New translations for getting mouse motion feedback
  198. static const String translations = wxMOTIF_STR(
  199. "<Btn1Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
  200. <Btn2Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
  201. <Btn3Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
  202. <BtnMotion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
  203. <Btn1Down>: DrawingAreaInput() ManagerGadgetArm()\n\
  204. <Btn2Down>: DrawingAreaInput() ManagerGadgetArm()\n\
  205. <Btn3Down>: DrawingAreaInput() ManagerGadgetArm()\n\
  206. <Btn1Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
  207. <Btn2Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
  208. <Btn3Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
  209. <Motion>: wxCanvasMotionEvent() DrawingAreaInput()\n\
  210. <EnterWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
  211. <LeaveWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
  212. <Key>: DrawingAreaInput()");
  213. XtActionsRec actions[1];
  214. actions[0].string = wxMOTIF_STR("wxCanvasMotionEvent");
  215. actions[0].proc = (XtActionProc) wxCanvasMotionEvent;
  216. XtAppAddActions ((XtAppContext) wxTheApp->GetAppContext(), actions, 1);
  217. Widget parentWidget = (Widget) parent->GetClientWidget();
  218. m_borderWidget = wxCreateBorderWidget( (WXWidget)parentWidget, style );
  219. m_scrolledWindow = (WXWidget)XtVaCreateManagedWidget
  220. (
  221. "scrolledWindow",
  222. xmScrolledWindowWidgetClass,
  223. m_borderWidget ? (Widget) m_borderWidget
  224. : parentWidget,
  225. XmNresizePolicy, XmRESIZE_NONE,
  226. XmNspacing, 0,
  227. XmNscrollingPolicy, XmAPPLICATION_DEFINED,
  228. //XmNscrollBarDisplayPolicy, XmAS_NEEDED,
  229. NULL
  230. );
  231. XtTranslations ptr = XtParseTranslationTable(translations);
  232. m_drawingArea = (WXWidget)XtVaCreateWidget
  233. (
  234. name,
  235. xmDrawingAreaWidgetClass, (Widget) m_scrolledWindow,
  236. XmNunitType, XmPIXELS,
  237. // XmNresizePolicy, XmRESIZE_ANY,
  238. XmNresizePolicy, XmRESIZE_NONE,
  239. XmNmarginHeight, 0,
  240. XmNmarginWidth, 0,
  241. XmNtranslations, ptr,
  242. NULL
  243. );
  244. XtFree((char *) ptr);
  245. #if 0
  246. if (GetWindowStyleFlag() & wxOVERRIDE_KEY_TRANSLATIONS)
  247. {
  248. ptr = XtParseTranslationTable ("<Key>: DrawingAreaInput()");
  249. XtOverrideTranslations ((Widget) m_drawingArea, ptr);
  250. XtFree ((char *) ptr);
  251. }
  252. #endif // 0
  253. wxAddWindowToTable((Widget) m_drawingArea, this);
  254. wxAddWindowToTable((Widget) m_scrolledWindow, this);
  255. // This order is very important in Motif 1.2.1
  256. XtRealizeWidget ((Widget) m_scrolledWindow);
  257. XtRealizeWidget ((Widget) m_drawingArea);
  258. XtManageChild ((Widget) m_drawingArea);
  259. ptr = XtParseTranslationTable("<Configure>: resize()");
  260. XtOverrideTranslations((Widget) m_drawingArea, ptr);
  261. XtFree ((char *) ptr);
  262. XtAddCallback ((Widget) m_drawingArea, XmNexposeCallback, (XtCallbackProc) wxCanvasRepaintProc, (XtPointer) this);
  263. XtAddCallback ((Widget) m_drawingArea, XmNinputCallback, (XtCallbackProc) wxCanvasInputEvent, (XtPointer) this);
  264. XtAddEventHandler(
  265. (Widget)m_drawingArea,
  266. PointerMotionHintMask | EnterWindowMask |
  267. LeaveWindowMask | FocusChangeMask,
  268. False,
  269. (XtEventHandler) wxCanvasEnterLeave,
  270. (XtPointer) this
  271. );
  272. XmScrolledWindowSetAreas(
  273. (Widget)m_scrolledWindow,
  274. (Widget) 0, (Widget) 0,
  275. (Widget) m_drawingArea);
  276. PostCreation();
  277. // Without this, the cursor may not be restored properly (e.g. in splitter
  278. // sample).
  279. SetCursor(*wxSTANDARD_CURSOR);
  280. DoSetSizeIntr(pos.x, pos.y, size.x,size.y, wxSIZE_AUTO, true);
  281. return true;
  282. }
  283. // Destructor
  284. wxWindow::~wxWindow()
  285. {
  286. SendDestroyEvent();
  287. if (g_captureWindow == this)
  288. g_captureWindow = NULL;
  289. // Motif-specific actions first
  290. WXWidget wMain = GetMainWidget();
  291. if ( wMain )
  292. {
  293. // Removes event handlers
  294. DetachWidget(wMain);
  295. }
  296. // If m_drawingArea, we're a fully-fledged window with drawing area,
  297. // scrollbars etc. (what wxCanvas used to be)
  298. if ( m_drawingArea )
  299. {
  300. // Destroy children before destroying self
  301. DestroyChildren();
  302. if (m_backingPixmap)
  303. XFreePixmap (XtDisplay ((Widget) GetMainWidget()), (Pixmap) m_backingPixmap);
  304. Widget w = (Widget) m_drawingArea;
  305. wxDeleteWindowFromTable(w);
  306. if (w)
  307. {
  308. XtDestroyWidget(w);
  309. m_drawingArea = (WXWidget) 0;
  310. }
  311. // Only if we're _really_ a canvas (not a dialog box/panel)
  312. if (m_scrolledWindow)
  313. {
  314. wxDeleteWindowFromTable((Widget) m_scrolledWindow);
  315. }
  316. if (m_hScrollBar)
  317. {
  318. wxDeleteWindowFromTable((Widget) m_hScrollBar);
  319. XtUnmanageChild((Widget) m_hScrollBar);
  320. }
  321. if (m_vScrollBar)
  322. {
  323. wxDeleteWindowFromTable((Widget) m_vScrollBar);
  324. XtUnmanageChild((Widget) m_vScrollBar);
  325. }
  326. if (m_hScrollBar)
  327. XtDestroyWidget((Widget) m_hScrollBar);
  328. if (m_vScrollBar)
  329. XtDestroyWidget((Widget) m_vScrollBar);
  330. UnmanageAndDestroy(m_scrolledWindow);
  331. if (m_borderWidget)
  332. {
  333. XtDestroyWidget ((Widget) m_borderWidget);
  334. m_borderWidget = (WXWidget) 0;
  335. }
  336. }
  337. else // Why wasn't this here before? JACS 8/3/2000
  338. DestroyChildren();
  339. // Destroy the window
  340. if (GetMainWidget())
  341. {
  342. // If this line (XtDestroyWidget) causes a crash, you may comment it out.
  343. // Child widgets will get destroyed automatically when a frame
  344. // or dialog is destroyed, but before that you may get some memory
  345. // leaks and potential layout problems if you delete and then add
  346. // child windows.
  347. // GRG, Feb/2000: commented this out when adding support for
  348. // wxSCROLL[WIN]_THUMBRELEASE events. Also it was reported
  349. // that this call crashed wxMotif under OS/2, so it seems
  350. // that leaving it out is the right thing to do.
  351. // SN, Feb/2000: newgrid/griddemo shows why it is needed :-(
  352. XtDestroyWidget((Widget) GetMainWidget());
  353. SetMainWidget((WXWidget) NULL);
  354. }
  355. }
  356. // ----------------------------------------------------------------------------
  357. // scrollbar management
  358. // ----------------------------------------------------------------------------
  359. WXWidget wxWindow::DoCreateScrollBar(WXWidget parent,
  360. wxOrientation orientation,
  361. void (*callback)())
  362. {
  363. int orient = ( orientation & wxHORIZONTAL ) ? XmHORIZONTAL : XmVERTICAL;
  364. Widget sb =
  365. XtVaCreateManagedWidget( "scrollBarWidget",
  366. xmScrollBarWidgetClass, (Widget)parent,
  367. XmNorientation, orient,
  368. XmNincrement, 1,
  369. XmNvalue, 0,
  370. NULL );
  371. XtPointer o = (XtPointer)orientation;
  372. XtCallbackProc cb = (XtCallbackProc)callback;
  373. XtAddCallback( sb, XmNvalueChangedCallback, cb, o );
  374. XtAddCallback( sb, XmNdragCallback, cb, o );
  375. XtAddCallback( sb, XmNincrementCallback, cb, o );
  376. XtAddCallback( sb, XmNdecrementCallback, cb, o );
  377. XtAddCallback( sb, XmNpageIncrementCallback, cb, o );
  378. XtAddCallback( sb, XmNpageDecrementCallback, cb, o );
  379. XtAddCallback( sb, XmNtoTopCallback, cb, o );
  380. XtAddCallback( sb, XmNtoBottomCallback, cb, o );
  381. return (WXWidget)sb;
  382. }
  383. // Helper function
  384. void wxWindow::CreateScrollbar(wxOrientation orientation)
  385. {
  386. wxCHECK_RET( m_drawingArea, "this window can't have scrollbars" );
  387. XtVaSetValues( (Widget) m_scrolledWindow,
  388. XmNresizePolicy, XmRESIZE_NONE,
  389. NULL );
  390. wxColour backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
  391. // Add scrollbars if required
  392. if (orientation == wxHORIZONTAL)
  393. {
  394. m_hScrollBar = DoCreateScrollBar( m_scrolledWindow, wxHORIZONTAL,
  395. (void (*)())wxScrollBarCallback );
  396. wxDoChangeBackgroundColour(m_hScrollBar, backgroundColour, true);
  397. XtRealizeWidget( (Widget)m_hScrollBar );
  398. XtVaSetValues((Widget) m_scrolledWindow,
  399. XmNhorizontalScrollBar, (Widget) m_hScrollBar,
  400. NULL);
  401. wxAddWindowToTable( (Widget)m_hScrollBar, this );
  402. }
  403. else if (orientation == wxVERTICAL)
  404. {
  405. m_vScrollBar = DoCreateScrollBar( m_scrolledWindow, wxVERTICAL,
  406. (void (*)())wxScrollBarCallback );
  407. wxDoChangeBackgroundColour(m_vScrollBar, backgroundColour, true);
  408. XtRealizeWidget((Widget)m_vScrollBar);
  409. XtVaSetValues((Widget) m_scrolledWindow,
  410. XmNverticalScrollBar, (Widget) m_vScrollBar,
  411. NULL);
  412. wxAddWindowToTable( (Widget)m_vScrollBar, this );
  413. }
  414. XtVaSetValues( (Widget) m_scrolledWindow,
  415. XmNresizePolicy, XmRESIZE_ANY,
  416. NULL );
  417. }
  418. void wxWindow::DestroyScrollbar(wxOrientation orientation)
  419. {
  420. wxCHECK_RET( m_drawingArea, "this window can't have scrollbars" );
  421. XtVaSetValues((Widget) m_scrolledWindow,
  422. XmNresizePolicy, XmRESIZE_NONE,
  423. NULL);
  424. String stringSB = orientation == wxHORIZONTAL ?
  425. XmNhorizontalScrollBar : XmNverticalScrollBar;
  426. WXWidget* widgetSB = orientation == wxHORIZONTAL ?
  427. &m_hScrollBar : &m_vScrollBar;
  428. if( *widgetSB )
  429. {
  430. wxDeleteWindowFromTable( (Widget)*widgetSB );
  431. XtDestroyWidget( (Widget)*widgetSB );
  432. *widgetSB = (WXWidget)NULL;
  433. }
  434. XtVaSetValues( (Widget)m_scrolledWindow,
  435. stringSB, (Widget) 0,
  436. NULL );
  437. XtVaSetValues((Widget) m_scrolledWindow,
  438. XmNresizePolicy, XmRESIZE_ANY,
  439. NULL);
  440. }
  441. // ---------------------------------------------------------------------------
  442. // basic operations
  443. // ---------------------------------------------------------------------------
  444. void wxWindow::SetFocus()
  445. {
  446. Widget wMain = (Widget) GetMainWidget();
  447. XmProcessTraversal(wMain, XmTRAVERSE_CURRENT);
  448. XmProcessTraversal((Widget) GetMainWidget(), XmTRAVERSE_CURRENT);
  449. }
  450. // Get the window with the focus
  451. wxWindow *wxWindowBase::DoFindFocus()
  452. {
  453. // TODO Problems:
  454. // (1) Can there be multiple focussed widgets in an application?
  455. // In which case we need to find the top-level window that's
  456. // currently active.
  457. // (2) The widget with the focus may not be in the widget table
  458. // depending on which widgets I put in the table
  459. wxWindow *winFocus = NULL;
  460. for ( wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
  461. node;
  462. node = node->GetNext() )
  463. {
  464. wxWindow *win = node->GetData();
  465. Widget w = XmGetFocusWidget ((Widget) win->GetTopWidget());
  466. if (w != (Widget) NULL)
  467. {
  468. winFocus = wxGetWindowFromTable(w);
  469. if ( winFocus )
  470. break;
  471. }
  472. }
  473. return winFocus;
  474. }
  475. bool wxWindow::Enable(bool enable)
  476. {
  477. if ( !wxWindowBase::Enable(enable) )
  478. return false;
  479. Widget wMain = (Widget)GetMainWidget();
  480. if ( wMain )
  481. {
  482. XtSetSensitive(wMain, enable);
  483. XmUpdateDisplay(wMain);
  484. }
  485. return true;
  486. }
  487. bool wxWindow::Show(bool show)
  488. {
  489. if ( !wxWindowBase::Show(show) )
  490. return false;
  491. if (m_borderWidget || m_scrolledWindow)
  492. {
  493. MapOrUnmap(m_borderWidget ? m_borderWidget : m_scrolledWindow, show);
  494. // MapOrUnmap(m_drawingArea, show);
  495. }
  496. else
  497. {
  498. if ( !MapOrUnmap(GetTopWidget(), show) )
  499. MapOrUnmap(GetMainWidget(), show);
  500. }
  501. return true;
  502. }
  503. // Raise the window to the top of the Z order
  504. void wxWindow::Raise()
  505. {
  506. Widget wTop = (Widget) GetTopWidget();
  507. Window window = XtWindow(wTop);
  508. XRaiseWindow(XtDisplay(wTop), window);
  509. }
  510. // Lower the window to the bottom of the Z order
  511. void wxWindow::Lower()
  512. {
  513. Widget wTop = (Widget) GetTopWidget();
  514. Window window = XtWindow(wTop);
  515. XLowerWindow(XtDisplay(wTop), window);
  516. }
  517. void wxWindow::SetLabel(const wxString& label)
  518. {
  519. XtVaSetValues((Widget)GetMainWidget(), XmNtitle,
  520. (const char*)label.mb_str(), NULL);
  521. }
  522. wxString wxWindow::GetLabel() const
  523. {
  524. char *label = NULL;
  525. XtVaGetValues((Widget)GetMainWidget(), XmNtitle, &label, NULL);
  526. return wxString(label);
  527. }
  528. void wxWindow::DoCaptureMouse()
  529. {
  530. g_captureWindow = this;
  531. if ( m_winCaptured )
  532. return;
  533. Widget wMain = (Widget)GetMainWidget();
  534. if ( wMain )
  535. XtAddGrab(wMain, True, False);
  536. m_winCaptured = true;
  537. }
  538. void wxWindow::DoReleaseMouse()
  539. {
  540. g_captureWindow = NULL;
  541. if ( !m_winCaptured )
  542. return;
  543. Widget wMain = (Widget)GetMainWidget();
  544. if ( wMain )
  545. XtRemoveGrab(wMain);
  546. m_winCaptured = false;
  547. }
  548. bool wxWindow::SetFont(const wxFont& font)
  549. {
  550. if ( !wxWindowBase::SetFont(font) )
  551. {
  552. // nothing to do
  553. return false;
  554. }
  555. ChangeFont();
  556. return true;
  557. }
  558. bool wxWindow::SetCursor(const wxCursor& cursor)
  559. {
  560. if ( !wxWindowBase::SetCursor(cursor) )
  561. {
  562. // no change
  563. return false;
  564. }
  565. // wxASSERT_MSG( m_cursor.IsOk(),
  566. // wxT("cursor must be valid after call to the base version"));
  567. const wxCursor* cursor2 = NULL;
  568. if (m_cursor.IsOk())
  569. cursor2 = & m_cursor;
  570. else
  571. cursor2 = wxSTANDARD_CURSOR;
  572. WXDisplay *dpy = GetXDisplay();
  573. WXCursor x_cursor = cursor2->GetXCursor(dpy);
  574. Widget w = (Widget) GetMainWidget();
  575. Window win = XtWindow(w);
  576. XDefineCursor((Display*) dpy, win, (Cursor) x_cursor);
  577. return true;
  578. }
  579. // Coordinates relative to the window
  580. void wxWindow::WarpPointer (int x, int y)
  581. {
  582. Widget wClient = (Widget)GetClientWidget();
  583. XWarpPointer(XtDisplay(wClient), None, XtWindow(wClient), 0, 0, 0, 0, x, y);
  584. }
  585. // ---------------------------------------------------------------------------
  586. // scrolling stuff
  587. // ---------------------------------------------------------------------------
  588. int wxWindow::GetScrollPos(int orient) const
  589. {
  590. if (orient == wxHORIZONTAL)
  591. return m_scrollPosX;
  592. else
  593. return m_scrollPosY;
  594. #if 0
  595. Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar);
  596. if (scrollBar)
  597. {
  598. int pos;
  599. XtVaGetValues(scrollBar, XmNvalue, &pos, NULL);
  600. return pos;
  601. }
  602. else
  603. return 0;
  604. #endif // 0
  605. }
  606. // This now returns the whole range, not just the number of positions that we
  607. // can scroll.
  608. int wxWindow::GetScrollRange(int orient) const
  609. {
  610. Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
  611. // CE scintilla windows don't always have these scrollbars
  612. // and it tends to pile up a whole bunch of asserts
  613. //wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
  614. int range = 0;
  615. if (scrollBar)
  616. XtVaGetValues(scrollBar, XmNmaximum, &range, NULL);
  617. return range;
  618. }
  619. int wxWindow::GetScrollThumb(int orient) const
  620. {
  621. Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
  622. //wxCHECK_MSG( scrollBar, 0, "no such scrollbar" );
  623. int thumb = 0;
  624. if (scrollBar)
  625. XtVaGetValues(scrollBar, XmNsliderSize, &thumb, NULL);
  626. return thumb;
  627. }
  628. void wxWindow::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
  629. {
  630. Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient);
  631. if ( scrollBar )
  632. {
  633. XtVaSetValues (scrollBar, XmNvalue, pos, NULL);
  634. }
  635. SetInternalScrollPos((wxOrientation)orient, pos);
  636. }
  637. // New function that will replace some of the above.
  638. void wxWindow::SetScrollbar(int orient, int pos, int thumbVisible,
  639. int range, bool WXUNUSED(refresh))
  640. {
  641. int oldW, oldH;
  642. GetSize(& oldW, & oldH);
  643. if (range == 0)
  644. range = 1;
  645. if (thumbVisible == 0)
  646. thumbVisible = 1;
  647. if (thumbVisible > range)
  648. thumbVisible = range;
  649. // Save the old state to see if it changed
  650. WXWidget oldScrollBar = GetScrollbar((wxOrientation)orient);
  651. if (orient == wxHORIZONTAL)
  652. {
  653. if (thumbVisible == range)
  654. {
  655. if (m_hScrollBar)
  656. DestroyScrollbar(wxHORIZONTAL);
  657. }
  658. else
  659. {
  660. if (!m_hScrollBar)
  661. CreateScrollbar(wxHORIZONTAL);
  662. }
  663. }
  664. if (orient == wxVERTICAL)
  665. {
  666. if (thumbVisible == range)
  667. {
  668. if (m_vScrollBar)
  669. DestroyScrollbar(wxVERTICAL);
  670. }
  671. else
  672. {
  673. if (!m_vScrollBar)
  674. CreateScrollbar(wxVERTICAL);
  675. }
  676. }
  677. WXWidget newScrollBar = GetScrollbar((wxOrientation)orient);
  678. if (oldScrollBar != newScrollBar)
  679. {
  680. // This is important! Without it, scrollbars misbehave badly.
  681. XtUnrealizeWidget((Widget) m_scrolledWindow);
  682. XmScrolledWindowSetAreas ((Widget) m_scrolledWindow, (Widget) m_hScrollBar, (Widget) m_vScrollBar, (Widget) m_drawingArea);
  683. XtRealizeWidget((Widget) m_scrolledWindow);
  684. XtManageChild((Widget) m_scrolledWindow);
  685. }
  686. if (newScrollBar)
  687. {
  688. XtVaSetValues((Widget) newScrollBar,
  689. XmNvalue, pos,
  690. XmNminimum, 0,
  691. XmNmaximum, range,
  692. XmNsliderSize, thumbVisible,
  693. NULL);
  694. }
  695. SetInternalScrollPos((wxOrientation)orient, pos);
  696. int newW, newH;
  697. GetSize(& newW, & newH);
  698. // Adjusting scrollbars can resize the canvas accidentally
  699. if (newW != oldW || newH != oldH)
  700. SetSize(wxDefaultCoord, wxDefaultCoord, oldW, oldH);
  701. }
  702. // Does a physical scroll
  703. void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
  704. {
  705. int x, y, w, h;
  706. if (rect)
  707. {
  708. // Use specified rectangle
  709. x = rect->x; y = rect->y; w = rect->width; h = rect->height;
  710. }
  711. else
  712. {
  713. // Use whole client area
  714. x = 0; y = 0;
  715. GetClientSize(& w, & h);
  716. }
  717. int x1 = (dx >= 0) ? x : x - dx;
  718. int y1 = (dy >= 0) ? y : y - dy;
  719. int w1 = w - abs(dx);
  720. int h1 = h - abs(dy);
  721. int x2 = (dx >= 0) ? x + dx : x;
  722. int y2 = (dy >= 0) ? y + dy : y;
  723. wxClientDC dc(this);
  724. wxClientDCImpl * const
  725. dcimpl = static_cast<wxClientDCImpl *>(dc.GetImpl());
  726. GC const gc = (GC) dcimpl->GetGC();
  727. dc.SetLogicalFunction (wxCOPY);
  728. Widget widget = (Widget) GetMainWidget();
  729. Window window = XtWindow(widget);
  730. Display* display = XtDisplay(widget);
  731. XCopyArea(display, window, window, gc, x1, y1, w1, h1, x2, y2);
  732. dcimpl->SetAutoSetting(true);
  733. wxBrush brush(GetBackgroundColour(), wxSOLID);
  734. dc.SetBrush(brush); // FIXME: needed?
  735. wxWindowList::compatibility_iterator cnode = m_children.GetFirst();
  736. while (cnode)
  737. {
  738. wxWindow *child = cnode->GetData();
  739. int sx = 0;
  740. int sy = 0;
  741. child->GetSize( &sx, &sy );
  742. wxPoint pos( child->GetPosition() );
  743. child->SetSize( pos.x + dx, pos.y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
  744. cnode = cnode->GetNext();
  745. }
  746. // We'll add rectangles to the list of update rectangles according to which
  747. // bits we've exposed.
  748. wxList updateRects;
  749. if (dx > 0)
  750. {
  751. wxRect *rect = new wxRect;
  752. rect->x = x;
  753. rect->y = y;
  754. rect->width = dx;
  755. rect->height = h;
  756. XFillRectangle(display, window, gc, rect->x, rect->y, rect->width, rect->height);
  757. rect->x = rect->x;
  758. rect->y = rect->y;
  759. rect->width = rect->width;
  760. rect->height = rect->height;
  761. updateRects.Append((wxObject*) rect);
  762. }
  763. else if (dx < 0)
  764. {
  765. wxRect *rect = new wxRect;
  766. rect->x = x + w + dx;
  767. rect->y = y;
  768. rect->width = -dx;
  769. rect->height = h;
  770. XFillRectangle(display, window, gc, rect->x, rect->y, rect->width, rect->height);
  771. rect->x = rect->x;
  772. rect->y = rect->y;
  773. rect->width = rect->width;
  774. rect->height = rect->height;
  775. updateRects.Append((wxObject*) rect);
  776. }
  777. if (dy > 0)
  778. {
  779. wxRect *rect = new wxRect;
  780. rect->x = x;
  781. rect->y = y;
  782. rect->width = w;
  783. rect->height = dy;
  784. XFillRectangle(display, window, gc, rect->x, rect->y, rect->width, rect->height);
  785. rect->x = rect->x;
  786. rect->y = rect->y;
  787. rect->width = rect->width;
  788. rect->height = rect->height;
  789. updateRects.Append((wxObject*) rect);
  790. }
  791. else if (dy < 0)
  792. {
  793. wxRect *rect = new wxRect;
  794. rect->x = x;
  795. rect->y = y + h + dy;
  796. rect->width = w;
  797. rect->height = -dy;
  798. XFillRectangle(display, window, gc, rect->x, rect->y, rect->width, rect->height);
  799. rect->x = rect->x;
  800. rect->y = rect->y;
  801. rect->width = rect->width;
  802. rect->height = rect->height;
  803. updateRects.Append((wxObject*) rect);
  804. }
  805. dc.SetBrush(wxNullBrush);
  806. // Now send expose events
  807. wxList::compatibility_iterator node = updateRects.GetFirst();
  808. while (node)
  809. {
  810. wxRect* rect = (wxRect*) node->GetData();
  811. XExposeEvent event;
  812. event.type = Expose;
  813. event.display = display;
  814. event.send_event = True;
  815. event.window = window;
  816. event.x = rect->x;
  817. event.y = rect->y;
  818. event.width = rect->width;
  819. event.height = rect->height;
  820. event.count = 0;
  821. XSendEvent(display, window, False, ExposureMask, (XEvent *)&event);
  822. node = node->GetNext();
  823. }
  824. // Delete the update rects
  825. node = updateRects.GetFirst();
  826. while (node)
  827. {
  828. wxRect* rect = (wxRect*) node->GetData();
  829. delete rect;
  830. node = node->GetNext();
  831. }
  832. XmUpdateDisplay((Widget) GetMainWidget());
  833. }
  834. // ---------------------------------------------------------------------------
  835. // drag and drop
  836. // ---------------------------------------------------------------------------
  837. #if wxUSE_DRAG_AND_DROP
  838. void wxWindow::SetDropTarget(wxDropTarget * WXUNUSED(pDropTarget))
  839. {
  840. // TODO
  841. }
  842. #endif
  843. // Old style file-manager drag&drop
  844. void wxWindow::DragAcceptFiles(bool WXUNUSED(accept))
  845. {
  846. // TODO
  847. }
  848. // ----------------------------------------------------------------------------
  849. // tooltips
  850. // ----------------------------------------------------------------------------
  851. #if wxUSE_TOOLTIPS
  852. void wxWindow::DoSetToolTip(wxToolTip * WXUNUSED(tooltip))
  853. {
  854. // TODO
  855. }
  856. #endif // wxUSE_TOOLTIPS
  857. // ----------------------------------------------------------------------------
  858. // popup menus
  859. // ----------------------------------------------------------------------------
  860. #if wxUSE_MENUS
  861. bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
  862. {
  863. if ( x == wxDefaultCoord && y == wxDefaultCoord )
  864. {
  865. wxPoint mouse = ScreenToClient(wxGetMousePosition());
  866. x = mouse.x; y = mouse.y;
  867. }
  868. Widget widget = (Widget) GetMainWidget();
  869. /* The menuId field seems to be usused, so we'll use it to
  870. indicate whether a menu is popped up or not:
  871. 0: Not currently created as a popup
  872. -1: Created as a popup, but not active
  873. 1: Active popup.
  874. */
  875. if (menu->GetParent() && (menu->GetId() != -1))
  876. return false;
  877. if (menu->GetMainWidget())
  878. {
  879. menu->DestroyMenu(true);
  880. }
  881. menu->SetId(1); /* Mark as popped-up */
  882. menu->CreateMenu(NULL, widget, menu, 0);
  883. menu->UpdateUI();
  884. // menu->SetParent(parent);
  885. // parent->children->Append(menu); // Store menu for later deletion
  886. Widget menuWidget = (Widget) menu->GetMainWidget();
  887. int rootX = 0;
  888. int rootY = 0;
  889. int deviceX = x;
  890. int deviceY = y;
  891. /*
  892. if (this->IsKindOf(CLASSINFO(wxCanvas)))
  893. {
  894. wxCanvas *canvas = (wxCanvas *) this;
  895. deviceX = canvas->GetDC ()->LogicalToDeviceX (x);
  896. deviceY = canvas->GetDC ()->LogicalToDeviceY (y);
  897. }
  898. */
  899. Display *display = XtDisplay (widget);
  900. Window rootWindow = RootWindowOfScreen (XtScreen((Widget)widget));
  901. Window thisWindow = XtWindow (widget);
  902. Window childWindow;
  903. XTranslateCoordinates (display, thisWindow, rootWindow, (int) deviceX, (int) deviceY,
  904. &rootX, &rootY, &childWindow);
  905. XButtonPressedEvent event;
  906. event.type = ButtonPress;
  907. event.button = 1;
  908. event.x = deviceX;
  909. event.y = deviceY;
  910. event.x_root = rootX;
  911. event.y_root = rootY;
  912. XmMenuPosition (menuWidget, &event);
  913. XtManageChild (menuWidget);
  914. // The ID of a pop-up menu is 1 when active, and is set to 0 by the
  915. // idle-time destroy routine.
  916. // Waiting until this ID changes causes this function to block until
  917. // the menu has been dismissed and the widgets cleaned up.
  918. // In other words, once this routine returns, it is safe to delete
  919. // the menu object.
  920. // Ian Brown <ian.brown@printsoft.de>
  921. wxEventLoop evtLoop;
  922. while (menu->GetId() == 1)
  923. {
  924. wxDoEventLoopIteration( evtLoop );
  925. }
  926. return true;
  927. }
  928. #endif
  929. // ---------------------------------------------------------------------------
  930. // moving and resizing
  931. // ---------------------------------------------------------------------------
  932. bool wxWindow::PreResize()
  933. {
  934. return true;
  935. }
  936. // Get total size
  937. void wxWindow::DoGetSize(int *x, int *y) const
  938. {
  939. Widget widget = (Widget)( !m_drawingArea ? GetTopWidget() :
  940. ( m_borderWidget ? m_borderWidget :
  941. m_scrolledWindow ? m_scrolledWindow :
  942. m_drawingArea ) );
  943. Dimension xx, yy;
  944. if (widget)
  945. XtVaGetValues( widget,
  946. XmNwidth, &xx,
  947. XmNheight, &yy,
  948. NULL );
  949. if(x) *x = widget ? xx : -1;
  950. if(y) *y = widget ? yy : -1;
  951. }
  952. void wxWindow::DoGetPosition(int *x, int *y) const
  953. {
  954. Widget widget = (Widget)
  955. ( m_drawingArea ?
  956. ( m_borderWidget ? m_borderWidget : m_scrolledWindow ) :
  957. GetTopWidget() );
  958. Position xx, yy;
  959. XtVaGetValues(widget, XmNx, &xx, XmNy, &yy, NULL);
  960. // We may be faking the client origin. So a window that's really at (0, 30)
  961. // may appear (to wxWin apps) to be at (0, 0).
  962. if (GetParent())
  963. {
  964. wxPoint pt(GetParent()->GetClientAreaOrigin());
  965. xx = (Position)(xx - pt.x);
  966. yy = (Position)(yy - pt.y);
  967. }
  968. if(x) *x = xx;
  969. if(y) *y = yy;
  970. }
  971. void wxWindow::DoScreenToClient(int *x, int *y) const
  972. {
  973. Widget widget = (Widget) GetClientWidget();
  974. Display *display = XtDisplay((Widget) GetMainWidget());
  975. Window rootWindow = RootWindowOfScreen(XtScreen(widget));
  976. Window thisWindow = XtWindow(widget);
  977. Window childWindow;
  978. int xx = x ? *x : 0;
  979. int yy = y ? *y : 0;
  980. XTranslateCoordinates(display, rootWindow, thisWindow,
  981. xx, yy, x ? x : &xx, y ? y : &yy,
  982. &childWindow);
  983. }
  984. void wxWindow::DoClientToScreen(int *x, int *y) const
  985. {
  986. Widget widget = (Widget) GetClientWidget();
  987. Display *display = XtDisplay(widget);
  988. Window rootWindow = RootWindowOfScreen(XtScreen(widget));
  989. Window thisWindow = XtWindow(widget);
  990. Window childWindow;
  991. int xx = x ? *x : 0;
  992. int yy = y ? *y : 0;
  993. XTranslateCoordinates(display, thisWindow, rootWindow,
  994. xx, yy, x ? x : &xx, y ? y : &yy,
  995. &childWindow);
  996. }
  997. // Get size *available for subwindows* i.e. excluding menu bar etc.
  998. void wxWindow::DoGetClientSize(int *x, int *y) const
  999. {
  1000. Widget widget = (Widget) GetClientWidget();
  1001. Dimension xx, yy;
  1002. XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL);
  1003. if(x) *x = xx; if(y) *y = yy;
  1004. }
  1005. void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags)
  1006. {
  1007. DoSetSizeIntr(x, y, width, height, sizeFlags, false);
  1008. }
  1009. void wxWindow::DoSetSizeIntr(int x, int y, int width, int height,
  1010. int sizeFlags, bool fromCtor)
  1011. {
  1012. // A bit of optimization to help sort out the flickers.
  1013. int oldX = -1, oldY = -1, oldW = -1, oldH = -1;
  1014. if( !fromCtor )
  1015. {
  1016. GetSize(& oldW, & oldH);
  1017. GetPosition(& oldX, & oldY);
  1018. }
  1019. if (x == -1)
  1020. x = oldX;
  1021. if (x == -1)
  1022. x = oldY;
  1023. if ( !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
  1024. {
  1025. if ( width == -1 )
  1026. width = oldW;
  1027. if ( height == -1 )
  1028. height = oldH;
  1029. }
  1030. wxSize size(wxDefaultSize);
  1031. if ( width <= 0 )
  1032. {
  1033. if ( ( sizeFlags & wxSIZE_AUTO_WIDTH ) && !fromCtor )
  1034. {
  1035. size = DoGetBestSize();
  1036. width = size.x;
  1037. }
  1038. else
  1039. {
  1040. width = oldW;
  1041. }
  1042. }
  1043. if ( height == -1 )
  1044. {
  1045. if( ( sizeFlags & wxSIZE_AUTO_HEIGHT ) && !fromCtor )
  1046. {
  1047. if( size.x == -1 ) size = DoGetBestSize();
  1048. height = size.y;
  1049. }
  1050. else
  1051. {
  1052. height = oldH;
  1053. }
  1054. }
  1055. if ( x != oldX || y != oldY || width != oldW || height != oldH
  1056. || !wxNoOptimize::CanOptimize() )
  1057. {
  1058. if (m_drawingArea)
  1059. {
  1060. int flags = 0;
  1061. if (x != oldX)
  1062. flags |= wxMOVE_X;
  1063. if (y != oldY)
  1064. flags |= wxMOVE_Y;
  1065. if (width > 0)
  1066. flags |= wxMOVE_WIDTH;
  1067. if (height > 0)
  1068. flags |= wxMOVE_HEIGHT;
  1069. int xx = x; int yy = y;
  1070. AdjustForParentClientOrigin(xx, yy, sizeFlags);
  1071. if( !fromCtor )
  1072. DoMoveWindow( xx, yy, width, height );
  1073. else
  1074. DoMoveWindowIntr( xx, yy, width, height, flags );
  1075. return;
  1076. }
  1077. Widget widget = (Widget) GetTopWidget();
  1078. if (!widget)
  1079. return;
  1080. bool managed = XtIsManaged( widget );
  1081. if (managed)
  1082. XtUnmanageChild(widget);
  1083. int xx = x;
  1084. int yy = y;
  1085. AdjustForParentClientOrigin(xx, yy, sizeFlags);
  1086. DoMoveWindow(xx, yy, width, height);
  1087. if (managed)
  1088. XtManageChild(widget);
  1089. }
  1090. }
  1091. void wxWindow::DoSetClientSize(int width, int height)
  1092. {
  1093. if (m_drawingArea)
  1094. {
  1095. Widget drawingArea = (Widget) m_drawingArea;
  1096. XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
  1097. if (width > -1)
  1098. XtVaSetValues(drawingArea, XmNwidth, width, NULL);
  1099. if (height > -1)
  1100. XtVaSetValues(drawingArea, XmNheight, height, NULL);
  1101. XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
  1102. return;
  1103. }
  1104. Widget widget = (Widget) GetTopWidget();
  1105. if (width > -1)
  1106. XtVaSetValues(widget, XmNwidth, width, NULL);
  1107. if (height > -1)
  1108. XtVaSetValues(widget, XmNheight, height, NULL);
  1109. }
  1110. void wxWindow::DoMoveWindowIntr(int xx, int yy, int w, int h,
  1111. int flags)
  1112. {
  1113. if (m_drawingArea)
  1114. {
  1115. Widget drawingArea = (Widget) m_drawingArea;
  1116. Widget borderOrScrolled = m_borderWidget ?
  1117. (Widget) m_borderWidget :
  1118. (Widget) m_scrolledWindow;
  1119. bool managed = XtIsManaged(borderOrScrolled);
  1120. if (managed)
  1121. XtUnmanageChild (borderOrScrolled);
  1122. XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
  1123. if (flags & wxMOVE_X)
  1124. XtVaSetValues (borderOrScrolled,
  1125. XmNx, xx,
  1126. NULL);
  1127. if (flags & wxMOVE_Y)
  1128. XtVaSetValues (borderOrScrolled,
  1129. XmNy, yy,
  1130. NULL);
  1131. if (flags & wxMOVE_WIDTH)
  1132. {
  1133. if (m_borderWidget)
  1134. {
  1135. XtVaSetValues ((Widget) m_borderWidget, XmNwidth, w, NULL);
  1136. short thick, margin;
  1137. XtVaGetValues ((Widget) m_borderWidget,
  1138. XmNshadowThickness, &thick,
  1139. XmNmarginWidth, &margin,
  1140. NULL);
  1141. w -= 2 * (thick + margin);
  1142. }
  1143. if( w < 1 ) w = 1;
  1144. XtVaSetValues ((Widget) m_scrolledWindow, XmNwidth, w, NULL);
  1145. }
  1146. if (flags & wxMOVE_HEIGHT)
  1147. {
  1148. if (m_borderWidget)
  1149. {
  1150. XtVaSetValues ((Widget) m_borderWidget, XmNheight, h, NULL);
  1151. short thick, margin;
  1152. XtVaGetValues ((Widget) m_borderWidget,
  1153. XmNshadowThickness, &thick,
  1154. XmNmarginHeight, &margin,
  1155. NULL);
  1156. h -= 2 * (thick + margin);
  1157. }
  1158. if( h < 1 ) h = 1;
  1159. XtVaSetValues ((Widget) m_scrolledWindow, XmNheight, h, NULL);
  1160. }
  1161. if (managed)
  1162. XtManageChild (borderOrScrolled);
  1163. XtVaSetValues(drawingArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
  1164. }
  1165. else
  1166. {
  1167. if( w < 1 ) w = 1;
  1168. if( h < 1 ) h = 1;
  1169. XtVaSetValues((Widget)GetTopWidget(),
  1170. XmNx, xx,
  1171. XmNy, yy,
  1172. XmNwidth, w,
  1173. XmNheight, h,
  1174. NULL);
  1175. }
  1176. }
  1177. void wxWindow::DoMoveWindow(int x, int y, int width, int height)
  1178. {
  1179. DoMoveWindowIntr (x, y, width, height,
  1180. wxMOVE_X|wxMOVE_Y|wxMOVE_WIDTH|wxMOVE_HEIGHT);
  1181. }
  1182. // ---------------------------------------------------------------------------
  1183. // text metrics
  1184. // ---------------------------------------------------------------------------
  1185. int wxWindow::GetCharHeight() const
  1186. {
  1187. int height;
  1188. if (m_font.IsOk())
  1189. wxGetTextExtent (GetXDisplay(), m_font, 1.0,
  1190. "x", NULL, &height, NULL, NULL);
  1191. else
  1192. wxGetTextExtent (this, "x", NULL, &height, NULL, NULL);
  1193. return height;
  1194. }
  1195. int wxWindow::GetCharWidth() const
  1196. {
  1197. int width;
  1198. if (m_font.IsOk())
  1199. wxGetTextExtent (GetXDisplay(), m_font, 1.0,
  1200. "x", &width, NULL, NULL, NULL);
  1201. else
  1202. wxGetTextExtent (this, "x", &width, NULL, NULL, NULL);
  1203. return width;
  1204. }
  1205. void wxWindow::DoGetTextExtent(const wxString& string,
  1206. int *x, int *y,
  1207. int *descent,
  1208. int *externalLeading,
  1209. const wxFont *theFont) const
  1210. {
  1211. const wxFont *fontToUse = theFont ? theFont : &m_font;
  1212. if (externalLeading)
  1213. *externalLeading = 0;
  1214. if (fontToUse->IsOk())
  1215. wxGetTextExtent (GetXDisplay(), *fontToUse, 1.0,
  1216. string, x, y, NULL, descent);
  1217. else
  1218. wxGetTextExtent (this, string, x, y, NULL, descent);
  1219. }
  1220. // ----------------------------------------------------------------------------
  1221. // painting
  1222. // ----------------------------------------------------------------------------
  1223. void wxWindow::AddUpdateRect(int x, int y, int w, int h)
  1224. {
  1225. m_updateRegion.Union( x, y, w, h );
  1226. }
  1227. void wxWindow::Refresh(bool eraseBack, const wxRect *rect)
  1228. {
  1229. Widget widget = (Widget) GetMainWidget();
  1230. if (!widget)
  1231. return;
  1232. m_needsRefresh = true;
  1233. Display *display = XtDisplay(widget);
  1234. Window thisWindow = XtWindow(widget);
  1235. XExposeEvent dummyEvent;
  1236. int width, height;
  1237. GetSize(&width, &height);
  1238. dummyEvent.type = Expose;
  1239. dummyEvent.display = display;
  1240. dummyEvent.send_event = True;
  1241. dummyEvent.window = thisWindow;
  1242. if (rect)
  1243. {
  1244. dummyEvent.x = rect->x;
  1245. dummyEvent.y = rect->y;
  1246. dummyEvent.width = rect->width;
  1247. dummyEvent.height = rect->height;
  1248. }
  1249. else
  1250. {
  1251. dummyEvent.x = 0;
  1252. dummyEvent.y = 0;
  1253. dummyEvent.width = width;
  1254. dummyEvent.height = height;
  1255. }
  1256. dummyEvent.count = 0;
  1257. if (eraseBack)
  1258. {
  1259. wxClientDC dc(this);
  1260. wxBrush backgroundBrush(GetBackgroundColour(), wxSOLID);
  1261. dc.SetBackground(backgroundBrush);
  1262. wxClientDCImpl * const
  1263. dcimpl = static_cast<wxClientDCImpl *>(dc.GetImpl());
  1264. if (rect)
  1265. dcimpl->Clear(*rect);
  1266. else
  1267. dcimpl->Clear();
  1268. }
  1269. XSendEvent(display, thisWindow, False, ExposureMask, (XEvent *)&dummyEvent);
  1270. }
  1271. void wxWindow::DoPaint()
  1272. {
  1273. //TODO : make a temporary gc so we can do the XCopyArea below
  1274. if (m_backingPixmap && !m_needsRefresh)
  1275. {
  1276. wxPaintDC dc(this);
  1277. wxPaintDCImpl * const
  1278. dcimpl = static_cast<wxPaintDCImpl *>(dc.GetImpl());
  1279. GC tempGC = (GC) dcimpl->GetBackingGC();
  1280. Widget widget = (Widget) GetMainWidget();
  1281. int scrollPosX = 0;
  1282. int scrollPosY = 0;
  1283. // We have to test whether it's a wxScrolledWindow (hack!) because
  1284. // otherwise we don't know how many pixels have been scrolled. We might
  1285. // solve this in the future by defining virtual wxWindow functions to get
  1286. // the scroll position in pixels. Or, each kind of scrolled window has to
  1287. // implement backing stores itself, using generic wxWidgets code.
  1288. wxScrolledWindow* scrolledWindow = wxDynamicCast(this, wxScrolledWindow);
  1289. if ( scrolledWindow )
  1290. {
  1291. int x, y;
  1292. scrolledWindow->CalcScrolledPosition(0, 0, &x, &y);
  1293. scrollPosX = - x;
  1294. scrollPosY = - y;
  1295. }
  1296. // TODO: This could be optimized further by only copying the areas in the
  1297. // current update region.
  1298. // Only blit the part visible in the client area. The backing pixmap
  1299. // always starts at 0, 0 but we may be looking at only a portion of it.
  1300. wxSize clientArea = GetClientSize();
  1301. int toBlitX = m_pixmapWidth - scrollPosX;
  1302. int toBlitY = m_pixmapHeight - scrollPosY;
  1303. // Copy whichever is samller, the amount of pixmap we have to copy,
  1304. // or the size of the client area.
  1305. toBlitX = wxMin(toBlitX, clientArea.x);
  1306. toBlitY = wxMin(toBlitY, clientArea.y);
  1307. // Make sure we're not negative
  1308. toBlitX = wxMax(0, toBlitX);
  1309. toBlitY = wxMax(0, toBlitY);
  1310. XCopyArea
  1311. (
  1312. XtDisplay(widget),
  1313. (Pixmap) m_backingPixmap,
  1314. XtWindow (widget),
  1315. tempGC,
  1316. scrollPosX, scrollPosY, // Start at the scroll position
  1317. toBlitX, toBlitY, // How much of the pixmap to copy
  1318. 0, 0 // Destination
  1319. );
  1320. }
  1321. else
  1322. {
  1323. wxWindowDC dc(this);
  1324. // Set an erase event first
  1325. wxEraseEvent eraseEvent(GetId(), &dc);
  1326. eraseEvent.SetEventObject(this);
  1327. HandleWindowEvent(eraseEvent);
  1328. wxPaintEvent event(GetId());
  1329. event.SetEventObject(this);
  1330. HandleWindowEvent(event);
  1331. m_needsRefresh = false;
  1332. }
  1333. }
  1334. // ----------------------------------------------------------------------------
  1335. // event handlers
  1336. // ----------------------------------------------------------------------------
  1337. // Responds to colour changes: passes event on to children.
  1338. void wxWindow::OnSysColourChanged(wxSysColourChangedEvent& event)
  1339. {
  1340. wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
  1341. while ( node )
  1342. {
  1343. // Only propagate to non-top-level windows
  1344. wxWindow *win = node->GetData();
  1345. if ( win->GetParent() )
  1346. {
  1347. wxSysColourChangedEvent event2;
  1348. event.SetEventObject(win);
  1349. win->HandleWindowEvent(event2);
  1350. }
  1351. node = node->GetNext();
  1352. }
  1353. }
  1354. // ----------------------------------------------------------------------------
  1355. // accelerators
  1356. // ----------------------------------------------------------------------------
  1357. bool wxWindow::ProcessAccelerator(wxKeyEvent& event)
  1358. {
  1359. #if wxUSE_ACCEL
  1360. if (!m_acceleratorTable.IsOk())
  1361. return false;
  1362. int count = m_acceleratorTable.GetCount();
  1363. wxAcceleratorEntry* entries = m_acceleratorTable.GetEntries();
  1364. int i;
  1365. for (i = 0; i < count; i++)
  1366. {
  1367. wxAcceleratorEntry* entry = & (entries[i]);
  1368. if (entry->MatchesEvent(event))
  1369. {
  1370. // Bingo, we have a match. Now find a control that matches the
  1371. // entry command id.
  1372. // Need to go up to the top of the window hierarchy, since it might
  1373. // be e.g. a menu item
  1374. wxWindow* parent = this;
  1375. while ( parent && !parent->IsTopLevel() )
  1376. parent = parent->GetParent();
  1377. if (!parent)
  1378. return false;
  1379. wxFrame* frame = wxDynamicCast(parent, wxFrame);
  1380. if ( frame )
  1381. {
  1382. #if wxUSE_MENUS
  1383. // Try for a menu command
  1384. if (frame->GetMenuBar())
  1385. {
  1386. wxMenuItem* item = frame->GetMenuBar()->FindItem(entry->GetCommand());
  1387. if (item)
  1388. {
  1389. wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, entry->GetCommand());
  1390. commandEvent.SetEventObject(frame);
  1391. // If ProcessEvent returns true (it was handled), then
  1392. // the calling code will skip the event handling.
  1393. return frame->HandleWindowEvent(commandEvent);
  1394. }
  1395. }
  1396. #endif
  1397. }
  1398. // Find a child matching the command id
  1399. wxWindow* child = parent->FindWindow(entry->GetCommand());
  1400. // No such child
  1401. if (!child)
  1402. return false;
  1403. // Now we process those kinds of windows that we can.
  1404. // For now, only buttons.
  1405. if ( wxDynamicCast(child, wxButton) )
  1406. {
  1407. wxCommandEvent commandEvent (wxEVT_C