diff options
author | Andreas Kling <kling@serenityos.org> | 2020-07-06 20:36:34 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-07-06 20:36:34 +0200 |
commit | 7a7e39c7af4a9a86339e5dab27e0567d6abe69b5 (patch) | |
tree | cd216350bdc622ba4897760dcbf777a6a6588625 /Libraries | |
parent | 32243e1df24820b8da8bcf5bc491cd812d261483 (diff) | |
download | serenity-7a7e39c7af4a9a86339e5dab27e0567d6abe69b5.zip |
LibWeb: Move WebContentView from Demos/WebView into LibWeb
Diffstat (limited to 'Libraries')
-rw-r--r-- | Libraries/LibWeb/CMakeLists.txt | 4 | ||||
-rw-r--r-- | Libraries/LibWeb/WebContentClient.cpp | 126 | ||||
-rw-r--r-- | Libraries/LibWeb/WebContentClient.h | 60 | ||||
-rw-r--r-- | Libraries/LibWeb/WebContentView.cpp | 166 | ||||
-rw-r--r-- | Libraries/LibWeb/WebContentView.h | 78 |
5 files changed, 434 insertions, 0 deletions
diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index 815119997d..30e79d5c3e 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -109,11 +109,15 @@ set(SOURCES CSS/PropertyID.h CSS/PropertyID.cpp CSS/DefaultStyleSheetSource.cpp + WebContentView.cpp + WebContentClient.cpp ) set(GENERATED_SOURCES ../../Services/ProtocolServer/ProtocolClientEndpoint.h ../../Services/ProtocolServer/ProtocolServerEndpoint.h + ../../Services/WebContent/WebContentClientEndpoint.h + ../../Services/WebContent/WebContentServerEndpoint.h ) set_property(GLOBAL PROPERTY wrapper_sources) diff --git a/Libraries/LibWeb/WebContentClient.cpp b/Libraries/LibWeb/WebContentClient.cpp new file mode 100644 index 0000000000..0042cc14db --- /dev/null +++ b/Libraries/LibWeb/WebContentClient.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "WebContentClient.h" +#include "WebContentView.h" +#include <AK/SharedBuffer.h> + +WebContentClient::WebContentClient(WebContentView& view) + : IPC::ServerConnection<WebContentClientEndpoint, WebContentServerEndpoint>(*this, "/tmp/portal/webcontent") + , m_view(view) +{ + handshake(); +} + +void WebContentClient::handshake() +{ + auto response = send_sync<Messages::WebContentServer::Greet>(getpid()); + set_my_client_id(response->client_id()); + set_server_pid(response->server_pid()); +} + +void WebContentClient::handle(const Messages::WebContentClient::DidPaint& message) +{ +#ifdef DEBUG_SPAM + dbg() << "handle: WebContentClient::DidPaint! content_rect=" << message.content_rect() << ", shbuf_id=" << message.shbuf_id(); +#endif + m_view.notify_server_did_paint({}, message.shbuf_id()); +} + +void WebContentClient::handle([[maybe_unused]] const Messages::WebContentClient::DidFinishLoad& message) +{ +#ifdef DEBUG_SPAM + dbg() << "handle: WebContentClient::DidFinishLoad! url=" << message.url(); +#endif +} + +void WebContentClient::handle(const Messages::WebContentClient::DidInvalidateContentRect& message) +{ +#ifdef DEBUG_SPAM + dbg() << "handle: WebContentClient::DidInvalidateContentRect! content_rect=" << message.content_rect(); +#endif + + // FIXME: Figure out a way to coalesce these messages to reduce unnecessary painting + m_view.notify_server_did_invalidate_content_rect({}, message.content_rect()); +} + +void WebContentClient::handle(const Messages::WebContentClient::DidChangeSelection&) +{ +#ifdef DEBUG_SPAM + dbg() << "handle: WebContentClient::DidChangeSelection!"; +#endif + m_view.notify_server_did_change_selection({}); +} + +void WebContentClient::handle(const Messages::WebContentClient::DidLayout& message) +{ +#ifdef DEBUG_SPAM + dbg() << "handle: WebContentClient::DidLayout! content_size=" << message.content_size(); +#endif + m_view.notify_server_did_layout({}, message.content_size()); +} + +void WebContentClient::handle(const Messages::WebContentClient::DidChangeTitle& message) +{ +#ifdef DEBUG_SPAM + dbg() << "handle: WebContentClient::DidChangeTitle! title=" << message.title(); +#endif + m_view.notify_server_did_change_title({}, message.title()); +} + +void WebContentClient::handle(const Messages::WebContentClient::DidRequestScrollIntoView& message) +{ +#ifdef DEBUG_SPAM + dbg() << "handle: WebContentClient::DidRequestScrollIntoView! rect=" << message.rect(); +#endif + m_view.notify_server_did_request_scroll_into_view({}, message.rect()); +} + +void WebContentClient::handle(const Messages::WebContentClient::DidHoverLink& message) +{ +#ifdef DEBUG_SPAM + dbg() << "handle: WebContentClient::DidHoverLink! url=" << message.url(); +#endif + m_view.notify_server_did_hover_link({}, message.url()); +} + +void WebContentClient::handle(const Messages::WebContentClient::DidUnhoverLink&) +{ +#ifdef DEBUG_SPAM + dbg() << "handle: WebContentClient::DidUnhoverLink!"; +#endif + m_view.notify_server_did_unhover_link({}); +} + +void WebContentClient::handle(const Messages::WebContentClient::DidClickLink& message) +{ + m_view.notify_server_did_click_link({}, message.url(), message.target(), message.modifiers()); +} + +void WebContentClient::handle(const Messages::WebContentClient::DidMiddleClickLink& message) +{ + m_view.notify_server_did_middle_click_link({}, message.url(), message.target(), message.modifiers()); +} diff --git a/Libraries/LibWeb/WebContentClient.h b/Libraries/LibWeb/WebContentClient.h new file mode 100644 index 0000000000..638cf22b40 --- /dev/null +++ b/Libraries/LibWeb/WebContentClient.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <AK/HashMap.h> +#include <LibIPC/ServerConnection.h> +#include <WebContent/WebContentClientEndpoint.h> +#include <WebContent/WebContentServerEndpoint.h> + +class WebContentView; + +class WebContentClient + : public IPC::ServerConnection<WebContentClientEndpoint, WebContentServerEndpoint> + , public WebContentClientEndpoint { + C_OBJECT(WebContentClient); + +public: + virtual void handshake() override; + +private: + WebContentClient(WebContentView&); + + virtual void handle(const Messages::WebContentClient::DidPaint&) override; + virtual void handle(const Messages::WebContentClient::DidFinishLoad&) override; + virtual void handle(const Messages::WebContentClient::DidInvalidateContentRect&) override; + virtual void handle(const Messages::WebContentClient::DidChangeSelection&) override; + virtual void handle(const Messages::WebContentClient::DidLayout&) override; + virtual void handle(const Messages::WebContentClient::DidChangeTitle&) override; + virtual void handle(const Messages::WebContentClient::DidRequestScrollIntoView&) override; + virtual void handle(const Messages::WebContentClient::DidHoverLink&) override; + virtual void handle(const Messages::WebContentClient::DidUnhoverLink&) override; + virtual void handle(const Messages::WebContentClient::DidClickLink&) override; + virtual void handle(const Messages::WebContentClient::DidMiddleClickLink&) override; + + WebContentView& m_view; +}; diff --git a/Libraries/LibWeb/WebContentView.cpp b/Libraries/LibWeb/WebContentView.cpp new file mode 100644 index 0000000000..67ceffecd8 --- /dev/null +++ b/Libraries/LibWeb/WebContentView.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "WebContentView.h" +#include "WebContentClient.h" +#include <AK/SharedBuffer.h> +#include <LibGUI/Painter.h> +#include <LibGUI/ScrollBar.h> +#include <LibGfx/SystemTheme.h> + +WebContentView::WebContentView() +{ + m_client = WebContentClient::construct(*this); + client().post_message(Messages::WebContentServer::UpdateSystemTheme(Gfx::current_system_theme_buffer_id())); +} + +WebContentView::~WebContentView() +{ +} + +void WebContentView::load(const URL& url) +{ + client().post_message(Messages::WebContentServer::LoadURL(url)); +} + +void WebContentView::paint_event(GUI::PaintEvent& event) +{ + GUI::ScrollableWidget::paint_event(event); + + GUI::Painter painter(*this); + painter.add_clip_rect(frame_inner_rect()); + painter.add_clip_rect(event.rect()); + painter.translate(frame_thickness(), frame_thickness()); + + ASSERT(m_front_bitmap); + painter.blit({ 0, 0 }, *m_front_bitmap, m_front_bitmap->rect()); +} + +void WebContentView::resize_event(GUI::ResizeEvent& event) +{ + GUI::ScrollableWidget::resize_event(event); + + m_front_bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::RGB32, available_size())->to_bitmap_backed_by_shared_buffer(); + m_front_bitmap->shared_buffer()->share_with(client().server_pid()); + + m_back_bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::RGB32, available_size())->to_bitmap_backed_by_shared_buffer(); + m_back_bitmap->shared_buffer()->share_with(client().server_pid()); + + client().post_message(Messages::WebContentServer::SetViewportRect(Gfx::IntRect({ horizontal_scrollbar().value(), vertical_scrollbar().value() }, available_size()))); + request_repaint(); +} + +void WebContentView::mousedown_event(GUI::MouseEvent& event) +{ + client().post_message(Messages::WebContentServer::MouseDown(to_content_position(event.position()), event.button(), event.buttons(), event.modifiers())); +} + +void WebContentView::mouseup_event(GUI::MouseEvent& event) +{ + client().post_message(Messages::WebContentServer::MouseUp(to_content_position(event.position()), event.button(), event.buttons(), event.modifiers())); +} + +void WebContentView::mousemove_event(GUI::MouseEvent& event) +{ + client().post_message(Messages::WebContentServer::MouseMove(to_content_position(event.position()), event.button(), event.buttons(), event.modifiers())); +} + +void WebContentView::notify_server_did_paint(Badge<WebContentClient>, i32 shbuf_id) +{ + if (m_back_bitmap->shbuf_id() == shbuf_id) { + swap(m_back_bitmap, m_front_bitmap); + update(); + } +} + +void WebContentView::notify_server_did_invalidate_content_rect(Badge<WebContentClient>, [[maybe_unused]] const Gfx::IntRect& content_rect) +{ +#ifdef DEBUG_SPAM + dbg() << "server did invalidate content_rect: " << content_rect << ", current shbuf_id=" << m_bitmap->shbuf_id(); +#endif + request_repaint(); +} + +void WebContentView::notify_server_did_change_selection(Badge<WebContentClient>) +{ + request_repaint(); +} + +void WebContentView::notify_server_did_layout(Badge<WebContentClient>, const Gfx::IntSize& content_size) +{ + set_content_size(content_size); +} + +void WebContentView::notify_server_did_change_title(Badge<WebContentClient>, const String& title) +{ + if (on_title_change) + on_title_change(title); +} + +void WebContentView::notify_server_did_request_scroll_into_view(Badge<WebContentClient>, const Gfx::IntRect& rect) +{ + scroll_into_view(rect, true, true); +} + +void WebContentView::notify_server_did_hover_link(Badge<WebContentClient>, const URL& url) +{ + if (on_link_hover) + on_link_hover(url); +} + +void WebContentView::notify_server_did_unhover_link(Badge<WebContentClient>) +{ + if (on_link_hover) + on_link_hover({}); +} + +void WebContentView::notify_server_did_click_link(Badge<WebContentClient>, const URL& url, const String& target, unsigned int modifiers) +{ + if (on_link_click) + on_link_click(url, target, modifiers); +} + +void WebContentView::notify_server_did_middle_click_link(Badge<WebContentClient>, const URL& url, const String& target, unsigned int modifiers) +{ + if (on_link_middle_click) + on_link_middle_click(url, target, modifiers); +} + +void WebContentView::did_scroll() +{ + client().post_message(Messages::WebContentServer::SetViewportRect(visible_content_rect())); + request_repaint(); +} + +void WebContentView::request_repaint() +{ + client().post_message(Messages::WebContentServer::Paint(m_back_bitmap->rect().translated(horizontal_scrollbar().value(), vertical_scrollbar().value()), m_back_bitmap->shbuf_id())); +} + +WebContentClient& WebContentView::client() +{ + return *m_client; +} diff --git a/Libraries/LibWeb/WebContentView.h b/Libraries/LibWeb/WebContentView.h new file mode 100644 index 0000000000..6af604a31c --- /dev/null +++ b/Libraries/LibWeb/WebContentView.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <LibGUI/ScrollableWidget.h> +#include <LibGUI/Widget.h> + +class WebContentClient; + +class WebContentView final : public GUI::ScrollableWidget { + C_OBJECT(WebContentView); + +public: + virtual ~WebContentView() override; + + void load(const URL&); + + Function<void(const String&)> on_title_change; + Function<void(const URL&)> on_link_hover; + Function<void(const URL&, const String& target, unsigned modifiers)> on_link_click; + Function<void(const URL&, const String& target, unsigned modifiers)> on_link_middle_click; + + void notify_server_did_layout(Badge<WebContentClient>, const Gfx::IntSize& content_size); + void notify_server_did_paint(Badge<WebContentClient>, i32 shbuf_id); + void notify_server_did_invalidate_content_rect(Badge<WebContentClient>, const Gfx::IntRect&); + void notify_server_did_change_selection(Badge<WebContentClient>); + void notify_server_did_change_title(Badge<WebContentClient>, const String&); + void notify_server_did_request_scroll_into_view(Badge<WebContentClient>, const Gfx::IntRect&); + void notify_server_did_hover_link(Badge<WebContentClient>, const URL&); + void notify_server_did_unhover_link(Badge<WebContentClient>); + void notify_server_did_click_link(Badge<WebContentClient>, const URL&, const String& target, unsigned modifiers); + void notify_server_did_middle_click_link(Badge<WebContentClient>, const URL&, const String& target, unsigned modifiers); + +private: + WebContentView(); + + // ^Widget + virtual void paint_event(GUI::PaintEvent&) override; + virtual void resize_event(GUI::ResizeEvent&) override; + virtual void mousedown_event(GUI::MouseEvent&) override; + virtual void mouseup_event(GUI::MouseEvent&) override; + virtual void mousemove_event(GUI::MouseEvent&) override; + + // ^ScrollableWidget + virtual void did_scroll() override; + + void request_repaint(); + + WebContentClient& client(); + + RefPtr<WebContentClient> m_client; + RefPtr<Gfx::Bitmap> m_front_bitmap; + RefPtr<Gfx::Bitmap> m_back_bitmap; +}; |