X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6954a1e2c983321297c11050d380485a8f3c724d..387c7b3eefde23a62e20465000dd96d58fc63bcd:/src/dfb/nonownedwnd.cpp diff --git a/src/dfb/nonownedwnd.cpp b/src/dfb/nonownedwnd.cpp index 35e8d3fd74..3652a13ba4 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) @@ -243,7 +243,18 @@ bool wxNonOwnedWindow::Show(bool show) m_dfbwin->SetOpacity(show ? m_opacity : 0); if ( show ) - SetDfbFocus(); + { + wxWindow *focused = FindFocus(); + if ( focused && focused->GetTLW() == this ) + { + // focus is on this frame or its children, apply it to DirectFB + SetDfbFocus(); + } + // 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; } @@ -296,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()); @@ -335,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, @@ -351,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()); @@ -368,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(); } @@ -385,7 +450,7 @@ 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; } @@ -400,12 +465,12 @@ void wxNonOwnedWindow::HandleDFBWindowEvent(const wxDFBWindowEvent& event_) if ( !recipient ) { wxLogTrace(TRACE_EVENTS, - _T("ignoring event: no recipient window")); + "ignoring event: no recipient window"); return; } wxCHECK_RET( recipient && recipient->GetTLW() == tlw, - _T("event recipient not in TLW which received the event") ); + "event recipient not in TLW which received the event" ); recipient->HandleKeyEvent(event_); break; @@ -413,12 +478,15 @@ void wxNonOwnedWindow::HandleDFBWindowEvent(const wxDFBWindowEvent& event_) case DWET_GOTFOCUS: case DWET_LOSTFOCUS: - tlw->HandleFocusEvent(event_); + { + 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: