This commit is contained in:
jst@mozilla.org 2007-07-25 21:14:33 -07:00
Родитель b1511aaf4e
Коммит 7c61932818
15 изменённых файлов: 467 добавлений и 33 удалений

Просмотреть файл

@ -47,6 +47,7 @@ class nsIContent;
class nsITransferable;
class nsACString;
class nsAString;
class nsIDOMNode;
class nsCopySupport
{
@ -64,6 +65,11 @@ class nsCopySupport
static nsresult ImageCopy(nsIImageLoadingContent* aImageElement,
PRInt32 aCopyFlags);
// Given the current selection, find the target that
// before[copy,cut,paste] and [copy,cut,paste] events will fire on.
static nsresult GetClipboardEventTarget(nsISelection *aSel,
nsIDOMNode **aEventTarget);
};
#endif

Просмотреть файл

@ -375,6 +375,12 @@ nsContentUtils::InitializeEventTable() {
(EventNameType_HTMLXUL | EventNameType_SVGSVG) }},
{ &nsGkAtoms::onscroll, { NS_SCROLL_EVENT,
(EventNameType_HTMLXUL | EventNameType_SVGSVG) }},
{ &nsGkAtoms::oncopy, { NS_COPY, EventNameType_HTMLXUL }},
{ &nsGkAtoms::oncut, { NS_CUT, EventNameType_HTMLXUL }},
{ &nsGkAtoms::onpaste, { NS_PASTE, EventNameType_HTMLXUL }},
{ &nsGkAtoms::onbeforecopy, { NS_BEFORECOPY, EventNameType_HTMLXUL }},
{ &nsGkAtoms::onbeforecut, { NS_BEFORECUT, EventNameType_HTMLXUL }},
{ &nsGkAtoms::onbeforepaste, { NS_BEFOREPASTE, EventNameType_HTMLXUL }},
// XUL specific events
{ &nsGkAtoms::ontext, { NS_TEXT_TEXT, EventNameType_XUL }},
{ &nsGkAtoms::oncompositionstart, { NS_COMPOSITION_START, EventNameType_XUL }},

Просмотреть файл

@ -545,3 +545,27 @@ static nsresult AppendDOMNode(nsITransferable *aTransferable,
// add a special flavor, even if we don't have html context data
return AppendString(aTransferable, context, kHTMLContext);
}
// Find the target that onbefore[copy,cut,paste] and on[copy,cut,paste]
// events will fire on -- the start node of the copy selection.
nsresult nsCopySupport::GetClipboardEventTarget(nsISelection *aSel,
nsIDOMNode **aEventTarget)
{
NS_ENSURE_ARG(aSel);
NS_ENSURE_ARG_POINTER(aEventTarget);
*aEventTarget = nsnull;
nsCOMPtr<nsIDOMRange> range;
nsresult rv = aSel->GetRangeAt(0, getter_AddRefs(range));
if (rv == NS_ERROR_INVALID_ARG) // empty selection
return NS_ERROR_FAILURE;
NS_ENSURE_SUCCESS(rv, rv);
if (!range)
return NS_ERROR_FAILURE;
rv = range->GetStartContainer(aEventTarget);
NS_ENSURE_SUCCESS(rv, rv);
return (*aEventTarget) ? NS_OK : NS_ERROR_FAILURE;
}

Просмотреть файл

@ -545,6 +545,9 @@ GK_ATOM(OFF, "OFF")
GK_ATOM(ol, "ol")
GK_ATOM(omitXmlDeclaration, "omit-xml-declaration")
GK_ATOM(onabort, "onabort")
GK_ATOM(onbeforecopy, "onbeforecopy")
GK_ATOM(onbeforecut, "onbeforecut")
GK_ATOM(onbeforepaste, "onbeforepaste")
GK_ATOM(onbeforeunload, "onbeforeunload")
GK_ATOM(onblur, "onblur")
GK_ATOM(onbroadcast, "onbroadcast")
@ -556,6 +559,8 @@ GK_ATOM(oncommandupdate, "oncommandupdate")
GK_ATOM(oncompositionend, "oncompositionend")
GK_ATOM(oncompositionstart, "oncompositionstart")
GK_ATOM(oncontextmenu, "oncontextmenu")
GK_ATOM(oncopy, "oncopy")
GK_ATOM(oncut, "oncut")
GK_ATOM(ondblclick, "ondblclick")
GK_ATOM(onDOMActivate, "onDOMActivate")
GK_ATOM(onDOMAttrModified, "onDOMAttrModified")
@ -599,6 +604,7 @@ GK_ATOM(onoverflowchanged, "onoverflowchanged")
GK_ATOM(onpagehide, "onpagehide")
GK_ATOM(onpageshow, "onpageshow")
GK_ATOM(onpaint, "onpaint")
GK_ATOM(onpaste, "onpaste")
GK_ATOM(onpopuphidden, "onpopuphidden")
GK_ATOM(onpopuphiding, "onpopuphiding")
GK_ATOM(onpopupshowing, "onpopupshowing")

Просмотреть файл

@ -70,7 +70,8 @@ static const char* const sEventNames[] = {
"DOMNodeRemovedFromDocument", "DOMNodeInsertedIntoDocument",
"DOMAttrModified", "DOMCharacterDataModified",
"DOMActivate", "DOMFocusIn", "DOMFocusOut",
"pageshow", "pagehide", "DOMMouseScroll", "offline", "online"
"pageshow", "pagehide", "DOMMouseScroll", "offline", "online",
"copy", "cut", "paste", "beforecopy", "beforecut", "beforepaste"
#ifdef MOZ_SVG
,
"SVGLoad", "SVGUnload", "SVGAbort", "SVGError", "SVGResize", "SVGScroll",
@ -497,6 +498,18 @@ nsDOMEvent::SetEventType(const nsAString& aEventTypeArg)
mEvent->message = NS_OFFLINE;
else if (atom == nsGkAtoms::ononline)
mEvent->message = NS_ONLINE;
else if (atom == nsGkAtoms::oncopy)
mEvent->message = NS_COPY;
else if (atom == nsGkAtoms::oncut)
mEvent->message = NS_CUT;
else if (atom == nsGkAtoms::onpaste)
mEvent->message = NS_PASTE;
else if (atom == nsGkAtoms::onbeforecopy)
mEvent->message = NS_BEFORECOPY;
else if (atom == nsGkAtoms::onbeforecut)
mEvent->message = NS_BEFORECUT;
else if (atom == nsGkAtoms::onbeforepaste)
mEvent->message = NS_BEFOREPASTE;
} else if (mEvent->eventStructType == NS_MUTATION_EVENT) {
if (atom == nsGkAtoms::onDOMAttrModified)
mEvent->message = NS_MUTATION_ATTRMODIFIED;
@ -1301,6 +1314,18 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
return sEventNames[eDOMEvents_offline];
case NS_ONLINE:
return sEventNames[eDOMEvents_online];
case NS_COPY:
return sEventNames[eDOMEvents_copy];
case NS_CUT:
return sEventNames[eDOMEvents_cut];
case NS_PASTE:
return sEventNames[eDOMEvents_paste];
case NS_BEFORECOPY:
return sEventNames[eDOMEvents_beforecopy];
case NS_BEFORECUT:
return sEventNames[eDOMEvents_beforecut];
case NS_BEFOREPASTE:
return sEventNames[eDOMEvents_beforepaste];
#ifdef MOZ_SVG
case NS_SVG_LOAD:
return sEventNames[eDOMEvents_SVGLoad];

Просмотреть файл

@ -125,7 +125,13 @@ public:
eDOMEvents_pagehide,
eDOMEvents_DOMMouseScroll,
eDOMEvents_offline,
eDOMEvents_online
eDOMEvents_online,
eDOMEvents_copy,
eDOMEvents_cut,
eDOMEvents_paste,
eDOMEvents_beforecopy,
eDOMEvents_beforecut,
eDOMEvents_beforepaste
#ifdef MOZ_SVG
,
eDOMEvents_SVGLoad,

Просмотреть файл

@ -1305,6 +1305,12 @@ jsval nsDOMClassInfo::sAddEventListener_id= JSVAL_VOID;
jsval nsDOMClassInfo::sBaseURIObject_id = JSVAL_VOID;
jsval nsDOMClassInfo::sNodePrincipal_id = JSVAL_VOID;
jsval nsDOMClassInfo::sDocumentURIObject_id=JSVAL_VOID;
jsval nsDOMClassInfo::sOncopy_id = JSVAL_VOID;
jsval nsDOMClassInfo::sOncut_id = JSVAL_VOID;
jsval nsDOMClassInfo::sOnpaste_id = JSVAL_VOID;
jsval nsDOMClassInfo::sOnbeforecopy_id = JSVAL_VOID;
jsval nsDOMClassInfo::sOnbeforecut_id = JSVAL_VOID;
jsval nsDOMClassInfo::sOnbeforepaste_id = JSVAL_VOID;
const JSClass *nsDOMClassInfo::sObjectClass = nsnull;
const JSClass *nsDOMClassInfo::sXPCNativeWrapperClass = nsnull;
@ -1496,6 +1502,12 @@ nsDOMClassInfo::DefineStaticJSVals(JSContext *cx)
SET_JSVAL_TO_STRING(sBaseURIObject_id, cx, "baseURIObject");
SET_JSVAL_TO_STRING(sNodePrincipal_id, cx, "nodePrincipal");
SET_JSVAL_TO_STRING(sDocumentURIObject_id,cx,"documentURIObject");
SET_JSVAL_TO_STRING(sOncopy_id, cx, "oncopy");
SET_JSVAL_TO_STRING(sOncut_id, cx, "oncut");
SET_JSVAL_TO_STRING(sOnpaste_id, cx, "onpaste");
SET_JSVAL_TO_STRING(sOnbeforecopy_id, cx, "oncopy");
SET_JSVAL_TO_STRING(sOnbeforecut_id, cx, "oncut");
SET_JSVAL_TO_STRING(sOnbeforepaste_id, cx, "onpaste");
return NS_OK;
}
@ -3972,6 +3984,12 @@ nsDOMClassInfo::ShutDown()
sBaseURIObject_id = JSVAL_VOID;
sNodePrincipal_id = JSVAL_VOID;
sDocumentURIObject_id=JSVAL_VOID;
sOncopy_id = JSVAL_VOID;
sOncut_id = JSVAL_VOID;
sOnpaste_id = JSVAL_VOID;
sOnbeforecopy_id = JSVAL_VOID;
sOnbeforecut_id = JSVAL_VOID;
sOnbeforepaste_id = JSVAL_VOID;
NS_IF_RELEASE(sXPConnect);
NS_IF_RELEASE(sSecMan);
@ -6629,7 +6647,10 @@ nsEventReceiverSH::ReallyIsEventName(jsval id, jschar aFirstChar)
return id == sOnabort_id;
case 'b' :
return (id == sOnbeforeunload_id ||
id == sOnblur_id);
id == sOnblur_id ||
id == sOnbeforecopy_id ||
id == sOnbeforecut_id ||
id == sOnbeforepaste_id);
case 'e' :
return id == sOnerror_id;
case 'f' :
@ -6637,7 +6658,9 @@ nsEventReceiverSH::ReallyIsEventName(jsval id, jschar aFirstChar)
case 'c' :
return (id == sOnchange_id ||
id == sOnclick_id ||
id == sOncontextmenu_id);
id == sOncontextmenu_id ||
id == sOncopy_id ||
id == sOncut_id);
case 'd' :
return id == sOndblclick_id;
case 'l' :
@ -6645,7 +6668,8 @@ nsEventReceiverSH::ReallyIsEventName(jsval id, jschar aFirstChar)
case 'p' :
return (id == sOnpaint_id ||
id == sOnpageshow_id ||
id == sOnpagehide_id);
id == sOnpagehide_id ||
id == sOnpaste_id);
case 'k' :
return (id == sOnkeydown_id ||
id == sOnkeypress_id ||

Просмотреть файл

@ -316,6 +316,12 @@ protected:
static jsval sBaseURIObject_id;
static jsval sNodePrincipal_id;
static jsval sDocumentURIObject_id;
static jsval sOncopy_id;
static jsval sOncut_id;
static jsval sOnpaste_id;
static jsval sOnbeforecopy_id;
static jsval sOnbeforecut_id;
static jsval sOnbeforepaste_id;
static const JSClass *sObjectClass;
static const JSClass *sXPCNativeWrapperClass;

Просмотреть файл

@ -224,7 +224,7 @@ nsDOMWindowUtils::SendKeyEvent(const nsAString& aType,
return NS_ERROR_DOM_SECURITY_ERR;
// get the widget to send the event to
nsIWidget* widget = GetWidget();
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget)
return NS_ERROR_FAILURE;

Просмотреть файл

@ -134,6 +134,7 @@
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsIContentFilter.h"
#include "nsEventDispatcher.h"
const PRUnichar nbsp = 160;
@ -1825,8 +1826,31 @@ NS_IMETHODIMP nsHTMLEditor::Paste(PRInt32 aSelectionType)
{
ForceCompositionEnd();
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps)
return NS_ERROR_NOT_INITIALIZED;
// Fire the paste event.
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_PASTE);
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
nsnull, &status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault)
return NS_OK;
// Did the event handler cause the editor to be destroyed?
// (ie. the input element was removed from the document)
// Don't proceed with paste.
if (mDidPreDestroy)
return NS_OK;
}
// Get Clipboard Service
nsresult rv;
nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
if (NS_FAILED(rv))
return rv;
@ -1934,15 +1958,34 @@ NS_IMETHODIMP nsHTMLEditor::PasteNoFormatting(PRInt32 aSelectionType)
NS_IMETHODIMP nsHTMLEditor::CanPaste(PRInt32 aSelectionType, PRBool *aCanPaste)
{
if (!aCanPaste)
return NS_ERROR_NULL_POINTER;
NS_ENSURE_ARG_POINTER(aCanPaste);
*aCanPaste = PR_FALSE;
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps)
return NS_ERROR_NOT_INITIALIZED;
// Fire the beforepaste event. If the event handler requests to prevent
// default behavior, set *aCanPaste = true. (IE-style behavior)
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_BEFOREPASTE);
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
nsnull, &status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault) {
*aCanPaste = PR_TRUE;
return NS_OK;
}
}
// can't paste if readonly
if (!IsModifiable())
return NS_OK;
nsresult rv;
nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
if (NS_FAILED(rv)) return rv;

Просмотреть файл

@ -66,6 +66,7 @@
#include "nsContentCID.h"
#include "nsISelectionPrivate.h"
#include "nsFrameSelection.h"
#include "nsEventDispatcher.h"
NS_IMETHODIMP nsPlaintextEditor::PrepareTransferable(nsITransferable **transferable)
{
@ -426,8 +427,31 @@ NS_IMETHODIMP nsPlaintextEditor::Paste(PRInt32 aSelectionType)
{
ForceCompositionEnd();
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps)
return NS_ERROR_NOT_INITIALIZED;
// Fire the paste event.
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_PASTE);
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
nsnull, &status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault)
return NS_OK;
// Did the event handler cause the editor to be destroyed?
// (ie. the input element was removed from the document)
// Don't proceed with paste, as it will crash.
if (mDidPreDestroy)
return NS_OK;
}
// Get Clipboard Service
nsresult rv;
nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
if ( NS_FAILED(rv) )
return rv;
@ -456,15 +480,34 @@ NS_IMETHODIMP nsPlaintextEditor::Paste(PRInt32 aSelectionType)
NS_IMETHODIMP nsPlaintextEditor::CanPaste(PRInt32 aSelectionType, PRBool *aCanPaste)
{
if (!aCanPaste)
return NS_ERROR_NULL_POINTER;
NS_ENSURE_ARG_POINTER(aCanPaste);
*aCanPaste = PR_FALSE;
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps)
return NS_ERROR_NOT_INITIALIZED;
// Fire the beforepaste event. If the event handler requests to prevent
// default behavior, set *aCanPaste = true. (IE-style behavior)
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_BEFOREPASTE);
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
nsnull, &status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault) {
*aCanPaste = PR_TRUE;
return NS_OK;
}
}
// can't paste if readonly
if (!IsModifiable())
return NS_OK;
nsresult rv;
nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
if (NS_FAILED(rv)) return rv;

Просмотреть файл

@ -78,10 +78,12 @@
#include "nsContentCID.h"
#include "nsAOLCiter.h"
#include "nsInternetCiter.h"
#include "nsEventDispatcher.h"
// Drag & Drop, Clipboard
#include "nsIClipboard.h"
#include "nsITransferable.h"
#include "nsCopySupport.h"
// prototype for rules creation shortcut
nsresult NS_NewTextEditRules(nsIEditRules** aInstancePtrResult);
@ -1133,53 +1135,150 @@ nsPlaintextEditor::Redo(PRUint32 aCount)
return result;
}
NS_IMETHODIMP nsPlaintextEditor::Cut()
nsresult nsPlaintextEditor::GetClipboardEventTarget(nsIDOMNode** aEventTarget)
{
NS_ENSURE_ARG_POINTER(aEventTarget);
*aEventTarget = nsnull;
nsCOMPtr<nsISelection> selection;
nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res))
return res;
return nsCopySupport::GetClipboardEventTarget(selection, aEventTarget);
}
NS_IMETHODIMP nsPlaintextEditor::Cut()
{
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps)
return NS_ERROR_NOT_INITIALIZED;
// Fire the cut event.
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_CUT);
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
nsnull, &status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault)
return NS_OK;
}
nsCOMPtr<nsISelection> selection;
rv = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(rv))
return rv;
PRBool isCollapsed;
if (NS_SUCCEEDED(selection->GetIsCollapsed(&isCollapsed)) && isCollapsed)
return NS_OK; // just return ok so no JS error is thrown
res = Copy();
if (NS_SUCCEEDED(res))
res = DeleteSelection(eNone);
return res;
rv = ps->DoCopy();
if (NS_SUCCEEDED(rv))
rv = DeleteSelection(eNone);
return rv;
}
NS_IMETHODIMP nsPlaintextEditor::CanCut(PRBool *aCanCut)
{
nsresult res = CanCopy(aCanCut);
if (NS_FAILED(res)) return res;
NS_ENSURE_ARG_POINTER(aCanCut);
*aCanCut = PR_FALSE;
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps)
return NS_ERROR_NOT_INITIALIZED;
// Fire the beforecut event. If the event handler requests to prevent
// default behavior, set *aCanCut = true. (IE-style behavior)
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_BEFORECUT);
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
nsnull, &status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault) {
*aCanCut = PR_TRUE;
return NS_OK;
}
}
nsCOMPtr<nsISelection> selection;
rv = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(rv)) return rv;
*aCanCut = *aCanCut && IsModifiable();
PRBool isCollapsed;
rv = selection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(rv)) return rv;
*aCanCut = !isCollapsed && IsModifiable();
return NS_OK;
}
NS_IMETHODIMP nsPlaintextEditor::Copy()
{
if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps) return NS_ERROR_NOT_INITIALIZED;
if (!ps)
return NS_ERROR_NOT_INITIALIZED;
// Fire the copy event.
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_COPY);
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
nsnull, &status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault)
return NS_OK;
// the affect of the event handler closing the window here has been
// tested, it works without crashes.
}
return ps->DoCopy();
}
NS_IMETHODIMP nsPlaintextEditor::CanCopy(PRBool *aCanCopy)
{
if (!aCanCopy)
return NS_ERROR_NULL_POINTER;
NS_ENSURE_ARG_POINTER(aCanCopy);
*aCanCopy = PR_FALSE;
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps)
return NS_ERROR_NOT_INITIALIZED;
// Fire the beforecopy event. If the event handler requests to prevent
// default behavior, set *aCopyable = true. (IE-style behavior)
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_BEFORECOPY);
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
nsnull, &status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault) {
*aCanCopy = PR_TRUE;
return NS_OK;
}
}
nsCOMPtr<nsISelection> selection;
nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
rv = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(rv)) return rv;
PRBool isCollapsed;
res = selection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(res)) return res;
rv = selection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(rv)) return rv;
*aCanCopy = !isCollapsed;
return NS_OK;

Просмотреть файл

@ -214,6 +214,10 @@ protected:
PRBool mIgnoreSpuriousDragEvent;
NS_IMETHOD IgnoreSpuriousDragEvent(PRBool aIgnoreSpuriousDragEvent) {mIgnoreSpuriousDragEvent = aIgnoreSpuriousDragEvent; return NS_OK;}
// Wrapper for nsCopySupport::GetClipboardEventTarget, finds target to fire
// [cut,copy,paste] and [beforecut,beforecopy,beforepaste] events at.
virtual nsresult GetClipboardEventTarget(nsIDOMNode** aEventTarget);
// Data members
protected:

Просмотреть файл

@ -373,6 +373,8 @@ private:
nsresult GetDocumentSelection(nsISelection **aSelection);
nsresult GetClipboardEventTarget(nsIDOMNode **aEventTarget);
#ifdef NS_PRINTING
// Called when the DocViewer is notified that the state
// of Printing or PP has changed
@ -2313,6 +2315,26 @@ NS_IMETHODIMP DocumentViewerImpl::SelectAll()
NS_IMETHODIMP DocumentViewerImpl::CopySelection()
{
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
// Fire the copy event.
nsresult rv;
nsCOMPtr<nsIDOMNode> eventTarget;
rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_COPY);
nsEventDispatcher::Dispatch(eventTarget, mPresContext, &evt, nsnull,
&status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault)
// Skip default behavior, return OK.
return NS_OK;
// It's possible the oncopy handler closed the window.
if (!mPresShell)
return NS_OK;
}
return mPresShell->DoCopy();
}
@ -2346,12 +2368,53 @@ NS_IMETHODIMP DocumentViewerImpl::CopyImage(PRInt32 aCopyFlags)
return nsCopySupport::ImageCopy(node, aCopyFlags);
}
nsresult DocumentViewerImpl::GetClipboardEventTarget(nsIDOMNode** aEventTarget)
{
NS_ENSURE_ARG_POINTER(aEventTarget);
*aEventTarget = nsnull;
if (!mPresShell)
return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsISelection> sel;
nsresult rv = mPresShell->GetSelectionForCopy(getter_AddRefs(sel));
if (NS_FAILED(rv))
return rv;
if (!sel)
return NS_ERROR_FAILURE;
return nsCopySupport::GetClipboardEventTarget(sel, aEventTarget);
}
NS_IMETHODIMP DocumentViewerImpl::GetCopyable(PRBool *aCopyable)
{
NS_ENSURE_ARG_POINTER(aCopyable);
*aCopyable = PR_FALSE;
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
// Fire the beforecopy event. If the event handler requests to prevent
// default behavior, set *aCopyable = true. (IE-style behavior)
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_BEFORECOPY);
nsEventDispatcher::Dispatch(eventTarget, mPresContext, &evt, nsnull,
&status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault) {
*aCopyable = PR_TRUE;
return NS_OK;
}
// It's possible the onbeforecopy handler closed the window.
if (!mPresShell)
return NS_OK;
}
nsCOMPtr<nsISelection> selection;
nsresult rv = mPresShell->GetSelectionForCopy(getter_AddRefs(selection));
rv = mPresShell->GetSelectionForCopy(getter_AddRefs(selection));
if (NS_FAILED(rv)) return rv;
PRBool isCollapsed;
@ -2363,24 +2426,94 @@ NS_IMETHODIMP DocumentViewerImpl::GetCopyable(PRBool *aCopyable)
NS_IMETHODIMP DocumentViewerImpl::CutSelection()
{
// Nothing to do here.
NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_INITIALIZED);
// Fire the cut event.
nsresult rv;
nsCOMPtr<nsIDOMNode> eventTarget;
rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEvent evt(PR_TRUE, NS_CUT);
nsEventDispatcher::Dispatch(eventTarget, mPresContext, &evt);
// should skip default behavior here if event handler returns false, but
// there is no default behavior to worry about.
}
return NS_OK;
}
NS_IMETHODIMP DocumentViewerImpl::GetCutable(PRBool *aCutable)
{
NS_ENSURE_ARG_POINTER(aCutable);
*aCutable = PR_FALSE;
NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_INITIALIZED);
// Fire the beforecut event. If the event handler requests to prevent
// default behavior, set *aCutable = true. (IE-style behavior)
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_BEFORECUT);
nsEventDispatcher::Dispatch(eventTarget, mPresContext, &evt, nsnull,
&status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault) {
*aCutable = PR_TRUE;
return NS_OK;
}
}
*aCutable = PR_FALSE; // mm, will this ever be called for an editable document?
return NS_OK;
}
NS_IMETHODIMP DocumentViewerImpl::Paste()
{
// Nothing to do here.
NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_INITIALIZED);
// Fire the paste event.
nsresult rv;
nsCOMPtr<nsIDOMNode> eventTarget;
rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEvent evt(PR_TRUE, NS_PASTE);
nsEventDispatcher::Dispatch(eventTarget, mPresContext, &evt);
// should skip default behavior here if event handler returns false, but
// there is no default behavior to worry about.
}
return NS_OK;
}
NS_IMETHODIMP DocumentViewerImpl::GetPasteable(PRBool *aPasteable)
{
NS_ENSURE_ARG_POINTER(aPasteable);
*aPasteable = PR_FALSE;
NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_INITIALIZED);
// Fire the beforepaste event. If the event handler requests to prevent
// default behavior, set *aPasteable = true. (IE-style behavior)
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_BEFOREPASTE);
nsEventDispatcher::Dispatch(eventTarget, mPresContext, &evt, nsnull,
&status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault) {
*aPasteable = PR_TRUE;
return NS_OK;
}
}
*aPasteable = PR_FALSE;
return NS_OK;
}

Просмотреть файл

@ -335,6 +335,15 @@ class nsHashKey;
#define NS_XULCOMMAND_EVENT_START 3000
#define NS_XUL_COMMAND (NS_XULCOMMAND_EVENT_START)
// Cut, copy, paste events
#define NS_CUTCOPYPASTE_EVENT_START 3100
#define NS_COPY (NS_CUTCOPYPASTE_EVENT_START)
#define NS_CUT (NS_CUTCOPYPASTE_EVENT_START + 1)
#define NS_PASTE (NS_CUTCOPYPASTE_EVENT_START + 2)
#define NS_BEFORECOPY (NS_CUTCOPYPASTE_EVENT_START + 3)
#define NS_BEFORECUT (NS_CUTCOPYPASTE_EVENT_START + 4)
#define NS_BEFOREPASTE (NS_CUTCOPYPASTE_EVENT_START + 5)
/**
* Return status for event processors, nsEventStatus, is defined in
* nsEvent.h.