diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:13:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:13:27 +0000 |
commit | 40a355a42d4a9444dc753c04c6608dade2f06a23 (patch) | |
tree | 871fc667d2de662f171103ce5ec067014ef85e61 /widget/uikit | |
parent | Adding upstream version 124.0.1. (diff) | |
download | firefox-adbda400be353e676059e335c3c0aaf99e719475.tar.xz firefox-adbda400be353e676059e335c3c0aaf99e719475.zip |
Adding upstream version 125.0.1.upstream/125.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'widget/uikit')
-rw-r--r-- | widget/uikit/GfxInfo.cpp | 45 | ||||
-rw-r--r-- | widget/uikit/GfxInfo.h | 21 | ||||
-rw-r--r-- | widget/uikit/MediaKeysEventSourceFactory.cpp | 17 | ||||
-rw-r--r-- | widget/uikit/TextInputHandler.h | 67 | ||||
-rw-r--r-- | widget/uikit/TextInputHandler.mm | 254 | ||||
-rw-r--r-- | widget/uikit/UIKitUtils.h | 23 | ||||
-rw-r--r-- | widget/uikit/UIKitUtils.mm | 89 | ||||
-rw-r--r-- | widget/uikit/components.conf | 28 | ||||
-rw-r--r-- | widget/uikit/moz.build | 17 | ||||
-rw-r--r-- | widget/uikit/nsAppShell.h | 4 | ||||
-rw-r--r-- | widget/uikit/nsBidiKeyboard.h | 23 | ||||
-rw-r--r-- | widget/uikit/nsBidiKeyboard.mm | 35 | ||||
-rw-r--r-- | widget/uikit/nsLookAndFeel.h | 7 | ||||
-rw-r--r-- | widget/uikit/nsLookAndFeel.mm | 46 | ||||
-rw-r--r-- | widget/uikit/nsNativeThemeUIKit.h | 21 | ||||
-rw-r--r-- | widget/uikit/nsNativeThemeUIKit.mm | 19 | ||||
-rw-r--r-- | widget/uikit/nsScreenManager.h | 61 | ||||
-rw-r--r-- | widget/uikit/nsScreenManager.mm | 104 | ||||
-rw-r--r-- | widget/uikit/nsWidgetFactory.h | 21 | ||||
-rw-r--r-- | widget/uikit/nsWidgetFactory.mm | 45 | ||||
-rw-r--r-- | widget/uikit/nsWindow.h | 77 | ||||
-rw-r--r-- | widget/uikit/nsWindow.mm | 420 |
22 files changed, 1106 insertions, 338 deletions
diff --git a/widget/uikit/GfxInfo.cpp b/widget/uikit/GfxInfo.cpp index d797e4f4a0..cb378915aa 100644 --- a/widget/uikit/GfxInfo.cpp +++ b/widget/uikit/GfxInfo.cpp @@ -17,9 +17,19 @@ GfxInfo::GfxInfo() {} GfxInfo::~GfxInfo() {} -nsresult GfxInfo::GetD2DEnabled(bool* aEnabled) { return NS_ERROR_FAILURE; } +NS_IMETHODIMP +GfxInfo::GetD2DEnabled(bool* aEnabled) { return NS_ERROR_FAILURE; } + +NS_IMETHODIMP +GfxInfo::GetDWriteEnabled(bool* aEnabled) { return NS_ERROR_FAILURE; } -nsresult GfxInfo::GetDWriteEnabled(bool* aEnabled) { return NS_ERROR_FAILURE; } +NS_IMETHODIMP +GfxInfo::GetEmbeddedInFirefoxReality(bool* aEmbeddedInFirefoxReality) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +GfxInfo::GetHasBattery(bool* aHasBattery) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP GfxInfo::GetDWriteVersion(nsAString& aDwriteVersion) { @@ -32,6 +42,14 @@ GfxInfo::GetCleartypeParameters(nsAString& aCleartypeParams) { } NS_IMETHODIMP +GfxInfo::GetWindowProtocol(nsAString& aWindowProtocol) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +GfxInfo::GetTestType(nsAString& aTestType) { return NS_ERROR_NOT_IMPLEMENTED; } + +NS_IMETHODIMP GfxInfo::GetAdapterDescription(nsAString& aAdapterDescription) { return NS_ERROR_FAILURE; } @@ -48,6 +66,16 @@ NS_IMETHODIMP GfxInfo::GetAdapterRAM2(uint32_t* aAdapterRAM) { return NS_ERROR_FAILURE; } NS_IMETHODIMP +GfxInfo::GetAdapterDriverVendor(nsAString& aAdapterDriverVendor) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +GfxInfo::GetAdapterDriverVendor2(nsAString& aAdapterDriverVendor2) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP GfxInfo::GetAdapterDriver(nsAString& aAdapterDriver) { return NS_ERROR_FAILURE; } @@ -90,7 +118,6 @@ GfxInfo::GetAdapterVendorID2(nsAString& aAdapterVendorID) { NS_IMETHODIMP GfxInfo::GetAdapterDeviceID(nsAString& aAdapterDeviceID) { return NS_ERROR_FAILURE; - return NS_OK; } NS_IMETHODIMP @@ -111,12 +138,18 @@ GfxInfo::GetAdapterSubsysID2(nsAString& aAdapterSubsysID) { NS_IMETHODIMP GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active) { return NS_ERROR_FAILURE; } +NS_IMETHODIMP +GfxInfo::GetDrmRenderDevice(nsACString& aDrmRenderDevice) { + return NS_ERROR_NOT_IMPLEMENTED; +} + const nsTArray<GfxDriverInfo>& GfxInfo::GetGfxDriverInfo() { if (sDriverInfo->IsEmpty()) { APPEND_TO_DRIVER_BLOCKLIST2( OperatingSystem::Ios, DeviceFamily::All, nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_STATUS_OK, - DRIVER_COMPARISON_IGNORED, GfxDriverInfo::allDriverVersions); + DRIVER_COMPARISON_IGNORED, GfxDriverInfo::allDriverVersions, + "FEATURE_OK_FORCE_OPENGL"); } return *sDriverInfo; @@ -124,7 +157,7 @@ const nsTArray<GfxDriverInfo>& GfxInfo::GetGfxDriverInfo() { nsresult GfxInfo::GetFeatureStatusImpl( int32_t aFeature, int32_t* aStatus, nsAString& aSuggestedDriverVersion, - const nsTArray<GfxDriverInfo>& aDriverInfo, + const nsTArray<GfxDriverInfo>& aDriverInfo, nsACString& aFailureId, OperatingSystem* aOS /* = nullptr */) { NS_ENSURE_ARG_POINTER(aStatus); aSuggestedDriverVersion.SetIsVoid(true); @@ -145,7 +178,7 @@ nsresult GfxInfo::GetFeatureStatusImpl( } return GfxInfoBase::GetFeatureStatusImpl( - aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, aOS); + aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, aFailureId, aOS); } #ifdef DEBUG diff --git a/widget/uikit/GfxInfo.h b/widget/uikit/GfxInfo.h index fe75e28d23..55deb58544 100644 --- a/widget/uikit/GfxInfo.h +++ b/widget/uikit/GfxInfo.h @@ -29,18 +29,26 @@ class GfxInfo : public GfxInfoBase { public: GfxInfo(); + OperatingSystem GetOperatingSystem() override { return OperatingSystem::Ios; } + // We only declare the subset of nsIGfxInfo that we actually implement. The // rest is brought forward from GfxInfoBase. NS_IMETHOD GetD2DEnabled(bool* aD2DEnabled) override; NS_IMETHOD GetDWriteEnabled(bool* aDWriteEnabled) override; + NS_IMETHOD GetEmbeddedInFirefoxReality( + bool* aEmbeddedInFirefoxReality) override; + NS_IMETHOD GetHasBattery(bool* aHasBattery) override; NS_IMETHOD GetDWriteVersion(nsAString& aDwriteVersion) override; NS_IMETHOD GetCleartypeParameters(nsAString& aCleartypeParams) override; + NS_IMETHOD GetWindowProtocol(nsAString& aWindowProtocol) override; + NS_IMETHOD GetTestType(nsAString& aTestType) override; NS_IMETHOD GetAdapterDescription(nsAString& aAdapterDescription) override; NS_IMETHOD GetAdapterDriver(nsAString& aAdapterDriver) override; NS_IMETHOD GetAdapterVendorID(nsAString& aAdapterVendorID) override; NS_IMETHOD GetAdapterDeviceID(nsAString& aAdapterDeviceID) override; NS_IMETHOD GetAdapterSubsysID(nsAString& aAdapterSubsysID) override; NS_IMETHOD GetAdapterRAM(uint32_t* aAdapterRAM) override; + NS_IMETHOD GetAdapterDriverVendor(nsAString& aAdapterDriverVendor) override; NS_IMETHOD GetAdapterDriverVersion(nsAString& aAdapterDriverVersion) override; NS_IMETHOD GetAdapterDriverDate(nsAString& aAdapterDriverDate) override; NS_IMETHOD GetAdapterDescription2(nsAString& aAdapterDescription) override; @@ -49,10 +57,12 @@ class GfxInfo : public GfxInfoBase { NS_IMETHOD GetAdapterDeviceID2(nsAString& aAdapterDeviceID) override; NS_IMETHOD GetAdapterSubsysID2(nsAString& aAdapterSubsysID) override; NS_IMETHOD GetAdapterRAM2(uint32_t* aAdapterRAM) override; + NS_IMETHOD GetAdapterDriverVendor2(nsAString& aAdapterDriverVendor) override; NS_IMETHOD GetAdapterDriverVersion2( nsAString& aAdapterDriverVersion) override; NS_IMETHOD GetAdapterDriverDate2(nsAString& aAdapterDriverDate) override; NS_IMETHOD GetIsGPU2Active(bool* aIsGPU2Active) override; + NS_IMETHOD GetDrmRenderDevice(nsACString& aDrmRenderDevice) override; using GfxInfoBase::GetFeatureStatus; using GfxInfoBase::GetFeatureSuggestedDriverVersion; @@ -62,11 +72,12 @@ class GfxInfo : public GfxInfoBase { #endif protected: - virtual nsresult GetFeatureStatusImpl( - int32_t aFeature, int32_t* aStatus, nsAString& aSuggestedDriverVersion, - const nsTArray<GfxDriverInfo>& aDriverInfo, - OperatingSystem* aOS = nullptr); - virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo(); + nsresult GetFeatureStatusImpl(int32_t aFeature, int32_t* aStatus, + nsAString& aSuggestedDriverVersion, + const nsTArray<GfxDriverInfo>& aDriverInfo, + nsACString& aFailureId, + OperatingSystem* aOS = nullptr) override; + const nsTArray<GfxDriverInfo>& GetGfxDriverInfo() override; }; } // namespace widget diff --git a/widget/uikit/MediaKeysEventSourceFactory.cpp b/widget/uikit/MediaKeysEventSourceFactory.cpp new file mode 100644 index 0000000000..b52919d4cc --- /dev/null +++ b/widget/uikit/MediaKeysEventSourceFactory.cpp @@ -0,0 +1,17 @@ +/* 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 "MediaKeysEventSourceFactory.h" + +namespace mozilla { +namespace widget { + +mozilla::dom::MediaControlKeySource* CreateMediaControlKeySource() { + // GeckoView uses MediaController.webidl for media session events and control, + // see bug 1623715. + return nullptr; +} + +} // namespace widget +} // namespace mozilla diff --git a/widget/uikit/TextInputHandler.h b/widget/uikit/TextInputHandler.h new file mode 100644 index 0000000000..1f27bf11f0 --- /dev/null +++ b/widget/uikit/TextInputHandler.h @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 sw=2 et 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/. */ + +#ifndef TextInputHandler_h_ +#define TextInputHandler_h_ + +#import <UIKit/UITextInput.h> + +#include "mozilla/EventForwards.h" +#include "mozilla/TextEventDispatcherListener.h" +#include "mozilla/widget/IMEData.h" +#include "nsCOMPtr.h" + +class nsWindow; + +namespace mozilla::widget { +class TextEventDispatcher; + +// This is the temporary input class. When implementing UITextInpt protocol, we +// should share this class with Cocoa's version. +class TextInputHandler final : public TextEventDispatcherListener { + public: + explicit TextInputHandler(nsWindow* aWidget); + TextInputHandler() = delete; + + NS_DECL_ISUPPORTS + + NS_IMETHOD NotifyIME(TextEventDispatcher* aTextEventDispatcher, + const IMENotification& aNotification) override; + NS_IMETHOD_(IMENotificationRequests) GetIMENotificationRequests() override; + NS_IMETHOD_(void) + OnRemovedFrom(TextEventDispatcher* aTextEventDispatcher) override; + NS_IMETHOD_(void) + WillDispatchKeyboardEvent(TextEventDispatcher* aTextEventDispatcher, + WidgetKeyboardEvent& aKeyboardEvent, + uint32_t aIndexOfKeypress, void* aData) override; + + // UIKeyInput delegation + bool InsertText(NSString* aText); + bool HandleCommand(Command aCommand); + + void OnDestroyed(); + + private: + virtual ~TextInputHandler() = default; + + bool DispatchKeyDownEvent(uint32_t aKeyCode, KeyNameIndex aKeyNameIndex, + char16_t aCharCode, nsEventStatus& aStatus); + bool DispatchKeyUpEvent(uint32_t aKeyCode, KeyNameIndex aKeyNameIndex, + char16_t aCharCode, nsEventStatus& aStatus); + bool DispatchKeyPressEvent(uint32_t aKeyCode, KeyNameIndex aKeyNameIndex, + char16_t aCharCode, nsEventStatus& aStatus); + + bool EmulateKeyboardEvent(uint32_t aKeyCode, KeyNameIndex aKeyNameIndex, + char16_t charCode); + + bool Destroyed() { return !mWidget; } + + nsWindow* mWidget; // weak ref + RefPtr<TextEventDispatcher> mDispatcher; +}; + +} // namespace mozilla::widget +#endif diff --git a/widget/uikit/TextInputHandler.mm b/widget/uikit/TextInputHandler.mm new file mode 100644 index 0000000000..9a4a6ae226 --- /dev/null +++ b/widget/uikit/TextInputHandler.mm @@ -0,0 +1,254 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 sw=2 et 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 "TextInputHandler.h" + +#import <UIKit/UIKit.h> + +#include "mozilla/EventForwards.h" +#include "mozilla/Logging.h" +#include "mozilla/MiscEvents.h" +#include "mozilla/TextEventDispatcher.h" +#include "mozilla/TextEvents.h" +#include "mozilla/WidgetUtils.h" +#include "nsIWidget.h" +#include "nsObjCExceptions.h" +#include "nsString.h" +#include "nsWindow.h" + +mozilla::LazyLogModule gIMELog("TextInputHandler"); + +namespace mozilla::widget { + +static void GetStringForNSString(const NSString* aSrc, nsAString& aDist) { + NS_OBJC_BEGIN_TRY_IGNORE_BLOCK; + + if (!aSrc) { + aDist.Truncate(); + return; + } + + aDist.SetLength([aSrc length]); + [aSrc getCharacters:reinterpret_cast<unichar*>(aDist.BeginWriting()) + range:NSMakeRange(0, [aSrc length])]; + + NS_OBJC_END_TRY_IGNORE_BLOCK; +} + +NS_IMPL_ISUPPORTS(TextInputHandler, TextEventDispatcherListener, + nsISupportsWeakReference) + +TextInputHandler::TextInputHandler(nsWindow* aWidget) + : mWidget(aWidget), mDispatcher(aWidget->GetTextEventDispatcher()) {} + +nsresult TextInputHandler::NotifyIME(TextEventDispatcher* aTextEventDispatcher, + const IMENotification& aNotification) { + return NS_OK; +} + +IMENotificationRequests TextInputHandler::GetIMENotificationRequests() { + return IMENotificationRequests(); +} + +void TextInputHandler::OnRemovedFrom( + TextEventDispatcher* aTextEventDispatcher) {} + +void TextInputHandler::WillDispatchKeyboardEvent( + TextEventDispatcher* aTextEventDispatcher, + WidgetKeyboardEvent& aKeyboardEvent, uint32_t aIndexOfKeypress, + void* aData) {} + +bool TextInputHandler::InsertText(NSString* aText) { + nsString str; + GetStringForNSString(aText, str); + + MOZ_LOG(gIMELog, LogLevel::Info, + ("%p TextInputHandler::InsertText(aText=%s)", this, + NS_ConvertUTF16toUTF8(str).get())); + + if (Destroyed()) { + return false; + } + + if (str.Length() == 1) { + char16_t charCode = str[0]; + if (charCode == 0x0a) { + return EmulateKeyboardEvent(NS_VK_RETURN, KEY_NAME_INDEX_Enter, charCode); + } + if (charCode == 0x08) { + return EmulateKeyboardEvent(NS_VK_BACK, KEY_NAME_INDEX_Backspace, + charCode); + } + if (uint32_t keyCode = WidgetUtils::ComputeKeyCodeFromChar(charCode)) { + return EmulateKeyboardEvent(keyCode, KEY_NAME_INDEX_USE_STRING, charCode); + } + } + + nsEventStatus status = nsEventStatus_eIgnore; + RefPtr<nsWindow> widget(mWidget); + if (!DispatchKeyDownEvent(NS_VK_PROCESSKEY, KEY_NAME_INDEX_Process, 0, + status)) { + return false; + } + if (Destroyed()) { + return false; + } + + mDispatcher->CommitComposition(status, &str, nullptr); + if (widget->Destroyed()) { + return false; + } + + DispatchKeyUpEvent(NS_VK_PROCESSKEY, KEY_NAME_INDEX_Process, 0, status); + + return true; +} + +bool TextInputHandler::HandleCommand(Command aCommand) { + MOZ_LOG(gIMELog, LogLevel::Info, + ("%p TextInputHandler::HandleCommand, aCommand=%s", this, + ToChar(aCommand))); + + if (Destroyed()) { + return false; + } + + if (aCommand != Command::DeleteCharBackward) { + return false; + } + + nsEventStatus status = nsEventStatus_eIgnore; + if (!DispatchKeyDownEvent(NS_VK_BACK, KEY_NAME_INDEX_Backspace, 0, status)) { + return true; + } + if (Destroyed() || status == nsEventStatus_eConsumeNoDefault) { + return true; + } + + // TODO: Focus check + + if (!DispatchKeyPressEvent(NS_VK_BACK, KEY_NAME_INDEX_Backspace, 0, status)) { + return true; + } + if (Destroyed() || status == nsEventStatus_eConsumeNoDefault) { + return true; + } + + // TODO: Focus check + + DispatchKeyUpEvent(NS_VK_BACK, KEY_NAME_INDEX_Backspace, 0, status); + + return true; +} + +static uint32_t ComputeKeyModifiers(uint32_t aCharCode) { + if (aCharCode >= 'A' && aCharCode <= 'Z') { + return MODIFIER_SHIFT; + } + return 0; +} + +static void InitKeyEvent(WidgetKeyboardEvent& aEvent, uint32_t aKeyCode, + KeyNameIndex aKeyNameIndex, char16_t aCharCode) { + aEvent.mKeyCode = aKeyCode; + aEvent.mIsRepeat = false; + aEvent.mKeyNameIndex = aKeyNameIndex; + // TODO(m_kato): + // How to get native key? Then, implement NativeKeyToDOM*.h for iOS + aEvent.mCodeNameIndex = CODE_NAME_INDEX_UNKNOWN; + if (aEvent.mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) { + aEvent.mKeyValue = aCharCode; + } + aEvent.mModifiers = ComputeKeyModifiers(aCharCode); + aEvent.mLocation = eKeyLocationStandard; + aEvent.mTimeStamp = TimeStamp::Now(); +} + +bool TextInputHandler::DispatchKeyDownEvent(uint32_t aKeyCode, + KeyNameIndex aKeyNameIndex, + char16_t aCharCode, + nsEventStatus& aStatus) { + MOZ_ASSERT(aKeyCode); + MOZ_ASSERT(mWidget); + + WidgetKeyboardEvent keydownEvent(true, eKeyDown, mWidget); + InitKeyEvent(keydownEvent, aKeyCode, aKeyNameIndex, aCharCode); + nsresult rv = mDispatcher->BeginNativeInputTransaction(); + if (NS_FAILED(rv)) { + NS_WARNING("BeginNativeInputTransaction is failed"); + return false; + } + return mDispatcher->DispatchKeyboardEvent(eKeyDown, keydownEvent, aStatus); +} + +bool TextInputHandler::DispatchKeyUpEvent(uint32_t aKeyCode, + KeyNameIndex aKeyNameIndex, + char16_t aCharCode, + nsEventStatus& aStatus) { + MOZ_ASSERT(aKeyCode); + MOZ_ASSERT(mWidget); + + WidgetKeyboardEvent keyupEvent(true, eKeyUp, mWidget); + InitKeyEvent(keyupEvent, aKeyCode, aKeyNameIndex, aCharCode); + nsresult rv = mDispatcher->BeginNativeInputTransaction(); + if (NS_FAILED(rv)) { + NS_WARNING("BeginNativeInputTransaction is failed"); + return false; + } + return mDispatcher->DispatchKeyboardEvent(eKeyUp, keyupEvent, aStatus); +} + +bool TextInputHandler::DispatchKeyPressEvent(uint32_t aKeyCode, + KeyNameIndex aKeyNameIndex, + char16_t aCharCode, + nsEventStatus& aStatus) { + MOZ_ASSERT(aKeyCode); + MOZ_ASSERT(mWidget); + + WidgetKeyboardEvent keypressEvent(true, eKeyPress, mWidget); + InitKeyEvent(keypressEvent, aKeyCode, aKeyNameIndex, aCharCode); + nsresult rv = mDispatcher->BeginNativeInputTransaction(); + if (NS_FAILED(rv)) { + NS_WARNING("BeginNativeInputTransaction is failed"); + return false; + } + return mDispatcher->MaybeDispatchKeypressEvents(keypressEvent, aStatus); +} + +bool TextInputHandler::EmulateKeyboardEvent(uint32_t aKeyCode, + KeyNameIndex aKeyNameIndex, + char16_t aCharCode) { + MOZ_ASSERT(aCharCode); + + MOZ_LOG(gIMELog, LogLevel::Info, + ("%p TextInputHandler::EmulateKeyboardEvent(aKeyCode=%x, " + "aKeyNameIndex=%x, aCharCode=%x)", + this, aKeyCode, aKeyNameIndex, aCharCode)); + + nsEventStatus status = nsEventStatus_eIgnore; + if (!DispatchKeyDownEvent(aKeyCode, aKeyNameIndex, aCharCode, status)) { + return true; + } + if (Destroyed() || status == nsEventStatus_eConsumeNoDefault) { + return true; + } + // TODO: Focus check + + if (!DispatchKeyPressEvent(aKeyCode, aKeyNameIndex, aCharCode, status)) { + return true; + } + if (Destroyed() || status == nsEventStatus_eConsumeNoDefault) { + return true; + } + // TODO: Focus check + + DispatchKeyUpEvent(aKeyCode, aKeyNameIndex, aCharCode, status); + return true; +} + +void TextInputHandler::OnDestroyed() { mWidget = nullptr; } + +} // namespace mozilla::widget diff --git a/widget/uikit/UIKitUtils.h b/widget/uikit/UIKitUtils.h new file mode 100644 index 0000000000..2e34b126fd --- /dev/null +++ b/widget/uikit/UIKitUtils.h @@ -0,0 +1,23 @@ +/* -*- Mode: C++; 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/. */ + +#import <UIKit/UIKit.h> + +#include "IMEData.h" + +namespace mozilla::widget { + +class UIKitUtils final { + public: + UIKitUtils() = delete; + ~UIKitUtils() = delete; + + static UIKeyboardType GetUIKeyboardType(const InputContext& aContext); + static UIReturnKeyType GetUIReturnKeyType(const InputContext& aContext); + static UITextAutocapitalizationType GetUITextAutocapitalizationType( + const InputContext& aContext); +}; + +} // namespace mozilla::widget diff --git a/widget/uikit/UIKitUtils.mm b/widget/uikit/UIKitUtils.mm new file mode 100644 index 0000000000..ddcd2312b0 --- /dev/null +++ b/widget/uikit/UIKitUtils.mm @@ -0,0 +1,89 @@ +/* -*- Mode: C++; 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/. */ + +#include "UIKitUtils.h" + +namespace mozilla::widget { + +// static +UIKeyboardType UIKitUtils::GetUIKeyboardType(const InputContext& aContext) { + if (aContext.mHTMLInputMode.EqualsLiteral("email")) { + return UIKeyboardTypeEmailAddress; + } + if (aContext.mHTMLInputMode.EqualsLiteral("deciaml")) { + return UIKeyboardTypeDecimalPad; + } + if (aContext.mHTMLInputMode.EqualsLiteral("numeric")) { + return UIKeyboardTypeNumberPad; + } + if (aContext.mHTMLInputMode.EqualsLiteral("search")) { + return UIKeyboardTypeWebSearch; + } + if (aContext.mHTMLInputMode.EqualsLiteral("tel")) { + return UIKeyboardTypePhonePad; + } + if (aContext.mHTMLInputMode.EqualsLiteral("url")) { + return UIKeyboardTypeURL; + } + + if (aContext.mHTMLInputType.EqualsLiteral("email")) { + return UIKeyboardTypeEmailAddress; + } + if (aContext.mHTMLInputType.EqualsLiteral("number")) { + return UIKeyboardTypeNumberPad; + } + if (aContext.mHTMLInputType.EqualsLiteral("tel")) { + return UIKeyboardTypePhonePad; + } + if (aContext.mHTMLInputType.EqualsLiteral("url")) { + return UIKeyboardTypeURL; + } + + return UIKeyboardTypeDefault; +} + +// static +UIReturnKeyType UIKitUtils::GetUIReturnKeyType(const InputContext& aContext) { + if (aContext.mActionHint.EqualsLiteral("done")) { + return UIReturnKeyDone; + } + if (aContext.mActionHint.EqualsLiteral("go")) { + return UIReturnKeyGo; + } + if (aContext.mActionHint.EqualsLiteral("next") || + aContext.mActionHint.EqualsLiteral("maybenext")) { + return UIReturnKeyNext; + } + if (aContext.mActionHint.EqualsLiteral("search")) { + return UIReturnKeySearch; + } + if (aContext.mActionHint.EqualsLiteral("send")) { + return UIReturnKeySend; + } + + return UIReturnKeyDefault; +} + +// static +UITextAutocapitalizationType UIKitUtils::GetUITextAutocapitalizationType( + const InputContext& aContext) { + if (aContext.mAutocapitalize.EqualsLiteral("characters")) { + return UITextAutocapitalizationTypeAllCharacters; + } + if (aContext.mAutocapitalize.EqualsLiteral("none")) { + return UITextAutocapitalizationTypeNone; + } + if (aContext.mAutocapitalize.EqualsLiteral("sentences")) { + return UITextAutocapitalizationTypeSentences; + } + if (aContext.mAutocapitalize.EqualsLiteral("words")) { + return UITextAutocapitalizationTypeWords; + } + // TODO(m_kato): + // Infer autocapitalization type by input type like GeckoView. + return UITextAutocapitalizationTypeNone; +} + +} // namespace mozilla::widget diff --git a/widget/uikit/components.conf b/widget/uikit/components.conf new file mode 100644 index 0000000000..0a4480ee4a --- /dev/null +++ b/widget/uikit/components.conf @@ -0,0 +1,28 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +Headers = '/widget/uikit/nsWidgetFactory.h', + +InitFunc = 'nsWidgetUIKitModuleCtor' +UnloadFunc = 'nsWidgetUIKitModuleDtor' + +Classes = [ + { + 'name': 'GfxInfo', + 'cid': '{d755a760-9f27-11df-0800-200c9a664242}', + 'contract_ids': ['@mozilla.org/gfx/info;1'], + 'type': 'mozilla::widget::GfxInfo', + 'headers': ['/widget/uikit/GfxInfo.h'], + 'init_method': 'Init', + }, + { + 'cid': '{2d96b3df-c051-11d1-a827-0040959a28c9}', + 'contract_ids': ['@mozilla.org/widget/appshell/uikit;1'], + 'legacy_constructor': 'nsAppShellConstructor', + 'headers': ['/widget/uikit/nsWidgetFactory.h'], + 'processes': ProcessSelector.ALLOW_IN_GPU_RDD_VR_SOCKET_AND_UTILITY_PROCESS, + }, +] diff --git a/widget/uikit/moz.build b/widget/uikit/moz.build index 6a3c2db994..88780c9690 100644 --- a/widget/uikit/moz.build +++ b/widget/uikit/moz.build @@ -7,13 +7,20 @@ with Files("**"): BUG_COMPONENT = ("Core", "Widget") +with Files("*TextInput*"): + BUG_COMPONENT = ("Core", "DOM: UI Events & Focus Handling") + SOURCES += [ "GfxInfo.cpp", + "MediaKeysEventSourceFactory.cpp", "nsAppShell.mm", + "nsBidiKeyboard.mm", "nsLookAndFeel.mm", - "nsScreenManager.mm", + "nsNativeThemeUIKit.mm", "nsWidgetFactory.mm", "nsWindow.mm", + "TextInputHandler.mm", + "UIKitUtils.mm", ] include("/ipc/chromium/chromium-config.mozbuild") @@ -22,3 +29,11 @@ FINAL_LIBRARY = "xul" LOCAL_INCLUDES += [ "/widget", ] + +XPCOM_MANIFESTS += [ + "components.conf", +] + +OS_LIBS += [ + "-framework UIKit", +] diff --git a/widget/uikit/nsAppShell.h b/widget/uikit/nsAppShell.h index fd46a51025..c8ae7ce9ef 100644 --- a/widget/uikit/nsAppShell.h +++ b/widget/uikit/nsAppShell.h @@ -41,8 +41,8 @@ class nsAppShell : public nsBaseAppShell { virtual ~nsAppShell(); static void ProcessGeckoEvents(void* aInfo); - virtual void ScheduleNativeEventCallback(); - virtual bool ProcessNextNativeEvent(bool aMayWait); + void ScheduleNativeEventCallback() override; + bool ProcessNextNativeEvent(bool aMayWait) override; NSAutoreleasePool* mAutoreleasePool; AppShellDelegate* mDelegate; diff --git a/widget/uikit/nsBidiKeyboard.h b/widget/uikit/nsBidiKeyboard.h new file mode 100644 index 0000000000..3a9a6fe2fb --- /dev/null +++ b/widget/uikit/nsBidiKeyboard.h @@ -0,0 +1,23 @@ +/* -*- Mode: C++; 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/. */ + +#ifndef nsBidiKeyboard_h_ +#define nsBidiKeyboard_h_ + +#include "nsIBidiKeyboard.h" + +class nsBidiKeyboard : public nsIBidiKeyboard { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIBIDIKEYBOARD + + nsBidiKeyboard(); + + protected: + virtual ~nsBidiKeyboard(); +}; + +#endif // nsBidiKeyboard_h_ diff --git a/widget/uikit/nsBidiKeyboard.mm b/widget/uikit/nsBidiKeyboard.mm new file mode 100644 index 0000000000..bbe1eff92f --- /dev/null +++ b/widget/uikit/nsBidiKeyboard.mm @@ -0,0 +1,35 @@ +/* -*- Mode: C++; 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/. */ + +#include "nsBidiKeyboard.h" +#include "nsIWidget.h" + +// This must be the last include: +#include "nsObjCExceptions.h" + +using namespace mozilla::widget; + +NS_IMPL_ISUPPORTS(nsBidiKeyboard, nsIBidiKeyboard) + +nsBidiKeyboard::nsBidiKeyboard() : nsIBidiKeyboard() { Reset(); } + +nsBidiKeyboard::~nsBidiKeyboard() {} + +NS_IMETHODIMP nsBidiKeyboard::Reset() { return NS_OK; } + +NS_IMETHODIMP nsBidiKeyboard::IsLangRTL(bool* aIsRTL) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsBidiKeyboard::GetHaveBidiKeyboards(bool* aResult) { + // not implemented yet + return NS_ERROR_NOT_IMPLEMENTED; +} + +// static +already_AddRefed<nsIBidiKeyboard> nsIWidget::CreateBidiKeyboardInner() { + return do_AddRef(new nsBidiKeyboard()); +} diff --git a/widget/uikit/nsLookAndFeel.h b/widget/uikit/nsLookAndFeel.h index 7de7e0712b..c696502ec1 100644 --- a/widget/uikit/nsLookAndFeel.h +++ b/widget/uikit/nsLookAndFeel.h @@ -14,13 +14,13 @@ class nsLookAndFeel final : public nsXPLookAndFeel { virtual ~nsLookAndFeel(); void NativeInit() final; - virtual void RefreshImpl(); - nsresult NativeGetImpl(IntID aID, int32_t& aResult) override; + void RefreshImpl() override; + nsresult NativeGetInt(IntID aID, int32_t& aResult) override; nsresult NativeGetFloat(FloatID aID, float& aResult) override; nsresult NativeGetColor(ColorID, ColorScheme, nscolor& aResult) override; bool NativeGetFont(FontID aID, nsString& aFontName, gfxFontStyle& aFontStyle) override; - virtual char16_t GetPasswordCharacterImpl() { + char16_t GetPasswordCharacterImpl() override { // unicode value for the bullet character, used for password textfields. return 0x2022; } @@ -28,7 +28,6 @@ class nsLookAndFeel final : public nsXPLookAndFeel { static bool UseOverlayScrollbars() { return true; } private: - nscolor mColorTextSelectForeground; nscolor mColorDarkText; bool mInitialized; diff --git a/widget/uikit/nsLookAndFeel.mm b/widget/uikit/nsLookAndFeel.mm index 29eb52a234..b420cc9a1d 100644 --- a/widget/uikit/nsLookAndFeel.mm +++ b/widget/uikit/nsLookAndFeel.mm @@ -13,6 +13,8 @@ #include "gfxFont.h" #include "gfxFontConstants.h" +using namespace mozilla; + nsLookAndFeel::nsLookAndFeel() : mInitialized(false) {} nsLookAndFeel::~nsLookAndFeel() {} @@ -41,7 +43,8 @@ void nsLookAndFeel::RefreshImpl() { mInitialized = false; } -nsresult nsLookAndFeel::NativeGetColor(ColorID, ColorScheme, nscolor& aResult) { +nsresult nsLookAndFeel::NativeGetColor(ColorID aID, ColorScheme, + nscolor& aResult) { EnsureInit(); nsresult res = NS_OK; @@ -55,7 +58,7 @@ nsresult nsLookAndFeel::NativeGetColor(ColorID, ColorScheme, nscolor& aResult) { break; case ColorID::Highlighttext: case ColorID::MozMenuhovertext: - aResult = mColorTextSelectForeground; + aResult = NS_SAME_AS_FOREGROUND_COLOR; break; case ColorID::IMESelectedRawTextBackground: case ColorID::IMESelectedConvertedTextBackground: @@ -154,11 +157,11 @@ nsresult nsLookAndFeel::NativeGetColor(ColorID, ColorScheme, nscolor& aResult) { aResult = NS_RGB(0xaa, 0xaa, 0xaa); break; case ColorID::Window: - case ColorID::MozField: + case ColorID::Field: case ColorID::MozCombobox: aResult = NS_RGB(0xff, 0xff, 0xff); break; - case ColorID::MozFieldtext: + case ColorID::Fieldtext: case ColorID::MozComboboxtext: aResult = mColorDarkText; break; @@ -175,12 +178,6 @@ nsresult nsLookAndFeel::NativeGetColor(ColorID, ColorScheme, nscolor& aResult) { case ColorID::MozMacFocusring: aResult = NS_RGB(0x3F, 0x98, 0xDD); break; - case ColorID::MozMacMenutextdisable: - aResult = NS_RGB(0x88, 0x88, 0x88); - break; - case ColorID::MozMacMenutextselect: - aResult = NS_RGB(0xaa, 0xaa, 0xaa); - break; case ColorID::MozMacDisabledtoolbartext: aResult = NS_RGB(0x3F, 0x3F, 0x3F); break; @@ -260,6 +257,19 @@ nsLookAndFeel::NativeGetInt(IntID aID, int32_t& aResult) { case IntID::ScrollArrowStyle: aResult = eScrollArrow_None; break; + case IntID::UseOverlayScrollbars: + case IntID::AllowOverlayScrollbarsOverlap: + aResult = 1; + break; + case IntID::ScrollbarDisplayOnMouseMove: + aResult = 0; + break; + case IntID::ScrollbarFadeBeginDelay: + aResult = 450; + break; + case IntID::ScrollbarFadeDuration: + aResult = 200; + break; case IntID::TreeOpenDelay: aResult = 1000; break; @@ -326,10 +336,10 @@ nsLookAndFeel::NativeGetFloat(FloatID aID, float& aResult) { bool nsLookAndFeel::NativeGetFont(FontID aID, nsString& aFontName, gfxFontStyle& aFontStyle) { // hack for now - if (aID == FontID::Window || aID == FontID::Document) { - aFontStyle.style = FontSlantStyle::Normal(); - aFontStyle.weight = FontWeight::Normal(); - aFontStyle.stretch = FontStretch::Normal(); + if (aID == FontID::Caption || aID == FontID::Menu) { + aFontStyle.style = FontSlantStyle::NORMAL; + aFontStyle.weight = FontWeight::NORMAL; + aFontStyle.stretch = FontStretch::NORMAL; aFontStyle.size = 14; aFontStyle.systemFont = true; @@ -347,14 +357,6 @@ void nsLookAndFeel::EnsureInit() { } mInitialized = true; - nscolor color; - GetColor(ColorID::TextSelectBackground, color); - if (color == 0x000000) { - mColorTextSelectForeground = NS_RGB(0xff, 0xff, 0xff); - } else { - mColorTextSelectForeground = NS_SAME_AS_FOREGROUND_COLOR; - } - mColorDarkText = GetColorFromUIColor([UIColor darkTextColor]); RecordTelemetry(); diff --git a/widget/uikit/nsNativeThemeUIKit.h b/widget/uikit/nsNativeThemeUIKit.h new file mode 100644 index 0000000000..87c631a8b8 --- /dev/null +++ b/widget/uikit/nsNativeThemeUIKit.h @@ -0,0 +1,21 @@ +/* -*- 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/. */ + +#ifndef nsNativeThemeUIKit_h +#define nsNativeThemeUIKit_h + +#include "nsITheme.h" +#include "Theme.h" + +class nsNativeThemeUIKit final : public mozilla::widget::Theme { + public: + nsNativeThemeUIKit(); + + protected: + virtual ~nsNativeThemeUIKit() = default; +}; + +#endif // nsNativeThemeUIKit_h diff --git a/widget/uikit/nsNativeThemeUIKit.mm b/widget/uikit/nsNativeThemeUIKit.mm new file mode 100644 index 0000000000..19cde52426 --- /dev/null +++ b/widget/uikit/nsNativeThemeUIKit.mm @@ -0,0 +1,19 @@ +/* -*- Mode: C++; 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/. */ + +#include "nsNativeThemeUIKit.h" + +using namespace mozilla; +using namespace mozilla::gfx; +using namespace mozilla::widget; + +nsNativeThemeUIKit::nsNativeThemeUIKit() : Theme(ScrollbarStyle()) {} + +already_AddRefed<Theme> do_CreateNativeThemeDoNotUseDirectly() { + if (gfxPlatform::IsHeadless()) { + return do_AddRef(new Theme(Theme::ScrollbarStyle())); + } + return do_AddRef(new nsNativeThemeUIKit()); +} diff --git a/widget/uikit/nsScreenManager.h b/widget/uikit/nsScreenManager.h deleted file mode 100644 index 0d19728264..0000000000 --- a/widget/uikit/nsScreenManager.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; 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/. */ - -#ifndef nsScreenManager_h_ -#define nsScreenManager_h_ - -#include "nsBaseScreen.h" -#include "nsIScreenManager.h" -#include "nsCOMPtr.h" -#include "nsRect.h" - -@class UIScreen; - -class UIKitScreen : public nsBaseScreen { - public: - explicit UIKitScreen(UIScreen* screen); - ~UIKitScreen() {} - - NS_IMETHOD GetId(uint32_t* outId) override { - *outId = 0; - return NS_OK; - } - - NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, - int32_t* aHeight) override; - NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, - int32_t* aHeight) override; - NS_IMETHOD GetRectDisplayPix(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, - int32_t* aHeight) override; - NS_IMETHOD GetAvailRectDisplayPix(int32_t* aLeft, int32_t* aTop, - int32_t* aWidth, int32_t* aHeight) override; - NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override; - NS_IMETHOD GetColorDepth(int32_t* aColorDepth) override; - NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor) override; - NS_IMETHOD GetDefaultCSSScaleFactor(double* aScaleFactor) override { - return GetContentsScaleFactor(aScaleFactor); - } - - private: - UIScreen* mScreen; -}; - -class UIKitScreenManager : public nsIScreenManager { - public: - UIKitScreenManager(); - - NS_DECL_ISUPPORTS - - NS_DECL_NSISCREENMANAGER - - static LayoutDeviceIntRect GetBounds(); - - private: - virtual ~UIKitScreenManager() {} - // TODO: support >1 screen, iPad supports external displays - nsCOMPtr<nsIScreen> mScreen; -}; - -#endif // nsScreenManager_h_ diff --git a/widget/uikit/nsScreenManager.mm b/widget/uikit/nsScreenManager.mm deleted file mode 100644 index da37a4199d..0000000000 --- a/widget/uikit/nsScreenManager.mm +++ /dev/null @@ -1,104 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; 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/. */ - -#import <UIKit/UIScreen.h> - -#include "gfxPoint.h" -#include "nsScreenManager.h" -#include "nsAppShell.h" - -static LayoutDeviceIntRect gScreenBounds; -static bool gScreenBoundsSet = false; - -UIKitScreen::UIKitScreen(UIScreen* aScreen) { mScreen = [aScreen retain]; } - -NS_IMETHODIMP -UIKitScreen::GetRect(int32_t* outX, int32_t* outY, int32_t* outWidth, - int32_t* outHeight) { - return GetRectDisplayPix(outX, outY, outWidth, outHeight); -} - -NS_IMETHODIMP -UIKitScreen::GetAvailRect(int32_t* outX, int32_t* outY, int32_t* outWidth, - int32_t* outHeight) { - return GetAvailRectDisplayPix(outX, outY, outWidth, outHeight); -} - -NS_IMETHODIMP -UIKitScreen::GetRectDisplayPix(int32_t* outX, int32_t* outY, int32_t* outWidth, - int32_t* outHeight) { - nsIntRect rect = UIKitScreenManager::GetBounds(); - *outX = rect.x; - *outY = rect.y; - *outWidth = rect.width; - *outHeight = rect.height; - - return NS_OK; -} - -NS_IMETHODIMP -UIKitScreen::GetAvailRectDisplayPix(int32_t* outX, int32_t* outY, - int32_t* outWidth, int32_t* outHeight) { - CGRect rect = [mScreen applicationFrame]; - CGFloat scale = [mScreen scale]; - - *outX = rect.origin.x * scale; - *outY = rect.origin.y * scale; - *outWidth = rect.size.width * scale; - *outHeight = rect.size.height * scale; - - return NS_OK; -} - -NS_IMETHODIMP -UIKitScreen::GetPixelDepth(int32_t* aPixelDepth) { - // Close enough. - *aPixelDepth = 24; - return NS_OK; -} - -NS_IMETHODIMP -UIKitScreen::GetColorDepth(int32_t* aColorDepth) { - return GetPixelDepth(aColorDepth); -} - -NS_IMETHODIMP -UIKitScreen::GetContentsScaleFactor(double* aContentsScaleFactor) { - *aContentsScaleFactor = [mScreen scale]; - return NS_OK; -} - -NS_IMPL_ISUPPORTS(UIKitScreenManager, nsIScreenManager) - -UIKitScreenManager::UIKitScreenManager() - : mScreen(new UIKitScreen([UIScreen mainScreen])) {} - -LayoutDeviceIntRect UIKitScreenManager::GetBounds() { - if (!gScreenBoundsSet) { - CGRect rect = [[UIScreen mainScreen] bounds]; - CGFloat scale = [[UIScreen mainScreen] scale]; - gScreenBounds.x = rect.origin.x * scale; - gScreenBounds.y = rect.origin.y * scale; - gScreenBounds.width = rect.size.width * scale; - gScreenBounds.height = rect.size.height * scale; - gScreenBoundsSet = true; - } - printf("UIKitScreenManager::GetBounds: %d %d %d %d\n", gScreenBounds.x, - gScreenBounds.y, gScreenBounds.width, gScreenBounds.height); - return gScreenBounds; -} - -NS_IMETHODIMP -UIKitScreenManager::GetPrimaryScreen(nsIScreen** outScreen) { - NS_IF_ADDREF(*outScreen = mScreen.get()); - return NS_OK; -} - -NS_IMETHODIMP -UIKitScreenManager::ScreenForRect(int32_t inLeft, int32_t inTop, - int32_t inWidth, int32_t inHeight, - nsIScreen** outScreen) { - return GetPrimaryScreen(outScreen); -} diff --git a/widget/uikit/nsWidgetFactory.h b/widget/uikit/nsWidgetFactory.h new file mode 100644 index 0000000000..570639e495 --- /dev/null +++ b/widget/uikit/nsWidgetFactory.h @@ -0,0 +1,21 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: + */ +/* 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/. */ + +#ifndef widget_uikit_nsWidgetFactory_h +#define widget_uikit_nsWidgetFactory_h + +#include "nscore.h" +#include "nsID.h" + +class nsISupports; + +nsresult nsAppShellConstructor(const nsIID& iid, void** result); + +void nsWidgetUIKitModuleCtor(); +void nsWidgetUIKitModuleDtor(); + +#endif // defined widget_uikit_nsWidgetFactory_h diff --git a/widget/uikit/nsWidgetFactory.mm b/widget/uikit/nsWidgetFactory.mm index 356e5b8cdf..e5b24d200f 100644 --- a/widget/uikit/nsWidgetFactory.mm +++ b/widget/uikit/nsWidgetFactory.mm @@ -3,51 +3,18 @@ * 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 "nsISupports.h" -#include "mozilla/ModuleUtils.h" - -#include "nsWidgetsCID.h" - #include "nsAppShell.h" #include "nsAppShellSingleton.h" #include "nsLookAndFeel.h" -#include "nsScreenManager.h" - -NS_GENERIC_FACTORY_CONSTRUCTOR(UIKitScreenManager) +#include "nsWidgetFactory.h" +#include "mozilla/WidgetUtils.h" -#include "GfxInfo.h" -namespace mozilla { -namespace widget { -// This constructor should really be shared with all platforms. -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(GfxInfo, Init) -} // namespace widget -} // namespace mozilla +using namespace mozilla::widget; -NS_DEFINE_NAMED_CID(NS_APPSHELL_CID); -NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID); -NS_DEFINE_NAMED_CID(NS_GFXINFO_CID); +void nsWidgetUIKitModuleCtor() { nsAppShellInit(); } -static const mozilla::Module::CIDEntry kWidgetCIDs[] = { - {&kNS_APPSHELL_CID, false, nullptr, nsAppShellConstructor}, - {&kNS_SCREENMANAGER_CID, false, nullptr, UIKitScreenManagerConstructor}, - {&kNS_GFXINFO_CID, false, nullptr, mozilla::widget::GfxInfoConstructor}, - {nullptr}}; - -static const mozilla::Module::ContractIDEntry kWidgetContracts[] = { - {"@mozilla.org/widget/appshell/uikit;1", &kNS_APPSHELL_CID}, - {"@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID}, - {"@mozilla.org/gfx/info;1", &kNS_GFXINFO_CID}, - {nullptr}}; - -static void nsWidgetUIKitModuleDtor() { +void nsWidgetUIKitModuleDtor() { + WidgetUtils::Shutdown(); nsLookAndFeel::Shutdown(); nsAppShellShutdown(); } - -extern const mozilla::Module kWidgetModule = {mozilla::Module::kVersion, - kWidgetCIDs, - kWidgetContracts, - nullptr, - nullptr, - nsAppShellInit, - nsWidgetUIKitModuleDtor}; diff --git a/widget/uikit/nsWindow.h b/widget/uikit/nsWindow.h index 5dad452930..cb5d676d7c 100644 --- a/widget/uikit/nsWindow.h +++ b/widget/uikit/nsWindow.h @@ -15,6 +15,10 @@ @class UIView; @class ChildView; +namespace mozilla::widget { +class TextInputHandler; +} + class nsWindow final : public nsBaseWidget { typedef nsBaseWidget Inherited; @@ -27,49 +31,47 @@ class nsWindow final : public nsBaseWidget { // nsIWidget // - [[nodiscard]] virtual nsresult Create( + [[nodiscard]] nsresult Create( nsIWidget* aParent, nsNativeWidget aNativeParent, const LayoutDeviceIntRect& aRect, - widget::InitData* aInitData = nullptr) override; - virtual void Destroy() override; - virtual void Show(bool aState) override; - virtual void Enable(bool aState) override {} - virtual bool IsEnabled() const override { return true; } - virtual bool IsVisible() const override { return mVisible; } - virtual void SetFocus(Raise, mozilla::dom::CallerType aCallerType) override; - virtual LayoutDeviceIntPoint WidgetToScreenOffset() override; - - virtual void SetBackgroundColor(const nscolor& aColor) override; - virtual void* GetNativeData(uint32_t aDataType) override; - - virtual void Move(double aX, double aY) override; - virtual nsSizeMode SizeMode() override { return mSizeMode; } - virtual void SetSizeMode(nsSizeMode aMode) override; + mozilla::widget::InitData* aInitData = nullptr) override; + void Destroy() override; + void Show(bool aState) override; + void Enable(bool aState) override {} + bool IsEnabled() const override { return true; } + bool IsVisible() const override { return mVisible; } + void SetFocus(Raise, mozilla::dom::CallerType aCallerType) override; + LayoutDeviceIntPoint WidgetToScreenOffset() override; + + void SetBackgroundColor(const nscolor& aColor) override; + void* GetNativeData(uint32_t aDataType) override; + + void Move(double aX, double aY) override; + nsSizeMode SizeMode() override { return mSizeMode; } + void SetSizeMode(nsSizeMode aMode) override; void EnteredFullScreen(bool aFullScreen); - virtual void Resize(double aWidth, double aHeight, bool aRepaint) override; - virtual void Resize(double aX, double aY, double aWidth, double aHeight, - bool aRepaint) override; - virtual LayoutDeviceIntRect GetScreenBounds() override; + void Resize(double aWidth, double aHeight, bool aRepaint) override; + void Resize(double aX, double aY, double aWidth, double aHeight, + bool aRepaint) override; + LayoutDeviceIntRect GetScreenBounds() override; void ReportMoveEvent(); void ReportSizeEvent(); void ReportSizeModeEvent(nsSizeMode aMode); CGFloat BackingScaleFactor(); void BackingScaleFactorChanged(); - virtual float GetDPI() override { + float GetDPI() override { // XXX: terrible return 326.0f; } - virtual double GetDefaultScaleInternal() override { - return BackingScaleFactor(); - } - virtual int32_t RoundsWidgetCoordinatesTo() override; + double GetDefaultScaleInternal() override { return BackingScaleFactor(); } + int32_t RoundsWidgetCoordinatesTo() override; - virtual nsresult SetTitle(const nsAString& aTitle) override { return NS_OK; } + nsresult SetTitle(const nsAString& aTitle) override { return NS_OK; } - virtual void Invalidate(const LayoutDeviceIntRect& aRect) override; - virtual nsresult DispatchEvent(mozilla::WidgetGUIEvent* aEvent, - nsEventStatus& aStatus) override; + void Invalidate(const LayoutDeviceIntRect& aRect) override; + nsresult DispatchEvent(mozilla::WidgetGUIEvent* aEvent, + nsEventStatus& aStatus) override; void WillPaintWindow(); bool PaintWindow(LayoutDeviceIntRegion aRegion); @@ -78,9 +80,16 @@ class nsWindow final : public nsBaseWidget { // virtual nsresult // NotifyIME(const IMENotification& aIMENotification) override; - virtual void SetInputContext(const InputContext& aContext, - const InputContextAction& aAction); - virtual InputContext GetInputContext(); + void SetInputContext(const InputContext& aContext, + const InputContextAction& aAction) override; + InputContext GetInputContext() override; + TextEventDispatcherListener* GetNativeTextEventDispatcherListener() override; + + mozilla::widget::TextInputHandler* GetTextInputHandler() const { + return mTextInputHandler; + } + bool IsVirtualKeyboardDisabled() const; + /* virtual bool ExecuteNativeKeyBinding( NativeKeyBindingsType aType, @@ -104,7 +113,9 @@ class nsWindow final : public nsBaseWidget { nsSizeMode mSizeMode; nsTArray<nsWindow*> mChildren; nsWindow* mParent; - InputContext mInputContext; + + mozilla::widget::InputContext mInputContext; + RefPtr<mozilla::widget::TextInputHandler> mTextInputHandler; void OnSizeChanged(const mozilla::gfx::IntSize& aSize); diff --git a/widget/uikit/nsWindow.mm b/widget/uikit/nsWindow.mm index 0c1a38c27c..51b317ee61 100644 --- a/widget/uikit/nsWindow.mm +++ b/widget/uikit/nsWindow.mm @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #import <UIKit/UIEvent.h> +#import <UIKit/UIKit.h> #import <UIKit/UIGraphics.h> #import <UIKit/UIInterface.h> #import <UIKit/UIScreen.h> @@ -17,29 +18,41 @@ #include <algorithm> #include "nsWindow.h" -#include "nsScreenManager.h" #include "nsAppShell.h" +#ifdef ACCESSIBILITY +# include "nsAccessibilityService.h" +# include "mozilla/a11y/LocalAccessible.h" +#endif #include "nsWidgetsCID.h" #include "nsGfxCIID.h" +#include "gfxPlatform.h" #include "gfxQuartzSurface.h" #include "gfxUtils.h" #include "gfxImageSurface.h" #include "gfxContext.h" +#include "nsObjCExceptions.h" #include "nsRegion.h" -#include "Layers.h" #include "nsTArray.h" +#include "TextInputHandler.h" +#include "UIKitUtils.h" #include "mozilla/BasicEvents.h" #include "mozilla/ProfilerLabels.h" #include "mozilla/TouchEvents.h" #include "mozilla/Unused.h" #include "mozilla/dom/MouseEventBinding.h" +#include "mozilla/gfx/Logging.h" +#ifdef ACCESSIBILITY +# include "mozilla/a11y/MUIRootAccessibleProtocol.h" +#endif using namespace mozilla; -using namespace mozilla::dom; +using namespace mozilla::gfx; using namespace mozilla::layers; +using mozilla::dom::Touch; +using mozilla::widget::UIKitUtils; #define ALOG(args...) \ fprintf(stderr, args); \ @@ -62,18 +75,22 @@ static CGRect DevPixelsToUIKitPoints(const LayoutDeviceIntRect& aRect, // Used to retain a Cocoa object for the remainder of a method's execution. class nsAutoRetainUIKitObject { public: - nsAutoRetainUIKitObject(id anObject) { mObject = [anObject retain]; } + explicit nsAutoRetainUIKitObject(id anObject) { mObject = [anObject retain]; } ~nsAutoRetainUIKitObject() { [mObject release]; } private: id mObject; // [STRONG] }; -@interface ChildView : UIView { +#ifdef ACCESSIBILITY +@interface ChildView : UIView <UIKeyInput, MUIRootAccessibleProtocol> { +#else +@interface ChildView : UIView <UIKeyInput> { +#endif @public nsWindow* mGeckoChild; // weak ref BOOL mWaitingForPaint; - CFMutableDictionaryRef mTouches; + NSMapTable<UITouch*, NSNumber*>* mTouches; int mNextTouchID; } // sets up our view, attaching it to its owning gecko view @@ -93,10 +110,32 @@ class nsAutoRetainUIKitObject { touches:(NSSet*)aTouches widget:(nsWindow*)aWindow; // Event handling (UIResponder) -- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event; -- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event; -- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event; -- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event; +- (void)touchesBegan:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event; +- (void)touchesCancelled:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event; +- (void)touchesEnded:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event; +- (void)touchesMoved:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event; + +- (void)activateWindow:(NSNotification*)notification; +- (void)deactivateWindow:(NSNotification*)notification; + +#ifdef ACCESSIBILITY +// MUIRootAccessible +- (BOOL)hasRepresentedView; +- (id)representedView; + +// MUIAccessible +- (BOOL)isAccessibilityElement; +- (NSString*)accessibilityLabel; +- (CGRect)accessibilityFrame; +- (NSString*)accessibilityValue; +- (uint64_t)accessibilityTraits; +- (NSInteger)accessibilityElementCount; +- (nullable id)accessibilityElementAtIndex:(NSInteger)index; +- (NSInteger)indexOfAccessibilityElement:(id)element; +- (NSArray* _Nullable)accessibilityElements; +- (UIAccessibilityContainerType)accessibilityContainerType; +#endif + @end @implementation ChildView @@ -120,15 +159,29 @@ class nsAutoRetainUIKitObject { tapRecognizer.numberOfTapsRequired = 1; [self addGestureRecognizer:tapRecognizer]; - mTouches = - CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr); + mTouches = [[NSMapTable alloc] init]; mNextTouchID = 0; + + // This is managed with weak references by the notification center so that we + // do not need to call removeObserver. + // https://developer.apple.com/documentation/foundation/nsnotificationcenter/1415360-addobserver#discussion + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(activateWindow:) + name:UIWindowDidBecomeKeyNotification + object:nil]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(deactivateWindow:) + name:UIWindowDidResignKeyNotification + object:nil]; + return self; } - (void)widgetDestroyed { mGeckoChild = nullptr; - CFRelease(mTouches); + [mTouches release]; } - (void)delayedTearDown { @@ -136,6 +189,30 @@ class nsAutoRetainUIKitObject { [self release]; } +- (void)activateWindow:(NSNotification*)notification { + ALOG("[[ChildView[%p] activateWindow]", (void*)self); + + if (!mGeckoChild) { + return; + } + + if (nsIWidgetListener* listener = mGeckoChild->GetWidgetListener()) { + listener->WindowActivated(); + } +} + +- (void)deactivateWindow:(NSNotification*)notification { + ALOG("[[ChildView[%p] deactivateWindow]", (void*)self); + + if (!mGeckoChild) { + return; + } + + if (nsIWidgetListener* listener = mGeckoChild->GetWidgetListener()) { + listener->WindowDeactivated(); + } +} + - (void)sendMouseEvent:(EventMessage)aType point:(LayoutDeviceIntPoint)aPoint widget:(nsWindow*)aWindow { @@ -144,9 +221,8 @@ class nsAutoRetainUIKitObject { event.mRefPoint = aPoint; event.mClickCount = 1; - event.button = MouseButton::ePrimary; - event.mTime = PR_IntervalNow(); - event.inputSource = MouseEvent_Binding::MOZ_SOURCE_UNKNOWN; + event.mButton = MouseButton::ePrimary; + event.mInputSource = mozilla::dom::MouseEvent_Binding::MOZ_SOURCE_UNKNOWN; nsEventStatus status; aWindow->DispatchEvent(&event, status); @@ -169,20 +245,20 @@ class nsAutoRetainUIKitObject { WidgetTouchEvent event(true, aType, aWindow); // XXX: I think nativeEvent.timestamp * 1000 is probably usable here but // I don't care that much right now. - event.mTime = PR_IntervalNow(); event.mTouches.SetCapacity(aTouches.count); for (UITouch* touch in aTouches) { LayoutDeviceIntPoint loc = UIKitPointsToDevPixels( [touch locationInView:self], [self contentScaleFactor]); - LayoutDeviceIntPoint radius = - UIKitPointsToDevPixels([touch majorRadius], [touch majorRadius]); - void* value; - if (!CFDictionaryGetValueIfPresent(mTouches, touch, (const void**)&value)) { + LayoutDeviceIntPoint radius = UIKitPointsToDevPixels( + CGPointMake([touch majorRadius], [touch majorRadius]), + [self contentScaleFactor]); + NSNumber* value = [mTouches objectForKey:touch]; + if (value == nil) { // This shouldn't happen. NS_ASSERTION(false, "Got a touch that we didn't know about"); continue; } - int id = reinterpret_cast<int>(value); + int id = [value intValue]; RefPtr<Touch> t = new Touch(id, loc, radius, 0.0f, 1.0f); event.mRefPoint = loc; event.mTouches.AppendElement(t); @@ -190,12 +266,12 @@ class nsAutoRetainUIKitObject { aWindow->DispatchInputEvent(&event); } -- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { +- (void)touchesBegan:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event { ALOG("[ChildView[%p] touchesBegan", self); if (!mGeckoChild) return; for (UITouch* touch : touches) { - CFDictionaryAddValue(mTouches, touch, (void*)mNextTouchID); + [mTouches setObject:[NSNumber numberWithInt:mNextTouchID] forKey:touch]; mNextTouchID++; } [self sendTouchEvent:eTouchStart @@ -203,31 +279,31 @@ class nsAutoRetainUIKitObject { widget:mGeckoChild]; } -- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event { +- (void)touchesCancelled:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event { ALOG("[ChildView[%p] touchesCancelled", self); [self sendTouchEvent:eTouchCancel touches:touches widget:mGeckoChild]; for (UITouch* touch : touches) { - CFDictionaryRemoveValue(mTouches, touch); + [mTouches removeObjectForKey:touch]; } - if (CFDictionaryGetCount(mTouches) == 0) { + if (mTouches.count == 0) { mNextTouchID = 0; } } -- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { +- (void)touchesEnded:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event { ALOG("[ChildView[%p] touchesEnded", self); if (!mGeckoChild) return; [self sendTouchEvent:eTouchEnd touches:touches widget:mGeckoChild]; for (UITouch* touch : touches) { - CFDictionaryRemoveValue(mTouches, touch); + [mTouches removeObjectForKey:touch]; } - if (CFDictionaryGetCount(mTouches) == 0) { + if (mTouches.count == 0) { mNextTouchID = 0; } } -- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { +- (void)touchesMoved:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event { ALOG("[ChildView[%p] touchesMoved", self); if (!mGeckoChild) return; @@ -236,6 +312,17 @@ class nsAutoRetainUIKitObject { widget:mGeckoChild]; } +- (BOOL)canBecomeFirstResponder { + if (!mGeckoChild) { + return NO; + } + + if (mGeckoChild->IsVirtualKeyboardDisabled()) { + return NO; + } + return YES; +} + - (void)setNeedsDisplayInRect:(CGRect)aRect { if ([self isUsingMainThreadOpenGL]) { // Draw without calling drawRect. This prevent us from @@ -326,7 +413,8 @@ class nsAutoRetainUIKitObject { CGContextScaleCTM(aContext, 1.0 / scale, 1.0 / scale); CGSize viewSize = [self bounds].size; - gfx::IntSize backingSize(viewSize.width * scale, viewSize.height * scale); + gfx::IntSize backingSize(NSToIntRound(viewSize.width * scale), + NSToIntRound(viewSize.height * scale)); CGContextSaveGState(aContext); @@ -339,13 +427,12 @@ class nsAutoRetainUIKitObject { // Create Cairo objects. RefPtr<gfxQuartzSurface> targetSurface; - UniquePtrPtr<gfxContext> targetContext; + UniquePtr<gfxContext> targetContext; if (gfxPlatform::GetPlatform()->SupportsAzureContentForType( gfx::BackendType::CAIRO)) { // This is dead code unless you mess with prefs, but keep it around for // debugging. targetSurface = new gfxQuartzSurface(aContext, backingSize); - targetSurface->SetAllowUseAsSource(false); RefPtr<gfx::DrawTarget> dt = gfxPlatform::CreateDrawTargetForSurface(targetSurface, backingSize); if (!dt || !dt->IsValid()) { @@ -399,6 +486,183 @@ class nsAutoRetainUIKitObject { CGContextStrokeRect(aContext, aRect); #endif } + +// UIKeyInput + +- (void)insertText:(NSString*)text { + if (!mGeckoChild || mGeckoChild->Destroyed()) { + return; + } + widget::TextInputHandler* textInputHandler = + mGeckoChild->GetTextInputHandler(); + if (!textInputHandler) { + return; + } + textInputHandler->InsertText(text); +} + +- (void)deleteBackward { + if (!mGeckoChild || mGeckoChild->Destroyed()) { + return; + } + widget::TextInputHandler* textInputHandler = + mGeckoChild->GetTextInputHandler(); + if (!textInputHandler) { + return; + } + textInputHandler->HandleCommand(Command::DeleteCharBackward); +} + +- (BOOL)hasText { + if (!mGeckoChild || mGeckoChild->Destroyed()) { + return NO; + } + widget::InputContext context = mGeckoChild->GetInputContext(); + if (context.mIMEState.mEnabled == mozilla::widget::IMEEnabled::Disabled) { + return NO; + } + return YES; +} + +// UITextInputTraits + +- (UIKeyboardType)keyboardType { + if (!mGeckoChild || mGeckoChild->Destroyed()) { + return UIKeyboardTypeDefault; + } + return UIKitUtils::GetUIKeyboardType(mGeckoChild->GetInputContext()); +} + +- (UIReturnKeyType)returnKeyType { + if (!mGeckoChild || mGeckoChild->Destroyed()) { + return UIReturnKeyDefault; + } + return UIKitUtils::GetUIReturnKeyType(mGeckoChild->GetInputContext()); +} + +- (UITextAutocapitalizationType)autocapitalizationType { + if (!mGeckoChild || mGeckoChild->Destroyed()) { + return UITextAutocapitalizationTypeNone; + } + return UIKitUtils::GetUITextAutocapitalizationType( + mGeckoChild->GetInputContext()); +} + +- (BOOL)isSecureTextEntry { + if (!mGeckoChild || mGeckoChild->Destroyed()) { + return NO; + } + if (mGeckoChild->GetInputContext().IsPasswordEditor()) { + return YES; + } + return NO; +} + +#ifdef ACCESSIBILITY +// MUIRootAccessible + +- (id<MUIRootAccessibleProtocol>)accessible { + if (!mGeckoChild) return nil; + + id<MUIRootAccessibleProtocol> nativeAccessible = nil; + + // nsAutoRetainCocoaObject kungFuDeathGrip(self); + RefPtr<nsWindow> geckoChild(mGeckoChild); + RefPtr<a11y::LocalAccessible> accessible = geckoChild->GetRootAccessible(); + if (!accessible) return nil; + + accessible->GetNativeInterface((void**)&nativeAccessible); + + return nativeAccessible; +} + +- (BOOL)hasRepresentedView { + return YES; +} + +- (id)representedView { + return self; +} + +- (BOOL)isAccessibilityElement { + if (!mozilla::a11y::ShouldA11yBeEnabled()) { + return [super isAccessibilityElement]; + } + + return [[self accessible] isAccessibilityElement]; +} + +- (NSString*)accessibilityLabel { + if (!mozilla::a11y::ShouldA11yBeEnabled()) { + return [super accessibilityLabel]; + } + + return [[self accessible] accessibilityLabel]; +} + +- (CGRect)accessibilityFrame { + // Use the UIView implementation here. We rely on the position of this + // frame to place gecko bounds in the right offset. + return [super accessibilityFrame]; +} + +- (NSString*)accessibilityValue { + if (!mozilla::a11y::ShouldA11yBeEnabled()) { + return [super accessibilityValue]; + } + + return [[self accessible] accessibilityValue]; +} + +- (uint64_t)accessibilityTraits { + if (!mozilla::a11y::ShouldA11yBeEnabled()) { + return [super accessibilityTraits]; + } + + return [[self accessible] accessibilityTraits]; +} + +- (NSInteger)accessibilityElementCount { + if (!mozilla::a11y::ShouldA11yBeEnabled()) { + return [super accessibilityElementCount]; + } + + return [[self accessible] accessibilityElementCount]; +} + +- (nullable id)accessibilityElementAtIndex:(NSInteger)index { + if (!mozilla::a11y::ShouldA11yBeEnabled()) { + return [super accessibilityElementAtIndex:index]; + } + + return [[self accessible] accessibilityElementAtIndex:index]; +} + +- (NSInteger)indexOfAccessibilityElement:(id)element { + if (!mozilla::a11y::ShouldA11yBeEnabled()) { + return [super indexOfAccessibilityElement:element]; + } + + return [[self accessible] indexOfAccessibilityElement:element]; +} + +- (NSArray* _Nullable)accessibilityElements { + if (!mozilla::a11y::ShouldA11yBeEnabled()) { + return [super accessibilityElements]; + } + + return [[self accessible] accessibilityElements]; +} + +- (UIAccessibilityContainerType)accessibilityContainerType { + if (!mozilla::a11y::ShouldA11yBeEnabled()) { + return [super accessibilityContainerType]; + } + + return [[self accessible] accessibilityContainerType]; +} +#endif + @end nsWindow::nsWindow() @@ -442,20 +706,7 @@ nsresult nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent, if (parent == nullptr && nativeParent) parent = nativeParent->mGeckoChild; if (parent && nativeParent == nullptr) nativeParent = parent->mNativeView; - // for toplevel windows, bounds are fixed to full screen size - if (parent == nullptr) { - if (nsAppShell::gWindow == nil) { - mBounds = UIKitScreenManager::GetBounds(); - } else { - CGRect cgRect = [nsAppShell::gWindow bounds]; - mBounds.x = cgRect.origin.x; - mBounds.y = cgRect.origin.y; - mBounds.width = cgRect.size.width; - mBounds.height = cgRect.size.height; - } - } else { - mBounds = aRect; - } + mBounds = aRect; ALOG("nsWindow[%p]::Create bounds: %d %d %d %d", (void*)this, mBounds.x, mBounds.y, mBounds.width, mBounds.height); @@ -487,6 +738,8 @@ nsresult nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent, [nsAppShell::gTopLevelViews addObject:mNativeView]; } + mTextInputHandler = new widget::TextInputHandler(this); + return NS_OK; } @@ -498,6 +751,11 @@ void nsWindow::Destroy() { if (mParent) mParent->mChildren.RemoveElement(this); + if (mTextInputHandler) { + mTextInputHandler->OnDestroyed(); + } + mTextInputHandler = nullptr; + [mNativeView widgetDestroyed]; nsBaseWidget::Destroy(); @@ -507,8 +765,6 @@ void nsWindow::Destroy() { TearDownView(); nsBaseWidget::OnDestroy(); - - return NS_OK; } void nsWindow::Show(bool aState) { @@ -595,16 +851,12 @@ void nsWindow::SetSizeMode(nsSizeMode aMode) { void nsWindow::Invalidate(const LayoutDeviceIntRect& aRect) { if (!mNativeView || !mVisible) return; - MOZ_RELEASE_ASSERT( - GetLayerManager()->GetBackendType() != LayersBackend::LAYERS_WR, - "Shouldn't need to invalidate with accelerated OMTC layers!"); - [mNativeView setNeedsLayout]; [mNativeView setNeedsDisplayInRect:DevPixelsToUIKitPoints( mBounds, BackingScaleFactor())]; } -void nsWindow::SetFocus(Raise) { +void nsWindow::SetFocus(Raise, mozilla::dom::CallerType) { [[mNativeView window] makeKeyWindow]; [mNativeView becomeFirstResponder]; } @@ -649,10 +901,16 @@ void nsWindow::ReportSizeModeEvent(nsSizeMode aMode) { } void nsWindow::ReportSizeEvent() { + LayoutDeviceIntRect innerBounds = GetClientBounds(); + if (mWidgetListener) { - LayoutDeviceIntRect innerBounds = GetClientBounds(); mWidgetListener->WindowResized(this, innerBounds.width, innerBounds.height); } + + if (mAttachedWidgetListener) { + mAttachedWidgetListener->WindowResized(this, innerBounds.width, + innerBounds.height); + } } LayoutDeviceIntRect nsWindow::GetScreenBounds() { @@ -672,8 +930,8 @@ LayoutDeviceIntPoint nsWindow::WidgetToScreenOffset() { temp = [nsAppShell::gWindow convertPoint:temp toWindow:nil]; } - offset.x += temp.x; - offset.y += temp.y; + offset.x += static_cast<int32_t>(temp.x); + offset.y += static_cast<int32_t>(temp.y); return offset; } @@ -682,23 +940,63 @@ nsresult nsWindow::DispatchEvent(mozilla::WidgetGUIEvent* aEvent, nsEventStatus& aStatus) { aStatus = nsEventStatus_eIgnore; nsCOMPtr<nsIWidget> kungFuDeathGrip(aEvent->mWidget); + mozilla::Unused << kungFuDeathGrip; // Not used within this function - if (mWidgetListener) + if (mAttachedWidgetListener) { + aStatus = mAttachedWidgetListener->HandleEvent(aEvent, mUseAttachedEvents); + } else if (mWidgetListener) { aStatus = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents); + } return NS_OK; } void nsWindow::SetInputContext(const InputContext& aContext, const InputContextAction& aAction) { - // TODO: actually show VKB + NS_OBJC_BEGIN_TRY_IGNORE_BLOCK; + + const bool changingEnabledState = + aContext.IsInputAttributeChanged(mInputContext); + mInputContext = aContext; + + if (IsVirtualKeyboardDisabled()) { + [mNativeView resignFirstResponder]; + return; + } + + [mNativeView becomeFirstResponder]; + + if (aAction.UserMightRequestOpenVKB() || changingEnabledState) { + // TODO(m_kato): + // It is unnecessary to call reloadInputViews with changingEnabledState if + // virtual keyboard is disappeared. + [mNativeView reloadInputViews]; + } + + NS_OBJC_END_TRY_IGNORE_BLOCK; } -mozilla::widget::InputContext nsWindow::GetInputContext() { +widget::InputContext nsWindow::GetInputContext() { + if (!mTextInputHandler) { + InputContext context; + context.mIMEState.mEnabled = IMEEnabled::Disabled; + context.mIMEState.mOpen = IMEState::OPEN_STATE_NOT_SUPPORTED; + return context; + } return mInputContext; } +widget::TextEventDispatcherListener* +nsWindow::GetNativeTextEventDispatcherListener() { + return mTextInputHandler; +} + +bool nsWindow::IsVirtualKeyboardDisabled() const { + return mInputContext.mIMEState.mEnabled == IMEEnabled::Disabled || + mInputContext.mHTMLInputMode.EqualsLiteral("none"); +} + void nsWindow::SetBackgroundColor(const nscolor& aColor) { mNativeView.backgroundColor = [UIColor colorWithRed:NS_GET_R(aColor) green:NS_GET_G(aColor) |