PageRenderTime 28ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/ExtLibs/wxWidgets/src/dfb/window.cpp

https://bitbucket.org/lennonchan/cafu
C++ | 1068 lines | 735 code | 185 blank | 148 comment | 133 complexity | ab8a5e2071bfb59817ba04598a84502e MD5 | raw file
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: src/dfb/window.cpp
  3. // Purpose: wxWindow
  4. // Author: Vaclav Slavik
  5. // (based on GTK, MSW, MGL implementations)
  6. // Created: 2006-80-10
  7. // RCS-ID: $Id$
  8. // Copyright: (c) 2006 REA Elektronik GmbH
  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. #ifdef __BORLANDC__
  20. #pragma hdrstop
  21. #endif
  22. #include "wx/window.h"
  23. #ifndef WX_PRECOMP
  24. #include "wx/dcclient.h"
  25. #include "wx/nonownedwnd.h"
  26. #endif
  27. #include "wx/caret.h"
  28. #include "wx/dynarray.h"
  29. #include "wx/dfb/private.h"
  30. #include "wx/private/overlay.h"
  31. #define TRACE_EVENTS "events"
  32. #define TRACE_PAINT "paint"
  33. // ===========================================================================
  34. // implementation
  35. // ===========================================================================
  36. // ---------------------------------------------------------------------------
  37. // global variables
  38. // ---------------------------------------------------------------------------
  39. // the window that has keyboard focus:
  40. static wxWindowDFB *gs_focusedWindow = NULL;
  41. // the window that is about to be focused after currently focused
  42. // one looses focus:
  43. static wxWindow *gs_toBeFocusedWindow = NULL;
  44. // the window that has mouse capture
  45. static wxWindowDFB *gs_mouseCapture = NULL;
  46. // ---------------------------------------------------------------------------
  47. // overlays support
  48. // ---------------------------------------------------------------------------
  49. WX_DEFINE_ARRAY_PTR(wxOverlayImpl*, wxDfbOverlaysList);
  50. // ---------------------------------------------------------------------------
  51. // event tables
  52. // ---------------------------------------------------------------------------
  53. // in wxUniv this class is abstract because it doesn't have DoPopupMenu()
  54. IMPLEMENT_ABSTRACT_CLASS(wxWindowDFB, wxWindowBase)
  55. BEGIN_EVENT_TABLE(wxWindowDFB, wxWindowBase)
  56. END_EVENT_TABLE()
  57. //-----------------------------------------------------------------------------
  58. // global functions
  59. //-----------------------------------------------------------------------------
  60. wxWindow *wxGetActiveWindow()
  61. {
  62. return wxWindow::FindFocus();
  63. }
  64. // ----------------------------------------------------------------------------
  65. // constructors and such
  66. // ----------------------------------------------------------------------------
  67. void wxWindowDFB::Init()
  68. {
  69. m_isShown = true;
  70. m_tlw = NULL;
  71. m_overlays = NULL;
  72. }
  73. // Destructor
  74. wxWindowDFB::~wxWindowDFB()
  75. {
  76. SendDestroyEvent();
  77. if ( gs_mouseCapture == this )
  78. ReleaseMouse();
  79. if ( gs_focusedWindow == this )
  80. DFBKillFocus();
  81. DestroyChildren();
  82. }
  83. // real construction (Init() must have been called before!)
  84. bool wxWindowDFB::Create(wxWindow *parent,
  85. wxWindowID id,
  86. const wxPoint& pos,
  87. const wxSize& size,
  88. long style,
  89. const wxString& name)
  90. {
  91. if ( !m_tlw && parent )
  92. m_tlw = parent->GetTLW();
  93. if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
  94. return false;
  95. if ( parent )
  96. parent->AddChild(this);
  97. // set the size to something bogus initially, in case some code tries to
  98. // create wxWindowDC before SetSize() is called below:
  99. m_rect.width = m_rect.height = 1;
  100. int x, y, w, h;
  101. x = pos.x, y = pos.y;
  102. if ( x == -1 ) x = 0;
  103. if ( y == -1 ) y = 0;
  104. w = WidthDefault(size.x);
  105. h = HeightDefault(size.y);
  106. SetSize(x, y, w, h);
  107. return true;
  108. }
  109. // ---------------------------------------------------------------------------
  110. // surface access
  111. // ---------------------------------------------------------------------------
  112. wxIDirectFBSurfacePtr wxWindowDFB::ObtainDfbSurface() const
  113. {
  114. wxCHECK_MSG( m_parent, NULL, "parentless window?" );
  115. wxIDirectFBSurfacePtr parentSurface(m_parent->GetDfbSurface());
  116. wxCHECK_MSG( parentSurface, NULL, "invalid parent surface" );
  117. wxRect r(GetRect());
  118. AdjustForParentClientOrigin(r.x, r.y, 0);
  119. DFBRectangle rect = { r.x, r.y, r.width, r.height };
  120. return parentSurface->GetSubSurface(&rect);
  121. }
  122. wxIDirectFBSurfacePtr wxWindowDFB::GetDfbSurface()
  123. {
  124. if ( !m_surface )
  125. {
  126. m_surface = ObtainDfbSurface();
  127. wxASSERT_MSG( m_surface, "invalid DirectFB surface" );
  128. }
  129. return m_surface;
  130. }
  131. void wxWindowDFB::InvalidateDfbSurface()
  132. {
  133. m_surface = NULL;
  134. // surfaces of the children are subsurfaces of this window's surface,
  135. // so they must be invalidated as well:
  136. wxWindowList& children = GetChildren();
  137. for ( wxWindowList::iterator i = children.begin(); i != children.end(); ++i )
  138. {
  139. (*i)->InvalidateDfbSurface();
  140. }
  141. }
  142. // ---------------------------------------------------------------------------
  143. // basic operations
  144. // ---------------------------------------------------------------------------
  145. void wxWindowDFB::SetFocus()
  146. {
  147. if ( gs_focusedWindow == this )
  148. return; // nothing to do, focused already
  149. wxWindowDFB *oldFocusedWindow = gs_focusedWindow;
  150. if ( gs_focusedWindow )
  151. {
  152. gs_toBeFocusedWindow = (wxWindow*)this;
  153. gs_focusedWindow->DFBKillFocus();
  154. gs_toBeFocusedWindow = NULL;
  155. }
  156. gs_focusedWindow = this;
  157. if ( IsShownOnScreen() &&
  158. (!oldFocusedWindow || oldFocusedWindow->GetTLW() != m_tlw) )
  159. {
  160. m_tlw->SetDfbFocus();
  161. }
  162. // else: do nothing, because DirectFB windows cannot have focus if they
  163. // are hidden; when the TLW becomes visible, it will set the focus
  164. // to use from wxTLW::Show()
  165. // notify the parent keeping track of focus for the kbd navigation
  166. // purposes that we got it
  167. wxChildFocusEvent eventFocus((wxWindow*)this);
  168. HandleWindowEvent(eventFocus);
  169. wxFocusEvent event(wxEVT_SET_FOCUS, GetId());
  170. event.SetEventObject(this);
  171. event.SetWindow((wxWindow*)oldFocusedWindow);
  172. HandleWindowEvent(event);
  173. #if wxUSE_CARET
  174. // caret needs to be informed about focus change
  175. wxCaret *caret = GetCaret();
  176. if ( caret )
  177. caret->OnSetFocus();
  178. #endif // wxUSE_CARET
  179. }
  180. void wxWindowDFB::DFBKillFocus()
  181. {
  182. wxCHECK_RET( gs_focusedWindow == this,
  183. "killing focus on window that doesn't have it" );
  184. gs_focusedWindow = NULL;
  185. if ( m_isBeingDeleted )
  186. return; // don't send any events from dtor
  187. #if wxUSE_CARET
  188. // caret needs to be informed about focus change
  189. wxCaret *caret = GetCaret();
  190. if ( caret )
  191. caret->OnKillFocus();
  192. #endif // wxUSE_CARET
  193. wxFocusEvent event(wxEVT_KILL_FOCUS, GetId());
  194. event.SetEventObject(this);
  195. event.SetWindow(gs_toBeFocusedWindow);
  196. HandleWindowEvent(event);
  197. }
  198. // ----------------------------------------------------------------------------
  199. // this wxWindowBase function is implemented here (in platform-specific file)
  200. // because it is static and so couldn't be made virtual
  201. // ----------------------------------------------------------------------------
  202. wxWindow *wxWindowBase::DoFindFocus()
  203. {
  204. return (wxWindow*)gs_focusedWindow;
  205. }
  206. bool wxWindowDFB::Show(bool show)
  207. {
  208. if ( !wxWindowBase::Show(show) )
  209. return false;
  210. // Unlike Refresh(), DoRefreshWindow() doesn't check visibility, so
  211. // call it to force refresh of either this window (if showing) or its
  212. // parent area at the place of this window (if hiding):
  213. DoRefreshWindow();
  214. return true;
  215. }
  216. // Raise the window to the top of the Z order
  217. void wxWindowDFB::Raise()
  218. {
  219. wxFAIL_MSG( "Raise() not implemented" );
  220. }
  221. // Lower the window to the bottom of the Z order
  222. void wxWindowDFB::Lower()
  223. {
  224. wxFAIL_MSG( "Lower() not implemented" );
  225. }
  226. void wxWindowDFB::DoCaptureMouse()
  227. {
  228. #warning "implement this"
  229. #if 0
  230. if ( gs_mouseCapture )
  231. DFB_wmUncaptureEvents(gs_mouseCapture->m_wnd, wxDFB_CAPTURE_MOUSE);
  232. #endif
  233. gs_mouseCapture = this;
  234. #if 0
  235. DFB_wmCaptureEvents(m_wnd, EVT_MOUSEEVT, wxDFB_CAPTURE_MOUSE);
  236. #endif
  237. }
  238. void wxWindowDFB::DoReleaseMouse()
  239. {
  240. wxASSERT_MSG( gs_mouseCapture == this, wxT("attempt to release mouse, but this window hasn't captured it") );
  241. #warning "implement this"
  242. #if 0
  243. DFB_wmUncaptureEvents(m_wnd, wxDFB_CAPTURE_MOUSE);
  244. #endif
  245. gs_mouseCapture = NULL;
  246. }
  247. /* static */ wxWindow *wxWindowBase::GetCapture()
  248. {
  249. return (wxWindow*)gs_mouseCapture;
  250. }
  251. bool wxWindowDFB::SetCursor(const wxCursor& cursor)
  252. {
  253. if ( !wxWindowBase::SetCursor(cursor) )
  254. {
  255. // no change
  256. return false;
  257. }
  258. #warning "implement this"
  259. #if 0
  260. if ( m_cursor.IsOk() )
  261. DFB_wmSetWindowCursor(m_wnd, *m_cursor.GetDFBCursor());
  262. else
  263. DFB_wmSetWindowCursor(m_wnd, *wxSTANDARD_CURSOR->GetDFBCursor());
  264. #endif
  265. return true;
  266. }
  267. void wxWindowDFB::WarpPointer(int x, int y)
  268. {
  269. int w, h;
  270. wxDisplaySize(&w, &h);
  271. ClientToScreen(&x, &y);
  272. if ( x < 0 ) x = 0;
  273. if ( y < 0 ) y = 0;
  274. if ( x >= w ) x = w-1;
  275. if ( y >= h ) y = h-1;
  276. wxIDirectFBDisplayLayerPtr layer(wxIDirectFB::Get()->GetDisplayLayer());
  277. wxCHECK_RET( layer, "no display layer" );
  278. layer->WarpCursor(x, y);
  279. }
  280. // Set this window to be the child of 'parent'.
  281. bool wxWindowDFB::Reparent(wxWindowBase *parent)
  282. {
  283. if ( !wxWindowBase::Reparent(parent) )
  284. return false;
  285. #warning "implement this"
  286. wxFAIL_MSG( "reparenting not yet implemented" );
  287. return true;
  288. }
  289. // ---------------------------------------------------------------------------
  290. // moving and resizing
  291. // ---------------------------------------------------------------------------
  292. // Get total size
  293. void wxWindowDFB::DoGetSize(int *x, int *y) const
  294. {
  295. if (x) *x = m_rect.width;
  296. if (y) *y = m_rect.height;
  297. }
  298. void wxWindowDFB::DoGetPosition(int *x, int *y) const
  299. {
  300. if (x) *x = m_rect.x;
  301. if (y) *y = m_rect.y;
  302. }
  303. static wxPoint GetScreenPosOfClientOrigin(const wxWindowDFB *win)
  304. {
  305. wxCHECK_MSG( win, wxPoint(0, 0), "no window provided" );
  306. wxPoint pt(win->GetPosition() + win->GetClientAreaOrigin());
  307. if ( !win->IsTopLevel() )
  308. pt += GetScreenPosOfClientOrigin(win->GetParent());
  309. return pt;
  310. }
  311. void wxWindowDFB::DoScreenToClient(int *x, int *y) const
  312. {
  313. wxPoint o = GetScreenPosOfClientOrigin(this);
  314. if (x) *x -= o.x;
  315. if (y) *y -= o.y;
  316. }
  317. void wxWindowDFB::DoClientToScreen(int *x, int *y) const
  318. {
  319. wxPoint o = GetScreenPosOfClientOrigin(this);
  320. if (x) *x += o.x;
  321. if (y) *y += o.y;
  322. }
  323. // Get size *available for subwindows* i.e. excluding menu bar etc.
  324. void wxWindowDFB::DoGetClientSize(int *x, int *y) const
  325. {
  326. DoGetSize(x, y);
  327. }
  328. void wxWindowDFB::DoMoveWindow(int x, int y, int width, int height)
  329. {
  330. // NB: [x,y] arguments are in (parent's) window coordinates, while
  331. // m_rect.{x,y} are in (parent's) client coordinates. That's why we
  332. // offset by parentOrigin in some places below
  333. wxPoint parentOrigin(0, 0);
  334. AdjustForParentClientOrigin(parentOrigin.x, parentOrigin.y);
  335. wxRect oldpos(m_rect);
  336. oldpos.Offset(parentOrigin);
  337. wxRect newpos(x, y, width, height);
  338. // input [x,y] is in window coords, but we store client coords in m_rect:
  339. m_rect = newpos;
  340. m_rect.Offset(-parentOrigin);
  341. // window's position+size changed and so did the subsurface that covers it
  342. InvalidateDfbSurface();
  343. if ( IsShown() )
  344. {
  345. // queue both former and new position of the window for repainting:
  346. wxWindow *parent = GetParent();
  347. // only refresh the visible parts:
  348. if ( !CanBeOutsideClientArea() )
  349. {
  350. wxRect parentClient(parent->GetClientSize());
  351. oldpos.Intersect(parentClient);
  352. newpos.Intersect(parentClient);
  353. }
  354. parent->RefreshRect(oldpos);
  355. parent->RefreshRect(newpos);
  356. }
  357. }
  358. // set the size of the window: if the dimensions are positive, just use them,
  359. // but if any of them is equal to -1, it means that we must find the value for
  360. // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
  361. // which case -1 is a valid value for x and y)
  362. //
  363. // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
  364. // the width/height to best suit our contents, otherwise we reuse the current
  365. // width/height
  366. void wxWindowDFB::DoSetSize(int x, int y, int width, int height, int sizeFlags)
  367. {
  368. // get the current size and position...
  369. int currentX, currentY;
  370. GetPosition(&currentX, &currentY);
  371. int currentW,currentH;
  372. GetSize(&currentW, &currentH);
  373. if ( x == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
  374. x = currentX;
  375. if ( y == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
  376. y = currentY;
  377. // ... and don't do anything (avoiding flicker) if it's already ok
  378. if ( x == currentX && y == currentY &&
  379. width == currentW && height == currentH )
  380. {
  381. return;
  382. }
  383. wxSize size(-1, -1);
  384. if ( width == -1 )
  385. {
  386. if ( sizeFlags & wxSIZE_AUTO_WIDTH )
  387. {
  388. size = DoGetBestSize();
  389. width = size.x;
  390. }
  391. else
  392. {
  393. // just take the current one
  394. width = currentW;
  395. }
  396. }
  397. if ( height == -1 )
  398. {
  399. if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
  400. {
  401. if ( size.x == -1 )
  402. {
  403. size = DoGetBestSize();
  404. }
  405. //else: already called DoGetBestSize() above
  406. height = size.y;
  407. }
  408. else
  409. {
  410. // just take the current one
  411. height = currentH;
  412. }
  413. }
  414. int maxWidth = GetMaxWidth(),
  415. minWidth = GetMinWidth(),
  416. maxHeight = GetMaxHeight(),
  417. minHeight = GetMinHeight();
  418. if ( minWidth != -1 && width < minWidth ) width = minWidth;
  419. if ( maxWidth != -1 && width > maxWidth ) width = maxWidth;
  420. if ( minHeight != -1 && height < minHeight ) height = minHeight;
  421. if ( maxHeight != -1 && height > maxHeight ) height = maxHeight;
  422. if ( m_rect.x != x || m_rect.y != y ||
  423. m_rect.width != width || m_rect.height != height )
  424. {
  425. AdjustForParentClientOrigin(x, y, sizeFlags);
  426. DoMoveWindow(x, y, width, height);
  427. wxSize newSize(width, height);
  428. wxSizeEvent event(newSize, GetId());
  429. event.SetEventObject(this);
  430. HandleWindowEvent(event);
  431. }
  432. }
  433. void wxWindowDFB::DoSetClientSize(int width, int height)
  434. {
  435. SetSize(width, height);
  436. }
  437. // ---------------------------------------------------------------------------
  438. // text metrics
  439. // ---------------------------------------------------------------------------
  440. int wxWindowDFB::GetCharHeight() const
  441. {
  442. wxWindowDC dc((wxWindow*)this);
  443. return dc.GetCharHeight();
  444. }
  445. int wxWindowDFB::GetCharWidth() const
  446. {
  447. wxWindowDC dc((wxWindow*)this);
  448. return dc.GetCharWidth();
  449. }
  450. void wxWindowDFB::DoGetTextExtent(const wxString& string,
  451. int *x, int *y,
  452. int *descent,
  453. int *externalLeading,
  454. const wxFont *theFont) const
  455. {
  456. wxWindowDC dc((wxWindow*)this);
  457. dc.GetTextExtent(string, x, y, descent, externalLeading, (wxFont*)theFont);
  458. }
  459. // ---------------------------------------------------------------------------
  460. // painting
  461. // ---------------------------------------------------------------------------
  462. void wxWindowDFB::Refresh(bool WXUNUSED(eraseBack), const wxRect *rect)
  463. {
  464. if ( !IsShown() || IsFrozen() )
  465. return;
  466. // NB[1]: We intentionally ignore the eraseBack argument here. This is
  467. // because of the way wxDFB's painting is implemented: the refresh
  468. // request is propagated up to wxTLW, which is then painted in
  469. // top-down order. This means that this window's area is first
  470. // painted by its parent and this window is then painted over it, so
  471. // it's not safe to not paint this window's background even if
  472. // eraseBack=false.
  473. // NB[2]: wxWindow::Refresh() takes the rectangle in client coords, but
  474. // wxUniv translates it to window coords before passing it to
  475. // wxWindowDFB::Refresh(), so we can directly pass the rect to
  476. // DoRefreshRect (which takes window, not client, coords) here.
  477. if ( rect )
  478. DoRefreshRect(*rect);
  479. else
  480. DoRefreshWindow();
  481. }
  482. void wxWindowDFB::RefreshWindowRect(const wxRect& rect)
  483. {
  484. if ( !IsShown() || IsFrozen() )
  485. return;
  486. DoRefreshRect(rect);
  487. }
  488. void wxWindowDFB::DoRefreshWindow()
  489. {
  490. // NB: DoRefreshRect() takes window coords, not client, so this is correct
  491. DoRefreshRect(wxRect(GetSize()));
  492. }
  493. void wxWindowDFB::DoRefreshRect(const wxRect& rect)
  494. {
  495. wxWindow *parent = GetParent();
  496. wxCHECK_RET( parent, "no parent" );
  497. // don't overlap outside of the window (NB: 'rect' is in window coords):
  498. wxRect r(rect);
  499. r.Intersect(wxRect(GetSize()));
  500. if ( r.IsEmpty() )
  501. return;
  502. wxLogTrace(TRACE_PAINT,
  503. "%p ('%s'): refresh rect [%i,%i,%i,%i]",
  504. this, GetName().c_str(),
  505. rect.x, rect.y, rect.GetRight(), rect.GetBottom());
  506. // convert the refresh rectangle to parent's coordinates and
  507. // recursively refresh the parent:
  508. r.Offset(GetPosition());
  509. r.Offset(parent->GetClientAreaOrigin());
  510. // normal windows cannot extend out of its parent's client area, so don't
  511. // refresh any hidden parts:
  512. if ( !CanBeOutsideClientArea() )
  513. r.Intersect(parent->GetClientRect());
  514. parent->DoRefreshRect(r);
  515. }
  516. void wxWindowDFB::Update()
  517. {
  518. if ( !IsShown() || IsFrozen() )
  519. return;
  520. GetParent()->Update();
  521. }
  522. void wxWindowDFB::DoThaw()
  523. {
  524. if ( IsShown() )
  525. DoRefreshWindow();
  526. }
  527. void wxWindowDFB::PaintWindow(const wxRect& rect)
  528. {
  529. wxCHECK_RET( !IsFrozen() && IsShown(), "shouldn't be called" );
  530. wxLogTrace(TRACE_PAINT,
  531. "%p ('%s'): painting region [%i,%i,%i,%i]",
  532. this, GetName().c_str(),
  533. rect.x, rect.y, rect.GetRight(), rect.GetBottom());
  534. m_updateRegion = rect;
  535. // FIXME_DFB: don't waste time rendering the area if it's fully covered
  536. // by some children, go directly to rendering the children
  537. // (unless some child has HasTransparentBackground()=true!)
  538. // NB: unconditionally send wxEraseEvent, because our implementation of
  539. // wxWindow::Refresh() ignores the eraseBack argument
  540. wxWindowDC dc((wxWindow*)this);
  541. wxEraseEvent eventEr(m_windowId, &dc);
  542. eventEr.SetEventObject(this);
  543. HandleWindowEvent(eventEr);
  544. wxRect clientRect(GetClientRect());
  545. // only send wxNcPaintEvent if drawing at least part of nonclient area:
  546. if ( !clientRect.Contains(rect) )
  547. {
  548. wxNcPaintEvent eventNc(GetId());
  549. eventNc.SetEventObject(this);
  550. HandleWindowEvent(eventNc);
  551. }
  552. else
  553. {
  554. wxLogTrace(TRACE_PAINT, "%p ('%s'): not sending wxNcPaintEvent",
  555. this, GetName().c_str());
  556. }
  557. // only send wxPaintEvent if drawing at least part of client area:
  558. if ( rect.Intersects(clientRect) )
  559. {
  560. wxPaintEvent eventPt(GetId());
  561. eventPt.SetEventObject(this);
  562. HandleWindowEvent(eventPt);
  563. }
  564. else
  565. {
  566. wxLogTrace(TRACE_PAINT, "%p ('%s'): not sending wxPaintEvent",
  567. this, GetName().c_str());
  568. }
  569. // draw window's overlays on top of the painted window, if we have any:
  570. PaintOverlays(rect);
  571. m_updateRegion.Clear();
  572. // client area portion of 'rect':
  573. wxRect rectClientOnly(rect);
  574. rectClientOnly.Intersect(clientRect);
  575. // paint the children:
  576. wxPoint origin = GetClientAreaOrigin();
  577. wxWindowList& children = GetChildren();
  578. for ( wxWindowList::iterator i = children.begin();
  579. i != children.end(); ++i )
  580. {
  581. wxWindow *child = *i;
  582. if ( child->IsFrozen() || !child->IsShown() )
  583. continue; // don't paint anything if the window is frozen or hidden
  584. // compute child's area to repaint
  585. wxRect childrect(child->GetRect());
  586. childrect.Offset(origin);
  587. if ( child->CanBeOutsideClientArea() )
  588. childrect.Intersect(rect);
  589. else
  590. childrect.Intersect(rectClientOnly);
  591. if ( childrect.IsEmpty() )
  592. continue;
  593. // and repaint it:
  594. childrect.Offset(-child->GetPosition());
  595. childrect.Offset(-origin);
  596. child->PaintWindow(childrect);
  597. }
  598. }
  599. void wxWindowDFB::PaintOverlays(const wxRect& rect)
  600. {
  601. if ( !m_overlays )
  602. return;
  603. for ( wxDfbOverlaysList::const_iterator i = m_overlays->begin();
  604. i != m_overlays->end(); ++i )
  605. {
  606. const wxOverlayImpl * const overlay = *i;
  607. wxRect orectOrig(overlay->GetRect());
  608. wxRect orect(orectOrig);
  609. orect.Intersect(rect);
  610. if ( orect.IsEmpty() )
  611. continue;
  612. if ( overlay->IsEmpty() )
  613. continue; // nothing to paint
  614. DFBRectangle dfbRect = { orect.x - orectOrig.x, orect.y - orectOrig.y,
  615. orect.width, orect.height };
  616. GetDfbSurface()->Blit
  617. (
  618. overlay->GetDirectFBSurface(),
  619. &dfbRect,
  620. orect.x, orect.y
  621. );
  622. }
  623. }
  624. void wxWindowDFB::AddOverlay(wxOverlayImpl *overlay)
  625. {
  626. if ( !m_overlays )
  627. m_overlays = new wxDfbOverlaysList;
  628. m_overlays->Add(overlay);
  629. }
  630. void wxWindowDFB::RemoveOverlay(wxOverlayImpl *overlay)
  631. {
  632. wxCHECK_RET( m_overlays, "no overlays to remove" );
  633. m_overlays->Remove(overlay);
  634. if ( m_overlays->empty() )
  635. {
  636. wxDELETE(m_overlays);
  637. }
  638. if ( !m_isBeingDeleted )
  639. RefreshWindowRect(overlay->GetRect());
  640. }
  641. // ---------------------------------------------------------------------------
  642. // events handling
  643. // ---------------------------------------------------------------------------
  644. #define KEY(dfb, wx) \
  645. case dfb: \
  646. wxLogTrace(TRACE_EVENTS, \
  647. wxT("key " #dfb " mapped to " #wx)); \
  648. return wx
  649. // returns translated keycode, i.e. the one for KEYUP/KEYDOWN where 'a'..'z' is
  650. // translated to 'A'..'Z'
  651. static long GetTranslatedKeyCode(DFBInputDeviceKeyIdentifier key_id)
  652. {
  653. switch ( key_id )
  654. {
  655. KEY(DIKI_UNKNOWN, 0);
  656. KEY(DIKI_A, 'A');
  657. KEY(DIKI_B, 'B');
  658. KEY(DIKI_C, 'C');
  659. KEY(DIKI_D, 'D');
  660. KEY(DIKI_E, 'E');
  661. KEY(DIKI_F, 'F');
  662. KEY(DIKI_G, 'G');
  663. KEY(DIKI_H, 'H');
  664. KEY(DIKI_I, 'I');
  665. KEY(DIKI_J, 'J');
  666. KEY(DIKI_K, 'K');
  667. KEY(DIKI_L, 'L');
  668. KEY(DIKI_M, 'M');
  669. KEY(DIKI_N, 'N');
  670. KEY(DIKI_O, 'O');
  671. KEY(DIKI_P, 'P');
  672. KEY(DIKI_Q, 'Q');
  673. KEY(DIKI_R, 'R');
  674. KEY(DIKI_S, 'S');
  675. KEY(DIKI_T, 'T');
  676. KEY(DIKI_U, 'U');
  677. KEY(DIKI_V, 'V');
  678. KEY(DIKI_W, 'W');
  679. KEY(DIKI_X, 'X');
  680. KEY(DIKI_Y, 'Y');
  681. KEY(DIKI_Z, 'Z');
  682. KEY(DIKI_0, '0');
  683. KEY(DIKI_1, '1');
  684. KEY(DIKI_2, '2');
  685. KEY(DIKI_3, '3');
  686. KEY(DIKI_4, '4');
  687. KEY(DIKI_5, '5');
  688. KEY(DIKI_6, '6');
  689. KEY(DIKI_7, '7');
  690. KEY(DIKI_8, '8');
  691. KEY(DIKI_9, '9');
  692. KEY(DIKI_F1, WXK_F1);
  693. KEY(DIKI_F2, WXK_F2);
  694. KEY(DIKI_F3, WXK_F3);
  695. KEY(DIKI_F4, WXK_F4);
  696. KEY(DIKI_F5, WXK_F5);
  697. KEY(DIKI_F6, WXK_F6);
  698. KEY(DIKI_F7, WXK_F7);
  699. KEY(DIKI_F8, WXK_F8);
  700. KEY(DIKI_F9, WXK_F9);
  701. KEY(DIKI_F10, WXK_F10);
  702. KEY(DIKI_F11, WXK_F11);
  703. KEY(DIKI_F12, WXK_F12);
  704. KEY(DIKI_SHIFT_L, WXK_SHIFT);
  705. KEY(DIKI_SHIFT_R, WXK_SHIFT);
  706. KEY(DIKI_CONTROL_L, WXK_CONTROL);
  707. KEY(DIKI_CONTROL_R, WXK_CONTROL);
  708. KEY(DIKI_ALT_L, WXK_ALT);
  709. KEY(DIKI_ALT_R, WXK_ALT);
  710. // this key was removed in 0.9.25 but include it for previous versions
  711. // just to avoid gcc warnings about unhandled enum value in switch
  712. #if !wxCHECK_DFB_VERSION(0, 9, 24)
  713. KEY(DIKI_ALTGR, 0);
  714. #endif
  715. KEY(DIKI_META_L, 0);
  716. KEY(DIKI_META_R, 0);
  717. KEY(DIKI_SUPER_L, 0);
  718. KEY(DIKI_SUPER_R, 0);
  719. KEY(DIKI_HYPER_L, 0);
  720. KEY(DIKI_HYPER_R, 0);
  721. KEY(DIKI_CAPS_LOCK, 0);
  722. KEY(DIKI_NUM_LOCK, WXK_NUMLOCK);
  723. KEY(DIKI_SCROLL_LOCK, 0);
  724. KEY(DIKI_ESCAPE, WXK_ESCAPE);
  725. KEY(DIKI_LEFT, WXK_LEFT);
  726. KEY(DIKI_RIGHT, WXK_RIGHT);
  727. KEY(DIKI_UP, WXK_UP);
  728. KEY(DIKI_DOWN, WXK_DOWN);
  729. KEY(DIKI_TAB, WXK_TAB);
  730. KEY(DIKI_ENTER, WXK_RETURN);
  731. KEY(DIKI_SPACE, WXK_SPACE);
  732. KEY(DIKI_BACKSPACE, WXK_BACK);
  733. KEY(DIKI_INSERT, WXK_INSERT);
  734. KEY(DIKI_DELETE, WXK_DELETE);
  735. KEY(DIKI_HOME, WXK_HOME);
  736. KEY(DIKI_END, WXK_END);
  737. KEY(DIKI_PAGE_UP, WXK_PAGEUP);
  738. KEY(DIKI_PAGE_DOWN, WXK_PAGEDOWN);
  739. KEY(DIKI_PRINT, WXK_PRINT);
  740. KEY(DIKI_PAUSE, WXK_PAUSE);
  741. KEY(DIKI_QUOTE_LEFT, '`');
  742. KEY(DIKI_MINUS_SIGN, '-');
  743. KEY(DIKI_EQUALS_SIGN, '=');
  744. KEY(DIKI_BRACKET_LEFT, '[');
  745. KEY(DIKI_BRACKET_RIGHT, ']');
  746. KEY(DIKI_BACKSLASH, '\\');
  747. KEY(DIKI_SEMICOLON, ';');
  748. KEY(DIKI_QUOTE_RIGHT, '\'');
  749. KEY(DIKI_COMMA, ',');
  750. KEY(DIKI_PERIOD, '.');
  751. KEY(DIKI_SLASH, '/');
  752. KEY(DIKI_LESS_SIGN, '<');
  753. KEY(DIKI_KP_DIV, WXK_NUMPAD_DIVIDE);
  754. KEY(DIKI_KP_MULT, WXK_NUMPAD_MULTIPLY);
  755. KEY(DIKI_KP_MINUS, WXK_NUMPAD_SUBTRACT);
  756. KEY(DIKI_KP_PLUS, WXK_NUMPAD_ADD);
  757. KEY(DIKI_KP_ENTER, WXK_NUMPAD_ENTER);
  758. KEY(DIKI_KP_SPACE, WXK_NUMPAD_SPACE);
  759. KEY(DIKI_KP_TAB, WXK_NUMPAD_TAB);
  760. KEY(DIKI_KP_F1, WXK_NUMPAD_F1);
  761. KEY(DIKI_KP_F2, WXK_NUMPAD_F2);
  762. KEY(DIKI_KP_F3, WXK_NUMPAD_F3);
  763. KEY(DIKI_KP_F4, WXK_NUMPAD_F4);
  764. KEY(DIKI_KP_EQUAL, WXK_NUMPAD_EQUAL);
  765. KEY(DIKI_KP_SEPARATOR, WXK_NUMPAD_SEPARATOR);
  766. KEY(DIKI_KP_DECIMAL, WXK_NUMPAD_DECIMAL);
  767. KEY(DIKI_KP_0, WXK_NUMPAD0);
  768. KEY(DIKI_KP_1, WXK_NUMPAD1);
  769. KEY(DIKI_KP_2, WXK_NUMPAD2);
  770. KEY(DIKI_KP_3, WXK_NUMPAD3);
  771. KEY(DIKI_KP_4, WXK_NUMPAD4);
  772. KEY(DIKI_KP_5, WXK_NUMPAD5);
  773. KEY(DIKI_KP_6, WXK_NUMPAD6);
  774. KEY(DIKI_KP_7, WXK_NUMPAD7);
  775. KEY(DIKI_KP_8, WXK_NUMPAD8);
  776. KEY(DIKI_KP_9, WXK_NUMPAD9);
  777. case DIKI_KEYDEF_END:
  778. case DIKI_NUMBER_OF_KEYS:
  779. wxFAIL_MSG( "invalid key_id value" );
  780. return 0;
  781. }
  782. return 0; // silence compiler warnings
  783. }
  784. // returns untranslated keycode, i.e. for EVT_CHAR, where characters are left in
  785. // the form they were entered (lowercase, diacritics etc.)
  786. static long GetUntraslatedKeyCode(DFBInputDeviceKeyIdentifier key_id,
  787. DFBInputDeviceKeySymbol key_symbol)
  788. {
  789. switch ( DFB_KEY_TYPE(key_symbol) )
  790. {
  791. case DIKT_UNICODE:
  792. #if wxUSE_UNICODE
  793. return key_symbol;
  794. #else
  795. if ( key_symbol < 128 )
  796. return key_symbol;
  797. else
  798. {
  799. wchar_t chr = key_symbol;
  800. wxCharBuffer buf(wxConvUI->cWC2MB(&chr, 1, NULL));
  801. if ( buf )
  802. return *buf; // may be 0 if failed
  803. else
  804. return 0;
  805. }
  806. #endif
  807. default:
  808. return GetTranslatedKeyCode(key_id);
  809. }
  810. }
  811. #undef KEY
  812. void wxWindowDFB::HandleKeyEvent(const wxDFBWindowEvent& event_)
  813. {
  814. if ( !IsEnabled() )
  815. return;
  816. const DFBWindowEvent& e = event_;
  817. wxLogTrace(TRACE_EVENTS,
  818. "handling key %s event for window %p ('%s')",
  819. e.type == DWET_KEYUP ? "up" : "down",
  820. this, GetName().c_str());
  821. // fill in wxKeyEvent fields:
  822. wxKeyEvent event;
  823. event.SetEventObject(this);
  824. event.SetTimestamp(wxDFB_EVENT_TIMESTAMP(e));
  825. event.m_rawCode = e.key_code;
  826. event.m_keyCode = GetTranslatedKeyCode(e.key_id);
  827. #if wxUSE_UNICODE
  828. event.m_uniChar = e.key_symbol;
  829. #endif
  830. event.m_shiftDown = ( e.modifiers & DIMM_SHIFT ) != 0;
  831. event.m_controlDown = ( e.modifiers & DIMM_CONTROL ) != 0;
  832. event.m_altDown = ( e.modifiers & DIMM_ALT ) != 0;
  833. event.m_metaDown = ( e.modifiers & DIMM_META ) != 0;
  834. // translate coordinates from TLW-relative to this window-relative:
  835. event.m_x = e.x;
  836. event.m_y = e.y;
  837. GetTLW()->ClientToScreen(&event.m_x, &event.m_y);
  838. this->ScreenToClient(&event.m_x, &event.m_y);
  839. if ( e.type == DWET_KEYUP )
  840. {
  841. event.SetEventType(wxEVT_KEY_UP);
  842. HandleWindowEvent(event);
  843. }
  844. else
  845. {
  846. bool isTab = (event.m_keyCode == WXK_TAB);
  847. event.SetEventType(wxEVT_KEY_DOWN);
  848. if ( HandleWindowEvent(event) )
  849. return;
  850. // only send wxEVT_CHAR event if not processed yet:
  851. event.m_keyCode = GetUntraslatedKeyCode(e.key_id, e.key_symbol);
  852. if ( event.m_keyCode != 0 )
  853. {
  854. event.SetEventType(wxEVT_CHAR);
  855. if ( HandleWindowEvent(event) )
  856. return;
  857. }
  858. // Synthetize navigation key event, but do it only if the TAB key
  859. // wasn't handled yet:
  860. if ( isTab && GetParent() && GetParent()->HasFlag(wxTAB_TRAVERSAL) )
  861. {
  862. wxNavigationKeyEvent navEvent;
  863. navEvent.SetEventObject(GetParent());
  864. // Shift-TAB goes in reverse direction:
  865. navEvent.SetDirection(!event.m_shiftDown);
  866. // Ctrl-TAB changes the (parent) window, i.e. switch notebook page:
  867. navEvent.SetWindowChange(event.m_controlDown);
  868. navEvent.SetCurrentFocus(wxStaticCast(this, wxWindow));
  869. GetParent()->HandleWindowEvent(navEvent);
  870. }
  871. }
  872. }
  873. // Find the wxWindow at the current mouse position, returning the mouse
  874. // position.
  875. wxWindow* wxFindWindowAtPointer(wxPoint& pt)
  876. {
  877. return wxFindWindowAtPoint(pt = wxGetMousePosition());
  878. }
  879. wxWindow* wxFindWindowAtPoint(const wxPoint& WXUNUSED(pt))
  880. {
  881. wxFAIL_MSG( "wxFindWindowAtPoint not implemented" );
  882. return NULL;
  883. }