qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

clipboard.c (4406B)


      1 #include "qemu/osdep.h"
      2 #include "ui/clipboard.h"
      3 #include "trace.h"
      4 
      5 static NotifierList clipboard_notifiers =
      6     NOTIFIER_LIST_INITIALIZER(clipboard_notifiers);
      7 
      8 static QemuClipboardInfo *cbinfo[QEMU_CLIPBOARD_SELECTION__COUNT];
      9 
     10 void qemu_clipboard_peer_register(QemuClipboardPeer *peer)
     11 {
     12     notifier_list_add(&clipboard_notifiers, &peer->notifier);
     13 }
     14 
     15 void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer)
     16 {
     17     int i;
     18 
     19     for (i = 0; i < QEMU_CLIPBOARD_SELECTION__COUNT; i++) {
     20         qemu_clipboard_peer_release(peer, i);
     21     }
     22     notifier_remove(&peer->notifier);
     23 }
     24 
     25 bool 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 
     33 void 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 
     45 bool qemu_clipboard_check_serial(QemuClipboardInfo *info, bool client)
     46 {
     47     bool ok;
     48 
     49     if (!info->has_serial ||
     50         !cbinfo[info->selection] ||
     51         !cbinfo[info->selection]->has_serial) {
     52         trace_clipboard_check_serial(-1, -1, true);
     53         return true;
     54     }
     55 
     56     if (client) {
     57         ok = info->serial >= cbinfo[info->selection]->serial;
     58     } else {
     59         ok = info->serial > cbinfo[info->selection]->serial;
     60     }
     61 
     62     trace_clipboard_check_serial(cbinfo[info->selection]->serial, info->serial, ok);
     63     return ok;
     64 }
     65 
     66 void qemu_clipboard_update(QemuClipboardInfo *info)
     67 {
     68     QemuClipboardNotify notify = {
     69         .type = QEMU_CLIPBOARD_UPDATE_INFO,
     70         .info = info,
     71     };
     72     assert(info->selection < QEMU_CLIPBOARD_SELECTION__COUNT);
     73 
     74     notifier_list_notify(&clipboard_notifiers, &notify);
     75 
     76     if (cbinfo[info->selection] != info) {
     77         qemu_clipboard_info_unref(cbinfo[info->selection]);
     78         cbinfo[info->selection] = qemu_clipboard_info_ref(info);
     79     }
     80 }
     81 
     82 QemuClipboardInfo *qemu_clipboard_info(QemuClipboardSelection selection)
     83 {
     84     assert(selection < QEMU_CLIPBOARD_SELECTION__COUNT);
     85 
     86     return cbinfo[selection];
     87 }
     88 
     89 QemuClipboardInfo *qemu_clipboard_info_new(QemuClipboardPeer *owner,
     90                                            QemuClipboardSelection selection)
     91 {
     92     QemuClipboardInfo *info = g_new0(QemuClipboardInfo, 1);
     93 
     94     info->owner = owner;
     95     info->selection = selection;
     96     info->refcount = 1;
     97 
     98     return info;
     99 }
    100 
    101 QemuClipboardInfo *qemu_clipboard_info_ref(QemuClipboardInfo *info)
    102 {
    103     info->refcount++;
    104     return info;
    105 }
    106 
    107 void qemu_clipboard_info_unref(QemuClipboardInfo *info)
    108 {
    109     uint32_t type;
    110 
    111     if (!info) {
    112         return;
    113     }
    114 
    115     info->refcount--;
    116     if (info->refcount > 0) {
    117         return;
    118     }
    119 
    120     for (type = 0; type < QEMU_CLIPBOARD_TYPE__COUNT; type++) {
    121         g_free(info->types[type].data);
    122     }
    123     g_free(info);
    124 }
    125 
    126 void qemu_clipboard_request(QemuClipboardInfo *info,
    127                             QemuClipboardType type)
    128 {
    129     if (info->types[type].data ||
    130         info->types[type].requested ||
    131         !info->types[type].available ||
    132         !info->owner)
    133         return;
    134 
    135     info->types[type].requested = true;
    136     info->owner->request(info, type);
    137 }
    138 
    139 void qemu_clipboard_reset_serial(void)
    140 {
    141     QemuClipboardNotify notify = { .type = QEMU_CLIPBOARD_RESET_SERIAL };
    142     int i;
    143 
    144     for (i = 0; i < QEMU_CLIPBOARD_SELECTION__COUNT; i++) {
    145         QemuClipboardInfo *info = qemu_clipboard_info(i);
    146         if (info) {
    147             info->serial = 0;
    148         }
    149     }
    150     notifier_list_notify(&clipboard_notifiers, &notify);
    151 }
    152 
    153 void qemu_clipboard_set_data(QemuClipboardPeer *peer,
    154                              QemuClipboardInfo *info,
    155                              QemuClipboardType type,
    156                              uint32_t size,
    157                              const void *data,
    158                              bool update)
    159 {
    160     if (!info ||
    161         info->owner != peer) {
    162         return;
    163     }
    164 
    165     g_free(info->types[type].data);
    166     info->types[type].data = g_memdup(data, size);
    167     info->types[type].size = size;
    168     info->types[type].available = true;
    169 
    170     if (update) {
    171         qemu_clipboard_update(info);
    172     }
    173 }