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