mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 987040 - Part 1: Implement mozbrowserselectionchange. r=vingtetun,ehsan,bugs. sr=bz
This commit is contained in:
parent
48b52013e5
commit
bdc2515786
@ -346,6 +346,7 @@ var shell = {
|
||||
window.addEventListener('sizemodechange', this);
|
||||
window.addEventListener('unload', this);
|
||||
this.contentBrowser.addEventListener('mozbrowserloadstart', this, true);
|
||||
this.contentBrowser.addEventListener('mozbrowserselectionchange', this, true);
|
||||
|
||||
CustomEventManager.init();
|
||||
WebappsHelper.init();
|
||||
@ -372,6 +373,7 @@ var shell = {
|
||||
window.removeEventListener('mozfullscreenchange', this);
|
||||
window.removeEventListener('sizemodechange', this);
|
||||
this.contentBrowser.removeEventListener('mozbrowserloadstart', this, true);
|
||||
this.contentBrowser.removeEventListener('mozbrowserselectionchange', this, true);
|
||||
ppmm.removeMessageListener("content-handler", this);
|
||||
|
||||
UserAgentOverrides.uninit();
|
||||
@ -514,6 +516,30 @@ var shell = {
|
||||
this.notifyContentStart();
|
||||
break;
|
||||
|
||||
case 'mozbrowserselectionchange':
|
||||
// The mozbrowserselectionchange event, may have crossed the chrome-content boundary.
|
||||
// This event always dispatch to shell.js. But the offset we got from this event is
|
||||
// based on tab's coordinate. So get the actual offsets between shell and evt.target.
|
||||
let elt = evt.target;
|
||||
let win = elt.ownerDocument.defaultView;
|
||||
let offsetX = win.mozInnerScreenX;
|
||||
let offsetY = win.mozInnerScreenY;
|
||||
|
||||
let rect = elt.getBoundingClientRect();
|
||||
offsetX += rect.left;
|
||||
offsetY += rect.top;
|
||||
|
||||
let data = evt.detail;
|
||||
data.offsetX = offsetX;
|
||||
data.offsetY = offsetY;
|
||||
|
||||
DoCommandHelper.setEvent(evt);
|
||||
shell.sendChromeEvent({
|
||||
type: 'selectionchange',
|
||||
detail: data,
|
||||
});
|
||||
break;
|
||||
|
||||
case 'MozApplicationManifest':
|
||||
try {
|
||||
if (!Services.prefs.getBoolPref('browser.cache.offline.enable'))
|
||||
@ -713,6 +739,23 @@ var CustomEventManager = {
|
||||
case 'inputmethod-update-layouts':
|
||||
KeyboardHelper.handleEvent(detail);
|
||||
break;
|
||||
case 'do-command':
|
||||
DoCommandHelper.handleEvent(detail.cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let DoCommandHelper = {
|
||||
_event: null,
|
||||
setEvent: function docommand_setEvent(evt) {
|
||||
this._event = evt;
|
||||
},
|
||||
|
||||
handleEvent: function docommand_handleEvent(cmd) {
|
||||
if (this._event) {
|
||||
shell.sendEvent(this._event.target, 'mozdocommand', { cmd: cmd });
|
||||
this._event = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -715,7 +715,7 @@ nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPres
|
||||
// Now that we have copied, update the clipboard commands. This should have
|
||||
// the effect of updating the enabled state of the paste menu item.
|
||||
if (doDefault || count) {
|
||||
piWindow->UpdateCommands(NS_LITERAL_STRING("clipboard"));
|
||||
piWindow->UpdateCommands(NS_LITERAL_STRING("clipboard"), nullptr, 0);
|
||||
}
|
||||
|
||||
return doDefault;
|
||||
|
@ -676,7 +676,9 @@ protected:
|
||||
*/
|
||||
virtual ~nsTextInputListener();
|
||||
|
||||
nsresult UpdateTextInputCommands(const nsAString& commandsToUpdate);
|
||||
nsresult UpdateTextInputCommands(const nsAString& commandsToUpdate,
|
||||
nsISelection* sel = nullptr,
|
||||
int16_t reason = 0);
|
||||
|
||||
protected:
|
||||
|
||||
@ -780,16 +782,18 @@ nsTextInputListener::NotifySelectionChanged(nsIDOMDocument* aDoc, nsISelection*
|
||||
}
|
||||
}
|
||||
|
||||
UpdateTextInputCommands(NS_LITERAL_STRING("selectionchange"), aSel, aReason);
|
||||
|
||||
// if the collapsed state did not change, don't fire notifications
|
||||
if (collapsed == mSelectionWasCollapsed)
|
||||
return NS_OK;
|
||||
|
||||
|
||||
mSelectionWasCollapsed = collapsed;
|
||||
|
||||
if (!weakFrame.IsAlive() || !nsContentUtils::IsFocusedContent(mFrame->GetContent()))
|
||||
return NS_OK;
|
||||
|
||||
return UpdateTextInputCommands(NS_LITERAL_STRING("select"));
|
||||
return UpdateTextInputCommands(NS_LITERAL_STRING("select"), aSel, aReason);
|
||||
}
|
||||
|
||||
// END nsIDOMSelectionListener
|
||||
@ -930,7 +934,9 @@ nsTextInputListener::EditAction()
|
||||
|
||||
|
||||
nsresult
|
||||
nsTextInputListener::UpdateTextInputCommands(const nsAString& commandsToUpdate)
|
||||
nsTextInputListener::UpdateTextInputCommands(const nsAString& commandsToUpdate,
|
||||
nsISelection* sel,
|
||||
int16_t reason)
|
||||
{
|
||||
nsIContent* content = mFrame->GetContent();
|
||||
NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
|
||||
@ -941,7 +947,7 @@ nsTextInputListener::UpdateTextInputCommands(const nsAString& commandsToUpdate)
|
||||
nsPIDOMWindow *domWindow = doc->GetWindow();
|
||||
NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
|
||||
|
||||
return domWindow->UpdateCommands(commandsToUpdate);
|
||||
return domWindow->UpdateCommands(commandsToUpdate, sel, reason);
|
||||
}
|
||||
|
||||
// END nsTextInputListener
|
||||
|
@ -923,7 +923,7 @@ nsFocusManager::WindowHidden(nsIDOMWindow* aWindow)
|
||||
NotifyFocusStateChange(oldFocusedContent,
|
||||
mFocusedWindow->ShouldShowFocusRing(),
|
||||
false);
|
||||
window->UpdateCommands(NS_LITERAL_STRING("focus"));
|
||||
window->UpdateCommands(NS_LITERAL_STRING("focus"), nullptr, 0);
|
||||
|
||||
if (presShell) {
|
||||
SendFocusOrBlurEvent(NS_BLUR_CONTENT, presShell,
|
||||
@ -1266,7 +1266,7 @@ nsFocusManager::SetFocusInner(nsIContent* aNewContent, int32_t aFlags,
|
||||
// update the commands even when inactive so that the attributes for that
|
||||
// window are up to date.
|
||||
if (allowFrameSwitch)
|
||||
newWindow->UpdateCommands(NS_LITERAL_STRING("focus"));
|
||||
newWindow->UpdateCommands(NS_LITERAL_STRING("focus"), nullptr, 0);
|
||||
|
||||
if (aFlags & FLAG_RAISE)
|
||||
RaiseWindow(newRootWindow);
|
||||
@ -1586,7 +1586,7 @@ nsFocusManager::Blur(nsPIDOMWindow* aWindowToClear,
|
||||
// window, then this was a blur caused by the active window being lowered,
|
||||
// so there is no need to update the commands
|
||||
if (mActiveWindow)
|
||||
window->UpdateCommands(NS_LITERAL_STRING("focus"));
|
||||
window->UpdateCommands(NS_LITERAL_STRING("focus"), nullptr, 0);
|
||||
|
||||
SendFocusOrBlurEvent(NS_BLUR_CONTENT, presShell,
|
||||
content->GetCurrentDoc(), content, 1, false);
|
||||
@ -1807,7 +1807,7 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow,
|
||||
// commands
|
||||
// XXXndeakin P2 someone could adjust the focus during the update
|
||||
if (!aWindowRaised)
|
||||
aWindow->UpdateCommands(NS_LITERAL_STRING("focus"));
|
||||
aWindow->UpdateCommands(NS_LITERAL_STRING("focus"), nullptr, 0);
|
||||
|
||||
SendFocusOrBlurEvent(NS_FOCUS_CONTENT, presShell,
|
||||
aContent->GetCurrentDoc(),
|
||||
@ -1817,7 +1817,7 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow,
|
||||
IMEStateManager::OnChangeFocus(presContext, nullptr,
|
||||
GetFocusMoveActionCause(aFlags));
|
||||
if (!aWindowRaised) {
|
||||
aWindow->UpdateCommands(NS_LITERAL_STRING("focus"));
|
||||
aWindow->UpdateCommands(NS_LITERAL_STRING("focus"), nullptr, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1842,7 +1842,7 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow,
|
||||
GetFocusMoveActionCause(aFlags));
|
||||
|
||||
if (!aWindowRaised)
|
||||
aWindow->UpdateCommands(NS_LITERAL_STRING("focus"));
|
||||
aWindow->UpdateCommands(NS_LITERAL_STRING("focus"), nullptr, 0);
|
||||
}
|
||||
|
||||
// update the caret visibility and position to match the newly focused
|
||||
|
@ -199,6 +199,8 @@
|
||||
|
||||
#include "nsRefreshDriver.h"
|
||||
|
||||
#include "mozilla/dom/SelectionChangeEvent.h"
|
||||
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsLocation.h"
|
||||
@ -9248,7 +9250,7 @@ public:
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::UpdateCommands(const nsAString& anAction)
|
||||
nsGlobalWindow::UpdateCommands(const nsAString& anAction, nsISelection* aSel, int16_t aReason)
|
||||
{
|
||||
nsPIDOMWindow *rootWindow = nsGlobalWindow::GetPrivateRoot();
|
||||
if (!rootWindow)
|
||||
@ -9257,7 +9259,9 @@ nsGlobalWindow::UpdateCommands(const nsAString& anAction)
|
||||
nsCOMPtr<nsIDOMXULDocument> xulDoc =
|
||||
do_QueryInterface(rootWindow->GetExtantDoc());
|
||||
// See if we contain a XUL document.
|
||||
if (xulDoc) {
|
||||
// selectionchange action is only used for mozbrowser, not for XUL. So we bypass
|
||||
// XUL command dispatch if anAction is "selectionchange".
|
||||
if (xulDoc && !anAction.EqualsLiteral("selectionchange")) {
|
||||
// Retrieve the command dispatcher and call updateCommands on it.
|
||||
nsCOMPtr<nsIDOMXULCommandDispatcher> xulCommandDispatcher;
|
||||
xulDoc->GetCommandDispatcher(getter_AddRefs(xulCommandDispatcher));
|
||||
@ -9267,6 +9271,29 @@ nsGlobalWindow::UpdateCommands(const nsAString& anAction)
|
||||
}
|
||||
}
|
||||
|
||||
if (mDoc && anAction.EqualsLiteral("selectionchange")) {
|
||||
SelectionChangeEventInit init;
|
||||
init.mBubbles = true;
|
||||
if (aSel) {
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
nsresult rv = aSel->GetRangeAt(0, getter_AddRefs(range));
|
||||
if (NS_SUCCEEDED(rv) && range) {
|
||||
nsRefPtr<nsRange> nsrange = static_cast<nsRange*>(range.get());
|
||||
init.mBoundingClientRect = nsrange->GetBoundingClientRect(true);
|
||||
range->ToString(init.mSelectedText);
|
||||
init.mReason = aReason;
|
||||
}
|
||||
|
||||
nsRefPtr<SelectionChangeEvent> event =
|
||||
SelectionChangeEvent::Constructor(mDoc, NS_LITERAL_STRING("mozselectionchange"), init);
|
||||
|
||||
event->SetTrusted(true);
|
||||
event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
|
||||
bool ret;
|
||||
mDoc->DispatchEvent(event, &ret);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -108,6 +108,13 @@ const OBSERVED_EVENTS = [
|
||||
'activity-done'
|
||||
];
|
||||
|
||||
const COMMAND_MAP = {
|
||||
'cut': 'cmd_cut',
|
||||
'copy': 'cmd_copy',
|
||||
'paste': 'cmd_paste',
|
||||
'selectall': 'cmd_selectAll'
|
||||
};
|
||||
|
||||
/**
|
||||
* The BrowserElementChild implements one half of <iframe mozbrowser>.
|
||||
* (The other half is, unsurprisingly, BrowserElementParent.)
|
||||
@ -200,6 +207,10 @@ BrowserElementChild.prototype = {
|
||||
/* useCapture = */ true,
|
||||
/* wantsUntrusted = */ false);
|
||||
|
||||
addEventListener('mozselectionchange',
|
||||
this._selectionChangeHandler.bind(this),
|
||||
/* useCapture = */ false,
|
||||
/* wantsUntrusted = */ false);
|
||||
|
||||
// This listens to unload events from our message manager, but /not/ from
|
||||
// the |content| window. That's because the window's unload event doesn't
|
||||
@ -237,7 +248,8 @@ BrowserElementChild.prototype = {
|
||||
"exit-fullscreen": this._recvExitFullscreen.bind(this),
|
||||
"activate-next-paint-listener": this._activateNextPaintListener.bind(this),
|
||||
"set-input-method-active": this._recvSetInputMethodActive.bind(this),
|
||||
"deactivate-next-paint-listener": this._deactivateNextPaintListener.bind(this)
|
||||
"deactivate-next-paint-listener": this._deactivateNextPaintListener.bind(this),
|
||||
"do-command": this._recvDoCommand
|
||||
}
|
||||
|
||||
addMessageListener("browser-element-api:call", function(aMessage) {
|
||||
@ -351,6 +363,15 @@ BrowserElementChild.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_isCommandEnabled: function(cmd) {
|
||||
let command = COMMAND_MAP[cmd];
|
||||
if (!command) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return docShell.isCommandEnabled(command);
|
||||
},
|
||||
|
||||
/**
|
||||
* Spin in a nested event loop until we receive a unblock-modal-prompt message for
|
||||
* this window.
|
||||
@ -589,6 +610,53 @@ BrowserElementChild.prototype = {
|
||||
sendAsyncMsg('metachange', meta);
|
||||
},
|
||||
|
||||
_selectionChangeHandler: function(e) {
|
||||
let isMouseUp = e.reason & Ci.nsISelectionListener.MOUSEUP_REASON;
|
||||
let isSelectAll = e.reason & Ci.nsISelectionListener.SELECTALL_REASON;
|
||||
// When selectall happened, gecko will first collapse the range then
|
||||
// select all. So we will receive two selection change events with
|
||||
// SELECTALL_REASON. We filter first event by check the length of
|
||||
// selectedText.
|
||||
if (!(isMouseUp || (isSelectAll && e.selectedText.length > 0))) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
let boundingClientRect = e.boundingClientRect;
|
||||
let zoomFactor = content.screen.width / content.innerWidth;
|
||||
|
||||
let detail = {
|
||||
rect: {
|
||||
width: boundingClientRect.width,
|
||||
height: boundingClientRect.height,
|
||||
top: boundingClientRect.top,
|
||||
bottom: boundingClientRect.bottom,
|
||||
left: boundingClientRect.left,
|
||||
right: boundingClientRect.right,
|
||||
},
|
||||
commands: {
|
||||
canSelectAll: this._isCommandEnabled("selectall"),
|
||||
canCut: this._isCommandEnabled("cut"),
|
||||
canCopy: this._isCommandEnabled("copy"),
|
||||
canPaste: this._isCommandEnabled("paste"),
|
||||
},
|
||||
zoomFactor: zoomFactor,
|
||||
};
|
||||
|
||||
// Get correct geometry information if we have nested <iframe mozbrowser>
|
||||
let currentWindow = e.target.defaultView;
|
||||
while (currentWindow.realFrameElement) {
|
||||
let currentRect = currentWindow.realFrameElement.getBoundingClientRect();
|
||||
detail.rect.top += currentRect.top;
|
||||
detail.rect.bottom += currentRect.top;
|
||||
detail.rect.left += currentRect.left;
|
||||
detail.rect.right += currentRect.left;
|
||||
currentWindow = currentWindow.realFrameElement.ownerDocument.defaultView;
|
||||
}
|
||||
|
||||
sendAsyncMsg("selectionchange", detail);
|
||||
},
|
||||
|
||||
_themeColorChangedHandler: function(eventType, target) {
|
||||
let meta = {
|
||||
name: 'theme-color',
|
||||
@ -1031,6 +1099,12 @@ BrowserElementChild.prototype = {
|
||||
webNav.stop(webNav.STOP_NETWORK);
|
||||
},
|
||||
|
||||
_recvDoCommand: function(data) {
|
||||
if (this._isCommandEnabled(data.json.command)) {
|
||||
docShell.doCommand(COMMAND_MAP[data.json.command]);
|
||||
}
|
||||
},
|
||||
|
||||
_recvSetInputMethodActive: function(data) {
|
||||
let msgData = { id: data.json.id };
|
||||
if (!this._isContentWindowCreated) {
|
||||
|
@ -159,6 +159,11 @@ function BrowserElementParent(frameLoader, hasRemoteFrame, isPendingFrame) {
|
||||
/* wantsUntrusted = */ false);
|
||||
}
|
||||
|
||||
this._frameElement.addEventListener('mozdocommand',
|
||||
this._doCommandHandler.bind(this),
|
||||
/* useCapture = */ false,
|
||||
/* wantsUntrusted = */ false);
|
||||
|
||||
this._window._browserElementParents.set(this, null);
|
||||
|
||||
// Insert ourself into the prompt service.
|
||||
@ -247,7 +252,8 @@ BrowserElementParent.prototype = {
|
||||
"exit-fullscreen": this._exitFullscreen,
|
||||
"got-visible": this._gotDOMRequestResult,
|
||||
"visibilitychange": this._childVisibilityChange,
|
||||
"got-set-input-method-active": this._gotDOMRequestResult
|
||||
"got-set-input-method-active": this._gotDOMRequestResult,
|
||||
"selectionchange": this._handleSelectionChange
|
||||
};
|
||||
|
||||
this._mm.addMessageListener('browser-element-api:call', function(aMsg) {
|
||||
@ -449,6 +455,17 @@ BrowserElementParent.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_handleSelectionChange: function(data) {
|
||||
let evt = this._createEvent('selectionchange', data.json,
|
||||
/* cancelable = */ false);
|
||||
this._frameElement.dispatchEvent(evt);
|
||||
},
|
||||
|
||||
_doCommandHandler: function(e) {
|
||||
e.stopPropagation();
|
||||
this._sendAsyncMsg('do-command', { command: e.detail.cmd });
|
||||
},
|
||||
|
||||
_createEvent: function(evtName, detail, cancelable) {
|
||||
// This will have to change if we ever want to send a CustomEvent with null
|
||||
// detail. For now, it's OK.
|
||||
|
@ -23,7 +23,7 @@ interface nsIVariant;
|
||||
* @see <http://www.whatwg.org/html/#window>
|
||||
*/
|
||||
|
||||
[scriptable, uuid(c3ff0328-6c47-4e64-a22f-ac221959e258)]
|
||||
[scriptable, uuid(ed7cc4e4-cf5b-42af-9c2e-8df074a01470)]
|
||||
interface nsIDOMWindow : nsISupports
|
||||
{
|
||||
// the current browsing context
|
||||
@ -426,7 +426,9 @@ interface nsIDOMWindow : nsISupports
|
||||
in nsISupports aExtraArgument);
|
||||
|
||||
// XXX Should this be in nsIDOMChromeWindow?
|
||||
void updateCommands(in DOMString action);
|
||||
void updateCommands(in DOMString action,
|
||||
[optional] in nsISelection sel,
|
||||
[optional] in short reason);
|
||||
|
||||
/* Find in page.
|
||||
* @param str: the search pattern
|
||||
|
19
dom/webidl/SelectionChangeEvent.webidl
Normal file
19
dom/webidl/SelectionChangeEvent.webidl
Normal file
@ -0,0 +1,19 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
dictionary SelectionChangeEventInit : EventInit {
|
||||
DOMString selectedText = "";
|
||||
DOMRectReadOnly? boundingClientRect = null;
|
||||
short reason = 0;
|
||||
};
|
||||
|
||||
[Constructor(DOMString type, optional SelectionChangeEventInit eventInit),
|
||||
ChromeOnly]
|
||||
interface SelectionChangeEvent : Event {
|
||||
readonly attribute DOMString selectedText;
|
||||
readonly attribute DOMRectReadOnly? boundingClientRect;
|
||||
readonly attribute short reason;
|
||||
};
|
@ -303,7 +303,9 @@ partial interface Window {
|
||||
[Throws, ChromeOnly] void home();
|
||||
|
||||
// XXX Should this be in nsIDOMChromeWindow?
|
||||
void updateCommands(DOMString action);
|
||||
void updateCommands(DOMString action,
|
||||
optional Selection? sel = null,
|
||||
optional short reason = 0);
|
||||
|
||||
/* Find in page.
|
||||
* @param str: the search pattern
|
||||
|
@ -668,6 +668,7 @@ GENERATED_EVENTS_WEBIDL_FILES = [
|
||||
'RTCPeerConnectionIceEvent.webidl',
|
||||
'RTCPeerConnectionIdentityErrorEvent.webidl',
|
||||
'RTCPeerConnectionIdentityEvent.webidl',
|
||||
'SelectionChangeEvent.webidl',
|
||||
'SmartCardEvent.webidl',
|
||||
'StyleRuleChangeEvent.webidl',
|
||||
'StyleSheetApplicableStateChangeEvent.webidl',
|
||||
|
@ -3529,7 +3529,7 @@ NS_IMETHODIMP nsDocumentViewer::GetInImage(bool* aInImage)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDocViewerSelectionListener::NotifySelectionChanged(nsIDOMDocument *, nsISelection *, int16_t)
|
||||
NS_IMETHODIMP nsDocViewerSelectionListener::NotifySelectionChanged(nsIDOMDocument *, nsISelection *, int16_t aReason)
|
||||
{
|
||||
NS_ASSERTION(mDocViewer, "Should have doc viewer!");
|
||||
|
||||
@ -3538,6 +3538,12 @@ NS_IMETHODIMP nsDocViewerSelectionListener::NotifySelectionChanged(nsIDOMDocumen
|
||||
nsresult rv = mDocViewer->GetDocumentSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsIDocument* theDoc = mDocViewer->GetDocument();
|
||||
if (!theDoc) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> domWindow = theDoc->GetWindow();
|
||||
if (!domWindow) return NS_ERROR_FAILURE;
|
||||
|
||||
bool selectionCollapsed;
|
||||
selection->GetIsCollapsed(&selectionCollapsed);
|
||||
// we only call UpdateCommands when the selection changes from collapsed
|
||||
@ -3545,17 +3551,13 @@ NS_IMETHODIMP nsDocViewerSelectionListener::NotifySelectionChanged(nsIDOMDocumen
|
||||
// for simple selection changes, but that would be expenseive.
|
||||
if (!mGotSelectionState || mSelectionWasCollapsed != selectionCollapsed)
|
||||
{
|
||||
nsIDocument* theDoc = mDocViewer->GetDocument();
|
||||
if (!theDoc) return NS_ERROR_FAILURE;
|
||||
|
||||
nsPIDOMWindow *domWindow = theDoc->GetWindow();
|
||||
if (!domWindow) return NS_ERROR_FAILURE;
|
||||
|
||||
domWindow->UpdateCommands(NS_LITERAL_STRING("select"));
|
||||
domWindow->UpdateCommands(NS_LITERAL_STRING("select"), selection, aReason);
|
||||
mGotSelectionState = true;
|
||||
mSelectionWasCollapsed = selectionCollapsed;
|
||||
}
|
||||
|
||||
domWindow->UpdateCommands(NS_LITERAL_STRING("selectionchange"), selection, aReason);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user