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