Bug 189983 - [macOS] Implement a way for the UI process to request typing attributes at the current selection
Summary: [macOS] Implement a way for the UI process to request typing attributes at th...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: HTML Editing (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Wenson Hsieh
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2018-09-25 19:14 PDT by Wenson Hsieh
Modified: 2018-10-02 07:14 PDT (History)
8 users (show)

See Also:


Attachments
Patch (59.47 KB, patch)
2018-09-25 19:41 PDT, Wenson Hsieh
no flags Details | Formatted Diff | Diff
Rebase on trunk (52.80 KB, patch)
2018-09-25 19:45 PDT, Wenson Hsieh
no flags Details | Formatted Diff | Diff
Fix macOS build (52.56 KB, patch)
2018-09-25 20:10 PDT, Wenson Hsieh
no flags Details | Formatted Diff | Diff
Patch (56.28 KB, patch)
2018-09-26 13:07 PDT, Wenson Hsieh
no flags Details | Formatted Diff | Diff
Rebase on trunk (56.22 KB, patch)
2018-10-01 19:11 PDT, Wenson Hsieh
rniwa: review+
commit-queue: commit-queue-
Details | Formatted Diff | Diff
Archive of layout-test-results from ews107 for mac-sierra-wk2 (2.97 MB, application/zip)
2018-10-01 21:07 PDT, EWS Watchlist
no flags Details
Patch for landing (56.37 KB, patch)
2018-10-02 02:51 PDT, Wenson Hsieh
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Wenson Hsieh 2018-09-25 19:14:02 PDT
<rdar://problem/44648705>
Comment 1 Wenson Hsieh 2018-09-25 19:14:35 PDT
This is for NSInspectorBar support on macOS.
Comment 2 Wenson Hsieh 2018-09-25 19:41:29 PDT
Created attachment 350836 [details]
Patch
Comment 3 Wenson Hsieh 2018-09-25 19:45:30 PDT
Created attachment 350837 [details]
Rebase on trunk
Comment 4 mitz 2018-09-25 19:51:39 PDT
How often is the client going to call into this API? How is it going to know when to call (that is, how is it going to know that the typing attributes at the current selection have changed)? Would it be possible to just deliver the typing attributes along with whatever signal says that they need to be queried again?
Comment 5 Wenson Hsieh 2018-09-25 20:05:38 PDT
(In reply to mitz from comment #4)
> How often is the client going to call into this API? How is it going to know
> when to call (that is, how is it going to know that the typing attributes at
> the current selection have changed)?

- The client (NSInspectorBar, in this case) is going to call into this API when the user changes a value using controls in the inspector bar. It will also call into this API when we tell it to update (i.e. upon selection change) by calling -[NSInspectorBar _update].

> Would it be possible to just deliver the typing attributes along with whatever signal 
> says that they need to be queried again?

I think it's possible to (efficiently) achieve this, but it would require a more complex implementation. We'd certainly want to avoid computing a full typing style and attributed string all the time on every selection change, so we'd need to KVO for the presence of the inspector bar (as well as inspector bar visibility) in the UI process and have the web process know that the inspector bar is visible. Only when the inspector bar is visible would the web process send (1) a selection range, (2) a typing attributes dictionary, and (3) an attributed string if the selection is a range.
Comment 6 Wenson Hsieh 2018-09-25 20:10:04 PDT
Created attachment 350839 [details]
Fix macOS build
Comment 7 mitz 2018-09-25 20:29:38 PDT
(In reply to Wenson Hsieh from comment #5)
> (In reply to mitz from comment #4)
> > How often is the client going to call into this API? How is it going to know
> > when to call (that is, how is it going to know that the typing attributes at
> > the current selection have changed)?
> 
> - The client (NSInspectorBar, in this case) is going to call into this API
> when the user changes a value using controls in the inspector bar. It will
> also call into this API when we tell it to update (i.e. upon selection
> change) by calling -[NSInspectorBar _update].

What happens when the selection doesn’t change but the attributes do change (for example because the use changed a value without using the inspector bar, or perhaps even not using the API, e.g. by something that invokes JavaScript on the page that makes the change that way)?

> 
> > Would it be possible to just deliver the typing attributes along with whatever signal 
> > says that they need to be queried again?
> 
> I think it's possible to (efficiently) achieve this, but it would require a
> more complex implementation. We'd certainly want to avoid computing a full
> typing style and attributed string all the time on every selection change,
> so we'd need to KVO for the presence of the inspector bar (as well as
> inspector bar visibility) in the UI process and have the web process know
> that the inspector bar is visible. Only when the inspector bar is visible
> would the web process send (1) a selection range, (2) a typing attributes
> dictionary, and (3) an attributed string if the selection is a range.

I know that this API is for the inspector bar, but how do we (plan to) make the Fonts panel track the typing style?
Comment 8 Wenson Hsieh 2018-09-25 21:36:58 PDT
(In reply to mitz from comment #7)
> (In reply to Wenson Hsieh from comment #5)
> > (In reply to mitz from comment #4)
> > > How often is the client going to call into this API? How is it going to know
> > > when to call (that is, how is it going to know that the typing attributes at
> > > the current selection have changed)?
> > 
> > - The client (NSInspectorBar, in this case) is going to call into this API
> > when the user changes a value using controls in the inspector bar. It will
> > also call into this API when we tell it to update (i.e. upon selection
> > change) by calling -[NSInspectorBar _update].
> 
> What happens when the selection doesn’t change but the attributes do change
> (for example because the use changed a value without using the inspector
> bar, or perhaps even not using the API, e.g. by something that invokes
> JavaScript on the page that makes the change that way)?

That's a really good point — unfortunately, I don't have a great plan to deal with this. I don't think we handle this either in the various scenarios currently where we have state in the UI process that's derived from the web process (e.g., some information in EditorState and AssistedNodeInformation come to mind). I'll think about this some more...

> 
> > 
> > > Would it be possible to just deliver the typing attributes along with whatever signal 
> > > says that they need to be queried again?
> > 
> > I think it's possible to (efficiently) achieve this, but it would require a
> > more complex implementation. We'd certainly want to avoid computing a full
> > typing style and attributed string all the time on every selection change,
> > so we'd need to KVO for the presence of the inspector bar (as well as
> > inspector bar visibility) in the UI process and have the web process know
> > that the inspector bar is visible. Only when the inspector bar is visible
> > would the web process send (1) a selection range, (2) a typing attributes
> > dictionary, and (3) an attributed string if the selection is a range.
> 
> I know that this API is for the inspector bar, but how do we (plan to) make
> the Fonts panel track the typing style?

TBH, not 100% sure. The (naive) approach I was considering is to request typing attributes using the same machinery as we would for the inspector bar. Then, to avoid doing excessive work computing typing attributes multiple times on every selection change, I'd implement some kind of batching mechanism so that when a typing attribute request is made while another typing attribute request is already in-flight, we'll just wait for the response to the former typing attribute request and invoke both callbacks then.

That being said, this isn't a viable strategy if we want to preserve the ability for clients to do things like: (1) request typing attributes, (2) immediately perform some editing operation, (3) request typing attributes again, and expect the typing attributes fetched in (3) to reflect the editing done in (2).

Alternately, we can cache computed FontAttributes in the web process instead (invalidated on selection change), so the only added cost of multiple calls to request typing attributes is a bit of IPC encoding/decoding.
Comment 9 mitz 2018-09-25 21:49:17 PDT
(In reply to Wenson Hsieh from comment #8)
> (In reply to mitz from comment #7)
> > (In reply to Wenson Hsieh from comment #5)
> > > (In reply to mitz from comment #4)
> > > > How often is the client going to call into this API? How is it going to know
> > > > when to call (that is, how is it going to know that the typing attributes at
> > > > the current selection have changed)?
> > > 
> > > - The client (NSInspectorBar, in this case) is going to call into this API
> > > when the user changes a value using controls in the inspector bar. It will
> > > also call into this API when we tell it to update (i.e. upon selection
> > > change) by calling -[NSInspectorBar _update].
> > 
> > What happens when the selection doesn’t change but the attributes do change
> > (for example because the use changed a value without using the inspector
> > bar, or perhaps even not using the API, e.g. by something that invokes
> > JavaScript on the page that makes the change that way)?
> 
> That's a really good point — unfortunately, I don't have a great plan to
> deal with this. I don't think we handle this either in the various scenarios
> currently where we have state in the UI process that's derived from the web
> process (e.g., some information in EditorState and AssistedNodeInformation
> come to mind). I'll think about this some more...

How is this handled for the Touch Bar?

This may be naïve, but if we handle these things correctly in a legacy WebView, it means that we are willing to do the work required to computed those things whenever they change and there’s an interested observer, so for WKWebView, we should be able to create proxies for those UI-process observers in the Web Content process and push the information of interest to them.

> 
> > 
> > > 
> > > > Would it be possible to just deliver the typing attributes along with whatever signal 
> > > > says that they need to be queried again?
> > > 
> > > I think it's possible to (efficiently) achieve this, but it would require a
> > > more complex implementation. We'd certainly want to avoid computing a full
> > > typing style and attributed string all the time on every selection change,
> > > so we'd need to KVO for the presence of the inspector bar (as well as
> > > inspector bar visibility) in the UI process and have the web process know
> > > that the inspector bar is visible. Only when the inspector bar is visible
> > > would the web process send (1) a selection range, (2) a typing attributes
> > > dictionary, and (3) an attributed string if the selection is a range.
> > 
> > I know that this API is for the inspector bar, but how do we (plan to) make
> > the Fonts panel track the typing style?
> 
> TBH, not 100% sure. The (naive) approach I was considering is to request
> typing attributes using the same machinery as we would for the inspector
> bar. Then, to avoid doing excessive work computing typing attributes
> multiple times on every selection change, I'd implement some kind of
> batching mechanism so that when a typing attribute request is made while
> another typing attribute request is already in-flight, we'll just wait for
> the response to the former typing attribute request and invoke both
> callbacks then.
> 
> That being said, this isn't a viable strategy if we want to preserve the
> ability for clients to do things like: (1) request typing attributes, (2)
> immediately perform some editing operation, (3) request typing attributes
> again, and expect the typing attributes fetched in (3) to reflect the
> editing done in (2).
> 
> Alternately, we can cache computed FontAttributes in the web process instead
> (invalidated on selection change), so the only added cost of multiple calls
> to request typing attributes is a bit of IPC encoding/decoding.
Comment 10 Wenson Hsieh 2018-09-26 08:17:20 PDT
> > > What happens when the selection doesn’t change but the attributes do change
> > > (for example because the use changed a value without using the inspector
> > > bar, or perhaps even not using the API, e.g. by something that invokes
> > > JavaScript on the page that makes the change that way)?
> …
> How is this handled for the Touch Bar?

Currently, it is not (both in legacy and modern WebKit). I determined this by adding and removing styles via web inspector and checking to see whether the inspector bar/Touch Bar/font panel updated to reflect the new state, but it looks like all three don't update until the next selection change.

> This may be naïve, but if we handle these things correctly in a legacy
> WebView, it means that we are willing to do the work required to computed
> those things whenever they change and there’s an interested observer, so for
> WKWebView, we should be able to create proxies for those UI-process
> observers in the Web Content process and push the information of interest to
> them.
Comment 11 Wenson Hsieh 2018-09-26 08:51:19 PDT
> This may be naïve, but if we handle these things correctly in a legacy
> WebView, it means that we are willing to do the work required to computed
> those things whenever they change and there’s an interested observer, so for
> WKWebView, we should be able to create proxies for those UI-process
> observers in the Web Content process and push the information of interest to
> them.

Currently, we handle updating the inspector bar alongside the font panel in legacy WebKit correctly, albeit inefficiently since we compute typing attributes twice when the font panel is visible. The first call is from WebKit updating the font panel when the selection changes...

1   0x11315995f WebCore::Editor::fontAttributesAtSelectionStart() const
2   0x1104d3769 -[WebHTMLView(WebInternal) _updateFontPanel]
3   0x102508bdc
4   0x110460af8 updateFontPanel(WebView*)
5   0x110460f30 WebEditorClient::respondToChangedContents()
6   0x1131466e4 WebCore::Editor::respondToChangedContents(WebCore::VisibleSelection const&)
7   0x113149b3d WebCore::Editor::appliedEditing(WebCore::CompositeEditCommand&)

...and this second call is from AppKit asking WebKit for typing attribute information when calling -updateSelectedAttributes to update the inspector bar.

1   0x11315995f WebCore::Editor::fontAttributesAtSelectionStart() const
2   0x1105b52bf -[WebView(WebViewEditingActions) typingAttributes]
3   0x103dc47fa -[__NSInspectorBarItemController _updateSelectedAttributesForSyncClient]
4   0x103dc3d30 -[__NSInspectorBarItemController updateSelectedAttributes]
5   0x103db7274 -[NSInspectorBar _update]
6   0x102508c20
7   0x110460af8 updateFontPanel(WebView*)
8   0x110460f30 WebEditorClient::respondToChangedContents()
9   0x1131466e4 WebCore::Editor::respondToChangedContents(WebCore::VisibleSelection const&)
10  0x113149b3d WebCore::Editor::appliedEditing(WebCore::CompositeEditCommand&)
Comment 12 Wenson Hsieh 2018-09-26 12:49:53 PDT
Dan and I chatted in person about this. (I think) we agree that computing and sending all font attribute information on selection change is too costly, and it's not straightforward how to limit this work to only when the inspector bar is present (and also visible, and the web view is also the first responder). We had briefly considered SPI for Mail to opt into computing and sending typing attributes whenever the selection changes, but a more straightforward solution is to simply cache typing attributes so that subsequent typing attribute requests are cheap, if the selection hasn't changed.
Comment 13 Wenson Hsieh 2018-09-26 13:07:42 PDT
Created attachment 350889 [details]
Patch
Comment 14 Wenson Hsieh 2018-10-01 19:11:13 PDT
Created attachment 351336 [details]
Rebase on trunk
Comment 15 EWS Watchlist 2018-10-01 21:07:28 PDT Comment hidden (obsolete)
Comment 16 EWS Watchlist 2018-10-01 21:07:30 PDT Comment hidden (obsolete)
Comment 17 Wenson Hsieh 2018-10-02 02:16:53 PDT
Comment on attachment 351336 [details]
Rebase on trunk

Thanks for the review!

The macOS failure (css3/filters/backdrop/add-remove-add-backdrop-filter.html) does not seem related.
Comment 18 WebKit Commit Bot 2018-10-02 02:47:27 PDT Comment hidden (obsolete)
Comment 19 Wenson Hsieh 2018-10-02 02:51:42 PDT
Created attachment 351363 [details]
Patch for landing
Comment 20 WebKit Commit Bot 2018-10-02 03:39:48 PDT
Comment on attachment 351363 [details]
Patch for landing

Clearing flags on attachment: 351363

Committed r236724: <https://trac.webkit.org/changeset/236724>