From 6ac1f05c3cb17fd551a2d82172b7709a370f0ae6 Mon Sep 17 00:00:00 2001 From: Emanuele Costa Date: Wed, 29 Jun 2011 15:49:42 -0400 Subject: [PATCH 01/37] When switching a window from background to foreground, reinitialize the timers that should fire sooner than the background clamp would have allowed. Bug 647001, r=bzbarsky --- dom/base/nsGlobalWindow.cpp | 112 +++++++++++++++++++++++++++++++++--- dom/base/nsGlobalWindow.h | 7 ++- dom/base/nsPIDOMWindow.h | 2 +- 3 files changed, 111 insertions(+), 10 deletions(-) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 6018ce8fc39e..13823c79c7c9 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -31,6 +31,7 @@ * Ryan Jones * Jeff Walden * Ben Bucksch + * Emanuele Costa * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -7483,6 +7484,15 @@ nsGlobalWindow::SetActive(PRBool aActive) NotifyDocumentTree(mDoc, nsnull); } +void nsGlobalWindow::SetIsBackground(PRBool aIsBackground) +{ + PRBool resetTimers = (!aIsBackground && IsBackground()); + nsPIDOMWindow::SetIsBackground(aIsBackground); + if (resetTimers) { + ResetTimersForNonBackgroundWindow(); + } +} + void nsGlobalWindow::MaybeUpdateTouchState() { FORWARD_TO_INNER_VOID(MaybeUpdateTouchState, ()); @@ -8848,10 +8858,8 @@ nsGlobalWindow::SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler, } nsRefPtr timeout = new nsTimeout(); - - if (aIsInterval) { - timeout->mInterval = interval; - } + timeout->mIsInterval = aIsInterval; + timeout->mInterval = interval; timeout->mScriptHandler = aHandler; // Now clamp the actual interval we will use for the timer based on @@ -9152,7 +9160,7 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout) ++gRunningTimeoutDepth; ++mTimeoutFiringDepth; - PRBool trackNestingLevel = !timeout->mInterval; + PRBool trackNestingLevel = !timeout->mIsInterval; PRUint32 nestingLevel; if (trackNestingLevel) { nestingLevel = sNestingLevel; @@ -9238,7 +9246,7 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout) // If we have a regular interval timer, we re-schedule the // timeout, accounting for clock drift. - if (timeout->mInterval) { + if (timeout->mIsInterval) { // Compute time to next timeout for interval timer. // Make sure nextInterval is at least DOMMinTimeoutValue(). TimeDuration nextInterval = @@ -9309,7 +9317,7 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout) } if (timeout->mTimer) { - if (timeout->mInterval) { + if (timeout->mIsInterval) { isInterval = PR_TRUE; } else { // The timeout still has an OS timer, and it's not an @@ -9387,7 +9395,7 @@ nsGlobalWindow::ClearTimeoutOrInterval(PRInt32 aTimerID) /* We're running from inside the timeout. Mark this timeout for deferred deletion by the code in RunTimeout() */ - timeout->mInterval = 0; + timeout->mIsInterval = PR_FALSE; } else { /* Delete the timeout from the pending timeout list */ @@ -9407,6 +9415,94 @@ nsGlobalWindow::ClearTimeoutOrInterval(PRInt32 aTimerID) return NS_OK; } +nsresult nsGlobalWindow::ResetTimersForNonBackgroundWindow() +{ + FORWARD_TO_INNER(ResetTimersForNonBackgroundWindow, (), + NS_ERROR_NOT_INITIALIZED); + + if (IsFrozen() || mTimeoutsSuspendDepth) { + return NS_OK; + } + + TimeStamp now = TimeStamp::Now(); + + for (nsTimeout *timeout = FirstTimeout(); IsTimeout(timeout); ) { + // It's important that this check be <= so that we guarantee that + // taking NS_MAX with |now| won't make a quantity equal to + // timeout->mWhen below. + if (timeout->mWhen <= now) { + timeout = timeout->Next(); + continue; + } + + if (timeout->mWhen - now > + TimeDuration::FromMilliseconds(gMinBackgroundTimeoutValue)) { + // No need to loop further. Timeouts are sorted in mWhen order + // and the ones after this point were all set up for at least + // gMinBackgroundTimeoutValue ms and hence were not clamped. + break; + } + + /* We switched from background. Re-init the timer appropriately */ + // Compute the interval the timer should have had if it had not been set in a + // background window + TimeDuration interval = + TimeDuration::FromMilliseconds(NS_MAX(timeout->mInterval, + PRUint32(DOMMinTimeoutValue()))); + PRUint32 oldIntervalMillisecs = 0; + timeout->mTimer->GetDelay(&oldIntervalMillisecs); + TimeDuration oldInterval = TimeDuration::FromMilliseconds(oldIntervalMillisecs); + if (oldInterval > interval) { + // unclamp + TimeStamp firingTime = + NS_MAX(timeout->mWhen - oldInterval + interval, now); + + NS_ASSERTION(firingTime < timeout->mWhen, + "Our firing time should strictly decrease!"); + + TimeDuration delay = firingTime - now; + timeout->mWhen = firingTime; + + // Since we reset mWhen we need to move |timeout| to the right + // place in the list so that it remains sorted by mWhen. + + // Get the pointer to the next timeout now, before we move the + // current timeout in the list. + nsTimeout* nextTimeout = timeout->Next(); + + // It is safe to remove and re-insert because mWhen is now + // strictly smaller than it used to be, so we know we'll insert + // |timeout| before nextTimeout. + NS_ASSERTION(!IsTimeout(nextTimeout) || + timeout->mWhen < nextTimeout->mWhen, "How did that happen?"); + PR_REMOVE_LINK(timeout); + // InsertTimeoutIntoList will addref |timeout| and reset + // mFiringDepth. Make sure to undo that after calling it. + PRUint32 firingDepth = timeout->mFiringDepth; + InsertTimeoutIntoList(timeout); + timeout->mFiringDepth = firingDepth; + timeout->Release(); + + nsresult rv = + timeout->mTimer->InitWithFuncCallback(TimerCallback, + timeout, + delay.ToMilliseconds(), + nsITimer::TYPE_ONE_SHOT); + + if (NS_FAILED(rv)) { + NS_WARNING("Error resetting non background timer for DOM timeout!"); + return rv; + } + + timeout = nextTimeout; + } else { + timeout = timeout->Next(); + } + } + + return NS_OK; +} + // A JavaScript specific version. nsresult nsGlobalWindow::ClearTimeoutOrInterval() diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 92d7ed48cb02..ec9a6c28801a 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -195,10 +195,13 @@ struct nsTimeout : PRCList // True if this is one of the timeouts that are currently running PRPackedBool mRunning; + // True if this is a repeating/interval timer + PRPackedBool mIsInterval; + // Returned as value of setTimeout() PRUint32 mPublicId; - // Non-zero interval in milliseconds if repetitive timeout + // Interval in milliseconds PRUint32 mInterval; // mWhen and mTimeRemaining can't be in a union, sadly, because they @@ -342,6 +345,7 @@ public: virtual NS_HIDDEN_(nsPIDOMWindow*) GetPrivateRoot(); virtual NS_HIDDEN_(void) ActivateOrDeactivate(PRBool aActivate); virtual NS_HIDDEN_(void) SetActive(PRBool aActive); + virtual NS_HIDDEN_(void) SetIsBackground(PRBool aIsBackground); virtual NS_HIDDEN_(void) SetChromeEventHandler(nsIDOMEventTarget* aChromeEventHandler); virtual NS_HIDDEN_(void) SetOpenerScriptPrincipal(nsIPrincipal* aPrincipal); @@ -664,6 +668,7 @@ protected: // JS specific timeout functions (JS args grabbed from context). nsresult SetTimeoutOrInterval(PRBool aIsInterval, PRInt32* aReturn); nsresult ClearTimeoutOrInterval(); + nsresult ResetTimersForNonBackgroundWindow(); // The timeout implementation functions. void RunTimeout(nsTimeout *aTimeout); diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index 2868a891f694..f25c629e4cde 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -105,7 +105,7 @@ public: return mIsActive; } - void SetIsBackground(PRBool aIsBackground) + virtual void SetIsBackground(PRBool aIsBackground) { mIsBackground = aIsBackground; } From a2888f3fb91dbf20c6a81d672ecb2ffa67e8f8ba Mon Sep 17 00:00:00 2001 From: Geoff Lankow Date: Wed, 29 Jun 2011 11:01:14 +1200 Subject: [PATCH 02/37] Bug 665378 - Intermittent browser_inlinesettings.js failures r=dtownsend --- .../mozapps/extensions/content/setting.xml | 2 +- .../test/browser/browser_inlinesettings.js | 111 ++++++++---------- 2 files changed, 52 insertions(+), 61 deletions(-) diff --git a/toolkit/mozapps/extensions/content/setting.xml b/toolkit/mozapps/extensions/content/setting.xml index 9f71a71ff270..9588dd8ee3cf 100644 --- a/toolkit/mozapps/extensions/content/setting.xml +++ b/toolkit/mozapps/extensions/content/setting.xml @@ -363,7 +363,7 @@ - + diff --git a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js index 4012abbf25eb..5aa8e311c0e2 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js +++ b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js @@ -181,78 +181,69 @@ add_test(function() { EventUtils.synthesizeKey("b", {}, gManagerWindow); is(input.value, "2", "Menulist should have updated value"); is(gManagerWindow._testValue, "2", "Menulist oncommand handler should've updated the test value"); + delete gManagerWindow._testValue; - setTimeout(function () { - EventUtils.synthesizeKey("c", {}, gManagerWindow); - is(input.value, "3", "Menulist should have updated value"); - is(gManagerWindow._testValue, "3", "Menulist oncommand handler should've updated the test value"); - delete gManagerWindow._testValue; + Services.prefs.setCharPref("extensions.inlinesettings1.color", "#FF0000"); + input = gManagerWindow.document.getAnonymousElementByAttribute(settings[5], "anonid", "input"); + is(input.color, "#FF0000", "Color picker should have initial value"); + input.focus(); + EventUtils.synthesizeKey("VK_RIGHT", {}, gManagerWindow); + EventUtils.synthesizeKey("VK_RIGHT", {}, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", {}, gManagerWindow); + input.hidePopup(); + is(input.color, "#FF9900", "Color picker should have updated value"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.color"), "#FF9900", "Color pref should have been updated"); - Services.prefs.setCharPref("extensions.inlinesettings1.color", "#FF0000"); - setTimeout(function () { - input = gManagerWindow.document.getAnonymousElementByAttribute(settings[5], "anonid", "input"); - is(input.color, "#FF0000", "Color picker should have initial value"); - input.focus(); - EventUtils.synthesizeKey("VK_RIGHT", {}, gManagerWindow); - EventUtils.synthesizeKey("VK_RIGHT", {}, gManagerWindow); - EventUtils.synthesizeKey("VK_RETURN", {}, gManagerWindow); - is(input.color, "#FF9900", "Color picker should have updated value"); - is(Services.prefs.getCharPref("extensions.inlinesettings1.color"), "#FF9900", "Color pref should have been updated"); + try { + mockFilePickerFactory.register(); - setTimeout(function () { - mockFilePickerFactory.register(); + var button = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "button"); + input = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "input"); + is(input.value, "", "Label value should be empty"); - try { - var button = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "button"); - input = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "input"); - is(input.value, "", "Label value should be empty"); + var profD = Services.dirsvc.get("ProfD", Ci.nsIFile); + var curProcD = Services.dirsvc.get("CurProcD", Ci.nsIFile); - var profD = Services.dirsvc.get("ProfD", Ci.nsIFile); - var curProcD = Services.dirsvc.get("CurProcD", Ci.nsIFile); + _returnFile = profD; + _returnValue = Ci.nsIFilePicker.returnOK; + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + is(_mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file"); + is(input.value, profD.path, "Label value should match file chosen"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should match file chosen"); - _returnFile = profD; - _returnValue = Ci.nsIFilePicker.returnOK; - EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); - is(_mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file"); - is(input.value, profD.path, "Label value should match file chosen"); - is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should match file chosen"); + _returnFile = curProcD; + _returnValue = Ci.nsIFilePicker.returnCancel; + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + is(_mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file"); + is(input.value, profD.path, "Label value should not have changed"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should not have changed"); - _returnFile = curProcD; - _returnValue = Ci.nsIFilePicker.returnCancel; - EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); - is(_mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file"); - is(input.value, profD.path, "Label value should not have changed"); - is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should not have changed"); + button = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "button"); + input = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "input"); + is(input.value, "", "Label value should be empty"); - button = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "button"); - input = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "input"); - is(input.value, "", "Label value should be empty"); - - _returnFile = profD; - _returnValue = Ci.nsIFilePicker.returnOK; - EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); - is(_mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory"); - is(input.value, profD.path, "Label value should match file chosen"); - is(Services.prefs.getCharPref("extensions.inlinesettings1.directory"), profD.path, "Directory pref should match file chosen"); + _returnFile = profD; + _returnValue = Ci.nsIFilePicker.returnOK; + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + is(_mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory"); + is(input.value, profD.path, "Label value should match file chosen"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.directory"), profD.path, "Directory pref should match file chosen"); - _returnFile = curProcD; - _returnValue = Ci.nsIFilePicker.returnCancel; - EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); - is(_mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory"); - is(input.value, profD.path, "Label value should not have changed"); - is(Services.prefs.getCharPref("extensions.inlinesettings1.directory"), profD.path, "Directory pref should not have changed"); + _returnFile = curProcD; + _returnValue = Ci.nsIFilePicker.returnCancel; + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + is(_mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory"); + is(input.value, profD.path, "Label value should not have changed"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.directory"), profD.path, "Directory pref should not have changed"); - } finally { - mockFilePickerFactory.unregister(); - } + } finally { + mockFilePickerFactory.unregister(); - button = gManagerWindow.document.getElementById("detail-prefs-btn"); - is_element_hidden(button, "Preferences button should not be visible"); + button = gManagerWindow.document.getElementById("detail-prefs-btn"); + is_element_hidden(button, "Preferences button should not be visible"); - gCategoryUtilities.openType("extension", run_next_test); - }, 0); - }, 0); - }, 1200); // Timeout value from toolkit/content/tests/widgets/test_menulist_keynav.xul + gCategoryUtilities.openType("extension", run_next_test); + } }); }); From 4126fe630a94a313909de553b64dacde8255c27d Mon Sep 17 00:00:00 2001 From: Brian Bondy Date: Wed, 29 Jun 2011 15:15:23 -0500 Subject: [PATCH 03/37] Bug 660833 - Fix for forms with input multiple on Windows do not accept more than 253 files at once. r=jimm --- widget/src/windows/nsFilePicker.cpp | 85 ++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 2 deletions(-) diff --git a/widget/src/windows/nsFilePicker.cpp b/widget/src/windows/nsFilePicker.cpp index 4ce495bef407..e2f0e2670fa3 100644 --- a/widget/src/windows/nsFilePicker.cpp +++ b/widget/src/windows/nsFilePicker.cpp @@ -97,6 +97,75 @@ int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpDa return 0; } +// Callback hook which will dynamically allocate a buffer large +// enough for the file picker dialog. +static unsigned int CALLBACK FilePickerHook(HWND hwnd, UINT msg, + WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + { + // Finds the child drop down of a File Picker dialog and sets the + // maximum amount of text it can hold when typed in manually. + // A wParam of 0 mean 0x7FFFFFFE characters. + HWND comboBox = FindWindowEx(GetParent(hwnd), NULL, + L"ComboBoxEx32", NULL ); + if(comboBox) + SendMessage(comboBox, CB_LIMITTEXT, 0, 0); + } + break; + case WM_NOTIFY: + { + LPOFNOTIFYW lpofn = (LPOFNOTIFYW) lParam; + // CDN_SELCHANGE is sent when the selection in the list box of the file + // selection dialog changes + if (lpofn->hdr.code == CDN_SELCHANGE) { + HWND parentHWND = GetParent(hwnd); + + // Get the required size for the selected files buffer + UINT newBufLength = 0; + int requiredBufLength = CommDlg_OpenSave_GetSpecW(parentHWND, + NULL, 0); + if(requiredBufLength >= 0) + newBufLength += requiredBufLength; + else + newBufLength += MAX_PATH; + + // If the user selects multiple files, the buffer contains the + // current directory followed by the file names of the selected + // files. So make room for the directory path. If the user + // selects a single file, it is no harm to add extra space. + requiredBufLength = CommDlg_OpenSave_GetFolderPathW(parentHWND, + NULL, 0); + if(requiredBufLength >= 0) + newBufLength += requiredBufLength; + else + newBufLength += MAX_PATH; + + // Check if lpstrFile and nMaxFile are large enough + if (newBufLength > lpofn->lpOFN->nMaxFile) + { + if (lpofn->lpOFN->lpstrFile) + delete[] lpofn->lpOFN->lpstrFile; + + // We allocate FILE_BUFFER_SIZE more bytes than is needed so that + // if the user selects a file and holds down shift and down to + // select additional items, we will not continuously reallocate + newBufLength += FILE_BUFFER_SIZE; + + PRUnichar* filesBuffer = new PRUnichar[newBufLength]; + ZeroMemory(filesBuffer, newBufLength * sizeof(PRUnichar)); + + lpofn->lpOFN->lpstrFile = filesBuffer; + lpofn->lpOFN->nMaxFile = newBufLength; + } + } + } + break; + } + return 0; +} + NS_IMETHODIMP nsFilePicker::ShowW(PRInt16 *aReturnVal) { NS_ENSURE_ARG_POINTER(aReturnVal); @@ -109,7 +178,8 @@ NS_IMETHODIMP nsFilePicker::ShowW(PRInt16 *aReturnVal) } PRBool result = PR_FALSE; - PRUnichar fileBuffer[FILE_BUFFER_SIZE+1]; + nsAutoArrayPtr fileBuffer(new PRUnichar[FILE_BUFFER_SIZE+1]); + wcsncpy(fileBuffer, mDefault.get(), FILE_BUFFER_SIZE); fileBuffer[FILE_BUFFER_SIZE] = '\0'; // null terminate in case copy truncated @@ -229,8 +299,19 @@ NS_IMETHODIMP nsFilePicker::ShowW(PRInt16 *aReturnVal) result = ::GetOpenFileNameW(&ofn); } else if (mMode == modeOpenMultiple) { - ofn.Flags |= OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_EXPLORER; + ofn.Flags |= OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | + OFN_EXPLORER | OFN_ENABLEHOOK; + + // The hook set here ensures that the buffer returned will always be + // long enough to hold all selected files. The hook may modify the + // value of ofn.lpstrFile and deallocate the old buffer that it pointed + // to (fileBuffer). The hook assumes that the passed in value is heap + // allocated and that the returned value should be freed by the caller. + // If the hook changes the buffer, it will deallocate the old buffer. + ofn.lpfnHook = FilePickerHook; + fileBuffer.forget(); result = ::GetOpenFileNameW(&ofn); + fileBuffer = ofn.lpstrFile; } else if (mMode == modeSave) { ofn.Flags |= OFN_NOREADONLYRETURN; From 058ec38c330905ae48700da6c02d03d4a05a302d Mon Sep 17 00:00:00 2001 From: Brian Bondy Date: Wed, 29 Jun 2011 15:15:58 -0500 Subject: [PATCH 04/37] Bug 418027 - Buttons on Windows should enter hover state when both focused and hovered. r=jimm --- widget/src/windows/nsNativeThemeWin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/widget/src/windows/nsNativeThemeWin.cpp b/widget/src/windows/nsNativeThemeWin.cpp index 513f688f236c..37b28a3f3233 100644 --- a/widget/src/windows/nsNativeThemeWin.cpp +++ b/widget/src/windows/nsNativeThemeWin.cpp @@ -515,10 +515,10 @@ nsNativeThemeWin::StandardGetState(nsIFrame* aFrame, PRUint8 aWidgetType, nsEventStates eventState = GetContentState(aFrame, aWidgetType); if (eventState.HasAllStates(NS_EVENT_STATE_HOVER | NS_EVENT_STATE_ACTIVE)) return TS_ACTIVE; - if (wantFocused && eventState.HasState(NS_EVENT_STATE_FOCUS)) - return TS_FOCUSED; if (eventState.HasState(NS_EVENT_STATE_HOVER)) return TS_HOVER; + if (wantFocused && eventState.HasState(NS_EVENT_STATE_FOCUS)) + return TS_FOCUSED; return TS_NORMAL; } From c9f703ff56906621dc9fbb632bfdf6082c3651c2 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Wed, 29 Jun 2011 17:00:16 -0400 Subject: [PATCH 05/37] Followup to the backout of bug 664152: use the old path to the test file --- layout/base/tests/chrome/test_bug551434.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/base/tests/chrome/test_bug551434.html b/layout/base/tests/chrome/test_bug551434.html index 517f9d716074..e13a92ccf4a5 100644 --- a/layout/base/tests/chrome/test_bug551434.html +++ b/layout/base/tests/chrome/test_bug551434.html @@ -17,7 +17,7 @@ - + + + +
+ + diff --git a/layout/reftests/canvas/ctm-1.html b/layout/reftests/canvas/ctm-1.html new file mode 100644 index 000000000000..1802820a59fe --- /dev/null +++ b/layout/reftests/canvas/ctm-1.html @@ -0,0 +1,18 @@ + + + + + +
+ + diff --git a/layout/reftests/canvas/ctm-sanity.html b/layout/reftests/canvas/ctm-sanity.html new file mode 100644 index 000000000000..991d683c8c3a --- /dev/null +++ b/layout/reftests/canvas/ctm-sanity.html @@ -0,0 +1,83 @@ + + + + + +
+ + diff --git a/layout/reftests/canvas/ctm-singular-sanity.html b/layout/reftests/canvas/ctm-singular-sanity.html new file mode 100644 index 000000000000..8e6af1c99ada --- /dev/null +++ b/layout/reftests/canvas/ctm-singular-sanity.html @@ -0,0 +1,53 @@ + + + + + +
+ + diff --git a/layout/reftests/canvas/reftest.list b/layout/reftests/canvas/reftest.list index c626cb2a98e3..1ccaac7acb2a 100644 --- a/layout/reftests/canvas/reftest.list +++ b/layout/reftests/canvas/reftest.list @@ -56,3 +56,7 @@ fails-if(cocoaWidget) == linear-gradient-1b.html linear-gradient-1-ref.html == evenodd-fill-1.html evenodd-fill-ref.html == evenodd-fill-2.html evenodd-fill-ref.html == evenodd-fill-3.html nonzero-fill-2.html + +== ctm-sanity.html data:text/html,Pass +fails == ctm-singular-sanity.html data:text/html,Pass # Bug 612033 +== ctm-1.html ctm-1-ref.html From d27b6463018a2d62668795bd2458fca06bca7413 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Wed, 29 Jun 2011 14:34:58 -0700 Subject: [PATCH 08/37] Bug 662038, part 0: Add gfxContext::CurrentDash(). r=jrmuizel --- gfx/thebes/gfxContext.cpp | 23 ++++++++++++++++++++++- gfx/thebes/gfxContext.h | 8 +++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/gfx/thebes/gfxContext.cpp b/gfx/thebes/gfxContext.cpp index a2f3e68afbf1..e165dbfcea29 100644 --- a/gfx/thebes/gfxContext.cpp +++ b/gfx/thebes/gfxContext.cpp @@ -545,7 +545,28 @@ gfxContext::SetDash(gfxFloat *dashes, int ndash, gfxFloat offset) { cairo_set_dash(mCairo, dashes, ndash, offset); } -//void getDash() const; + +bool +gfxContext::CurrentDash(FallibleTArray& dashes, gfxFloat* offset) const +{ + int count = cairo_get_dash_count(mCairo); + if (count <= 0 || !dashes.SetLength(count)) { + return false; + } + cairo_get_dash(mCairo, dashes.Elements(), offset); + return true; +} + +gfxFloat +gfxContext::CurrentDashOffset() const +{ + if (cairo_get_dash_count(mCairo) <= 0) { + return 0.0; + } + gfxFloat offset; + cairo_get_dash(mCairo, NULL, &offset); + return offset; +} void gfxContext::SetLineWidth(gfxFloat width) diff --git a/gfx/thebes/gfxContext.h b/gfx/thebes/gfxContext.h index 9f6a7a97b8c2..eca64350d1c8 100644 --- a/gfx/thebes/gfxContext.h +++ b/gfx/thebes/gfxContext.h @@ -51,6 +51,7 @@ #include "nsISupportsImpl.h" typedef struct _cairo cairo_t; +template class FallibleTArray; /** * This is the main class for doing actual drawing. It is initialized using @@ -465,7 +466,12 @@ public: void SetDash(gfxLineType ltype); void SetDash(gfxFloat *dashes, int ndash, gfxFloat offset); - //void getDash() const; + // Return true if dashing is set, false if it's not enabled or the + // context is in an error state. |offset| can be NULL to mean + // "don't care". + bool CurrentDash(FallibleTArray& dashes, gfxFloat* offset) const; + // Returns 0.0 if dashing isn't enabled. + gfxFloat CurrentDashOffset() const; /** * Sets the line width that's used for line drawing. From 952bc1a6688412dce98767ed8207b3cdf60917fc Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Wed, 29 Jun 2011 14:34:58 -0700 Subject: [PATCH 09/37] Bug 662038, part 2: Add dashing API to Azure. r=Bas sr=roc --- gfx/2d/2D.h | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index da001346e820..54937afee6f7 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -107,20 +107,38 @@ struct DrawOptions { * mLineJoin - Join style used for joining lines. * mLineCap - Cap style used for capping lines. * mMiterLimit - Miter limit in units of linewidth + * mDashPattern - Series of on/off userspace lengths defining dash. + * Owned by the caller; must live at least as long as + * this StrokeOptions. + * mDashPattern != null <=> mDashLength > 0. + * mDashLength - Number of on/off lengths in mDashPattern. + * mDashOffset - Userspace offset within mDashPattern at which stroking + * begins. */ struct StrokeOptions { StrokeOptions(Float aLineWidth = 1.0f, JoinStyle aLineJoin = JOIN_MITER_OR_BEVEL, CapStyle aLineCap = CAP_BUTT, - Float aMiterLimit = 10.0f) + Float aMiterLimit = 10.0f, + size_t aDashLength = 0, + const Float* aDashPattern = 0, + Float aDashOffset = 0.f) : mLineWidth(aLineWidth) , mMiterLimit(aMiterLimit) + , mDashPattern(aDashLength > 0 ? aDashPattern : 0) + , mDashLength(aDashLength) + , mDashOffset(aDashOffset) , mLineJoin(aLineJoin) , mLineCap(aLineCap) - {} + { + MOZ_ASSERT(aDashLength == 0 || aDashPattern); + } Float mLineWidth; Float mMiterLimit; + const Float* mDashPattern; + size_t mDashLength; + Float mDashOffset; JoinStyle mLineJoin : 4; CapStyle mLineCap : 3; }; From e0d217fcaabeaf47d4e73fe30ca11d9c042ccf88 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Wed, 29 Jun 2011 14:34:58 -0700 Subject: [PATCH 10/37] Bug 662038, part 3: Implement dashing for d2d. r=Bas --- gfx/2d/DrawTargetD2D.cpp | 42 ++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/gfx/2d/DrawTargetD2D.cpp b/gfx/2d/DrawTargetD2D.cpp index dd34e0a85c00..403222eb8345 100644 --- a/gfx/2d/DrawTargetD2D.cpp +++ b/gfx/2d/DrawTargetD2D.cpp @@ -65,6 +65,8 @@ typedef HRESULT (WINAPI*D3D10CreateEffectFromMemoryFunc)( __out ID3D10Effect **ppEffect ); +using namespace std; + namespace mozilla { namespace gfx { @@ -665,8 +667,10 @@ DrawTargetD2D::CopySurface(SourceSurface *aSurface, const IntRect &aSourceRect, const IntPoint &aDestination) { - Rect srcRect(aSourceRect.x, aSourceRect.y, aSourceRect.width, aSourceRect.height); - Rect dstRect(aDestination.x, aDestination.y, aSourceRect.width, aSourceRect.height); + Rect srcRect(Float(aSourceRect.x), Float(aSourceRect.y), + Float(aSourceRect.width), Float(aSourceRect.height)); + Rect dstRect(Float(aDestination.x), Float(aDestination.y), + Float(aSourceRect.width), Float(aSourceRect.height)); mRT->SetTransform(D2D1::IdentityMatrix()); mRT->PushAxisAlignedClip(D2DRect(dstRect), D2D1_ANTIALIAS_MODE_ALIASED); @@ -1632,10 +1636,36 @@ DrawTargetD2D::CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions) } - HRESULT hr = factory()->CreateStrokeStyle(D2D1::StrokeStyleProperties(capStyle, capStyle, - capStyle, joinStyle, - aStrokeOptions.mMiterLimit), - NULL, 0, byRef(style)); + HRESULT hr; + if (aStrokeOptions.mDashPattern) { + typedef vector FloatVector; + // D2D "helpfully" multiplies the dash pattern by the line width. + // That's not what cairo does, or is what 's dash wants. + // So fix the multiplication in advance. + Float lineWidth = aStrokeOptions.mLineWidth; + FloatVector dash(aStrokeOptions.mDashPattern, + aStrokeOptions.mDashPattern + aStrokeOptions.mDashLength); + for (FloatVector::iterator it = dash.begin(); it != dash.end(); ++it) { + *it /= lineWidth; + } + + hr = factory()->CreateStrokeStyle( + D2D1::StrokeStyleProperties(capStyle, capStyle, + capStyle, joinStyle, + aStrokeOptions.mMiterLimit, + D2D1_DASH_STYLE_CUSTOM, + aStrokeOptions.mDashOffset), + &dash[0], // data() is not C++98, although it's in recent gcc + // and VC10's STL + dash.size(), + byRef(style)); + } else { + hr = factory()->CreateStrokeStyle( + D2D1::StrokeStyleProperties(capStyle, capStyle, + capStyle, joinStyle, + aStrokeOptions.mMiterLimit), + NULL, 0, byRef(style)); + } if (FAILED(hr)) { gfxWarning() << "Failed to create Direct2D stroke style."; From d0aa936a4b04c42bd99401da8dedfed52ad4e790 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Wed, 29 Jun 2011 14:34:58 -0700 Subject: [PATCH 11/37] Bug 662038, parts 1, 4-5: Add canvas.mozDash and .mozDashOffset. r=joe sr=vlad --- content/canvas/src/CanvasUtils.cpp | 3 +- content/canvas/src/CanvasUtils.h | 87 +++++++++++++++++++ .../canvas/src/nsCanvasRenderingContext2D.cpp | 59 +++++++++++++ .../src/nsCanvasRenderingContext2DAzure.cpp | 80 +++++++++++++++-- .../canvas/nsIDOMCanvasRenderingContext2D.idl | 4 + 5 files changed, 224 insertions(+), 9 deletions(-) diff --git a/content/canvas/src/CanvasUtils.cpp b/content/canvas/src/CanvasUtils.cpp index 983ce9069647..447df2323cbc 100644 --- a/content/canvas/src/CanvasUtils.cpp +++ b/content/canvas/src/CanvasUtils.cpp @@ -194,7 +194,8 @@ JSValToMatrix(JSContext* cx, const jsval& val, Matrix* matrix, nsresult* rv) gfxMatrix m; if (!JSValToMatrix(cx, val, &m, rv)) return false; - *matrix = Matrix(m.xx, m.yx, m.xy, m.yy, m.x0, m.y0); + *matrix = Matrix(Float(m.xx), Float(m.yx), Float(m.xy), Float(m.yy), + Float(m.x0), Float(m.y0)); return true; } diff --git a/content/canvas/src/CanvasUtils.h b/content/canvas/src/CanvasUtils.h index d1ec418dbcfc..3d57d9a32b56 100644 --- a/content/canvas/src/CanvasUtils.h +++ b/content/canvas/src/CanvasUtils.h @@ -131,6 +131,93 @@ inline PRBool FloatValidate (double f1, double f2, double f3, double f4, double #undef VALIDATE +template +nsresult +JSValToDashArray(JSContext* cx, const jsval& val, + FallibleTArray& dashArray); + +template +nsresult +DashArrayToJSVal(FallibleTArray& dashArray, + JSContext* cx, jsval* val); + +template +nsresult +JSValToDashArray(JSContext* cx, const jsval& patternArray, + FallibleTArray& dashes) +{ + // The cap is pretty arbitrary. 16k should be enough for + // anybody... + static const jsuint MAX_NUM_DASHES = 1 << 14; + + if (!JSVAL_IS_PRIMITIVE(patternArray)) { + JSObject* obj = JSVAL_TO_OBJECT(patternArray); + jsuint length; + if (!JS_GetArrayLength(cx, obj, &length)) { + // Not an array-like thing + return NS_ERROR_INVALID_ARG; + } else if (length > MAX_NUM_DASHES) { + // Too many dashes in the pattern + return NS_ERROR_ILLEGAL_VALUE; + } + + bool haveNonzeroElement = false; + for (jsint i = 0; i < jsint(length); ++i) { + jsval elt; + double d; + if (!JS_GetElement(cx, obj, i, &elt)) { + return NS_ERROR_FAILURE; + } + if (!(CoerceDouble(elt, &d) && + FloatValidate(d) && + d >= 0.0)) { + // Pattern elements must be finite "numbers" >= 0. + return NS_ERROR_INVALID_ARG; + } else if (d > 0.0) { + haveNonzeroElement = true; + } + if (!dashes.AppendElement(d)) { + return NS_ERROR_OUT_OF_MEMORY; + } + } + + if (dashes.Length() > 0 && !haveNonzeroElement) { + // An all-zero pattern makes no sense. + return NS_ERROR_ILLEGAL_VALUE; + } + } else if (!(JSVAL_IS_VOID(patternArray) || JSVAL_IS_NULL(patternArray))) { + // undefined and null mean "reset to no dash". Any other + // random garbage is a type error. + return NS_ERROR_INVALID_ARG; + } + + return NS_OK; +} + +template +nsresult +DashArrayToJSVal(FallibleTArray& dashes, + JSContext* cx, jsval* val) +{ + if (dashes.IsEmpty()) { + *val = JSVAL_NULL; + } else { + JSObject* obj = JS_NewArrayObject(cx, dashes.Length(), nsnull); + if (!obj) { + return NS_ERROR_OUT_OF_MEMORY; + } + for (PRUint32 i = 0; i < dashes.Length(); ++i) { + double d = dashes[i]; + jsval elt = DOUBLE_TO_JSVAL(d); + if (!JS_SetElement(cx, obj, i, &elt)) { + return NS_ERROR_FAILURE; + } + } + *val = OBJECT_TO_JSVAL(obj); + } + return NS_OK; +} + } } diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp index c15527574982..f1253cf7c5f2 100644 --- a/content/canvas/src/nsCanvasRenderingContext2D.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp @@ -167,6 +167,12 @@ CopyContext(gfxContext* dest, gfxContext* src) dest->SetFillRule(src->CurrentFillRule()); dest->SetAntialiasMode(src->CurrentAntialiasMode()); + + AutoFallibleTArray dashes; + double dashOffset; + if (src->CurrentDash(dashes, &dashOffset)) { + dest->SetDash(dashes.Elements(), dashes.Length(), dashOffset); + } } /** @@ -3287,6 +3293,59 @@ nsCanvasRenderingContext2D::GetMiterLimit(float *miter) return NS_OK; } +NS_IMETHODIMP +nsCanvasRenderingContext2D::SetMozDash(JSContext *cx, const jsval& patternArray) +{ + AutoFallibleTArray dashes; + nsresult rv = JSValToDashArray(cx, patternArray, dashes); + if (NS_SUCCEEDED(rv)) { + mThebes->SetDash(dashes.Elements(), dashes.Length(), + mThebes->CurrentDashOffset()); + } + return rv; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::GetMozDash(JSContext* cx, jsval* dashArray) +{ + AutoFallibleTArray dashes; + if (!mThebes->CurrentDash(dashes, nsnull)) { + dashes.SetLength(0); + } + return DashArrayToJSVal(dashes, cx, dashArray); +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::SetMozDashOffset(float offset) +{ + if (!FloatValidate(offset)) { + return NS_ERROR_ILLEGAL_VALUE; + } + + AutoFallibleTArray dashes; + if (!mThebes->CurrentDash(dashes, nsnull)) { + // Either no dash is set or the cairo call failed. Either + // way, eat the error. + + // XXX ERRMSG we need to report an error to developers here! (bug 329026) + return NS_OK; + } + NS_ABORT_IF_FALSE(dashes.Length() > 0, + "CurrentDash() should have returned false"); + + mThebes->SetDash(dashes.Elements(), dashes.Length(), + gfxFloat(offset)); + + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::GetMozDashOffset(float* offset) +{ + *offset = float(mThebes->CurrentDashOffset()); + return NS_OK; +} + NS_IMETHODIMP nsCanvasRenderingContext2D::IsPointInPath(float x, float y, PRBool *retVal) { diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp index 68333f259816..47352035445c 100644 --- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp @@ -684,6 +684,7 @@ protected: miterLimit(10.0f), globalAlpha(1.0f), shadowBlur(0.0), + dashOffset(0.0f), op(OP_OVER), fillRule(FILL_WINDING), lineCap(CAP_BUTT), @@ -703,6 +704,8 @@ protected: miterLimit(other.miterLimit), globalAlpha(other.globalAlpha), shadowBlur(other.shadowBlur), + dash(other.dash), + dashOffset(other.dashOffset), op(other.op), fillRule(FILL_WINDING), lineCap(other.lineCap), @@ -761,6 +764,8 @@ protected: Float miterLimit; Float globalAlpha; Float shadowBlur; + FallibleTArray dash; + Float dashOffset; CompositionOp op; FillRule fillRule; @@ -2147,7 +2152,10 @@ nsCanvasRenderingContext2DAzure::StrokeRect(float x, float y, float w, float h) StrokeLine(Point(x, y), Point(x + w, y), GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget), StrokeOptions(state.lineWidth, state.lineJoin, - cap, state.miterLimit), + cap, state.miterLimit, + state.dash.Length(), + state.dash.Elements(), + state.dashOffset), DrawOptions(state.globalAlpha, state.op)); return NS_OK; } else if (!w) { @@ -2159,7 +2167,10 @@ nsCanvasRenderingContext2DAzure::StrokeRect(float x, float y, float w, float h) StrokeLine(Point(x, y), Point(x, y + h), GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget), StrokeOptions(state.lineWidth, state.lineJoin, - cap, state.miterLimit), + cap, state.miterLimit, + state.dash.Length(), + state.dash.Elements(), + state.dashOffset), DrawOptions(state.globalAlpha, state.op)); return NS_OK; } @@ -2168,7 +2179,10 @@ nsCanvasRenderingContext2DAzure::StrokeRect(float x, float y, float w, float h) StrokeRect(mgfx::Rect(x, y, w, h), GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget), StrokeOptions(state.lineWidth, state.lineJoin, - state.lineCap, state.miterLimit), + state.lineCap, state.miterLimit, + state.dash.Length(), + state.dash.Elements(), + state.dashOffset), DrawOptions(state.globalAlpha, state.op)); return Redraw(); @@ -2232,7 +2246,10 @@ nsCanvasRenderingContext2DAzure::Stroke() AdjustedTarget(this)-> Stroke(mPath, GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget), StrokeOptions(state.lineWidth, state.lineJoin, - state.lineCap, state.miterLimit), + state.lineCap, state.miterLimit, + state.dash.Length(), + state.dash.Elements(), + state.dashOffset), DrawOptions(state.globalAlpha, state.op)); return Redraw(); @@ -2971,6 +2988,8 @@ nsCanvasRenderingContext2DAzure::MeasureText(const nsAString& rawText, */ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiProcessor { + typedef nsCanvasRenderingContext2DAzure::ContextState ContextState; + virtual void SetText(const PRUnichar* text, PRInt32 length, nsBidiDirection direction) { mTextRun = gfxTextRunCache::MakeTextRun(text, @@ -3111,12 +3130,16 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP Matrix oldTransform = mCtx->mTarget->GetTransform(); + const ContextState& state = *mState; nsCanvasRenderingContext2DAzure::AdjustedTarget(mCtx)-> Stroke(path, nsCanvasRenderingContext2DAzure::GeneralPattern(). ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_STROKE, mCtx->mTarget), - StrokeOptions(mCtx->CurrentState().lineWidth, mCtx->CurrentState().lineJoin, - mCtx->CurrentState().lineCap, mCtx->CurrentState().miterLimit), - DrawOptions(mState->globalAlpha, mState->op)); + StrokeOptions(state.lineWidth, state.lineJoin, + state.lineCap, state.miterLimit, + state.dash.Length(), + state.dash.Elements(), + state.dashOffset), + DrawOptions(state.globalAlpha, state.op)); } } @@ -3144,7 +3167,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP nsCanvasRenderingContext2DAzure::TextDrawOperation mOp; // context state - nsCanvasRenderingContext2DAzure::ContextState *mState; + ContextState *mState; // union of bounding boxes of all runs, needed for shadows gfxRect mBoundingBox; @@ -3542,6 +3565,47 @@ nsCanvasRenderingContext2DAzure::GetMiterLimit(float *miter) return NS_OK; } +NS_IMETHODIMP +nsCanvasRenderingContext2DAzure::SetMozDash(JSContext *cx, const jsval& patternArray) +{ + FallibleTArray dash; + nsresult rv = JSValToDashArray(cx, patternArray, dash); + if (NS_SUCCEEDED(rv)) { + ContextState& state = CurrentState(); + state.dash = dash; + if (state.dash.IsEmpty()) { + state.dashOffset = 0; + } + } + return rv; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2DAzure::GetMozDash(JSContext* cx, jsval* dashArray) +{ + return DashArrayToJSVal(CurrentState().dash, cx, dashArray); +} + +NS_IMETHODIMP +nsCanvasRenderingContext2DAzure::SetMozDashOffset(float offset) +{ + if (!FloatValidate(offset)) { + return NS_ERROR_ILLEGAL_VALUE; + } + ContextState& state = CurrentState(); + if (!state.dash.IsEmpty()) { + state.dashOffset = offset; + } + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2DAzure::GetMozDashOffset(float* offset) +{ + *offset = CurrentState().dashOffset; + return NS_OK; +} + NS_IMETHODIMP nsCanvasRenderingContext2DAzure::IsPointInPath(float x, float y, PRBool *retVal) { diff --git a/dom/interfaces/canvas/nsIDOMCanvasRenderingContext2D.idl b/dom/interfaces/canvas/nsIDOMCanvasRenderingContext2D.idl index a2ad7a2cc546..81dbf537b0ae 100644 --- a/dom/interfaces/canvas/nsIDOMCanvasRenderingContext2D.idl +++ b/dom/interfaces/canvas/nsIDOMCanvasRenderingContext2D.idl @@ -121,6 +121,10 @@ enum CanvasMultiGetterType { attribute DOMString lineJoin; /* "round", "bevel", "miter" (default) */ attribute float miterLimit; /* default 10 */ + [implicit_jscontext] + attribute jsval mozDash; /* default |null| */ + attribute float mozDashOffset; /* default 0.0 */ + // shadows attribute float shadowOffsetX; attribute float shadowOffsetY; From 9e7179916d7f1111ae3fd54af3bed747681f6180 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Wed, 29 Jun 2011 14:34:58 -0700 Subject: [PATCH 12/37] Bug 662038: Very basic tests of mozDash/mozDashOffset. r=joe --- layout/reftests/canvas/dash-1-ref.svg | 14 ++++ layout/reftests/canvas/dash-1.html | 26 ++++++++ layout/reftests/canvas/dash-sanity.html | 85 +++++++++++++++++++++++++ layout/reftests/canvas/reftest.list | 3 + 4 files changed, 128 insertions(+) create mode 100644 layout/reftests/canvas/dash-1-ref.svg create mode 100644 layout/reftests/canvas/dash-1.html create mode 100644 layout/reftests/canvas/dash-sanity.html diff --git a/layout/reftests/canvas/dash-1-ref.svg b/layout/reftests/canvas/dash-1-ref.svg new file mode 100644 index 000000000000..b577edf5ae18 --- /dev/null +++ b/layout/reftests/canvas/dash-1-ref.svg @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/layout/reftests/canvas/dash-1.html b/layout/reftests/canvas/dash-1.html new file mode 100644 index 000000000000..e0921e1eac68 --- /dev/null +++ b/layout/reftests/canvas/dash-1.html @@ -0,0 +1,26 @@ + + + + + +
+ + diff --git a/layout/reftests/canvas/dash-sanity.html b/layout/reftests/canvas/dash-sanity.html new file mode 100644 index 000000000000..d28c79277f59 --- /dev/null +++ b/layout/reftests/canvas/dash-sanity.html @@ -0,0 +1,85 @@ + + + + + +
+ + diff --git a/layout/reftests/canvas/reftest.list b/layout/reftests/canvas/reftest.list index 1ccaac7acb2a..59d4e03e9eb1 100644 --- a/layout/reftests/canvas/reftest.list +++ b/layout/reftests/canvas/reftest.list @@ -57,6 +57,9 @@ fails-if(cocoaWidget) == linear-gradient-1b.html linear-gradient-1-ref.html == evenodd-fill-2.html evenodd-fill-ref.html == evenodd-fill-3.html nonzero-fill-2.html +== dash-sanity.html data:text/html,Pass +== dash-1.html dash-1-ref.svg + == ctm-sanity.html data:text/html,Pass fails == ctm-singular-sanity.html data:text/html,Pass # Bug 612033 == ctm-1.html ctm-1-ref.html From e01163e2007f53b65f01ff0603b9d4e0d63a6bb2 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Wed, 29 Jun 2011 17:19:28 -0400 Subject: [PATCH 13/37] Bug 661927 - Add Cu.schedulePreciseGC to allow for a GC to run with no JS code running. r=mrbkap --- js/src/xpconnect/idl/xpccomponents.idl | 17 +++++++- js/src/xpconnect/src/xpccomponents.cpp | 39 +++++++++++++++++++ js/src/xpconnect/tests/chrome/Makefile.in | 1 + .../xpconnect/tests/chrome/test_precisegc.xul | 29 ++++++++++++++ 4 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 js/src/xpconnect/tests/chrome/test_precisegc.xul diff --git a/js/src/xpconnect/idl/xpccomponents.idl b/js/src/xpconnect/idl/xpccomponents.idl index 2e0ad7b2a0a4..cda16f72cfd7 100644 --- a/js/src/xpconnect/idl/xpccomponents.idl +++ b/js/src/xpconnect/idl/xpccomponents.idl @@ -120,10 +120,19 @@ interface nsIXPCComponents_utils_Sandbox : nsISupports { }; +/** + * interface for callback to be passed to Cu.schedulePreciseGC + */ +[scriptable, function, uuid(71000535-b0fd-44d1-8ce0-909760e3953c)] +interface ScheduledGCCallback : nsISupports +{ + void callback(); +}; + /** * interface of Components.utils */ -[scriptable, uuid(5f0acf45-135a-48d1-976c-082ce3b24ead)] +[scriptable, uuid(fed2d752-6cb3-4135-97b0-2c290e541e2d)] interface nsIXPCComponents_Utils : nsISupports { @@ -228,6 +237,12 @@ interface nsIXPCComponents_Utils : nsISupports */ void forceGC(); + /* + * Schedule a garbage collection cycle for a point in the future when no JS + * is running. Call the provided function once this has occurred. + */ + void schedulePreciseGC(in ScheduledGCCallback callback); + /* * To be called from JS only. * diff --git a/js/src/xpconnect/src/xpccomponents.cpp b/js/src/xpconnect/src/xpccomponents.cpp index 0e8cb62b95ad..4779e6fb09d9 100644 --- a/js/src/xpconnect/src/xpccomponents.cpp +++ b/js/src/xpconnect/src/xpccomponents.cpp @@ -55,6 +55,7 @@ #include "nsNullPrincipal.h" #include "nsJSUtils.h" #include "mozJSComponentLoader.h" +#include "nsContentUtils.h" /***************************************************************************/ // stuff used by all @@ -3775,6 +3776,44 @@ nsXPCComponents_Utils::ForceGC() return NS_OK; } +class PreciseGCRunnable : public nsRunnable +{ + public: + PreciseGCRunnable(ScheduledGCCallback* aCallback) + : mCallback(aCallback) {} + + NS_IMETHOD Run() + { + nsCOMPtr runtimeSvc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1"); + NS_ENSURE_STATE(runtimeSvc); + + JSRuntime* rt = nsnull; + runtimeSvc->GetRuntime(&rt); + NS_ENSURE_STATE(rt); + + JSContext *cx; + JSContext *iter = nsnull; + while ((cx = js_ContextIterator(rt, JS_FALSE, &iter)) != NULL) { + if (JS_IsRunning(cx)) { + return NS_DispatchToMainThread(this); + } + } + mCallback->Callback(); + return NS_OK; + } + + private: + nsRefPtr mCallback; +}; + +/* void schedulePreciseGC(in ScheduledGCCallback callback); */ +NS_IMETHODIMP +nsXPCComponents_Utils::SchedulePreciseGC(ScheduledGCCallback* aCallback) +{ + nsRefPtr event = new PreciseGCRunnable(aCallback); + return NS_DispatchToMainThread(event); +} + /* void getGlobalForObject(); */ NS_IMETHODIMP nsXPCComponents_Utils::GetGlobalForObject() diff --git a/js/src/xpconnect/tests/chrome/Makefile.in b/js/src/xpconnect/tests/chrome/Makefile.in index 020dd6063f62..f7bec21c9b2e 100644 --- a/js/src/xpconnect/tests/chrome/Makefile.in +++ b/js/src/xpconnect/tests/chrome/Makefile.in @@ -66,6 +66,7 @@ _CHROME_FILES = \ test_bug596580.xul \ test_bug654370.xul \ test_bug658560.xul \ + test_precisegc.xul \ $(NULL) # Disabled until this test gets updated to test the new proxy based diff --git a/js/src/xpconnect/tests/chrome/test_precisegc.xul b/js/src/xpconnect/tests/chrome/test_precisegc.xul new file mode 100644 index 000000000000..aa956a421062 --- /dev/null +++ b/js/src/xpconnect/tests/chrome/test_precisegc.xul @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + From 198c9903aa24cffd3c8700699b6a5a5a94e98c9a Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Wed, 29 Jun 2011 17:24:47 -0400 Subject: [PATCH 14/37] Bug 668352 - Ensure TabParent::GetIMEEnabled always returns a value. r=blassey --- dom/ipc/TabParent.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 11fb64bed3c2..1cddde7eba92 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -514,8 +514,10 @@ bool TabParent::RecvGetIMEEnabled(PRUint32* aValue) { nsCOMPtr widget = GetWidget(); - if (!widget) + if (!widget) { + *aValue = nsIWidget::IME_STATUS_DISABLED; return true; + } IMEContext context; widget->GetInputMode(context); From 58df7199e03d84be2361db5ee226c56a74ea272a Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Wed, 29 Jun 2011 14:39:21 -0700 Subject: [PATCH 15/37] Back out changeset 85e5b0ed7081, which was landed with the wrong bug number (really bug 667947, but marked as bug 667948) in order to reland it. --- content/canvas/src/nsCanvasRenderingContext2D.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp index f1253cf7c5f2..9dcd9b11fd49 100644 --- a/content/canvas/src/nsCanvasRenderingContext2D.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp @@ -2622,7 +2622,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessor : public nsBidiPresUtils::BidiProces mBoundingBox = mBoundingBox.Union(textRunMetrics.mBoundingBox); } - return NSToCoordRound(textRunMetrics.mAdvanceWidth); + return static_cast(textRunMetrics.mAdvanceWidth/gfxFloat(mAppUnitsPerDevPixel)); } virtual void DrawText(nscoord xOffset, nscoord width) @@ -2773,7 +2773,7 @@ nsCanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText, processor.mFontgrp = GetCurrentFontStyle(); NS_ASSERTION(processor.mFontgrp, "font group is null"); - nscoord totalWidthCoord; + nscoord totalWidth; // calls bidi algo twice since it needs the full text width and the // bounding boxes before rendering anything @@ -2785,13 +2785,12 @@ nsCanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText, nsBidiPresUtils::MODE_MEASURE, nsnull, 0, - &totalWidthCoord); + &totalWidth); if (NS_FAILED(rv)) return rv; - float totalWidth = float(totalWidthCoord) / processor.mAppUnitsPerDevPixel; if (aWidth) - *aWidth = totalWidth; + *aWidth = static_cast(totalWidth); // if only measuring, don't need to do any more work if (aOp==TEXT_DRAW_OPERATION_MEASURE) From 362567a30a7fc4c0db63cdd1e3ffd1782b563542 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Wed, 29 Jun 2011 14:39:21 -0700 Subject: [PATCH 16/37] Convert canvas text measurement widths from app units to pixels *after* they switch from integers to floats. (Bug 667947) r=roc --- content/canvas/src/nsCanvasRenderingContext2D.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp index 9dcd9b11fd49..f1253cf7c5f2 100644 --- a/content/canvas/src/nsCanvasRenderingContext2D.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp @@ -2622,7 +2622,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessor : public nsBidiPresUtils::BidiProces mBoundingBox = mBoundingBox.Union(textRunMetrics.mBoundingBox); } - return static_cast(textRunMetrics.mAdvanceWidth/gfxFloat(mAppUnitsPerDevPixel)); + return NSToCoordRound(textRunMetrics.mAdvanceWidth); } virtual void DrawText(nscoord xOffset, nscoord width) @@ -2773,7 +2773,7 @@ nsCanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText, processor.mFontgrp = GetCurrentFontStyle(); NS_ASSERTION(processor.mFontgrp, "font group is null"); - nscoord totalWidth; + nscoord totalWidthCoord; // calls bidi algo twice since it needs the full text width and the // bounding boxes before rendering anything @@ -2785,12 +2785,13 @@ nsCanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText, nsBidiPresUtils::MODE_MEASURE, nsnull, 0, - &totalWidth); + &totalWidthCoord); if (NS_FAILED(rv)) return rv; + float totalWidth = float(totalWidthCoord) / processor.mAppUnitsPerDevPixel; if (aWidth) - *aWidth = static_cast(totalWidth); + *aWidth = totalWidth; // if only measuring, don't need to do any more work if (aOp==TEXT_DRAW_OPERATION_MEASURE) From 17c6a77daf441e6ba6f8ed3db61ea5d2e50f5091 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Wed, 29 Jun 2011 14:39:21 -0700 Subject: [PATCH 17/37] Make nsMenuFrame::SizeToPopup consider its own border/padding properly, by increasing the popup's content's width by the larger of its own border/padding or the popup's scrollbar, rather than only the latter. (Bug 623922) r=enndeakin --- layout/xul/base/src/nsMenuFrame.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/layout/xul/base/src/nsMenuFrame.cpp b/layout/xul/base/src/nsMenuFrame.cpp index 96621ca0d0e8..205cf1ecc76c 100644 --- a/layout/xul/base/src/nsMenuFrame.cpp +++ b/layout/xul/base/src/nsMenuFrame.cpp @@ -1384,14 +1384,27 @@ nsMenuFrame::SizeToPopup(nsBoxLayoutState& aState, nsSize& aSize) if (!mPopupFrame) return PR_FALSE; tmpSize = mPopupFrame->GetPrefSize(aState); - aSize.width = tmpSize.width; + + // Produce a size such that: + // (1) the menu and its popup can be the same width + // (2) there's enough room in the menu for the content and its + // border-padding + // (3) there's enough room in the popup for the content and its + // scrollbar + nsMargin borderPadding; + GetBorderAndPadding(borderPadding); // if there is a scroll frame, add the desired width of the scrollbar as well nsIScrollableFrame* scrollFrame = do_QueryFrame(mPopupFrame->GetFirstChild(nsnull)); + nscoord scrollbarWidth = 0; if (scrollFrame) { - aSize.width += scrollFrame->GetDesiredScrollbarSizes(&aState).LeftRight(); + scrollbarWidth = + scrollFrame->GetDesiredScrollbarSizes(&aState).LeftRight(); } + aSize.width = + tmpSize.width + NS_MAX(borderPadding.LeftRight(), scrollbarWidth); + return PR_TRUE; } } From 391757ac7f7f897e38583f29513f5cb84677b922 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Wed, 29 Jun 2011 14:39:21 -0700 Subject: [PATCH 18/37] Add reftests for bug 623922. menulist-shrinkwrap-1 tests one of the important characteristics of the fix: that the intrinsic size of a menulist doesn't depend on which item is selected. It passes both with and without the patch, across platforms. menulist-shrinkwrap-2 tests the actual bug being fixed: that a menulist at its intrinsic size doesn't truncate some of the items with "...". It passes on Mac OS X with and without this patch. This patch changes it from failing to passing on Linux. It fails on Windows XP and Windows 7 both with and without the patch, although the patch slightly reduces the amount of text truncated on Windows 7, from "long i..." to "long it...", although it's constant at "long i..." on Windows XP. --- .../xul/menulist-shrinkwrap-1-ref.xul | 9 +++++++ layout/reftests/xul/menulist-shrinkwrap-1.xul | 9 +++++++ .../xul/menulist-shrinkwrap-2-ref.xul | 24 +++++++++++++++++++ layout/reftests/xul/menulist-shrinkwrap-2.xul | 24 +++++++++++++++++++ layout/reftests/xul/reftest.list | 2 ++ 5 files changed, 68 insertions(+) create mode 100644 layout/reftests/xul/menulist-shrinkwrap-1-ref.xul create mode 100644 layout/reftests/xul/menulist-shrinkwrap-1.xul create mode 100644 layout/reftests/xul/menulist-shrinkwrap-2-ref.xul create mode 100644 layout/reftests/xul/menulist-shrinkwrap-2.xul diff --git a/layout/reftests/xul/menulist-shrinkwrap-1-ref.xul b/layout/reftests/xul/menulist-shrinkwrap-1-ref.xul new file mode 100644 index 000000000000..7c85e4c6b07a --- /dev/null +++ b/layout/reftests/xul/menulist-shrinkwrap-1-ref.xul @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/layout/reftests/xul/menulist-shrinkwrap-1.xul b/layout/reftests/xul/menulist-shrinkwrap-1.xul new file mode 100644 index 000000000000..c7141814fa69 --- /dev/null +++ b/layout/reftests/xul/menulist-shrinkwrap-1.xul @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/layout/reftests/xul/menulist-shrinkwrap-2-ref.xul b/layout/reftests/xul/menulist-shrinkwrap-2-ref.xul new file mode 100644 index 000000000000..dc8e56d70871 --- /dev/null +++ b/layout/reftests/xul/menulist-shrinkwrap-2-ref.xul @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + diff --git a/layout/reftests/xul/menulist-shrinkwrap-2.xul b/layout/reftests/xul/menulist-shrinkwrap-2.xul new file mode 100644 index 000000000000..fa7b2167844e --- /dev/null +++ b/layout/reftests/xul/menulist-shrinkwrap-2.xul @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + diff --git a/layout/reftests/xul/reftest.list b/layout/reftests/xul/reftest.list index c0512a0c13aa..37299484446d 100644 --- a/layout/reftests/xul/reftest.list +++ b/layout/reftests/xul/reftest.list @@ -1 +1,3 @@ == menuitem-key.xul menuitem-key-ref.xul +== menulist-shrinkwrap-1.xul menulist-shrinkwrap-1-ref.xul +fails-if(winWidget) == menulist-shrinkwrap-2.xul menulist-shrinkwrap-2-ref.xul From 4f2850eae45bb0d3579d4b7c588a4825aa7ff48f Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Wed, 29 Jun 2011 14:39:21 -0700 Subject: [PATCH 19/37] Don't assert when interpolating font-weight to a result less than 100. (Bug 664927) r=bzbarsky --- layout/style/nsStyleAnimation.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/layout/style/nsStyleAnimation.cpp b/layout/style/nsStyleAnimation.cpp index 7db5f530b185..8bc753994573 100644 --- a/layout/style/nsStyleAnimation.cpp +++ b/layout/style/nsStyleAnimation.cpp @@ -1422,13 +1422,12 @@ nsStyleAnimation::AddWeighted(nsCSSProperty aProperty, PRInt32 result = NS_floor(aCoeff1 * double(aValue1.GetIntValue()) + aCoeff2 * double(aValue2.GetIntValue())); if (aProperty == eCSSProperty_font_weight) { - NS_ASSERTION(result > 0, "unexpected value"); - result -= result % 100; if (result < 100) { result = 100; } else if (result > 900) { result = 900; } + result -= result % 100; } else { result = RestrictValue(aProperty, result); } From 2dd9a8ab37152f86de143673dcd1831edeae3ce6 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Wed, 29 Jun 2011 14:39:21 -0700 Subject: [PATCH 20/37] Remove NS_STYLE_LIST_STYLE_OLD_* constants to fix computed list-style-type style resulting from type attribute on lists. (Bug 665857) r=bzbarsky --- content/html/content/src/nsHTMLLIElement.cpp | 11 +-- .../html/content/src/nsHTMLOListElement.cpp | 14 +-- layout/base/nsStyleConsts.h | 5 -- layout/generic/nsBulletFrame.cpp | 15 ---- layout/style/test/Makefile.in | 1 + .../test_html_attribute_computed_values.html | 85 +++++++++++++++++++ 6 files changed, 99 insertions(+), 32 deletions(-) create mode 100644 layout/style/test/test_html_attribute_computed_values.html diff --git a/content/html/content/src/nsHTMLLIElement.cpp b/content/html/content/src/nsHTMLLIElement.cpp index 967204245dd1..728b12542e16 100644 --- a/content/html/content/src/nsHTMLLIElement.cpp +++ b/content/html/content/src/nsHTMLLIElement.cpp @@ -108,7 +108,7 @@ NS_IMPL_ELEMENT_CLONE(nsHTMLLIElement) NS_IMPL_STRING_ATTR(nsHTMLLIElement, Type, type) NS_IMPL_INT_ATTR(nsHTMLLIElement, Value, value) - +// values that are handled case-insensitively static const nsAttrValue::EnumTable kUnorderedListItemTypeTable[] = { { "disc", NS_STYLE_LIST_STYLE_DISC }, { "circle", NS_STYLE_LIST_STYLE_CIRCLE }, @@ -117,11 +117,12 @@ static const nsAttrValue::EnumTable kUnorderedListItemTypeTable[] = { { 0 } }; +// values that are handled case-sensitively static const nsAttrValue::EnumTable kOrderedListItemTypeTable[] = { - { "A", NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA }, - { "a", NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA }, - { "I", NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN }, - { "i", NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN }, + { "A", NS_STYLE_LIST_STYLE_UPPER_ALPHA }, + { "a", NS_STYLE_LIST_STYLE_LOWER_ALPHA }, + { "I", NS_STYLE_LIST_STYLE_UPPER_ROMAN }, + { "i", NS_STYLE_LIST_STYLE_LOWER_ROMAN }, { "1", NS_STYLE_LIST_STYLE_DECIMAL }, { 0 } }; diff --git a/content/html/content/src/nsHTMLOListElement.cpp b/content/html/content/src/nsHTMLOListElement.cpp index 2011fcf942d3..4bd2635ce412 100644 --- a/content/html/content/src/nsHTMLOListElement.cpp +++ b/content/html/content/src/nsHTMLOListElement.cpp @@ -148,7 +148,7 @@ NS_IMPL_BOOL_ATTR(nsHTMLSharedListElement, Compact, compact) NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLSharedListElement, Start, start, 1) NS_IMPL_STRING_ATTR(nsHTMLSharedListElement, Type, type) - +// Shared with nsHTMLSharedElement.cpp nsAttrValue::EnumTable kListTypeTable[] = { { "none", NS_STYLE_LIST_STYLE_NONE }, { "disc", NS_STYLE_LIST_STYLE_DISC }, @@ -163,12 +163,12 @@ nsAttrValue::EnumTable kListTypeTable[] = { { 0 } }; -nsAttrValue::EnumTable kOldListTypeTable[] = { - { "1", NS_STYLE_LIST_STYLE_OLD_DECIMAL }, - { "A", NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA }, - { "a", NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA }, - { "I", NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN }, - { "i", NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN }, +static const nsAttrValue::EnumTable kOldListTypeTable[] = { + { "1", NS_STYLE_LIST_STYLE_DECIMAL }, + { "A", NS_STYLE_LIST_STYLE_UPPER_ALPHA }, + { "a", NS_STYLE_LIST_STYLE_LOWER_ALPHA }, + { "I", NS_STYLE_LIST_STYLE_UPPER_ROMAN }, + { "i", NS_STYLE_LIST_STYLE_LOWER_ROMAN }, { 0 } }; diff --git a/layout/base/nsStyleConsts.h b/layout/base/nsStyleConsts.h index 654163c724e8..ed32bdf74198 100644 --- a/layout/base/nsStyleConsts.h +++ b/layout/base/nsStyleConsts.h @@ -557,11 +557,6 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) { #define NS_STYLE_LIST_STYLE_KATAKANA 16 #define NS_STYLE_LIST_STYLE_HIRAGANA_IROHA 17 #define NS_STYLE_LIST_STYLE_KATAKANA_IROHA 18 -#define NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN 19 -#define NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN 20 -#define NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA 21 -#define NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA 22 -#define NS_STYLE_LIST_STYLE_OLD_DECIMAL 23 #define NS_STYLE_LIST_STYLE_MOZ_CJK_HEAVENLY_STEM 24 #define NS_STYLE_LIST_STYLE_MOZ_CJK_EARTHLY_BRANCH 25 #define NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_INFORMAL 26 diff --git a/layout/generic/nsBulletFrame.cpp b/layout/generic/nsBulletFrame.cpp index f9260f35b4d2..f27aac01b60c 100644 --- a/layout/generic/nsBulletFrame.cpp +++ b/layout/generic/nsBulletFrame.cpp @@ -335,16 +335,11 @@ nsBulletFrame::PaintBullet(nsRenderingContext& aRenderingContext, nsPoint aPt, break; case NS_STYLE_LIST_STYLE_DECIMAL: - case NS_STYLE_LIST_STYLE_OLD_DECIMAL: case NS_STYLE_LIST_STYLE_DECIMAL_LEADING_ZERO: case NS_STYLE_LIST_STYLE_LOWER_ROMAN: case NS_STYLE_LIST_STYLE_UPPER_ROMAN: case NS_STYLE_LIST_STYLE_LOWER_ALPHA: case NS_STYLE_LIST_STYLE_UPPER_ALPHA: - case NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN: - case NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN: - case NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA: - case NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA: case NS_STYLE_LIST_STYLE_LOWER_GREEK: case NS_STYLE_LIST_STYLE_HEBREW: case NS_STYLE_LIST_STYLE_ARMENIAN: @@ -1062,7 +1057,6 @@ nsBulletFrame::AppendCounterText(PRInt32 aListStyleType, break; case NS_STYLE_LIST_STYLE_DECIMAL: - case NS_STYLE_LIST_STYLE_OLD_DECIMAL: default: // CSS2 say "A users agent that does not recognize a numbering system // should use 'decimal' success = DecimalToText(aOrdinal, result); @@ -1073,23 +1067,19 @@ nsBulletFrame::AppendCounterText(PRInt32 aListStyleType, break; case NS_STYLE_LIST_STYLE_LOWER_ROMAN: - case NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN: success = RomanToText(aOrdinal, result, gLowerRomanCharsA, gLowerRomanCharsB); break; case NS_STYLE_LIST_STYLE_UPPER_ROMAN: - case NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN: success = RomanToText(aOrdinal, result, gUpperRomanCharsA, gUpperRomanCharsB); break; case NS_STYLE_LIST_STYLE_LOWER_ALPHA: - case NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA: success = CharListToText(aOrdinal, result, gLowerAlphaChars, ALPHA_SIZE); break; case NS_STYLE_LIST_STYLE_UPPER_ALPHA: - case NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA: success = CharListToText(aOrdinal, result, gUpperAlphaChars, ALPHA_SIZE); break; @@ -1371,15 +1361,10 @@ nsBulletFrame::GetDesiredSize(nsPresContext* aCX, default: case NS_STYLE_LIST_STYLE_DECIMAL_LEADING_ZERO: case NS_STYLE_LIST_STYLE_DECIMAL: - case NS_STYLE_LIST_STYLE_OLD_DECIMAL: case NS_STYLE_LIST_STYLE_LOWER_ROMAN: case NS_STYLE_LIST_STYLE_UPPER_ROMAN: case NS_STYLE_LIST_STYLE_LOWER_ALPHA: case NS_STYLE_LIST_STYLE_UPPER_ALPHA: - case NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN: - case NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN: - case NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA: - case NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA: case NS_STYLE_LIST_STYLE_KATAKANA: case NS_STYLE_LIST_STYLE_HIRAGANA: case NS_STYLE_LIST_STYLE_KATAKANA_IROHA: diff --git a/layout/style/test/Makefile.in b/layout/style/test/Makefile.in index 8bf14407e11a..cbd9108538f6 100644 --- a/layout/style/test/Makefile.in +++ b/layout/style/test/Makefile.in @@ -139,6 +139,7 @@ _TEST_FILES = test_acid3_test46.html \ test_dont_use_document_colors.html \ test_font_face_parser.html \ test_garbage_at_end_of_declarations.html \ + test_html_attribute_computed_values.html \ test_ident_escaping.html \ test_inherit_computation.html \ test_inherit_storage.html \ diff --git a/layout/style/test/test_html_attribute_computed_values.html b/layout/style/test/test_html_attribute_computed_values.html new file mode 100644 index 000000000000..bf4562b51f88 --- /dev/null +++ b/layout/style/test/test_html_attribute_computed_values.html @@ -0,0 +1,85 @@ + + + + + Test for Bug + + + + + +Mozilla Bug +
+
+
+
+ + From 71c07e9a9150037ad79138f8a18e0f4f85cfbc93 Mon Sep 17 00:00:00 2001 From: Wes Johnston Date: Wed, 29 Jun 2011 14:48:34 -0700 Subject: [PATCH 21/37] Bug 664287 - Disable the menubutton during the discoverability demo. r=mfinkle --- mobile/chrome/content/browser.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mobile/chrome/content/browser.js b/mobile/chrome/content/browser.js index 681c17dfd9f7..818a7b90c200 100644 --- a/mobile/chrome/content/browser.js +++ b/mobile/chrome/content/browser.js @@ -2194,6 +2194,10 @@ IdentityHandler.prototype = { * Click handler for the identity-box element in primary chrome. */ handleIdentityButtonEvent: function(aEvent) { + let broadcaster = document.getElementById("bcast_uidiscovery"); + if (broadcaster && broadcaster.getAttribute("mode") == "discovery") + return; + aEvent.stopPropagation(); if ((aEvent.type == "click" && aEvent.button != 0) || From aeccf070e0406d9d8b91b636b87c17103ffe67f4 Mon Sep 17 00:00:00 2001 From: Wes Johnston Date: Wed, 29 Jun 2011 14:48:36 -0700 Subject: [PATCH 22/37] Bug 668017 - Check for context menus before showing text selection. r=mbrubeck --- mobile/chrome/content/browser.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mobile/chrome/content/browser.js b/mobile/chrome/content/browser.js index 818a7b90c200..26bd765d4ed8 100644 --- a/mobile/chrome/content/browser.js +++ b/mobile/chrome/content/browser.js @@ -1754,13 +1754,13 @@ const ContentTouchHandler = { case "Browser:ContextMenu": // Long tap let contextMenu = { name: aMessage.name, json: json, target: aMessage.target }; - if (!SelectionHelper.showPopup(contextMenu)) { - if (ContextHelper.showPopup(contextMenu)) { - // Stop all input sequences - let event = document.createEvent("Events"); - event.initEvent("CancelTouchSequence", true, false); - document.dispatchEvent(event); - } + if (ContextHelper.showPopup(contextMenu)) { + // Stop all input sequences + let event = document.createEvent("Events"); + event.initEvent("CancelTouchSequence", true, false); + document.dispatchEvent(event); + } else { + SelectionHelper.showPopup(contextMenu); } break; case "Browser:CaptureEvents": { From a244c5e9adc44caea82e84480502e063c4d0fed4 Mon Sep 17 00:00:00 2001 From: Wes Johnston Date: Wed, 29 Jun 2011 14:48:38 -0700 Subject: [PATCH 23/37] Bug 662623 - If open, show the locale picker window when returning from background. r=mbrubeck --- mobile/chrome/content/localePicker.xul | 1 + mobile/components/BrowserCLH.js | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/mobile/chrome/content/localePicker.xul b/mobile/chrome/content/localePicker.xul index a89e90b768d4..e0da34a88183 100644 --- a/mobile/chrome/content/localePicker.xul +++ b/mobile/chrome/content/localePicker.xul @@ -5,6 +5,7 @@ - - - - - - - - - - From 8e02986af0f2540c69f76da148ac08ccbc82ef26 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Wed, 29 Jun 2011 16:15:27 -0700 Subject: [PATCH 26/37] Bug 668379 - Restore correct session history in Fennec's undo close tab [r=wesj] --- mobile/components/SessionStore.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/mobile/components/SessionStore.js b/mobile/components/SessionStore.js index ca4e67a87176..5a5a06a5e71c 100644 --- a/mobile/components/SessionStore.js +++ b/mobile/components/SessionStore.js @@ -441,7 +441,6 @@ SessionStore.prototype = { this._windows[aWindow.__SSID].selected = parseInt(index) + 1; // 1-based // Restore the resurrected browser - // * currently we only load the last URL into the browser if (aBrowser.__SS_restore) { let data = aBrowser.__SS_data; if (data.entries.length > 0) { @@ -634,13 +633,18 @@ SessionStore.prototype = { let closedTab = closedTabs.splice(aIndex, 1).shift(); // create a new tab and bring to front - let tab = aWindow.Browser.addTab(closedTab.entries[0].url, true); + let tab = aWindow.Browser.addTab(closedTab.entries[closedTab.index - 1].url, true); + + tab.browser.messageManager.sendAsyncMessage("WebNavigation:LoadURI", { + uri: closedTab.entries[closedTab.index - 1].url, + flags: null, + entries: closedTab.entries, + index: closedTab.index + }); // Put back the extra data tab.browser.__SS_extdata = closedTab.extData; - // TODO: save and restore more data (position, field values, etc) - return tab.chromeTab; }, From e16af51f51ac9d2f02b33e7390d332596b84e828 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Wed, 29 Jun 2011 16:20:22 -0700 Subject: [PATCH 27/37] Bug 668380 - browser.sessionstore.max_tabs_undo should default to 1 on mobile [r=wesj] --- mobile/app/mobile.js | 2 +- mobile/components/SessionStore.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/app/mobile.js b/mobile/app/mobile.js index 542e20581ee0..3b56e69558f9 100644 --- a/mobile/app/mobile.js +++ b/mobile/app/mobile.js @@ -137,7 +137,7 @@ pref("browser.sessionstore.resume_session_once", false); pref("browser.sessionstore.resume_from_crash", true); pref("browser.sessionstore.resume_from_crash_timeout", 60); // minutes pref("browser.sessionstore.interval", 10000); // milliseconds -pref("browser.sessionstore.max_tabs_undo", 5); +pref("browser.sessionstore.max_tabs_undo", 1); /* these should help performance */ pref("mozilla.widget.force-24bpp", true); diff --git a/mobile/components/SessionStore.js b/mobile/components/SessionStore.js index 5a5a06a5e71c..1e5c0a09d663 100644 --- a/mobile/components/SessionStore.js +++ b/mobile/components/SessionStore.js @@ -74,7 +74,7 @@ SessionStore.prototype = { _lastSaveTime: 0, _lastSessionTime: 0, _interval: 10000, - _maxTabsUndo: 5, + _maxTabsUndo: 1, _shouldRestore: false, init: function ss_init() { From 03b46a82e6a41ed2b5d62ee63196cf85df862742 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 30 Jun 2011 09:39:32 +1000 Subject: [PATCH 28/37] Bug 666075 - Add memory multi-reporters. r=khuey, sr=bz. --- dom/ipc/ContentChild.cpp | 92 ++++++++++++++----- .../aboutmemory/content/aboutMemory.js | 33 +++++-- .../tests/chrome/test_aboutmemory.xul | 31 +++++-- xpcom/base/nsIMemoryReporter.idl | 70 ++++++++++++-- xpcom/base/nsMemoryReporterManager.cpp | 49 +++++++++- xpcom/base/nsMemoryReporterManager.h | 5 +- 6 files changed, 232 insertions(+), 48 deletions(-) diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index c2cc22f10680..6a6a815be783 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -299,42 +299,92 @@ ContentChild::AllocPMemoryReportRequest() return new MemoryReportRequestChild(); } +// This is just a wrapper for InfallibleTArray that implements +// nsISupports, so it can be passed to nsIMemoryMultiReporter::CollectReports. +class MemoryReportsWrapper : public nsISupports { +public: + NS_DECL_ISUPPORTS + MemoryReportsWrapper(InfallibleTArray *r) : mReports(r) { } + InfallibleTArray *mReports; +}; +NS_IMPL_ISUPPORTS0(MemoryReportsWrapper) + +class MemoryReportCallback : public nsIMemoryMultiReporterCallback +{ +public: + NS_DECL_ISUPPORTS + + MemoryReportCallback(const nsACString &aProcess) + : mProcess(aProcess) + { + } + + NS_IMETHOD Callback(const nsACString &aProcess, const nsACString &aPath, + PRInt32 aKind, PRInt32 aUnits, PRInt64 aAmount, + const nsACString &aDescription, + nsISupports *aiWrappedReports) + { + MemoryReportsWrapper *wrappedReports = + static_cast(aiWrappedReports); + + MemoryReport memreport(mProcess, nsCString(aPath), aKind, aUnits, + aAmount, nsCString(aDescription)); + wrappedReports->mReports->AppendElement(memreport); + return NS_OK; + } +private: + const nsCString mProcess; +}; +NS_IMPL_ISUPPORTS1( + MemoryReportCallback +, nsIMemoryMultiReporterCallback +) + bool ContentChild::RecvPMemoryReportRequestConstructor(PMemoryReportRequestChild* child) { - InfallibleTArray reports; nsCOMPtr mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); - nsCOMPtr r; - mgr->EnumerateReporters(getter_AddRefs(r)); + InfallibleTArray reports; + + static const int maxLength = 31; // big enough; pid is only a few chars + nsPrintfCString process(maxLength, "Content (%d)", getpid()); + + // First do the vanilla memory reporters. + nsCOMPtr e; + mgr->EnumerateReporters(getter_AddRefs(e)); PRBool more; - while (NS_SUCCEEDED(r->HasMoreElements(&more)) && more) { - nsCOMPtr report; - r->GetNext(getter_AddRefs(report)); + while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) { + nsCOMPtr r; + e->GetNext(getter_AddRefs(r)); nsCString path; PRInt32 kind; PRInt32 units; - nsCString desc; PRInt64 amount; - report->GetPath(getter_Copies(path)); - report->GetKind(&kind); - report->GetUnits(&units); - report->GetAmount(&amount); - report->GetDescription(getter_Copies(desc)); - - static const int maxLength = 31; // big enough; pid is only a few chars - MemoryReport memreport(nsPrintfCString(maxLength, "Content (%d)", - getpid()), - path, - kind, - units, - amount, - desc); + nsCString desc; + r->GetPath(getter_Copies(path)); + r->GetKind(&kind); + r->GetUnits(&units); + r->GetAmount(&amount); + r->GetDescription(getter_Copies(desc)); + MemoryReport memreport(process, path, kind, units, amount, desc); reports.AppendElement(memreport); + } + // Then do the memory multi-reporters, by calling CollectReports on each + // one, whereupon the callback will turn each measurement into a + // MemoryReport. + mgr->EnumerateMultiReporters(getter_AddRefs(e)); + MemoryReportsWrapper wrappedReports(&reports); + MemoryReportCallback cb(process); + while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) { + nsCOMPtr r; + e->GetNext(getter_AddRefs(r)); + + r->CollectReports(&cb, &wrappedReports); } child->Send__delete__(child, reports); diff --git a/toolkit/components/aboutmemory/content/aboutMemory.js b/toolkit/components/aboutmemory/content/aboutMemory.js index fbe488961943..35f319808736 100644 --- a/toolkit/components/aboutmemory/content/aboutMemory.js +++ b/toolkit/components/aboutmemory/content/aboutMemory.js @@ -167,16 +167,16 @@ function update() // once before most of the memory required to generate this page is // allocated. var reportersByProcess = {}; - var e = mgr.enumerateReporters(); - while (e.hasMoreElements()) { - var rOrig = e.getNext().QueryInterface(Ci.nsIMemoryReporter); - var process = rOrig.process === "" ? "Main" : rOrig.process; + + function addReporter(aProcess, aPath, aKind, aUnits, aAmount, aDescription) + { + var process = aProcess === "" ? "Main" : aProcess; var r = { - _path: rOrig.path, - _kind: rOrig.kind, - _units: rOrig.units, - _amount: rOrig.amount, - _description: rOrig.description + _path: aPath, + _kind: aKind, + _units: aUnits, + _amount: aAmount, + _description: aDescription }; if (!reportersByProcess[process]) { reportersByProcess[process] = {}; @@ -191,6 +191,19 @@ function update() } } + // Process vanilla reporters first, then multi-reporters. + var e = mgr.enumerateReporters(); + while (e.hasMoreElements()) { + var rOrig = e.getNext().QueryInterface(Ci.nsIMemoryReporter); + addReporter(rOrig.process, rOrig.path, rOrig.kind, rOrig.units, + rOrig.amount, rOrig.description); + } + var e = mgr.enumerateMultiReporters(); + while (e.hasMoreElements()) { + var r = e.getNext().QueryInterface(Ci.nsIMemoryMultiReporter); + r.collectReports(addReporter, null); + } + // Generate output for one process at a time. Always start with the // Main process. var text = genProcessText("Main", reportersByProcess["Main"]); @@ -242,7 +255,7 @@ function update() function cmp_amount(a, b) { if (a._units != b._units) - return b._units - a._units; + return a._units - b._units; // use the enum order from nsIMemoryReporter else return b._amount - a._amount; }; diff --git a/toolkit/components/aboutmemory/tests/chrome/test_aboutmemory.xul b/toolkit/components/aboutmemory/tests/chrome/test_aboutmemory.xul index e69df0d73ff1..c5ffaa33e0f6 100644 --- a/toolkit/components/aboutmemory/tests/chrome/test_aboutmemory.xul +++ b/toolkit/components/aboutmemory/tests/chrome/test_aboutmemory.xul @@ -18,17 +18,29 @@ var mgr = Cc["@mozilla.org/memory-reporter-manager;1"]. getService(Ci.nsIMemoryReporterManager); - // Remove all the real reporters; save them to restore at the end. + // Remove all the real reporters and multi-reporters; save them to + // restore at the end. var e = mgr.enumerateReporters(); var realReporters = []; var dummy = 0; while (e.hasMoreElements()) { - var mr = e.getNext().QueryInterface(Ci.nsIMemoryReporter); - // Get the memoryUsed field, even though we don't use it, just to test + var r = e.getNext().QueryInterface(Ci.nsIMemoryReporter); + // Get the |amount| field, even though we don't use it, just to test // that the reporter doesn't crash or anything. - dummy += mr.memoryUsed; - mgr.unregisterReporter(mr); - realReporters.push(mr); + dummy += r.amount; + mgr.unregisterReporter(r); + realReporters.push(r); + } + e = mgr.enumerateMultiReporters(); + var realMultiReporters = []; + var dummy = 0; + while (e.hasMoreElements()) { + var r = e.getNext().QueryInterface(Ci.nsIMemoryMultiReporter); + // Call collectReports, even though we don't use its results, just to + // test that the multi-reporter doesn't crash or anything. + r.collectReports(function(){}, null); + mgr.unregisterMultiReporter(r); + realMultiReporters.push(r); } // Setup various fake-but-deterministic reporters. @@ -224,14 +236,17 @@ Other Measurements\n\ function finish() { - // Unregister fake reporters, re-register the real reporters, just in - // case subsequent tests rely on them. + // Unregister fake reporters, re-register the real reporters and + // multi-reporters, just in case subsequent tests rely on them. for (var i = 0; i < fakeReporters.length; i++) { mgr.unregisterReporter(fakeReporters[i]); } for (var i = 0; i < realReporters.length; i++) { mgr.registerReporter(realReporters[i]); } + for (var i = 0; i < realMultiReporters.length; i++) { + mgr.registerMultiReporter(realMultiReporters[i]); + } SimpleTest.finish(); } diff --git a/xpcom/base/nsIMemoryReporter.idl b/xpcom/base/nsIMemoryReporter.idl index d577247a54b5..13f7bc4e1a87 100644 --- a/xpcom/base/nsIMemoryReporter.idl +++ b/xpcom/base/nsIMemoryReporter.idl @@ -40,6 +40,16 @@ interface nsISimpleEnumerator; +/* + * An nsIMemoryReporter reports a single memory measurement as an object. + * Use this when it makes sense to gather this measurement without gathering + * related measurements at the same time. + * + * Note that the |amount| field may be implemented as a function, and so + * accessing it can trigger significant computation; the other fields can + * be accessed without triggering this computation. (Compare and contrast + * this with nsIMemoryMultiReporter.) + */ [scriptable, uuid(37d18434-9819-4ce1-922f-15d8b63da066)] interface nsIMemoryReporter : nsISupports { @@ -133,7 +143,7 @@ interface nsIMemoryReporter : nsISupports /* * The numeric value reported by this memory reporter. */ - readonly attribute long long amount; + readonly attribute PRInt64 amount; /* * A human-readable description of this memory usage report. @@ -141,7 +151,34 @@ interface nsIMemoryReporter : nsISupports readonly attribute string description; }; -[scriptable, uuid(7c62de18-1edd-40f8-9da2-a8c622763074)] +[scriptable, function, uuid(5b15f3fa-ba15-443c-8337-7770f5f0ce5d)] +interface nsIMemoryMultiReporterCallback : nsISupports +{ + void callback(in ACString process, in AUTF8String path, in PRInt32 kind, + in PRInt32 units, in PRInt64 amount, + in AUTF8String description, in nsISupports closure); +}; + +/* + * An nsIMemoryMultiReporter reports multiple memory measurements via a + * callback function which is called once for each measurement. Use this + * when you want to gather multiple measurements in a single operation (eg. + * a single traversal of a large data structure). + * + * The arguments to the callback deliberately match the fields in + * nsIMemoryReporter, but note that seeing any of these arguments requires + * calling collectReports which will trigger all relevant computation. + * (Compare and contrast this with nsIMemoryReporter, which allows all + * fields except |amount| to be accessed without triggering computation.) + */ +[scriptable, uuid(eae277ad-b67d-4389-95f4-03fa11c09d06)] +interface nsIMemoryMultiReporter : nsISupports +{ + void collectReports(in nsIMemoryMultiReporterCallback callback, + in nsISupports closure); +}; + +[scriptable, uuid(80a93b4c-6fff-4acd-8598-3891074a30ab)] interface nsIMemoryReporterManager : nsISupports { /* @@ -150,18 +187,36 @@ interface nsIMemoryReporterManager : nsISupports nsISimpleEnumerator enumerateReporters (); /* - * Register the given nsIMemoryReporter. It is an error to register - * more than one reporter with the same path. After a reporter is - * registered, it will be available via enumerateReporters(). The - * Manager service will hold a strong reference to the given reporter. + * Return an enumerator of nsIMemoryMultiReporters that are currently + * registered. + */ + nsISimpleEnumerator enumerateMultiReporters (); + + /* + * Register the given nsIMemoryReporter. After a reporter is registered, + * it will be available via enumerateReporters(). The Manager service + * will hold a strong reference to the given reporter. */ void registerReporter (in nsIMemoryReporter reporter); + /* + * Register the given nsIMemoryMultiReporter. After a multi-reporter is + * registered, it will be available via enumerateMultiReporters(). The + * Manager service will hold a strong reference to the given + * multi-reporter. + */ + void registerMultiReporter (in nsIMemoryMultiReporter reporter); + /* * Unregister the given memory reporter. */ void unregisterReporter (in nsIMemoryReporter reporter); + /* + * Unregister the given memory multi-reporter. + */ + void unregisterMultiReporter (in nsIMemoryMultiReporter reporter); + /* * Initialize. */ @@ -189,6 +244,9 @@ interface nsIMemoryReporterManager : nsISupports #define NS_MEMORY_REPORTER_NAME(_classname) MemoryReporter_##_classname NS_COM nsresult NS_RegisterMemoryReporter (nsIMemoryReporter *reporter); +NS_COM nsresult NS_RegisterMemoryMultiReporter (nsIMemoryMultiReporter *reporter); + NS_COM nsresult NS_UnregisterMemoryReporter (nsIMemoryReporter *reporter); +NS_COM nsresult NS_UnregisterMemoryMultiReporter (nsIMemoryMultiReporter *reporter); %} diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp index 602b2e1b3e1b..88162a03f6d2 100644 --- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -437,6 +437,15 @@ nsMemoryReporterManager::EnumerateReporters(nsISimpleEnumerator **result) return rv; } +NS_IMETHODIMP +nsMemoryReporterManager::EnumerateMultiReporters(nsISimpleEnumerator **result) +{ + nsresult rv; + mozilla::MutexAutoLock autoLock(mMutex); + rv = NS_NewArrayEnumerator(result, mMultiReporters); + return rv; +} + NS_IMETHODIMP nsMemoryReporterManager::RegisterReporter(nsIMemoryReporter *reporter) { @@ -448,6 +457,17 @@ nsMemoryReporterManager::RegisterReporter(nsIMemoryReporter *reporter) return NS_OK; } +NS_IMETHODIMP +nsMemoryReporterManager::RegisterMultiReporter(nsIMemoryMultiReporter *reporter) +{ + mozilla::MutexAutoLock autoLock(mMutex); + if (mMultiReporters.IndexOf(reporter) != -1) + return NS_ERROR_FAILURE; + + mMultiReporters.AppendObject(reporter); + return NS_OK; +} + NS_IMETHODIMP nsMemoryReporterManager::UnregisterReporter(nsIMemoryReporter *reporter) { @@ -458,6 +478,16 @@ nsMemoryReporterManager::UnregisterReporter(nsIMemoryReporter *reporter) return NS_OK; } +NS_IMETHODIMP +nsMemoryReporterManager::UnregisterMultiReporter(nsIMemoryMultiReporter *reporter) +{ + mozilla::MutexAutoLock autoLock(mMutex); + if (!mMultiReporters.RemoveObject(reporter)) + return NS_ERROR_FAILURE; + + return NS_OK; +} + NS_IMPL_ISUPPORTS1(nsMemoryReporter, nsIMemoryReporter) nsMemoryReporter::nsMemoryReporter(nsCString& process, @@ -515,7 +545,6 @@ NS_IMETHODIMP nsMemoryReporter::GetDescription(char **aDescription) return NS_OK; } - NS_COM nsresult NS_RegisterMemoryReporter (nsIMemoryReporter *reporter) { @@ -525,6 +554,15 @@ NS_RegisterMemoryReporter (nsIMemoryReporter *reporter) return mgr->RegisterReporter(reporter); } +NS_COM nsresult +NS_RegisterMemoryMultiReporter (nsIMemoryMultiReporter *reporter) +{ + nsCOMPtr mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); + if (mgr == nsnull) + return NS_ERROR_FAILURE; + return mgr->RegisterMultiReporter(reporter); +} + NS_COM nsresult NS_UnregisterMemoryReporter (nsIMemoryReporter *reporter) { @@ -534,3 +572,12 @@ NS_UnregisterMemoryReporter (nsIMemoryReporter *reporter) return mgr->UnregisterReporter(reporter); } +NS_COM nsresult +NS_UnregisterMemoryMultiReporter (nsIMemoryMultiReporter *reporter) +{ + nsCOMPtr mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); + if (mgr == nsnull) + return NS_ERROR_FAILURE; + return mgr->UnregisterMultiReporter(reporter); +} + diff --git a/xpcom/base/nsMemoryReporterManager.h b/xpcom/base/nsMemoryReporterManager.h index 81da08146b06..f54a680cab9f 100644 --- a/xpcom/base/nsMemoryReporterManager.h +++ b/xpcom/base/nsMemoryReporterManager.h @@ -40,8 +40,9 @@ public: virtual ~nsMemoryReporterManager(); private: - nsCOMArray mReporters; - Mutex mMutex; + nsCOMArray mReporters; + nsCOMArray mMultiReporters; + Mutex mMutex; }; #define NS_MEMORY_REPORTER_MANAGER_CID \ From 5b09fc8a8b379eeba322898794ccc154f158ab3c Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Thu, 30 Jun 2011 02:56:49 +0200 Subject: [PATCH 29/37] Bug 666669 - Restrict selection painting to the nsCharClipDisplayItem edges (same as for non-selected text). r=roc --- layout/generic/nsTextFrame.h | 6 ++ layout/generic/nsTextFrameThebes.cpp | 84 ++++++++++++++++------------ 2 files changed, 54 insertions(+), 36 deletions(-) diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index 7e70555fd21f..bf287655980e 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -317,6 +317,8 @@ public: const gfxPoint& aTextBaselinePt, const gfxRect& aDirtyRect, PropertyProvider& aProvider, + PRUint32 aContentOffset, + PRUint32 aContentLength, nsTextPaintStyle& aTextPaintStyle, const nsCharClipDisplayItem::ClipEdges& aClipEdges); // helper: paint text with foreground and background colors determined @@ -327,6 +329,8 @@ public: const gfxPoint& aTextBaselinePt, const gfxRect& aDirtyRect, PropertyProvider& aProvider, + PRUint32 aContentOffset, + PRUint32 aContentLength, nsTextPaintStyle& aTextPaintStyle, SelectionDetails* aDetails, SelectionType* aAllTypes); @@ -336,6 +340,8 @@ public: const gfxPoint& aTextBaselinePt, const gfxRect& aDirtyRect, PropertyProvider& aProvider, + PRUint32 aContentOffset, + PRUint32 aContentLength, nsTextPaintStyle& aTextPaintStyle, SelectionDetails* aDetails, SelectionType aSelectionType); diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index d0faed6784f5..f654d8115079 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -4661,10 +4661,14 @@ public: /** * aStart and aLength are in the original string. aSelectionDetails is * according to the original string. + * @param aXOffset the offset from the origin of the frame to the start + * of the text (the left baseline origin for LTR, the right baseline origin + * for RTL) */ SelectionIterator(SelectionDetails** aSelectionDetails, PRInt32 aStart, PRInt32 aLength, - PropertyProvider& aProvider, gfxTextRun* aTextRun); + PropertyProvider& aProvider, gfxTextRun* aTextRun, + gfxFloat aXOffset); /** * Returns the next segment of uniformly selected (or not) text. @@ -4698,11 +4702,11 @@ private: SelectionIterator::SelectionIterator(SelectionDetails** aSelectionDetails, PRInt32 aStart, PRInt32 aLength, PropertyProvider& aProvider, - gfxTextRun* aTextRun) + gfxTextRun* aTextRun, gfxFloat aXOffset) : mSelectionDetails(aSelectionDetails), mProvider(aProvider), mTextRun(aTextRun), mIterator(aProvider.GetStart()), mOriginalStart(aStart), mOriginalEnd(aStart + aLength), - mXOffset(mTextRun->IsRightToLeft() ? aProvider.GetFrame()->GetSize().width : 0) + mXOffset(aXOffset) { mIterator.SetOriginalOffset(aStart); } @@ -4842,29 +4846,28 @@ void nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx, const gfxPoint& aFramePt, const gfxPoint& aTextBaselinePt, const gfxRect& aDirtyRect, - PropertyProvider& aProvider, nsTextPaintStyle& aTextPaintStyle, - SelectionDetails* aDetails, SelectionType* aAllTypes) + PropertyProvider& aProvider, + PRUint32 aContentOffset, PRUint32 aContentLength, + nsTextPaintStyle& aTextPaintStyle, SelectionDetails* aDetails, + SelectionType* aAllTypes) { - PRInt32 contentOffset = aProvider.GetStart().GetOriginalOffset(); - PRInt32 contentLength = aProvider.GetOriginalLength(); - // Figure out which selections control the colors to use for each character. nsAutoTArray prevailingSelectionsBuffer; - if (!prevailingSelectionsBuffer.AppendElements(contentLength)) + if (!prevailingSelectionsBuffer.AppendElements(aContentLength)) return; SelectionDetails** prevailingSelections = prevailingSelectionsBuffer.Elements(); - PRInt32 i; SelectionType allTypes = 0; - for (i = 0; i < contentLength; ++i) { + for (PRUint32 i = 0; i < aContentLength; ++i) { prevailingSelections[i] = nsnull; } SelectionDetails *sdptr = aDetails; PRBool anyBackgrounds = PR_FALSE; while (sdptr) { - PRInt32 start = NS_MAX(0, sdptr->mStart - contentOffset); - PRInt32 end = NS_MIN(contentLength, sdptr->mEnd - contentOffset); + PRInt32 start = NS_MAX(0, sdptr->mStart - PRInt32(aContentOffset)); + PRInt32 end = NS_MIN(PRInt32(aContentLength), + sdptr->mEnd - PRInt32(aContentOffset)); SelectionType type = sdptr->mType; if (start < end) { allTypes |= type; @@ -4875,7 +4878,7 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx, if (NS_GET_A(background) > 0) { anyBackgrounds = PR_TRUE; } - for (i = start; i < end; ++i) { + for (PRInt32 i = start; i < end; ++i) { // Favour normal selection over IME selections if (!prevailingSelections[i] || type < prevailingSelections[i]->mType) { @@ -4888,14 +4891,15 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx, } *aAllTypes = allTypes; + const gfxFloat startXOffset = aTextBaselinePt.x - aFramePt.x; gfxFloat xOffset, hyphenWidth; PRUint32 offset, length; // in transformed string SelectionType type; nsTextRangeStyle rangeStyle; // Draw background colors if (anyBackgrounds) { - SelectionIterator iterator(prevailingSelections, contentOffset, contentLength, - aProvider, mTextRun); + SelectionIterator iterator(prevailingSelections, aContentOffset, aContentLength, + aProvider, mTextRun, startXOffset); while (iterator.GetNextSegment(&xOffset, &offset, &length, &hyphenWidth, &type, &rangeStyle)) { nscolor foreground, background; @@ -4915,8 +4919,8 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx, } // Draw text - SelectionIterator iterator(prevailingSelections, contentOffset, contentLength, - aProvider, mTextRun); + SelectionIterator iterator(prevailingSelections, aContentOffset, aContentLength, + aProvider, mTextRun, startXOffset); while (iterator.GetNextSegment(&xOffset, &offset, &length, &hyphenWidth, &type, &rangeStyle)) { nscolor foreground, background; @@ -4940,32 +4944,31 @@ void nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx, const gfxPoint& aFramePt, const gfxPoint& aTextBaselinePt, const gfxRect& aDirtyRect, - PropertyProvider& aProvider, nsTextPaintStyle& aTextPaintStyle, - SelectionDetails* aDetails, SelectionType aSelectionType) + PropertyProvider& aProvider, + PRUint32 aContentOffset, PRUint32 aContentLength, + nsTextPaintStyle& aTextPaintStyle, SelectionDetails* aDetails, + SelectionType aSelectionType) { // Hide text decorations if we're currently hiding @font-face fallback text if (aProvider.GetFontGroup()->ShouldSkipDrawing()) return; - PRInt32 contentOffset = aProvider.GetStart().GetOriginalOffset(); - PRInt32 contentLength = aProvider.GetOriginalLength(); - // Figure out which characters will be decorated for this selection. nsAutoTArray selectedCharsBuffer; - if (!selectedCharsBuffer.AppendElements(contentLength)) + if (!selectedCharsBuffer.AppendElements(aContentLength)) return; SelectionDetails** selectedChars = selectedCharsBuffer.Elements(); - PRInt32 i; - for (i = 0; i < contentLength; ++i) { + for (PRUint32 i = 0; i < aContentLength; ++i) { selectedChars[i] = nsnull; } SelectionDetails *sdptr = aDetails; while (sdptr) { if (sdptr->mType == aSelectionType) { - PRInt32 start = NS_MAX(0, sdptr->mStart - contentOffset); - PRInt32 end = NS_MIN(contentLength, sdptr->mEnd - contentOffset); - for (i = start; i < end; ++i) { + PRInt32 start = NS_MAX(0, sdptr->mStart - PRInt32(aContentOffset)); + PRInt32 end = NS_MIN(PRInt32(aContentLength), + sdptr->mEnd - PRInt32(aContentOffset)); + for (PRInt32 i = start; i < end; ++i) { selectedChars[i] = sdptr; } } @@ -4979,8 +4982,9 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx, decorationMetrics.underlineOffset = aProvider.GetFontGroup()->GetUnderlineOffset(); - SelectionIterator iterator(selectedChars, contentOffset, contentLength, - aProvider, mTextRun); + gfxFloat startXOffset = aTextBaselinePt.x - aFramePt.x; + SelectionIterator iterator(selectedChars, aContentOffset, aContentLength, + aProvider, mTextRun, startXOffset); gfxFloat xOffset, hyphenWidth; PRUint32 offset, length; PRInt32 app = aTextPaintStyle.PresContext()->AppUnitsPerDevPixel(); @@ -5008,7 +5012,8 @@ PRBool nsTextFrame::PaintTextWithSelection(gfxContext* aCtx, const gfxPoint& aFramePt, const gfxPoint& aTextBaselinePt, const gfxRect& aDirtyRect, - PropertyProvider& aProvider, nsTextPaintStyle& aTextPaintStyle, + PropertyProvider& aProvider, PRUint32 aContentOffset, PRUint32 aContentLength, + nsTextPaintStyle& aTextPaintStyle, const nsCharClipDisplayItem::ClipEdges& aClipEdges) { SelectionDetails* details = GetSelectionDetails(); @@ -5017,7 +5022,8 @@ nsTextFrame::PaintTextWithSelection(gfxContext* aCtx, SelectionType allTypes; PaintTextWithSelectionColors(aCtx, aFramePt, aTextBaselinePt, aDirtyRect, - aProvider, aTextPaintStyle, details, &allTypes); + aProvider, aContentOffset, aContentLength, + aTextPaintStyle, details, &allTypes); PaintTextDecorations(aCtx, aDirtyRect, aFramePt, aTextBaselinePt, aTextPaintStyle, aProvider, aClipEdges); PRInt32 i; @@ -5033,7 +5039,8 @@ nsTextFrame::PaintTextWithSelection(gfxContext* aCtx, // (there might not be any for this type but that's OK, // PaintTextSelectionDecorations will exit early). PaintTextSelectionDecorations(aCtx, aFramePt, aTextBaselinePt, aDirtyRect, - aProvider, aTextPaintStyle, details, type); + aProvider, aContentOffset, aContentLength, + aTextPaintStyle, details, type); } } @@ -5260,8 +5267,13 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt, aDirtyRect.width, aDirtyRect.height); // Fork off to the (slower) paint-with-selection path if necessary. if (nsLayoutUtils::GetNonGeneratedAncestor(this)->GetStateBits() & NS_FRAME_SELECTED_CONTENT) { - if (PaintTextWithSelection(ctx, framePt, textBaselinePt, - dirtyRect, provider, textPaintStyle, clipEdges)) + gfxSkipCharsIterator tmp(provider.GetStart()); + PRInt32 contentOffset = tmp.ConvertSkippedToOriginal(startOffset); + PRInt32 contentLength = + tmp.ConvertSkippedToOriginal(startOffset + maxLength) - contentOffset; + if (PaintTextWithSelection(ctx, framePt, textBaselinePt, dirtyRect, + provider, contentOffset, contentLength, + textPaintStyle, clipEdges)) return; } From 2e8bd5ee285316b4344589c591237feea50c48d8 Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Thu, 30 Jun 2011 02:56:49 +0200 Subject: [PATCH 30/37] Bug 666669 - Test rendering of selected text, background and selection decorations with text-overflow. r=roc --- layout/reftests/text-overflow/reftest.list | 1 + .../reftests/text-overflow/selection-ref.html | 113 ++++++++++++++++++ layout/reftests/text-overflow/selection.html | 111 +++++++++++++++++ 3 files changed, 225 insertions(+) create mode 100644 layout/reftests/text-overflow/selection-ref.html create mode 100644 layout/reftests/text-overflow/selection.html diff --git a/layout/reftests/text-overflow/reftest.list b/layout/reftests/text-overflow/reftest.list index 092c2fc144e3..0730e3f2c721 100644 --- a/layout/reftests/text-overflow/reftest.list +++ b/layout/reftests/text-overflow/reftest.list @@ -12,3 +12,4 @@ HTTP(..) == quirks-decorations.html quirks-decorations-ref.html HTTP(..) == quirks-line-height.html quirks-line-height-ref.html HTTP(..) == standards-decorations.html standards-decorations-ref.html HTTP(..) == standards-line-height.html standards-line-height-ref.html +HTTP(..) == selection.html selection-ref.html diff --git a/layout/reftests/text-overflow/selection-ref.html b/layout/reftests/text-overflow/selection-ref.html new file mode 100644 index 000000000000..f1c09750461e --- /dev/null +++ b/layout/reftests/text-overflow/selection-ref.html @@ -0,0 +1,113 @@ + + + +text-overflow: Selected text, background, decorations + + + + + + + +
+ + + + + + + + + + + + + + + diff --git a/layout/reftests/text-overflow/selection.html b/layout/reftests/text-overflow/selection.html new file mode 100644 index 000000000000..d8277f01e2aa --- /dev/null +++ b/layout/reftests/text-overflow/selection.html @@ -0,0 +1,111 @@ + + + +text-overflow: Selected text, background, decorations + + + + + + + + +
+ + + + + + + + + + + + + + From 91a8b3dfd6604dcc1162211aaada0ec5fcd3ebc7 Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Thu, 30 Jun 2011 02:56:50 +0200 Subject: [PATCH 31/37] Bug 667653 - Make NS_FRAME_SELECTED_CONTENT on text frames less sticky. r=roc --- layout/generic/nsTextFrame.h | 24 +++++++++-------- layout/generic/nsTextFrameThebes.cpp | 40 +++++++++++++++++++++------- 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index bf287655980e..2b402d5cc7d5 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -310,21 +310,23 @@ public: const nsCharClipDisplayItem::ClipEdges& aClipEdges, const nscolor* aOverrideColor = nsnull); // helper: paint text frame when we're impacted by at least one selection. - // Return PR_FALSE if the text was not painted and we should continue with + // Return false if the text was not painted and we should continue with // the fast path. - PRBool PaintTextWithSelection(gfxContext* aCtx, - const gfxPoint& aFramePt, - const gfxPoint& aTextBaselinePt, - const gfxRect& aDirtyRect, - PropertyProvider& aProvider, - PRUint32 aContentOffset, - PRUint32 aContentLength, - nsTextPaintStyle& aTextPaintStyle, - const nsCharClipDisplayItem::ClipEdges& aClipEdges); + bool PaintTextWithSelection(gfxContext* aCtx, + const gfxPoint& aFramePt, + const gfxPoint& aTextBaselinePt, + const gfxRect& aDirtyRect, + PropertyProvider& aProvider, + PRUint32 aContentOffset, + PRUint32 aContentLength, + nsTextPaintStyle& aTextPaintStyle, + const nsCharClipDisplayItem::ClipEdges& aClipEdges); // helper: paint text with foreground and background colors determined // by selection(s). Also computes a mask of all selection types applying to // our text, returned in aAllTypes. - void PaintTextWithSelectionColors(gfxContext* aCtx, + // Return false if the text was not painted and we should continue with + // the fast path. + bool PaintTextWithSelectionColors(gfxContext* aCtx, const gfxPoint& aFramePt, const gfxPoint& aTextBaselinePt, const gfxRect& aDirtyRect, diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index f654d8115079..99cc671a6763 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -4842,7 +4842,7 @@ nsTextFrame::PaintOneShadow(PRUint32 aOffset, PRUint32 aLength, // Paints selection backgrounds and text in the correct colors. Also computes // aAllTypes, the union of all selection types that are applying to this text. -void +bool nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx, const gfxPoint& aFramePt, const gfxPoint& aTextBaselinePt, const gfxRect& aDirtyRect, @@ -4854,7 +4854,7 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx, // Figure out which selections control the colors to use for each character. nsAutoTArray prevailingSelectionsBuffer; if (!prevailingSelectionsBuffer.AppendElements(aContentLength)) - return; + return false; SelectionDetails** prevailingSelections = prevailingSelectionsBuffer.Elements(); SelectionType allTypes = 0; @@ -4891,6 +4891,17 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx, } *aAllTypes = allTypes; + if (!allTypes) { + // Nothing is selected in the given text range. + if (aContentLength == aProvider.GetOriginalLength()) { + // It's the full text range so we can remove the FRAME_SELECTED_CONTENT + // bit to avoid going through this slow path until something is selected + // in this frame again. + RemoveStateBits(NS_FRAME_SELECTED_CONTENT); + } + return false; + } + const gfxFloat startXOffset = aTextBaselinePt.x - aFramePt.x; gfxFloat xOffset, hyphenWidth; PRUint32 offset, length; // in transformed string @@ -4938,6 +4949,7 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx, } iterator.UpdateWithAdvance(advance); } + return true; } void @@ -5008,7 +5020,7 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx, } } -PRBool +bool nsTextFrame::PaintTextWithSelection(gfxContext* aCtx, const gfxPoint& aFramePt, const gfxPoint& aTextBaselinePt, const gfxRect& aDirtyRect, @@ -5017,13 +5029,23 @@ nsTextFrame::PaintTextWithSelection(gfxContext* aCtx, const nsCharClipDisplayItem::ClipEdges& aClipEdges) { SelectionDetails* details = GetSelectionDetails(); - if (!details) - return PR_FALSE; + if (!details) { + if (aContentLength == aProvider.GetOriginalLength()) { + // It's the full text range so we can remove the FRAME_SELECTED_CONTENT + // bit to avoid going through this slow path until something is selected + // in this frame again. + RemoveStateBits(NS_FRAME_SELECTED_CONTENT); + } + return false; + } SelectionType allTypes; - PaintTextWithSelectionColors(aCtx, aFramePt, aTextBaselinePt, aDirtyRect, - aProvider, aContentOffset, aContentLength, - aTextPaintStyle, details, &allTypes); + if (!PaintTextWithSelectionColors(aCtx, aFramePt, aTextBaselinePt, aDirtyRect, + aProvider, aContentOffset, aContentLength, + aTextPaintStyle, details, &allTypes)) { + DestroySelectionDetails(details); + return false; + } PaintTextDecorations(aCtx, aDirtyRect, aFramePt, aTextBaselinePt, aTextPaintStyle, aProvider, aClipEdges); PRInt32 i; @@ -5045,7 +5067,7 @@ nsTextFrame::PaintTextWithSelection(gfxContext* aCtx, } DestroySelectionDetails(details); - return PR_TRUE; + return true; } nscolor From 4bd4a133969c07d2120896233a0278d11df31ec8 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Wed, 29 Jun 2011 17:58:15 -0700 Subject: [PATCH 32/37] Work around bug 668412: random-if() the test for bug 662038 for android. r=philor --HG-- extra : rebase_source : ee67d408511ae3b0438687d3b7d919c64788ece2 --- layout/reftests/canvas/reftest.list | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/reftests/canvas/reftest.list b/layout/reftests/canvas/reftest.list index 59d4e03e9eb1..4968d8d07769 100644 --- a/layout/reftests/canvas/reftest.list +++ b/layout/reftests/canvas/reftest.list @@ -58,7 +58,7 @@ fails-if(cocoaWidget) == linear-gradient-1b.html linear-gradient-1-ref.html == evenodd-fill-3.html nonzero-fill-2.html == dash-sanity.html data:text/html,Pass -== dash-1.html dash-1-ref.svg +random-if(Android) == dash-1.html dash-1-ref.svg # Bug 668412 (really is android-specific, not IPC-specific) == ctm-sanity.html data:text/html,Pass fails == ctm-singular-sanity.html data:text/html,Pass # Bug 612033 From 48cda824f26f45a5acf9c1744223083e750c7b9c Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Thu, 30 Jun 2011 03:00:12 +0200 Subject: [PATCH 33/37] Bug 667298: Allow taskbar previews to explicitly create a thebes canvas. r=roc --- layout/build/nsLayoutCID.h | 4 ++++ layout/build/nsLayoutModule.cpp | 5 +++++ widget/src/windows/TaskbarPreview.cpp | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/layout/build/nsLayoutCID.h b/layout/build/nsLayoutCID.h index b18ccd4445c8..af09a6cf2732 100644 --- a/layout/build/nsLayoutCID.h +++ b/layout/build/nsLayoutCID.h @@ -91,6 +91,10 @@ #define NS_CANVASRENDERINGCONTEXT2D_CID \ { 0xa35d1cd4, 0xc505, 0x4d2d, { 0xa0, 0xf9, 0xae, 0xf0, 0x0b, 0x7c, 0xe5, 0xa5 } } +// {BCD923C0-9788-4350-AC48-365F473161EB} +#define NS_CANVASRENDERINGCONTEXT2DTHEBES_CID \ +{ 0xbcd923c0, 0x9788, 0x4350, { 0xac, 0x48, 0x36, 0x5f, 0x47, 0x31, 0x61, 0xeb } } + // {9052bb12-79b0-4bdd-8e60-7bf078026b6d} #define NS_CANVASRENDERINGCONTEXT2DAZURE_CID \ {0x9052bb12, 0x79b0, 0x4bdd, {0x8e, 0x60, 0x7b, 0xf0, 0x78, 0x02, 0x6b, 0x6d}} diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index 53aa9bc4db29..c5e66a481992 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -440,6 +440,7 @@ nsresult NS_NewTreeBoxObject(nsIBoxObject** aResult); #endif nsresult NS_NewCanvasRenderingContext2D(nsIDOMCanvasRenderingContext2D** aResult); +nsresult NS_NewCanvasRenderingContext2DThebes(nsIDOMCanvasRenderingContext2D** aResult); nsresult NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult); nsresult NS_CreateFrameTraversal(nsIFrameTraversal** aResult); @@ -568,6 +569,7 @@ MAKE_CTOR(CreateVideoDocument, nsIDocument, NS_NewVid MAKE_CTOR(CreateFocusManager, nsIFocusManager, NS_NewFocusManager) MAKE_CTOR(CreateCanvasRenderingContext2D, nsIDOMCanvasRenderingContext2D, NS_NewCanvasRenderingContext2D) +MAKE_CTOR(CreateCanvasRenderingContext2DThebes, nsIDOMCanvasRenderingContext2D, NS_NewCanvasRenderingContext2DThebes) MAKE_CTOR(CreateCanvasRenderingContextWebGL, nsIDOMWebGLRenderingContext, NS_NewCanvasRenderingContextWebGL) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStyleSheetService, Init) @@ -771,6 +773,7 @@ NS_DEFINE_NAMED_CID(NS_HTMLOPTIONELEMENT_CID); NS_DEFINE_NAMED_CID(NS_HTMLAUDIOELEMENT_CID); #endif NS_DEFINE_NAMED_CID(NS_CANVASRENDERINGCONTEXT2D_CID); +NS_DEFINE_NAMED_CID(NS_CANVASRENDERINGCONTEXT2DTHEBES_CID); NS_DEFINE_NAMED_CID(NS_CANVASRENDERINGCONTEXT2DAZURE_CID); NS_DEFINE_NAMED_CID(NS_CANVASRENDERINGCONTEXTWEBGL_CID); NS_DEFINE_NAMED_CID(NS_TEXT_ENCODER_CID); @@ -914,6 +917,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = { #ifdef MOZ_MEDIA { &kNS_HTMLAUDIOELEMENT_CID, false, NULL, CreateHTMLAudioElement }, #endif + { &kNS_CANVASRENDERINGCONTEXT2DTHEBES_CID, false, NULL, CreateCanvasRenderingContext2DThebes }, { &kNS_CANVASRENDERINGCONTEXT2D_CID, false, NULL, CreateCanvasRenderingContext2D }, { &kNS_CANVASRENDERINGCONTEXTWEBGL_CID, false, NULL, CreateCanvasRenderingContextWebGL }, { &kNS_TEXT_ENCODER_CID, false, NULL, CreateTextEncoder }, @@ -1049,6 +1053,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = { { NS_HTMLAUDIOELEMENT_CONTRACTID, &kNS_HTMLAUDIOELEMENT_CID }, #endif { "@mozilla.org/content/canvas-rendering-context;1?id=2d", &kNS_CANVASRENDERINGCONTEXT2D_CID }, + { "@mozilla.org/content/canvas-rendering-context;1?id=2dthebes", &kNS_CANVASRENDERINGCONTEXT2DTHEBES_CID }, { "@mozilla.org/content/canvas-rendering-context;1?id=moz-webgl", &kNS_CANVASRENDERINGCONTEXTWEBGL_CID }, { "@mozilla.org/content/canvas-rendering-context;1?id=experimental-webgl", &kNS_CANVASRENDERINGCONTEXTWEBGL_CID }, { NS_DOC_ENCODER_CONTRACTID_BASE "text/xml", &kNS_TEXT_ENCODER_CID }, diff --git a/widget/src/windows/TaskbarPreview.cpp b/widget/src/windows/TaskbarPreview.cpp index 6cb699597418..b1a4a8365996 100644 --- a/widget/src/windows/TaskbarPreview.cpp +++ b/widget/src/windows/TaskbarPreview.cpp @@ -96,7 +96,7 @@ GetRenderingContext(nsIDocShell *shell, gfxASurface *surface, if (!ctx) { // create the canvas rendering context - ctx = do_CreateInstance("@mozilla.org/content/canvas-rendering-context;1?id=2d", &rv); + ctx = do_CreateInstance("@mozilla.org/content/canvas-rendering-context;1?id=2dthebes", &rv); if (NS_FAILED(rv)) { NS_WARNING("Could not create nsICanvasRenderingContextInternal for tab previews!"); return rv; From 9d6dc8e6e440edc0a13cce4f03c81ff63f4386c0 Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Thu, 30 Jun 2011 03:00:15 +0200 Subject: [PATCH 34/37] Bug 667461: Cache ThebesSurface for Azure canvas to speed up frequent source usage of an Azure canvas. r=roc --- .../src/nsCanvasRenderingContext2DAzure.cpp | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp index 47352035445c..a449da1a0de4 100644 --- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp @@ -571,6 +571,10 @@ protected: */ PRPackedBool mPredictManyRedrawCalls; + // This is stored after GetThebesSurface has been called once to avoid + // excessive ThebesSurface initialization overhead. + nsRefPtr mThebesSurface; + /** * We also have a device space pathbuilder. The reason for this is as * follows, when a path is being built, but the transform changes, we @@ -1061,9 +1065,14 @@ nsCanvasRenderingContext2DAzure::Reset() } mTarget = nsnull; + + // Since the target changes the backing texture will change, and this will + // no longer be valid. + mThebesSurface = nsnull; mValid = PR_FALSE; mIsEntireFrameInvalid = PR_FALSE; mPredictManyRedrawCalls = PR_FALSE; + return NS_OK; } @@ -4318,11 +4327,22 @@ nsCanvasRenderingContext2DAzure::GetThebesSurface(gfxASurface **surface) *surface = tmpSurf.forget().get(); return NS_OK; } - - nsRefPtr newSurf = - gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mTarget); - *surface = newSurf.forget().get(); + if (!mThebesSurface) { + mThebesSurface = + gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mTarget); + + if (!mThebesSurface) { + return NS_ERROR_FAILURE; + } + } else { + // Normally GetThebesSurfaceForDrawTarget will handle the flush, when + // we're returning a cached ThebesSurface we need to flush here. + mTarget->Flush(); + } + + mThebesSurface->AddRef(); + *surface = mThebesSurface; return NS_OK; } From 44c895469da0ed53a39338ff93038fbd97db10ea Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Wed, 29 Jun 2011 21:01:59 -0400 Subject: [PATCH 35/37] Bug 439808 - Make sure that deleting a selection works in inline contenteditable elements which have a non-editable parent block; r=roc --HG-- extra : rebase_source : 74d3df996b904032696000daa532d217140d3b2d --- editor/libeditor/html/nsHTMLEditRules.cpp | 5 ++- editor/libeditor/html/tests/Makefile.in | 1 + .../libeditor/html/tests/test_bug439808.html | 38 +++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 editor/libeditor/html/tests/test_bug439808.html diff --git a/editor/libeditor/html/nsHTMLEditRules.cpp b/editor/libeditor/html/nsHTMLEditRules.cpp index b8af59f200dd..2cbbdd1987b8 100644 --- a/editor/libeditor/html/nsHTMLEditRules.cpp +++ b/editor/libeditor/html/nsHTMLEditRules.cpp @@ -4934,8 +4934,9 @@ nsHTMLEditRules::CheckForEmptyBlock(nsIDOMNode *aStartNode, NS_ENSURE_SUCCESS(res, res); } } - - if (emptyBlock) + + nsCOMPtr emptyContent = do_QueryInterface(emptyBlock); + if (emptyBlock && emptyContent->IsEditable()) { nsCOMPtr blockParent; PRInt32 offset; diff --git a/editor/libeditor/html/tests/Makefile.in b/editor/libeditor/html/tests/Makefile.in index bd1ab81f4c09..e7dc495c031a 100644 --- a/editor/libeditor/html/tests/Makefile.in +++ b/editor/libeditor/html/tests/Makefile.in @@ -52,6 +52,7 @@ _TEST_FILES = \ test_bug372345.html \ test_bug410986.html \ test_bug432225.html \ + test_bug439808.html \ test_bug455992.html \ test_bug456244.html \ test_bug478725.html \ diff --git a/editor/libeditor/html/tests/test_bug439808.html b/editor/libeditor/html/tests/test_bug439808.html new file mode 100644 index 000000000000..0ee8fb04d313 --- /dev/null +++ b/editor/libeditor/html/tests/test_bug439808.html @@ -0,0 +1,38 @@ + + + + + Test for Bug 439808 + + + + + + +Mozilla Bug 439808 +

+
+twest +
+
+
+
+ + From d5b4813116a7844331fede882c2e954377fe1974 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Wed, 29 Jun 2011 21:02:09 -0400 Subject: [PATCH 36/37] Bug 668267 - Make sure that the print preview tests close the window they open on Mac; r=roc --HG-- extra : rebase_source : fc54922908a848265d7fae6597c4fb2b0014daf0 --- .../tests/chrome/printpreview_bug396024_helper.xul | 12 ++++++++---- .../tests/chrome/printpreview_bug482976_helper.xul | 11 +++++++---- layout/base/tests/chrome/printpreview_helper.xul | 12 ++++++++---- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/layout/base/tests/chrome/printpreview_bug396024_helper.xul b/layout/base/tests/chrome/printpreview_bug396024_helper.xul index e219c084aaf5..bfb6bcdf98eb 100644 --- a/layout/base/tests/chrome/printpreview_bug396024_helper.xul +++ b/layout/base/tests/chrome/printpreview_bug396024_helper.xul @@ -48,6 +48,11 @@ function exitprintpreview() { .getInterface(Components.interfaces.nsIWebBrowserPrint).exitPrintPreview(); } +function finish() { + SimpleTest.finish(); + window.close(); +} + function run() { /** Test for Bug 396024 **/ @@ -59,7 +64,7 @@ function run() .getService(Components.interfaces.nsIPrinterEnumerator); } catch(e) { todo(false, "Test skipped on MacOSX, as the print preview code doesn't work there"); - SimpleTest.finish(); + finish(); return; } @@ -72,7 +77,7 @@ function run() setTimeout(run2, 0) } else { todo(false, "No printer seems installed on this machine, that is necessary for this test"); - SimpleTest.finish(); + finish(); } } @@ -112,8 +117,7 @@ function run5() { //XXX this shouldn't be necessary, see bug 405555 printpreview(); exitprintpreview(); - SimpleTest.finish(); //should not have crashed after all of this - window.close(); + finish(); //should not have crashed after all of this } ]]> diff --git a/layout/base/tests/chrome/printpreview_bug482976_helper.xul b/layout/base/tests/chrome/printpreview_bug482976_helper.xul index ac9a06cfc49c..01b26f093283 100644 --- a/layout/base/tests/chrome/printpreview_bug482976_helper.xul +++ b/layout/base/tests/chrome/printpreview_bug482976_helper.xul @@ -48,6 +48,11 @@ function exitprintpreview() { .getInterface(Components.interfaces.nsIWebBrowserPrint).exitPrintPreview(); } +function finish() { + SimpleTest.finish(); + window.close(); +} + function run1() { /** Test for Bug 482976 **/ @@ -59,7 +64,7 @@ function run1() .getService(Components.interfaces.nsIPrinterEnumerator); } catch(e) { todo(false, "Test skipped on MacOSX, as the print preview code doesn't work there"); - SimpleTest.finish(); + finish(); return; } @@ -68,12 +73,10 @@ function run1() ok(gWbp.doingPrintPreview, "Should be doing print preview"); exitprintpreview(); ok(!gWbp.doingPrintPreview, "Should not be doing print preview anymore"); - SimpleTest.finish(); } else { todo(false, "No printer seems installed on this machine, that is necessary for this test"); - SimpleTest.finish(); } - window.close(); + finish(); } ]]> diff --git a/layout/base/tests/chrome/printpreview_helper.xul b/layout/base/tests/chrome/printpreview_helper.xul index 44d1735d90f4..0d5716d20ae8 100644 --- a/layout/base/tests/chrome/printpreview_helper.xul +++ b/layout/base/tests/chrome/printpreview_helper.xul @@ -65,6 +65,11 @@ function exitprintpreview() { .getInterface(Components.interfaces.nsIWebBrowserPrint).exitPrintPreview(); } +function finish() { + SimpleTest.finish(); + window.close(); +} + function runTests() { var printService = Components.classes["@mozilla.org/gfx/printsettings-service;1"] @@ -75,7 +80,7 @@ function runTests() .getService(Components.interfaces.nsIPrinterEnumerator); } catch(e) { todo(false, "Test skipped on MacOSX, as the print preview code doesn't work there"); - SimpleTest.finish(); + finish(); return; } @@ -83,7 +88,7 @@ function runTests() startTest1(); } else { todo(false, "No printer seems installed on this machine, that is necessary for this test"); - SimpleTest.finish(); + finish(); } } @@ -239,8 +244,7 @@ function runTest5() { ''; printpreview(); exitprintpreview(); - SimpleTest.finish(); - window.close(); + finish(); } ]]> From effbfd3c5a8012ff8ac963bb27bd755a00a9ed35 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Mon, 6 Sep 2010 16:59:41 -0400 Subject: [PATCH 37/37] Bug 549262 - Enable the (shift-)space shortcut key for scrolling up/down in pages containing editable elements; r=roc --HG-- extra : rebase_source : 99706dd2e678052b345b011ea76f17370ad1a227 --- content/xbl/builtin/editor-base.inc | 3 + editor/libeditor/html/tests/Makefile.in | 2 + .../libeditor/html/tests/file_bug549262.html | 8 ++ .../libeditor/html/tests/test_bug549262.html | 74 +++++++++++++++++++ 4 files changed, 87 insertions(+) create mode 100644 editor/libeditor/html/tests/file_bug549262.html create mode 100644 editor/libeditor/html/tests/test_bug549262.html diff --git a/content/xbl/builtin/editor-base.inc b/content/xbl/builtin/editor-base.inc index b33cbab4d489..f439c1bf8ad5 100644 --- a/content/xbl/builtin/editor-base.inc +++ b/content/xbl/builtin/editor-base.inc @@ -1,3 +1,6 @@ + + + diff --git a/editor/libeditor/html/tests/Makefile.in b/editor/libeditor/html/tests/Makefile.in index e7dc495c031a..b46269f28618 100644 --- a/editor/libeditor/html/tests/Makefile.in +++ b/editor/libeditor/html/tests/Makefile.in @@ -62,6 +62,8 @@ _TEST_FILES = \ test_bug520189.html \ test_bug525389.html \ test_bug537046.html \ + test_bug549262.html \ + file_bug549262.html \ test_bug550434.html \ test_bug551704.html \ test_bug592592.html \ diff --git a/editor/libeditor/html/tests/file_bug549262.html b/editor/libeditor/html/tests/file_bug549262.html new file mode 100644 index 000000000000..92a0c76f3541 --- /dev/null +++ b/editor/libeditor/html/tests/file_bug549262.html @@ -0,0 +1,8 @@ + + + + test +
abc
+
+ + diff --git a/editor/libeditor/html/tests/test_bug549262.html b/editor/libeditor/html/tests/test_bug549262.html new file mode 100644 index 000000000000..9f23c0ece744 --- /dev/null +++ b/editor/libeditor/html/tests/test_bug549262.html @@ -0,0 +1,74 @@ + + + + + Test for Bug 549262 + + + + + + +Mozilla Bug 549262 +

+
+
+
+
+
+ +