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