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