mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 501154, consolidate places where clipboard events are fired from, r=smaug,sr=neil
This commit is contained in:
parent
e29fe1df23
commit
8f3acb3041
@ -48,6 +48,7 @@ class nsITransferable;
|
||||
class nsACString;
|
||||
class nsAString;
|
||||
class nsIDOMNode;
|
||||
class nsIPresShell;
|
||||
|
||||
class nsCopySupport
|
||||
{
|
||||
@ -66,16 +67,51 @@ 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);
|
||||
|
||||
// Get the selection as a transferable. Similar to HTMLCopy except does
|
||||
// not deal with the clipboard.
|
||||
static nsresult GetTransferableForSelection(nsISelection * aSelection,
|
||||
nsIDocument * aDocument,
|
||||
nsITransferable ** aTransferable);
|
||||
|
||||
/**
|
||||
* Retrieve the selection for the given document. If the current focus
|
||||
* within the document has its own selection, aSelection will be set to it
|
||||
* and this focused content node returned. Otherwise, aSelection will be
|
||||
* set to the document's selection and null will be returned.
|
||||
*/
|
||||
static nsIContent* GetSelectionForCopy(nsIDocument* aDocument,
|
||||
nsISelection** aSelection);
|
||||
|
||||
/**
|
||||
* Returns true if a copy operation is currently permitted based on the
|
||||
* current focus and selection within the specified document.
|
||||
*/
|
||||
static PRBool CanCopy(nsIDocument* aDocument);
|
||||
|
||||
/**
|
||||
* Fires a cut, copy or paste event, on the given presshell, depending
|
||||
* on the value of aType, which should be either NS_CUT, NS_COPY or
|
||||
* NS_PASTE, and perform the default copy action if the event was not
|
||||
* cancelled.
|
||||
*
|
||||
* If aSelection is specified, then this selection is used as the target
|
||||
* of the operation. Otherwise, GetSelectionForCopy is used to retrieve
|
||||
* the current selection.
|
||||
*
|
||||
* This will fire a cut, copy or paste event at the node at the start
|
||||
* point of the selection. If a cut or copy event is not cancelled, the
|
||||
* selection is copied to the clipboard and true is returned. Paste events
|
||||
* have no default behaviour but true will be returned. It is expected
|
||||
* that the caller will execute any needed default paste behaviour. Also,
|
||||
* note that this method only copies text to the clipboard, the caller is
|
||||
* responsible for removing the content during a cut operation if true is
|
||||
* returned.
|
||||
*
|
||||
* If the event is cancelled or an error occurs, false will be returned.
|
||||
*/
|
||||
static PRBool FireClipboardEvent(PRInt32 aType,
|
||||
nsIPresShell* aPresShell,
|
||||
nsISelection* aSelection);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -50,18 +50,26 @@
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIContentViewerEdit.h"
|
||||
#include "nsIClipboardDragDropHooks.h"
|
||||
#include "nsIClipboardDragDropHookList.h"
|
||||
#include "nsIClipboardHelper.h"
|
||||
#include "nsISelectionController.h"
|
||||
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsIFrame.h"
|
||||
|
||||
// image copy stuff
|
||||
#include "nsIImageLoadingContent.h"
|
||||
@ -582,26 +590,128 @@ static nsresult AppendDOMNode(nsITransferable *aTransferable,
|
||||
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)
|
||||
nsIContent*
|
||||
nsCopySupport::GetSelectionForCopy(nsIDocument* aDocument, nsISelection** aSelection)
|
||||
{
|
||||
NS_ENSURE_ARG(aSel);
|
||||
NS_ENSURE_ARG_POINTER(aEventTarget);
|
||||
*aEventTarget = nsnull;
|
||||
*aSelection = 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);
|
||||
nsIPresShell* presShell = aDocument->GetPrimaryShell();
|
||||
if (!presShell)
|
||||
return nsnull;
|
||||
|
||||
if (!range)
|
||||
return NS_ERROR_FAILURE;
|
||||
// check if the focused node in the window has a selection
|
||||
nsCOMPtr<nsPIDOMWindow> focusedWindow;
|
||||
nsIContent* content =
|
||||
nsFocusManager::GetFocusedDescendant(aDocument->GetWindow(), PR_FALSE,
|
||||
getter_AddRefs(focusedWindow));
|
||||
if (content) {
|
||||
nsIFrame* frame = content->GetPrimaryFrame();
|
||||
if (frame) {
|
||||
nsCOMPtr<nsISelectionController> selCon;
|
||||
frame->GetSelectionController(presShell->GetPresContext(), getter_AddRefs(selCon));
|
||||
if (selCon) {
|
||||
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, aSelection);
|
||||
return content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rv = range->GetStartContainer(aEventTarget);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return (*aEventTarget) ? NS_OK : NS_ERROR_FAILURE;
|
||||
// if no selection was found, use the main selection for the window
|
||||
NS_IF_ADDREF(*aSelection = presShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL));
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsCopySupport::CanCopy(nsIDocument* aDocument)
|
||||
{
|
||||
if (!aDocument)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsISelection> sel;
|
||||
GetSelectionForCopy(aDocument, getter_AddRefs(sel));
|
||||
|
||||
PRBool isCollapsed;
|
||||
sel->GetIsCollapsed(&isCollapsed);
|
||||
return !isCollapsed;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsCopySupport::FireClipboardEvent(PRInt32 aType, nsIPresShell* aPresShell, nsISelection* aSelection)
|
||||
{
|
||||
NS_ASSERTION(aType == NS_CUT || aType == NS_COPY || aType == NS_PASTE,
|
||||
"Invalid clipboard event type");
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = aPresShell;
|
||||
if (!presShell)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = presShell->GetDocument();
|
||||
if (!doc)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> piWindow = doc->GetWindow();
|
||||
if (!piWindow)
|
||||
return PR_FALSE;
|
||||
|
||||
// if a selection was not supplied, try to find it
|
||||
nsCOMPtr<nsIContent> content;
|
||||
nsCOMPtr<nsISelection> sel = aSelection;
|
||||
if (!sel)
|
||||
content = GetSelectionForCopy(doc, getter_AddRefs(sel));
|
||||
|
||||
// retrieve the event target node from the start of the selection
|
||||
if (sel) {
|
||||
// Only cut or copy when there is an uncollapsed selection
|
||||
if (aType == NS_CUT || aType == NS_COPY) {
|
||||
PRBool isCollapsed;
|
||||
sel->GetIsCollapsed(&isCollapsed);
|
||||
if (isCollapsed)
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
nsresult rv = sel->GetRangeAt(0, getter_AddRefs(range));
|
||||
if (NS_SUCCEEDED(rv) && range) {
|
||||
nsCOMPtr<nsIDOMNode> startContainer;
|
||||
range->GetStartContainer(getter_AddRefs(startContainer));
|
||||
if (startContainer)
|
||||
content = do_QueryInterface(startContainer);
|
||||
}
|
||||
}
|
||||
|
||||
// if no content node was set, just get the root
|
||||
if (!content) {
|
||||
content = doc->GetRootContent();
|
||||
if (!content)
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// It seems to be unsafe to fire an event handler during reflow (bug 393696)
|
||||
if (!nsContentUtils::IsSafeToRunScript())
|
||||
return PR_FALSE;
|
||||
|
||||
// next, fire the cut or copy event
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsEvent evt(PR_TRUE, aType);
|
||||
nsEventDispatcher::Dispatch(content, presShell->GetPresContext(), &evt, nsnull,
|
||||
&status);
|
||||
// if the event was cancelled, don't do the clipboard operation
|
||||
if (status == nsEventStatus_eConsumeNoDefault)
|
||||
return PR_FALSE;
|
||||
|
||||
// no need to do anything special during a paste. Either an event listener
|
||||
// took care of it and cancelled the event, or the caller will handle it.
|
||||
// Return true to indicate the event wasn't cancelled.
|
||||
if (aType == NS_PASTE)
|
||||
return PR_TRUE;
|
||||
|
||||
// call the copy code
|
||||
if (NS_FAILED(nsCopySupport::HTMLCopy(sel, doc, nsIClipboard::kGlobalClipboard)))
|
||||
return PR_FALSE;
|
||||
|
||||
// Now that we have copied, update the clipboard commands. This should have
|
||||
// the effect of updating the paste menu item.
|
||||
piWindow->UpdateCommands(NS_LITERAL_STRING("clipboard"));
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
@ -89,8 +89,8 @@ nsContentEventHandler::InitCommon()
|
||||
nsresult rv = mPresShell->FlushPendingNotifications(Flush_Layout);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mPresShell->GetSelectionForCopy(getter_AddRefs(mSelection));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCopySupport::GetSelectionForCopy(mPresShell->GetDocument(),
|
||||
getter_AddRefs(mSelection));
|
||||
NS_ASSERTION(mSelection,
|
||||
"GetSelectionForCopy succeeded, but the result is null");
|
||||
|
||||
|
@ -40,12 +40,9 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(1691a02f-53b2-4cb8-8769-48e7efc908b8)]
|
||||
[scriptable, uuid(AF13EA3A-D488-4308-B843-526E055AB943)]
|
||||
interface nsIContentViewerEdit : nsISupports
|
||||
{
|
||||
void search();
|
||||
readonly attribute boolean searchable;
|
||||
|
||||
void clearSelection();
|
||||
void selectAll();
|
||||
|
||||
@ -62,12 +59,6 @@ interface nsIContentViewerEdit : nsISupports
|
||||
void copyImage(in long aCopyFlags);
|
||||
readonly attribute boolean inImage;
|
||||
|
||||
void cutSelection();
|
||||
readonly attribute boolean cutable;
|
||||
|
||||
void paste();
|
||||
readonly attribute boolean pasteable;
|
||||
|
||||
AString getContents(in string aMimeType, in boolean aSelectionOnly);
|
||||
readonly attribute boolean canGetContents;
|
||||
};
|
||||
|
@ -59,6 +59,8 @@
|
||||
#include "nsIContentViewerEdit.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsCopySupport.h"
|
||||
#include "nsGUIEvent.h"
|
||||
|
||||
#include "nsIClipboardDragDropHooks.h"
|
||||
#include "nsIClipboardDragDropHookList.h"
|
||||
@ -407,7 +409,71 @@ nsSelectCommand::DoSelectCommand(const char *aCommandName, nsIDOMWindow *aWindow
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
class nsClipboardBaseCommand : public nsIControllerCommand
|
||||
class nsClipboardCommand : public nsIControllerCommand
|
||||
{
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICONTROLLERCOMMAND
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsClipboardCommand, nsIControllerCommand)
|
||||
|
||||
nsresult
|
||||
nsClipboardCommand::IsCommandEnabled(const char* aCommandName, nsISupports *aContext, PRBool *outCmdEnabled)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(outCmdEnabled);
|
||||
*outCmdEnabled = PR_FALSE;
|
||||
|
||||
if (strcmp(aCommandName, "cmd_copy"))
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aContext);
|
||||
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(window->GetExtantDocument());
|
||||
*outCmdEnabled = nsCopySupport::CanCopy(doc);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsClipboardCommand::DoCommand(const char *aCommandName, nsISupports *aContext)
|
||||
{
|
||||
if (strcmp(aCommandName, "cmd_copy"))
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aContext);
|
||||
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
|
||||
|
||||
nsIDocShell *docShell = window->GetDocShell();
|
||||
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
docShell->GetPresShell(getter_AddRefs(presShell));
|
||||
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
|
||||
|
||||
nsCopySupport::FireClipboardEvent(NS_COPY, presShell, nsnull);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsClipboardCommand::GetCommandStateParams(const char *aCommandName,
|
||||
nsICommandParams *aParams, nsISupports *aCommandContext)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsClipboardCommand::DoCommandParams(const char *aCommandName, nsICommandParams* aParams, nsISupports *aContext)
|
||||
{
|
||||
return DoCommand(aCommandName, aContext);
|
||||
}
|
||||
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
class nsSelectionCommand : public nsIControllerCommand
|
||||
{
|
||||
public:
|
||||
|
||||
@ -425,19 +491,19 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsClipboardBaseCommand, nsIControllerCommand)
|
||||
NS_IMPL_ISUPPORTS1(nsSelectionCommand, nsIControllerCommand)
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
nsClipboardBaseCommand
|
||||
nsSelectionCommand
|
||||
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsClipboardBaseCommand::IsCommandEnabled(const char * aCommandName,
|
||||
nsISupports *aCommandContext,
|
||||
PRBool *outCmdEnabled)
|
||||
nsSelectionCommand::IsCommandEnabled(const char * aCommandName,
|
||||
nsISupports *aCommandContext,
|
||||
PRBool *outCmdEnabled)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(outCmdEnabled);
|
||||
*outCmdEnabled = PR_FALSE;
|
||||
@ -450,8 +516,8 @@ nsClipboardBaseCommand::IsCommandEnabled(const char * aCommandName,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsClipboardBaseCommand::DoCommand(const char *aCommandName,
|
||||
nsISupports *aCommandContext)
|
||||
nsSelectionCommand::DoCommand(const char *aCommandName,
|
||||
nsISupports *aCommandContext)
|
||||
{
|
||||
nsCOMPtr<nsIContentViewerEdit> contentEdit;
|
||||
GetContentViewerEditFromContext(aCommandContext, getter_AddRefs(contentEdit));
|
||||
@ -461,17 +527,17 @@ nsClipboardBaseCommand::DoCommand(const char *aCommandName,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsClipboardBaseCommand::GetCommandStateParams(const char *aCommandName,
|
||||
nsICommandParams *aParams,
|
||||
nsISupports *aCommandContext)
|
||||
nsSelectionCommand::GetCommandStateParams(const char *aCommandName,
|
||||
nsICommandParams *aParams,
|
||||
nsISupports *aCommandContext)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsClipboardBaseCommand::DoCommandParams(const char *aCommandName,
|
||||
nsICommandParams *aParams,
|
||||
nsISupports *aCommandContext)
|
||||
nsSelectionCommand::DoCommandParams(const char *aCommandName,
|
||||
nsICommandParams *aParams,
|
||||
nsISupports *aCommandContext)
|
||||
{
|
||||
nsCOMPtr<nsIContentViewerEdit> contentEdit;
|
||||
GetContentViewerEditFromContext(aCommandContext, getter_AddRefs(contentEdit));
|
||||
@ -481,8 +547,8 @@ nsClipboardBaseCommand::DoCommandParams(const char *aCommandName,
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsClipboardBaseCommand::GetContentViewerEditFromContext(nsISupports *aContext,
|
||||
nsIContentViewerEdit **aEditInterface)
|
||||
nsSelectionCommand::GetContentViewerEditFromContext(nsISupports *aContext,
|
||||
nsIContentViewerEdit **aEditInterface)
|
||||
{
|
||||
NS_ENSURE_ARG(aEditInterface);
|
||||
*aEditInterface = nsnull;
|
||||
@ -508,7 +574,7 @@ nsClipboardBaseCommand::GetContentViewerEditFromContext(nsISupports *aContext,
|
||||
#endif
|
||||
|
||||
#define NS_DECL_CLIPBOARD_COMMAND(_cmd) \
|
||||
class _cmd : public nsClipboardBaseCommand \
|
||||
class _cmd : public nsSelectionCommand \
|
||||
{ \
|
||||
protected: \
|
||||
\
|
||||
@ -519,68 +585,11 @@ protected:
|
||||
/* no member variables, please, we're stateless! */ \
|
||||
};
|
||||
|
||||
NS_DECL_CLIPBOARD_COMMAND(nsClipboardCopyCommand)
|
||||
NS_DECL_CLIPBOARD_COMMAND(nsClipboardCutCommand)
|
||||
NS_DECL_CLIPBOARD_COMMAND(nsClipboardPasteCommand)
|
||||
NS_DECL_CLIPBOARD_COMMAND(nsClipboardCopyLinkCommand)
|
||||
NS_DECL_CLIPBOARD_COMMAND(nsClipboardImageCommands)
|
||||
NS_DECL_CLIPBOARD_COMMAND(nsClipboardSelectAllNoneCommands)
|
||||
NS_DECL_CLIPBOARD_COMMAND(nsClipboardGetContentsCommand)
|
||||
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
|
||||
nsresult
|
||||
nsClipboardCutCommand::IsClipboardCommandEnabled(const char* aCommandName, nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled)
|
||||
{
|
||||
return aEdit->GetCutable(outCmdEnabled);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsClipboardCutCommand::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams)
|
||||
{
|
||||
return aEdit->CutSelection();
|
||||
}
|
||||
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
nsClipboardCopyCommand::IsClipboardCommandEnabled(const char* aCommandName, nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled)
|
||||
{
|
||||
return aEdit->GetCopyable(outCmdEnabled);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsClipboardCopyCommand::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams)
|
||||
{
|
||||
return aEdit->CopySelection();
|
||||
}
|
||||
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
nsClipboardPasteCommand::IsClipboardCommandEnabled(const char* aCommandName, nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled)
|
||||
{
|
||||
return aEdit->GetPasteable(outCmdEnabled);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsClipboardPasteCommand::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams)
|
||||
{
|
||||
return aEdit->Paste();
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
nsClipboardCopyLinkCommand::IsClipboardCommandEnabled(const char* aCommandName, nsIContentViewerEdit* aEdit, PRBool *outCmdEnabled)
|
||||
{
|
||||
@ -965,9 +974,9 @@ nsWindowCommandRegistration::RegisterWindowCommands(
|
||||
NS_REGISTER_NEXT_COMMAND(nsSelectCommand, sSelectTopString);
|
||||
NS_REGISTER_LAST_COMMAND(nsSelectCommand, sSelectBottomString);
|
||||
|
||||
NS_REGISTER_ONE_COMMAND(nsClipboardCopyCommand, "cmd_copy");
|
||||
NS_REGISTER_ONE_COMMAND(nsClipboardCutCommand, "cmd_cut");
|
||||
NS_REGISTER_ONE_COMMAND(nsClipboardPasteCommand, "cmd_paste");
|
||||
NS_REGISTER_ONE_COMMAND(nsClipboardCommand, "cmd_cut");
|
||||
NS_REGISTER_ONE_COMMAND(nsClipboardCommand, "cmd_copy");
|
||||
NS_REGISTER_ONE_COMMAND(nsClipboardCommand, "cmd_paste");
|
||||
NS_REGISTER_ONE_COMMAND(nsClipboardCopyLinkCommand, "cmd_copyLink");
|
||||
NS_REGISTER_FIRST_COMMAND(nsClipboardImageCommands, sCopyImageLocationString);
|
||||
NS_REGISTER_NEXT_COMMAND(nsClipboardImageCommands, sCopyImageContentsString);
|
||||
|
@ -55,6 +55,7 @@ _TEST_FILES = \
|
||||
test_offsets.js \
|
||||
test_offsets.xul \
|
||||
test_windowProperties.html \
|
||||
test_clipboard_events.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
322
dom/tests/mochitest/general/test_clipboard_events.html
Normal file
322
dom/tests/mochitest/general/test_clipboard_events.html
Normal file
@ -0,0 +1,322 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Clipboard Events</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="border: 3px solid black; padding: 3em;">CONTENT TEXT<input id="content-input" value="INPUT TEXT"></div>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript;version=1.7">
|
||||
|
||||
// Enable full privledges for clipboard read/write operations.
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
var content = document.getElementById("content");
|
||||
var contentInput = document.getElementById("content-input");
|
||||
var clipboardInitialValue = "empty";
|
||||
|
||||
// Test that clearing and reading the clipboard works. A random number
|
||||
// is used to make sure that leftover clipboard values from a previous
|
||||
// test run don't cause a false-positive test.
|
||||
var cb_text = "empty_" + Math.random();
|
||||
setClipboardText(cb_text);
|
||||
is(getClipboardText(), cb_text, "set/get clipboard text failed");
|
||||
|
||||
// Some test functions need to be run with delays.
|
||||
var delayedTests = [];
|
||||
|
||||
// Ensure window focus before running tests, otherwise key events can
|
||||
// misfire. We set the onfocus event handler here to actually begin
|
||||
// running tests, and call window.focus() afterwards.
|
||||
window.onfocus = function()
|
||||
{
|
||||
window.onfocus = null;
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
// A list of test functions to run. Before each test function is run, the
|
||||
// clipboard is initialized to clipboardInitialValue, and the contents of
|
||||
// div#content are set as the window's selection.
|
||||
var testFunctions = [
|
||||
test_dom_oncopy,
|
||||
test_dom_oncut,
|
||||
test_dom_onpaste,
|
||||
test_dom_oncopy_abort,
|
||||
test_input_oncopy,
|
||||
test_input_oncut,
|
||||
test_input_onpaste,
|
||||
test_input_oncopy_abort,
|
||||
test_input_oncut_abort,
|
||||
test_input_onpaste_abort,
|
||||
];
|
||||
|
||||
// Run the main tests. This will also populate the delayedTests array
|
||||
for (let i = 0; i < testFunctions.length; i++) {
|
||||
// Init clipboard
|
||||
setClipboardText(clipboardInitialValue);
|
||||
|
||||
// Reset value of contentInput.
|
||||
contentInput.value = "INPUT TEXT";
|
||||
|
||||
var func = testFunctions[i];
|
||||
func();
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
// Calling .focus begins the test run.
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
window.focus();
|
||||
|
||||
function getClipboardText() {
|
||||
var trans = Components.classes["@mozilla.org/widget/transferable;1"]
|
||||
.createInstance();
|
||||
trans = trans.QueryInterface(Components.interfaces.nsITransferable);
|
||||
trans.addDataFlavor("text/unicode");
|
||||
|
||||
var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
|
||||
.getService();
|
||||
clipboard = clipboard.QueryInterface(Components.interfaces.nsIClipboard);
|
||||
clipboard.getData(trans, clipboard.kGlobalClipboard);
|
||||
|
||||
var str = new Object();
|
||||
var strLen = new Object();
|
||||
|
||||
try {
|
||||
trans.getTransferData("text/unicode", str, strLen);
|
||||
} catch(e) {
|
||||
// NS_ERROR_FAILURE will occur if the transferable object has no
|
||||
// text/unicode data in it. In that case, it's not an error:
|
||||
if (e instanceof Components.interfaces.nsIXPCException &&
|
||||
e.result == Components.results.NS_ERROR_FAILURE) {
|
||||
return null;
|
||||
} else {
|
||||
// if we don't know how to handle it then rethrow
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (!str) return null;
|
||||
|
||||
str = str.value.QueryInterface(Components.interfaces.nsISupportsString);
|
||||
if (!str) return null;
|
||||
|
||||
str = str.data.substring(0, strLen.value / 2);
|
||||
if (!str) return null;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
function setClipboardText(text) {
|
||||
var helper = Components.classes["@mozilla.org/widget/clipboardhelper;1"]
|
||||
.getService(Components.interfaces.nsIClipboardHelper);
|
||||
helper.copyString(text);
|
||||
}
|
||||
|
||||
function selectContentDiv() {
|
||||
// Set selection
|
||||
var selection = window.getSelection();
|
||||
selection.removeAllRanges();
|
||||
selection.selectAllChildren(content);
|
||||
}
|
||||
|
||||
function selectContentInput() {
|
||||
contentInput.select();
|
||||
contentInput.focus();
|
||||
}
|
||||
|
||||
function test_dom_oncopy() {
|
||||
// Setup an oncopy event handler, fire copy. Ensure that the event
|
||||
// handler was called, and the clipboard contents have set to CONTENT TEXT.
|
||||
// Test firing oncopy event on ctrl-c:
|
||||
selectContentDiv();
|
||||
var oncopy_fired = false;
|
||||
content.oncopy = function() { oncopy_fired = true; };
|
||||
try {
|
||||
synthesizeKey("c", {accelKey: 1});
|
||||
ok(oncopy_fired, "copy event firing on DOM element");
|
||||
is(getClipboardText(), "CONTENT TEXT",
|
||||
"copy on DOM element set clipboard correctly");
|
||||
} finally {
|
||||
content.oncopy = null;
|
||||
}
|
||||
}
|
||||
|
||||
function test_dom_oncut() {
|
||||
// Setup an oncut event handler, fire cut. Ensure that the event handler
|
||||
// was called. The <div> doesn't handle a cut, so ensure that the
|
||||
// clipboard text is clipboardInitialValue, NOT "CONTENT TEXT".
|
||||
selectContentDiv();
|
||||
var oncut_fired = false;
|
||||
content.oncut = function() { oncut_fired = true; };
|
||||
try {
|
||||
synthesizeKey("x", {accelKey: 1});
|
||||
ok(!oncut_fired, "cut event firing on DOM element")
|
||||
is(getClipboardText(), clipboardInitialValue,
|
||||
"cut on DOM element did not modify clipboard");
|
||||
} finally {
|
||||
content.oncut = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function test_dom_onpaste() {
|
||||
// Setup an onpaste event handler, fire paste. Ensure that the event
|
||||
// handler was called.
|
||||
selectContentDiv();
|
||||
var onpaste_fired = false;
|
||||
content.onpaste = function() { onpaste_fired = true; };
|
||||
try {
|
||||
synthesizeKey("v", {accelKey: 1});
|
||||
ok(!onpaste_fired, "paste event firing on DOM element");
|
||||
} finally {
|
||||
content.onpaste = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function test_dom_oncopy_abort() {
|
||||
// Setup an oncopy event handler that aborts the copy, and fire the copy
|
||||
// event. Ensure that the event handler was fired, and the clipboard
|
||||
// contents have not been modified.
|
||||
selectContentDiv();
|
||||
var oncopy_fired = false;
|
||||
content.oncopy = function() { oncopy_fired = true; return false; };
|
||||
try {
|
||||
synthesizeKey("c", {accelKey: 1});
|
||||
ok(oncopy_fired, "copy event (to-be-cancelled) firing on DOM element");
|
||||
is(getClipboardText(), clipboardInitialValue,
|
||||
"aborted copy on DOM element did not modify clipboard");
|
||||
} finally {
|
||||
content.oncopy = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function test_input_oncopy() {
|
||||
// Setup an oncopy event handler, fire copy. Ensure that the event
|
||||
// handler was called, and the clipboard contents have set to INPUT TEXT.
|
||||
// Test firing oncopy event on ctrl-c:
|
||||
selectContentInput();
|
||||
var oncopy_fired = false;
|
||||
contentInput.oncopy = function() { oncopy_fired = true; };
|
||||
try {
|
||||
synthesizeKey("c", {accelKey: 1});
|
||||
ok(oncopy_fired, "copy event firing on plaintext editor");
|
||||
is(getClipboardText(), "INPUT TEXT",
|
||||
"copy on plaintext editor set clipboard correctly");
|
||||
} finally {
|
||||
contentInput.oncopy = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function test_input_oncut() {
|
||||
// Setup an oncut event handler, and fire cut. Ensure that the event
|
||||
// handler was fired, the clipboard contains the INPUT TEXT, and
|
||||
// that the input itself is empty.
|
||||
selectContentInput();
|
||||
var oncut_fired = false;
|
||||
contentInput.oncut = function() { oncut_fired = true; };
|
||||
try {
|
||||
synthesizeKey("x", {accelKey: 1});
|
||||
ok(oncut_fired, "cut event firing on plaintext editor");
|
||||
is(getClipboardText(), "INPUT TEXT",
|
||||
"cut on plaintext editor set clipboard correctly");
|
||||
is(contentInput.value, "",
|
||||
"cut on plaintext editor emptied editor");
|
||||
} finally {
|
||||
contentInput.oncut = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function test_input_onpaste() {
|
||||
// Setup an onpaste event handler, and fire paste. Ensure that the event
|
||||
// handler was fired, the clipboard contents didn't change, and that the
|
||||
// input value did change (ie. paste succeeded).
|
||||
selectContentInput();
|
||||
var onpaste_fired = false;
|
||||
contentInput.onpaste = function() { onpaste_fired = true; };
|
||||
try {
|
||||
synthesizeKey("v", {accelKey: 1});
|
||||
ok(onpaste_fired, "paste event firing on plaintext editor");
|
||||
is(getClipboardText(), clipboardInitialValue,
|
||||
"paste on plaintext editor did not modify clipboard contents");
|
||||
is(contentInput.value, clipboardInitialValue,
|
||||
"paste on plaintext editor did modify editor value");
|
||||
} finally {
|
||||
contentInput.onpaste = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function test_input_oncopy_abort() {
|
||||
// Setup an oncopy event handler, fire copy. Ensure that the event
|
||||
// handler was called, and that the clipboard value did NOT change.
|
||||
selectContentInput();
|
||||
var oncopy_fired = false;
|
||||
contentInput.oncopy = function() { oncopy_fired = true; return false; };
|
||||
try {
|
||||
synthesizeKey("c", {accelKey: 1});
|
||||
ok(oncopy_fired, "copy event (to-be-cancelled) firing on plaintext editor");
|
||||
is(getClipboardText(), clipboardInitialValue,
|
||||
"aborted copy on plaintext editor did not modify clipboard");
|
||||
} finally {
|
||||
contentInput.oncopy = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function test_input_oncut_abort() {
|
||||
// Setup an oncut event handler, and fire cut. Ensure that the event
|
||||
// handler was fired, the clipboard contains the INPUT TEXT, and
|
||||
// that the input itself is empty.
|
||||
selectContentInput();
|
||||
var oncut_fired = false;
|
||||
contentInput.oncut = function() { oncut_fired = true; return false; };
|
||||
try {
|
||||
synthesizeKey("x", {accelKey: 1});
|
||||
ok(oncut_fired, "cut event (to-be-cancelled) firing on plaintext editor");
|
||||
is(getClipboardText(), clipboardInitialValue,
|
||||
"aborted cut on plaintext editor did not modify clipboard.");
|
||||
is(contentInput.value, "INPUT TEXT",
|
||||
"aborted cut on plaintext editor did not modify editor contents");
|
||||
} finally {
|
||||
contentInput.oncut = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function test_input_onpaste_abort() {
|
||||
// Setup an onpaste event handler, and fire paste. Ensure that the event
|
||||
// handler was fired, the clipboard contents didn't change, and that the
|
||||
// input value did change (ie. paste succeeded).
|
||||
selectContentInput();
|
||||
var onpaste_fired = false;
|
||||
contentInput.onpaste = function() { onpaste_fired = true; return false; };
|
||||
try {
|
||||
synthesizeKey("v", {accelKey: 1});
|
||||
ok(onpaste_fired,
|
||||
"paste event (to-be-cancelled) firing on plaintext editor");
|
||||
is(getClipboardText(), clipboardInitialValue,
|
||||
"aborted paste on plaintext editor did not modify clipboard");
|
||||
is(contentInput.value, "INPUT TEXT",
|
||||
"aborted paste on plaintext editor did not modify modified editor value");
|
||||
} finally {
|
||||
contentInput.onpaste = null;
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1847,14 +1847,11 @@ PRBool nsHTMLEditor::HavePrivateHTMLFlavor(nsIClipboard *aClipboard)
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::Paste(PRInt32 aSelectionType)
|
||||
{
|
||||
ForceCompositionEnd();
|
||||
|
||||
PRBool preventDefault;
|
||||
nsresult rv = FireClipboardEvent(NS_PASTE, &preventDefault);
|
||||
if (NS_FAILED(rv) || preventDefault)
|
||||
return rv;
|
||||
if (!FireClipboardEvent(NS_PASTE))
|
||||
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;
|
||||
@ -1932,12 +1929,8 @@ NS_IMETHODIMP nsHTMLEditor::Paste(PRInt32 aSelectionType)
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::PasteTransferable(nsITransferable *aTransferable)
|
||||
{
|
||||
ForceCompositionEnd();
|
||||
|
||||
PRBool preventDefault;
|
||||
nsresult rv = FireClipboardEvent(NS_PASTE, &preventDefault);
|
||||
if (NS_FAILED(rv) || preventDefault)
|
||||
return rv;
|
||||
if (!FireClipboardEvent(NS_PASTE))
|
||||
return NS_OK;
|
||||
|
||||
// handle transferable hooks
|
||||
nsCOMPtr<nsIDOMDocument> domdoc;
|
||||
@ -1948,10 +1941,8 @@ NS_IMETHODIMP nsHTMLEditor::PasteTransferable(nsITransferable *aTransferable)
|
||||
// Beware! This may flush notifications via synchronous
|
||||
// ScrollSelectionIntoView.
|
||||
nsAutoString contextStr, infoStr;
|
||||
rv = InsertFromTransferable(aTransferable, nsnull, contextStr, infoStr,
|
||||
nsnull, 0, PR_TRUE);
|
||||
|
||||
return rv;
|
||||
return InsertFromTransferable(aTransferable, nsnull, contextStr, infoStr,
|
||||
nsnull, 0, PR_TRUE);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -60,6 +60,7 @@
|
||||
#include "nsITransferable.h"
|
||||
#include "nsIDragService.h"
|
||||
#include "nsIDOMNSUIEvent.h"
|
||||
#include "nsCopySupport.h"
|
||||
|
||||
// Misc
|
||||
#include "nsEditorUtils.h"
|
||||
@ -409,14 +410,11 @@ NS_IMETHODIMP nsPlaintextEditor::DoDrag(nsIDOMEvent *aDragEvent)
|
||||
|
||||
NS_IMETHODIMP nsPlaintextEditor::Paste(PRInt32 aSelectionType)
|
||||
{
|
||||
ForceCompositionEnd();
|
||||
|
||||
PRBool preventDefault;
|
||||
nsresult rv = FireClipboardEvent(NS_PASTE, &preventDefault);
|
||||
if (NS_FAILED(rv) || preventDefault)
|
||||
return rv;
|
||||
if (!FireClipboardEvent(NS_PASTE))
|
||||
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;
|
||||
@ -446,12 +444,8 @@ NS_IMETHODIMP nsPlaintextEditor::Paste(PRInt32 aSelectionType)
|
||||
|
||||
NS_IMETHODIMP nsPlaintextEditor::PasteTransferable(nsITransferable *aTransferable)
|
||||
{
|
||||
ForceCompositionEnd();
|
||||
|
||||
PRBool preventDefault;
|
||||
nsresult rv = FireClipboardEvent(NS_PASTE, &preventDefault);
|
||||
if (NS_FAILED(rv) || preventDefault)
|
||||
return rv;
|
||||
if (!FireClipboardEvent(NS_PASTE))
|
||||
return NS_OK;
|
||||
|
||||
if (!IsModifiable())
|
||||
return NS_OK;
|
||||
@ -464,9 +458,7 @@ NS_IMETHODIMP nsPlaintextEditor::PasteTransferable(nsITransferable *aTransferabl
|
||||
|
||||
// Beware! This may flush notifications via synchronous
|
||||
// ScrollSelectionIntoView.
|
||||
rv = InsertTextFromTransferable(aTransferable, nsnull, nsnull, PR_TRUE);
|
||||
|
||||
return rv;
|
||||
return InsertTextFromTransferable(aTransferable, nsnull, nsnull, PR_TRUE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPlaintextEditor::CanPaste(PRInt32 aSelectionType, PRBool *aCanPaste)
|
||||
|
@ -1142,128 +1142,66 @@ nsPlaintextEditor::Redo(PRUint32 aCount)
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult nsPlaintextEditor::GetClipboardEventTarget(nsIDOMNode** aEventTarget)
|
||||
PRBool
|
||||
nsPlaintextEditor::CanCutOrCopy()
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aEventTarget);
|
||||
*aEventTarget = nsnull;
|
||||
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
nsresult res = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
if (NS_FAILED(GetSelection(getter_AddRefs(selection))))
|
||||
return PR_FALSE;
|
||||
|
||||
return nsCopySupport::GetClipboardEventTarget(selection, aEventTarget);
|
||||
PRBool isCollapsed;
|
||||
selection->GetIsCollapsed(&isCollapsed);
|
||||
return !isCollapsed;
|
||||
}
|
||||
|
||||
nsresult nsPlaintextEditor::FireClipboardEvent(PRUint32 msg,
|
||||
PRBool* aPreventDefault)
|
||||
PRBool
|
||||
nsPlaintextEditor::FireClipboardEvent(PRInt32 aType)
|
||||
{
|
||||
*aPreventDefault = PR_FALSE;
|
||||
if (aType == NS_PASTE)
|
||||
ForceCompositionEnd();
|
||||
|
||||
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
|
||||
if (!ps)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShellWeak);
|
||||
NS_ENSURE_TRUE(presShell, PR_FALSE);
|
||||
|
||||
// Unsafe to fire event during reflow (bug 396108)
|
||||
PRBool isReflowing = PR_TRUE;
|
||||
nsresult rv = ps->IsReflowLocked(&isReflowing);
|
||||
if (NS_FAILED(rv) || isReflowing)
|
||||
return NS_OK;
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
if (NS_FAILED(GetSelection(getter_AddRefs(selection))))
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> eventTarget;
|
||||
rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
|
||||
if (NS_FAILED(rv))
|
||||
// On failure to get event target, just forget about it and don't fire.
|
||||
return NS_OK;
|
||||
if (!nsCopySupport::FireClipboardEvent(aType, presShell, selection))
|
||||
return PR_FALSE;
|
||||
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsEvent evt(PR_TRUE, msg);
|
||||
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
|
||||
nsnull, &status);
|
||||
// if event handler return'd false (PreventDefault)
|
||||
if (status == nsEventStatus_eConsumeNoDefault)
|
||||
*aPreventDefault = PR_TRUE;
|
||||
|
||||
// Did the event handler cause the editor to be destroyed? (ie. the input
|
||||
// element was removed from the document) Don't proceed with command,
|
||||
// could crash, definitely does during paste.
|
||||
if (mDidPreDestroy)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return NS_OK;
|
||||
// If the event handler caused the editor to be destroyed, return false.
|
||||
// Otherwise return true to indicate that the event was not cancelled.
|
||||
return !mDidPreDestroy;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPlaintextEditor::Cut()
|
||||
{
|
||||
PRBool preventDefault;
|
||||
nsresult rv = FireClipboardEvent(NS_CUT, &preventDefault);
|
||||
if (NS_FAILED(rv) || preventDefault)
|
||||
return rv;
|
||||
|
||||
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
|
||||
|
||||
// ps should be guaranteed by FireClipboardEvent not failing
|
||||
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
|
||||
rv = ps->DoCopy();
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = DeleteSelection(eNone);
|
||||
return rv;
|
||||
if (FireClipboardEvent(NS_CUT))
|
||||
return DeleteSelection(eNone);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPlaintextEditor::CanCut(PRBool *aCanCut)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCanCut);
|
||||
*aCanCut = PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
nsresult rv = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRBool isCollapsed;
|
||||
rv = selection->GetIsCollapsed(&isCollapsed);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*aCanCut = !isCollapsed && IsModifiable();
|
||||
*aCanCut = IsModifiable() && CanCutOrCopy();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPlaintextEditor::Copy()
|
||||
{
|
||||
PRBool preventDefault;
|
||||
nsresult rv = FireClipboardEvent(NS_COPY, &preventDefault);
|
||||
if (NS_FAILED(rv) || preventDefault)
|
||||
return rv;
|
||||
|
||||
// ps should be guaranteed by FireClipboardEvent not failing
|
||||
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
|
||||
return ps->DoCopy();
|
||||
FireClipboardEvent(NS_COPY);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPlaintextEditor::CanCopy(PRBool *aCanCopy)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCanCopy);
|
||||
*aCanCopy = PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
nsresult rv = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRBool isCollapsed;
|
||||
rv = selection->GetIsCollapsed(&isCollapsed);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*aCanCopy = !isCollapsed;
|
||||
*aCanCopy = CanCutOrCopy();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// Shared between OutputToString and OutputToStream
|
||||
NS_IMETHODIMP
|
||||
nsPlaintextEditor::GetAndInitDocEncoder(const nsAString& aFormatType,
|
||||
|
@ -219,10 +219,8 @@ 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.
|
||||
nsresult GetClipboardEventTarget(nsIDOMNode** aEventTarget);
|
||||
nsresult FireClipboardEvent(PRUint32 msg, PRBool* aPreventDefault);
|
||||
PRBool CanCutOrCopy();
|
||||
PRBool FireClipboardEvent(PRInt32 aType);
|
||||
|
||||
// Data members
|
||||
protected:
|
||||
|
@ -398,9 +398,6 @@ private:
|
||||
|
||||
nsresult GetDocumentSelection(nsISelection **aSelection);
|
||||
|
||||
nsresult GetClipboardEventTarget(nsIDOMNode **aEventTarget);
|
||||
nsresult FireClipboardEvent(PRUint32 msg, PRBool* aPreventDefault);
|
||||
|
||||
void DestroyPresShell();
|
||||
|
||||
#ifdef NS_PRINTING
|
||||
@ -2410,8 +2407,7 @@ DocumentViewerImpl::CreateDeviceContext(nsIView* aContainerView)
|
||||
}
|
||||
|
||||
// Return the selection for the document. Note that text fields have their
|
||||
// own selection, which cannot be accessed with this method. Use
|
||||
// mPresShell->GetSelectionForCopy() instead.
|
||||
// own selection, which cannot be accessed with this method.
|
||||
nsresult DocumentViewerImpl::GetDocumentSelection(nsISelection **aSelection)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSelection);
|
||||
@ -2431,25 +2427,12 @@ nsresult DocumentViewerImpl::GetDocumentSelection(nsISelection **aSelection)
|
||||
* nsIContentViewerEdit
|
||||
* ======================================================================================== */
|
||||
|
||||
NS_IMETHODIMP DocumentViewerImpl::Search()
|
||||
{
|
||||
// Nothing to do here.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DocumentViewerImpl::GetSearchable(PRBool *aSearchable)
|
||||
{
|
||||
// Nothing to do here.
|
||||
*aSearchable = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DocumentViewerImpl::ClearSelection()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
|
||||
// use mPresShell->GetSelectionForCopy() ?
|
||||
// use nsCopySupport::GetSelectionForCopy() ?
|
||||
rv = GetDocumentSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
@ -2464,7 +2447,7 @@ NS_IMETHODIMP DocumentViewerImpl::SelectAll()
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
nsresult rv;
|
||||
|
||||
// use mPresShell->GetSelectionForCopy() ?
|
||||
// use nsCopySupport::GetSelectionForCopy() ?
|
||||
rv = GetDocumentSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
@ -2494,12 +2477,8 @@ NS_IMETHODIMP DocumentViewerImpl::SelectAll()
|
||||
|
||||
NS_IMETHODIMP DocumentViewerImpl::CopySelection()
|
||||
{
|
||||
PRBool preventDefault;
|
||||
nsresult rv = FireClipboardEvent(NS_COPY, &preventDefault);
|
||||
if (NS_FAILED(rv) || preventDefault)
|
||||
return rv;
|
||||
|
||||
return mPresShell->DoCopy();
|
||||
nsCopySupport::FireClipboardEvent(NS_COPY, mPresShell, nsnull);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DocumentViewerImpl::CopyLinkLocation()
|
||||
@ -2532,118 +2511,47 @@ 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);
|
||||
}
|
||||
|
||||
nsresult DocumentViewerImpl::FireClipboardEvent(PRUint32 msg,
|
||||
PRBool* aPreventDefault)
|
||||
{
|
||||
*aPreventDefault = PR_FALSE;
|
||||
|
||||
NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_INITIALIZED);
|
||||
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
// It seems to be unsafe to fire an event handler during reflow (bug 393696)
|
||||
PRBool isReflowing = PR_TRUE;
|
||||
nsresult rv = mPresShell->IsReflowLocked(&isReflowing);
|
||||
if (NS_FAILED(rv) || isReflowing)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> eventTarget;
|
||||
rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
|
||||
if (NS_FAILED(rv))
|
||||
// On failure to get event target, just forget about it and don't fire.
|
||||
return NS_OK;
|
||||
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsEvent evt(PR_TRUE, msg);
|
||||
nsEventDispatcher::Dispatch(eventTarget, mPresContext, &evt, nsnull,
|
||||
&status);
|
||||
// if event handler return'd false (PreventDefault)
|
||||
if (status == nsEventStatus_eConsumeNoDefault)
|
||||
*aPreventDefault = PR_TRUE;
|
||||
|
||||
// Ensure that the calling function can use mPresShell -- if the event
|
||||
// handler closed this window, mPresShell will be gone.
|
||||
NS_ENSURE_STATE(mPresShell);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DocumentViewerImpl::GetCopyable(PRBool *aCopyable)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCopyable);
|
||||
*aCopyable = PR_FALSE;
|
||||
|
||||
NS_ENSURE_STATE(mPresShell);
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
nsresult rv = mPresShell->GetSelectionForCopy(getter_AddRefs(selection));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
PRBool isCollapsed;
|
||||
selection->GetIsCollapsed(&isCollapsed);
|
||||
|
||||
*aCopyable = !isCollapsed;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DocumentViewerImpl::CutSelection()
|
||||
{
|
||||
// preventDefault's value is ignored because cut from the document has no
|
||||
// default behaviour.
|
||||
PRBool preventDefault;
|
||||
return FireClipboardEvent(NS_CUT, &preventDefault);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DocumentViewerImpl::GetCutable(PRBool *aCutable)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCutable);
|
||||
*aCutable = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DocumentViewerImpl::Paste()
|
||||
{
|
||||
// preventDefault's value is ignored because paste into the document has no
|
||||
// default behaviour.
|
||||
PRBool preventDefault;
|
||||
return FireClipboardEvent(NS_PASTE, &preventDefault);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DocumentViewerImpl::GetPasteable(PRBool *aPasteable)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPasteable);
|
||||
*aPasteable = PR_FALSE;
|
||||
*aCopyable = nsCopySupport::CanCopy(mDocument);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* AString getContents (in string mimeType, in boolean selectionOnly); */
|
||||
NS_IMETHODIMP DocumentViewerImpl::GetContents(const char *mimeType, PRBool selectionOnly, nsAString& aOutValue)
|
||||
{
|
||||
aOutValue.Truncate();
|
||||
|
||||
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
|
||||
return mPresShell->DoGetContents(nsDependentCString(mimeType), 0, selectionOnly, aOutValue);
|
||||
NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
// Now we have the selection. Make sure it's nonzero:
|
||||
nsCOMPtr<nsISelection> sel;
|
||||
if (selectionOnly) {
|
||||
nsCopySupport::GetSelectionForCopy(mDocument, getter_AddRefs(sel));
|
||||
NS_ENSURE_TRUE(sel, NS_ERROR_FAILURE);
|
||||
|
||||
PRBool isCollapsed;
|
||||
sel->GetIsCollapsed(&isCollapsed);
|
||||
if (isCollapsed)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// call the copy code
|
||||
return nsCopySupport::GetContents(nsDependentCString(mimeType), 0, sel,
|
||||
mDocument, aOutValue);
|
||||
}
|
||||
|
||||
/* readonly attribute boolean canGetContents; */
|
||||
NS_IMETHODIMP DocumentViewerImpl::GetCanGetContents(PRBool *aCanGetContents)
|
||||
{
|
||||
return GetCopyable(aCanGetContents);
|
||||
NS_ENSURE_ARG_POINTER(aCanGetContents);
|
||||
*aCanGetContents = PR_FALSE;
|
||||
NS_ENSURE_STATE(mDocument);
|
||||
*aCanGetContents = nsCopySupport::CanCopy(mDocument);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef XP_MAC
|
||||
|
@ -127,8 +127,8 @@ typedef struct CapturingContentInfo {
|
||||
} CapturingContentInfo;
|
||||
|
||||
#define NS_IPRESSHELL_IID \
|
||||
{ 0xe5e070ce, 0xbc17, 0x4b5f, \
|
||||
{ 0xb2, 0x21, 0xbf, 0xc3, 0xe1, 0x68, 0xbe, 0x9b } }
|
||||
{ 0x0e170e5f, 0xf6d4, 0x44c5, \
|
||||
{ 0xbc, 0x2c, 0x44, 0x94, 0x20, 0x7e, 0xcc, 0x30 } }
|
||||
|
||||
// Constants for ScrollContentIntoView() function
|
||||
#define NS_PRESSHELL_SCROLL_TOP 0
|
||||
@ -578,27 +578,11 @@ public:
|
||||
*/
|
||||
NS_IMETHOD NotifyDestroyingFrame(nsIFrame* aFrame) = 0;
|
||||
|
||||
/**
|
||||
* Notify the Clipboard that we have something to copy.
|
||||
*/
|
||||
NS_IMETHOD DoCopy() = 0;
|
||||
|
||||
/**
|
||||
* Get the selection of the focussed element (either the page selection,
|
||||
* or the selection for a text field).
|
||||
*/
|
||||
NS_IMETHOD GetSelectionForCopy(nsISelection** outSelection) = 0;
|
||||
|
||||
/**
|
||||
* Get link location.
|
||||
*/
|
||||
NS_IMETHOD GetLinkLocation(nsIDOMNode* aNode, nsAString& aLocation) = 0;
|
||||
|
||||
/**
|
||||
* Get the doc or the selection as text or html.
|
||||
*/
|
||||
NS_IMETHOD DoGetContents(const nsACString& aMimeType, PRUint32 aFlags, PRBool aSelectionOnly, nsAString& outValue) = 0;
|
||||
|
||||
/**
|
||||
* Get the caret, if it exists. AddRefs it.
|
||||
*/
|
||||
|
@ -738,12 +738,8 @@ public:
|
||||
|
||||
NS_IMETHOD SetIgnoreFrameDestruction(PRBool aIgnore);
|
||||
NS_IMETHOD NotifyDestroyingFrame(nsIFrame* aFrame);
|
||||
|
||||
NS_IMETHOD DoCopy();
|
||||
NS_IMETHOD GetSelectionForCopy(nsISelection** outSelection);
|
||||
|
||||
NS_IMETHOD GetLinkLocation(nsIDOMNode* aNode, nsAString& aLocationString);
|
||||
NS_IMETHOD DoGetContents(const nsACString& aMimeType, PRUint32 aFlags, PRBool aSelectionOnly, nsAString& outValue);
|
||||
|
||||
NS_IMETHOD CaptureHistoryState(nsILayoutHistoryState** aLayoutHistoryState, PRBool aLeavingPage);
|
||||
|
||||
@ -4298,57 +4294,6 @@ NS_IMETHODIMP PresShell::GetLinkLocation(nsIDOMNode* aNode, nsAString& aLocation
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::GetSelectionForCopy(nsISelection** outSelection)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
*outSelection = nsnull;
|
||||
|
||||
if (!mDocument) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIContent> content;
|
||||
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (fm) {
|
||||
nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(mDocument->GetWindow());
|
||||
|
||||
nsCOMPtr<nsIDOMElement> focusedElement;
|
||||
fm->GetFocusedElementForWindow(window, PR_FALSE, nsnull, getter_AddRefs(focusedElement));
|
||||
content = do_QueryInterface(focusedElement);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISelection> sel;
|
||||
if (content)
|
||||
{
|
||||
//check to see if we need to get selection from frame
|
||||
//optimization that MAY need to be expanded as more things implement their own "selection"
|
||||
nsCOMPtr<nsIDOMNSHTMLInputElement> htmlInputElement(do_QueryInterface(content));
|
||||
nsCOMPtr<nsIDOMNSHTMLTextAreaElement> htmlTextAreaElement(do_QueryInterface(content));
|
||||
if (htmlInputElement || htmlTextAreaElement)
|
||||
{
|
||||
nsIFrame *htmlInputFrame = content->GetPrimaryFrame();
|
||||
if (!htmlInputFrame) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISelectionController> selCon;
|
||||
rv = htmlInputFrame->
|
||||
GetSelectionController(mPresContext,getter_AddRefs(selCon));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!selCon) return NS_ERROR_FAILURE;
|
||||
|
||||
rv = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
|
||||
getter_AddRefs(sel));
|
||||
}
|
||||
}
|
||||
if (!sel) {
|
||||
sel = mSelection->GetSelection(nsISelectionController::SELECTION_NORMAL);
|
||||
rv = NS_OK;
|
||||
}
|
||||
|
||||
*outSelection = sel;
|
||||
NS_IF_ADDREF(*outSelection);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
PresShell::DispatchSynthMouseMove(nsGUIEvent *aEvent,
|
||||
PRBool aFlushOnHoverChange)
|
||||
@ -4405,67 +4350,6 @@ PresShell::ClearMouseCapture(nsIView* aView)
|
||||
gCaptureInfo.mAllowed = PR_FALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::DoGetContents(const nsACString& aMimeType, PRUint32 aFlags, PRBool aSelectionOnly, nsAString& aOutValue)
|
||||
{
|
||||
aOutValue.Truncate();
|
||||
|
||||
if (!mDocument) return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISelection> sel;
|
||||
|
||||
// Now we have the selection. Make sure it's nonzero:
|
||||
if (aSelectionOnly)
|
||||
{
|
||||
rv = GetSelectionForCopy(getter_AddRefs(sel));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!sel) return NS_ERROR_FAILURE;
|
||||
|
||||
PRBool isCollapsed;
|
||||
sel->GetIsCollapsed(&isCollapsed);
|
||||
if (isCollapsed)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// call the copy code
|
||||
return nsCopySupport::GetContents(aMimeType, aFlags, sel,
|
||||
mDocument, aOutValue);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::DoCopy()
|
||||
{
|
||||
if (!mDocument) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISelection> sel;
|
||||
nsresult rv = GetSelectionForCopy(getter_AddRefs(sel));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (!sel)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Now we have the selection. Make sure it's nonzero:
|
||||
PRBool isCollapsed;
|
||||
sel->GetIsCollapsed(&isCollapsed);
|
||||
if (isCollapsed)
|
||||
return NS_OK;
|
||||
|
||||
// call the copy code
|
||||
rv = nsCopySupport::HTMLCopy(sel, mDocument, nsIClipboard::kGlobalClipboard);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Now that we have copied, update the Paste menu item
|
||||
nsPIDOMWindow *domWindow = mDocument->GetWindow();
|
||||
if (domWindow)
|
||||
{
|
||||
domWindow->UpdateCommands(NS_LITERAL_STRING("clipboard"));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::CaptureHistoryState(nsILayoutHistoryState** aState, PRBool aLeavingPage)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user