From 0e2219690946c6fe7953504ce9c77cde1963afeb Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Sun, 28 Oct 2012 00:24:02 -0400 Subject: [PATCH] Backout b6089a8b78d3 (bug 782547) to see if it fixes Flash hangs. --- dom/base/nsGlobalWindow.h | 2 + widget/windows/nsFilePicker.cpp | 23 +++++++++ widget/windows/nsWindow.cpp | 88 ++++++++++++++++++++------------- widget/windows/nsWindow.h | 5 +- 4 files changed, 81 insertions(+), 37 deletions(-) diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 1507ff1a5d2a..0520c13f6698 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -829,6 +829,8 @@ protected: bool CanMoveResizeWindows(); + bool GetBlurSuppression(); + // If aDoFlush is true, we'll flush our own layout; otherwise we'll try to // just flush our parent and only flush ourselves if we think we need to. nsresult GetScrollXY(int32_t* aScrollX, int32_t* aScrollY, diff --git a/widget/windows/nsFilePicker.cpp b/widget/windows/nsFilePicker.cpp index ac4e41badc4e..c110a8f6dabd 100644 --- a/widget/windows/nsFilePicker.cpp +++ b/widget/windows/nsFilePicker.cpp @@ -44,6 +44,27 @@ typedef DWORD FILEOPENDIALOGOPTIONS; /////////////////////////////////////////////////////////////////////////////// // Helper classes +// Manages matching SuppressBlurEvents calls on the parent widget. +class AutoSuppressEvents +{ +public: + explicit AutoSuppressEvents(nsIWidget* aWidget) : + mWindow(static_cast(aWidget)) { + SuppressWidgetEvents(true); + } + + ~AutoSuppressEvents() { + SuppressWidgetEvents(false); + } +private: + void SuppressWidgetEvents(bool aFlag) { + if (mWindow) { + mWindow->SuppressBlurEvents(aFlag); + } + } + nsRefPtr mWindow; +}; + // Manages the current working path. class AutoRestoreWorkingPath { @@ -1006,6 +1027,8 @@ nsFilePicker::ShowW(int16_t *aReturnVal) *aReturnVal = returnCancel; + AutoSuppressEvents supress(mParentWidget); + nsAutoString initialDir; if (mDisplayDirectory) mDisplayDirectory->GetPath(initialDir); diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 40881452be90..40f95a138829 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -164,7 +164,7 @@ #include "nsIContent.h" -#include "mozilla/HangMonitor.h" +#include "mozilla/HangMonitor.h" #include "nsIMM32Handler.h" using namespace mozilla::widget; @@ -338,6 +338,7 @@ nsWindow::nsWindow() : nsBaseWidget() mOldExStyle = 0; mPainting = 0; mLastKeyboardLayout = 0; + mBlurSuppressLevel = 0; mLastPaintEndTime = TimeStamp::Now(); #ifdef MOZ_XUL mTransparentSurface = nullptr; @@ -4007,14 +4008,25 @@ bool nsWindow::DispatchMouseEvent(uint32_t aEventType, WPARAM wParam, return result; } -HWND nsWindow::GetTopLevelForFocus(HWND aCurWnd) +void nsWindow::DispatchFocusToTopLevelWindow(bool aIsActivate) { - // retrieve the toplevel window or dialog - HWND toplevelWnd = NULL; - while (aCurWnd) { - toplevelWnd = aCurWnd; + if (aIsActivate) + sJustGotActivate = false; + sJustGotDeactivate = false; - nsWindow *win = WinUtils::GetNSWindowPtr(aCurWnd); + if (!aIsActivate && BlurEventsSuppressed()) + return; + + if (!mWidgetListener) + return; + + // retrive the toplevel window or dialog + HWND curWnd = mWnd; + HWND toplevelWnd = NULL; + while (curWnd) { + toplevelWnd = curWnd; + + nsWindow *win = WinUtils::GetNSWindowPtr(curWnd); if (win) { nsWindowType wintype; win->GetWindowType(wintype); @@ -4022,23 +4034,9 @@ HWND nsWindow::GetTopLevelForFocus(HWND aCurWnd) break; } - aCurWnd = ::GetParent(aCurWnd); // Parent or owner (if has no parent) + curWnd = ::GetParent(curWnd); // Parent or owner (if has no parent) } - return toplevelWnd; -} - -void nsWindow::DispatchFocusToTopLevelWindow(bool aIsActivate) -{ - if (aIsActivate) - sJustGotActivate = false; - sJustGotDeactivate = false; - mLastKillFocusWindow = NULL; - - if (!mWidgetListener) - return; - - HWND toplevelWnd = GetTopLevelForFocus(mWnd); if (toplevelWnd) { nsWindow *win = WinUtils::GetNSWindowPtr(toplevelWnd); if (win) { @@ -4068,6 +4066,36 @@ bool nsWindow::IsTopLevelMouseExit(HWND aWnd) return WinUtils::GetTopLevelHWND(aWnd) != mouseTopLevel; } +bool nsWindow::BlurEventsSuppressed() +{ + // are they suppressed in this window? + if (mBlurSuppressLevel > 0) + return true; + + // are they suppressed by any container widget? + HWND parentWnd = ::GetParent(mWnd); + if (parentWnd) { + nsWindow *parent = WinUtils::GetNSWindowPtr(parentWnd); + if (parent) + return parent->BlurEventsSuppressed(); + } + return false; +} + +// In some circumstances (opening dependent windows) it makes more sense +// (and fixes a crash bug) to not blur the parent window. Called from +// nsFilePicker. +void nsWindow::SuppressBlurEvents(bool aSuppress) +{ + if (aSuppress) + ++mBlurSuppressLevel; // for this widget + else { + NS_ASSERTION(mBlurSuppressLevel > 0, "unbalanced blur event suppression"); + if (mBlurSuppressLevel > 0) + --mBlurSuppressLevel; + } +} + bool nsWindow::ConvertStatus(nsEventStatus aStatus) { return aStatus == nsEventStatus_eConsumeNoDefault; @@ -4998,13 +5026,9 @@ bool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam, int32_t fActive = LOWORD(wParam); if (WA_INACTIVE == fActive) { - // When minimizing a window, the deactivation and focus events will + // when minimizing a window, the deactivation and focus events will // be fired in the reverse order. Instead, just deactivate right away. - // This can also happen when a modal file dialog is opened, so check - // if the last window to receive the WM_KILLFOCUS message was this one - // or a child of this one. - if (HIWORD(wParam) || - (mLastKillFocusWindow && (GetTopLevelForFocus(mLastKillFocusWindow) == mWnd))) + if (HIWORD(wParam)) DispatchFocusToTopLevelWindow(false); else sJustGotDeactivate = true; @@ -5080,9 +5104,6 @@ bool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam, if (sJustGotDeactivate) { DispatchFocusToTopLevelWindow(false); } - else { - mLastKillFocusWindow = mWnd; - } break; case WM_WINDOWPOSCHANGED: @@ -7056,9 +7077,6 @@ void nsWindow::OnDestroy() mWidgetListener = nullptr; mAttachedWidgetListener = nullptr; - if (mWnd == mLastKillFocusWindow) - mLastKillFocusWindow = NULL; - // Free our subclass and clear |this| stored in the window props. We will no longer // receive events from Windows after this point. SubclassWindow(FALSE); @@ -7073,7 +7091,7 @@ void nsWindow::OnDestroy() // Release references to children, device context, toolkit, and app shell. nsBaseWidget::OnDestroy(); - + // Clear our native parent handle. // XXX Windows will take care of this in the proper order, and SetParent(nullptr)'s // remove child on the parent already took place in nsBaseWidget's Destroy call above. diff --git a/widget/windows/nsWindow.h b/widget/windows/nsWindow.h index d0cc6d5980b0..b1a8331ca2fc 100644 --- a/widget/windows/nsWindow.h +++ b/widget/windows/nsWindow.h @@ -203,6 +203,8 @@ public: LPARAM aLParam, bool aDispatchPendingEvents); + void SuppressBlurEvents(bool aSuppress); // Called from nsFilePicker + bool BlurEventsSuppressed(); #ifdef ACCESSIBILITY Accessible* GetRootAccessible(); #endif // ACCESSIBILITY @@ -327,7 +329,6 @@ protected: * Event processing helpers */ bool DispatchPluginEvent(const MSG &aMsg); - HWND GetTopLevelForFocus(HWND aCurWnd); void DispatchFocusToTopLevelWindow(bool aIsActivate); bool DispatchStandardEvent(uint32_t aMsg); bool DispatchCommandEvent(uint32_t aEventCommand); @@ -469,6 +470,7 @@ protected: bool mFullscreenMode; bool mMousePresent; bool mDestroyCalled; + uint32_t mBlurSuppressLevel; DWORD_PTR mOldStyle; DWORD_PTR mOldExStyle; InputContext mInputContext; @@ -481,7 +483,6 @@ protected: uint32_t mPickerDisplayCount; HICON mIconSmall; HICON mIconBig; - HWND mLastKillFocusWindow; static bool sDropShadowEnabled; static uint32_t sInstanceCount; static TriStateBool sCanQuit;