qemu/ui/clipboard.c
<<
>>
Prefs
   1#include "qemu/osdep.h"
   2#include "ui/clipboard.h"
   3
   4static NotifierList clipboard_notifiers =
   5    NOTIFIER_LIST_INITIALIZER(clipboard_notifiers);
   6
   7static QemuClipboardInfo *cbinfo[QEMU_CLIPBOARD_SELECTION__COUNT];
   8
   9void qemu_clipboard_peer_register(QemuClipboardPeer *peer)
  10{
  11    notifier_list_add(&clipboard_notifiers, &peer->update);
  12}
  13
  14void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer)
  15{
  16    int i;
  17
  18    for (i = 0; i < QEMU_CLIPBOARD_SELECTION__COUNT; i++) {
  19        qemu_clipboard_peer_release(peer, i);
  20    }
  21
  22    notifier_remove(&peer->update);
  23}
  24
  25bool qemu_clipboard_peer_owns(QemuClipboardPeer *peer,
  26                              QemuClipboardSelection selection)
  27{
  28    QemuClipboardInfo *info = qemu_clipboard_info(selection);
  29
  30    return info && info->owner == peer;
  31}
  32
  33void qemu_clipboard_peer_release(QemuClipboardPeer *peer,
  34                                 QemuClipboardSelection selection)
  35{
  36    g_autoptr(QemuClipboardInfo) info = NULL;
  37
  38    if (qemu_clipboard_peer_owns(peer, selection)) {
  39        /* set empty clipboard info */
  40        info = qemu_clipboard_info_new(NULL, selection);
  41        qemu_clipboard_update(info);
  42    }
  43}
  44
  45void qemu_clipboard_update(QemuClipboardInfo *info)
  46{
  47    g_autoptr(QemuClipboardInfo) old = NULL;
  48    assert(info->selection < QEMU_CLIPBOARD_SELECTION__COUNT);
  49
  50    notifier_list_notify(&clipboard_notifiers, info);
  51
  52    old = cbinfo[info->selection];
  53    cbinfo[info->selection] = qemu_clipboard_info_ref(info);
  54}
  55
  56QemuClipboardInfo *qemu_clipboard_info(QemuClipboardSelection selection)
  57{
  58    assert(selection < QEMU_CLIPBOARD_SELECTION__COUNT);
  59
  60    return cbinfo[selection];
  61}
  62
  63QemuClipboardInfo *qemu_clipboard_info_new(QemuClipboardPeer *owner,
  64                                           QemuClipboardSelection selection)
  65{
  66    QemuClipboardInfo *info = g_new0(QemuClipboardInfo, 1);
  67
  68    info->owner = owner;
  69    info->selection = selection;
  70    info->refcount = 1;
  71
  72    return info;
  73}
  74
  75QemuClipboardInfo *qemu_clipboard_info_ref(QemuClipboardInfo *info)
  76{
  77    info->refcount++;
  78    return info;
  79}
  80
  81void qemu_clipboard_info_unref(QemuClipboardInfo *info)
  82{
  83    uint32_t type;
  84
  85    if (!info) {
  86        return;
  87    }
  88
  89    info->refcount--;
  90    if (info->refcount > 0) {
  91        return;
  92    }
  93
  94    for (type = 0; type < QEMU_CLIPBOARD_TYPE__COUNT; type++) {
  95        g_free(info->types[type].data);
  96    }
  97    g_free(info);
  98}
  99
 100void qemu_clipboard_request(QemuClipboardInfo *info,
 101                            QemuClipboardType type)
 102{
 103    if (info->types[type].data ||
 104        info->types[type].requested ||
 105        !info->types[type].available ||
 106        !info->owner)
 107        return;
 108
 109    info->types[type].requested = true;
 110    info->owner->request(info, type);
 111}
 112
 113void qemu_clipboard_set_data(QemuClipboardPeer *peer,
 114                             QemuClipboardInfo *info,
 115                             QemuClipboardType type,
 116                             uint32_t size,
 117                             const void *data,
 118                             bool update)
 119{
 120    if (!info ||
 121        info->owner != peer) {
 122        return;
 123    }
 124
 125    g_free(info->types[type].data);
 126    info->types[type].data = g_memdup(data, size);
 127    info->types[type].size = size;
 128    info->types[type].available = true;
 129
 130    if (update) {
 131        qemu_clipboard_update(info);
 132    }
 133}
 134