RESOLVED FIXED 189983
[macOS] Implement a way for the UI process to request typing attributes at the current selection
https://bugs.webkit.org/show_bug.cgi?id=189983
Summary [macOS] Implement a way for the UI process to request typing attributes at th...
Wenson Hsieh
Reported 2018-09-25 19:14:02 PDT
Attachments
Patch (59.47 KB, patch)
2018-09-25 19:41 PDT, Wenson Hsieh
no flags
Rebase on trunk (52.80 KB, patch)
2018-09-25 19:45 PDT, Wenson Hsieh
no flags
Fix macOS build (52.56 KB, patch)
2018-09-25 20:10 PDT, Wenson Hsieh
no flags
Patch (56.28 KB, patch)
2018-09-26 13:07 PDT, Wenson Hsieh
no flags
Rebase on trunk (56.22 KB, patch)
2018-10-01 19:11 PDT, Wenson Hsieh
rniwa: review+
commit-queue: commit-queue-
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
Patch for landing (56.37 KB, patch)
2018-10-02 02:51 PDT, Wenson Hsieh
no flags
Wenson Hsieh
Comment 1 2018-09-25 19:14:35 PDT
This is for NSInspectorBar support on macOS.
Wenson Hsieh
Comment 2 2018-09-25 19:41:29 PDT
Wenson Hsieh
Comment 3 2018-09-25 19:45:30 PDT
Created attachment 350837 [details] Rebase on trunk
mitz
Comment 4 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?
Wenson Hsieh
Comment 5 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.
Wenson Hsieh
Comment 6 2018-09-25 20:10:04 PDT
Created attachment 350839 [details] Fix macOS build
mitz
Comment 7 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?
Wenson Hsieh
Comment 8 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.
mitz
Comment 9 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.
Wenson Hsieh
Comment 10 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.
Wenson Hsieh
Comment 11 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&)
Wenson Hsieh
Comment 12 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.
Wenson Hsieh
Comment 13 2018-09-26 13:07:42 PDT
Wenson Hsieh
Comment 14 2018-10-01 19:11:13 PDT
Created attachment 351336 [details] Rebase on trunk
EWS Watchlist
Comment 15 2018-10-01 21:07:28 PDT Comment hidden (obsolete)
EWS Watchlist
Comment 16 2018-10-01 21:07:30 PDT Comment hidden (obsolete)
Wenson Hsieh
Comment 17 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.
WebKit Commit Bot
Comment 18 2018-10-02 02:47:27 PDT Comment hidden (obsolete)
Wenson Hsieh
Comment 19 2018-10-02 02:51:42 PDT
Created attachment 351363 [details] Patch for landing
WebKit Commit Bot
Comment 20 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>
Note You need to log in before you can comment on or make changes to this bug.