Bug 399852. Experimental relanding to collect data from centos5.

This commit is contained in:
roc+@cs.cmu.edu 2008-02-19 01:16:20 -08:00
parent 335bc29d74
commit e491c305ca
6 changed files with 186 additions and 2 deletions

View File

@ -379,6 +379,23 @@ static nsresult
DeletingFrameSubtree(nsFrameManager* aFrameManager,
nsIFrame* aFrame);
void nsFocusEventSuppressor::Suppress(nsIPresShell *aPresShell)
{
NS_ASSERTION(aPresShell, "Need non-null nsIPresShell!");
if (!mViewManager) {
nsFrameManager *frameManager = aPresShell->FrameManager();
mViewManager = frameManager->GetPresContext()->GetViewManager();
NS_ASSERTION(mViewManager, "We must have an mViewManager here");
}
mViewManager->SuppressFocusEvents();
}
void nsFocusEventSuppressor::Unsuppress()
{
NS_ASSERTION(mViewManager, "We must have an mViewManager here");
mViewManager->UnsuppressFocusEvents();
}
#ifdef MOZ_SVG
static nsIFrame *
@ -10232,6 +10249,12 @@ nsCSSFrameConstructor::AttributeChanged(nsIContent* aContent,
return result;
}
void
nsCSSFrameConstructor::BeginUpdate() {
mFocusSuppressor.Suppress(mPresShell);
++mUpdateCount;
}
void
nsCSSFrameConstructor::EndUpdate()
{
@ -10242,7 +10265,7 @@ nsCSSFrameConstructor::EndUpdate()
RecalcQuotesAndCounters();
NS_ASSERTION(mUpdateCount == 1, "Odd update count");
}
mFocusSuppressor.Unsuppress();
--mUpdateCount;
}

View File

@ -84,6 +84,7 @@ function restoreForm() {
uname.value = "";
pword.value = "";
uname.focus();
ok(document.activeElement == uname, "Username should be focused.");
}
@ -126,6 +127,7 @@ function runTest(testNum) {
// Seems we need to enable this again, or sendKeyEvent() complaints.
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
ok(true, "Starting test #" + testNum);
ok(document.hasFocus(), "Document should be focused");
switch(testNum) {
case 1:
@ -417,12 +419,31 @@ function runTest(testNum) {
}
function __log(message) {
var m = '[CPEARCE] ' + message;
dump(m);
ok(true, m);
}
function startTest() {
runTest(1);
__log('JS: onload() document.hasFocus=' + document.hasFocus()
+' document.activeElement=[tag=' + document.activeElement.tagName +' name=' +document.activeElement.name +']\n');
runTest(1);
}
window.onload = startTest;
window.onfocus = function() {
__log('JS: onfocus() document.hasFocus=' + document.hasFocus()
+' document.activeElement=[tag=' + document.activeElement.tagName +' name=' +document.activeElement.name +']\n');
}
window.onblur = function() {
__log('JS: onblur() document.hasFocus=' + document.hasFocus()
+' document.activeElement=[tag=' + document.activeElement.tagName +' name=' +document.activeElement.name +']\n');
}
SimpleTest.waitForExplicitFinish();
</script>
</pre>

View File

@ -481,6 +481,31 @@ public:
* (aFromScroll is false) or scrolled (aFromScroll is true).
*/
NS_IMETHOD SynthesizeMouseMove(PRBool aFromScroll)=0;
/**
* Enables focus/blur event suppression. This stops focus/blur
* events from reaching the widgets. This should be enabled
* when we're messing with the frame tree, so focus/blur handlers
* don't mess with stuff while we are. See Bug 399852.
*/
virtual void SuppressFocusEvents()=0;
/**
* Disables focus/blur event suppression. This "reboots" the focus
* by sending a blur to what was focused before suppression began,
* and by sending a focus event to what should be currently focused.
* Note this can run arbitrary code, and could even destroy the view
* manager. The suppression should be enabled when we're messing with
* the frame tree, so focus/blur handlers don't mess with stuff while
* we are. See Bug 399852.
*/
virtual void UnsuppressFocusEvents()=0;
/**
* Returns true when focus suppression is on.
*/
virtual PRBool IsFocusSuppressed()=0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIViewManager, NS_IVIEWMANAGER_IID)

View File

@ -200,6 +200,19 @@ nsView::~nsView()
{
MOZ_COUNT_DTOR(nsView);
if (this == nsViewManager::GetViewFocusedBeforeSuppression()) {
if (GetViewManager()->IsFocusSuppressed()) {
printf("*** 0 INFO TODO [CPEARCE] destroying view focused before suppression, while suppressed\n");
}
nsViewManager::SetViewFocusedBeforeSuppression(nsnull);
}
if (this == nsViewManager::GetCurrentlyFocusedView()) {
if (GetViewManager()->IsFocusSuppressed()) {
printf("*** 0 INFO TODO [CPEARCE] destroying view currently focused, while suppressed\n");
}
nsViewManager::SetCurrentlyFocusedView(nsnull);
}
while (GetFirstChild())
{
nsView* child = GetFirstChild();

View File

@ -935,6 +935,61 @@ void nsViewManager::UpdateViews(nsView *aView, PRUint32 aUpdateFlags)
}
}
nsView *nsViewManager::sCurrentlyFocusView = nsnull;
nsView *nsViewManager::sViewFocusedBeforeSuppression = nsnull;
PRInt32 nsViewManager::sSuppressCount = 0;
void nsViewManager::SuppressFocusEvents()
{
sSuppressCount++;
if (sSuppressCount == 1) {
// We're turning on focus/blur suppression, remember what had
// the focus.
SetViewFocusedBeforeSuppression(GetCurrentlyFocusedView());
}
}
void nsViewManager::UnsuppressFocusEvents()
{
sSuppressCount--;
if (sSuppressCount > 0 ||
GetCurrentlyFocusedView() == GetViewFocusedBeforeSuppression())
return;
// We're turning off suppression, synthesize LOSTFOCUS/GOTFOCUS.
nsIWidget *widget = nsnull;
nsEventStatus status;
// Backup what is focused before we send the blur. If the
// blur causes a focus change, keep that new focus change,
// don't overwrite with the old "currently focused view".
nsIView *currentFocusBeforeBlur = GetCurrentlyFocusedView();
// Send NS_LOSTFOCUS to widget that was focused before
// focus/blur suppression.
if (GetViewFocusedBeforeSuppression()) {
widget = GetViewFocusedBeforeSuppression()->GetWidget();
if (widget) {
printf("*** 0 INFO TODO [CPEARCE] Unsuppressing, dispatching NS_LOSTFOCUS\n");
nsGUIEvent event(PR_TRUE, NS_LOSTFOCUS, widget);
widget->DispatchEvent(&event, status);
}
}
// Send NS_GOTFOCUS to the widget that we think should be focused.
if (GetCurrentlyFocusedView() &&
currentFocusBeforeBlur == GetCurrentlyFocusedView())
{
widget = GetCurrentlyFocusedView()->GetWidget();
if (widget) {
printf("*** 0 INFO TODO [CPEARCE] Unsuppressing, dispatching NS_GOTFOCUS\n");
nsGUIEvent event(PR_TRUE, NS_GOTFOCUS, widget);
widget->DispatchEvent(&event, status);
}
}
}
NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aStatus)
{
*aStatus = nsEventStatus_eIgnore;
@ -1138,6 +1193,20 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aS
default:
{
if (aEvent->message == NS_GOTFOCUS) {
printf("*** 0 INFO TODO [CPEARCE] Focus changing%s\n",
(nsViewManager::IsFocusSuppressed() ? " while suppressed" : ""));
SetCurrentlyFocusedView(nsView::GetViewFor(aEvent->widget));
}
if ((aEvent->message == NS_GOTFOCUS || aEvent->message == NS_LOSTFOCUS) &&
nsViewManager::IsFocusSuppressed())
{
printf("*** 0 INFO TODO [CPEARCE] Suppressing %s\n",
(aEvent->message == NS_GOTFOCUS ? "NS_GOTFOCUS" : "NS_LOSTFOCUS"));
break;
}
if ((NS_IS_MOUSE_EVENT(aEvent) &&
// Ignore moves that we synthesize.
static_cast<nsMouseEvent*>(aEvent)->reason ==

View File

@ -201,10 +201,43 @@ public:
/* Update the cached RootViewManager pointer on this view manager. */
void InvalidateHierarchy();
virtual void SuppressFocusEvents();
virtual void UnsuppressFocusEvents();
virtual PRBool IsFocusSuppressed()
{
return sSuppressCount > 0;
}
static void SetCurrentlyFocusedView(nsView *aView)
{
sCurrentlyFocusView = aView;
}
static nsView* GetCurrentlyFocusedView()
{
return sCurrentlyFocusView;
}
static void SetViewFocusedBeforeSuppression(nsView *aView)
{
sViewFocusedBeforeSuppression = aView;
}
static nsView* GetViewFocusedBeforeSuppression()
{
return sViewFocusedBeforeSuppression;
}
protected:
virtual ~nsViewManager();
private:
static nsView *sCurrentlyFocusView;
static nsView *sViewFocusedBeforeSuppression;
static PRInt32 sSuppressCount;
void FlushPendingInvalidates();
void ProcessPendingUpdates(nsView *aView, PRBool aDoInvalidate);
void ReparentChildWidgets(nsIView* aView, nsIWidget *aNewWidget);