Bug 452385 Bookmark This Page panel hangs Firefox when -moz-border-radius is used r=ere, sr=vlad
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 10 Sep 2008 02:22:12 +0900
changeset 19016 957eab222b84b9dc4b4a0e67249567ff0761c9c2
parent 19015 4a1ad24a36bcdd67c3b9498e70c0ee6a8c3f9f44
child 19017 dbdaae775f5bf718e0816f5a400c5dcb292d3a72
push id1911
push usermasayuki@d-toybox.com
push dateTue, 09 Sep 2008 17:22:50 +0000
treeherderautoland@957eab222b84 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersere, vlad
bugs452385
milestone1.9.1b1pre
Bug 452385 Bookmark This Page panel hangs Firefox when -moz-border-radius is used r=ere, sr=vlad
widget/src/windows/nsWindow.cpp
widget/src/windows/nsWindow.h
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -424,16 +424,20 @@ static PRBool is_vk_down(int vk)
 #define GET_APPCOMMAND_LPARAM(lParam) ((short)(HIWORD(lParam) & ~FAPPCOMMAND_MASK))
 //#define GET_DEVICE_LPARAM(lParam)     ((WORD)(HIWORD(lParam) & FAPPCOMMAND_MASK))
 //#define GET_MOUSEORKEY_LPARAM         GET_DEVICE_LPARAM
 //#define GET_FLAGS_LPARAM(lParam)      (LOWORD(lParam))
 //#define GET_KEYSTATE_LPARAM(lParam)   GET_FLAGS_LPARAM(lParam)
 
 #endif  // #ifndef APPCOMMAND_BROWSER_BACKWARD
 
+#define VERIFY_WINDOW_STYLE(s) \
+  NS_ASSERTION(((s) & (WS_CHILD | WS_POPUP)) != (WS_CHILD | WS_POPUP), \
+               "WS_POPUP and WS_CHILD are mutually exclusive")
+
 /* This object maintains a correlation between attention timers and the
    windows to which they belong. It's lighter than a hashtable (expected usage
    is really just one at a time) and allows nsWindow::GetNSWindowPtr
    to remain private. */
 class nsAttentionTimerMonitor {
 public:
   nsAttentionTimerMonitor() : mHeadTimer(0) { }
   ~nsAttentionTimerMonitor() {
@@ -537,31 +541,31 @@ private:
     }
   }
 
   TimerInfo *mHeadTimer;
 };
 
 static nsAttentionTimerMonitor *gAttentionTimerMonitor = 0;
 
-HWND nsWindow::GetTopLevelHWND(HWND aWnd, PRBool aStopOnFirstTopLevel)
+HWND nsWindow::GetTopLevelHWND(HWND aWnd, PRBool aStopOnDialogOrPopup)
 {
   HWND curWnd = aWnd;
   HWND topWnd = NULL;
 
-  while (curWnd)
-  {
+  while (curWnd) {
     topWnd = curWnd;
 
 #ifndef WINCE
-    if (aStopOnFirstTopLevel)
-    {
+    if (aStopOnDialogOrPopup) {
       DWORD style = ::GetWindowLongW(curWnd, GWL_STYLE);
 
-      if (!(style & WS_CHILDWINDOW))    // first top-level window
+      VERIFY_WINDOW_STYLE(style);
+
+      if (!(style & WS_CHILD)) // first top-level window
         break;
     }
 #endif
 
     curWnd = ::GetParent(curWnd);       // Parent or owner (if has no parent)
   }
 
   return topWnd;
@@ -1511,28 +1515,28 @@ NS_IMETHODIMP nsWindow::SetParent(nsIWid
 
 //-------------------------------------------------------------------------
 //
 // Get this nsWindow parent
 //
 //-------------------------------------------------------------------------
 nsIWidget* nsWindow::GetParent(void)
 {
-  return GetParent(PR_TRUE);
-}
-
-// XXX does anyone pass false for aStopOnFirstTopLevel?
-nsWindow* nsWindow::GetParent(PRBool aStopOnFirstTopLevel)
-{
-  if (mIsTopWidgetWindow && aStopOnFirstTopLevel) {
+  return GetParentWindow();
+}
+
+nsWindow* nsWindow::GetParentWindow()
+{
+  if (mIsTopWidgetWindow) {
     // Must use a flag instead of mWindowType to tell if the window is the
     // owned by the topmost widget, because a child window can be embedded inside
     // a HWND which is not associated with a nsIWidget.
     return nsnull;
   }
+
   // If this widget has already been destroyed, pretend we have no parent.
   // This corresponds to code in Destroy which removes the destroyed
   // widget from its parent's child list.
   if (mIsDestroying || mOnDestroyCalled)
     return nsnull;
 
   nsWindow* widget = nsnull;
   if (mWnd) {
@@ -2621,16 +2625,17 @@ NS_IMETHODIMP nsWindow::HideWindowChrome
       mOldStyle = ::GetWindowLongW(hwnd, GWL_STYLE);
       mOldExStyle = ::GetWindowLongW(hwnd, GWL_EXSTYLE);
     }
 
     style = mOldStyle;
     exStyle = mOldExStyle;
   }
 
+  VERIFY_WINDOW_STYLE(style);
   ::SetWindowLongW(hwnd, GWL_STYLE, style);
   ::SetWindowLongW(hwnd, GWL_EXSTYLE, exStyle);
 
   return NS_OK;
 }
 
 // ------------------------------------------------------------------------
 //
@@ -5543,16 +5548,17 @@ DWORD nsWindow::WindowStyle()
 
   if (mBorderStyle != eBorderStyle_default && mBorderStyle != eBorderStyle_all) {
     if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_border))
       style &= ~WS_BORDER;
 
     if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_title)) {
       style &= ~WS_DLGFRAME;
       style |= WS_POPUP;
+      style &= ~WS_CHILD;
     }
 
     if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_close))
       style &= ~0;
     // XXX The close box can only be removed by changing the window class,
     // as far as I know   --- roc+moz@cs.cmu.edu
 
     if (mBorderStyle == eBorderStyle_none ||
@@ -5568,16 +5574,17 @@ DWORD nsWindow::WindowStyle()
 
     if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_minimize))
       style &= ~WS_MINIMIZEBOX;
 
     if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_maximize))
       style &= ~WS_MAXIMIZEBOX;
   }
 #endif // WINCE
+  VERIFY_WINDOW_STYLE(style);
   return style;
 }
 
 
 //-------------------------------------------------------------------------
 //
 // return nsWindow extended styles
 //
@@ -5958,17 +5965,17 @@ static PRBool IsTopLevelMouseExit(HWND a
   POINT mp;
   mp.x = GET_X_LPARAM(pos);
   mp.y = GET_Y_LPARAM(pos);
   HWND mouseWnd = ::WindowFromPoint(mp);
 
   // GetTopLevelHWND will return a HWND for the window frame (which includes
   // the non-client area).  If the mouse has moved into the non-client area,
   // we should treat it as a top-level exit.
-  HWND mouseTopLevel = nsWindow::GetTopLevelHWND(mouseWnd, false);
+  HWND mouseTopLevel = nsWindow::GetTopLevelHWND(mouseWnd);
   if (mouseWnd == mouseTopLevel)
     return PR_TRUE;
 
   return nsWindow::GetTopLevelHWND(aWnd) != mouseTopLevel;
 }
 
 //-------------------------------------------------------------------------
 //
@@ -6330,17 +6337,21 @@ PRBool ChildWindow::DispatchMouseEvent(P
 
 //-------------------------------------------------------------------------
 //
 // return the style for a child nsWindow
 //
 //-------------------------------------------------------------------------
 DWORD ChildWindow::WindowStyle()
 {
-  return WS_CHILD | WS_CLIPCHILDREN | nsWindow::WindowStyle();
+  DWORD style = WS_CLIPCHILDREN | nsWindow::WindowStyle();
+  if (!(style & WS_POPUP))
+    style |= WS_CHILD; // WS_POPUP and WS_CHILD are mutually exclusive.
+  VERIFY_WINDOW_STYLE(style);
+  return style;
 }
 
 NS_METHOD nsWindow::SetTitle(const nsAString& aTitle)
 {
   const nsString& strTitle = PromiseFlatString(aTitle);
   ::SendMessageW(mWnd, WM_SETTEXT, (WPARAM)0, (LPARAM)(LPCWSTR)strTitle.get());
   return NS_OK;
 }
@@ -7154,17 +7165,19 @@ PRBool nsWindow::OnIMEQueryCharPosition(
     InitEvent(caretRect, &point);
     DispatchWindowEvent(&caretRect);
     if (!caretRect.mSucceeded)
       return PR_FALSE;
     r = caretRect.mReply.mRect;
   }
 
   nsRect screenRect;
-  ResolveIMECaretPos(GetTopLevelWindow(), r, nsnull, screenRect);
+  // We always need top level window that is owner window of the popup window
+  // even if the content of the popup window has focus.
+  ResolveIMECaretPos(GetTopLevelWindow(PR_FALSE), r, nsnull, screenRect);
   pCharPosition->pt.x = screenRect.x;
   pCharPosition->pt.y = screenRect.y;
 
   pCharPosition->cLineHeight = r.height;
 
   // XXX Should we create "query focused content rect event"?
   ::GetWindowRect(mWnd, &pCharPosition->rcDocument);
 
@@ -7981,28 +7994,35 @@ STDMETHODIMP_(LRESULT) nsWindow::Lresult
   }
 
   return 0;
 }
 #endif
 
 #ifdef MOZ_XUL
 
-nsWindow* nsWindow::GetTopLevelWindow()
+nsWindow* nsWindow::GetTopLevelWindow(PRBool aStopOnDialogOrPopup)
 {
   nsWindow* curWindow = this;
 
-  while (PR_TRUE)
-  {
-    nsWindow* parentWindow = curWindow->GetParent(PR_TRUE);
-
-    if (parentWindow)
-      curWindow = parentWindow;
-    else
+  while (PR_TRUE) {
+    if (aStopOnDialogOrPopup) {
+      switch (curWindow->mWindowType) {
+        case eWindowType_dialog:
+        case eWindowType_popup:
+          return curWindow;
+      }
+    }
+
+    nsWindow* parentWindow = curWindow->GetParentWindow();
+
+    if (!parentWindow)
       return curWindow;
+
+    curWindow = parentWindow;
   }
 }
 
 gfxASurface *nsWindow::GetThebesSurface()
 {
   if (mPaintDC)
     return (new gfxWindowsSurface(mPaintDC));
 
@@ -8015,22 +8035,22 @@ void nsWindow::ResizeTranslucentWindow(P
     return;
 
   mTransparentSurface = new gfxWindowsSurface(gfxIntSize(aNewWidth, aNewHeight), gfxASurface::ImageFormatARGB32);
   mMemoryDC = mTransparentSurface->GetDC();
 }
 
 nsTransparencyMode nsWindow::GetTransparencyMode()
 {
-  return GetTopLevelWindow()->GetWindowTranslucencyInner();
+  return GetTopLevelWindow(PR_TRUE)->GetWindowTranslucencyInner();
 }
 
 void nsWindow::SetTransparencyMode(nsTransparencyMode aMode)
 {
-  GetTopLevelWindow()->SetWindowTranslucencyInner(aMode);
+  GetTopLevelWindow(PR_TRUE)->SetWindowTranslucencyInner(aMode);
 }
 
 void nsWindow::SetWindowTranslucencyInner(nsTransparencyMode aMode)
 {
   if (aMode == mTransparencyMode)
     return;
 
   HWND hWnd = GetTopLevelHWND(mWnd, PR_TRUE);
@@ -8050,16 +8070,17 @@ void nsWindow::SetWindowTranslucencyInne
   switch(aMode) {
     case eTransparencyTransparent:
       exStyle |= WS_EX_LAYERED;
     case eTransparencyOpaque:
     case eTransparencyGlass:
       topWindow->mTransparencyMode = aMode;
       break;
   }
+  VERIFY_WINDOW_STYLE(style);
   ::SetWindowLongW(hWnd, GWL_STYLE, style);
   ::SetWindowLongW(hWnd, GWL_EXSTYLE, exStyle);
 
   mTransparencyMode = aMode;
 
   SetupTranslucentWindowMemoryBitmap(aMode);
   MARGINS margins = { 0, 0, 0, 0 };
   if(eTransparencyGlass == aMode)
--- a/widget/src/windows/nsWindow.h
+++ b/widget/src/windows/nsWindow.h
@@ -206,17 +206,22 @@ public:
 
   virtual void            SetUpForPaint(HDC aHDC);
   virtual void            ConvertToDeviceCoordinates(nscoord& aX,nscoord& aY) {}
 
   NS_IMETHOD              CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent);
 
   NS_IMETHOD              GetAttention(PRInt32 aCycleCount);
   NS_IMETHOD              GetLastInputEventTime(PRUint32& aTime);
-  nsWindow*               GetTopLevelWindow();
+
+  // Note that the result of GetTopLevelWindow method can be different from the
+  // result of GetTopLevelHWND method.  The result can be non-floating window.
+  // Because our top level window may be contained in another window which is
+  // not managed by us.
+  nsWindow*               GetTopLevelWindow(PRBool aStopOnDialogOrPopup);
 
   gfxASurface             *GetThebesSurface();
 
 #ifdef MOZ_XUL
   virtual void            SetTransparencyMode(nsTransparencyMode aMode);
   virtual nsTransparencyMode GetTransparencyMode();
 private:
   void                    SetWindowTranslucencyInner(nsTransparencyMode aMode);
@@ -282,17 +287,17 @@ protected:
 #endif
 
   static BOOL             DealWithPopups (HWND inWnd, UINT inMsg, WPARAM inWParam, LPARAM inLParam, LRESULT* outResult);
 
   static PRBool           EventIsInsideWindow(UINT Msg, nsWindow* aWindow);
 
   static nsWindow*        GetNSWindowPtr(HWND aWnd);
   static BOOL             SetNSWindowPtr(HWND aWnd, nsWindow * ptr);
-  nsWindow*               GetParent(PRBool aStopOnFirstTopLevel);
+  nsWindow*               GetParentWindow();
 
   void                    DispatchPendingEvents();
   virtual PRBool          ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *aRetValue);
   virtual PRBool          DispatchWindowEvent(nsGUIEvent* event);
   virtual PRBool          DispatchWindowEvent(nsGUIEvent*event, nsEventStatus &aStatus);
 
    // Allow Derived classes to modify the height that is passed
    // when the window is created or resized.
@@ -515,17 +520,22 @@ protected:
 
   static BOOL CALLBACK BroadcastMsgToChildren(HWND aWnd, LPARAM aMsg);
   static BOOL CALLBACK BroadcastMsg(HWND aTopWindow, LPARAM aMsg);
   static BOOL CALLBACK DispatchStarvedPaints(HWND aTopWindow, LPARAM aMsg);
   static BOOL CALLBACK InvalidateForeignChildWindows(HWND aWnd, LPARAM aMsg);
 
 public:
   static void GlobalMsgWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
-  static HWND GetTopLevelHWND(HWND aWnd, PRBool aStopOnFirstTopLevel = PR_FALSE);
+  // Note that the result of GetTopLevelHWND can be different from the result
+  // of GetTopLevelWindow method.  Because this is checking whether the window
+  // is top level only in Win32 window system.  Therefore, the result window
+  // may not be managed by us.
+  static HWND GetTopLevelHWND(HWND aWnd,
+                              PRBool aStopOnDialogOrPopup = PR_FALSE);
 };
 
 //
 // A child window is a window with different style
 //
 class ChildWindow : public nsWindow {
 
 public: