Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <AK/Badge.h>
28#include <AK/SharedBuffer.h>
29#include <LibGUI/Clipboard.h>
30#include <LibGUI/WindowServerConnection.h>
31
32namespace GUI {
33
34Clipboard& Clipboard::the()
35{
36 static Clipboard* s_the;
37 if (!s_the)
38 s_the = new Clipboard;
39 return *s_the;
40}
41
42Clipboard::Clipboard()
43{
44}
45
46Clipboard::DataAndType Clipboard::data_and_type() const
47{
48 auto response = WindowServerConnection::the().send_sync<Messages::WindowServer::GetClipboardContents>();
49 if (response->shbuf_id() < 0)
50 return {};
51 auto shared_buffer = SharedBuffer::create_from_shbuf_id(response->shbuf_id());
52 if (!shared_buffer) {
53 dbgprintf("GUI::Clipboard::data() failed to attach to the shared buffer\n");
54 return {};
55 }
56 if (response->content_size() > shared_buffer->size()) {
57 dbgprintf("GUI::Clipboard::data() clipping contents size is greater than shared buffer size\n");
58 return {};
59 }
60 auto data = String((const char*)shared_buffer->data(), response->content_size());
61 auto type = response->content_type();
62 return { data, type };
63}
64
65void Clipboard::set_data(const StringView& data, const String& type)
66{
67 auto shared_buffer = SharedBuffer::create_with_size(data.length() + 1);
68 if (!shared_buffer) {
69 dbgprintf("GUI::Clipboard::set_data() failed to create a shared buffer\n");
70 return;
71 }
72 if (!data.is_empty())
73 memcpy(shared_buffer->data(), data.characters_without_null_termination(), data.length() + 1);
74 else
75 ((u8*)shared_buffer->data())[0] = '\0';
76 shared_buffer->seal();
77 shared_buffer->share_with(WindowServerConnection::the().server_pid());
78
79 WindowServerConnection::the().send_sync<Messages::WindowServer::SetClipboardContents>(shared_buffer->shbuf_id(), data.length(), type);
80}
81
82void Clipboard::did_receive_clipboard_contents_changed(Badge<WindowServerConnection>, const String& data_type)
83{
84 if (on_content_change)
85 on_content_change(data_type);
86}
87
88}