X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/42b0d8b96d2b4246ccfbe985639ee40f94225b5b..0bbe61b8c18a1795189f0cf73cc61c14a0fb846d:/src/dfb/nonownedwnd.cpp diff --git a/src/dfb/nonownedwnd.cpp b/src/dfb/nonownedwnd.cpp index 4fe1ac999d..33f2777360 100644 --- a/src/dfb/nonownedwnd.cpp +++ b/src/dfb/nonownedwnd.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // Name: src/dfb/nonownedwnd.cpp -// Purpose: implementation of wxNonOwnedWindowow +// Purpose: implementation of wxNonOwnedWindow // Author: Vaclav Slavik // Created: 2006-12-24 // RCS-ID: $Id$ @@ -21,8 +21,8 @@ #include "wx/evtloop.h" #include "wx/dfb/private.h" -#define TRACE_EVENTS _T("events") -#define TRACE_PAINT _T("paint") +#define TRACE_EVENTS "events" +#define TRACE_PAINT "paint" // ============================================================================ // globals @@ -101,14 +101,14 @@ bool wxNonOwnedWindow::Create(wxWindow *parent, long style, const wxString &name) { - wxCHECK_MSG( pos.x >= 0 && pos.y >= 0, false, _T("invalid position") ); - wxCHECK_MSG( size.x > 0 && size.y > 0, false, _T("invalid size") ); + wxCHECK_MSG( pos.x >= 0 && pos.y >= 0, false, "invalid position" ); + wxCHECK_MSG( size.x > 0 && size.y > 0, false, "invalid size" ); m_tlw = this; // create DirectFB window: wxIDirectFBDisplayLayerPtr layer(wxIDirectFB::Get()->GetDisplayLayer()); - wxCHECK_MSG( layer, false, _T("no display layer") ); + wxCHECK_MSG( layer, false, "no display layer" ); DFBWindowDescription desc; desc.flags = (DFBWindowDescriptionFlags) @@ -228,7 +228,7 @@ bool wxNonOwnedWindow::Show(bool show) m_sizeSet = true; wxSizeEvent event(GetSize(), GetId()); event.SetEventObject(this); - GetEventHandler()->ProcessEvent(event); + HandleWindowEvent(event); } // make sure the window is fully painted, with all pending updates, before @@ -244,18 +244,16 @@ bool wxNonOwnedWindow::Show(bool show) if ( show ) { - wxWindow *focused = wxWindow::FindFocus(); + wxWindow *focused = FindFocus(); if ( focused && focused->GetTLW() == this ) { + // focus is on this frame or its children, apply it to DirectFB SetDfbFocus(); } - else if ( AcceptsFocus() ) - { - // FIXME: we should probably always call SetDfbFocus instead - // and call SetFocus() from wxActivateEvent/DWET_GOTFOCUS - // handler - SetFocus(); - } + // else: don't do anything, if this is wxFrame or wxDialog that should + // get focus when it's shown, + // wxTopLevelWindowDFB::HandleFocusEvent() will do it as soon as + // the event loop starts } return true; @@ -309,7 +307,7 @@ void wxNonOwnedWindow::HandleQueuedPaintRequests() continue; // nothing to refresh wxLogTrace(TRACE_PAINT, - _T("%p ('%s'): processing paint request [%i,%i,%i,%i]"), + "%p ('%s'): processing paint request [%i,%i,%i,%i]", this, GetName().c_str(), clipped.x, clipped.y, clipped.GetRight(), clipped.GetBottom()); @@ -348,7 +346,7 @@ void wxNonOwnedWindow::HandleQueuedPaintRequests() GetDfbSurface()->FlipToFront(rptr); wxLogTrace(TRACE_PAINT, - _T("%p ('%s'): processed %i paint requests, flipped surface: [%i,%i,%i,%i]"), + "%p ('%s'): processed %i paint requests, flipped surface: [%i,%i,%i,%i]", this, GetName().c_str(), requestsCount, paintedRect.x, paintedRect.y, @@ -364,7 +362,7 @@ void wxNonOwnedWindow::DoRefreshRect(const wxRect& rect) return; wxLogTrace(TRACE_PAINT, - _T("%p ('%s'): [TLW] refresh rect [%i,%i,%i,%i]"), + "%p ('%s'): [TLW] refresh rect [%i,%i,%i,%i]", this, GetName().c_str(), rect.x, rect.y, rect.GetRight(), rect.GetBottom()); @@ -381,11 +379,65 @@ void wxNonOwnedWindow::Update() // events handling // --------------------------------------------------------------------------- +namespace +{ + +static wxNonOwnedWindow *gs_insideDFBFocusHandlerOf = NULL; + +struct InsideDFBFocusHandlerSetter +{ + InsideDFBFocusHandlerSetter(wxNonOwnedWindow *win) + { + wxASSERT( gs_insideDFBFocusHandlerOf == NULL ); + gs_insideDFBFocusHandlerOf = win; + } + ~InsideDFBFocusHandlerSetter() + { + gs_insideDFBFocusHandlerOf = NULL; + } +}; + +} // anonymous namespace + + void wxNonOwnedWindow::SetDfbFocus() { - wxCHECK_RET( IsShown(), _T("cannot set focus to hidden window") ); + wxCHECK_RET( IsShown(), "cannot set focus to hidden window" ); wxASSERT_MSG( FindFocus() && FindFocus()->GetTLW() == this, - _T("setting DirectFB focus to unexpected window") ); + "setting DirectFB focus to unexpected window" ); + + // Don't set DirectFB focus if we're called from HandleFocusEvent() on + // this window, because we already have the focus in that case. Not only + // would it be unnecessary, it would be harmful: RequestFocus() adds + // an event to DirectFB event queue and calling it when in + // HandleFocusEvent() could result in a window being focused when it + // should not be. Consider this example: + // + // tlw1->SetFocus(); // (1) + // tlw2->SetFocus(); // (2) + // + // This results in adding these events to DFB queue: + // + // DWET_GOTFOCUS(tlw1) + // DWET_LOSTFOCUS(tlw1) + // DWET_GOTFOCUS(tlw2) + // + // Note that the events are processed by event loop, i.e. not between + // execution of lines (1) and (2) above. So by the time the first + // DWET_GOTFOCUS event is handled, tlw2->SetFocus() was already executed. + // If we onconditionally called RequestFocus() from here, handling the + // first event would result in this change to the event queue: + // + // DWET_LOSTFOCUS(tlw1) + // DWET_GOTFOCUS(tlw2) // (3) + // DWET_LOSTFOCUS(tlw2) + // DWET_GOTFOCUS(tlw1) + // + // And the focus would get back to tlw1 even though that's not what we + // wanted. + + if ( gs_insideDFBFocusHandlerOf == this ) + return; GetDirectFBWindow()->RequestFocus(); } @@ -398,47 +450,49 @@ void wxNonOwnedWindow::HandleDFBWindowEvent(const wxDFBWindowEvent& event_) if ( gs_dfbWindowsMap.find(event.window_id) == gs_dfbWindowsMap.end() ) { wxLogTrace(TRACE_EVENTS, - _T("received event for unknown DirectFB window, ignoring")); + "received event for unknown DirectFB window, ignoring"); return; } wxNonOwnedWindow *tlw = gs_dfbWindowsMap[event.window_id]; - wxWindow *recipient = NULL; - void (wxWindow::*handlerFunc)(const wxDFBWindowEvent&) = NULL; switch ( event.type ) { case DWET_KEYDOWN: case DWET_KEYUP: { - recipient = wxWindow::FindFocus(); - handlerFunc = &wxWindowDFB::HandleKeyEvent; + wxWindow *recipient = wxWindow::FindFocus(); + if ( !recipient ) + { + wxLogTrace(TRACE_EVENTS, + "ignoring event: no recipient window"); + return; + } + + wxCHECK_RET( recipient && recipient->GetTLW() == tlw, + "event recipient not in TLW which received the event" ); + + recipient->HandleKeyEvent(event_); break; } + case DWET_GOTFOCUS: + case DWET_LOSTFOCUS: + { + InsideDFBFocusHandlerSetter inside(tlw); + tlw->HandleFocusEvent(event_); + } + break; + case DWET_NONE: case DWET_ALL: - { - wxFAIL_MSG( _T("invalid event type") ); + wxFAIL_MSG( "invalid event type" ); break; - } default: // we're not interested in them here break; } - - if ( !recipient ) - { - wxLogTrace(TRACE_EVENTS, _T("ignoring event: no recipient window")); - return; - } - - wxCHECK_RET( recipient && recipient->GetTLW() == tlw, - _T("event recipient not in TLW which received the event") ); - - // process the event: - (recipient->*handlerFunc)(event_); } // ---------------------------------------------------------------------------