content/xul/document/src/nsXULCommandDispatcher.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=2 sw=2 et tw=80: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 /*
michael@0 8
michael@0 9 This file provides the implementation for the XUL Command Dispatcher.
michael@0 10
michael@0 11 */
michael@0 12
michael@0 13 #include "nsIContent.h"
michael@0 14 #include "nsFocusManager.h"
michael@0 15 #include "nsIControllers.h"
michael@0 16 #include "nsIDOMDocument.h"
michael@0 17 #include "nsIDOMElement.h"
michael@0 18 #include "nsIDOMWindow.h"
michael@0 19 #include "nsIDOMXULElement.h"
michael@0 20 #include "nsIDocument.h"
michael@0 21 #include "nsPresContext.h"
michael@0 22 #include "nsIPresShell.h"
michael@0 23 #include "nsIScriptGlobalObject.h"
michael@0 24 #include "nsPIDOMWindow.h"
michael@0 25 #include "nsPIWindowRoot.h"
michael@0 26 #include "nsRDFCID.h"
michael@0 27 #include "nsXULCommandDispatcher.h"
michael@0 28 #include "prlog.h"
michael@0 29 #include "nsContentUtils.h"
michael@0 30 #include "nsReadableUtils.h"
michael@0 31 #include "nsCRT.h"
michael@0 32 #include "nsError.h"
michael@0 33 #include "nsDOMClassInfoID.h"
michael@0 34 #include "mozilla/BasicEvents.h"
michael@0 35 #include "mozilla/EventDispatcher.h"
michael@0 36 #include "mozilla/dom/Element.h"
michael@0 37
michael@0 38 using namespace mozilla;
michael@0 39
michael@0 40 #ifdef PR_LOGGING
michael@0 41 static PRLogModuleInfo* gCommandLog;
michael@0 42 #endif
michael@0 43
michael@0 44 ////////////////////////////////////////////////////////////////////////
michael@0 45
michael@0 46 nsXULCommandDispatcher::nsXULCommandDispatcher(nsIDocument* aDocument)
michael@0 47 : mDocument(aDocument), mUpdaters(nullptr)
michael@0 48 {
michael@0 49
michael@0 50 #ifdef PR_LOGGING
michael@0 51 if (! gCommandLog)
michael@0 52 gCommandLog = PR_NewLogModule("nsXULCommandDispatcher");
michael@0 53 #endif
michael@0 54 }
michael@0 55
michael@0 56 nsXULCommandDispatcher::~nsXULCommandDispatcher()
michael@0 57 {
michael@0 58 Disconnect();
michael@0 59 }
michael@0 60
michael@0 61 // QueryInterface implementation for nsXULCommandDispatcher
michael@0 62
michael@0 63 DOMCI_DATA(XULCommandDispatcher, nsXULCommandDispatcher)
michael@0 64
michael@0 65 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULCommandDispatcher)
michael@0 66 NS_INTERFACE_MAP_ENTRY(nsIDOMXULCommandDispatcher)
michael@0 67 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
michael@0 68 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMXULCommandDispatcher)
michael@0 69 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XULCommandDispatcher)
michael@0 70 NS_INTERFACE_MAP_END
michael@0 71
michael@0 72 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULCommandDispatcher)
michael@0 73 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULCommandDispatcher)
michael@0 74
michael@0 75 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULCommandDispatcher)
michael@0 76
michael@0 77 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULCommandDispatcher)
michael@0 78 tmp->Disconnect();
michael@0 79 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
michael@0 80
michael@0 81 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULCommandDispatcher)
michael@0 82 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
michael@0 83 Updater* updater = tmp->mUpdaters;
michael@0 84 while (updater) {
michael@0 85 cb.NoteXPCOMChild(updater->mElement);
michael@0 86 updater = updater->mNext;
michael@0 87 }
michael@0 88 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
michael@0 89
michael@0 90 void
michael@0 91 nsXULCommandDispatcher::Disconnect()
michael@0 92 {
michael@0 93 while (mUpdaters) {
michael@0 94 Updater* doomed = mUpdaters;
michael@0 95 mUpdaters = mUpdaters->mNext;
michael@0 96 delete doomed;
michael@0 97 }
michael@0 98 mDocument = nullptr;
michael@0 99 }
michael@0 100
michael@0 101 already_AddRefed<nsPIWindowRoot>
michael@0 102 nsXULCommandDispatcher::GetWindowRoot()
michael@0 103 {
michael@0 104 if (mDocument) {
michael@0 105 nsCOMPtr<nsPIDOMWindow> window(mDocument->GetWindow());
michael@0 106 if (window) {
michael@0 107 return window->GetTopWindowRoot();
michael@0 108 }
michael@0 109 }
michael@0 110
michael@0 111 return nullptr;
michael@0 112 }
michael@0 113
michael@0 114 nsIContent*
michael@0 115 nsXULCommandDispatcher::GetRootFocusedContentAndWindow(nsPIDOMWindow** aWindow)
michael@0 116 {
michael@0 117 *aWindow = nullptr;
michael@0 118
michael@0 119 if (mDocument) {
michael@0 120 nsCOMPtr<nsPIDOMWindow> win = mDocument->GetWindow();
michael@0 121 if (win) {
michael@0 122 nsCOMPtr<nsPIDOMWindow> rootWindow = win->GetPrivateRoot();
michael@0 123 if (rootWindow) {
michael@0 124 return nsFocusManager::GetFocusedDescendant(rootWindow, true, aWindow);
michael@0 125 }
michael@0 126 }
michael@0 127 }
michael@0 128
michael@0 129 return nullptr;
michael@0 130 }
michael@0 131
michael@0 132 NS_IMETHODIMP
michael@0 133 nsXULCommandDispatcher::GetFocusedElement(nsIDOMElement** aElement)
michael@0 134 {
michael@0 135 *aElement = nullptr;
michael@0 136
michael@0 137 nsCOMPtr<nsPIDOMWindow> focusedWindow;
michael@0 138 nsIContent* focusedContent =
michael@0 139 GetRootFocusedContentAndWindow(getter_AddRefs(focusedWindow));
michael@0 140 if (focusedContent) {
michael@0 141 CallQueryInterface(focusedContent, aElement);
michael@0 142
michael@0 143 // Make sure the caller can access the focused element.
michael@0 144 if (!nsContentUtils::CanCallerAccess(*aElement)) {
michael@0 145 // XXX This might want to return null, but we use that return value
michael@0 146 // to mean "there is no focused element," so to be clear, throw an
michael@0 147 // exception.
michael@0 148 NS_RELEASE(*aElement);
michael@0 149 return NS_ERROR_DOM_SECURITY_ERR;
michael@0 150 }
michael@0 151 }
michael@0 152
michael@0 153 return NS_OK;
michael@0 154 }
michael@0 155
michael@0 156 NS_IMETHODIMP
michael@0 157 nsXULCommandDispatcher::GetFocusedWindow(nsIDOMWindow** aWindow)
michael@0 158 {
michael@0 159 *aWindow = nullptr;
michael@0 160
michael@0 161 nsCOMPtr<nsPIDOMWindow> window;
michael@0 162 GetRootFocusedContentAndWindow(getter_AddRefs(window));
michael@0 163 if (!window)
michael@0 164 return NS_OK;
michael@0 165
michael@0 166 // Make sure the caller can access this window. The caller can access this
michael@0 167 // window iff it can access the document.
michael@0 168 nsCOMPtr<nsIDOMDocument> domdoc;
michael@0 169 nsresult rv = window->GetDocument(getter_AddRefs(domdoc));
michael@0 170 NS_ENSURE_SUCCESS(rv, rv);
michael@0 171
michael@0 172 // Note: If there is no document, then this window has been cleared and
michael@0 173 // there's nothing left to protect, so let the window pass through.
michael@0 174 if (domdoc && !nsContentUtils::CanCallerAccess(domdoc))
michael@0 175 return NS_ERROR_DOM_SECURITY_ERR;
michael@0 176
michael@0 177 CallQueryInterface(window, aWindow);
michael@0 178 return NS_OK;
michael@0 179 }
michael@0 180
michael@0 181 NS_IMETHODIMP
michael@0 182 nsXULCommandDispatcher::SetFocusedElement(nsIDOMElement* aElement)
michael@0 183 {
michael@0 184 nsIFocusManager* fm = nsFocusManager::GetFocusManager();
michael@0 185 NS_ENSURE_TRUE(fm, NS_ERROR_FAILURE);
michael@0 186
michael@0 187 if (aElement)
michael@0 188 return fm->SetFocus(aElement, 0);
michael@0 189
michael@0 190 // if aElement is null, clear the focus in the currently focused child window
michael@0 191 nsCOMPtr<nsPIDOMWindow> focusedWindow;
michael@0 192 GetRootFocusedContentAndWindow(getter_AddRefs(focusedWindow));
michael@0 193 return fm->ClearFocus(focusedWindow);
michael@0 194 }
michael@0 195
michael@0 196 NS_IMETHODIMP
michael@0 197 nsXULCommandDispatcher::SetFocusedWindow(nsIDOMWindow* aWindow)
michael@0 198 {
michael@0 199 NS_ENSURE_TRUE(aWindow, NS_OK); // do nothing if set to null
michael@0 200
michael@0 201 nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(aWindow));
michael@0 202 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
michael@0 203
michael@0 204 nsIFocusManager* fm = nsFocusManager::GetFocusManager();
michael@0 205 NS_ENSURE_TRUE(fm, NS_ERROR_FAILURE);
michael@0 206
michael@0 207 // get the containing frame for the window, and set it as focused. This will
michael@0 208 // end up focusing whatever is currently focused inside the frame. Since
michael@0 209 // setting the command dispatcher's focused window doesn't raise the window,
michael@0 210 // setting it to a top-level window doesn't need to do anything.
michael@0 211 nsCOMPtr<nsIDOMElement> frameElement =
michael@0 212 do_QueryInterface(window->GetFrameElementInternal());
michael@0 213 if (frameElement)
michael@0 214 return fm->SetFocus(frameElement, 0);
michael@0 215
michael@0 216 return NS_OK;
michael@0 217 }
michael@0 218
michael@0 219 NS_IMETHODIMP
michael@0 220 nsXULCommandDispatcher::AdvanceFocus()
michael@0 221 {
michael@0 222 return AdvanceFocusIntoSubtree(nullptr);
michael@0 223 }
michael@0 224
michael@0 225 NS_IMETHODIMP
michael@0 226 nsXULCommandDispatcher::RewindFocus()
michael@0 227 {
michael@0 228 nsCOMPtr<nsPIDOMWindow> win;
michael@0 229 GetRootFocusedContentAndWindow(getter_AddRefs(win));
michael@0 230
michael@0 231 nsCOMPtr<nsIDOMElement> result;
michael@0 232 nsIFocusManager* fm = nsFocusManager::GetFocusManager();
michael@0 233 if (fm)
michael@0 234 return fm->MoveFocus(win, nullptr, nsIFocusManager::MOVEFOCUS_BACKWARD,
michael@0 235 0, getter_AddRefs(result));
michael@0 236 return NS_OK;
michael@0 237 }
michael@0 238
michael@0 239 NS_IMETHODIMP
michael@0 240 nsXULCommandDispatcher::AdvanceFocusIntoSubtree(nsIDOMElement* aElt)
michael@0 241 {
michael@0 242 nsCOMPtr<nsPIDOMWindow> win;
michael@0 243 GetRootFocusedContentAndWindow(getter_AddRefs(win));
michael@0 244
michael@0 245 nsCOMPtr<nsIDOMElement> result;
michael@0 246 nsIFocusManager* fm = nsFocusManager::GetFocusManager();
michael@0 247 if (fm)
michael@0 248 return fm->MoveFocus(win, aElt, nsIFocusManager::MOVEFOCUS_FORWARD,
michael@0 249 0, getter_AddRefs(result));
michael@0 250 return NS_OK;
michael@0 251 }
michael@0 252
michael@0 253 NS_IMETHODIMP
michael@0 254 nsXULCommandDispatcher::AddCommandUpdater(nsIDOMElement* aElement,
michael@0 255 const nsAString& aEvents,
michael@0 256 const nsAString& aTargets)
michael@0 257 {
michael@0 258 NS_PRECONDITION(aElement != nullptr, "null ptr");
michael@0 259 if (! aElement)
michael@0 260 return NS_ERROR_NULL_POINTER;
michael@0 261
michael@0 262 NS_ENSURE_TRUE(mDocument, NS_ERROR_UNEXPECTED);
michael@0 263
michael@0 264 nsresult rv = nsContentUtils::CheckSameOrigin(mDocument, aElement);
michael@0 265
michael@0 266 if (NS_FAILED(rv)) {
michael@0 267 return rv;
michael@0 268 }
michael@0 269
michael@0 270 Updater* updater = mUpdaters;
michael@0 271 Updater** link = &mUpdaters;
michael@0 272
michael@0 273 while (updater) {
michael@0 274 if (updater->mElement == aElement) {
michael@0 275
michael@0 276 #ifdef DEBUG
michael@0 277 if (PR_LOG_TEST(gCommandLog, PR_LOG_NOTICE)) {
michael@0 278 nsAutoCString eventsC, targetsC, aeventsC, atargetsC;
michael@0 279 eventsC.AssignWithConversion(updater->mEvents);
michael@0 280 targetsC.AssignWithConversion(updater->mTargets);
michael@0 281 CopyUTF16toUTF8(aEvents, aeventsC);
michael@0 282 CopyUTF16toUTF8(aTargets, atargetsC);
michael@0 283 PR_LOG(gCommandLog, PR_LOG_NOTICE,
michael@0 284 ("xulcmd[%p] replace %p(events=%s targets=%s) with (events=%s targets=%s)",
michael@0 285 this, aElement,
michael@0 286 eventsC.get(),
michael@0 287 targetsC.get(),
michael@0 288 aeventsC.get(),
michael@0 289 atargetsC.get()));
michael@0 290 }
michael@0 291 #endif
michael@0 292
michael@0 293 // If the updater was already in the list, then replace
michael@0 294 // (?) the 'events' and 'targets' filters with the new
michael@0 295 // specification.
michael@0 296 updater->mEvents = aEvents;
michael@0 297 updater->mTargets = aTargets;
michael@0 298 return NS_OK;
michael@0 299 }
michael@0 300
michael@0 301 link = &(updater->mNext);
michael@0 302 updater = updater->mNext;
michael@0 303 }
michael@0 304 #ifdef DEBUG
michael@0 305 if (PR_LOG_TEST(gCommandLog, PR_LOG_NOTICE)) {
michael@0 306 nsAutoCString aeventsC, atargetsC;
michael@0 307 CopyUTF16toUTF8(aEvents, aeventsC);
michael@0 308 CopyUTF16toUTF8(aTargets, atargetsC);
michael@0 309
michael@0 310 PR_LOG(gCommandLog, PR_LOG_NOTICE,
michael@0 311 ("xulcmd[%p] add %p(events=%s targets=%s)",
michael@0 312 this, aElement,
michael@0 313 aeventsC.get(),
michael@0 314 atargetsC.get()));
michael@0 315 }
michael@0 316 #endif
michael@0 317
michael@0 318 // If we get here, this is a new updater. Append it to the list.
michael@0 319 updater = new Updater(aElement, aEvents, aTargets);
michael@0 320 if (! updater)
michael@0 321 return NS_ERROR_OUT_OF_MEMORY;
michael@0 322
michael@0 323 *link = updater;
michael@0 324 return NS_OK;
michael@0 325 }
michael@0 326
michael@0 327 NS_IMETHODIMP
michael@0 328 nsXULCommandDispatcher::RemoveCommandUpdater(nsIDOMElement* aElement)
michael@0 329 {
michael@0 330 NS_PRECONDITION(aElement != nullptr, "null ptr");
michael@0 331 if (! aElement)
michael@0 332 return NS_ERROR_NULL_POINTER;
michael@0 333
michael@0 334 Updater* updater = mUpdaters;
michael@0 335 Updater** link = &mUpdaters;
michael@0 336
michael@0 337 while (updater) {
michael@0 338 if (updater->mElement == aElement) {
michael@0 339 #ifdef DEBUG
michael@0 340 if (PR_LOG_TEST(gCommandLog, PR_LOG_NOTICE)) {
michael@0 341 nsAutoCString eventsC, targetsC;
michael@0 342 eventsC.AssignWithConversion(updater->mEvents);
michael@0 343 targetsC.AssignWithConversion(updater->mTargets);
michael@0 344 PR_LOG(gCommandLog, PR_LOG_NOTICE,
michael@0 345 ("xulcmd[%p] remove %p(events=%s targets=%s)",
michael@0 346 this, aElement,
michael@0 347 eventsC.get(),
michael@0 348 targetsC.get()));
michael@0 349 }
michael@0 350 #endif
michael@0 351
michael@0 352 *link = updater->mNext;
michael@0 353 delete updater;
michael@0 354 return NS_OK;
michael@0 355 }
michael@0 356
michael@0 357 link = &(updater->mNext);
michael@0 358 updater = updater->mNext;
michael@0 359 }
michael@0 360
michael@0 361 // Hmm. Not found. Oh well.
michael@0 362 return NS_OK;
michael@0 363 }
michael@0 364
michael@0 365 NS_IMETHODIMP
michael@0 366 nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName)
michael@0 367 {
michael@0 368 nsAutoString id;
michael@0 369 nsCOMPtr<nsIDOMElement> element;
michael@0 370 GetFocusedElement(getter_AddRefs(element));
michael@0 371 if (element) {
michael@0 372 nsresult rv = element->GetAttribute(NS_LITERAL_STRING("id"), id);
michael@0 373 NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get element's id");
michael@0 374 if (NS_FAILED(rv)) return rv;
michael@0 375 }
michael@0 376
michael@0 377 nsCOMArray<nsIContent> updaters;
michael@0 378
michael@0 379 for (Updater* updater = mUpdaters; updater != nullptr; updater = updater->mNext) {
michael@0 380 // Skip any nodes that don't match our 'events' or 'targets'
michael@0 381 // filters.
michael@0 382 if (! Matches(updater->mEvents, aEventName))
michael@0 383 continue;
michael@0 384
michael@0 385 if (! Matches(updater->mTargets, id))
michael@0 386 continue;
michael@0 387
michael@0 388 nsCOMPtr<nsIContent> content = do_QueryInterface(updater->mElement);
michael@0 389 NS_ASSERTION(content != nullptr, "not an nsIContent");
michael@0 390 if (! content)
michael@0 391 return NS_ERROR_UNEXPECTED;
michael@0 392
michael@0 393 updaters.AppendObject(content);
michael@0 394 }
michael@0 395
michael@0 396 for (int32_t u = 0; u < updaters.Count(); u++) {
michael@0 397 nsIContent* content = updaters[u];
michael@0 398
michael@0 399 nsCOMPtr<nsIDocument> document = content->GetDocument();
michael@0 400
michael@0 401 NS_ASSERTION(document != nullptr, "element has no document");
michael@0 402 if (! document)
michael@0 403 continue;
michael@0 404
michael@0 405 #ifdef DEBUG
michael@0 406 if (PR_LOG_TEST(gCommandLog, PR_LOG_NOTICE)) {
michael@0 407 nsAutoCString aeventnameC;
michael@0 408 CopyUTF16toUTF8(aEventName, aeventnameC);
michael@0 409 PR_LOG(gCommandLog, PR_LOG_NOTICE,
michael@0 410 ("xulcmd[%p] update %p event=%s",
michael@0 411 this, content,
michael@0 412 aeventnameC.get()));
michael@0 413 }
michael@0 414 #endif
michael@0 415
michael@0 416 nsCOMPtr<nsIPresShell> shell = document->GetShell();
michael@0 417 if (shell) {
michael@0 418 // Retrieve the context in which our DOM event will fire.
michael@0 419 nsRefPtr<nsPresContext> context = shell->GetPresContext();
michael@0 420
michael@0 421 // Handle the DOM event
michael@0 422 nsEventStatus status = nsEventStatus_eIgnore;
michael@0 423
michael@0 424 WidgetEvent event(true, NS_XUL_COMMAND_UPDATE);
michael@0 425
michael@0 426 EventDispatcher::Dispatch(content, context, &event, nullptr, &status);
michael@0 427 }
michael@0 428 }
michael@0 429 return NS_OK;
michael@0 430 }
michael@0 431
michael@0 432 bool
michael@0 433 nsXULCommandDispatcher::Matches(const nsString& aList,
michael@0 434 const nsAString& aElement)
michael@0 435 {
michael@0 436 if (aList.EqualsLiteral("*"))
michael@0 437 return true; // match _everything_!
michael@0 438
michael@0 439 int32_t indx = aList.Find(PromiseFlatString(aElement));
michael@0 440 if (indx == -1)
michael@0 441 return false; // not in the list at all
michael@0 442
michael@0 443 // okay, now make sure it's not a substring snafu; e.g., 'ur'
michael@0 444 // found inside of 'blur'.
michael@0 445 if (indx > 0) {
michael@0 446 char16_t ch = aList[indx - 1];
michael@0 447 if (! nsCRT::IsAsciiSpace(ch) && ch != char16_t(','))
michael@0 448 return false;
michael@0 449 }
michael@0 450
michael@0 451 if (indx + aElement.Length() < aList.Length()) {
michael@0 452 char16_t ch = aList[indx + aElement.Length()];
michael@0 453 if (! nsCRT::IsAsciiSpace(ch) && ch != char16_t(','))
michael@0 454 return false;
michael@0 455 }
michael@0 456
michael@0 457 return true;
michael@0 458 }
michael@0 459
michael@0 460 NS_IMETHODIMP
michael@0 461 nsXULCommandDispatcher::GetControllers(nsIControllers** aResult)
michael@0 462 {
michael@0 463 nsCOMPtr<nsPIWindowRoot> root = GetWindowRoot();
michael@0 464 NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
michael@0 465
michael@0 466 return root->GetControllers(aResult);
michael@0 467 }
michael@0 468
michael@0 469 NS_IMETHODIMP
michael@0 470 nsXULCommandDispatcher::GetControllerForCommand(const char *aCommand, nsIController** _retval)
michael@0 471 {
michael@0 472 nsCOMPtr<nsPIWindowRoot> root = GetWindowRoot();
michael@0 473 NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
michael@0 474
michael@0 475 return root->GetControllerForCommand(aCommand, _retval);
michael@0 476 }
michael@0 477
michael@0 478 NS_IMETHODIMP
michael@0 479 nsXULCommandDispatcher::GetSuppressFocusScroll(bool* aSuppressFocusScroll)
michael@0 480 {
michael@0 481 *aSuppressFocusScroll = false;
michael@0 482 return NS_OK;
michael@0 483 }
michael@0 484
michael@0 485 NS_IMETHODIMP
michael@0 486 nsXULCommandDispatcher::SetSuppressFocusScroll(bool aSuppressFocusScroll)
michael@0 487 {
michael@0 488 return NS_OK;
michael@0 489 }
michael@0 490

mercurial