зеркало из https://github.com/mozilla/pjs.git
Bug 598833 part 5. Store focus and focusring state directly on elements. r=smaug,enn
This commit is contained in:
Родитель
c45aba531e
Коммит
ace23ff3cb
|
@ -44,6 +44,8 @@
|
|||
#include "nsEventStates.h"
|
||||
|
||||
class nsEventStateManager;
|
||||
class nsGlobalWindow;
|
||||
class nsFocusManager;
|
||||
|
||||
// Element-specific flags
|
||||
enum {
|
||||
|
@ -107,8 +109,11 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
// Need to allow the ESM to set our state
|
||||
// Need to allow the ESM, nsGlobalWindow, and the focus manager to
|
||||
// set our state
|
||||
friend class ::nsEventStateManager;
|
||||
friend class ::nsGlobalWindow;
|
||||
friend class ::nsFocusManager;
|
||||
|
||||
void NotifyStateChange(nsEventStates aStates);
|
||||
|
||||
|
|
|
@ -4211,18 +4211,6 @@ GetLabelTarget(nsIContent* aPossibleLabel)
|
|||
return label->GetLabeledElement();
|
||||
}
|
||||
|
||||
static bool
|
||||
ShouldShowFocusRing(nsIContent* aContent)
|
||||
{
|
||||
nsIDocument* doc = aContent->GetOwnerDoc();
|
||||
if (doc) {
|
||||
nsPIDOMWindow* window = doc->GetWindow();
|
||||
return window && window->ShouldShowFocusRing();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nsEventStates
|
||||
nsEventStateManager::GetContentState(nsIContent *aContent)
|
||||
{
|
||||
|
@ -4231,15 +4219,6 @@ nsEventStateManager::GetContentState(nsIContent *aContent)
|
|||
state = aContent->AsElement()->State();
|
||||
}
|
||||
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
nsIContent* focusedContent = fm ? fm->GetFocusedContent() : nsnull;
|
||||
if (aContent == focusedContent) {
|
||||
state |= NS_EVENT_STATE_FOCUS;
|
||||
|
||||
if (ShouldShowFocusRing(aContent)) {
|
||||
state |= NS_EVENT_STATE_FOCUSRING;
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
|
|
|
@ -803,6 +803,7 @@ nsFocusManager::ContentRemoved(nsIDocument* aDocument, nsIContent* aContent)
|
|||
// of the currently focused element, reset the focus within that window.
|
||||
nsIContent* content = window->GetFocusedNode();
|
||||
if (content && nsContentUtils::ContentIsDescendantOf(content, aContent)) {
|
||||
PRBool shouldShowFocusRing = window->ShouldShowFocusRing();
|
||||
window->SetFocusedNode(nsnull);
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
|
||||
|
@ -832,6 +833,8 @@ nsFocusManager::ContentRemoved(nsIDocument* aDocument, nsIContent* aContent)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
NotifyFocusStateChange(aContent, shouldShowFocusRing, PR_FALSE);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -884,18 +887,6 @@ nsFocusManager::WindowShown(nsIDOMWindow* aWindow, PRBool aNeedsFocus)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
NotifyFocusStateChange(nsIContent* aContent, nsPIDOMWindow* aWindow)
|
||||
{
|
||||
nsIDocument *doc = aContent->GetCurrentDoc();
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
nsEventStates eventState = NS_EVENT_STATE_FOCUS;
|
||||
if (aWindow->ShouldShowFocusRing()) {
|
||||
eventState |= NS_EVENT_STATE_FOCUSRING;
|
||||
}
|
||||
doc->ContentStateChanged(aContent, eventState);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFocusManager::WindowHidden(nsIDOMWindow* aWindow)
|
||||
{
|
||||
|
@ -946,7 +937,9 @@ nsFocusManager::WindowHidden(nsIDOMWindow* aWindow)
|
|||
mFocusedContent = nsnull;
|
||||
|
||||
if (oldFocusedContent && oldFocusedContent->IsInDoc()) {
|
||||
NotifyFocusStateChange(oldFocusedContent, mFocusedWindow);
|
||||
NotifyFocusStateChange(oldFocusedContent,
|
||||
mFocusedWindow->ShouldShowFocusRing(),
|
||||
PR_FALSE);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> focusedDocShell = mFocusedWindow->GetDocShell();
|
||||
|
@ -1033,6 +1026,26 @@ nsFocusManager::FocusPlugin(nsIContent* aContent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsFocusManager::NotifyFocusStateChange(nsIContent* aContent,
|
||||
PRBool aWindowShouldShowFocusRing,
|
||||
PRBool aGettingFocus)
|
||||
{
|
||||
if (!aContent->IsElement()) {
|
||||
return;
|
||||
}
|
||||
nsEventStates eventState = NS_EVENT_STATE_FOCUS;
|
||||
if (aWindowShouldShowFocusRing) {
|
||||
eventState |= NS_EVENT_STATE_FOCUSRING;
|
||||
}
|
||||
if (aGettingFocus) {
|
||||
aContent->AsElement()->AddStates(eventState);
|
||||
} else {
|
||||
aContent->AsElement()->RemoveStates(eventState);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsFocusManager::EnsureCurrentWidgetFocused()
|
||||
|
@ -1501,6 +1514,7 @@ nsFocusManager::Blur(nsPIDOMWindow* aWindowToClear,
|
|||
// now adjust the actual focus, by clearing the fields in the focus manager
|
||||
// and in the window.
|
||||
mFocusedContent = nsnull;
|
||||
PRBool shouldShowFocusRing = window->ShouldShowFocusRing();
|
||||
if (aWindowToClear)
|
||||
aWindowToClear->SetFocusedNode(nsnull);
|
||||
|
||||
|
@ -1513,7 +1527,7 @@ nsFocusManager::Blur(nsPIDOMWindow* aWindowToClear,
|
|||
content && content->IsInDoc() && !IsNonFocusableRoot(content);
|
||||
if (content) {
|
||||
if (sendBlurEvent) {
|
||||
NotifyFocusStateChange(content, window);
|
||||
NotifyFocusStateChange(content, shouldShowFocusRing, PR_FALSE);
|
||||
}
|
||||
|
||||
// if an object/plug-in is being blurred, move the system focus to the
|
||||
|
@ -1729,7 +1743,7 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow,
|
|||
if (aFocusChanged)
|
||||
ScrollIntoView(presShell, aContent, aFlags);
|
||||
|
||||
NotifyFocusStateChange(aContent, aWindow);
|
||||
NotifyFocusStateChange(aContent, aWindow->ShouldShowFocusRing(), PR_TRUE);
|
||||
|
||||
// if this is an object/plug-in, focus the plugin's widget. Note that we might
|
||||
// no longer be in the same document, due to the events we fired above when
|
||||
|
|
|
@ -467,6 +467,19 @@ protected:
|
|||
nsIContent* aEndSelection,
|
||||
nsIContent** aFocusedContent);
|
||||
|
||||
private:
|
||||
// Notify that the focus state of aContent has changed. Note that
|
||||
// we need to pass in whether the window should show a focus ring
|
||||
// before the SetFocusedNode call on it happened when losing focus
|
||||
// and after the SetFocusedNode call when gaining focus, which is
|
||||
// why that information needs to be an explicit argument instead of
|
||||
// just passing in the window and asking it whether it should show
|
||||
// focus rings: in the losing focus case that information could be
|
||||
// wrong..
|
||||
static void NotifyFocusStateChange(nsIContent* aContent,
|
||||
PRBool aWindowShouldShowFocusRing,
|
||||
PRBool aGettingFocus);
|
||||
|
||||
// the currently active and front-most top-most window
|
||||
nsCOMPtr<nsPIDOMWindow> mActiveWindow;
|
||||
|
||||
|
|
|
@ -7653,6 +7653,8 @@ nsGlobalWindow::SetKeyboardIndicators(UIStateChangeType aShowAccelerators,
|
|||
{
|
||||
FORWARD_TO_INNER_VOID(SetKeyboardIndicators, (aShowAccelerators, aShowFocusRings));
|
||||
|
||||
PRBool oldShouldShowFocusRing = ShouldShowFocusRing();
|
||||
|
||||
// only change the flags that have been modified
|
||||
if (aShowAccelerators != UIStateChangeType_NoChange)
|
||||
mShowAccelerators = aShowAccelerators == UIStateChangeType_Set;
|
||||
|
@ -7675,11 +7677,15 @@ nsGlobalWindow::SetKeyboardIndicators(UIStateChangeType aShowAccelerators,
|
|||
}
|
||||
}
|
||||
|
||||
if (mHasFocus && mFocusedNode) { // send content state notifications
|
||||
nsIDocument *doc = mFocusedNode->GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(mFocusedNode, NS_EVENT_STATE_FOCUSRING);
|
||||
PRBool newShouldShowFocusRing = ShouldShowFocusRing();
|
||||
if (mHasFocus && mFocusedNode &&
|
||||
oldShouldShowFocusRing != newShouldShowFocusRing &&
|
||||
mFocusedNode->IsElement()) {
|
||||
// Update mFocusedNode's state.
|
||||
if (newShouldShowFocusRing) {
|
||||
mFocusedNode->AsElement()->AddStates(NS_EVENT_STATE_FOCUSRING);
|
||||
} else {
|
||||
mFocusedNode->AsElement()->RemoveStates(NS_EVENT_STATE_FOCUSRING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче