mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 558970 nsEditorEventListener should store its owner as nsEditor rather than nsIEditor r=smaug
This commit is contained in:
parent
44bdccd814
commit
acb56f8ab0
@ -44,9 +44,7 @@
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
#include "nsIDOMHTMLElement.h"
|
||||
#include "nsIDOMNSHTMLElement.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsPIDOMEventTarget.h"
|
||||
#include "nsIEventListenerManager.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
@ -60,12 +58,6 @@
|
||||
#include "nsIDOMNamedNodeMap.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsIDOMEventGroup.h"
|
||||
#include "nsIDOMMouseListener.h"
|
||||
#include "nsIDOMFocusListener.h"
|
||||
#include "nsIDOMTextListener.h"
|
||||
#include "nsIDOMCompositionListener.h"
|
||||
#include "nsIDOMHTMLBRElement.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsITransactionManager.h"
|
||||
@ -318,7 +310,7 @@ nsEditor::CreateEventListeners()
|
||||
{
|
||||
NS_ENSURE_TRUE(!mEventListener, NS_ERROR_ALREADY_INITIALIZED);
|
||||
mEventListener = do_QueryInterface(
|
||||
static_cast<nsIDOMKeyListener*>(new nsEditorEventListener(this)));
|
||||
static_cast<nsIDOMKeyListener*>(new nsEditorEventListener()));
|
||||
NS_ENSURE_TRUE(mEventListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
return NS_OK;
|
||||
}
|
||||
@ -328,121 +320,18 @@ nsEditor::InstallEventListeners()
|
||||
{
|
||||
NS_ENSURE_TRUE(mDocWeak && mPresShellWeak && mEventListener,
|
||||
NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsCOMPtr<nsPIDOMEventTarget> piTarget = GetPIDOMEventTarget();
|
||||
|
||||
if (!piTarget) {
|
||||
RemoveEventListeners();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// register the event listeners with the listener manager
|
||||
nsCOMPtr<nsIDOMEventGroup> sysGroup;
|
||||
piTarget->GetSystemEventGroup(getter_AddRefs(sysGroup));
|
||||
nsIEventListenerManager* elmP = piTarget->GetListenerManager(PR_TRUE);
|
||||
|
||||
if (sysGroup && elmP)
|
||||
{
|
||||
rv = elmP->AddEventListenerByType(mEventListener,
|
||||
NS_LITERAL_STRING("keypress"),
|
||||
NS_EVENT_FLAG_BUBBLE |
|
||||
NS_PRIV_EVENT_UNTRUSTED_PERMITTED,
|
||||
sysGroup);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"failed to register key listener in system group");
|
||||
}
|
||||
|
||||
rv |= piTarget->AddEventListenerByIID(mEventListener,
|
||||
NS_GET_IID(nsIDOMMouseListener));
|
||||
|
||||
if (elmP) {
|
||||
// Focus event doesn't bubble so adding the listener to capturing phase.
|
||||
// Make sure this works after bug 235441 gets fixed.
|
||||
rv |= elmP->AddEventListenerByIID(mEventListener,
|
||||
NS_GET_IID(nsIDOMFocusListener),
|
||||
NS_EVENT_FLAG_CAPTURE);
|
||||
}
|
||||
|
||||
rv |= piTarget->AddEventListenerByIID(mEventListener,
|
||||
NS_GET_IID(nsIDOMTextListener));
|
||||
|
||||
rv |= piTarget->AddEventListenerByIID(mEventListener,
|
||||
NS_GET_IID(nsIDOMCompositionListener));
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(piTarget));
|
||||
if (target) {
|
||||
// See bug 455215, we cannot use the standard dragstart event yet
|
||||
rv |= elmP->AddEventListenerByType(mEventListener, NS_LITERAL_STRING("draggesture"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
rv |= elmP->AddEventListenerByType(mEventListener, NS_LITERAL_STRING("dragenter"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
rv |= elmP->AddEventListenerByType(mEventListener, NS_LITERAL_STRING("dragover"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
rv |= elmP->AddEventListenerByType(mEventListener, NS_LITERAL_STRING("dragleave"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
rv |= elmP->AddEventListenerByType(mEventListener, NS_LITERAL_STRING("drop"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_ERROR("failed to register some event listeners");
|
||||
|
||||
RemoveEventListeners();
|
||||
}
|
||||
|
||||
return rv;
|
||||
nsEditorEventListener* listener =
|
||||
reinterpret_cast<nsEditorEventListener*>(mEventListener.get());
|
||||
return listener->Connect(this);
|
||||
}
|
||||
|
||||
void
|
||||
nsEditor::RemoveEventListeners()
|
||||
{
|
||||
if (!mDocWeak || !mEventListener)
|
||||
{
|
||||
if (!mDocWeak || !mEventListener) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMEventTarget> piTarget = GetPIDOMEventTarget();
|
||||
|
||||
if (piTarget)
|
||||
{
|
||||
// unregister the event listeners with the DOM event target
|
||||
nsCOMPtr<nsIEventListenerManager> elmP =
|
||||
piTarget->GetListenerManager(PR_TRUE);
|
||||
nsCOMPtr<nsIDOMEventGroup> sysGroup;
|
||||
piTarget->GetSystemEventGroup(getter_AddRefs(sysGroup));
|
||||
if (sysGroup && elmP)
|
||||
{
|
||||
elmP->RemoveEventListenerByType(mEventListener,
|
||||
NS_LITERAL_STRING("keypress"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
elmP->RemoveEventListenerByType(mEventListener, NS_LITERAL_STRING("draggesture"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
elmP->RemoveEventListenerByType(mEventListener, NS_LITERAL_STRING("dragenter"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
elmP->RemoveEventListenerByType(mEventListener, NS_LITERAL_STRING("dragover"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
elmP->RemoveEventListenerByType(mEventListener, NS_LITERAL_STRING("dragleave"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
elmP->RemoveEventListenerByType(mEventListener, NS_LITERAL_STRING("drop"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
}
|
||||
|
||||
piTarget->RemoveEventListenerByIID(mEventListener,
|
||||
NS_GET_IID(nsIDOMMouseListener));
|
||||
|
||||
elmP->RemoveEventListenerByIID(mEventListener,
|
||||
NS_GET_IID(nsIDOMFocusListener),
|
||||
NS_EVENT_FLAG_CAPTURE);
|
||||
|
||||
piTarget->RemoveEventListenerByIID(mEventListener,
|
||||
NS_GET_IID(nsIDOMTextListener));
|
||||
|
||||
piTarget->RemoveEventListenerByIID(mEventListener,
|
||||
NS_GET_IID(nsIDOMCompositionListener));
|
||||
}
|
||||
reinterpret_cast<nsEditorEventListener*>(mEventListener.get())->Disconnect();
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -344,7 +344,7 @@ protected:
|
||||
|
||||
|
||||
// install the event listeners for the editor
|
||||
nsresult InstallEventListeners();
|
||||
virtual nsresult InstallEventListeners();
|
||||
|
||||
virtual nsresult CreateEventListeners();
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIDOMNSEvent.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsPIDOMEventTarget.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsISelection.h"
|
||||
@ -58,6 +59,8 @@
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsILookAndFeel.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsIEventListenerManager.h"
|
||||
#include "nsIDOMEventGroup.h"
|
||||
|
||||
// Drag & Drop, Clipboard
|
||||
#include "nsIServiceManager.h"
|
||||
@ -76,24 +79,173 @@
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
nsEditorEventListener::nsEditorEventListener(nsEditor* aEditor) :
|
||||
mEditor(aEditor), mCaretDrawn(PR_FALSE), mCommitText(PR_FALSE),
|
||||
nsEditorEventListener::nsEditorEventListener() :
|
||||
mEditor(nsnull), mCaretDrawn(PR_FALSE), mCommitText(PR_FALSE),
|
||||
mInTransaction(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
nsEditorEventListener::~nsEditorEventListener()
|
||||
{
|
||||
if (mEditor) {
|
||||
NS_WARNING("We're not uninstalled");
|
||||
Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditorEventListener::Connect(nsEditor* aEditor)
|
||||
{
|
||||
NS_ENSURE_ARG(aEditor);
|
||||
NS_ENSURE_TRUE(!mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
mEditor = aEditor;
|
||||
|
||||
nsresult rv = InstallToEditor();
|
||||
if (NS_FAILED(rv)) {
|
||||
Disconnect();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditorEventListener::InstallToEditor()
|
||||
{
|
||||
NS_PRECONDITION(mEditor, "The caller must set mEditor");
|
||||
|
||||
nsCOMPtr<nsPIDOMEventTarget> piTarget = mEditor->GetPIDOMEventTarget();
|
||||
NS_ENSURE_TRUE(piTarget, NS_ERROR_FAILURE);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// register the event listeners with the listener manager
|
||||
nsCOMPtr<nsIDOMEventGroup> sysGroup;
|
||||
piTarget->GetSystemEventGroup(getter_AddRefs(sysGroup));
|
||||
NS_ENSURE_STATE(sysGroup);
|
||||
nsIEventListenerManager* elmP = piTarget->GetListenerManager(PR_TRUE);
|
||||
NS_ENSURE_STATE(elmP);
|
||||
|
||||
rv = elmP->AddEventListenerByType(static_cast<nsIDOMKeyListener*>(this),
|
||||
NS_LITERAL_STRING("keypress"),
|
||||
NS_EVENT_FLAG_BUBBLE |
|
||||
NS_PRIV_EVENT_UNTRUSTED_PERMITTED,
|
||||
sysGroup);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// See bug 455215, we cannot use the standard dragstart event yet
|
||||
rv = elmP->AddEventListenerByType(static_cast<nsIDOMKeyListener*>(this),
|
||||
NS_LITERAL_STRING("draggesture"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = elmP->AddEventListenerByType(static_cast<nsIDOMKeyListener*>(this),
|
||||
NS_LITERAL_STRING("dragenter"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = elmP->AddEventListenerByType(static_cast<nsIDOMKeyListener*>(this),
|
||||
NS_LITERAL_STRING("dragover"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = elmP->AddEventListenerByType(static_cast<nsIDOMKeyListener*>(this),
|
||||
NS_LITERAL_STRING("dragleave"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = elmP->AddEventListenerByType(static_cast<nsIDOMKeyListener*>(this),
|
||||
NS_LITERAL_STRING("drop"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = piTarget->AddEventListenerByIID(static_cast<nsIDOMMouseListener*>(this),
|
||||
NS_GET_IID(nsIDOMMouseListener));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Focus event doesn't bubble so adding the listener to capturing phase.
|
||||
// Make sure this works after bug 235441 gets fixed.
|
||||
rv = elmP->AddEventListenerByIID(static_cast<nsIDOMFocusListener*>(this),
|
||||
NS_GET_IID(nsIDOMFocusListener),
|
||||
NS_EVENT_FLAG_CAPTURE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = piTarget->AddEventListenerByIID(static_cast<nsIDOMTextListener*>(this),
|
||||
NS_GET_IID(nsIDOMTextListener));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = piTarget->AddEventListenerByIID(
|
||||
static_cast<nsIDOMCompositionListener*>(this),
|
||||
NS_GET_IID(nsIDOMCompositionListener));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsEditorEventListener::Disconnect()
|
||||
{
|
||||
if (!mEditor) {
|
||||
return;
|
||||
}
|
||||
UninstallFromEditor();
|
||||
mEditor = nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsEditorEventListener::UninstallFromEditor()
|
||||
{
|
||||
nsCOMPtr<nsPIDOMEventTarget> piTarget = mEditor->GetPIDOMEventTarget();
|
||||
if (!piTarget) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIEventListenerManager> elmP =
|
||||
piTarget->GetListenerManager(PR_TRUE);
|
||||
if (!elmP) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIDOMEventGroup> sysGroup;
|
||||
piTarget->GetSystemEventGroup(getter_AddRefs(sysGroup));
|
||||
if (!sysGroup) {
|
||||
return;
|
||||
}
|
||||
|
||||
elmP->RemoveEventListenerByType(static_cast<nsIDOMKeyListener*>(this),
|
||||
NS_LITERAL_STRING("keypress"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
elmP->RemoveEventListenerByType(static_cast<nsIDOMKeyListener*>(this),
|
||||
NS_LITERAL_STRING("draggesture"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
elmP->RemoveEventListenerByType(static_cast<nsIDOMKeyListener*>(this),
|
||||
NS_LITERAL_STRING("dragenter"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
elmP->RemoveEventListenerByType(static_cast<nsIDOMKeyListener*>(this),
|
||||
NS_LITERAL_STRING("dragover"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
elmP->RemoveEventListenerByType(static_cast<nsIDOMKeyListener*>(this),
|
||||
NS_LITERAL_STRING("dragleave"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
elmP->RemoveEventListenerByType(static_cast<nsIDOMKeyListener*>(this),
|
||||
NS_LITERAL_STRING("drop"),
|
||||
NS_EVENT_FLAG_BUBBLE, sysGroup);
|
||||
|
||||
piTarget->RemoveEventListenerByIID(static_cast<nsIDOMMouseListener*>(this),
|
||||
NS_GET_IID(nsIDOMMouseListener));
|
||||
|
||||
elmP->RemoveEventListenerByIID(static_cast<nsIDOMFocusListener*>(this),
|
||||
NS_GET_IID(nsIDOMFocusListener),
|
||||
NS_EVENT_FLAG_CAPTURE);
|
||||
|
||||
piTarget->RemoveEventListenerByIID(static_cast<nsIDOMTextListener*>(this),
|
||||
NS_GET_IID(nsIDOMTextListener));
|
||||
|
||||
piTarget->RemoveEventListenerByIID(
|
||||
static_cast<nsIDOMCompositionListener*>(this),
|
||||
NS_GET_IID(nsIDOMCompositionListener));
|
||||
}
|
||||
|
||||
already_AddRefed<nsIPresShell>
|
||||
nsEditorEventListener::GetPresShell()
|
||||
{
|
||||
NS_ENSURE_TRUE(mEditor, nsnull);
|
||||
// mEditor is nsEditor or its inherited class.
|
||||
// This is guaranteed by constructor.
|
||||
NS_PRECONDITION(mEditor,
|
||||
"The caller must check whether this is connected to an editor");
|
||||
nsCOMPtr<nsIPresShell> ps;
|
||||
static_cast<nsEditor*>(mEditor)->GetPresShell(getter_AddRefs(ps));
|
||||
mEditor->GetPresShell(getter_AddRefs(ps));
|
||||
return ps.forget();
|
||||
}
|
||||
|
||||
@ -121,6 +273,8 @@ NS_INTERFACE_MAP_END
|
||||
NS_IMETHODIMP
|
||||
nsEditorEventListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent);
|
||||
if (dragEvent) {
|
||||
nsAutoString eventType;
|
||||
@ -146,18 +300,24 @@ nsEditorEventListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
NS_IMETHODIMP
|
||||
nsEditorEventListener::KeyDown(nsIDOMEvent* aKeyEvent)
|
||||
{
|
||||
// WARNING: If you change this method, you comment out next line.
|
||||
// NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditorEventListener::KeyUp(nsIDOMEvent* aKeyEvent)
|
||||
{
|
||||
// WARNING: If you change this method, you comment out next line.
|
||||
// NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditorEventListener::KeyPress(nsIDOMEvent* aKeyEvent)
|
||||
{
|
||||
NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
// DOM event handling happens in two passes, the client pass and the system
|
||||
// pass. We do all of our processing in the system pass, to allow client
|
||||
// handlers the opportunity to cancel events and prevent typing in the editor.
|
||||
@ -184,8 +344,7 @@ nsEditorEventListener::KeyPress(nsIDOMEvent* aKeyEvent)
|
||||
keyEvent->GetKeyCode(&keyCode);
|
||||
|
||||
// if we are readonly or disabled, then do nothing.
|
||||
nsEditor* editor = static_cast<nsEditor*>(mEditor);
|
||||
if (editor->IsReadonly() || editor->IsDisabled())
|
||||
if (mEditor->IsReadonly() || mEditor->IsDisabled())
|
||||
{
|
||||
// consume backspace for disabled and readonly textfields, to prevent
|
||||
// back in history, which could be confusing to users
|
||||
@ -195,8 +354,9 @@ nsEditorEventListener::KeyPress(nsIDOMEvent* aKeyEvent)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPlaintextEditor> textEditor (do_QueryInterface(mEditor));
|
||||
if (!textEditor) return NS_ERROR_NO_INTERFACE;
|
||||
nsCOMPtr<nsIPlaintextEditor> textEditor =
|
||||
do_QueryInterface(static_cast<nsIEditor*>(mEditor));
|
||||
NS_ASSERTION(textEditor, "nsEditor must have nsIPlaintextEditor");
|
||||
|
||||
// if there is no charCode, then it's a key that doesn't map to a character,
|
||||
// so look for special keys using keyCode.
|
||||
@ -254,8 +414,8 @@ nsEditorEventListener::KeyPress(nsIDOMEvent* aKeyEvent)
|
||||
break;
|
||||
|
||||
case nsIDOMKeyEvent::DOM_VK_TAB:
|
||||
if (editor->IsSingleLineEditor() || editor->IsPasswordEditor() ||
|
||||
editor->IsFormWidget() || editor->IsInteractionAllowed()) {
|
||||
if (mEditor->IsSingleLineEditor() || mEditor->IsPasswordEditor() ||
|
||||
mEditor->IsFormWidget() || mEditor->IsInteractionAllowed()) {
|
||||
return NS_OK; // let it be used for focus switching
|
||||
}
|
||||
|
||||
@ -272,7 +432,7 @@ nsEditorEventListener::KeyPress(nsIDOMEvent* aKeyEvent)
|
||||
if (isAnyModifierKeyButShift)
|
||||
return NS_OK;
|
||||
|
||||
if (!editor->IsSingleLineEditor())
|
||||
if (!mEditor->IsSingleLineEditor())
|
||||
{
|
||||
textEditor->HandleKeyPress(keyEvent);
|
||||
aKeyEvent->PreventDefault(); // consumed
|
||||
@ -292,6 +452,8 @@ nsEditorEventListener::KeyPress(nsIDOMEvent* aKeyEvent)
|
||||
NS_IMETHODIMP
|
||||
nsEditorEventListener::MouseClick(nsIDOMEvent* aMouseEvent)
|
||||
{
|
||||
NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aMouseEvent);
|
||||
nsCOMPtr<nsIDOMNSEvent> nsevent = do_QueryInterface(aMouseEvent);
|
||||
PRBool isTrusted = PR_FALSE;
|
||||
@ -314,14 +476,9 @@ nsEditorEventListener::MouseClick(nsIDOMEvent* aMouseEvent)
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIEditor> editor = do_QueryInterface(mEditor);
|
||||
if (!editor) { return NS_OK; }
|
||||
|
||||
// If we got a mouse down inside the editing area, we should force the
|
||||
// IME to commit before we change the cursor position
|
||||
nsCOMPtr<nsIEditorIMESupport> imeEditor = do_QueryInterface(mEditor);
|
||||
if (imeEditor)
|
||||
imeEditor->ForceCompositionEnd();
|
||||
mEditor->ForceCompositionEnd();
|
||||
|
||||
PRUint16 button = (PRUint16)-1;
|
||||
mouseEvent->GetButton(&button);
|
||||
@ -345,7 +502,7 @@ nsEditorEventListener::MouseClick(nsIDOMEvent* aMouseEvent)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
if (NS_SUCCEEDED(editor->GetSelection(getter_AddRefs(selection))))
|
||||
if (NS_SUCCEEDED(mEditor->GetSelection(getter_AddRefs(selection))))
|
||||
(void)selection->Collapse(parent, offset);
|
||||
|
||||
// If the ctrl key is pressed, we'll do paste as quotation.
|
||||
@ -355,7 +512,7 @@ nsEditorEventListener::MouseClick(nsIDOMEvent* aMouseEvent)
|
||||
|
||||
nsCOMPtr<nsIEditorMailSupport> mailEditor;
|
||||
if (ctrlKey)
|
||||
mailEditor = do_QueryInterface(mEditor);
|
||||
mailEditor = do_QueryInterface(static_cast<nsIEditor*>(mEditor));
|
||||
|
||||
PRInt32 clipboard;
|
||||
|
||||
@ -368,7 +525,7 @@ nsEditorEventListener::MouseClick(nsIDOMEvent* aMouseEvent)
|
||||
if (mailEditor)
|
||||
mailEditor->PasteAsQuotation(clipboard);
|
||||
else
|
||||
editor->Paste(clipboard);
|
||||
mEditor->Paste(clipboard);
|
||||
|
||||
// Prevent the event from propagating up to be possibly handled
|
||||
// again by the containing window:
|
||||
@ -386,34 +543,40 @@ nsEditorEventListener::MouseClick(nsIDOMEvent* aMouseEvent)
|
||||
NS_IMETHODIMP
|
||||
nsEditorEventListener::MouseDown(nsIDOMEvent* aMouseEvent)
|
||||
{
|
||||
nsCOMPtr<nsIEditorIMESupport> imeEditor = do_QueryInterface(mEditor);
|
||||
if (!imeEditor)
|
||||
return NS_OK;
|
||||
imeEditor->ForceCompositionEnd();
|
||||
NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
mEditor->ForceCompositionEnd();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditorEventListener::MouseUp(nsIDOMEvent* aMouseEvent)
|
||||
{
|
||||
// WARNING: If you change this method, you comment out next line.
|
||||
// NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditorEventListener::MouseDblClick(nsIDOMEvent* aMouseEvent)
|
||||
{
|
||||
// WARNING: If you change this method, you comment out next line.
|
||||
// NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditorEventListener::MouseOver(nsIDOMEvent* aMouseEvent)
|
||||
{
|
||||
// WARNING: If you change this method, you comment out next line.
|
||||
// NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditorEventListener::MouseOut(nsIDOMEvent* aMouseEvent)
|
||||
{
|
||||
// WARNING: If you change this method, you comment out next line.
|
||||
// NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -424,6 +587,8 @@ nsEditorEventListener::MouseOut(nsIDOMEvent* aMouseEvent)
|
||||
NS_IMETHODIMP
|
||||
nsEditorEventListener::HandleText(nsIDOMEvent* aTextEvent)
|
||||
{
|
||||
NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsCOMPtr<nsIPrivateTextEvent> textEvent = do_QueryInterface(aTextEvent);
|
||||
if (!textEvent) {
|
||||
//non-ui event passed in. bad things.
|
||||
@ -436,13 +601,12 @@ nsEditorEventListener::HandleText(nsIDOMEvent* aTextEvent)
|
||||
textEvent->GetText(composedText);
|
||||
textRangeList = textEvent->GetInputRange();
|
||||
|
||||
nsEditor* editor = static_cast<nsEditor*>(mEditor);
|
||||
// if we are readonly or disabled, then do nothing.
|
||||
if (editor->IsReadonly() || editor->IsDisabled()) {
|
||||
if (mEditor->IsReadonly() || mEditor->IsDisabled()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return editor->SetCompositionString(composedText, textRangeList);
|
||||
return mEditor->SetCompositionString(composedText, textRangeList);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -452,9 +616,6 @@ nsEditorEventListener::HandleText(nsIDOMEvent* aTextEvent)
|
||||
nsresult
|
||||
nsEditorEventListener::DragGesture(nsIDOMDragEvent* aDragEvent)
|
||||
{
|
||||
if ( !mEditor )
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// ...figure out if a drag should be started...
|
||||
PRBool canDrag;
|
||||
nsresult rv = mEditor->CanDrag(aDragEvent, &canDrag);
|
||||
@ -574,9 +735,6 @@ nsEditorEventListener::Drop(nsIDOMDragEvent* aMouseEvent)
|
||||
}
|
||||
}
|
||||
|
||||
if (!mEditor)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMNSUIEvent> nsuiEvent = do_QueryInterface(aMouseEvent);
|
||||
if (nsuiEvent) {
|
||||
PRBool defaultPrevented;
|
||||
@ -598,8 +756,7 @@ nsEditorEventListener::Drop(nsIDOMDragEvent* aMouseEvent)
|
||||
if (!canDrop)
|
||||
{
|
||||
// was it because we're read-only?
|
||||
nsEditor* editor = static_cast<nsEditor*>(mEditor);
|
||||
if (editor->IsReadonly() || editor->IsDisabled())
|
||||
if (mEditor->IsReadonly() || mEditor->IsDisabled())
|
||||
{
|
||||
// it was decided to "eat" the event as this is the "least surprise"
|
||||
// since someone else handling it might be unintentional and the
|
||||
@ -621,8 +778,7 @@ PRBool
|
||||
nsEditorEventListener::CanDrop(nsIDOMDragEvent* aEvent)
|
||||
{
|
||||
// if the target doc is read-only, we can't drop
|
||||
nsEditor* editor = static_cast<nsEditor*>(mEditor);
|
||||
if (editor->IsReadonly() || editor->IsDisabled()) {
|
||||
if (mEditor->IsReadonly() || mEditor->IsDisabled()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
@ -642,7 +798,7 @@ nsEditorEventListener::CanDrop(nsIDOMDragEvent* aEvent)
|
||||
types->Contains(NS_LITERAL_STRING(kTextMime), &typeSupported);
|
||||
if (!typeSupported) {
|
||||
types->Contains(NS_LITERAL_STRING(kMozTextInternal), &typeSupported);
|
||||
if (!typeSupported && !editor->IsPlaintextEditor()) {
|
||||
if (!typeSupported && !mEditor->IsPlaintextEditor()) {
|
||||
types->Contains(NS_LITERAL_STRING(kHTMLMime), &typeSupported);
|
||||
if (!typeSupported) {
|
||||
types->Contains(NS_LITERAL_STRING(kFileMime), &typeSupported);
|
||||
@ -730,13 +886,15 @@ nsEditorEventListener::CanDrop(nsIDOMDragEvent* aEvent)
|
||||
NS_IMETHODIMP
|
||||
nsEditorEventListener::HandleStartComposition(nsIDOMEvent* aCompositionEvent)
|
||||
{
|
||||
return static_cast<nsEditor*>(mEditor)->BeginComposition();
|
||||
NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
return mEditor->BeginComposition();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditorEventListener::HandleEndComposition(nsIDOMEvent* aCompositionEvent)
|
||||
{
|
||||
return static_cast<nsEditor*>(mEditor)->EndComposition();
|
||||
NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
return mEditor->EndComposition();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -746,6 +904,7 @@ nsEditorEventListener::HandleEndComposition(nsIDOMEvent* aCompositionEvent)
|
||||
static already_AddRefed<nsIContent>
|
||||
FindSelectionRoot(nsEditor *aEditor, nsIContent *aContent)
|
||||
{
|
||||
NS_PRECONDITION(aEditor, "aEditor must not be null");
|
||||
nsIDocument *document = aContent->GetCurrentDoc();
|
||||
if (!document) {
|
||||
return nsnull;
|
||||
@ -790,79 +949,77 @@ FindSelectionRoot(nsEditor *aEditor, nsIContent *aContent)
|
||||
NS_IMETHODIMP
|
||||
nsEditorEventListener::Focus(nsIDOMEvent* aEvent)
|
||||
{
|
||||
NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
NS_ENSURE_ARG(aEvent);
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
aEvent->GetTarget(getter_AddRefs(target));
|
||||
|
||||
// turn on selection and caret
|
||||
if (mEditor)
|
||||
if (mEditor->IsDisabled()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(target);
|
||||
|
||||
PRBool targetIsEditableDoc = PR_FALSE;
|
||||
nsCOMPtr<nsIContent> editableRoot;
|
||||
if (content) {
|
||||
editableRoot = FindSelectionRoot(mEditor, content);
|
||||
|
||||
// make sure that the element is really focused in case an earlier
|
||||
// listener in the chain changed the focus.
|
||||
if (editableRoot) {
|
||||
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
NS_ENSURE_TRUE(fm, NS_OK);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
fm->GetFocusedElement(getter_AddRefs(element));
|
||||
if (!SameCOMIdentity(element, target))
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIDocument> document = do_QueryInterface(target);
|
||||
targetIsEditableDoc = document && document->HasFlag(NODE_IS_EDITABLE);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISelectionController> selCon;
|
||||
mEditor->GetSelectionController(getter_AddRefs(selCon));
|
||||
if (selCon && (targetIsEditableDoc || editableRoot))
|
||||
{
|
||||
nsEditor* editor = static_cast<nsEditor*>(mEditor);
|
||||
if (!editor->IsDisabled())
|
||||
{ // only enable caret and selection if the editor is not disabled
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(target);
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
|
||||
getter_AddRefs(selection));
|
||||
|
||||
PRBool targetIsEditableDoc = PR_FALSE;
|
||||
nsCOMPtr<nsIContent> editableRoot;
|
||||
if (content) {
|
||||
editableRoot = FindSelectionRoot(editor, content);
|
||||
|
||||
// make sure that the element is really focused in case an earlier
|
||||
// listener in the chain changed the focus.
|
||||
if (editableRoot) {
|
||||
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
NS_ENSURE_TRUE(fm, NS_OK);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
fm->GetFocusedElement(getter_AddRefs(element));
|
||||
if (!SameCOMIdentity(element, target))
|
||||
return NS_OK;
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
if (presShell) {
|
||||
nsRefPtr<nsCaret> caret = presShell->GetCaret();
|
||||
if (caret) {
|
||||
caret->SetIgnoreUserModify(PR_FALSE);
|
||||
if (selection) {
|
||||
caret->SetCaretDOMSelection(selection);
|
||||
}
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIDocument> document = do_QueryInterface(target);
|
||||
targetIsEditableDoc = document && document->HasFlag(NODE_IS_EDITABLE);
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISelectionController> selCon;
|
||||
mEditor->GetSelectionController(getter_AddRefs(selCon));
|
||||
if (selCon && (targetIsEditableDoc || editableRoot))
|
||||
{
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
|
||||
getter_AddRefs(selection));
|
||||
selCon->SetCaretReadOnly(mEditor->IsReadonly());
|
||||
selCon->SetCaretEnabled(PR_TRUE);
|
||||
selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
|
||||
selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL);
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
if (presShell) {
|
||||
nsRefPtr<nsCaret> caret = presShell->GetCaret();
|
||||
if (caret) {
|
||||
caret->SetIgnoreUserModify(PR_FALSE);
|
||||
if (selection) {
|
||||
caret->SetCaretDOMSelection(selection);
|
||||
}
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsISelectionPrivate> selectionPrivate =
|
||||
do_QueryInterface(selection);
|
||||
if (selectionPrivate)
|
||||
{
|
||||
selectionPrivate->SetAncestorLimiter(editableRoot);
|
||||
}
|
||||
|
||||
selCon->SetCaretReadOnly(editor->IsReadonly());
|
||||
selCon->SetCaretEnabled(PR_TRUE);
|
||||
selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
|
||||
selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL);
|
||||
|
||||
nsCOMPtr<nsISelectionPrivate> selectionPrivate =
|
||||
do_QueryInterface(selection);
|
||||
if (selectionPrivate)
|
||||
{
|
||||
selectionPrivate->SetAncestorLimiter(editableRoot);
|
||||
}
|
||||
|
||||
if (selection && !editableRoot) {
|
||||
PRInt32 rangeCount;
|
||||
selection->GetRangeCount(&rangeCount);
|
||||
if (rangeCount == 0) {
|
||||
mEditor->BeginningOfDocument();
|
||||
}
|
||||
}
|
||||
if (selection && !editableRoot) {
|
||||
PRInt32 rangeCount;
|
||||
selection->GetRangeCount(&rangeCount);
|
||||
if (rangeCount == 0) {
|
||||
mEditor->BeginningOfDocument();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -872,6 +1029,9 @@ nsEditorEventListener::Focus(nsIDOMEvent* aEvent)
|
||||
NS_IMETHODIMP
|
||||
nsEditorEventListener::Blur(nsIDOMEvent* aEvent)
|
||||
{
|
||||
NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
NS_ENSURE_ARG(aEvent);
|
||||
|
||||
// check if something else is focused. If another element is focused, then
|
||||
// we should not change the selection.
|
||||
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
@ -882,52 +1042,43 @@ nsEditorEventListener::Blur(nsIDOMEvent* aEvent)
|
||||
if (element)
|
||||
return NS_OK;
|
||||
|
||||
NS_ENSURE_ARG(aEvent);
|
||||
// turn off selection and caret
|
||||
if (mEditor)
|
||||
nsCOMPtr<nsISelectionController>selCon;
|
||||
mEditor->GetSelectionController(getter_AddRefs(selCon));
|
||||
if (selCon)
|
||||
{
|
||||
nsCOMPtr<nsIEditor>editor = do_QueryInterface(mEditor);
|
||||
if (editor)
|
||||
{
|
||||
nsCOMPtr<nsISelectionController>selCon;
|
||||
editor->GetSelectionController(getter_AddRefs(selCon));
|
||||
if (selCon)
|
||||
{
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
|
||||
getter_AddRefs(selection));
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
|
||||
getter_AddRefs(selection));
|
||||
|
||||
nsCOMPtr<nsISelectionPrivate> selectionPrivate =
|
||||
do_QueryInterface(selection);
|
||||
if (selectionPrivate) {
|
||||
selectionPrivate->SetAncestorLimiter(nsnull);
|
||||
}
|
||||
nsCOMPtr<nsISelectionPrivate> selectionPrivate =
|
||||
do_QueryInterface(selection);
|
||||
if (selectionPrivate) {
|
||||
selectionPrivate->SetAncestorLimiter(nsnull);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
if (presShell) {
|
||||
nsRefPtr<nsCaret> caret = presShell->GetCaret();
|
||||
if (caret) {
|
||||
caret->SetIgnoreUserModify(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
selCon->SetCaretEnabled(PR_FALSE);
|
||||
|
||||
nsEditor* editor = static_cast<nsEditor*>(mEditor);
|
||||
if(editor->IsFormWidget() || editor->IsPasswordEditor() ||
|
||||
editor->IsReadonly() || editor->IsDisabled() ||
|
||||
editor->IsInputFiltered())
|
||||
{
|
||||
selCon->SetDisplaySelection(nsISelectionController::SELECTION_HIDDEN);//hide but do NOT turn off
|
||||
}
|
||||
else
|
||||
{
|
||||
selCon->SetDisplaySelection(nsISelectionController::SELECTION_DISABLED);
|
||||
}
|
||||
|
||||
selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL);
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
if (presShell) {
|
||||
nsRefPtr<nsCaret> caret = presShell->GetCaret();
|
||||
if (caret) {
|
||||
caret->SetIgnoreUserModify(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
selCon->SetCaretEnabled(PR_FALSE);
|
||||
|
||||
if(mEditor->IsFormWidget() || mEditor->IsPasswordEditor() ||
|
||||
mEditor->IsReadonly() || mEditor->IsDisabled() ||
|
||||
mEditor->IsInputFiltered())
|
||||
{
|
||||
selCon->SetDisplaySelection(nsISelectionController::SELECTION_HIDDEN);//hide but do NOT turn off
|
||||
}
|
||||
else
|
||||
{
|
||||
selCon->SetDisplaySelection(nsISelectionController::SELECTION_DISABLED);
|
||||
}
|
||||
|
||||
selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -61,9 +61,13 @@ class nsEditorEventListener : public nsIDOMKeyListener,
|
||||
public nsIDOMFocusListener
|
||||
{
|
||||
public:
|
||||
nsEditorEventListener(nsEditor* aEditor);
|
||||
nsEditorEventListener();
|
||||
virtual ~nsEditorEventListener();
|
||||
|
||||
virtual nsresult Connect(nsEditor* aEditor);
|
||||
|
||||
void Disconnect();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
@ -92,6 +96,9 @@ public:
|
||||
NS_IMETHOD Blur(nsIDOMEvent* aEvent);
|
||||
|
||||
protected:
|
||||
nsresult InstallToEditor();
|
||||
void UninstallFromEditor();
|
||||
|
||||
PRBool CanDrop(nsIDOMDragEvent* aEvent);
|
||||
nsresult DragEnter(nsIDOMDragEvent* aDragEvent);
|
||||
nsresult DragOver(nsIDOMDragEvent* aDragEvent);
|
||||
@ -101,7 +108,7 @@ protected:
|
||||
already_AddRefed<nsIPresShell> GetPresShell();
|
||||
|
||||
protected:
|
||||
nsIEditor* mEditor; // weak
|
||||
nsEditor* mEditor; // weak
|
||||
nsRefPtr<nsCaret> mCaret;
|
||||
PRPackedBool mCaretDrawn;
|
||||
PRPackedBool mCommitText;
|
||||
|
@ -336,11 +336,21 @@ nsHTMLEditor::CreateEventListeners()
|
||||
{
|
||||
NS_ENSURE_TRUE(!mEventListener, NS_ERROR_ALREADY_INITIALIZED);
|
||||
mEventListener = do_QueryInterface(
|
||||
static_cast<nsIDOMKeyListener*>(new nsHTMLEditorEventListener(this)));
|
||||
static_cast<nsIDOMKeyListener*>(new nsHTMLEditorEventListener()));
|
||||
NS_ENSURE_TRUE(mEventListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditor::InstallEventListeners()
|
||||
{
|
||||
NS_ENSURE_TRUE(mDocWeak && mPresShellWeak && mEventListener,
|
||||
NS_ERROR_NOT_INITIALIZED);
|
||||
nsHTMLEditorEventListener* listener =
|
||||
reinterpret_cast<nsHTMLEditorEventListener*>(mEventListener.get());
|
||||
return listener->Connect(this);
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLEditor::RemoveEventListeners()
|
||||
{
|
||||
|
@ -429,6 +429,7 @@ protected:
|
||||
// Create the event listeners for the editor to install
|
||||
virtual nsresult CreateEventListeners();
|
||||
|
||||
virtual nsresult InstallEventListeners();
|
||||
virtual void RemoveEventListeners();
|
||||
|
||||
// Return TRUE if aElement is a table-related elemet and caret was set
|
||||
|
@ -38,6 +38,7 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#include "nsHTMLEditorEventListener.h"
|
||||
#include "nsHTMLEditor.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "nsIDOMEvent.h"
|
||||
@ -53,13 +54,10 @@
|
||||
#include "nsIDOMHTMLTableCellElement.h"
|
||||
#include "nsIContent.h"
|
||||
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIHTMLEditor.h"
|
||||
#include "nsIHTMLObjectResizer.h"
|
||||
#include "nsEditProperty.h"
|
||||
#include "nsTextEditUtils.h"
|
||||
#include "nsHTMLEditUtils.h"
|
||||
#include "nsIHTMLInlineTableEditor.h"
|
||||
|
||||
/*
|
||||
* nsHTMLEditorEventListener implementation
|
||||
@ -68,31 +66,50 @@
|
||||
* moves the caret or selects an element as it does for normal click
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
nsresult
|
||||
nsHTMLEditorEventListener::Connect(nsEditor* aEditor)
|
||||
{
|
||||
nsCOMPtr<nsIHTMLEditor> htmlEditor =
|
||||
do_QueryInterface(static_cast<nsIEditor*>(aEditor));
|
||||
nsCOMPtr<nsIHTMLInlineTableEditor> htmlInlineTableEditor =
|
||||
do_QueryInterface(static_cast<nsIEditor*>(aEditor));
|
||||
NS_PRECONDITION(htmlEditor && htmlInlineTableEditor,
|
||||
"Set nsHTMLEditor or its sub class");
|
||||
return nsEditorEventListener::Connect(aEditor);
|
||||
}
|
||||
#endif
|
||||
|
||||
nsHTMLEditor*
|
||||
nsHTMLEditorEventListener::GetHTMLEditor()
|
||||
{
|
||||
// mEditor must be nsHTMLEditor or its subclass.
|
||||
return static_cast<nsHTMLEditor*>(mEditor);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditorEventListener::MouseUp(nsIDOMEvent* aMouseEvent)
|
||||
{
|
||||
NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
|
||||
if (!mouseEvent) {
|
||||
//non-ui event passed in. bad things.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Don't do anything special if not an HTML editor
|
||||
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(mEditor);
|
||||
if (htmlEditor)
|
||||
{
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
nsresult res = aMouseEvent->GetTarget(getter_AddRefs(target));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!target) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
|
||||
nsHTMLEditor* htmlEditor = GetHTMLEditor();
|
||||
|
||||
nsCOMPtr<nsIHTMLObjectResizer> objectResizer = do_QueryInterface(htmlEditor);
|
||||
PRInt32 clientX, clientY;
|
||||
mouseEvent->GetClientX(&clientX);
|
||||
mouseEvent->GetClientY(&clientY);
|
||||
objectResizer->MouseUp(clientX, clientY, element);
|
||||
}
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
nsresult res = aMouseEvent->GetTarget(getter_AddRefs(target));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!target) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
|
||||
|
||||
PRInt32 clientX, clientY;
|
||||
mouseEvent->GetClientX(&clientX);
|
||||
mouseEvent->GetClientY(&clientY);
|
||||
htmlEditor->MouseUp(clientX, clientY, element);
|
||||
|
||||
return nsEditorEventListener::MouseUp(aMouseEvent);
|
||||
}
|
||||
@ -100,175 +117,172 @@ nsHTMLEditorEventListener::MouseUp(nsIDOMEvent* aMouseEvent)
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditorEventListener::MouseDown(nsIDOMEvent* aMouseEvent)
|
||||
{
|
||||
NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
|
||||
if (!mouseEvent) {
|
||||
//non-ui event passed in. bad things.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Don't do anything special if not an HTML editor
|
||||
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(mEditor);
|
||||
if (htmlEditor)
|
||||
{
|
||||
// Detect only "context menu" click
|
||||
//XXX This should be easier to do!
|
||||
// But eDOMEvents_contextmenu and NS_CONTEXTMENU is not exposed in any event interface :-(
|
||||
PRUint16 buttonNumber;
|
||||
nsresult res = mouseEvent->GetButton(&buttonNumber);
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsHTMLEditor* htmlEditor = GetHTMLEditor();
|
||||
|
||||
PRBool isContextClick;
|
||||
// Detect only "context menu" click
|
||||
//XXX This should be easier to do!
|
||||
// But eDOMEvents_contextmenu and NS_CONTEXTMENU is not exposed in any event interface :-(
|
||||
PRUint16 buttonNumber;
|
||||
nsresult res = mouseEvent->GetButton(&buttonNumber);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
PRBool isContextClick;
|
||||
|
||||
#if defined(XP_MAC) || defined(XP_MACOSX)
|
||||
// Ctrl+Click for context menu
|
||||
res = mouseEvent->GetCtrlKey(&isContextClick);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// Ctrl+Click for context menu
|
||||
res = mouseEvent->GetCtrlKey(&isContextClick);
|
||||
if (NS_FAILED(res)) return res;
|
||||
#else
|
||||
// Right mouse button for Windows, UNIX
|
||||
isContextClick = buttonNumber == 2;
|
||||
// Right mouse button for Windows, UNIX
|
||||
isContextClick = buttonNumber == 2;
|
||||
#endif
|
||||
|
||||
PRInt32 clickCount;
|
||||
res = mouseEvent->GetDetail(&clickCount);
|
||||
|
||||
PRInt32 clickCount;
|
||||
res = mouseEvent->GetDetail(&clickCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
nsCOMPtr<nsIDOMNSEvent> internalEvent = do_QueryInterface(aMouseEvent);
|
||||
res = internalEvent->GetExplicitOriginalTarget(getter_AddRefs(target));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!target) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
|
||||
|
||||
if (isContextClick || (buttonNumber == 0 && clickCount == 2))
|
||||
{
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (!selection) return NS_OK;
|
||||
|
||||
// Get location of mouse within target node
|
||||
nsCOMPtr<nsIDOMNSUIEvent> uiEvent = do_QueryInterface(aMouseEvent);
|
||||
if (!uiEvent) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset = 0;
|
||||
|
||||
res = uiEvent->GetRangeParent(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!parent) return NS_ERROR_FAILURE;
|
||||
|
||||
res = uiEvent->GetRangeOffset(&offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
nsCOMPtr<nsIDOMNSEvent> internalEvent = do_QueryInterface(aMouseEvent);
|
||||
res = internalEvent->GetExplicitOriginalTarget(getter_AddRefs(target));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!target) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
|
||||
|
||||
if (isContextClick || (buttonNumber == 0 && clickCount == 2))
|
||||
// Detect if mouse point is within current selection for context click
|
||||
PRBool nodeIsInSelection = PR_FALSE;
|
||||
if (isContextClick)
|
||||
{
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (!selection) return NS_OK;
|
||||
|
||||
// Get location of mouse within target node
|
||||
nsCOMPtr<nsIDOMNSUIEvent> uiEvent = do_QueryInterface(aMouseEvent);
|
||||
if (!uiEvent) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset = 0;
|
||||
|
||||
res = uiEvent->GetRangeParent(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!parent) return NS_ERROR_FAILURE;
|
||||
|
||||
res = uiEvent->GetRangeOffset(&offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// Detect if mouse point is within current selection for context click
|
||||
PRBool nodeIsInSelection = PR_FALSE;
|
||||
if (isContextClick)
|
||||
PRBool isCollapsed;
|
||||
selection->GetIsCollapsed(&isCollapsed);
|
||||
if (!isCollapsed)
|
||||
{
|
||||
PRBool isCollapsed;
|
||||
selection->GetIsCollapsed(&isCollapsed);
|
||||
if (!isCollapsed)
|
||||
PRInt32 rangeCount;
|
||||
res = selection->GetRangeCount(&rangeCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
for (PRInt32 i = 0; i < rangeCount; i++)
|
||||
{
|
||||
PRInt32 rangeCount;
|
||||
res = selection->GetRangeCount(&rangeCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
|
||||
for (PRInt32 i = 0; i < rangeCount; i++)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
res = selection->GetRangeAt(i, getter_AddRefs(range));
|
||||
if (NS_FAILED(res) || !range)
|
||||
continue;//don't bail yet, iterate through them all
|
||||
|
||||
res = selection->GetRangeAt(i, getter_AddRefs(range));
|
||||
if (NS_FAILED(res) || !range)
|
||||
continue;//don't bail yet, iterate through them all
|
||||
nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));
|
||||
if (NS_FAILED(res) || !nsrange)
|
||||
continue;//don't bail yet, iterate through them all
|
||||
|
||||
nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));
|
||||
if (NS_FAILED(res) || !nsrange)
|
||||
continue;//don't bail yet, iterate through them all
|
||||
res = nsrange->IsPointInRange(parent, offset, &nodeIsInSelection);
|
||||
|
||||
res = nsrange->IsPointInRange(parent, offset, &nodeIsInSelection);
|
||||
|
||||
// Done when we find a range that we are in
|
||||
if (nodeIsInSelection)
|
||||
break;
|
||||
}
|
||||
// Done when we find a range that we are in
|
||||
if (nodeIsInSelection)
|
||||
break;
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(target);
|
||||
if (node && !nodeIsInSelection)
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(target);
|
||||
if (node && !nodeIsInSelection)
|
||||
{
|
||||
if (!element)
|
||||
{
|
||||
if (!element)
|
||||
if (isContextClick)
|
||||
{
|
||||
if (isContextClick)
|
||||
// Set the selection to the point under the mouse cursor:
|
||||
selection->Collapse(parent, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get enclosing link if in text so we can select the link
|
||||
nsCOMPtr<nsIDOMElement> linkElement;
|
||||
res = htmlEditor->GetElementOrParentByTagName(NS_LITERAL_STRING("href"), node, getter_AddRefs(linkElement));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (linkElement)
|
||||
element = linkElement;
|
||||
}
|
||||
}
|
||||
// Select entire element clicked on if NOT within an existing selection
|
||||
// and not the entire body, or table-related elements
|
||||
if (element)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> selectAllNode =
|
||||
htmlEditor->FindUserSelectAllNode(element);
|
||||
|
||||
if (selectAllNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement> newElement = do_QueryInterface(selectAllNode);
|
||||
if (newElement)
|
||||
{
|
||||
// Set the selection to the point under the mouse cursor:
|
||||
selection->Collapse(parent, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get enclosing link if in text so we can select the link
|
||||
nsCOMPtr<nsIDOMElement> linkElement;
|
||||
res = htmlEditor->GetElementOrParentByTagName(NS_LITERAL_STRING("href"), node, getter_AddRefs(linkElement));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (linkElement)
|
||||
element = linkElement;
|
||||
node = selectAllNode;
|
||||
element = newElement;
|
||||
}
|
||||
}
|
||||
// Select entire element clicked on if NOT within an existing selection
|
||||
// and not the entire body, or table-related elements
|
||||
if (element)
|
||||
{
|
||||
// mEditor must be nsHTMLEditor, see the constructor.
|
||||
nsCOMPtr<nsIDOMNode> selectAllNode =
|
||||
reinterpret_cast<nsHTMLEditor*>(mEditor)->FindUserSelectAllNode(element);
|
||||
|
||||
if (selectAllNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement> newElement = do_QueryInterface(selectAllNode);
|
||||
if (newElement)
|
||||
{
|
||||
node = selectAllNode;
|
||||
element = newElement;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: should we call nsHTMLEditUtils::IsTableElement here?
|
||||
// that also checks for thead, tbody, tfoot
|
||||
if (nsTextEditUtils::IsBody(node) ||
|
||||
nsHTMLEditUtils::IsTableCellOrCaption(node) ||
|
||||
nsHTMLEditUtils::IsTableRow(node) ||
|
||||
nsHTMLEditUtils::IsTable(node))
|
||||
{
|
||||
// This will place caret just inside table cell or at start of body
|
||||
selection->Collapse(parent, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
htmlEditor->SelectElement(element);
|
||||
}
|
||||
if (nsTextEditUtils::IsBody(node) ||
|
||||
nsHTMLEditUtils::IsTableCellOrCaption(node) ||
|
||||
nsHTMLEditUtils::IsTableRow(node) ||
|
||||
nsHTMLEditUtils::IsTable(node))
|
||||
{
|
||||
// This will place caret just inside table cell or at start of body
|
||||
selection->Collapse(parent, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
htmlEditor->SelectElement(element);
|
||||
}
|
||||
}
|
||||
// HACK !!! Context click places the caret but the context menu consumes
|
||||
// the event; so we need to check resizing state ourselves
|
||||
htmlEditor->CheckSelectionStateForAnonymousButtons(selection);
|
||||
}
|
||||
// HACK !!! Context click places the caret but the context menu consumes
|
||||
// the event; so we need to check resizing state ourselves
|
||||
htmlEditor->CheckSelectionStateForAnonymousButtons(selection);
|
||||
|
||||
// Prevent bubbling if we changed selection or
|
||||
// for all context clicks
|
||||
if (element || isContextClick)
|
||||
{
|
||||
#ifndef XP_OS2
|
||||
mouseEvent->PreventDefault();
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
else if (!isContextClick && buttonNumber == 0 && clickCount == 1)
|
||||
// Prevent bubbling if we changed selection or
|
||||
// for all context clicks
|
||||
if (element || isContextClick)
|
||||
{
|
||||
// if the target element is an image, we have to display resizers
|
||||
nsCOMPtr<nsIHTMLObjectResizer> objectResizer = do_QueryInterface(htmlEditor);
|
||||
PRInt32 clientX, clientY;
|
||||
mouseEvent->GetClientX(&clientX);
|
||||
mouseEvent->GetClientY(&clientY);
|
||||
objectResizer->MouseDown(clientX, clientY, element, aMouseEvent);
|
||||
#ifndef XP_OS2
|
||||
mouseEvent->PreventDefault();
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
else if (!isContextClick && buttonNumber == 0 && clickCount == 1)
|
||||
{
|
||||
// if the target element is an image, we have to display resizers
|
||||
PRInt32 clientX, clientY;
|
||||
mouseEvent->GetClientX(&clientX);
|
||||
mouseEvent->GetClientY(&clientY);
|
||||
htmlEditor->MouseDown(clientX, clientY, element, aMouseEvent);
|
||||
}
|
||||
|
||||
return nsEditorEventListener::MouseDown(aMouseEvent);
|
||||
}
|
||||
@ -276,24 +290,21 @@ nsHTMLEditorEventListener::MouseDown(nsIDOMEvent* aMouseEvent)
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditorEventListener::MouseClick(nsIDOMEvent* aMouseEvent)
|
||||
{
|
||||
NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
|
||||
if (!mouseEvent) {
|
||||
//non-ui event passed in. bad things.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Don't do anything special if not an HTML inline table editor
|
||||
nsCOMPtr<nsIHTMLInlineTableEditor> inlineTableEditing = do_QueryInterface(mEditor);
|
||||
if (inlineTableEditing)
|
||||
{
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
nsresult res = aMouseEvent->GetTarget(getter_AddRefs(target));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!target) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
nsresult res = aMouseEvent->GetTarget(getter_AddRefs(target));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!target) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
|
||||
|
||||
inlineTableEditing->DoInlineTableEditingAction(element);
|
||||
}
|
||||
GetHTMLEditor()->DoInlineTableEditingAction(element);
|
||||
|
||||
return nsEditorEventListener::MouseClick(aMouseEvent);
|
||||
}
|
||||
|
@ -41,13 +41,14 @@
|
||||
#define nsHTMLEditorEventListener_h__
|
||||
|
||||
#include "nsEditorEventListener.h"
|
||||
#include "nsHTMLEditor.h"
|
||||
|
||||
class nsHTMLEditor;
|
||||
|
||||
class nsHTMLEditorEventListener : public nsEditorEventListener
|
||||
{
|
||||
public:
|
||||
nsHTMLEditorEventListener(nsHTMLEditor* aEditor) :
|
||||
nsEditorEventListener(aEditor)
|
||||
nsHTMLEditorEventListener() :
|
||||
nsEditorEventListener()
|
||||
{
|
||||
}
|
||||
|
||||
@ -55,9 +56,17 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// WARNING: You must be use nsHTMLEditor or its sub class for this class.
|
||||
virtual nsresult Connect(nsEditor* aEditor);
|
||||
#endif
|
||||
|
||||
NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent);
|
||||
NS_IMETHOD MouseUp(nsIDOMEvent* aMouseEvent);
|
||||
NS_IMETHOD MouseClick(nsIDOMEvent* aMouseEvent);
|
||||
|
||||
protected:
|
||||
inline nsHTMLEditor* GetHTMLEditor();
|
||||
};
|
||||
|
||||
#endif // nsHTMLEditorEventListener_h__
|
||||
|
Loading…
Reference in New Issue
Block a user