xref: /openbmc/qemu/ui/clipboard.c (revision 2113aed6)
1  #include "qemu/osdep.h"
2  #include "ui/clipboard.h"
3  
4  static NotifierList clipboard_notifiers =
5      NOTIFIER_LIST_INITIALIZER(clipboard_notifiers);
6  
7  static QemuClipboardInfo *cbinfo[QEMU_CLIPBOARD_SELECTION__COUNT];
8  
9  void qemu_clipboard_peer_register(QemuClipboardPeer *peer)
10  {
11      notifier_list_add(&clipboard_notifiers, &peer->update);
12  }
13  
14  void 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  
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  void 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  
56  QemuClipboardInfo *qemu_clipboard_info(QemuClipboardSelection selection)
57  {
58      assert(selection < QEMU_CLIPBOARD_SELECTION__COUNT);
59  
60      return cbinfo[selection];
61  }
62  
63  QemuClipboardInfo *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  
75  QemuClipboardInfo *qemu_clipboard_info_ref(QemuClipboardInfo *info)
76  {
77      info->refcount++;
78      return info;
79  }
80  
81  void 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  
100  void 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  
113  void 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