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