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