Skip to content

Commit

Permalink
Update clipboard command controllers to match cut/copy action spec.
Browse files Browse the repository at this point in the history
  • Loading branch information
wolfbeast committed Dec 19, 2016
1 parent 385d59f commit 66bb875
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 32 deletions.
65 changes: 46 additions & 19 deletions dom/base/nsCopySupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "nsIFrame.h"
#include "nsIURI.h"
#include "nsISimpleEnumerator.h"
#include "nsIFormControl.h"

// image copy stuff
#include "nsIImageLoadingContent.h"
Expand Down Expand Up @@ -583,8 +584,14 @@ nsCopySupport::CanCopy(nsIDocument* aDocument)
}

bool
nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPresShell* aPresShell, nsISelection* aSelection)
nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPresShell* aPresShell,
nsISelection* aSelection, bool* aActionTaken)
{
// Keep track of action taken or not to pass up the chain.
if (aActionTaken) {
*aActionTaken = false;
}

NS_ASSERTION(aType == NS_CUT || aType == NS_COPY || aType == NS_PASTE,
"Invalid clipboard event type");

Expand All @@ -609,14 +616,6 @@ nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPres
// retrieve the event target node from the start of the selection
nsresult rv;
if (sel) {
// Only cut or copy when there is an uncollapsed selection
if (aType == NS_CUT || aType == NS_COPY) {
bool isCollapsed;
sel->GetIsCollapsed(&isCollapsed);
if (isCollapsed)
return false;
}

nsCOMPtr<nsIDOMRange> range;
rv = sel->GetRangeAt(0, getter_AddRefs(range));
if (NS_SUCCEEDED(rv) && range) {
Expand Down Expand Up @@ -670,7 +669,9 @@ nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPres
clipboardData->ClearAll();
clipboardData->SetReadOnly();
}

if (aActionTaken) {
*aActionTaken = true;
}
return doDefault;
}

Expand All @@ -684,15 +685,38 @@ nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPres
// use the data added to the data transfer and copy that instead.
uint32_t count = 0;
if (doDefault) {
// get the data from the selection if any
bool isCollapsed;
sel->GetIsCollapsed(&isCollapsed);
if (isCollapsed) {
return false;
// find the focused node
nsCOMPtr<nsIContent> srcNode = content;
if (content->IsInNativeAnonymousSubtree()) {
srcNode = content->FindFirstNonChromeOnlyAccessContent();
}

// check if we are looking at a password input
nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(srcNode);
if (formControl) {
if (formControl->GetType() == NS_FORM_INPUT_PASSWORD) {
return false;
}
}
// call the copy code
rv = HTMLCopy(sel, doc, aClipboardType);
if (NS_FAILED(rv)) {

// when cutting non-editable content, do nothing
// XXX this may be the wrong editable flag to check
if (aType != NS_CUT || content->IsEditable()) {
// get the data from the selection if any
bool isCollapsed;
sel->GetIsCollapsed(&isCollapsed);
if (isCollapsed) {
if (aActionTaken) {
*aActionTaken = true;
}
return false;
}
// call the copy code
rv = HTMLCopy(sel, doc, aClipboardType);
if (NS_FAILED(rv)) {
return false;
}
} else {
return false;
}
} else if (clipboardData) {
Expand Down Expand Up @@ -720,6 +744,9 @@ nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPres
if (doDefault || count) {
piWindow->UpdateCommands(NS_LITERAL_STRING("clipboard"), nullptr, 0);
}

if (aActionTaken) {
*aActionTaken = true;
}

return doDefault;
}
6 changes: 5 additions & 1 deletion dom/base/nsCopySupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,16 @@ class nsCopySupport
*
* aClipboardType specifies which clipboard to use, from nsIClipboard.
*
* If aActionTaken is non-NULL, it will be set to true if an action was
* taken, whether it be the default action or the default being prevented.
*
* If the event is cancelled or an error occurs, false will be returned.
*/
static bool FireClipboardEvent(int32_t aType,
int32_t aClipboardType,
nsIPresShell* aPresShell,
nsISelection* aSelection);
nsISelection* aSelection,
bool* aActionTaken = nullptr);
};

#endif
17 changes: 14 additions & 3 deletions dom/base/nsGlobalWindowCommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,9 @@ nsClipboardCommand::IsCommandEnabled(const char* aCommandName, nsISupports *aCon
nsresult
nsClipboardCommand::DoCommand(const char *aCommandName, nsISupports *aContext)
{
if (strcmp(aCommandName, "cmd_copy") &&
// Careful: inverse logic.
if (strcmp(aCommandName, "cmd_cut") &&
strcmp(aCommandName, "cmd_copy") &&
strcmp(aCommandName, "cmd_copyAndCollapseToEnd"))
return NS_OK;

Expand All @@ -521,7 +523,13 @@ nsClipboardCommand::DoCommand(const char *aCommandName, nsISupports *aContext)
nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);

nsCopySupport::FireClipboardEvent(NS_COPY, nsIClipboard::kGlobalClipboard, presShell, nullptr);
int32_t eventType = NS_COPY;
if (strcmp(aCommandName, "cmd_cut") == 0) {
eventType = NS_CUT;
}

bool actionTaken = false;
nsCopySupport::FireClipboardEvent(eventType, nsIClipboard::kGlobalClipboard, presShell, nullptr, &actionTaken);

if (!strcmp(aCommandName, "cmd_copyAndCollapseToEnd")) {
dom::Selection *sel =
Expand All @@ -530,7 +538,10 @@ nsClipboardCommand::DoCommand(const char *aCommandName, nsISupports *aContext)
sel->CollapseToEnd();
}

return NS_OK;
if (actionTaken) {
return NS_OK;
}
return NS_ERROR_FAILURE;
}

NS_IMETHODIMP
Expand Down
2 changes: 1 addition & 1 deletion dom/tests/mochitest/general/test_clipboard_events.html
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
content.oncut = function() { oncut_fired = true; };
try {
synthesizeKey("x", {accelKey: 1});
ok(!oncut_fired, "cut event firing on DOM element")
ok(oncut_fired, "cut event firing on DOM element")
is(getClipboardText(), clipboardInitialValue,
"cut on DOM element did not modify clipboard");
} finally {
Expand Down
18 changes: 11 additions & 7 deletions editor/libeditor/nsPlaintextEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1168,7 +1168,7 @@ nsPlaintextEditor::CanCutOrCopy(PasswordFieldAllowed aPasswordFieldAllowed)
}

bool
nsPlaintextEditor::FireClipboardEvent(int32_t aType, int32_t aSelectionType)
nsPlaintextEditor::FireClipboardEvent(int32_t aType, int32_t aSelectionType, bool* aActionTaken)
{
if (aType == NS_PASTE)
ForceCompositionEnd();
Expand All @@ -1181,7 +1181,7 @@ nsPlaintextEditor::FireClipboardEvent(int32_t aType, int32_t aSelectionType)
return false;
}

if (!nsCopySupport::FireClipboardEvent(aType, aSelectionType, presShell, selection))
if (!nsCopySupport::FireClipboardEvent(aType, aSelectionType, presShell, selection, aActionTaken))
return false;

// If the event handler caused the editor to be destroyed, return false.
Expand All @@ -1191,9 +1191,11 @@ nsPlaintextEditor::FireClipboardEvent(int32_t aType, int32_t aSelectionType)

NS_IMETHODIMP nsPlaintextEditor::Cut()
{
if (FireClipboardEvent(NS_CUT, nsIClipboard::kGlobalClipboard))
return DeleteSelection(eNone, eStrip);
return NS_OK;
bool actionTaken = false;
if (FireClipboardEvent(NS_CUT, nsIClipboard::kGlobalClipboard, &actionTaken)) {
DeleteSelection(eNone, eStrip);
}
return actionTaken ? NS_OK : NS_ERROR_FAILURE;
}

NS_IMETHODIMP nsPlaintextEditor::CanCut(bool *aCanCut)
Expand All @@ -1208,8 +1210,10 @@ NS_IMETHODIMP nsPlaintextEditor::CanCut(bool *aCanCut)

NS_IMETHODIMP nsPlaintextEditor::Copy()
{
FireClipboardEvent(NS_COPY, nsIClipboard::kGlobalClipboard);
return NS_OK;
bool actionTaken = false;
FireClipboardEvent(NS_COPY, nsIClipboard::kGlobalClipboard, &actionTaken);

return actionTaken ? NS_OK : NS_ERROR_FAILURE;
}

NS_IMETHODIMP nsPlaintextEditor::CanCopy(bool *aCanCopy)
Expand Down
2 changes: 1 addition & 1 deletion editor/libeditor/nsPlaintextEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ class nsPlaintextEditor : public nsEditor,
ePasswordFieldNotAllowed
};
bool CanCutOrCopy(PasswordFieldAllowed aPasswordFieldAllowed);
bool FireClipboardEvent(int32_t aType, int32_t aSelectionType);
bool FireClipboardEvent(int32_t aType, int32_t aSelectionType, bool* aActionTaken = nullptr);

bool UpdateMetaCharset(nsIDOMDocument* aDocument,
const nsACString& aCharacterSet);
Expand Down

0 comments on commit 66bb875

Please sign in to comment.