summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Applications/FileManager/main.cpp2
-rw-r--r--Base/etc/SystemServer.ini6
-rw-r--r--Base/etc/group1
-rw-r--r--Base/etc/passwd1
-rw-r--r--Libraries/LibGUI/Application.cpp2
-rw-r--r--Libraries/LibGUI/Clipboard.cpp54
-rw-r--r--Libraries/LibGUI/Clipboard.h4
-rw-r--r--Libraries/LibGUI/WindowServerConnection.cpp5
-rw-r--r--Libraries/LibGUI/WindowServerConnection.h1
-rw-r--r--Services/CMakeLists.txt1
-rw-r--r--Services/Clipboard/CMakeLists.txt13
-rw-r--r--Services/Clipboard/ClientConnection.cpp103
-rw-r--r--Services/Clipboard/ClientConnection.h (renamed from Services/WindowServer/Clipboard.cpp)61
-rw-r--r--Services/Clipboard/ClipboardClient.ipc4
-rw-r--r--Services/Clipboard/ClipboardServer.ipc7
-rw-r--r--Services/Clipboard/Storage.cpp (renamed from Services/WindowServer/Clipboard.h)54
-rw-r--r--Services/Clipboard/Storage.h44
-rw-r--r--Services/Clipboard/WindowServer.ipc97
-rw-r--r--Services/Clipboard/main.cpp76
-rw-r--r--Services/WindowServer/CMakeLists.txt1
-rw-r--r--Services/WindowServer/ClientConnection.cpp40
-rw-r--r--Services/WindowServer/ClientConnection.h5
-rw-r--r--Services/WindowServer/EventLoop.cpp7
-rw-r--r--Services/WindowServer/WindowClient.ipc2
-rw-r--r--Services/WindowServer/WindowServer.ipc2
25 files changed, 447 insertions, 146 deletions
diff --git a/Applications/FileManager/main.cpp b/Applications/FileManager/main.cpp
index 3c9359fbde..31a2f4720d 100644
--- a/Applications/FileManager/main.cpp
+++ b/Applications/FileManager/main.cpp
@@ -607,7 +607,7 @@ int run_in_windowed_mode(RefPtr<Core::ConfigFile> config, String initial_locatio
},
window);
- GUI::Clipboard::the().on_content_change = [&](const String& data_type) {
+ GUI::Clipboard::the().on_change = [&](const String& data_type) {
auto current_location = directory_view.path();
paste_action->set_enabled(data_type == "file-list" && access(current_location.characters(), W_OK) == 0);
};
diff --git a/Base/etc/SystemServer.ini b/Base/etc/SystemServer.ini
index 6ce8893a01..0e9727be55 100644
--- a/Base/etc/SystemServer.ini
+++ b/Base/etc/SystemServer.ini
@@ -46,6 +46,12 @@ Priority=high
KeepAlive=1
User=window
+[Clipboard]
+Socket=/tmp/portal/clipboard
+SocketPermissions=660
+KeepAlive=1
+User=clipboard
+
[SystemMenu]
KeepAlive=1
User=anon
diff --git a/Base/etc/group b/Base/etc/group
index 6aecd0e7ae..5eafd79298 100644
--- a/Base/etc/group
+++ b/Base/etc/group
@@ -7,4 +7,5 @@ lookup:x:10:protocol,anon
protocol:x:11:anon
notify:x:12:anon
window:x:13:anon,notify
+clipboard:x:14:anon
users:x:100:anon
diff --git a/Base/etc/passwd b/Base/etc/passwd
index 67cf5d44b3..814e0d6f96 100644
--- a/Base/etc/passwd
+++ b/Base/etc/passwd
@@ -3,5 +3,6 @@ lookup:x:10:10:LookupServer,,,:/:/bin/false
protocol:x:11:11:ProtocolServer,,,:/:/bin/false
notify:x:12:12:NotificationServer,,,:/:/bin/false
window:x:13:13:WindowServer,,,:/:/bin/false
+clipboard:x:14:14:Clipboard,,,:/:/bin/false
anon:x:100:100:Anonymous,,,:/home/anon:/bin/sh
nona:x:200:200:Nona,,,:/home/nona:/bin/sh
diff --git a/Libraries/LibGUI/Application.cpp b/Libraries/LibGUI/Application.cpp
index b2d2121da9..7f7148b754 100644
--- a/Libraries/LibGUI/Application.cpp
+++ b/Libraries/LibGUI/Application.cpp
@@ -27,6 +27,7 @@
#include <LibCore/EventLoop.h>
#include <LibGUI/Action.h>
#include <LibGUI/Application.h>
+#include <LibGUI/Clipboard.h>
#include <LibGUI/Desktop.h>
#include <LibGUI/Label.h>
#include <LibGUI/MenuBar.h>
@@ -54,6 +55,7 @@ Application::Application(int argc, char** argv)
s_the = this;
m_event_loop = make<Core::EventLoop>();
WindowServerConnection::the();
+ Clipboard::initialize({});
if (argc > 0)
m_invoked_as = argv[0];
for (int i = 1; i < argc; i++) {
diff --git a/Libraries/LibGUI/Clipboard.cpp b/Libraries/LibGUI/Clipboard.cpp
index 8663f6a365..f596df1b7a 100644
--- a/Libraries/LibGUI/Clipboard.cpp
+++ b/Libraries/LibGUI/Clipboard.cpp
@@ -26,11 +26,32 @@
#include <AK/Badge.h>
#include <AK/SharedBuffer.h>
+#include <Clipboard/ClipboardClientEndpoint.h>
+#include <Clipboard/ClipboardServerEndpoint.h>
#include <LibGUI/Clipboard.h>
-#include <LibGUI/WindowServerConnection.h>
+#include <LibIPC/ServerConnection.h>
namespace GUI {
+class ClipboardServerConnection : public IPC::ServerConnection<ClipboardClientEndpoint, ClipboardServerEndpoint>
+ , public ClipboardClientEndpoint {
+ C_OBJECT(ClipboardServerConnection);
+
+public:
+ virtual void handshake() override
+ {
+ auto response = send_sync<Messages::ClipboardServer::Greet>();
+ set_my_client_id(response->client_id());
+ }
+
+private:
+ ClipboardServerConnection()
+ : IPC::ServerConnection<ClipboardClientEndpoint, ClipboardServerEndpoint>(*this, "/tmp/portal/clipboard")
+ {
+ }
+ virtual void handle(const Messages::ClipboardClient::ClipboardDataChanged&) override;
+};
+
Clipboard& Clipboard::the()
{
static Clipboard* s_the;
@@ -39,13 +60,25 @@ Clipboard& Clipboard::the()
return *s_the;
}
+ClipboardServerConnection* s_connection;
+
+static ClipboardServerConnection& connection()
+{
+ return *s_connection;
+}
+
+void Clipboard::initialize(Badge<Application>)
+{
+ s_connection = &ClipboardServerConnection::construct().leak_ref();
+}
+
Clipboard::Clipboard()
{
}
Clipboard::DataAndType Clipboard::data_and_type() const
{
- auto response = WindowServerConnection::the().send_sync<Messages::WindowServer::GetClipboardContents>();
+ auto response = connection().send_sync<Messages::ClipboardServer::GetClipboardData>();
if (response->shbuf_id() < 0)
return {};
auto shared_buffer = SharedBuffer::create_from_shbuf_id(response->shbuf_id());
@@ -53,12 +86,12 @@ Clipboard::DataAndType Clipboard::data_and_type() const
dbgprintf("GUI::Clipboard::data() failed to attach to the shared buffer\n");
return {};
}
- if (response->content_size() > shared_buffer->size()) {
+ if (response->data_size() > shared_buffer->size()) {
dbgprintf("GUI::Clipboard::data() clipping contents size is greater than shared buffer size\n");
return {};
}
- auto data = String((const char*)shared_buffer->data(), response->content_size());
- auto type = response->content_type();
+ auto data = String((const char*)shared_buffer->data(), response->data_size());
+ auto type = response->mime_type();
return { data, type };
}
@@ -74,15 +107,16 @@ void Clipboard::set_data(const StringView& data, const String& type)
else
((u8*)shared_buffer->data())[0] = '\0';
shared_buffer->seal();
- shared_buffer->share_with(WindowServerConnection::the().server_pid());
+ shared_buffer->share_with(connection().server_pid());
- WindowServerConnection::the().send_sync<Messages::WindowServer::SetClipboardContents>(shared_buffer->shbuf_id(), data.length(), type);
+ connection().send_sync<Messages::ClipboardServer::SetClipboardData>(shared_buffer->shbuf_id(), data.length(), type);
}
-void Clipboard::did_receive_clipboard_contents_changed(Badge<WindowServerConnection>, const String& data_type)
+void ClipboardServerConnection::handle(const Messages::ClipboardClient::ClipboardDataChanged& message)
{
- if (on_content_change)
- on_content_change(data_type);
+ auto& clipboard = Clipboard::the();
+ if (clipboard.on_change)
+ clipboard.on_change(message.mime_type());
}
}
diff --git a/Libraries/LibGUI/Clipboard.h b/Libraries/LibGUI/Clipboard.h
index 5504d91d88..e04e04c8f0 100644
--- a/Libraries/LibGUI/Clipboard.h
+++ b/Libraries/LibGUI/Clipboard.h
@@ -47,9 +47,9 @@ public:
DataAndType data_and_type() const;
- void did_receive_clipboard_contents_changed(Badge<WindowServerConnection>, const String& data_type);
+ Function<void(const String& data_type)> on_change;
- Function<void(const String& data_type)> on_content_change;
+ static void initialize(Badge<Application>);
private:
Clipboard();
diff --git a/Libraries/LibGUI/WindowServerConnection.cpp b/Libraries/LibGUI/WindowServerConnection.cpp
index e960c14ca3..6041429a26 100644
--- a/Libraries/LibGUI/WindowServerConnection.cpp
+++ b/Libraries/LibGUI/WindowServerConnection.cpp
@@ -280,11 +280,6 @@ void WindowServerConnection::handle(const Messages::WindowClient::ScreenRectChan
Desktop::the().did_receive_screen_rect({}, message.rect());
}
-void WindowServerConnection::handle(const Messages::WindowClient::ClipboardContentsChanged& message)
-{
- Clipboard::the().did_receive_clipboard_contents_changed({}, message.content_type());
-}
-
void WindowServerConnection::handle(const Messages::WindowClient::AsyncSetWallpaperFinished&)
{
// This is handled manually by Desktop::set_wallpaper().
diff --git a/Libraries/LibGUI/WindowServerConnection.h b/Libraries/LibGUI/WindowServerConnection.h
index 9ae71a9795..1bf058c42a 100644
--- a/Libraries/LibGUI/WindowServerConnection.h
+++ b/Libraries/LibGUI/WindowServerConnection.h
@@ -63,7 +63,6 @@ private:
virtual void handle(const Messages::WindowClient::WindowResized&) override;
virtual void handle(const Messages::WindowClient::MenuItemActivated&) override;
virtual void handle(const Messages::WindowClient::ScreenRectChanged&) override;
- virtual void handle(const Messages::WindowClient::ClipboardContentsChanged&) override;
virtual void handle(const Messages::WindowClient::WM_WindowRemoved&) override;
virtual void handle(const Messages::WindowClient::WM_WindowStateChanged&) override;
virtual void handle(const Messages::WindowClient::WM_WindowIconBitmapChanged&) override;
diff --git a/Services/CMakeLists.txt b/Services/CMakeLists.txt
index cf18e97b48..4a2b261d06 100644
--- a/Services/CMakeLists.txt
+++ b/Services/CMakeLists.txt
@@ -1,4 +1,5 @@
add_subdirectory(AudioServer)
+add_subdirectory(Clipboard)
add_subdirectory(DHCPClient)
add_subdirectory(LaunchServer)
add_subdirectory(LookupServer)
diff --git a/Services/Clipboard/CMakeLists.txt b/Services/Clipboard/CMakeLists.txt
new file mode 100644
index 0000000000..4f0e5ab65a
--- /dev/null
+++ b/Services/Clipboard/CMakeLists.txt
@@ -0,0 +1,13 @@
+compile_ipc(ClipboardServer.ipc ClipboardServerEndpoint.h)
+compile_ipc(ClipboardClient.ipc ClipboardClientEndpoint.h)
+
+set(SOURCES
+ ClientConnection.cpp
+ ClipboardClientEndpoint.h
+ ClipboardServerEndpoint.h
+ Storage.cpp
+ main.cpp
+)
+
+serenity_bin(Clipboard)
+target_link_libraries(Clipboard LibCore LibIPC)
diff --git a/Services/Clipboard/ClientConnection.cpp b/Services/Clipboard/ClientConnection.cpp
new file mode 100644
index 0000000000..16b882d1e9
--- /dev/null
+++ b/Services/Clipboard/ClientConnection.cpp
@@ -0,0 +1,103 @@
+/*
+ * 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 <AK/Badge.h>
+#include <AK/SharedBuffer.h>
+#include <Clipboard/ClientConnection.h>
+#include <Clipboard/ClipboardClientEndpoint.h>
+#include <Clipboard/Storage.h>
+
+namespace Clipboard {
+
+static HashMap<int, RefPtr<ClientConnection>> s_connections;
+
+void ClientConnection::for_each_client(Function<void(ClientConnection&)> callback)
+{
+ for (auto& it : s_connections) {
+ callback(*it.value);
+ }
+}
+
+ClientConnection::ClientConnection(Core::LocalSocket& socket, int client_id)
+ : IPC::ClientConnection<ClipboardServerEndpoint>(*this, socket, client_id)
+{
+ s_connections.set(client_id, *this);
+}
+
+ClientConnection::~ClientConnection()
+{
+}
+
+void ClientConnection::die()
+{
+ s_connections.remove(client_id());
+}
+
+OwnPtr<Messages::ClipboardServer::GreetResponse> ClientConnection::handle(const Messages::ClipboardServer::Greet&)
+{
+ return make<Messages::ClipboardServer::GreetResponse>(client_id());
+}
+
+OwnPtr<Messages::ClipboardServer::SetClipboardDataResponse> ClientConnection::handle(const Messages::ClipboardServer::SetClipboardData& message)
+{
+ auto shared_buffer = SharedBuffer::create_from_shbuf_id(message.shbuf_id());
+ if (!shared_buffer) {
+ did_misbehave("SetClipboardData: Bad shared buffer ID");
+ return nullptr;
+ }
+ Storage::the().set_data(*shared_buffer, message.data_size(), message.mime_type());
+ return make<Messages::ClipboardServer::SetClipboardDataResponse>();
+}
+
+OwnPtr<Messages::ClipboardServer::GetClipboardDataResponse> ClientConnection::handle(const Messages::ClipboardServer::GetClipboardData&)
+{
+ auto& storage = Storage::the();
+
+ i32 shbuf_id = -1;
+ if (storage.data_size()) {
+ // FIXME: Optimize case where an app is copy/pasting within itself.
+ // We can just reuse the SharedBuffer then, since it will have the same peer PID.
+ // It would be even nicer if a SharedBuffer could have an arbitrary number of clients..
+ RefPtr<SharedBuffer> shared_buffer = SharedBuffer::create_with_size(storage.data_size());
+ ASSERT(shared_buffer);
+ memcpy(shared_buffer->data(), storage.data(), storage.data_size());
+ shared_buffer->seal();
+ shared_buffer->share_with(client_pid());
+ shbuf_id = shared_buffer->shbuf_id();
+
+ // FIXME: This is a workaround for the fact that SharedBuffers will go away if neither side is retaining them.
+ // After we respond to GetClipboardData, we have to wait for the client to ref the buffer on his side.
+ m_last_sent_buffer = move(shared_buffer);
+ }
+ return make<Messages::ClipboardServer::GetClipboardDataResponse>(shbuf_id, storage.data_size(), storage.mime_type());
+}
+
+void ClientConnection::notify_about_clipboard_change()
+{
+ post_message(Messages::ClipboardClient::ClipboardDataChanged(Storage::the().mime_type()));
+}
+
+}
diff --git a/Services/WindowServer/Clipboard.cpp b/Services/Clipboard/ClientConnection.h
index 4d9db8b4bc..904b04abc1 100644
--- a/Services/WindowServer/Clipboard.cpp
+++ b/Services/Clipboard/ClientConnection.h
@@ -24,55 +24,34 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <WindowServer/Clipboard.h>
+#pragma once
-namespace WindowServer {
+#include <AK/HashMap.h>
+#include <Clipboard/ClipboardServerEndpoint.h>
+#include <LibIPC/ClientConnection.h>
-Clipboard& Clipboard::the()
-{
- static Clipboard* s_the;
- if (!s_the)
- s_the = new Clipboard;
- return *s_the;
-}
+namespace Clipboard {
-Clipboard::Clipboard()
-{
-}
+class ClientConnection final : public IPC::ClientConnection<ClipboardServerEndpoint>
+ , public ClipboardServerEndpoint {
+ C_OBJECT(ClientConnection);
-Clipboard::~Clipboard()
-{
-}
+public:
+ explicit ClientConnection(Core::LocalSocket&, int client_id);
+ virtual ~ClientConnection() override;
-const u8* Clipboard::data() const
-{
- if (!m_shared_buffer)
- return nullptr;
- return (const u8*)m_shared_buffer->data();
-}
+ virtual void die() override;
-int Clipboard::size() const
-{
- if (!m_shared_buffer)
- return 0;
- return m_contents_size;
-}
+ static void for_each_client(Function<void(ClientConnection&)>);
-void Clipboard::clear()
-{
- m_shared_buffer = nullptr;
- m_contents_size = 0;
-}
+ void notify_about_clipboard_change();
-void Clipboard::set_data(NonnullRefPtr<SharedBuffer>&& data, int contents_size, const String& data_type)
-{
- dbg() << "Clipboard::set_data <- [" << data_type << "] " << data->data() << " (" << contents_size << " bytes)";
- m_shared_buffer = move(data);
- m_contents_size = contents_size;
- m_data_type = data_type;
+private:
+ virtual OwnPtr<Messages::ClipboardServer::GreetResponse> handle(const Messages::ClipboardServer::Greet&) override;
+ virtual OwnPtr<Messages::ClipboardServer::GetClipboardDataResponse> handle(const Messages::ClipboardServer::GetClipboardData&) override;
+ virtual OwnPtr<Messages::ClipboardServer::SetClipboardDataResponse> handle(const Messages::ClipboardServer::SetClipboardData&) override;
- if (on_content_change)
- on_content_change();
-}
+ RefPtr<SharedBuffer> m_last_sent_buffer;
+};
}
diff --git a/Services/Clipboard/ClipboardClient.ipc b/Services/Clipboard/ClipboardClient.ipc
new file mode 100644
index 0000000000..4434c56f21
--- /dev/null
+++ b/Services/Clipboard/ClipboardClient.ipc
@@ -0,0 +1,4 @@
+endpoint ClipboardClient = 804
+{
+ ClipboardDataChanged(String mime_type) =|
+}
diff --git a/Services/Clipboard/ClipboardServer.ipc b/Services/Clipboard/ClipboardServer.ipc
new file mode 100644
index 0000000000..4b419459ec
--- /dev/null
+++ b/Services/Clipboard/ClipboardServer.ipc
@@ -0,0 +1,7 @@
+endpoint ClipboardServer = 802
+{
+ Greet() => (i32 client_id)
+
+ GetClipboardData() => (i32 shbuf_id, i32 data_size, String mime_type)
+ SetClipboardData(i32 shbuf_id, i32 data_size, String mime_type) => ()
+}
diff --git a/Services/WindowServer/Clipboard.h b/Services/Clipboard/Storage.cpp
index 6cb9140234..f64b5a4f70 100644
--- a/Services/WindowServer/Clipboard.h
+++ b/Services/Clipboard/Storage.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,39 +24,35 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#pragma once
+#include <Clipboard/Storage.h>
-#include <AK/Function.h>
-#include <AK/SharedBuffer.h>
-#include <AK/String.h>
+namespace Clipboard {
-namespace WindowServer {
-
-class Clipboard {
-public:
- static Clipboard& the();
- ~Clipboard();
-
- bool has_data() const
- {
- return m_shared_buffer;
- }
-
- const String& data_type() const { return m_data_type; }
- const u8* data() const;
- int size() const;
+Storage& Storage::the()
+{
+ static Storage* s_the;
+ if (!s_the)
+ s_the = new Storage;
+ return *s_the;
+}
- void clear();
- void set_data(NonnullRefPtr<SharedBuffer>&&, int contents_size, const String& data_type);
+Storage::Storage()
+{
+}
- Function<void()> on_content_change;
+Storage::~Storage()
+{
+}
-private:
- Clipboard();
+void Storage::set_data(NonnullRefPtr<SharedBuffer> data, size_t data_size, const String& mime_type)
+{
+ dbg() << "Storage::set_data <- [" << mime_type << "] " << data->data() << " (" << data_size << " bytes)";
+ m_shared_buffer = move(data);
+ m_data_size = data_size;
+ m_mime_type = mime_type;
- String m_data_type;
- RefPtr<SharedBuffer> m_shared_buffer;
- int m_contents_size { 0 };
-};
+ if (on_content_change)
+ on_content_change();
+}
}
diff --git a/Services/Clipboard/Storage.h b/Services/Clipboard/Storage.h
new file mode 100644
index 0000000000..7f38c3d1db
--- /dev/null
+++ b/Services/Clipboard/Storage.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include <AK/Function.h>
+#include <AK/SharedBuffer.h>
+#include <AK/String.h>
+
+namespace Clipboard {
+
+class Storage {
+public:
+ static Storage& the();
+ ~Storage();
+
+ bool has_data() const { return m_shared_buffer; }
+
+ const String& mime_type() const { return m_mime_type; }
+
+ const u8* data() const
+ {
+ if (!has_data())
+ return nullptr;
+ return static_cast<const u8*>(m_shared_buffer->data());
+ }
+
+ size_t data_size() const
+ {
+ if (has_data())
+ return m_data_size;
+ return 0;
+ }
+
+ void set_data(NonnullRefPtr<SharedBuffer>, size_t data_size, const String& mime_type);
+
+ Function<void()> on_content_change;
+
+private:
+ Storage();
+
+ String m_mime_type;
+ RefPtr<SharedBuffer> m_shared_buffer;
+ size_t m_data_size { 0 };
+};
+
+}
diff --git a/Services/Clipboard/WindowServer.ipc b/Services/Clipboard/WindowServer.ipc
new file mode 100644
index 0000000000..1d678cbfb5
--- /dev/null
+++ b/Services/Clipboard/WindowServer.ipc
@@ -0,0 +1,97 @@
+endpoint WindowServer = 2
+{
+ Greet() => (i32 client_id, Gfx::Rect screen_rect, i32 system_theme_buffer_id)
+
+ CreateMenubar() => (i32 menubar_id)
+ DestroyMenubar(i32 menubar_id) => ()
+
+ CreateMenu(String menu_title) => (i32 menu_id)
+ DestroyMenu(i32 menu_id) => ()
+
+ AddMenuToMenubar(i32 menubar_id, i32 menu_id) => ()
+ SetApplicationMenubar(i32 menubar_id) => ()
+
+ SetSystemMenu(i32 menu_id) => ()
+
+ AddMenuItem(
+ i32 menu_id,
+ i32 identifier,
+ i32 submenu_id,
+ String text,
+ bool enabled,
+ bool checkable,
+ bool checked,
+ String shortcut,
+ i32 icon_buffer_id,
+ bool exclusive) => ()
+
+ AddMenuSeparator(i32 menu_id) => ()
+
+ UpdateMenuItem(i32 menu_id, i32 identifier, i32 submenu_id, String text, bool enabled, bool checkable, bool checked, String shortcut) => ()
+
+ CreateWindow(
+ Gfx::Rect rect,
+ bool has_alpha_channel,
+ bool modal,
+ bool minimizable,
+ bool resizable,
+ bool fullscreen,
+ bool frameless,
+ float opacity,
+ Gfx::Size base_size,
+ Gfx::Size size_increment,
+ i32 type,
+ String title,
+ i32 parent_window_id) => (i32 window_id)
+
+ DestroyWindow(i32 window_id) => (Vector<i32> destroyed_window_ids)
+
+ SetWindowTitle(i32 window_id, String title) => ()
+ GetWindowTitle(i32 window_id) => (String title)
+
+ SetWindowRect(i32 window_id, Gfx::Rect rect) => (Gfx::Rect rect)
+ GetWindowRect(i32 window_id) => (Gfx::Rect rect)
+
+ InvalidateRect(i32 window_id, Vector<Gfx::Rect> rects, bool ignore_occlusion) =|
+ DidFinishPainting(i32 window_id, Vector<Gfx::Rect> rects) =|
+
+ SetGlobalCursorTracking(i32 window_id, bool enabled) => ()
+ SetWindowOpacity(i32 window_id, float opacity) => ()
+
+ SetWindowBackingStore(i32 window_id, i32 bpp, i32 pitch, i32 shbuf_id, bool has_alpha_channel, Gfx::Size size, bool flush_immediately) => ()
+ GetClipboardData() => (i32 shbuf_id, i32 content_size, String content_type)
+ SetClipboardData(i32 shbuf_id, i32 content_size, String content_type) => ()
+
+ WM_SetActiveWindow(i32 client_id, i32 window_id) =|
+ WM_SetWindowMinimized(i32 client_id, i32 window_id, bool minimized) =|
+ WM_StartWindowResize(i32 client_id, i32 window_id) =|
+ WM_PopupWindowMenu(i32 client_id, i32 window_id, Gfx::Point screen_position) =|
+ WM_SetWindowTaskbarRect(i32 client_id, i32 window_id, Gfx::Rect rect) =|
+
+ SetWindowHasAlphaChannel(i32 window_id, bool has_alpha_channel) => ()
+ MoveWindowToFront(i32 window_id) => ()
+ SetFullscreen(i32 window_id, bool fullscreen) => ()
+ PopupMenu(i32 menu_id, Gfx::Point screen_position) => ()
+ DismissMenu(i32 menu_id) => ()
+
+ AsyncSetWallpaper(String path) =|
+
+ SetBackgroundColor(String background_color) => ()
+ SetWallpaperMode(String mode) => ()
+
+ SetResolution(Gfx::Size resolution) => (bool success, Gfx::Size resolution)
+ SetWindowIconBitmap(i32 window_id, Gfx::ShareableBitmap icon) => ()
+
+ GetWallpaper() => (String path)
+ SetWindowOverrideCursor(i32 window_id, i32 cursor_type) => ()
+
+ StartDrag(String text, String data_type, String data, i32 bitmap_id, Gfx::Size bitmap_size) => (bool started)
+
+ SetSystemTheme(String theme_path, String theme_name) => (bool success)
+ GetSystemTheme() => (String theme_name)
+
+ SetWindowBaseSizeAndSizeIncrement(i32 window_id, Gfx::Size base_size, Gfx::Size size_increment) => ()
+
+ EnableDisplayLink() =|
+ DisableDisplayLink() =|
+}
diff --git a/Services/Clipboard/main.cpp b/Services/Clipboard/main.cpp
new file mode 100644
index 0000000000..18839418b8
--- /dev/null
+++ b/Services/Clipboard/main.cpp
@@ -0,0 +1,76 @@
+/*
+ * 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 <Clipboard/ClientConnection.h>
+#include <Clipboard/Storage.h>
+#include <LibCore/EventLoop.h>
+#include <LibCore/LocalServer.h>
+#include <LibIPC/ClientConnection.h>
+
+int main(int, char**)
+{
+ if (pledge("stdio shared_buffer accept unix rpath cpath fattr", nullptr) < 0) {
+ perror("pledge");
+ return 1;
+ }
+ Core::EventLoop event_loop;
+ if (pledge("stdio shared_buffer unix accept", nullptr) < 0) {
+ perror("pledge");
+ return 1;
+ }
+ if (unveil(nullptr, nullptr) < 0) {
+ perror("unveil");
+ return 1;
+ }
+
+ auto server = Core::LocalServer::construct();
+ bool ok = server->take_over_from_system_server();
+ ASSERT(ok);
+
+ if (pledge("stdio shared_buffer accept", nullptr) < 0) {
+ perror("pledge");
+ return 1;
+ }
+
+ server->on_ready_to_accept = [&] {
+ auto client_socket = server->accept();
+ if (!client_socket) {
+ dbg() << "ProtocolServer: accept failed.";
+ return;
+ }
+ static int s_next_client_id = 0;
+ int client_id = ++s_next_client_id;
+ IPC::new_client_connection<Clipboard::ClientConnection>(*client_socket, client_id);
+ };
+
+ Clipboard::Storage::the().on_content_change = [&] {
+ Clipboard::ClientConnection::for_each_client([&](auto& client) {
+ client.notify_about_clipboard_change();
+ });
+ };
+
+ return event_loop.exec();
+}
diff --git a/Services/WindowServer/CMakeLists.txt b/Services/WindowServer/CMakeLists.txt
index af14d6aa96..b822fec6b5 100644
--- a/Services/WindowServer/CMakeLists.txt
+++ b/Services/WindowServer/CMakeLists.txt
@@ -5,7 +5,6 @@ set(SOURCES
AppletManager.cpp
Button.cpp
ClientConnection.cpp
- Clipboard.cpp
Compositor.cpp
Cursor.cpp
EventLoop.cpp
diff --git a/Services/WindowServer/ClientConnection.cpp b/Services/WindowServer/ClientConnection.cpp
index 16827c9cd8..3b1deebc28 100644
--- a/Services/WindowServer/ClientConnection.cpp
+++ b/Services/WindowServer/ClientConnection.cpp
@@ -30,7 +30,6 @@
#include <LibGfx/SystemTheme.h>
#include <WindowServer/AppletManager.h>
#include <WindowServer/ClientConnection.h>
-#include <WindowServer/Clipboard.h>
#include <WindowServer/Compositor.h>
#include <WindowServer/EventLoop.h>
#include <WindowServer/Menu.h>
@@ -112,11 +111,6 @@ void ClientConnection::notify_about_new_screen_rect(const Gfx::Rect& rect)
post_message(Messages::WindowClient::ScreenRectChanged(rect));
}
-void ClientConnection::notify_about_clipboard_contents_changed()
-{
- post_message(Messages::WindowClient::ClipboardContentsChanged(Clipboard::the().data_type()));
-}
-
OwnPtr<Messages::WindowServer::CreateMenubarResponse> ClientConnection::handle(const Messages::WindowServer::CreateMenubar&)
{
int menubar_id = m_next_menubar_id++;
@@ -417,40 +411,6 @@ OwnPtr<Messages::WindowServer::GetWindowRectResponse> ClientConnection::handle(c
return make<Messages::WindowServer::GetWindowRectResponse>(it->value->rect());
}
-OwnPtr<Messages::WindowServer::SetClipboardContentsResponse> ClientConnection::handle(const Messages::WindowServer::SetClipboardContents& message)
-{
- auto shared_buffer = SharedBuffer::create_from_shbuf_id(message.shbuf_id());
- if (!shared_buffer) {
- did_misbehave("SetClipboardContents: Bad shared buffer ID");
- return nullptr;
- }
- Clipboard::the().set_data(*shared_buffer, message.content_size(), message.content_type());
- return make<Messages::WindowServer::SetClipboardContentsResponse>();
-}
-
-OwnPtr<Messages::WindowServer::GetClipboardContentsResponse> ClientConnection::handle(const Messages::WindowServer::GetClipboardContents&)
-{
- auto& clipboard = Clipboard::the();
-
- i32 shbuf_id = -1;
- if (clipboard.size()) {
- // FIXME: Optimize case where an app is copy/pasting within itself.
- // We can just reuse the SharedBuffer then, since it will have the same peer PID.
- // It would be even nicer if a SharedBuffer could have an arbitrary number of clients..
- RefPtr<SharedBuffer> shared_buffer = SharedBuffer::create_with_size(clipboard.size());
- ASSERT(shared_buffer);
- memcpy(shared_buffer->data(), clipboard.data(), clipboard.size());
- shared_buffer->seal();
- shared_buffer->share_with(client_pid());
- shbuf_id = shared_buffer->shbuf_id();
-
- // FIXME: This is a workaround for the fact that SharedBuffers will go away if neither side is retaining them.
- // After we respond to GetClipboardContents, we have to wait for the client to ref the buffer on his side.
- m_last_sent_clipboard_content = move(shared_buffer);
- }
- return make<Messages::WindowServer::GetClipboardContentsResponse>(shbuf_id, clipboard.size(), clipboard.data_type());
-}
-
Window* ClientConnection::window_from_id(i32 window_id)
{
auto it = m_windows.find(window_id);
diff --git a/Services/WindowServer/ClientConnection.h b/Services/WindowServer/ClientConnection.h
index 92c2f2fa08..bedcdb5e91 100644
--- a/Services/WindowServer/ClientConnection.h
+++ b/Services/WindowServer/ClientConnection.h
@@ -63,7 +63,6 @@ public:
bool is_showing_modal_window() const;
void notify_about_new_screen_rect(const Gfx::Rect&);
- void notify_about_clipboard_contents_changed();
void post_paint_message(Window&, bool ignore_occlusion = false);
Menu* find_menu_by_id(int menu_id)
@@ -102,8 +101,6 @@ private:
virtual OwnPtr<Messages::WindowServer::SetGlobalCursorTrackingResponse> handle(const Messages::WindowServer::SetGlobalCursorTracking&) override;
virtual OwnPtr<Messages::WindowServer::SetWindowOpacityResponse> handle(const Messages::WindowServer::SetWindowOpacity&) override;
virtual OwnPtr<Messages::WindowServer::SetWindowBackingStoreResponse> handle(const Messages::WindowServer::SetWindowBackingStore&) override;
- virtual OwnPtr<Messages::WindowServer::GetClipboardContentsResponse> handle(const Messages::WindowServer::GetClipboardContents&) override;
- virtual OwnPtr<Messages::WindowServer::SetClipboardContentsResponse> handle(const Messages::WindowServer::SetClipboardContents&) override;
virtual void handle(const Messages::WindowServer::WM_SetActiveWindow&) override;
virtual void handle(const Messages::WindowServer::WM_SetWindowMinimized&) override;
virtual void handle(const Messages::WindowServer::WM_StartWindowResize&) override;
@@ -141,8 +138,6 @@ private:
int m_next_window_id { 1982 };
bool m_has_display_link { false };
-
- RefPtr<SharedBuffer> m_last_sent_clipboard_content;
};
}
diff --git a/Services/WindowServer/EventLoop.cpp b/Services/WindowServer/EventLoop.cpp
index 078794d6f3..45a34e9055 100644
--- a/Services/WindowServer/EventLoop.cpp
+++ b/Services/WindowServer/EventLoop.cpp
@@ -24,7 +24,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "Clipboard.h"
#include <Kernel/KeyCode.h>
#include <Kernel/MousePacket.h>
#include <LibCore/LocalSocket.h>
@@ -76,12 +75,6 @@ EventLoop::EventLoop()
m_mouse_notifier = Core::Notifier::construct(m_mouse_fd, Core::Notifier::Read);
m_mouse_notifier->on_ready_to_read = [this] { drain_mouse(); };
-
- Clipboard::the().on_content_change = [&] {
- ClientConnection::for_each_client([&](auto& client) {
- client.notify_about_clipboard_contents_changed();
- });
- };
}
EventLoop::~EventLoop()
diff --git a/Services/WindowServer/WindowClient.ipc b/Services/WindowServer/WindowClient.ipc
index 3c94ccf89e..ec04a2a91a 100644
--- a/Services/WindowServer/WindowClient.ipc
+++ b/Services/WindowServer/WindowClient.ipc
@@ -20,8 +20,6 @@ endpoint WindowClient = 4
ScreenRectChanged(Gfx::Rect rect) =|
- ClipboardContentsChanged(String content_type) =|
-
WM_WindowRemoved(i32 wm_id, i32 client_id, i32 window_id) =|
WM_WindowStateChanged(i32 wm_id, i32 client_id, i32 window_id, bool is_active, bool is_minimized, bool is_frameless, i32 window_type, String title, Gfx::Rect rect) =|
WM_WindowIconBitmapChanged(i32 wm_id, i32 client_id, i32 window_id, i32 icon_buffer_id, Gfx::Size icon_size) =|
diff --git a/Services/WindowServer/WindowServer.ipc b/Services/WindowServer/WindowServer.ipc
index 214afa7567..8d958823a0 100644
--- a/Services/WindowServer/WindowServer.ipc
+++ b/Services/WindowServer/WindowServer.ipc
@@ -59,8 +59,6 @@ endpoint WindowServer = 2
SetWindowOpacity(i32 window_id, float opacity) => ()
SetWindowBackingStore(i32 window_id, i32 bpp, i32 pitch, i32 shbuf_id, bool has_alpha_channel, Gfx::Size size, bool flush_immediately) => ()
- GetClipboardContents() => (i32 shbuf_id, i32 content_size, String content_type)
- SetClipboardContents(i32 shbuf_id, i32 content_size, String content_type) => ()
WM_SetActiveWindow(i32 client_id, i32 window_id) =|
WM_SetWindowMinimized(i32 client_id, i32 window_id, bool minimized) =|