Files
wxWidgets/src/dfb/window.cpp

1131 lines
33 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: src/dfb/window.cpp
// Purpose: wxWindow
// Author: Vaclav Slavik
// (based on GTK, MSW, MGL implementations)
// Created: 2006-80-10
// RCS-ID: $Id$
// Copyright: (c) 2006 REA Elektronik GmbH
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ===========================================================================
// declarations
// ===========================================================================
// ---------------------------------------------------------------------------
// headers
// ---------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "wx/window.h"
#ifndef WX_PRECOMP
#include "wx/dcclient.h"
#endif
#include "wx/caret.h"
#include "wx/dynarray.h"
#include "wx/dfb/private.h"
#include "wx/private/overlay.h"
#define TRACE_EVENTS _T("events")
#define TRACE_PAINT _T("paint")
// ===========================================================================
// implementation
// ===========================================================================
// ---------------------------------------------------------------------------
// global variables
// ---------------------------------------------------------------------------
// the window that has keyboard focus:
static wxWindowDFB *gs_focusedWindow = NULL;
// the window that is about to be focused after currently focused
// one looses focus:
static wxWindow *gs_toBeFocusedWindow = NULL;
// the window that has mouse capture
static wxWindowDFB *gs_mouseCapture = NULL;
// ---------------------------------------------------------------------------
// overlays support
// ---------------------------------------------------------------------------
WX_DEFINE_ARRAY_PTR(wxOverlayImpl*, wxDfbOverlaysList);
// ---------------------------------------------------------------------------
// event tables
// ---------------------------------------------------------------------------
// in wxUniv this class is abstract because it doesn't have DoPopupMenu()
IMPLEMENT_ABSTRACT_CLASS(wxWindowDFB, wxWindowBase)
BEGIN_EVENT_TABLE(wxWindowDFB, wxWindowBase)
END_EVENT_TABLE()
// ----------------------------------------------------------------------------
// constructors and such
// ----------------------------------------------------------------------------
void wxWindowDFB::Init()
{
m_isShown = true;
m_frozenness = 0;
m_tlw = NULL;
m_overlays = NULL;
}
// Destructor
wxWindowDFB::~wxWindowDFB()
{
SendDestroyEvent();
m_isBeingDeleted = true;
if ( gs_mouseCapture == this )
ReleaseMouse();
#warning "FIXME: what to do with gs_activeFrame here and elsewhere?"
#if 0
if (gs_activeFrame == this)
{
gs_activeFrame = NULL;
// activate next frame in Z-order:
if ( m_wnd->prev )
{
wxWindowDFB *win = (wxWindowDFB*)m_wnd->prev->userData;
win->SetFocus();
}
else if ( m_wnd->next )
{
wxWindowDFB *win = (wxWindowDFB*)m_wnd->next->userData;
win->SetFocus();
}
}
#endif
if ( gs_focusedWindow == this )
DFBKillFocus();
DestroyChildren();
}
// real construction (Init() must have been called before!)
bool wxWindowDFB::Create(wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name)
{
if ( !m_tlw && parent )
m_tlw = parent->GetTLW();
if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
return false;
if ( parent )
parent->AddChild(this);
// set the size to something bogus initially, in case some code tries to
// create wxWindowDC before SetSize() is called below:
m_rect.width = m_rect.height = 1;
int x, y, w, h;
x = pos.x, y = pos.y;
if ( x == -1 ) x = 0;
if ( y == -1 ) y = 0;
w = WidthDefault(size.x);
h = HeightDefault(size.y);
SetSize(x, y, w, h);
return true;
}
// ---------------------------------------------------------------------------
// surface access
// ---------------------------------------------------------------------------
wxIDirectFBSurfacePtr wxWindowDFB::ObtainDfbSurface() const
{
wxCHECK_MSG( m_parent, NULL, _T("parentless window?") );
wxIDirectFBSurfacePtr parentSurface(m_parent->GetDfbSurface());
wxCHECK_MSG( parentSurface, NULL, _T("invalid parent surface") );
wxRect r(GetRect());
AdjustForParentClientOrigin(r.x, r.y, 0);
DFBRectangle rect = { r.x, r.y, r.width, r.height };
return parentSurface->GetSubSurface(&rect);
}
wxIDirectFBSurfacePtr wxWindowDFB::GetDfbSurface()
{
if ( !m_surface )
{
m_surface = ObtainDfbSurface();
wxASSERT_MSG( m_surface, _T("invalid DirectFB surface") );
}
return m_surface;
}
void wxWindowDFB::InvalidateDfbSurface()
{
m_surface = NULL;
// surfaces of the children are subsurfaces of this window's surface,
// so they must be invalidated as well:
wxWindowList& children = GetChildren();
for ( wxWindowList::iterator i = children.begin(); i != children.end(); ++i )
{
(*i)->InvalidateDfbSurface();
}
}
// ---------------------------------------------------------------------------
// basic operations
// ---------------------------------------------------------------------------
void wxWindowDFB::SetFocus()
{
if ( gs_focusedWindow == this )
return; // nothing to do, focused already
wxWindowDFB *oldFocusedWindow = gs_focusedWindow;
if ( gs_focusedWindow )
{
gs_toBeFocusedWindow = (wxWindow*)this;
gs_focusedWindow->DFBKillFocus();
gs_toBeFocusedWindow = NULL;
}
gs_focusedWindow = this;
if ( IsShownOnScreen() )
{
m_tlw->SetDfbFocus();
}
// else: do nothing, because DirectFB windows cannot have focus if they
// are hidden; when the TLW becomes visible, it will set the focus
// to use from wxTLW::Show()
#warning "FIXME: implement in terms of DWET_{GOT,LOST}FOCUS"
#warning "FIXME: keep this or not? not, think multiapp core"
#if 0
wxWindowDFB *active = wxGetTopLevelParent((wxWindow*)this);
if ( !(m_windowStyle & wxPOPUP_WINDOW) && active != gs_activeFrame )
{
if ( gs_activeFrame )
{
wxActivateEvent event(wxEVT_ACTIVATE, false, gs_activeFrame->GetId());
event.SetEventObject(gs_activeFrame);
gs_activeFrame->GetEventHandler()->ProcessEvent(event);
}
gs_activeFrame = active;
wxActivateEvent event(wxEVT_ACTIVATE, true, gs_activeFrame->GetId());
event.SetEventObject(gs_activeFrame);
gs_activeFrame->GetEventHandler()->ProcessEvent(event);
}
#endif
// notify the parent keeping track of focus for the kbd navigation
// purposes that we got it
wxChildFocusEvent eventFocus((wxWindow*)this);
GetEventHandler()->ProcessEvent(eventFocus);
wxFocusEvent event(wxEVT_SET_FOCUS, GetId());
event.SetEventObject(this);
event.SetWindow((wxWindow*)oldFocusedWindow);
GetEventHandler()->ProcessEvent(event);
#if wxUSE_CARET
// caret needs to be informed about focus change
wxCaret *caret = GetCaret();
if ( caret )
caret->OnSetFocus();
#endif // wxUSE_CARET
}
void wxWindowDFB::DFBKillFocus()
{
wxCHECK_RET( gs_focusedWindow == this,
_T("killing focus on window that doesn't have it") );
gs_focusedWindow = NULL;
if ( m_isBeingDeleted )
return; // don't send any events from dtor
#if wxUSE_CARET
// caret needs to be informed about focus change
wxCaret *caret = GetCaret();
if ( caret )
caret->OnKillFocus();
#endif // wxUSE_CARET
wxFocusEvent event(wxEVT_KILL_FOCUS, GetId());
event.SetEventObject(this);
event.SetWindow(gs_toBeFocusedWindow);
GetEventHandler()->ProcessEvent(event);
}
// ----------------------------------------------------------------------------
// this wxWindowBase function is implemented here (in platform-specific file)
// because it is static and so couldn't be made virtual
// ----------------------------------------------------------------------------
wxWindow *wxWindowBase::DoFindFocus()
{
return (wxWindow*)gs_focusedWindow;
}
bool wxWindowDFB::Show(bool show)
{
if ( !wxWindowBase::Show(show) )
return false;
// Unlike Refresh(), DoRefreshWindow() doesn't check visibility, so
// call it to force refresh of either this window (if showing) or its
// parent area at the place of this window (if hiding):
DoRefreshWindow();
#warning "FIXME: all of this must be implemented for DFB"
#if 0
DFB_wmShowWindow(m_wnd, show);
if (!show && gs_activeFrame == this)
{
// activate next frame in Z-order:
if ( m_wnd->prev )
{
wxWindowDFB *win = (wxWindowDFB*)m_wnd->prev->userData;
win->SetFocus();
}
else if ( m_wnd->next )
{
wxWindowDFB *win = (wxWindowDFB*)m_wnd->next->userData;
win->SetFocus();
}
else
{
gs_activeFrame = NULL;
}
}
#endif
return true;
}
// Raise the window to the top of the Z order
void wxWindowDFB::Raise()
{
wxFAIL_MSG( _T("Raise() not implemented") );
}
// Lower the window to the bottom of the Z order
void wxWindowDFB::Lower()
{
wxFAIL_MSG( _T("Lower() not implemented") );
}
void wxWindowDFB::DoCaptureMouse()
{
#warning "implement this"
#if 0
if ( gs_mouseCapture )
DFB_wmUncaptureEvents(gs_mouseCapture->m_wnd, wxDFB_CAPTURE_MOUSE);
#endif
gs_mouseCapture = this;
#if 0
DFB_wmCaptureEvents(m_wnd, EVT_MOUSEEVT, wxDFB_CAPTURE_MOUSE);
#endif
}
void wxWindowDFB::DoReleaseMouse()
{
wxASSERT_MSG( gs_mouseCapture == this, wxT("attempt to release mouse, but this window hasn't captured it") );
#warning "implement this"
#if 0
DFB_wmUncaptureEvents(m_wnd, wxDFB_CAPTURE_MOUSE);
#endif
gs_mouseCapture = NULL;
}
/* static */ wxWindow *wxWindowBase::GetCapture()
{
return (wxWindow*)gs_mouseCapture;
}
bool wxWindowDFB::SetCursor(const wxCursor& cursor)
{
if ( !wxWindowBase::SetCursor(cursor) )
{
// no change
return false;
}
#warning "implement this"
#if 0
if ( m_cursor.Ok() )
DFB_wmSetWindowCursor(m_wnd, *m_cursor.GetDFBCursor());
else
DFB_wmSetWindowCursor(m_wnd, *wxSTANDARD_CURSOR->GetDFBCursor());
#endif
return true;
}
void wxWindowDFB::WarpPointer(int x, int y)
{
int w, h;
wxDisplaySize(&w, &h);
ClientToScreen(&x, &y);
if ( x < 0 ) x = 0;
if ( y < 0 ) y = 0;
if ( x >= w ) x = w-1;
if ( y >= h ) y = h-1;
wxIDirectFBDisplayLayerPtr layer(wxIDirectFB::Get()->GetDisplayLayer());
wxCHECK_RET( layer, _T("no display layer") );
layer->WarpCursor(x, y);
}
// Set this window to be the child of 'parent'.
bool wxWindowDFB::Reparent(wxWindowBase *parent)
{
if ( !wxWindowBase::Reparent(parent) )
return false;
#warning "implement this"
wxFAIL_MSG( _T("reparenting not yet implemented") );
return true;
}
// ---------------------------------------------------------------------------
// moving and resizing
// ---------------------------------------------------------------------------
// Get total size
void wxWindowDFB::DoGetSize(int *x, int *y) const
{
if (x) *x = m_rect.width;
if (y) *y = m_rect.height;
}
void wxWindowDFB::DoGetPosition(int *x, int *y) const
{
if (x) *x = m_rect.x;
if (y) *y = m_rect.y;
}
static wxPoint GetScreenPosOfClientOrigin(const wxWindowDFB *win)
{
wxCHECK_MSG( win, wxPoint(0, 0), _T("no window provided") );
wxPoint pt(win->GetPosition() + win->GetClientAreaOrigin());
if ( !win->IsTopLevel() )
pt += GetScreenPosOfClientOrigin(win->GetParent());
return pt;
}
void wxWindowDFB::DoScreenToClient(int *x, int *y) const
{
wxPoint o = GetScreenPosOfClientOrigin(this);
if (x) *x -= o.x;
if (y) *y -= o.y;
}
void wxWindowDFB::DoClientToScreen(int *x, int *y) const
{
wxPoint o = GetScreenPosOfClientOrigin(this);
if (x) *x += o.x;
if (y) *y += o.y;
}
// Get size *available for subwindows* i.e. excluding menu bar etc.
void wxWindowDFB::DoGetClientSize(int *x, int *y) const
{
DoGetSize(x, y);
}
void wxWindowDFB::DoMoveWindow(int x, int y, int width, int height)
{
// NB: [x,y] arguments are in (parent's) window coordinates, while
// m_rect.{x,y} are in (parent's) client coordinates. That's why we
// offset by parentOrigin in some places below
wxPoint parentOrigin(0, 0);
AdjustForParentClientOrigin(parentOrigin.x, parentOrigin.y);
wxRect oldpos(m_rect);
oldpos.Offset(parentOrigin);
wxRect newpos(x, y, width, height);
// input [x,y] is in window coords, but we store client coords in m_rect:
m_rect = newpos;
m_rect.Offset(-parentOrigin);
// window's position+size changed and so did the subsurface that covers it
InvalidateDfbSurface();
if ( IsShown() )
{
// queue both former and new position of the window for repainting:
wxWindow *parent = GetParent();
parent->RefreshRect(oldpos);
parent->RefreshRect(newpos);
}
}
// set the size of the window: if the dimensions are positive, just use them,
// but if any of them is equal to -1, it means that we must find the value for
// it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
// which case -1 is a valid value for x and y)
//
// If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
// the width/height to best suit our contents, otherwise we reuse the current
// width/height
void wxWindowDFB::DoSetSize(int x, int y, int width, int height, int sizeFlags)
{
// get the current size and position...
int currentX, currentY;
GetPosition(&currentX, &currentY);
int currentW,currentH;
GetSize(&currentW, &currentH);
if ( x == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
x = currentX;
if ( y == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
y = currentY;
// ... and don't do anything (avoiding flicker) if it's already ok
if ( x == currentX && y == currentY &&
width == currentW && height == currentH )
{
return;
}
wxSize size(-1, -1);
if ( width == -1 )
{
if ( sizeFlags & wxSIZE_AUTO_WIDTH )
{
size = DoGetBestSize();
width = size.x;
}
else
{
// just take the current one
width = currentW;
}
}
if ( height == -1 )
{
if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
{
if ( size.x == -1 )
{
size = DoGetBestSize();
}
//else: already called DoGetBestSize() above
height = size.y;
}
else
{
// just take the current one
height = currentH;
}
}
int maxWidth = GetMaxWidth(),
minWidth = GetMinWidth(),
maxHeight = GetMaxHeight(),
minHeight = GetMinHeight();
if ( minWidth != -1 && width < minWidth ) width = minWidth;
if ( maxWidth != -1 && width > maxWidth ) width = maxWidth;
if ( minHeight != -1 && height < minHeight ) height = minHeight;
if ( maxHeight != -1 && height > maxHeight ) height = maxHeight;
if ( m_rect.x != x || m_rect.y != y ||
m_rect.width != width || m_rect.height != height )
{
AdjustForParentClientOrigin(x, y, sizeFlags);
DoMoveWindow(x, y, width, height);
wxSize newSize(width, height);
wxSizeEvent event(newSize, GetId());
event.SetEventObject(this);
GetEventHandler()->ProcessEvent(event);
}
}
void wxWindowDFB::DoSetClientSize(int width, int height)
{
SetSize(width, height);
}
// ---------------------------------------------------------------------------
// text metrics
// ---------------------------------------------------------------------------
int wxWindowDFB::GetCharHeight() const
{
wxWindowDC dc((wxWindow*)this);
return dc.GetCharHeight();
}
int wxWindowDFB::GetCharWidth() const
{
wxWindowDC dc((wxWindow*)this);
return dc.GetCharWidth();
}
void wxWindowDFB::GetTextExtent(const wxString& string,
int *x, int *y,
int *descent, int *externalLeading,
const wxFont *theFont) const
{
wxWindowDC dc((wxWindow*)this);
dc.GetTextExtent(string, x, y, descent, externalLeading, (wxFont*)theFont);
}
// ---------------------------------------------------------------------------
// painting
// ---------------------------------------------------------------------------
void wxWindowDFB::Clear()
{
wxClientDC dc((wxWindow *)this);
wxBrush brush(GetBackgroundColour(), wxSOLID);
dc.SetBackground(brush);
dc.Clear();
}
void wxWindowDFB::Refresh(bool WXUNUSED(eraseBack), const wxRect *rect)
{
if ( !IsShown() || IsFrozen() )
return;
// NB[1]: We intentionally ignore the eraseBack argument here. This is
// because of the way wxDFB's painting is implemented: the refresh
// request is propagated up to wxTLW, which is then painted in
// top-down order. This means that this window's area is first
// painted by its parent and this window is then painted over it, so
// it's not safe to not paint this window's background even if
// eraseBack=false.
// NB[2]: wxWindow::Refresh() takes the rectangle in client coords, but
// wxUniv translates it to window coords before passing it to
// wxWindowDFB::Refresh(), so we can directly pass the rect to
// DoRefreshRect (which takes window, not client, coords) here.
if ( rect )
DoRefreshRect(*rect);
else
DoRefreshWindow();
}
void wxWindowDFB::RefreshWindowRect(const wxRect& rect)
{
if ( !IsShown() || IsFrozen() )
return;
DoRefreshRect(rect);
}
void wxWindowDFB::DoRefreshWindow()
{
// NB: DoRefreshRect() takes window coords, not client, so this is correct
DoRefreshRect(wxRect(GetSize()));
}
void wxWindowDFB::DoRefreshRect(const wxRect& rect)
{
wxWindow *parent = GetParent();
wxCHECK_RET( parent, _T("no parent") );
// don't overlap outside of the window (NB: 'rect' is in window coords):
wxRect r(rect);
r.Intersect(wxRect(GetSize()));
if ( r.IsEmpty() )
return;
wxLogTrace(TRACE_PAINT,
_T("%p ('%s'): refresh rect [%i,%i,%i,%i]"),
this, GetName().c_str(),
rect.x, rect.y, rect.GetRight(), rect.GetBottom());
// convert the refresh rectangle to parent's coordinates and
// recursively refresh the parent:
r.Offset(GetPosition());
r.Offset(parent->GetClientAreaOrigin());
parent->DoRefreshRect(r);
}
void wxWindowDFB::Update()
{
if ( !IsShown() || IsFrozen() )
return;
GetParent()->Update();
}
void wxWindowDFB::Freeze()
{
m_frozenness++;
}
void wxWindowDFB::Thaw()
{
wxASSERT_MSG( IsFrozen(), _T("Thaw() without matching Freeze()") );
if ( --m_frozenness == 0 )
{
if ( IsShown() )
DoRefreshWindow();
}
}
void wxWindowDFB::PaintWindow(const wxRect& rect)
{
wxCHECK_RET( !IsFrozen() && IsShown(), _T("shouldn't be called") );
wxLogTrace(TRACE_PAINT,
_T("%p ('%s'): painting region [%i,%i,%i,%i]"),
this, GetName().c_str(),
rect.x, rect.y, rect.GetRight(), rect.GetBottom());
m_updateRegion = rect;
// FIXME_DFB: don't waste time rendering the area if it's fully covered
// by some children, go directly to rendering the children
// NB: unconditionally send wxEraseEvent, because our implementation of
// wxWindow::Refresh() ignores the eraseBack argument
wxWindowDC dc((wxWindow*)this);
wxEraseEvent eventEr(m_windowId, &dc);
eventEr.SetEventObject(this);
GetEventHandler()->ProcessEvent(eventEr);
wxRect clientRect(GetClientRect());
// only send wxNcPaintEvent if drawing at least part of nonclient area:
if ( !clientRect.Contains(rect) )
{
wxNcPaintEvent eventNc(GetId());
eventNc.SetEventObject(this);
GetEventHandler()->ProcessEvent(eventNc);
}
else
{
wxLogTrace(TRACE_PAINT, _T("%p ('%s'): not sending wxNcPaintEvent"),
this, GetName().c_str());
}
// only send wxPaintEvent if drawing at least part of client area:
if ( rect.Intersects(clientRect) )
{
wxPaintEvent eventPt(GetId());
eventPt.SetEventObject(this);
GetEventHandler()->ProcessEvent(eventPt);
}
else
{
wxLogTrace(TRACE_PAINT, _T("%p ('%s'): not sending wxPaintEvent"),
this, GetName().c_str());
}
// draw window's overlays on top of the painted window, if we have any:
PaintOverlays(rect);
m_updateRegion.Clear();
// paint the children:
wxPoint origin = GetClientAreaOrigin();
wxWindowList& children = GetChildren();
for ( wxWindowList::iterator i = children.begin();
i != children.end(); ++i )
{
wxWindow *child = *i;
if ( child->IsFrozen() || !child->IsShown() )
continue; // don't paint anything if the window is frozen or hidden
// compute child's area to repaint
wxRect childrect(child->GetRect());
childrect.Offset(origin);
childrect.Intersect(rect);
if ( childrect.IsEmpty() )
continue;
// and repaint it:
childrect.Offset(-child->GetPosition());
childrect.Offset(-origin);
child->PaintWindow(childrect);
}
}
void wxWindowDFB::PaintOverlays(const wxRect& rect)
{
if ( !m_overlays )
return;
for ( wxDfbOverlaysList::const_iterator i = m_overlays->begin();
i != m_overlays->end(); ++i )
{
wxOverlayImpl *overlay = *i;
wxRect orectOrig(overlay->GetRect());
wxRect orect(orectOrig);
orect.Intersect(rect);
if ( orect.IsEmpty() )
continue;
if ( overlay->IsEmpty() )
continue; // nothing to paint
DFBRectangle dfbRect = { orect.x - orectOrig.x, orect.y - orectOrig.y,
orect.width, orect.height };
GetDfbSurface()->Blit
(
overlay->GetDirectFBSurface(),
&dfbRect,
orect.x, orect.y
);
}
}
void wxWindowDFB::AddOverlay(wxOverlayImpl *overlay)
{
if ( !m_overlays )
m_overlays = new wxDfbOverlaysList;
m_overlays->Add(overlay);
}
void wxWindowDFB::RemoveOverlay(wxOverlayImpl *overlay)
{
wxCHECK_RET( m_overlays, _T("no overlays to remove") );
m_overlays->Remove(overlay);
if ( m_overlays->empty() )
{
wxDELETE(m_overlays);
}
if ( !m_isBeingDeleted )
RefreshWindowRect(overlay->GetRect());
}
// ---------------------------------------------------------------------------
// events handling
// ---------------------------------------------------------------------------
#define KEY(dfb, wx) \
case dfb: \
wxLogTrace(TRACE_EVENTS, \
_T("key " #dfb " mapped to " #wx)); \
return wx
// returns translated keycode, i.e. the one for KEYUP/KEYDOWN where 'a'..'z' is
// translated to 'A'..'Z'
static long GetTranslatedKeyCode(DFBInputDeviceKeyIdentifier key_id)
{
switch ( key_id )
{
KEY(DIKI_UNKNOWN, 0);
KEY(DIKI_A, 'A');
KEY(DIKI_B, 'B');
KEY(DIKI_C, 'C');
KEY(DIKI_D, 'D');
KEY(DIKI_E, 'E');
KEY(DIKI_F, 'F');
KEY(DIKI_G, 'G');
KEY(DIKI_H, 'H');
KEY(DIKI_I, 'I');
KEY(DIKI_J, 'J');
KEY(DIKI_K, 'K');
KEY(DIKI_L, 'L');
KEY(DIKI_M, 'M');
KEY(DIKI_N, 'N');
KEY(DIKI_O, 'O');
KEY(DIKI_P, 'P');
KEY(DIKI_Q, 'Q');
KEY(DIKI_R, 'R');
KEY(DIKI_S, 'S');
KEY(DIKI_T, 'T');
KEY(DIKI_U, 'U');
KEY(DIKI_V, 'V');
KEY(DIKI_W, 'W');
KEY(DIKI_X, 'X');
KEY(DIKI_Y, 'Y');
KEY(DIKI_Z, 'Z');
KEY(DIKI_0, '0');
KEY(DIKI_1, '1');
KEY(DIKI_2, '2');
KEY(DIKI_3, '3');
KEY(DIKI_4, '4');
KEY(DIKI_5, '5');
KEY(DIKI_6, '6');
KEY(DIKI_7, '7');
KEY(DIKI_8, '8');
KEY(DIKI_9, '9');
KEY(DIKI_F1, WXK_F1);
KEY(DIKI_F2, WXK_F2);
KEY(DIKI_F3, WXK_F3);
KEY(DIKI_F4, WXK_F4);
KEY(DIKI_F5, WXK_F5);
KEY(DIKI_F6, WXK_F6);
KEY(DIKI_F7, WXK_F7);
KEY(DIKI_F8, WXK_F8);
KEY(DIKI_F9, WXK_F9);
KEY(DIKI_F10, WXK_F10);
KEY(DIKI_F11, WXK_F11);
KEY(DIKI_F12, WXK_F12);
KEY(DIKI_SHIFT_L, WXK_SHIFT);
KEY(DIKI_SHIFT_R, WXK_SHIFT);
KEY(DIKI_CONTROL_L, WXK_CONTROL);
KEY(DIKI_CONTROL_R, WXK_CONTROL);
KEY(DIKI_ALT_L, WXK_ALT);
KEY(DIKI_ALT_R, WXK_ALT);
// this key was removed in 0.9.25 but include it for previous versions
// just to avoid gcc warnings about unhandled enum value in switch
#if !wxCHECK_DFB_VERSION(0, 9, 24)
KEY(DIKI_ALTGR, 0);
#endif
KEY(DIKI_META_L, 0);
KEY(DIKI_META_R, 0);
KEY(DIKI_SUPER_L, 0);
KEY(DIKI_SUPER_R, 0);
KEY(DIKI_HYPER_L, 0);
KEY(DIKI_HYPER_R, 0);
KEY(DIKI_CAPS_LOCK, 0);
KEY(DIKI_NUM_LOCK, WXK_NUMLOCK);
KEY(DIKI_SCROLL_LOCK, 0);
KEY(DIKI_ESCAPE, WXK_ESCAPE);
KEY(DIKI_LEFT, WXK_LEFT);
KEY(DIKI_RIGHT, WXK_RIGHT);
KEY(DIKI_UP, WXK_UP);
KEY(DIKI_DOWN, WXK_DOWN);
KEY(DIKI_TAB, WXK_TAB);
KEY(DIKI_ENTER, WXK_RETURN);
KEY(DIKI_SPACE, WXK_SPACE);
KEY(DIKI_BACKSPACE, WXK_BACK);
KEY(DIKI_INSERT, WXK_INSERT);
KEY(DIKI_DELETE, WXK_DELETE);
KEY(DIKI_HOME, WXK_HOME);
KEY(DIKI_END, WXK_END);
KEY(DIKI_PAGE_UP, WXK_PAGEUP);
KEY(DIKI_PAGE_DOWN, WXK_PAGEDOWN);
KEY(DIKI_PRINT, WXK_PRINT);
KEY(DIKI_PAUSE, WXK_PAUSE);
KEY(DIKI_QUOTE_LEFT, '`');
KEY(DIKI_MINUS_SIGN, '-');
KEY(DIKI_EQUALS_SIGN, '=');
KEY(DIKI_BRACKET_LEFT, '[');
KEY(DIKI_BRACKET_RIGHT, ']');
KEY(DIKI_BACKSLASH, '\\');
KEY(DIKI_SEMICOLON, ';');
KEY(DIKI_QUOTE_RIGHT, '\'');
KEY(DIKI_COMMA, ',');
KEY(DIKI_PERIOD, '.');
KEY(DIKI_SLASH, '/');
KEY(DIKI_LESS_SIGN, '<');
KEY(DIKI_KP_DIV, WXK_NUMPAD_DIVIDE);
KEY(DIKI_KP_MULT, WXK_NUMPAD_MULTIPLY);
KEY(DIKI_KP_MINUS, WXK_NUMPAD_SUBTRACT);
KEY(DIKI_KP_PLUS, WXK_NUMPAD_ADD);
KEY(DIKI_KP_ENTER, WXK_NUMPAD_ENTER);
KEY(DIKI_KP_SPACE, WXK_NUMPAD_SPACE);
KEY(DIKI_KP_TAB, WXK_NUMPAD_TAB);
KEY(DIKI_KP_F1, WXK_NUMPAD_F1);
KEY(DIKI_KP_F2, WXK_NUMPAD_F2);
KEY(DIKI_KP_F3, WXK_NUMPAD_F3);
KEY(DIKI_KP_F4, WXK_NUMPAD_F4);
KEY(DIKI_KP_EQUAL, WXK_NUMPAD_EQUAL);
KEY(DIKI_KP_SEPARATOR, WXK_NUMPAD_SEPARATOR);
KEY(DIKI_KP_DECIMAL, WXK_NUMPAD_DECIMAL);
KEY(DIKI_KP_0, WXK_NUMPAD0);
KEY(DIKI_KP_1, WXK_NUMPAD1);
KEY(DIKI_KP_2, WXK_NUMPAD2);
KEY(DIKI_KP_3, WXK_NUMPAD3);
KEY(DIKI_KP_4, WXK_NUMPAD4);
KEY(DIKI_KP_5, WXK_NUMPAD5);
KEY(DIKI_KP_6, WXK_NUMPAD6);
KEY(DIKI_KP_7, WXK_NUMPAD7);
KEY(DIKI_KP_8, WXK_NUMPAD8);
KEY(DIKI_KP_9, WXK_NUMPAD9);
case DIKI_KEYDEF_END:
case DIKI_NUMBER_OF_KEYS:
wxFAIL_MSG( _T("invalid key_id value") );
return 0;
}
return 0; // silence compiler warnings
}
// returns untranslated keycode, i.e. for EVT_CHAR, where characters are left in
// the form they were entered (lowercase, diacritics etc.)
static long GetUntraslatedKeyCode(DFBInputDeviceKeyIdentifier key_id,
DFBInputDeviceKeySymbol key_symbol)
{
switch ( DFB_KEY_TYPE(key_symbol) )
{
case DIKT_UNICODE:
#if wxUSE_UNICODE
return key_symbol;
#else
if ( key_symbol < 128 )
return key_symbol;
else
{
#if wxUSE_WCHAR_T
wchar_t chr = key_symbol;
wxCharBuffer buf(wxConvUI->cWC2MB(&chr, 1, NULL));
if ( buf )
return *buf; // may be 0 if failed
else
#endif // wxUSE_WCHAR_T
return 0;
}
#endif
default:
return GetTranslatedKeyCode(key_id);
}
}
#undef KEY
void wxWindowDFB::HandleKeyEvent(const wxDFBWindowEvent& event_)
{
if ( !IsEnabled() )
return;
const DFBWindowEvent& e = event_;
wxLogTrace(TRACE_EVENTS,
_T("handling key %s event for window %p ('%s')"),
e.type == DWET_KEYUP ? _T("up") : _T("down"),
this, GetName().c_str());
// fill in wxKeyEvent fields:
wxKeyEvent event;
event.SetEventObject(this);
event.SetTimestamp(wxDFB_EVENT_TIMESTAMP(e));
event.m_rawCode = e.key_code;
event.m_keyCode = GetTranslatedKeyCode(e.key_id);
event.m_scanCode = 0; // not used by wx at all
#if wxUSE_UNICODE
event.m_uniChar = e.key_symbol;
#endif
event.m_shiftDown = ( e.modifiers & DIMM_SHIFT ) != 0;
event.m_controlDown = ( e.modifiers & DIMM_CONTROL ) != 0;
event.m_altDown = ( e.modifiers & DIMM_ALT ) != 0;
event.m_metaDown = ( e.modifiers & DIMM_META ) != 0;
// translate coordinates from TLW-relative to this window-relative:
event.m_x = e.x;
event.m_y = e.y;
GetTLW()->ClientToScreen(&event.m_x, &event.m_y);
this->ScreenToClient(&event.m_x, &event.m_y);
if ( e.type == DWET_KEYUP )
{
event.SetEventType(wxEVT_KEY_UP);
GetEventHandler()->ProcessEvent(event);
}
else
{
bool isTab = (event.m_keyCode == WXK_TAB);
event.SetEventType(wxEVT_KEY_DOWN);
if ( GetEventHandler()->ProcessEvent(event) )
return;
// only send wxEVT_CHAR event if not processed yet:
event.m_keyCode = GetUntraslatedKeyCode(e.key_id, e.key_symbol);
if ( event.m_keyCode != 0 )
{
event.SetEventType(wxEVT_CHAR);
if ( GetEventHandler()->ProcessEvent(event) )
return;
}
// Synthetize navigation key event, but do it only if the TAB key
// wasn't handled yet:
if ( isTab && GetParent() && GetParent()->HasFlag(wxTAB_TRAVERSAL) )
{
wxNavigationKeyEvent navEvent;
navEvent.SetEventObject(GetParent());
// Shift-TAB goes in reverse direction:
navEvent.SetDirection(!event.m_shiftDown);
// Ctrl-TAB changes the (parent) window, i.e. switch notebook page:
navEvent.SetWindowChange(event.m_controlDown);
navEvent.SetCurrentFocus(wxStaticCast(this, wxWindow));
GetParent()->GetEventHandler()->ProcessEvent(navEvent);
}
}
}
// ---------------------------------------------------------------------------
// idle events processing
// ---------------------------------------------------------------------------
void wxWindowDFB::OnInternalIdle()
{
if (wxUpdateUIEvent::CanUpdate(this))
UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
}
// Find the wxWindow at the current mouse position, returning the mouse
// position.
wxWindow* wxFindWindowAtPointer(wxPoint& pt)
{
return wxFindWindowAtPoint(pt = wxGetMousePosition());
}
wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
{
wxFAIL_MSG( _T("wxFindWindowAtPoint not implemented") );
return NULL;
}