/* * Copyright © 2020 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "config.h" #include #include "gdkmacosclipboard-private.h" #include "gdkmacospasteboard-private.h" #include "gdkmacosutils-private.h" #include "gdkprivate.h" struct _GdkMacosClipboard { GdkClipboard parent_instance; NSPasteboard *pasteboard; NSInteger last_change_count; }; G_DEFINE_TYPE (GdkMacosClipboard, _gdk_macos_clipboard, GDK_TYPE_CLIPBOARD) static void _gdk_macos_clipboard_load_contents (GdkMacosClipboard *self) { GdkContentFormats *formats; NSInteger change_count; g_assert (GDK_IS_MACOS_CLIPBOARD (self)); change_count = [self->pasteboard changeCount]; formats = _gdk_macos_pasteboard_load_formats (self->pasteboard); gdk_clipboard_claim_remote (GDK_CLIPBOARD (self), formats); gdk_content_formats_unref (formats); self->last_change_count = change_count; } static void _gdk_macos_clipboard_read_async (GdkClipboard *clipboard, GdkContentFormats *formats, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { _gdk_macos_pasteboard_read_async (G_OBJECT (clipboard), GDK_MACOS_CLIPBOARD (clipboard)->pasteboard, formats, io_priority, cancellable, callback, user_data); } static GInputStream * _gdk_macos_clipboard_read_finish (GdkClipboard *clipboard, GAsyncResult *result, const char **out_mime_type, GError **error) { return _gdk_macos_pasteboard_read_finish (G_OBJECT (clipboard), result, out_mime_type, error); } static void _gdk_macos_clipboard_send_to_pasteboard (GdkMacosClipboard *self, GdkContentProvider *content) { GdkMacosPasteboardItem *item; NSArray *items; g_assert (GDK_IS_MACOS_CLIPBOARD (self)); g_assert (GDK_IS_CONTENT_PROVIDER (content)); if (self->pasteboard == NULL) return; GDK_BEGIN_MACOS_ALLOC_POOL; item = [[GdkMacosPasteboardItem alloc] initForClipboard:GDK_CLIPBOARD (self) withContentProvider:content]; items = [NSArray arrayWithObject:item]; [self->pasteboard clearContents]; if ([self->pasteboard writeObjects:items] == NO) g_warning ("Failed to send clipboard to pasteboard"); self->last_change_count = [self->pasteboard changeCount]; GDK_END_MACOS_ALLOC_POOL; } static gboolean _gdk_macos_clipboard_claim (GdkClipboard *clipboard, GdkContentFormats *formats, gboolean local, GdkContentProvider *provider) { GdkMacosClipboard *self = (GdkMacosClipboard *)clipboard; gboolean ret; g_assert (GDK_IS_CLIPBOARD (clipboard)); g_assert (formats != NULL); g_assert (!provider || GDK_IS_CONTENT_PROVIDER (provider)); ret = GDK_CLIPBOARD_CLASS (_gdk_macos_clipboard_parent_class)->claim (clipboard, formats, local, provider); if (local) _gdk_macos_clipboard_send_to_pasteboard (self, provider); return ret; } static void _gdk_macos_clipboard_constructed (GObject *object) { GdkMacosClipboard *self = (GdkMacosClipboard *)object; if (self->pasteboard == nil) self->pasteboard = [[NSPasteboard generalPasteboard] retain]; G_OBJECT_CLASS (_gdk_macos_clipboard_parent_class)->constructed (object); } static void _gdk_macos_clipboard_finalize (GObject *object) { GdkMacosClipboard *self = (GdkMacosClipboard *)object; if (self->pasteboard != nil) { [self->pasteboard release]; self->pasteboard = nil; } G_OBJECT_CLASS (_gdk_macos_clipboard_parent_class)->finalize (object); } static void _gdk_macos_clipboard_class_init (GdkMacosClipboardClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GdkClipboardClass *clipboard_class = GDK_CLIPBOARD_CLASS (klass); object_class->constructed = _gdk_macos_clipboard_constructed; object_class->finalize = _gdk_macos_clipboard_finalize; clipboard_class->claim = _gdk_macos_clipboard_claim; clipboard_class->read_async = _gdk_macos_clipboard_read_async; clipboard_class->read_finish = _gdk_macos_clipboard_read_finish; } static void _gdk_macos_clipboard_init (GdkMacosClipboard *self) { } GdkClipboard * _gdk_macos_clipboard_new (GdkMacosDisplay *display) { GdkMacosClipboard *self; g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL); self = g_object_new (GDK_TYPE_MACOS_CLIPBOARD, "display", display, NULL); _gdk_macos_clipboard_load_contents (self); return GDK_CLIPBOARD (self); } void _gdk_macos_clipboard_check_externally_modified (GdkMacosClipboard *self) { g_return_if_fail (GDK_IS_MACOS_CLIPBOARD (self)); if ([self->pasteboard changeCount] != self->last_change_count) _gdk_macos_clipboard_load_contents (self); }