GClipboard.cpp 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. #include <LibC/SharedBuffer.h>
  2. #include <LibGUI/GClipboard.h>
  3. #include <LibGUI/GEventLoop.h>
  4. #include <WindowServer/WSAPITypes.h>
  5. GClipboard& GClipboard::the()
  6. {
  7. static GClipboard* s_the;
  8. if (!s_the)
  9. s_the = new GClipboard;
  10. return *s_the;
  11. }
  12. GClipboard::GClipboard()
  13. {
  14. }
  15. GClipboard::DataAndType GClipboard::data_and_type() const
  16. {
  17. WSAPI_ClientMessage request;
  18. request.type = WSAPI_ClientMessage::Type::GetClipboardContents;
  19. auto response = GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidGetClipboardContents);
  20. if (response.clipboard.shared_buffer_id < 0)
  21. return {};
  22. auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(response.clipboard.shared_buffer_id);
  23. if (!shared_buffer) {
  24. dbgprintf("GClipboard::data() failed to attach to the shared buffer\n");
  25. return {};
  26. }
  27. if (response.clipboard.contents_size > shared_buffer->size()) {
  28. dbgprintf("GClipboard::data() clipping contents size is greater than shared buffer size\n");
  29. return {};
  30. }
  31. auto data = String((const char*)shared_buffer->data(), response.clipboard.contents_size);
  32. auto type = String(response.text, response.text_length);
  33. return { data, type };
  34. }
  35. void GClipboard::set_data(const StringView& data, const String& type)
  36. {
  37. WSAPI_ClientMessage request;
  38. request.type = WSAPI_ClientMessage::Type::SetClipboardContents;
  39. auto shared_buffer = SharedBuffer::create_with_size(data.length() + 1);
  40. if (!shared_buffer) {
  41. dbgprintf("GClipboard::set_data() failed to create a shared buffer\n");
  42. return;
  43. }
  44. if (!data.is_empty())
  45. memcpy(shared_buffer->data(), data.characters_without_null_termination(), data.length() + 1);
  46. else
  47. ((u8*)shared_buffer->data())[0] = '\0';
  48. shared_buffer->seal();
  49. shared_buffer->share_with(GWindowServerConnection::the().server_pid());
  50. request.clipboard.shared_buffer_id = shared_buffer->shared_buffer_id();
  51. request.clipboard.contents_size = data.length();
  52. ASSERT(type.length() < (ssize_t)sizeof(request.text));
  53. if (!type.is_null())
  54. strcpy(request.text, type.characters());
  55. request.text_length = type.length();
  56. auto response = GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidSetClipboardContents);
  57. ASSERT(response.clipboard.shared_buffer_id == shared_buffer->shared_buffer_id());
  58. }
  59. void GClipboard::did_receive_clipboard_contents_changed(Badge<GWindowServerConnection>, const String& data_type)
  60. {
  61. if (on_content_change)
  62. on_content_change(data_type);
  63. }