mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
fe3519e975
- Bug 1257611 - Fix wrong CondVar::Wait() and Monitor::Wait() usage in netwerk/cache2, r=honzab (54f1a79f43) - Bug 1239687 - Leak invalid/doomed file handles immediately after HTTP cache shutdown. r=michal (a20bcf662b) - Bug 996836 - Merge CLOSE and WRITE priority in cache2 I/O thread. r=michal (8b0af50593) - Bug 1265243 - Do not initialize CacheObserver in the child process, r=honzab (87f69529d2) - Bug 1247432 - Don't do any unnecessary I/O in cache2 after shutdown. r=michal (7c5a2b89ac) - Bug 1220272 - Fix signalling in HTTP cache test code suspender. r=michal (293a16731d) - Bug 1160368 - Part 2: Clean up some cruft in nsCookie.h from PRBool/bool conversions. r=jdm (aa873f2dcc) - Bug 1160368 - Part 5: Clean up some confusing browser_storage_listings.js checks. r=jdm (b27f5930a9) - Bug 866380 - Null check for amlogic libc implementation. r=valentin (c3a487af9c) - Bug 1257320 - Disable C4577 to unblock compilation on VS2015; r=mayhemer (2f800ca85c) - Bug 1229726 - fix the data copy from sockaddr to NetAddr on OSX/FreeBSD. r=mcmanus. (fde11e004e) - Bug 1241368 - provide JS implemented MDNS service as a fallback. r=nwgh,nalexander. (afe1445eb8) - Bug 571126: Remove NECKO_SEPARATE_STACKS support, r=jduell (fb5b87bb3a) - Bug 1057689 - Add xpcshell test checking correct notifications and app-offline state r=jduell (89946b44ba) - Bug 1259459 - h2 0 length options puts end-stream on headers r=hurley (618480a609) - Bug 1234251 - Remove HttpChannelChild::mSynthesizedResponseHead; r=jdm (20981affea) - Bug 904559 - Veto redirect when target channel doesn't implement nsIParentRedirectingChannel. r=jduell (b3da2fae91) - Bug 1261784 Make sure InterceptedChannel body streams are always closed. r=jdm (cd50b1a52b) - Bug 1224508 - Use URI path without reference as the callback key. r=valentin. (b8a953f23a) - Bug 1226760 - ViewSource doesn't work for packaged app resources r=mcmanus (ec9b0297de) - Bug 1254061 - Rewrite nsHttp::ParseInt64 using strtoll r=mcmanus (2125b8ae6f) - Bug 1241565 - nsIHttpChannelInternal should be a builtinclass, r=honzab.moz (d24da6a95a) - Bug 1252386 - Removed debugging printf,r=me (c5d89f353c) - bug 277813 - autogenerated expires needs max r=mayhemer (6aa7c255a5) - Bug 1225384 - Change how the default resource "host names" are handled. r=michal (868732baab) - Bug 719905: Fix resolution of resource: URLs containing : and / characters. r=valentin (f60f4baacf) - Bug 1195173 - Convert ExtensionProtocolHandler to use channel->Open2() (r=maglione) (063f5d5d10) - Bug 1226909 followup to fix bustage. Make sure that the channel returned by NS_NewChannel doesn't have a loadinfo that indicates that the channel has already been opened (42ebe0f44e) - Bug 241698 - Fixed init and use of nsDirIndex::mLastModified (-1LL) + built in nullptr checks where they were missing. r=dragana (e9c2277a3d) - Bug 1261318 - make sure brotli context is created in onstoprequest r=bagder (6646fed64d) - Bug 1212223 - Update |bufLen| as well when we probed the multipart preamble. r=valentin. (ec878c5b0f) - Bug 1259561: Increase CRAZY_COORD (threshold for debug build layout warnings) by an order of magnitude. r=mats (c05c16dd85) - Bug 1261698. Make ReparentFrameViewTo return void because it always returns NS_OK. r=mats (e806d6abcb) - Bug 1261698. Remove comment that is not relevant in nsContainerFrame.cpp. (f570189d15) - Bug 1261698. Don't descend into child frames looking for views in ReparentFrameViewTo if the frame doesn't have the NS_FRAME_HAS_CHILD_WITH_VIEW bit set. r=mats (0d42befd46) - Bug 1265154 - Fix compile error in MSVC 2013 caused by ArrayLength; r=heycam (1c962f2840) - Bug 1260351 - Image: Enable ConvolveVertically/Horizontally in LS3 MMI. r=tnikkel (576b6bbdb3) - Bug 1209780 (Part 1) - Mark DrawResult MOZ_MUST_USE. r=tn (e6c113bef2) - Bug 1253753 - Remove unnecessary switch fallthrough to avoid -Wimplicit-fallthrough warning. r=karlt (96bd93fc5c) - bug 1260178 null check pattern from -unico-border-gradient r=acomminos (f63c9c7ffb) - Bug 1247796. Use keyboardFocusIndicatorColor for ActiveBorder system color keyword. r=mstange (7ed133de97) - Bug 1248675 - Update the cached mBounds in nsChildView when its backing scale factor (display DPI) changes. r=mstange (8197274118) - Bug 1256576 - Make sure texture is (re)initialized if the size changed. r=snorp (2c56790ca9) - Bug 1242449 - Fix confusion among CSS, desktop and device pixel units in nsXULWindow position/size and window staggering so as to work consistently across mixed resolution displays. r=emk (f73d2fd41d) - Bug 1255645 - Ensure nsXULWindow constrains the window to the bounds of its screen after applying intrinsic sizing (if appropriate), by re-doing positioning after the window has been sized properly. r=emk (e87e0cea81) - Bug 1259492 - Ensure window position is constrained to the screen after it has been sized properly in nsXULWindow::OnChromeLoaded. r=emk (7cf599b39b) - Bug 1832708 - Disable std::__throw_* wrapping on libc++ >= 14.0. r=firefox-build-system-reviewers,andi (29e0cc9319)
567 lines
17 KiB
C++
567 lines
17 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* 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/. */
|
|
|
|
#include "HardwareKeyHandler.h"
|
|
#include "mozilla/BasicEvents.h"
|
|
#include "mozilla/ClearOnShutdown.h"
|
|
#include "mozilla/dom/KeyboardEvent.h"
|
|
#include "mozilla/dom/TabParent.h"
|
|
#include "mozilla/EventDispatcher.h"
|
|
#include "mozilla/EventStateManager.h"
|
|
#include "mozilla/TextEvents.h"
|
|
#include "nsDeque.h"
|
|
#include "nsFocusManager.h"
|
|
#include "nsFrameLoader.h"
|
|
#include "nsIContent.h"
|
|
#include "nsIDOMHTMLDocument.h"
|
|
#include "nsIDOMHTMLElement.h"
|
|
#include "nsPIDOMWindow.h"
|
|
#include "nsPresContext.h"
|
|
#include "nsPresShell.h"
|
|
|
|
namespace mozilla {
|
|
|
|
using namespace dom;
|
|
|
|
NS_IMPL_ISUPPORTS(HardwareKeyHandler, nsIHardwareKeyHandler)
|
|
|
|
StaticRefPtr<HardwareKeyHandler> HardwareKeyHandler::sInstance;
|
|
|
|
HardwareKeyHandler::HardwareKeyHandler()
|
|
: mInputMethodAppConnected(false)
|
|
{
|
|
}
|
|
|
|
HardwareKeyHandler::~HardwareKeyHandler()
|
|
{
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
HardwareKeyHandler::OnInputMethodAppConnected()
|
|
{
|
|
if (NS_WARN_IF(mInputMethodAppConnected)) {
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
|
|
mInputMethodAppConnected = true;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
HardwareKeyHandler::OnInputMethodAppDisconnected()
|
|
{
|
|
if (NS_WARN_IF(!mInputMethodAppConnected)) {
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
|
|
mInputMethodAppConnected = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
HardwareKeyHandler::RegisterListener(nsIHardwareKeyEventListener* aListener)
|
|
{
|
|
// Make sure the listener is not nullptr and there is no available
|
|
// hardwareKeyEventListener now
|
|
if (NS_WARN_IF(!aListener)) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
|
|
if (NS_WARN_IF(mHardwareKeyEventListener)) {
|
|
return NS_ERROR_ALREADY_INITIALIZED;
|
|
}
|
|
|
|
mHardwareKeyEventListener = do_GetWeakReference(aListener);
|
|
|
|
if (NS_WARN_IF(!mHardwareKeyEventListener)) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
HardwareKeyHandler::UnregisterListener()
|
|
{
|
|
// Clear the HardwareKeyEventListener
|
|
mHardwareKeyEventListener = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
bool
|
|
HardwareKeyHandler::ForwardKeyToInputMethodApp(nsINode* aTarget,
|
|
WidgetKeyboardEvent* aEvent,
|
|
nsEventStatus* aEventStatus)
|
|
{
|
|
MOZ_ASSERT(aTarget, "No target provided");
|
|
MOZ_ASSERT(aEvent, "No event provided");
|
|
|
|
// No need to forward hardware key event to IME
|
|
// if key's defaultPrevented is true
|
|
if (aEvent->mFlags.mDefaultPrevented) {
|
|
return false;
|
|
}
|
|
|
|
// No need to forward hardware key event to IME if IME is disabled
|
|
if (!mInputMethodAppConnected) {
|
|
return false;
|
|
}
|
|
|
|
// No need to forward hardware key event to IME
|
|
// if this key event is generated by IME itself(from nsITextInputProcessor)
|
|
if (aEvent->mIsSynthesizedByTIP) {
|
|
return false;
|
|
}
|
|
|
|
// No need to forward hardware key event to IME
|
|
// if the key event is handling or already handled
|
|
if (aEvent->mInputMethodAppState != WidgetKeyboardEvent::eNotHandled) {
|
|
return false;
|
|
}
|
|
|
|
// No need to forward hardware key event to IME
|
|
// if there is no nsIHardwareKeyEventListener in use
|
|
nsCOMPtr<nsIHardwareKeyEventListener>
|
|
keyHandler(do_QueryReferent(mHardwareKeyEventListener));
|
|
if (!keyHandler) {
|
|
return false;
|
|
}
|
|
|
|
// Set the flags to specify the keyboard event is in forwarding phase.
|
|
aEvent->mInputMethodAppState = WidgetKeyboardEvent::eHandling;
|
|
|
|
// For those keypress events coming after their heading keydown's reply
|
|
// already arrives, they should be dispatched directly instead of
|
|
// being stored into the event queue. Otherwise, without the heading keydown
|
|
// in the event queue, the stored keypress will never be withdrawn to be fired.
|
|
if (aEvent->mMessage == eKeyPress && mEventQueue.IsEmpty()) {
|
|
DispatchKeyPress(aTarget, *aEvent, *aEventStatus);
|
|
return true;
|
|
}
|
|
|
|
// Push the key event into queue for reuse when its reply arrives.
|
|
KeyboardInfo* copiedInfo =
|
|
new KeyboardInfo(aTarget,
|
|
*aEvent,
|
|
aEventStatus ? *aEventStatus : nsEventStatus_eIgnore);
|
|
|
|
// No need to forward hardware key event to IME if the event queue is full
|
|
if (!mEventQueue.Push(copiedInfo)) {
|
|
delete copiedInfo;
|
|
return false;
|
|
}
|
|
|
|
// We only forward keydown and keyup event to input-method-app
|
|
// because input-method-app will generate keypress by itself.
|
|
if (aEvent->mMessage == eKeyPress) {
|
|
return true;
|
|
}
|
|
|
|
// Create a keyboard event to pass into
|
|
// nsIHardwareKeyEventListener.onHardwareKey
|
|
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
|
|
nsPresContext* presContext = GetPresContext(aTarget);
|
|
RefPtr<KeyboardEvent> keyboardEvent =
|
|
NS_NewDOMKeyboardEvent(eventTarget, presContext, aEvent->AsKeyboardEvent());
|
|
// Duplicate the internal event data in the heap for the keyboardEvent,
|
|
// or the internal data from |aEvent| in the stack may be destroyed by others.
|
|
keyboardEvent->DuplicatePrivateData();
|
|
|
|
// Forward the created keyboard event to input-method-app
|
|
bool isSent = false;
|
|
keyHandler->OnHardwareKey(keyboardEvent, &isSent);
|
|
|
|
// Pop the pending key event if it can't be forwarded
|
|
if (!isSent) {
|
|
mEventQueue.RemoveFront();
|
|
}
|
|
|
|
return isSent;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
HardwareKeyHandler::OnHandledByInputMethodApp(const nsAString& aType,
|
|
uint16_t aDefaultPrevented)
|
|
{
|
|
// We can not handle this reply because the pending events had been already
|
|
// removed from the forwarding queue before this reply arrives.
|
|
if (mEventQueue.IsEmpty()) {
|
|
return NS_OK;
|
|
}
|
|
|
|
RefPtr<KeyboardInfo> keyInfo = mEventQueue.PopFront();
|
|
|
|
// Only allow keydown and keyup to call this method
|
|
if (NS_WARN_IF(aType.EqualsLiteral("keydown") &&
|
|
keyInfo->mEvent.mMessage != eKeyDown) ||
|
|
NS_WARN_IF(aType.EqualsLiteral("keyup") &&
|
|
keyInfo->mEvent.mMessage != eKeyUp)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
// The value of defaultPrevented depends on whether or not
|
|
// the key is consumed by input-method-app
|
|
SetDefaultPrevented(keyInfo->mEvent, aDefaultPrevented);
|
|
|
|
// Set the flag to specify the reply phase
|
|
keyInfo->mEvent.mInputMethodAppState = WidgetKeyboardEvent::eHandled;
|
|
|
|
// Check whether the event is still valid to be fired
|
|
if (CanDispatchEvent(keyInfo->mTarget, keyInfo->mEvent)) {
|
|
// If the key's defaultPrevented is true, it means that the
|
|
// input-method-app has already consumed this key,
|
|
// so we can dispatch |mozbrowserafterkey*| directly if
|
|
// preference "dom.beforeAfterKeyboardEvent.enabled" is enabled.
|
|
if (keyInfo->mEvent.mFlags.mDefaultPrevented) {
|
|
DispatchAfterKeyEvent(keyInfo->mTarget, keyInfo->mEvent);
|
|
// Otherwise, it means that input-method-app doesn't handle this key,
|
|
// so we need to dispatch it to its current event target.
|
|
} else {
|
|
DispatchToTargetApp(keyInfo->mTarget,
|
|
keyInfo->mEvent,
|
|
keyInfo->mStatus);
|
|
}
|
|
}
|
|
|
|
// No need to do further processing if the event is not keydown
|
|
if (keyInfo->mEvent.mMessage != eKeyDown) {
|
|
return NS_OK;
|
|
}
|
|
|
|
// Update the latest keydown data:
|
|
// Release the holding reference to the previous keydown's data and
|
|
// add a reference count to the current keydown's data.
|
|
mLatestKeyDownInfo = keyInfo;
|
|
|
|
// Handle the pending keypress event once keydown's reply arrives:
|
|
// It may have many keypress events per keydown on some platforms,
|
|
// so we use loop to dispatch keypress events.
|
|
// (But Gonk dispatch only one keypress per keydown)
|
|
// However, if there is no keypress after this keydown,
|
|
// then those following keypress will be handled in
|
|
// ForwardKeyToInputMethodApp directly.
|
|
for (KeyboardInfo* keypressInfo;
|
|
!mEventQueue.IsEmpty() &&
|
|
(keypressInfo = mEventQueue.PeekFront()) &&
|
|
keypressInfo->mEvent.mMessage == eKeyPress;
|
|
mEventQueue.RemoveFront()) {
|
|
DispatchKeyPress(keypressInfo->mTarget,
|
|
keypressInfo->mEvent,
|
|
keypressInfo->mStatus);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
bool
|
|
HardwareKeyHandler::DispatchKeyPress(nsINode* aTarget,
|
|
WidgetKeyboardEvent& aEvent,
|
|
nsEventStatus& aStatus)
|
|
{
|
|
MOZ_ASSERT(aTarget, "No target provided");
|
|
MOZ_ASSERT(aEvent, "No event provided");
|
|
MOZ_ASSERT(aEvent.mMessage == eKeyPress, "Event is not keypress");
|
|
|
|
// No need to dispatch keypress to the event target
|
|
// if the keydown event is consumed by the input-method-app.
|
|
if (mLatestKeyDownInfo &&
|
|
mLatestKeyDownInfo->mEvent.mFlags.mDefaultPrevented) {
|
|
return false;
|
|
}
|
|
|
|
// No need to dispatch keypress to the event target
|
|
// if the previous keydown event is modifier key's
|
|
if (mLatestKeyDownInfo &&
|
|
mLatestKeyDownInfo->mEvent.IsModifierKeyEvent()) {
|
|
return false;
|
|
}
|
|
|
|
// No need to dispatch keypress to the event target
|
|
// if it's invalid to be dispatched
|
|
if (!CanDispatchEvent(aTarget, aEvent)) {
|
|
return false;
|
|
}
|
|
|
|
// Set the flag to specify the reply phase.
|
|
aEvent.mInputMethodAppState = WidgetKeyboardEvent::eHandled;
|
|
|
|
// Dispatch the pending keypress event
|
|
bool ret = DispatchToTargetApp(aTarget, aEvent, aStatus);
|
|
|
|
// Re-trigger EventStateManager::PostHandleKeyboardEvent for keypress
|
|
PostHandleKeyboardEvent(aTarget, aEvent, aStatus);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
HardwareKeyHandler::DispatchAfterKeyEvent(nsINode* aTarget,
|
|
WidgetKeyboardEvent& aEvent)
|
|
{
|
|
MOZ_ASSERT(aTarget, "No target provided");
|
|
MOZ_ASSERT(aEvent, "No event provided");
|
|
|
|
if (!PresShell::BeforeAfterKeyboardEventEnabled() ||
|
|
aEvent.mMessage == eKeyPress) {
|
|
return;
|
|
}
|
|
|
|
nsCOMPtr<nsIPresShell> presShell = GetPresShell(aTarget);
|
|
if (NS_WARN_IF(presShell)) {
|
|
presShell->DispatchAfterKeyboardEvent(aTarget,
|
|
aEvent,
|
|
aEvent.mFlags.mDefaultPrevented);
|
|
}
|
|
}
|
|
|
|
bool
|
|
HardwareKeyHandler::DispatchToTargetApp(nsINode* aTarget,
|
|
WidgetKeyboardEvent& aEvent,
|
|
nsEventStatus& aStatus)
|
|
{
|
|
MOZ_ASSERT(aTarget, "No target provided");
|
|
MOZ_ASSERT(aEvent, "No event provided");
|
|
|
|
// Get current focused element as the event target
|
|
nsCOMPtr<nsIContent> currentTarget = GetCurrentTarget();
|
|
if (NS_WARN_IF(!currentTarget)) {
|
|
return false;
|
|
}
|
|
|
|
// The event target should be set to the current focused element.
|
|
// However, it might have security issue if the event is dispatched to
|
|
// the unexpected application, and it might cause unexpected operation
|
|
// in the new app.
|
|
nsCOMPtr<nsPIDOMWindowOuter> originalRootWindow = GetRootWindow(aTarget);
|
|
nsCOMPtr<nsPIDOMWindowOuter> currentRootWindow = GetRootWindow(currentTarget);
|
|
if (currentRootWindow != originalRootWindow) {
|
|
NS_WARNING("The root window is changed during the event is dispatching");
|
|
return false;
|
|
}
|
|
|
|
// If the current focused element is still in the same app,
|
|
// then we can use it as the current target to dispatch event.
|
|
nsCOMPtr<nsIPresShell> presShell = GetPresShell(currentTarget);
|
|
if (!presShell) {
|
|
return false;
|
|
}
|
|
|
|
if (!presShell->CanDispatchEvent(&aEvent)) {
|
|
return false;
|
|
}
|
|
|
|
// In-process case: the event target is in the current process
|
|
if (!PresShell::IsTargetIframe(currentTarget)) {
|
|
DispatchToCurrentProcess(presShell, currentTarget, aEvent, aStatus);
|
|
|
|
if (presShell->CanDispatchEvent(&aEvent)) {
|
|
DispatchAfterKeyEvent(aTarget, aEvent);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// OOP case: the event target is in the child process
|
|
return DispatchToCrossProcess(aTarget, aEvent);
|
|
|
|
// After the oop target receives the event from TabChild::RecvRealKeyEvent
|
|
// and return the result through TabChild::SendDispatchAfterKeyboardEvent,
|
|
// the |mozbrowserafterkey*| will be fired from
|
|
// TabParent::RecvDispatchAfterKeyboardEvent, so we don't need to dispatch
|
|
// |mozbrowserafterkey*| by ourselves in this module.
|
|
}
|
|
|
|
void
|
|
HardwareKeyHandler::DispatchToCurrentProcess(nsIPresShell* presShell,
|
|
nsIContent* aTarget,
|
|
WidgetKeyboardEvent& aEvent,
|
|
nsEventStatus& aStatus)
|
|
{
|
|
EventDispatcher::Dispatch(aTarget, presShell->GetPresContext(),
|
|
&aEvent, nullptr, &aStatus, nullptr);
|
|
}
|
|
|
|
bool
|
|
HardwareKeyHandler::DispatchToCrossProcess(nsINode* aTarget,
|
|
WidgetKeyboardEvent& aEvent)
|
|
{
|
|
nsCOMPtr<nsIFrameLoaderOwner> remoteLoaderOwner = do_QueryInterface(aTarget);
|
|
if (NS_WARN_IF(!remoteLoaderOwner)) {
|
|
return false;
|
|
}
|
|
|
|
RefPtr<nsFrameLoader> remoteFrameLoader =
|
|
remoteLoaderOwner->GetFrameLoader();
|
|
if (NS_WARN_IF(!remoteFrameLoader)) {
|
|
return false;
|
|
}
|
|
|
|
uint32_t eventMode;
|
|
remoteFrameLoader->GetEventMode(&eventMode);
|
|
if (eventMode == nsIFrameLoader::EVENT_MODE_DONT_FORWARD_TO_CHILD) {
|
|
return false;
|
|
}
|
|
|
|
PBrowserParent* remoteBrowser = remoteFrameLoader->GetRemoteBrowser();
|
|
TabParent* remote = static_cast<TabParent*>(remoteBrowser);
|
|
if (NS_WARN_IF(!remote)) {
|
|
return false;
|
|
}
|
|
|
|
return remote->SendRealKeyEvent(aEvent);
|
|
}
|
|
|
|
void
|
|
HardwareKeyHandler::PostHandleKeyboardEvent(nsINode* aTarget,
|
|
WidgetKeyboardEvent& aEvent,
|
|
nsEventStatus& aStatus)
|
|
{
|
|
MOZ_ASSERT(aTarget, "No target provided");
|
|
MOZ_ASSERT(aEvent, "No event provided");
|
|
|
|
nsPresContext* presContext = GetPresContext(aTarget);
|
|
|
|
RefPtr<mozilla::EventStateManager> esm = presContext->EventStateManager();
|
|
bool dispatchedToChildProcess = PresShell::IsTargetIframe(aTarget);
|
|
esm->PostHandleKeyboardEvent(&aEvent, aStatus, dispatchedToChildProcess);
|
|
}
|
|
|
|
void
|
|
HardwareKeyHandler::SetDefaultPrevented(WidgetKeyboardEvent& aEvent,
|
|
uint16_t aDefaultPrevented) {
|
|
if (aDefaultPrevented & DEFAULT_PREVENTED) {
|
|
aEvent.mFlags.mDefaultPrevented = true;
|
|
}
|
|
|
|
if (aDefaultPrevented & DEFAULT_PREVENTED_BY_CHROME) {
|
|
aEvent.mFlags.mDefaultPreventedByChrome = true;
|
|
}
|
|
|
|
if (aDefaultPrevented & DEFAULT_PREVENTED_BY_CONTENT) {
|
|
aEvent.mFlags.mDefaultPreventedByContent = true;
|
|
}
|
|
}
|
|
|
|
bool
|
|
HardwareKeyHandler::CanDispatchEvent(nsINode* aTarget,
|
|
WidgetKeyboardEvent& aEvent)
|
|
{
|
|
nsCOMPtr<nsIPresShell> presShell = GetPresShell(aTarget);
|
|
if (NS_WARN_IF(!presShell)) {
|
|
return false;
|
|
}
|
|
return presShell->CanDispatchEvent(&aEvent);
|
|
}
|
|
|
|
already_AddRefed<nsPIDOMWindowOuter>
|
|
HardwareKeyHandler::GetRootWindow(nsINode* aNode)
|
|
{
|
|
// Get nsIPresShell's pointer first
|
|
nsCOMPtr<nsIPresShell> presShell = GetPresShell(aNode);
|
|
if (NS_WARN_IF(!presShell)) {
|
|
return nullptr;
|
|
}
|
|
nsCOMPtr<nsPIDOMWindowOuter> rootWindow = presShell->GetRootWindow();
|
|
return rootWindow.forget();
|
|
}
|
|
|
|
already_AddRefed<nsIContent>
|
|
HardwareKeyHandler::GetCurrentTarget()
|
|
{
|
|
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
|
if (NS_WARN_IF(!fm)) {
|
|
return nullptr;
|
|
}
|
|
|
|
nsCOMPtr<nsIDOMWindow> domWindow;
|
|
fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
|
|
if (NS_WARN_IF(!focusedWindow)) {
|
|
return nullptr;
|
|
}
|
|
|
|
auto* ourWindow = nsPIDOMWindowOuter::From(focusedWindow);
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> rootWindow = ourWindow->GetPrivateRoot();
|
|
if (NS_WARN_IF(!rootWindow)) {
|
|
return nullptr;
|
|
}
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> focusedFrame;
|
|
nsCOMPtr<nsIContent> focusedContent =
|
|
fm->GetFocusedDescendant(rootWindow, true, getter_AddRefs(focusedFrame));
|
|
|
|
// If there is no focus, then we use document body instead
|
|
if (NS_WARN_IF(!focusedContent || !focusedContent->GetPrimaryFrame())) {
|
|
nsIDocument* document = ourWindow->GetExtantDoc();
|
|
if (NS_WARN_IF(!document)) {
|
|
return nullptr;
|
|
}
|
|
|
|
focusedContent = document->GetRootElement();
|
|
|
|
nsCOMPtr<nsIDOMHTMLDocument> htmlDocument = do_QueryInterface(document);
|
|
if (htmlDocument) {
|
|
nsCOMPtr<nsIDOMHTMLElement> body;
|
|
htmlDocument->GetBody(getter_AddRefs(body));
|
|
nsCOMPtr<nsIContent> bodyContent = do_QueryInterface(body);
|
|
if (bodyContent) {
|
|
focusedContent = bodyContent;
|
|
}
|
|
}
|
|
}
|
|
|
|
return focusedContent ? focusedContent.forget() : nullptr;
|
|
}
|
|
|
|
nsPresContext*
|
|
HardwareKeyHandler::GetPresContext(nsINode* aNode)
|
|
{
|
|
// Get nsIPresShell's pointer first
|
|
nsCOMPtr<nsIPresShell> presShell = GetPresShell(aNode);
|
|
if (NS_WARN_IF(!presShell)) {
|
|
return nullptr;
|
|
}
|
|
|
|
// then use nsIPresShell to get nsPresContext's pointer
|
|
return presShell->GetPresContext();
|
|
}
|
|
|
|
already_AddRefed<nsIPresShell>
|
|
HardwareKeyHandler::GetPresShell(nsINode* aNode)
|
|
{
|
|
nsIDocument* doc = aNode->OwnerDoc();
|
|
if (NS_WARN_IF(!doc)) {
|
|
return nullptr;
|
|
}
|
|
|
|
nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
|
|
if (NS_WARN_IF(!presShell)) {
|
|
return nullptr;
|
|
}
|
|
|
|
return presShell.forget();
|
|
}
|
|
|
|
/* static */
|
|
already_AddRefed<HardwareKeyHandler>
|
|
HardwareKeyHandler::GetInstance()
|
|
{
|
|
if (!XRE_IsParentProcess()) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (!sInstance) {
|
|
sInstance = new HardwareKeyHandler();
|
|
ClearOnShutdown(&sInstance);
|
|
}
|
|
|
|
RefPtr<HardwareKeyHandler> service = sInstance.get();
|
|
return service.forget();
|
|
}
|
|
|
|
} // namespace mozilla
|