From ab4fec91be80e1cf7bd35c66043426052d8b3cfa Mon Sep 17 00:00:00 2001 From: Michael James Gratton Date: Thu, 19 Jan 2017 13:16:13 +1100 Subject: [PATCH] Enable editing a link by clicking on it. * src/client/composer/composer-widget.vala (ComposerWidget::on_button_press): Show a link popover on button release. * src/client/composer/composer-web-view.vala (ComposerWebView): Add button_release_event_done signal to work around WK eating mouse events, fire it after default processing has occurred. * ui/composer-web-view.js: Don't bother selecting a link on click, we are handling insertion and deletion without it fine now. Just cancel the event's default so link clicks are not activated. --- src/client/composer/composer-web-view.vala | 12 +++++++++++ src/client/composer/composer-widget.vala | 24 ++++++++++++++++++++++ ui/composer-web-view.js | 5 +---- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/client/composer/composer-web-view.vala b/src/client/composer/composer-web-view.vala index 868b883c..24f2a003 100644 --- a/src/client/composer/composer-web-view.vala +++ b/src/client/composer/composer-web-view.vala @@ -158,6 +158,9 @@ public class ComposerWebView : ClientWebView { /** Emitted when the cursor's edit context has changed. */ public signal void cursor_context_changed(EditContext cursor_context); + /** Workaround for WebView eating the button event */ + internal signal bool button_release_event_done(Gdk.Event event); + public ComposerWebView(Configuration config) { base(config); @@ -447,6 +450,15 @@ public class ComposerWebView : ClientWebView { return ""; // XXX } + public override bool button_release_event(Gdk.EventButton event) { + // WebView seems to unconditionally consume button events, so + // to show a link popopver after the view has processed one, + // we need to emit our own. + bool ret = base.button_press_event(event); + button_release_event_done(event); + return ret; + } + private void on_command_stack_changed(WebKit.JavascriptResult result) { try { string[] values = WebKitUtil.to_string(result).split(","); diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala index d9c0a422..25d2a186 100644 --- a/src/client/composer/composer-widget.vala +++ b/src/client/composer/composer-widget.vala @@ -508,6 +508,7 @@ public class ComposerWidget : Gtk.EventBox { this.reply_to_entry.changed.connect(validate_send_button); this.editor.command_stack_changed.connect(on_command_state_changed); + this.editor.button_release_event_done.connect(on_button_release); this.editor.context_menu.connect(on_context_menu); this.editor.cursor_context_changed.connect(on_cursor_context_changed); this.editor.document_modified.connect(() => { draft_changed(); }); @@ -2213,6 +2214,29 @@ public class ComposerWidget : Gtk.EventBox { } } + private bool on_button_release(Gdk.Event event) { + // Show the link popover on mouse release (instead of press) + // so the user can still select text with a link in it, + // without the popover immediately appearing and raining on + // their text selection parade. + if (this.pointer_url != null && + this.actions.get_action_state(ACTION_COMPOSE_AS_HTML).get_boolean()) { + Gdk.EventButton? button = (Gdk.EventButton) event; + Gdk.Rectangle location = new Gdk.Rectangle(); + location.x = (int) button.x; + location.y = (int) button.y; + + ComposerLinkPopover popover = new_link_popover( + ComposerLinkPopover.Type.EXISTING_LINK, + this.pointer_url + ); + popover.set_relative_to(this.editor); + popover.set_pointing_to(location); + popover.show(); + } + return Gdk.EVENT_PROPAGATE; + } + private void on_cursor_context_changed(ComposerWebView.EditContext context) { this.cursor_url = context.is_link ? context.link_url : null; update_cursor_actions(); diff --git a/ui/composer-web-view.js b/ui/composer-web-view.js index 96656317..7aefa150 100644 --- a/ui/composer-web-view.js +++ b/ui/composer-web-view.js @@ -33,7 +33,7 @@ ComposerPageState.prototype = { document.addEventListener("click", function(e) { if (e.target.tagName == "A") { - state.linkClicked(e.target); + e.preventDefault(); } }, true); @@ -204,9 +204,6 @@ ComposerPageState.prototype = { documentModified: function(element) { window.webkit.messageHandlers.documentModified.postMessage(null); }, - linkClicked: function(element) { - window.getSelection().selectAllChildren(element); - }, selectionChanged: function() { PageState.prototype.selectionChanged.apply(this, []);