[iOS] Draw caps lock indicator in password fields
authordbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Nov 2018 19:10:27 +0000 (19:10 +0000)
committerdbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Nov 2018 19:10:27 +0000 (19:10 +0000)
https://bugs.webkit.org/show_bug.cgi?id=190565
<rdar://problem/45262343>

Reviewed by Dean Jackson.

Source/WebCore:

Draw the caps lock indicator in a focused password field on iOS. This makes the behavior of password
fields on iOS more closely match the behavior of password fields on Mac. For now, we only draw the
indicator when caps locks is enabled via the hardware keyboard. We will look to support the software
keyboard in a subsequent commit (see <https://bugs.webkit.org/show_bug.cgi?id=191475>).

The majority of this patch is implementing PlatformKeyboardEvent::currentCapsLockState() for iOS.
In Legacy WebKit, the implementation boils down to calling call -[::WebEvent modifierFlags]. In
Modern WebKit the UIProcess is responsible for -[::WebEvent modifierFlags] and passing it the
WebProcess to store such that invocations of PlatformKeyboardEvent::currentCapsLockState() consult
the store in the WebProcess. A smaller part of this patch is having both the legacy and modern
web views listen for keyboard availability changes so as to update the the caps lock state when
a hardware keyboard is detached or attached.

* WebCore.xcodeproj/project.pbxproj:
* page/EventHandler.cpp:
(WebCore::EventHandler::capsLockStateMayHaveChanged const): Extracted from EventHandler::internalKeyEvent()
so that it can shared between WebCore, Modern WebKit, and Legacy WebKit code.
(WebCore::EventHandler::internalKeyEvent): Modified to call capsLockStateMayHaveChanged().
* page/EventHandler.h:
* platform/cocoa/KeyEventCocoa.mm:
(WebCore::PlatformKeyboardEvent::currentCapsLockState): Moved from KeyEventMac.mm.
(WebCore::PlatformKeyboardEvent::getCurrentModifierState): Moved from KeyEventMac.mm.
* platform/ios/KeyEventIOS.mm:
(WebCore::PlatformKeyboardEvent::currentStateOfModifierKeys): Fetch the current modifier state.
(WebCore::PlatformKeyboardEvent::currentCapsLockState): Deleted; we now use the Cocoa implementation.
(WebCore::PlatformKeyboardEvent::getCurrentModifierState): Deleted; we now use the Cocoa implementation.
* platform/ios/WebEvent.h:
* platform/ios/WebEvent.mm:
(+[WebEvent modifierFlags]): Added.
* platform/mac/KeyEventMac.mm:
(WebCore::PlatformKeyboardEvent::currentCapsLockState): Deleted; moved to KeyEventCocoa.mm to be shared
by both Mac and iOS.
(WebCore::PlatformKeyboardEvent::getCurrentModifierState): Deleted; moved to KeyEventCocoa.mm to be shared
by both Mac and iOS.
* rendering/RenderThemeCocoa.h:
* rendering/RenderThemeCocoa.mm:
(WebCore::RenderThemeCocoa::shouldHaveCapsLockIndicator const): Moved from RenderThemeMac.mm.
* rendering/RenderThemeIOS.h:
* rendering/RenderThemeIOS.mm:
(WebCore::RenderThemeIOS::shouldHaveCapsLockIndicator const): Deleted.
* rendering/RenderThemeMac.h:
* rendering/RenderThemeMac.mm:
(WebCore::RenderThemeMac::shouldHaveCapsLockIndicator const): Deleted; moved to RenderThemeCocoa.mm to be
shared by both Mac and iOS.

Source/WebCore/PAL:

Forward declare some more SPI.

* pal/spi/ios/GraphicsServicesSPI.h:
* pal/spi/ios/UIKitSPI.h:

Source/WebKit:

Notify the WebContent process with the current modifer state on window activation changes. Notify
the WebContent process when hardware keyboard availability changes (e.g. a keyboard is attached).

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _initializeWithConfiguration:]): Register for hardware keyboard availability changed notifications.
(-[WKWebView dealloc]): Unregister from hardware availability changed notifications.
(hardwareKeyboardAvailabilityChangedCallback): Added.
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::updateCurrentModifierState): Compile this code when building for iOS.
* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _handleKeyUIEvent:]): Update the current modifier state if this event is a hardware
keyboard flags changed event.
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::hardwareKeyboardAvailabilityChanged): Added.

* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::hardwareKeyboardAvailabilityChanged):
Added new message HardwareKeyboardAvailabilityChanged. Notify the focused HTML input element (if we have
one) that the caps lock state may have changed when we receive message HardwareKeyboardAvailabilityChanged
so that we toggle visibility of the caps lock indicator.

Source/WebKitLegacy/mac:

Update the caps lock state when a hardware keyboard is attached or detached.

* WebView/WebHTMLView.mm:
(hardwareKeyboardAvailabilityChangedCallback): Added.
(-[WebHTMLView initWithFrame:]): Register for hardware keyboard availability changed notifications.
(-[WebHTMLView dealloc]): Unregister from hardware keyboard availability changed notifications.

WebKitLibraries:

Expose some more symbols.

* WebKitPrivateFrameworkStubs/iOS/12/GraphicsServices.framework/GraphicsServices.tbd:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238047 268f45cc-cd09-0410-ab3c-d52691b4dbfc

31 files changed:
Source/WebCore/ChangeLog
Source/WebCore/PAL/ChangeLog
Source/WebCore/PAL/pal/spi/ios/GraphicsServicesSPI.h
Source/WebCore/PAL/pal/spi/ios/UIKitSPI.h
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/page/EventHandler.cpp
Source/WebCore/page/EventHandler.h
Source/WebCore/platform/cocoa/KeyEventCocoa.mm
Source/WebCore/platform/ios/KeyEventIOS.mm
Source/WebCore/platform/ios/WebEvent.h
Source/WebCore/platform/ios/WebEvent.mm
Source/WebCore/platform/mac/KeyEventMac.mm
Source/WebCore/rendering/RenderThemeCocoa.h
Source/WebCore/rendering/RenderThemeCocoa.mm
Source/WebCore/rendering/RenderThemeIOS.h
Source/WebCore/rendering/RenderThemeIOS.mm
Source/WebCore/rendering/RenderThemeMac.h
Source/WebCore/rendering/RenderThemeMac.mm
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/WebPage.messages.in
Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm
Source/WebKitLegacy/mac/ChangeLog
Source/WebKitLegacy/mac/WebView/WebHTMLView.mm
WebKitLibraries/ChangeLog
WebKitLibraries/WebKitPrivateFrameworkStubs/iOS/12/GraphicsServices.framework/GraphicsServices.tbd

index edb8fde..8683e87 100644 (file)
@@ -1,3 +1,56 @@
+2018-11-09  Daniel Bates  <dabates@apple.com>
+
+        [iOS] Draw caps lock indicator in password fields
+        https://bugs.webkit.org/show_bug.cgi?id=190565
+        <rdar://problem/45262343>
+
+        Reviewed by Dean Jackson.
+
+        Draw the caps lock indicator in a focused password field on iOS. This makes the behavior of password
+        fields on iOS more closely match the behavior of password fields on Mac. For now, we only draw the
+        indicator when caps locks is enabled via the hardware keyboard. We will look to support the software
+        keyboard in a subsequent commit (see <https://bugs.webkit.org/show_bug.cgi?id=191475>).
+
+        The majority of this patch is implementing PlatformKeyboardEvent::currentCapsLockState() for iOS.
+        In Legacy WebKit, the implementation boils down to calling call -[::WebEvent modifierFlags]. In
+        Modern WebKit the UIProcess is responsible for -[::WebEvent modifierFlags] and passing it the
+        WebProcess to store such that invocations of PlatformKeyboardEvent::currentCapsLockState() consult
+        the store in the WebProcess. A smaller part of this patch is having both the legacy and modern
+        web views listen for keyboard availability changes so as to update the the caps lock state when
+        a hardware keyboard is detached or attached.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::capsLockStateMayHaveChanged const): Extracted from EventHandler::internalKeyEvent()
+        so that it can shared between WebCore, Modern WebKit, and Legacy WebKit code.
+        (WebCore::EventHandler::internalKeyEvent): Modified to call capsLockStateMayHaveChanged().
+        * page/EventHandler.h:
+        * platform/cocoa/KeyEventCocoa.mm:
+        (WebCore::PlatformKeyboardEvent::currentCapsLockState): Moved from KeyEventMac.mm.
+        (WebCore::PlatformKeyboardEvent::getCurrentModifierState): Moved from KeyEventMac.mm.
+        * platform/ios/KeyEventIOS.mm:
+        (WebCore::PlatformKeyboardEvent::currentStateOfModifierKeys): Fetch the current modifier state.
+        (WebCore::PlatformKeyboardEvent::currentCapsLockState): Deleted; we now use the Cocoa implementation.
+        (WebCore::PlatformKeyboardEvent::getCurrentModifierState): Deleted; we now use the Cocoa implementation.
+        * platform/ios/WebEvent.h:
+        * platform/ios/WebEvent.mm:
+        (+[WebEvent modifierFlags]): Added.
+        * platform/mac/KeyEventMac.mm:
+        (WebCore::PlatformKeyboardEvent::currentCapsLockState): Deleted; moved to KeyEventCocoa.mm to be shared
+        by both Mac and iOS.
+        (WebCore::PlatformKeyboardEvent::getCurrentModifierState): Deleted; moved to KeyEventCocoa.mm to be shared
+        by both Mac and iOS.
+        * rendering/RenderThemeCocoa.h:
+        * rendering/RenderThemeCocoa.mm:
+        (WebCore::RenderThemeCocoa::shouldHaveCapsLockIndicator const): Moved from RenderThemeMac.mm.
+        * rendering/RenderThemeIOS.h:
+        * rendering/RenderThemeIOS.mm:
+        (WebCore::RenderThemeIOS::shouldHaveCapsLockIndicator const): Deleted.
+        * rendering/RenderThemeMac.h:
+        * rendering/RenderThemeMac.mm:
+        (WebCore::RenderThemeMac::shouldHaveCapsLockIndicator const): Deleted; moved to RenderThemeCocoa.mm to be
+        shared by both Mac and iOS.
+
 2018-11-09  Chris Dumez  <cdumez@apple.com>
 
         Unreviewed attempt to fix WinCairo build after r238039.
index b4f407d..acd8f0a 100644 (file)
@@ -1,3 +1,16 @@
+2018-11-09  Daniel Bates  <dabates@apple.com>
+
+        [iOS] Draw caps lock indicator in password fields
+        https://bugs.webkit.org/show_bug.cgi?id=190565
+        <rdar://problem/45262343>
+
+        Reviewed by Dean Jackson.
+
+        Forward declare some more SPI.
+
+        * pal/spi/ios/GraphicsServicesSPI.h:
+        * pal/spi/ios/UIKitSPI.h:
+
 2018-11-08  Megan Gardner  <megan_gardner@apple.com>
 
         Adopt Reveal Framework to replace Lookup
index 1cc8b31..1b5bd97 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -43,6 +43,12 @@ CFStringRef GSSystemRootDirectory(void);
 void GSFontInitialize(void);
 void GSFontPurgeFontCache(void);
 
+typedef struct __GSKeyboard* GSKeyboardRef;
+uint32_t GSKeyboardGetModifierState(GSKeyboardRef);
+Boolean GSEventIsHardwareKeyboardAttached();
+
+extern const char *kGSEventHardwareKeyboardAvailabilityChangedNotification;
+
 WTF_EXTERN_C_END
 
 #endif
index 7c94714..1a87af5 100644 (file)
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+WTF_EXTERN_C_BEGIN
+typedef struct __GSKeyboard* GSKeyboardRef;
+WTF_EXTERN_C_END
+
 #if USE(APPLE_INTERNAL_SDK)
 
 #import <UIKit/NSParagraphStyle_Private.h>
@@ -44,6 +48,7 @@
 
 @interface UIApplication ()
 + (UIApplicationSceneClassicMode)_classicMode;
+- (GSKeyboardRef)_hardwareKeyboard;
 @end
 
 #else
@@ -75,10 +80,9 @@ typedef NS_ENUM(NSInteger, UIApplicationSceneClassicMode) {
 @end
 
 @interface UIApplication ()
-
 - (BOOL)_isClassic;
 + (UIApplicationSceneClassicMode)_classicMode;
-
+- (GSKeyboardRef)_hardwareKeyboard;
 @end
 
 @interface UIColor ()
index 15d6aa8..ca0f990 100644 (file)
                CE2849881CA3614600B4A57F /* ContentSecurityPolicyDirectiveNames.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ContentSecurityPolicyDirectiveNames.cpp; path = csp/ContentSecurityPolicyDirectiveNames.cpp; sourceTree = "<group>"; };
                CE5CB1B314EDAB6F00BB2795 /* EventSender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventSender.h; sourceTree = "<group>"; };
                CE5FA253209E48C50051D700 /* ContentSecurityPolicyClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ContentSecurityPolicyClient.h; path = csp/ContentSecurityPolicyClient.h; sourceTree = "<group>"; };
+               CE68C8FF21924EE5001230B3 /* PlatformKeyboardEvent.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformKeyboardEvent.cpp; sourceTree = "<group>"; };
                CE6D89294C7AACE0AD89B3DD /* MathMLMencloseElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MathMLMencloseElement.h; sourceTree = "<group>"; };
                CE6DADF71C591E6A003F6A88 /* ContentSecurityPolicyResponseHeaders.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ContentSecurityPolicyResponseHeaders.cpp; path = csp/ContentSecurityPolicyResponseHeaders.cpp; sourceTree = "<group>"; };
                CE6DADF81C591E6A003F6A88 /* ContentSecurityPolicyResponseHeaders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContentSecurityPolicyResponseHeaders.h; path = csp/ContentSecurityPolicyResponseHeaders.h; sourceTree = "<group>"; };
                                A14978701ABAF3A500CEF7E4 /* PlatformContentFilter.h */,
                                BC5C76291497FE1400BC4775 /* PlatformEvent.h */,
                                A723F77A1484CA4C008C6DBE /* PlatformExportMacros.h */,
+                               CE68C8FF21924EE5001230B3 /* PlatformKeyboardEvent.cpp */,
                                935C476609AC4D4300A6AAB4 /* PlatformKeyboardEvent.h */,
                                935C476709AC4D4300A6AAB4 /* PlatformMouseEvent.h */,
                                C5BAC16F14E30E4700008837 /* PlatformPasteboard.h */,
index b80b768..ffd4607 100644 (file)
@@ -3162,6 +3162,14 @@ bool EventHandler::keyEvent(const PlatformKeyboardEvent& keyEvent)
     return wasHandled;
 }
 
+void EventHandler::capsLockStateMayHaveChanged() const
+{
+    auto* focusedElement = m_frame.document()->focusedElement();
+    if (!is<HTMLInputElement>(focusedElement))
+        return;
+    downcast<HTMLInputElement>(*focusedElement).capsLockStateMayHaveChanged();
+}
+
 bool EventHandler::internalKeyEvent(const PlatformKeyboardEvent& initialKeyEvent)
 {
     Ref<Frame> protectedFrame(m_frame);
@@ -3194,12 +3202,8 @@ bool EventHandler::internalKeyEvent(const PlatformKeyboardEvent& initialKeyEvent
     }
 #endif
 
-    if (initialKeyEvent.windowsVirtualKeyCode() == VK_CAPITAL) {
-        if (auto* element = m_frame.document()->focusedElement()) {
-            if (is<HTMLInputElement>(*element))
-                downcast<HTMLInputElement>(*element).capsLockStateMayHaveChanged();
-        }
-    }
+    if (initialKeyEvent.windowsVirtualKeyCode() == VK_CAPITAL)
+        capsLockStateMayHaveChanged();
 
 #if ENABLE(PAN_SCROLLING)
     if (m_frame.mainFrame().eventHandler().panScrollInProgress()) {
index f5fe08f..92fbc5a 100644 (file)
@@ -256,6 +256,7 @@ public:
     WEBCORE_EXPORT bool handleAccessKey(const PlatformKeyboardEvent&);
     WEBCORE_EXPORT bool keyEvent(const PlatformKeyboardEvent&);
     void defaultKeyboardEventHandler(KeyboardEvent&);
+    WEBCORE_EXPORT void capsLockStateMayHaveChanged() const;
 
     bool accessibilityPreventsEventPropagation(KeyboardEvent&);
     WEBCORE_EXPORT void handleKeyboardSelectionMovementForAccessibility(KeyboardEvent&);
index 631dd14..b3e04f2 100644 (file)
@@ -27,6 +27,7 @@
 #import "KeyEventCocoa.h"
 
 #import "Logging.h"
+#import "PlatformKeyboardEvent.h"
 #import "WindowsKeyboardCodes.h"
 #import <wtf/ASCIICType.h>
 #import <wtf/text/WTFString.h>
@@ -39,6 +40,20 @@ using namespace WTF;
 
 namespace WebCore {
 
+bool PlatformKeyboardEvent::currentCapsLockState()
+{
+    return currentStateOfModifierKeys().contains(PlatformEvent::Modifier::CapsLockKey);
+}
+
+void PlatformKeyboardEvent::getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey)
+{
+    auto currentModifiers = currentStateOfModifierKeys();
+    shiftKey = currentModifiers.contains(PlatformEvent::Modifier::ShiftKey);
+    ctrlKey = currentModifiers.contains(PlatformEvent::Modifier::CtrlKey);
+    altKey = currentModifiers.contains(PlatformEvent::Modifier::AltKey);
+    metaKey = currentModifiers.contains(PlatformEvent::Modifier::MetaKey);
+}
+
 // https://w3c.github.io/uievents-key/
 String keyForCharCode(unichar charCode)
 {
index 19ca9bf..9bd57e7 100644 (file)
 #import "KeyEventCocoa.h"
 #import "KeyEventCodesIOS.h"
 #import "NotImplemented.h"
+#import "WebEvent.h"
 #import "WindowsKeyboardCodes.h"
 #import <pal/spi/cocoa/IOKitSPI.h>
+#import <wtf/MainThread.h>
 
 using namespace WTF;
 
@@ -312,19 +314,29 @@ void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardCom
     }
 }
 
-bool PlatformKeyboardEvent::currentCapsLockState()
+OptionSet<PlatformEvent::Modifier> PlatformKeyboardEvent::currentStateOfModifierKeys()
 {
-    notImplemented();
-    return false;
-}
+    // s_currentModifiers is only set in the WebContent process, not in the UI process.
+    if (s_currentModifiers) {
+        ASSERT(isMainThread());
+        return *s_currentModifiers;
+    }
 
-void PlatformKeyboardEvent::getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey)
-{
-    notImplemented();
-    shiftKey = false;
-    ctrlKey = false;
-    altKey = false;
-    metaKey = false;
+    ::WebEventFlags currentModifiers = [::WebEvent modifierFlags];
+
+    OptionSet<PlatformEvent::Modifier> modifiers;
+    if (currentModifiers & ::WebEventFlagMaskShiftKey)
+        modifiers.add(PlatformEvent::Modifier::ShiftKey);
+    if (currentModifiers & ::WebEventFlagMaskControlKey)
+        modifiers.add(PlatformEvent::Modifier::CtrlKey);
+    if (currentModifiers & ::WebEventFlagMaskOptionKey)
+        modifiers.add(PlatformEvent::Modifier::AltKey);
+    if (currentModifiers & ::WebEventFlagMaskCommandKey)
+        modifiers.add(PlatformEvent::Modifier::MetaKey);
+    if (currentModifiers & ::WebEventFlagMaskLeftCapsLockKey)
+        modifiers.add(PlatformEvent::Modifier::CapsLockKey);
+
+    return modifiers;
 }
 
 }
index 3bd36bf..224a07e 100644 (file)
@@ -216,6 +216,8 @@ WEBCORE_EXPORT @interface WebEvent : NSObject {
 
 @property(nonatomic) BOOL wasHandled;
 
+@property (class, readonly) WebEventFlags modifierFlags;
+
 @end
 
 #endif // TARGET_OS_IPHONE
index e678e9e..a6bd733 100644 (file)
 #import "KeyEventCodesIOS.h"
 #import "WAKAppKitStubs.h"
 #import <pal/spi/cocoa/IOKitSPI.h>
+#import <pal/spi/ios/GraphicsServicesSPI.h>
+#import <pal/spi/ios/UIKitSPI.h>
+#import <wtf/SoftLinking.h>
+
+SOFT_LINK_FRAMEWORK(UIKit)
+SOFT_LINK_CLASS(UIKit, UIApplication);
+
+#define UIApplication getUIApplicationClass()
 
 using WebCore::windowsKeyCodeForKeyCode;
 using WebCore::windowsKeyCodeForCharCode;
@@ -491,6 +499,11 @@ static NSString *normalizedStringWithAppKitCompatibilityMapping(NSString *charac
     return _gestureRotation;
 }
 
++ (WebEventFlags)modifierFlags
+{
+    return GSEventIsHardwareKeyboardAttached() ? GSKeyboardGetModifierState([UIApplication sharedApplication]._hardwareKeyboard) : 0;
+}
+
 @end
 
 #endif // PLATFORM(IOS_FAMILY)
index b08a53e..2bcb510 100644 (file)
@@ -258,21 +258,6 @@ void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardCom
     }
 }
 
-bool PlatformKeyboardEvent::currentCapsLockState()
-{
-    auto currentModifiers = currentStateOfModifierKeys();
-    return currentModifiers.contains(PlatformEvent::Modifier::CapsLockKey);
-}
-
-void PlatformKeyboardEvent::getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey)
-{
-    auto currentModifiers = currentStateOfModifierKeys();
-    shiftKey = currentModifiers.contains(PlatformEvent::Modifier::ShiftKey);
-    ctrlKey = currentModifiers.contains(PlatformEvent::Modifier::CtrlKey);
-    altKey = currentModifiers.contains(PlatformEvent::Modifier::AltKey);
-    metaKey = currentModifiers.contains(PlatformEvent::Modifier::MetaKey);
-}
-
 OptionSet<PlatformEvent::Modifier> PlatformKeyboardEvent::currentStateOfModifierKeys()
 {
 #if ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
index a464c10..f188742 100644 (file)
@@ -36,6 +36,8 @@ namespace WebCore {
 
 class RenderThemeCocoa : public RenderTheme {
 private:
+    bool shouldHaveCapsLockIndicator(const HTMLInputElement&) const final;
+
 #if ENABLE(APPLE_PAY)
     void adjustApplePayButtonStyle(StyleResolver&, RenderStyle&, const Element*) const override;
     bool paintApplePayButton(const RenderObject&, const PaintInfo&, const IntRect&) override;
index feacfc5..b4aaf64 100644 (file)
@@ -27,6 +27,7 @@
 #import "RenderThemeCocoa.h"
 
 #import "GraphicsContextCG.h"
+#import "HTMLInputElement.h"
 #import "RenderText.h"
 
 #if ENABLE(APPLE_PAY)
@@ -51,6 +52,11 @@ SOFT_LINK_MAY_FAIL(PassKit, PKDrawApplePayButton, void, (CGContextRef context, C
 
 namespace WebCore {
 
+bool RenderThemeCocoa::shouldHaveCapsLockIndicator(const HTMLInputElement& element) const
+{
+    return element.isPasswordField();
+}
+
 #if ENABLE(APPLE_PAY)
 
 static const auto applePayButtonMinimumWidth = 140;
index ca8c0ba..a5a30ac 100644 (file)
@@ -117,7 +117,6 @@ protected:
 #endif
 
     bool shouldHaveSpinButton(const HTMLInputElement&) const override;
-    bool shouldHaveCapsLockIndicator(const HTMLInputElement&) const override;
 
 #if ENABLE(VIDEO)
     String mediaControlsStyleSheet() override;
index 1d17aea..52b4d74 100644 (file)
@@ -1135,11 +1135,6 @@ bool RenderThemeIOS::shouldHaveSpinButton(const HTMLInputElement&) const
     return false;
 }
 
-bool RenderThemeIOS::shouldHaveCapsLockIndicator(const HTMLInputElement&) const
-{
-    return false;
-}
-
 FontCascadeDescription& RenderThemeIOS::cachedSystemFontDescription(CSSValueID valueID) const
 {
     static NeverDestroyed<FontCascadeDescription> systemFont;
index 1dd2b1f..b74344c 100644 (file)
@@ -164,8 +164,6 @@ private:
     bool supportsClosedCaptioning() const final { return true; }
 #endif
 
-    bool shouldHaveCapsLockIndicator(const HTMLInputElement&) const final;
-
     bool paintSnapshottedPluginOverlay(const RenderObject&, const PaintInfo&, const IntRect&) final;
 
 #if ENABLE(ATTACHMENT_ELEMENT)
index d550e5b..94d4ded 100644 (file)
@@ -2342,11 +2342,6 @@ void RenderThemeMac::adjustSliderThumbSize(RenderStyle& style, const Element*) c
     }
 }
 
-bool RenderThemeMac::shouldHaveCapsLockIndicator(const HTMLInputElement& element) const
-{
-    return element.isPasswordField();
-}
-
 NSPopUpButtonCell* RenderThemeMac::popupButton() const
 {
     if (!m_popupButton) {
index cc43147..4d8817b 100644 (file)
@@ -1,3 +1,35 @@
+2018-11-09  Daniel Bates  <dabates@apple.com>
+
+        [iOS] Draw caps lock indicator in password fields
+        https://bugs.webkit.org/show_bug.cgi?id=190565
+        <rdar://problem/45262343>
+
+        Reviewed by Dean Jackson.
+
+        Notify the WebContent process with the current modifer state on window activation changes. Notify
+        the WebContent process when hardware keyboard availability changes (e.g. a keyboard is attached).
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _initializeWithConfiguration:]): Register for hardware keyboard availability changed notifications.
+        (-[WKWebView dealloc]): Unregister from hardware availability changed notifications.
+        (hardwareKeyboardAvailabilityChangedCallback): Added.
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::updateCurrentModifierState): Compile this code when building for iOS.
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _handleKeyUIEvent:]): Update the current modifier state if this event is a hardware
+        keyboard flags changed event.
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::hardwareKeyboardAvailabilityChanged): Added.
+
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::hardwareKeyboardAvailabilityChanged):
+        Added new message HardwareKeyboardAvailabilityChanged. Notify the focused HTML input element (if we have
+        one) that the caps lock state may have changed when we receive message HardwareKeyboardAvailabilityChanged
+        so that we toggle visibility of the caps lock indicator.
+
 2018-11-09  Tim Horton  <timothy_horton@apple.com>
 
         Make use of _UIRemoteView instead of CALayerHost if possible for WKRemoteView
index 448f932..4b05f9c 100644 (file)
 #import <WebCore/WebSQLiteDatabaseTrackerClient.h>
 #import <pal/spi/cg/CoreGraphicsSPI.h>
 #import <pal/spi/cocoa/QuartzCoreSPI.h>
+#import <pal/spi/ios/GraphicsServicesSPI.h>
 #import <wtf/cocoa/Entitlements.h>
 
 #define RELEASE_LOG_IF_ALLOWED(...) RELEASE_LOG_IF(_page && _page->isAlwaysOnLoggingAllowed(), ViewState, __VA_ARGS__)
@@ -705,6 +706,8 @@ static void validate(WKWebViewConfiguration *configuration)
 
     [[_configuration _contentProviderRegistry] addPage:*_page];
     _page->setForceAlwaysUserScalable([_configuration ignoresViewportScaleLimits]);
+
+    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge const void *)(self), hardwareKeyboardAvailabilityChangedCallback, (CFStringRef)[NSString stringWithUTF8String:kGSEventHardwareKeyboardAvailabilityChangedNotification], nullptr, CFNotificationSuspensionBehaviorCoalesce);
 #endif
 
 #if PLATFORM(MAC)
@@ -842,6 +845,8 @@ static void validate(WKWebViewConfiguration *configuration)
     [[_configuration _contentProviderRegistry] removePage:*_page];
     [[NSNotificationCenter defaultCenter] removeObserver:self];
     [_scrollView setInternalDelegate:nil];
+
+    CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge const void *)(self), (CFStringRef)[NSString stringWithUTF8String:kGSEventHardwareKeyboardAvailabilityChangedNotification], nullptr);
 #endif
 
 #if ENABLE(ACCESSIBILITY_EVENTS)
@@ -3102,6 +3107,13 @@ static int32_t activeOrientation(WKWebView *webView)
     [self _keyboardChangedWithInfo:notification.userInfo adjustScrollView:YES];
 }
 
+static void hardwareKeyboardAvailabilityChangedCallback(CFNotificationCenterRef, void* observer, CFStringRef, const void*, CFDictionaryRef)
+{
+    ASSERT(observer);
+    WKWebView *webView = (__bridge WKWebView *)observer;
+    webView._page->hardwareKeyboardAvailabilityChanged();
+}
+
 - (void)_windowDidRotate:(NSNotification *)notification
 {
     if (!_overridesInterfaceOrientation)
index 35cece5..8b72b3e 100644 (file)
@@ -8132,7 +8132,7 @@ void WebPageProxy::getIsViewVisible(bool& result)
 
 void WebPageProxy::updateCurrentModifierState()
 {
-#if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
+#if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING) || PLATFORM(IOS_FAMILY)
     auto modifiers = PlatformKeyboardEvent::currentStateOfModifierKeys();
     m_process->send(Messages::WebPage::UpdateCurrentModifierState(modifiers), m_pageID);
 #endif
index 29bddcb..615a08d 100644 (file)
@@ -645,6 +645,7 @@ public:
     void storeSelectionForAccessibility(bool);
     void startAutoscrollAtPosition(const WebCore::FloatPoint& positionInWindow);
     void cancelAutoscroll();
+    void hardwareKeyboardAvailabilityChanged();
 #if ENABLE(DATA_INTERACTION)
     void didHandleStartDataInteractionRequest(bool started);
     void didHandleAdditionalDragItemsRequest(bool added);
@@ -1365,6 +1366,8 @@ public:
     void didCloseSuggestions();
 #endif
 
+    void updateCurrentModifierState();
+
 private:
     WebPageProxy(PageClient&, WebProcessProxy&, uint64_t pageID, Ref<API::PageConfiguration>&&);
     void platformInitialize();
@@ -1847,8 +1850,6 @@ private:
     void stopDisplayLink(unsigned observerID);
 #endif
 
-    void updateCurrentModifierState();
-
     void reportPageLoadResult(const WebCore::ResourceError& = { });
 
     void continueNavigationInNewProcess(API::Navigation&, Ref<WebProcessProxy>&&);
index ee5dff8..c806e10 100644 (file)
@@ -3756,9 +3756,13 @@ static NSString *contentTypeFromFieldName(WebCore::AutofillFieldName fieldName)
 
 - (void)_handleKeyUIEvent:(::UIEvent *)event
 {
+    bool isHardwareKeyboardEvent = !!event._hidEvent;
+    if (isHardwareKeyboardEvent && ((UIPhysicalKeyboardEvent *)event)._inputFlags & kUIKeyboardInputModifierFlagsChanged)
+        _page->updateCurrentModifierState();
+
     // We only want to handle key event from the hardware keyboard when we are
     // first responder and we are not interacting with editable content.
-    if ([self isFirstResponder] && event._hidEvent && !_page->editorState().isContentEditable) {
+    if ([self isFirstResponder] && isHardwareKeyboardEvent && !_page->editorState().isContentEditable) {
         [self handleKeyEvent:event];
         return;
     }
index 3865884..3dc7fb4 100644 (file)
@@ -1089,6 +1089,12 @@ void WebPageProxy::setIsScrollingOrZooming(bool isScrollingOrZooming)
         m_validationBubble->show();
 }
 
+void WebPageProxy::hardwareKeyboardAvailabilityChanged()
+{
+    updateCurrentModifierState();
+    m_process->send(Messages::WebPage::HardwareKeyboardAvailabilityChanged(), m_pageID);
+}
+
 #if ENABLE(DATA_INTERACTION)
 
 void WebPageProxy::didHandleStartDataInteractionRequest(bool started)
index 4076ea7..99f4424 100644 (file)
@@ -913,6 +913,8 @@ public:
 
     bool platformPrefersTextLegibilityBasedZoomScaling() const;
     const WebCore::ViewportConfiguration& viewportConfiguration() const { return m_viewportConfiguration; }
+
+    void hardwareKeyboardAvailabilityChanged();
 #endif
 
 #if ENABLE(IOS_TOUCH_EVENTS)
index fd430d6..7626fbb 100644 (file)
@@ -106,6 +106,7 @@ messages -> WebPage LegacyReceiver {
     StartAutoscrollAtPosition(WebCore::FloatPoint positionInWindow)
     CancelAutoscroll()
     RequestAssistedNodeInformation(WebKit::CallbackID callbackID)
+    HardwareKeyboardAvailabilityChanged()
 #endif
 
     SetControlledByAutomation(bool controlled)
index 3ad9ace..ef3a5f3 100644 (file)
@@ -3087,6 +3087,12 @@ String WebPage::platformUserAgent(const URL&) const
     return String();
 }
 
+void WebPage::hardwareKeyboardAvailabilityChanged()
+{
+    if (auto* focusedFrame = m_page->focusController().focusedFrame())
+        focusedFrame->eventHandler().capsLockStateMayHaveChanged();
+}
+
 #if USE(QUICK_LOOK)
 void WebPage::didReceivePasswordForQuickLookDocument(const String& password)
 {
index a03a78a..2253843 100644 (file)
@@ -1,5 +1,20 @@
 2018-11-09  Daniel Bates  <dabates@apple.com>
 
+        [iOS] Draw caps lock indicator in password fields
+        https://bugs.webkit.org/show_bug.cgi?id=190565
+        <rdar://problem/45262343>
+
+        Reviewed by Dean Jackson.
+
+        Update the caps lock state when a hardware keyboard is attached or detached.
+
+        * WebView/WebHTMLView.mm:
+        (hardwareKeyboardAvailabilityChangedCallback): Added.
+        (-[WebHTMLView initWithFrame:]): Register for hardware keyboard availability changed notifications.
+        (-[WebHTMLView dealloc]): Unregister from hardware keyboard availability changed notifications.
+
+2018-11-09  Daniel Bates  <dabates@apple.com>
+
         [iOS] Pressing forward delete key in text field does nothing and we should not invoke an editor
         action when forward delete is pressed outside a text field
         https://bugs.webkit.org/show_bug.cgi?id=190566
index 734fd02..c4e2d41 100644 (file)
 #import <WebCore/WAKScrollView.h>
 #import <WebCore/WAKWindow.h>
 #import <WebCore/WKGraphics.h>
+#import <WebCore/WebCoreThreadRun.h>
 #import <WebCore/WebEvent.h>
+#import <pal/spi/ios/GraphicsServicesSPI.h>
 #endif
 
 using namespace WebCore;
@@ -814,6 +816,16 @@ static CachedImageClient& promisedDataClient()
 
 #if PLATFORM(IOS_FAMILY)
 static NSString * const WebMarkedTextUpdatedNotification = @"WebMarkedTextUpdated";
+
+static void hardwareKeyboardAvailabilityChangedCallback(CFNotificationCenterRef, void* observer, CFStringRef, const void*, CFDictionaryRef)
+{
+    ASSERT(observer);
+    WebThreadRun(^{
+        WebHTMLView *webView = (__bridge WebHTMLView *)observer;
+        if (Frame* coreFrame = core([webView _frame]))
+            coreFrame->eventHandler().capsLockStateMayHaveChanged();
+    });
+}
 #endif
 
 @interface WebHTMLView (WebHTMLViewFileInternal)
@@ -2610,6 +2622,7 @@ ALLOW_DEPRECATED_DECLARATIONS_END
     [[NSNotificationCenter defaultCenter] 
             addObserver:self selector:@selector(markedTextUpdate:) 
                    name:WebMarkedTextUpdatedNotification object:nil];
+    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge const void *)(self), hardwareKeyboardAvailabilityChangedCallback, (CFStringRef)[NSString stringWithUTF8String:kGSEventHardwareKeyboardAvailabilityChangedNotification], nullptr, CFNotificationSuspensionBehaviorCoalesce);
 #endif
 
 #if PLATFORM(MAC)
@@ -2626,6 +2639,7 @@ ALLOW_DEPRECATED_DECLARATIONS_END
 
 #if PLATFORM(IOS_FAMILY)
     [[NSNotificationCenter defaultCenter] removeObserver:self name:WebMarkedTextUpdatedNotification object:nil];
+    CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge const void *)(self), (CFStringRef)[NSString stringWithUTF8String:kGSEventHardwareKeyboardAvailabilityChangedNotification], nullptr);
 #endif
 
     // We can't assert that close has already been called because
index 0db108f..cdd3a8b 100644 (file)
@@ -1,3 +1,15 @@
+2018-11-09  Daniel Bates  <dabates@apple.com>
+
+        [iOS] Draw caps lock indicator in password fields
+        https://bugs.webkit.org/show_bug.cgi?id=190565
+        <rdar://problem/45262343>
+
+        Reviewed by Dean Jackson.
+
+        Expose some more symbols.
+
+        * WebKitPrivateFrameworkStubs/iOS/12/GraphicsServices.framework/GraphicsServices.tbd:
+
 2018-06-27  Jonathan Bedard  <jbedard@apple.com>
 
         Enable WebKit iOS 12 build
index ab1c406..d354324 100644 (file)
@@ -15,10 +15,13 @@ exports:
       - x86_64
     symbols:
       - _GSCurrentEventTimestamp
+      - _GSEventIsHardwareKeyboardAttached
       - _GSFontInitialize
       - _GSFontPurgeFontCache
       - _GSInitialize
+      - _GSKeyboardGetModifierState
       - _GSSystemRootDirectory
+      - _kGSEventHardwareKeyboardAvailabilityChangedNotification
 install-name: /System/Library/PrivateFrameworks/GraphicsServices.framework/GraphicsServices
 objc-constraint: none
 platform: ios