Changeset 288728 in webkit


Ignore:
Timestamp:
Jan 27, 2022 11:02:29 PM (6 months ago)
Author:
graouts@webkit.org
Message:

[Model] Allow disabling interaction
https://bugs.webkit.org/show_bug.cgi?id=227621
<rdar://problem/80079703>

Reviewed by Darin Adler.

Source/WebCore:

We add support for the "interactive" IDL property and HTML attribute as discussed
in the <model> explainer at https://github.com/WebKit/explainers/tree/main/model.

If the "interactive" property is "true", then the HTML "interactive" attribute is
set on the element. If the property is "false", then the HTML attribute is absent.

Likewise, if the HTML attribute is present, the property returns "true". If the
HTML attribute is midding, the property returns "false".

Note that the value held by the HTML attribute is not taken into account, its mere
presence is all that is required.

Based on the value of the "interactive" property, we either disable or enable
interaction. On macOS, we check the property in HTMLModelElement::defaultEventHandler()
while on iOS, where dragging is performed entirely in the UI process, we use the
new ModelPlayer::setInteractionEnabled() method.

By default, interaction is disabled.

Tests: model-element/model-element-interactive-dragging.html

model-element/model-element-interactive.html

  • Modules/model-element/HTMLModelElement.cpp:

(WebCore::HTMLModelElement::isInteractive const):
(WebCore::HTMLModelElement::attributeChanged):
(WebCore::HTMLModelElement::defaultEventHandler):

  • Modules/model-element/HTMLModelElement.h:
  • Modules/model-element/HTMLModelElement.idl:
  • Modules/model-element/ModelPlayer.cpp:

(WebCore::ModelPlayer::setInteractionEnabled):

  • Modules/model-element/ModelPlayer.h:
  • html/HTMLAttributeNames.in:

Source/WebKit:

Override the new ModelPlayer::setInteractionEnabled() method for the iOS flavor
and send the value up to the UI process such that it may set the matching value
for UIView.userInteractionEnabled on the matching WKModelView.

  • UIProcess/Cocoa/ModelElementControllerCocoa.mm:

(WebKit::ModelElementController::setInteractionEnabledForModelElement):

  • UIProcess/ModelElementController.h:
  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::modelElementSetInteractionEnabled):

  • UIProcess/WebPageProxy.h:
  • UIProcess/WebPageProxy.messages.in:
  • UIProcess/ios/WKModelView.mm:

(-[WKModelView initWithModel:]):

  • WebProcess/Model/ios/ARKitInlinePreviewModelPlayerIOS.h:
  • WebProcess/Model/ios/ARKitInlinePreviewModelPlayerIOS.mm:

(WebKit::ARKitInlinePreviewModelPlayerIOS::setInteractionEnabled):

LayoutTests:

Add two new tests:

  • model-element/model-element-interactive.html tests the "interactive" IDL property

and the "interactive" HTML attribute,

  • model-element/model-element-interactive-dragging.html tests that the "interactive"

IDL property correctly disables setting the camera by dragging when "false", and allows
it when "true".

We also refactor some code previously found in model-element/model-element-camera.html
to now be in the shared model-element/resources/model-utils.js to ease writing <model>
tests.

  • model-element/model-element-camera.html:
  • model-element/model-element-interactive-dragging-expected.txt: Added.
  • model-element/model-element-interactive-dragging.html: Added.
  • model-element/model-element-interactive-expected.txt: Added.
  • model-element/model-element-interactive.html: Added.
  • model-element/resources/model-utils.js: Added.

(const.makeModel):
(const.bodyAvailability.async return):
(const.bodyAvailability):
(const.readyModel.async test):
(const.assert_cameras_are_equal):
(const.assert_cameras_are_not_equal):

  • platform/ios/TestExpectations:
  • platform/mac/TestExpectations:
Location:
trunk
Files:
5 added
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r288707 r288728  
     12022-01-27  Antoine Quint  <graouts@webkit.org>
     2
     3        [Model] Allow disabling interaction
     4        https://bugs.webkit.org/show_bug.cgi?id=227621
     5        <rdar://problem/80079703>
     6
     7        Reviewed by Darin Adler.
     8
     9        Add two new tests:
     10       
     11        - model-element/model-element-interactive.html tests the "interactive" IDL property
     12        and the "interactive" HTML attribute,
     13        - model-element/model-element-interactive-dragging.html tests that the "interactive"
     14        IDL property correctly disables setting the camera by dragging when "false", and allows
     15        it when "true".
     16
     17        We also refactor some code previously found in model-element/model-element-camera.html
     18        to now be in the shared model-element/resources/model-utils.js to ease writing <model>
     19        tests.
     20
     21        * model-element/model-element-camera.html:
     22        * model-element/model-element-interactive-dragging-expected.txt: Added.
     23        * model-element/model-element-interactive-dragging.html: Added.
     24        * model-element/model-element-interactive-expected.txt: Added.
     25        * model-element/model-element-interactive.html: Added.
     26        * model-element/resources/model-utils.js: Added.
     27        (const.makeModel):
     28        (const.bodyAvailability.async return):
     29        (const.bodyAvailability):
     30        (const.readyModel.async test):
     31        (const.assert_cameras_are_equal):
     32        (const.assert_cameras_are_not_equal):
     33        * platform/ios/TestExpectations:
     34        * platform/mac/TestExpectations:
     35
    1362022-01-27  Chris Dumez  <cdumez@apple.com>
    237
  • trunk/LayoutTests/model-element/model-element-camera.html

    r288440 r288728  
    11<script src="../resources/testharness.js"></script>
    22<script src="../resources/testharnessreport.js"></script>
     3<script src="resources/model-utils.js"></script>
    34<script>
    45
    5 const makeModel = () => {
    6     const source = document.createElement("source");
    7     source.src = "resources/cube.usdz";
    8     const model = document.createElement("model");
    9     model.appendChild(source);
    10     return model;
    11 }
    12 
    13 const bodyAvailability = async () => {
    14     return new Promise(resolve => {
    15         if (document.body)
    16             resolve();
    17         else
    18             window.addEventListener("DOMContentLoaded", event => resolve());
    19     });
    20 };
    21 
    22 const readyModel = async (test) => {
    23     await bodyAvailability();
    24     const model = document.body.appendChild(makeModel());
    25     test.add_cleanup(() => model.remove());
    26     await model.ready;
    27     return model;
    28 };
    29 
    30 const epsilon = 0.001;
    316const expectedCamera = { pitch: 10, yaw: 40, scale: 2 };
    327
     
    5833    await model.setCamera(expectedCamera);
    5934    const actualCamera = await model.getCamera();
    60     assert_approx_equals(actualCamera.pitch, expectedCamera.pitch, epsilon, "Camera has expected pitch");
    61     assert_approx_equals(actualCamera.yaw, expectedCamera.yaw, epsilon, "Camera has expected yaw");
    62     assert_approx_equals(actualCamera.scale, expectedCamera.scale, epsilon, "Camera has expected scale");
     35    assert_cameras_are_equal(actualCamera, expectedCamera);
    6336}, "<model> can set the camera and read it back");
    6437
  • trunk/LayoutTests/platform/ios/TestExpectations

    r288697 r288728  
    34203420# This test requires ARQL SPIs not yet available to OpenSource builds.
    34213421model-element/model-element-camera.html [ Skip ]
     3422model-element/model-element-interactive-dragging.html [ Skip ]
    34223423
    34233424# These tests require the design system ui fonts to be installed.
  • trunk/LayoutTests/platform/mac/TestExpectations

    r288655 r288728  
    110110# This test requires ARQL SPIs not yet available to OpenSource builds.
    111111model-element/model-element-camera.html [ Skip ]
     112model-element/model-element-interactive-dragging.html [ Skip ]
    112113
    113114# Accessibility tests for notifications that don't exist or aren't needed on Mac OS X.
  • trunk/Source/WebCore/ChangeLog

    r288726 r288728  
     12022-01-27  Antoine Quint  <graouts@webkit.org>
     2
     3        [Model] Allow disabling interaction
     4        https://bugs.webkit.org/show_bug.cgi?id=227621
     5        <rdar://problem/80079703>
     6
     7        Reviewed by Darin Adler.
     8
     9        We add support for the "interactive" IDL property and HTML attribute as discussed
     10        in the <model> explainer at https://github.com/WebKit/explainers/tree/main/model.
     11
     12        If the "interactive" property is "true", then the HTML "interactive" attribute is
     13        set on the element. If the property is "false", then the HTML attribute is absent.
     14
     15        Likewise, if the HTML attribute is present, the property returns "true". If the
     16        HTML attribute is midding, the property returns "false".
     17
     18        Note that the value held by the HTML attribute is not taken into account, its mere
     19        presence is all that is required.
     20
     21        Based on the value of the "interactive" property, we either disable or enable
     22        interaction. On macOS, we check the property in HTMLModelElement::defaultEventHandler()
     23        while on iOS, where dragging is performed entirely in the UI process, we use the
     24        new ModelPlayer::setInteractionEnabled() method.
     25
     26        By default, interaction is disabled.
     27
     28        Tests: model-element/model-element-interactive-dragging.html
     29               model-element/model-element-interactive.html
     30
     31        * Modules/model-element/HTMLModelElement.cpp:
     32        (WebCore::HTMLModelElement::isInteractive const):
     33        (WebCore::HTMLModelElement::attributeChanged):
     34        (WebCore::HTMLModelElement::defaultEventHandler):
     35        * Modules/model-element/HTMLModelElement.h:
     36        * Modules/model-element/HTMLModelElement.idl:
     37        * Modules/model-element/ModelPlayer.cpp:
     38        (WebCore::ModelPlayer::setInteractionEnabled):
     39        * Modules/model-element/ModelPlayer.h:
     40        * html/HTMLAttributeNames.in:
     41
    1422022-01-27  Carlos Garcia Campos  <cgarcia@igalia.com>
    243
  • trunk/Source/WebCore/Modules/model-element/HTMLModelElement.cpp

    r288723 r288728  
    335335}
    336336
     337bool HTMLModelElement::isInteractive() const
     338{
     339    return hasAttributeWithoutSynchronization(HTMLNames::interactiveAttr);
     340}
     341
     342void HTMLModelElement::attributeChanged(const QualifiedName& name, const AtomString& oldValue, const AtomString& newValue, AttributeModificationReason reason)
     343{
     344    HTMLElement::attributeChanged(name, oldValue, newValue, reason);
     345    if (m_modelPlayer && name == HTMLNames::interactiveAttr)
     346        m_modelPlayer->setInteractionEnabled(isInteractive());
     347}
     348
    337349void HTMLModelElement::defaultEventHandler(Event& event)
    338350{
     351    HTMLElement::defaultEventHandler(event);
     352
    339353    if (!m_modelPlayer || !m_modelPlayer->supportsMouseInteraction())
    340354        return;
     
    350364        return;
    351365
    352     if (type == eventNames().mousedownEvent && !m_isDragging && !event.defaultPrevented())
     366    if (type == eventNames().mousedownEvent && !m_isDragging && !event.defaultPrevented() && isInteractive())
    353367        dragDidStart(mouseEvent);
    354368    else if (type == eventNames().mousemoveEvent && m_isDragging)
  • trunk/Source/WebCore/Modules/model-element/HTMLModelElement.h

    r288723 r288728  
    120120    // DOM overrides.
    121121    void didMoveToNewDocument(Document& oldDocument, Document& newDocument) final;
     122    void attributeChanged(const QualifiedName&, const AtomString& oldValue, const AtomString& newValue, AttributeModificationReason) final;
    122123
    123124    // Rendering overrides.
     
    143144    void setAnimationIsPlaying(bool, DOMPromiseDeferred<void>&&);
    144145
     146    bool isInteractive() const;
     147
    145148    URL m_sourceURL;
    146149    CachedResourceHandle<CachedRawResource> m_resource;
  • trunk/Source/WebCore/Modules/model-element/HTMLModelElement.idl

    r288424 r288728  
    3434    readonly attribute Promise<HTMLModelElement> ready;
    3535
     36    [Reflect] attribute boolean interactive;
     37
    3638    undefined enterFullscreen();
    3739
  • trunk/Source/WebCore/Modules/model-element/ModelPlayer.cpp

    r288723 r288728  
    4141}
    4242
     43void ModelPlayer::setInteractionEnabled(bool)
     44{
    4345}
     46
     47}
  • trunk/Source/WebCore/Modules/model-element/ModelPlayer.h

    r288723 r288728  
    4949    virtual bool supportsMouseInteraction();
    5050    virtual bool supportsDragging();
     51    virtual void setInteractionEnabled(bool);
    5152    virtual void handleMouseDown(const LayoutPoint&, MonotonicTime) = 0;
    5253    virtual void handleMouseMove(const LayoutPoint&, MonotonicTime) = 0;
  • trunk/Source/WebCore/html/HTMLAttributeNames.in

    r287019 r288728  
    162162inputmode
    163163integrity
     164interactive
    164165is
    165166ismap
  • trunk/Source/WebKit/ChangeLog

    r288723 r288728  
     12022-01-27  Antoine Quint  <graouts@webkit.org>
     2
     3        [Model] Allow disabling interaction
     4        https://bugs.webkit.org/show_bug.cgi?id=227621
     5        <rdar://problem/80079703>
     6
     7        Reviewed by Darin Adler.
     8
     9        Override the new ModelPlayer::setInteractionEnabled() method for the iOS flavor
     10        and send the value up to the UI process such that it may set the matching value
     11        for UIView.userInteractionEnabled on the matching WKModelView.
     12
     13        * UIProcess/Cocoa/ModelElementControllerCocoa.mm:
     14        (WebKit::ModelElementController::setInteractionEnabledForModelElement):
     15        * UIProcess/ModelElementController.h:
     16        * UIProcess/WebPageProxy.cpp:
     17        (WebKit::WebPageProxy::modelElementSetInteractionEnabled):
     18        * UIProcess/WebPageProxy.h:
     19        * UIProcess/WebPageProxy.messages.in:
     20        * UIProcess/ios/WKModelView.mm:
     21        (-[WKModelView initWithModel:]):
     22        * WebProcess/Model/ios/ARKitInlinePreviewModelPlayerIOS.h:
     23        * WebProcess/Model/ios/ARKitInlinePreviewModelPlayerIOS.mm:
     24        (WebKit::ARKitInlinePreviewModelPlayerIOS::setInteractionEnabled):
     25
    1262022-01-27  Antoine Quint  <graouts@webkit.org>
    227
  • trunk/Source/WebKit/UIProcess/Cocoa/ModelElementControllerCocoa.mm

    r288610 r288728  
    132132}
    133133
     134void ModelElementController::setInteractionEnabledForModelElement(ModelIdentifier modelIdentifier, bool isInteractionEnabled)
     135{
     136    if (auto *modelView = modelViewForModelIdentifier(modelIdentifier))
     137        modelView.userInteractionEnabled = isInteractionEnabled;
     138}
     139
    134140#endif
    135141
  • trunk/Source/WebKit/UIProcess/ModelElementController.h

    r286317 r288728  
    6868#if ENABLE(ARKIT_INLINE_PREVIEW_IOS)
    6969    void takeModelElementFullscreen(ModelIdentifier);
     70    void setInteractionEnabledForModelElement(ModelIdentifier, bool);
    7071#endif
    7172#if ENABLE(ARKIT_INLINE_PREVIEW_MAC)
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r288610 r288728  
    1100411004    modelElementController()->takeModelElementFullscreen(modelIdentifier);
    1100511005}
     11006
     11007void WebPageProxy::modelElementSetInteractionEnabled(ModelIdentifier modelIdentifier, bool isInteractionEnabled)
     11008{
     11009    modelElementController()->setInteractionEnabledForModelElement(modelIdentifier, isInteractionEnabled);
     11010}
    1100611011#endif
    1100711012
  • trunk/Source/WebKit/UIProcess/WebPageProxy.h

    r288679 r288728  
    606606#if ENABLE(ARKIT_INLINE_PREVIEW_IOS)
    607607    void takeModelElementFullscreen(ModelIdentifier);
     608    void modelElementSetInteractionEnabled(ModelIdentifier, bool);
    608609#endif
    609610#if ENABLE(ARKIT_INLINE_PREVIEW_MAC)
  • trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in

    r288610 r288728  
    586586#if ENABLE(ARKIT_INLINE_PREVIEW_IOS)
    587587    TakeModelElementFullscreen(struct WebKit::ModelIdentifier modelIdentifier)
     588    ModelElementSetInteractionEnabled(struct WebKit::ModelIdentifier modelIdentifier, bool isInteractionEnabled)
    588589#endif
    589590#if ENABLE(ARKIT_INLINE_PREVIEW_MAC)
  • trunk/Source/WebKit/UIProcess/ios/WKModelView.mm

    r286317 r288728  
    100100    _modelInteractionGestureRecognizer = adoptNS([[WKModelInteractionGestureRecognizer alloc] init]);
    101101    [self addGestureRecognizer:_modelInteractionGestureRecognizer.get()];
     102    self.userInteractionEnabled = NO;
    102103
    103104    return self;
  • trunk/Source/WebKit/WebProcess/Model/ios/ARKitInlinePreviewModelPlayerIOS.h

    r288694 r288728  
    4646    // WebCore::ModelPlayer overrides.
    4747    void enterFullscreen() override;
     48    void setInteractionEnabled(bool) override;
    4849    void handleMouseDown(const WebCore::LayoutPoint&, MonotonicTime) override;
    4950    void handleMouseMove(const WebCore::LayoutPoint&, MonotonicTime) override;
  • trunk/Source/WebKit/WebProcess/Model/ios/ARKitInlinePreviewModelPlayerIOS.mm

    r288694 r288728  
    7272}
    7373
     74void ARKitInlinePreviewModelPlayerIOS::setInteractionEnabled(bool isInteractionEnabled)
     75{
     76    RefPtr strongPage = page();
     77    if (!strongPage)
     78        return;
     79
     80    if (auto modelIdentifier = this->modelIdentifier())
     81        strongPage->send(Messages::WebPageProxy::ModelElementSetInteractionEnabled(*modelIdentifier, isInteractionEnabled));
     82}
     83
    7484void ARKitInlinePreviewModelPlayerIOS::handleMouseDown(const WebCore::LayoutPoint&, MonotonicTime)
    7585{
Note: See TracChangeset for help on using the changeset viewer.