summaryrefslogtreecommitdiffstats
path: root/widget/uikit
diff options
context:
space:
mode:
Diffstat (limited to 'widget/uikit')
-rw-r--r--widget/uikit/GfxInfo.cpp45
-rw-r--r--widget/uikit/GfxInfo.h21
-rw-r--r--widget/uikit/MediaKeysEventSourceFactory.cpp17
-rw-r--r--widget/uikit/TextInputHandler.h67
-rw-r--r--widget/uikit/TextInputHandler.mm254
-rw-r--r--widget/uikit/UIKitUtils.h23
-rw-r--r--widget/uikit/UIKitUtils.mm89
-rw-r--r--widget/uikit/components.conf28
-rw-r--r--widget/uikit/moz.build17
-rw-r--r--widget/uikit/nsAppShell.h4
-rw-r--r--widget/uikit/nsBidiKeyboard.h23
-rw-r--r--widget/uikit/nsBidiKeyboard.mm35
-rw-r--r--widget/uikit/nsLookAndFeel.h7
-rw-r--r--widget/uikit/nsLookAndFeel.mm46
-rw-r--r--widget/uikit/nsNativeThemeUIKit.h21
-rw-r--r--widget/uikit/nsNativeThemeUIKit.mm19
-rw-r--r--widget/uikit/nsScreenManager.h61
-rw-r--r--widget/uikit/nsScreenManager.mm104
-rw-r--r--widget/uikit/nsWidgetFactory.h21
-rw-r--r--widget/uikit/nsWidgetFactory.mm45
-rw-r--r--widget/uikit/nsWindow.h77
-rw-r--r--widget/uikit/nsWindow.mm420
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)