bare-gtk 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/CMakeLists.txt +16 -2
  2. package/README.md +35 -1
  3. package/binding.c +350 -1
  4. package/index.d.ts +65 -0
  5. package/index.js +32 -0
  6. package/lib/adjustment.d.ts +21 -0
  7. package/lib/adjustment.h +112 -0
  8. package/lib/adjustment.js +24 -0
  9. package/lib/bridging.h +347 -0
  10. package/lib/clipboard.d.ts +22 -0
  11. package/lib/clipboard.h +176 -0
  12. package/lib/clipboard.js +18 -0
  13. package/lib/constants.d.ts +40 -0
  14. package/lib/constants.js +51 -0
  15. package/lib/css-provider.d.ts +13 -0
  16. package/lib/css-provider.h +56 -0
  17. package/lib/css-provider.js +14 -0
  18. package/lib/cursor.d.ts +35 -0
  19. package/lib/cursor.h +220 -0
  20. package/lib/cursor.js +45 -0
  21. package/lib/device.d.ts +13 -0
  22. package/lib/device.h +35 -0
  23. package/lib/device.js +8 -0
  24. package/lib/dialog.d.ts +41 -0
  25. package/lib/dialog.js +37 -0
  26. package/lib/display.d.ts +25 -0
  27. package/lib/display.h +86 -0
  28. package/lib/display.js +23 -0
  29. package/lib/editable.h +160 -0
  30. package/lib/entry.d.ts +93 -0
  31. package/lib/entry.h +340 -0
  32. package/lib/entry.js +118 -0
  33. package/lib/event-controller-focus.d.ts +17 -0
  34. package/lib/event-controller-focus.h +55 -0
  35. package/lib/event-controller-focus.js +13 -0
  36. package/lib/event-controller-motion.d.ts +18 -0
  37. package/lib/event-controller-motion.h +66 -0
  38. package/lib/event-controller-motion.js +14 -0
  39. package/lib/event-controller.d.ts +17 -0
  40. package/lib/event-controller.h +103 -0
  41. package/lib/event-controller.js +22 -0
  42. package/lib/events.js +23 -0
  43. package/lib/fixed.d.ts +10 -0
  44. package/lib/fixed.h +28 -0
  45. package/lib/fixed.js +8 -0
  46. package/lib/frame-fixed.d.ts +10 -0
  47. package/lib/frame-fixed.js +12 -0
  48. package/lib/frame-layout-child.d.ts +17 -0
  49. package/lib/frame-layout-child.js +16 -0
  50. package/lib/frame-layout.d.ts +27 -0
  51. package/lib/frame-layout.h +291 -0
  52. package/lib/frame-layout.js +19 -0
  53. package/lib/gesture-click.d.ts +19 -0
  54. package/lib/gesture-click.h +66 -0
  55. package/lib/gesture-click.js +14 -0
  56. package/lib/gesture-drag.d.ts +25 -0
  57. package/lib/gesture-drag.h +165 -0
  58. package/lib/gesture-drag.js +23 -0
  59. package/lib/gesture-single.d.ts +13 -0
  60. package/lib/gesture-single.js +12 -0
  61. package/lib/gesture.d.ts +13 -0
  62. package/lib/gesture.h +73 -0
  63. package/lib/gesture.js +8 -0
  64. package/lib/handle.d.ts +5 -0
  65. package/lib/handle.js +6 -0
  66. package/lib/label.d.ts +36 -0
  67. package/lib/label.h +269 -0
  68. package/lib/label.js +78 -0
  69. package/lib/layout-child.d.ts +13 -0
  70. package/lib/layout-child.h +35 -0
  71. package/lib/layout-child.js +10 -0
  72. package/lib/layout-manager.d.ts +15 -0
  73. package/lib/layout-manager.h +42 -0
  74. package/lib/layout-manager.js +15 -0
  75. package/lib/message-dialog.d.ts +26 -0
  76. package/lib/message-dialog.h +190 -0
  77. package/lib/message-dialog.js +22 -0
  78. package/lib/monitor.d.ts +32 -0
  79. package/lib/monitor.h +143 -0
  80. package/lib/monitor.js +40 -0
  81. package/lib/native.h +31 -0
  82. package/lib/object.d.ts +18 -0
  83. package/lib/object.js +38 -0
  84. package/lib/paintable.d.ts +10 -0
  85. package/lib/paintable.js +3 -0
  86. package/lib/picture.d.ts +22 -0
  87. package/lib/picture.h +127 -0
  88. package/lib/picture.js +35 -0
  89. package/lib/reachable.js +11 -0
  90. package/lib/runtime.c +21 -4
  91. package/lib/scrolled-window.d.ts +22 -0
  92. package/lib/scrolled-window.h +142 -0
  93. package/lib/scrolled-window.js +37 -0
  94. package/lib/settings.d.ts +25 -0
  95. package/lib/settings.h +163 -0
  96. package/lib/settings.js +34 -0
  97. package/lib/spinner.d.ts +12 -0
  98. package/lib/spinner.h +61 -0
  99. package/lib/spinner.js +22 -0
  100. package/lib/style-context.d.ts +15 -0
  101. package/lib/style-context.h +67 -0
  102. package/lib/style-context.js +9 -0
  103. package/lib/surface.d.ts +19 -0
  104. package/lib/surface.h +61 -0
  105. package/lib/surface.js +22 -0
  106. package/lib/switch.d.ts +19 -0
  107. package/lib/switch.h +114 -0
  108. package/lib/switch.js +30 -0
  109. package/lib/text-buffer.d.ts +31 -0
  110. package/lib/text-buffer.h +246 -0
  111. package/lib/text-buffer.js +33 -0
  112. package/lib/text-view.d.ts +39 -0
  113. package/lib/text-view.h +247 -0
  114. package/lib/text-view.js +63 -0
  115. package/lib/text.d.ts +18 -0
  116. package/lib/text.h +189 -0
  117. package/lib/text.js +31 -0
  118. package/lib/texture.d.ts +20 -0
  119. package/lib/texture.h +100 -0
  120. package/lib/texture.js +17 -0
  121. package/lib/viewport.d.ts +22 -0
  122. package/lib/viewport.h +151 -0
  123. package/lib/viewport.js +38 -0
  124. package/lib/widget.d.ts +102 -0
  125. package/lib/widget.h +695 -17
  126. package/lib/widget.js +176 -11
  127. package/lib/window.d.ts +31 -0
  128. package/lib/window.h +142 -61
  129. package/lib/window.js +32 -11
  130. package/lib/wrap.js +7 -0
  131. package/package.json +12 -3
  132. package/prebuilds/linux-arm64/bare +2 -2
  133. package/prebuilds/linux-arm64/bare-gtk.bare +0 -0
  134. package/prebuilds/linux-x64/bare +2 -2
  135. package/prebuilds/linux-x64/bare-gtk.bare +0 -0
@@ -0,0 +1,112 @@
1
+ #ifndef BARE_GTK_ADJUSTMENT_H
2
+ #define BARE_GTK_ADJUSTMENT_H
3
+
4
+ #include <assert.h>
5
+ #include <js.h>
6
+
7
+ #include <gtk/gtk.h>
8
+
9
+ #include "bridging.h"
10
+
11
+ enum {
12
+ bare_gtk_adjustment_event_value_changed = 1 << 0,
13
+ };
14
+
15
+ static void
16
+ bare_gtk_adjustment__on_value_changed(GtkAdjustment *adjustment, gpointer data) {
17
+ bare_gtk_state_t *state = data;
18
+
19
+ if ((bare_gtk__observed(state, adjustment) & bare_gtk_adjustment_event_value_changed) == 0) return;
20
+
21
+ bare_gtk__emit(state, adjustment, "value-changed", 1, (const double[]) {gtk_adjustment_get_value(adjustment)});
22
+ }
23
+
24
+ static js_value_t *
25
+ bare_gtk_adjustment_event_mask(js_env_t *env, js_callback_info_t *info) {
26
+ int err;
27
+
28
+ size_t argc = 2;
29
+ js_value_t *argv[2];
30
+
31
+ bare_gtk_state_t *state;
32
+ err = js_get_callback_info(env, info, &argc, argv, NULL, (void **) &state);
33
+ assert(err == 0);
34
+
35
+ assert(argc == 2);
36
+
37
+ GtkAdjustment *adjustment;
38
+ err = bare_gobject_read_tag(env, state->registry, argv[0], "adjustment", (gpointer *) &adjustment);
39
+ if (err < 0) return NULL;
40
+
41
+ uint32_t events;
42
+ err = bare_gtk__read_uint32(env, argv[1], "events", &events);
43
+ if (err < 0) return NULL;
44
+
45
+ // Connected once and left connected. The mask decides whether anything is
46
+ // sent.
47
+ if (bare_gtk__observe(state, adjustment, events)) {
48
+ g_signal_connect(adjustment, "value-changed", G_CALLBACK(bare_gtk_adjustment__on_value_changed), state);
49
+ }
50
+
51
+ return NULL;
52
+ }
53
+
54
+ static js_value_t *
55
+ bare_gtk_adjustment_value(js_env_t *env, js_callback_info_t *info) {
56
+ int err;
57
+
58
+ size_t argc = 2;
59
+ js_value_t *argv[2];
60
+
61
+ bare_gtk_state_t *state;
62
+ err = js_get_callback_info(env, info, &argc, argv, NULL, (void **) &state);
63
+ assert(err == 0);
64
+
65
+ assert(argc == 1 || argc == 2);
66
+
67
+ GtkAdjustment *adjustment;
68
+ err = bare_gobject_read_tag(env, state->registry, argv[0], "adjustment", (gpointer *) &adjustment);
69
+ if (err < 0) return NULL;
70
+
71
+ if (argc == 1) {
72
+ js_value_t *result;
73
+ err = js_create_double(env, gtk_adjustment_get_value(adjustment), &result);
74
+ assert(err == 0);
75
+
76
+ return result;
77
+ }
78
+
79
+ double value;
80
+ err = js_get_value_double(env, argv[1], &value);
81
+ assert(err == 0);
82
+
83
+ gtk_adjustment_set_value(adjustment, value);
84
+
85
+ return NULL;
86
+ }
87
+
88
+ static js_value_t *
89
+ bare_gtk_adjustment_upper(js_env_t *env, js_callback_info_t *info) {
90
+ int err;
91
+
92
+ size_t argc = 1;
93
+ js_value_t *argv[1];
94
+
95
+ bare_gtk_state_t *state;
96
+ err = js_get_callback_info(env, info, &argc, argv, NULL, (void **) &state);
97
+ assert(err == 0);
98
+
99
+ assert(argc == 1);
100
+
101
+ GtkAdjustment *adjustment;
102
+ err = bare_gobject_read_tag(env, state->registry, argv[0], "adjustment", (gpointer *) &adjustment);
103
+ if (err < 0) return NULL;
104
+
105
+ js_value_t *result;
106
+ err = js_create_double(env, gtk_adjustment_get_upper(adjustment), &result);
107
+ assert(err == 0);
108
+
109
+ return result;
110
+ }
111
+
112
+ #endif // BARE_GTK_ADJUSTMENT_H
@@ -0,0 +1,24 @@
1
+ const binding = require('../binding')
2
+ const GObject = require('./object')
3
+
4
+ module.exports = exports = class GTKAdjustment extends GObject {
5
+ static _events = {
6
+ 'value-changed': binding.ADJUSTMENT_EVENT_VALUE_CHANGED
7
+ }
8
+
9
+ _eventMask(mask) {
10
+ binding.adjustmentEventMask(this._tag, mask)
11
+ }
12
+
13
+ get value() {
14
+ return binding.adjustmentValue(this._tag)
15
+ }
16
+
17
+ set value(value) {
18
+ binding.adjustmentValue(this._tag, value)
19
+ }
20
+
21
+ get upper() {
22
+ return binding.adjustmentUpper(this._tag)
23
+ }
24
+ }
package/lib/bridging.h ADDED
@@ -0,0 +1,347 @@
1
+ #ifndef BARE_GTK_BRIDGING_H
2
+ #define BARE_GTK_BRIDGING_H
3
+
4
+ #include <assert.h>
5
+ #include <glib.h>
6
+ #include <js.h>
7
+ #include <stdbool.h>
8
+ #include <stdint.h>
9
+ #include <utf.h>
10
+
11
+ #include <gtk/gtk.h>
12
+
13
+ #include "registry.h"
14
+
15
+ // What the addon keeps between calls. It belongs to one instantiation, because
16
+ // an addon can be loaded more than once in a process. Bindings reach it through
17
+ // their data pointer, and signal handlers through the object they are connected
18
+ // to.
19
+ typedef struct {
20
+ bare_gobject_registry_t *registry;
21
+ js_env_t *env;
22
+
23
+ GHashTable *events;
24
+
25
+ // A label that is never shown, used to measure text in the font a real label
26
+ // draws with. A standalone Pango context would pick a different font. A theme
27
+ // may pad a label, so its inset is measured too.
28
+ GtkWidget *text_probe;
29
+ int text_inset_width;
30
+ int text_inset_height;
31
+ } bare_gtk_state_t;
32
+
33
+ static void
34
+ bare_gtk__on_observed_gone(gpointer data, GObject *object);
35
+
36
+ static void
37
+ bare_gtk__on_state_release(js_env_t *env, void *data, void *finalize_hint) {
38
+ bare_gtk_state_t *state = data;
39
+
40
+ GHashTableIter iter;
41
+ gpointer object;
42
+
43
+ g_hash_table_iter_init(&iter, state->events);
44
+
45
+ while (g_hash_table_iter_next(&iter, &object, NULL)) {
46
+ g_object_weak_unref(G_OBJECT(object), bare_gtk__on_observed_gone, state);
47
+ }
48
+
49
+ g_hash_table_destroy(state->events);
50
+
51
+ if (state->text_probe) g_object_unref(state->text_probe);
52
+
53
+ bare_gobject_registry_release(state->registry);
54
+
55
+ g_free(state);
56
+ }
57
+
58
+ static bare_gtk_state_t *
59
+ bare_gtk_state_create(js_env_t *env, js_value_t *exports) {
60
+ int err;
61
+
62
+ bare_gtk_state_t *state = g_new0(bare_gtk_state_t, 1);
63
+
64
+ state->registry = bare_gobject_registry_create(env, exports);
65
+ state->env = env;
66
+
67
+ state->events = g_hash_table_new(NULL, NULL);
68
+
69
+ err = js_add_finalizer(env, exports, state, bare_gtk__on_state_release, NULL, NULL);
70
+ assert(err == 0);
71
+
72
+ return state;
73
+ }
74
+
75
+ static int
76
+ bare_gtk__read_bool(js_env_t *env, js_value_t *value, const char *name, bool *result) {
77
+ int err;
78
+
79
+ bool is;
80
+ err = js_is_boolean(env, value, &is);
81
+ assert(err == 0);
82
+
83
+ if (!is) {
84
+ err = js_throw_type_errorf(env, NULL, "Expected '%s' to be a boolean", name);
85
+ assert(err == 0);
86
+
87
+ return -1;
88
+ }
89
+
90
+ err = js_get_value_bool(env, value, result);
91
+ assert(err == 0);
92
+
93
+ return 0;
94
+ }
95
+
96
+ static int
97
+ bare_gtk__read_number(js_env_t *env, js_value_t *value, const char *name) {
98
+ int err;
99
+
100
+ bool is;
101
+ err = js_is_number(env, value, &is);
102
+ assert(err == 0);
103
+
104
+ if (!is) {
105
+ err = js_throw_type_errorf(env, NULL, "Expected '%s' to be a number", name);
106
+ assert(err == 0);
107
+
108
+ return -1;
109
+ }
110
+
111
+ return 0;
112
+ }
113
+
114
+ static int
115
+ bare_gtk__read_int32(js_env_t *env, js_value_t *value, const char *name, int32_t *result) {
116
+ int err;
117
+
118
+ err = bare_gtk__read_number(env, value, name);
119
+ if (err < 0) return err;
120
+
121
+ err = js_get_value_int32(env, value, result);
122
+ assert(err == 0);
123
+
124
+ return 0;
125
+ }
126
+
127
+ static int
128
+ bare_gtk__read_uint32(js_env_t *env, js_value_t *value, const char *name, uint32_t *result) {
129
+ int err;
130
+
131
+ err = bare_gtk__read_number(env, value, name);
132
+ if (err < 0) return err;
133
+
134
+ err = js_get_value_uint32(env, value, result);
135
+ assert(err == 0);
136
+
137
+ return 0;
138
+ }
139
+
140
+ static int
141
+ bare_gtk__read_double(js_env_t *env, js_value_t *value, const char *name, double *result) {
142
+ int err;
143
+
144
+ err = bare_gtk__read_number(env, value, name);
145
+ if (err < 0) return err;
146
+
147
+ err = js_get_value_double(env, value, result);
148
+ assert(err == 0);
149
+
150
+ return 0;
151
+ }
152
+
153
+ static int
154
+ bare_gtk__read_string(js_env_t *env, js_value_t *value, const char *name, char **result) {
155
+ int err;
156
+
157
+ bool is;
158
+ err = js_is_string(env, value, &is);
159
+ assert(err == 0);
160
+
161
+ if (!is) {
162
+ err = js_throw_type_errorf(env, NULL, "Expected '%s' to be a string", name);
163
+ assert(err == 0);
164
+
165
+ return -1;
166
+ }
167
+
168
+ size_t len;
169
+ err = js_get_value_string_utf8(env, value, NULL, 0, &len);
170
+ assert(err == 0);
171
+
172
+ char *str = g_malloc(len + 1);
173
+
174
+ err = js_get_value_string_utf8(env, value, (utf8_t *) str, len + 1, NULL);
175
+ assert(err == 0);
176
+
177
+ *result = str;
178
+
179
+ return 0;
180
+ }
181
+
182
+ static int
183
+ bare_gtk__read_string_or_null(js_env_t *env, js_value_t *value, const char *name, char **result) {
184
+ int err;
185
+
186
+ bool is;
187
+ err = js_is_null(env, value, &is);
188
+ assert(err == 0);
189
+
190
+ if (is) {
191
+ *result = NULL;
192
+
193
+ return 0;
194
+ }
195
+
196
+ return bare_gtk__read_string(env, value, name, result);
197
+ }
198
+
199
+ // A GTK call that fails sets a `GError`. Here that becomes a thrown error.
200
+ static int
201
+ bare_gtk__throw(js_env_t *env, GError *error) {
202
+ int err = js_throw_error(env, NULL, error->message);
203
+ assert(err == 0);
204
+
205
+ g_error_free(error);
206
+
207
+ return -1;
208
+ }
209
+
210
+ static int
211
+ bare_gtk__read_tag_or_null(js_env_t *env, bare_gobject_registry_t *registry, js_value_t *value, const char *name, gpointer *result) {
212
+ int err;
213
+
214
+ bool is;
215
+ err = js_is_null(env, value, &is);
216
+ assert(err == 0);
217
+
218
+ if (is) {
219
+ *result = NULL;
220
+
221
+ return 0;
222
+ }
223
+
224
+ return bare_gobject_read_tag(env, registry, value, name, result);
225
+ }
226
+
227
+ static js_value_t *
228
+ bare_gtk__create_tag(js_env_t *env, bare_gtk_state_t *state, gpointer object) {
229
+ int err;
230
+
231
+ js_value_t *result;
232
+
233
+ if (object) {
234
+ err = js_create_uint32(env, bare_gobject_tag(state->registry, object), &result);
235
+ } else {
236
+ err = js_get_null(env, &result);
237
+ }
238
+
239
+ assert(err == 0);
240
+
241
+ return result;
242
+ }
243
+
244
+ // Each instantiation keeps its own event mask for an object, because objects
245
+ // such as `GtkSettings` are shared by the whole process. The weak reference
246
+ // removes the entry when the object goes away.
247
+ static void
248
+ bare_gtk__on_observed_gone(gpointer data, GObject *object) {
249
+ bare_gtk_state_t *state = data;
250
+
251
+ g_hash_table_remove(state->events, object);
252
+ }
253
+
254
+ static uint32_t
255
+ bare_gtk__observed(bare_gtk_state_t *state, gpointer object) {
256
+ return GPOINTER_TO_UINT(g_hash_table_lookup(state->events, object));
257
+ }
258
+
259
+ // Returns true the first time this state sees the object, which is when it
260
+ // still has to connect its signals.
261
+ static bool
262
+ bare_gtk__observe(bare_gtk_state_t *state, gpointer object, uint32_t events) {
263
+ if (!g_hash_table_insert(state->events, object, GUINT_TO_POINTER(events))) return false;
264
+
265
+ g_object_weak_ref(G_OBJECT(object), bare_gtk__on_observed_gone, state);
266
+
267
+ return true;
268
+ }
269
+
270
+ // Emit an edit before it happens, as the range it replaces and the new text.
271
+ static void
272
+ bare_gtk__emit_replacement(bare_gtk_state_t *state, gpointer object, const char *event, const char *text, int start, int end) {
273
+ int err;
274
+
275
+ js_env_t *env = state->env;
276
+
277
+ js_handle_scope_t *scope;
278
+ err = js_open_handle_scope(env, &scope);
279
+ assert(err == 0);
280
+
281
+ js_value_t *wrapper = bare_gobject_lookup(env, state->registry, object);
282
+
283
+ if (wrapper) {
284
+ js_value_t *emit;
285
+ err = js_get_named_property(env, wrapper, "emit", &emit);
286
+ assert(err == 0);
287
+
288
+ js_value_t *argv[4];
289
+
290
+ err = js_create_string_utf8(env, (const utf8_t *) event, (size_t) -1, &argv[0]);
291
+ assert(err == 0);
292
+
293
+ err = js_create_string_utf8(env, (const utf8_t *) (text == NULL ? "" : text), (size_t) -1, &argv[1]);
294
+ assert(err == 0);
295
+
296
+ err = js_create_int32(env, start, &argv[2]);
297
+ assert(err == 0);
298
+
299
+ err = js_create_int32(env, end, &argv[3]);
300
+ assert(err == 0);
301
+
302
+ err = js_call_function(env, wrapper, emit, 4, argv, NULL);
303
+ assert(err == 0 || err == js_pending_exception);
304
+ }
305
+
306
+ err = js_close_handle_scope(env, scope);
307
+ assert(err == 0);
308
+ }
309
+
310
+ static void
311
+ bare_gtk__emit(bare_gtk_state_t *state, gpointer object, const char *event, size_t argc, const double args[]) {
312
+ int err;
313
+
314
+ js_env_t *env = state->env;
315
+
316
+ js_handle_scope_t *scope;
317
+ err = js_open_handle_scope(env, &scope);
318
+ assert(err == 0);
319
+
320
+ js_value_t *wrapper = bare_gobject_lookup(env, state->registry, object);
321
+
322
+ if (wrapper) {
323
+ js_value_t *emit;
324
+ err = js_get_named_property(env, wrapper, "emit", &emit);
325
+ assert(err == 0);
326
+
327
+ js_value_t *argv[8];
328
+
329
+ assert(argc + 1 <= 8);
330
+
331
+ err = js_create_string_utf8(env, (const utf8_t *) event, (size_t) -1, &argv[0]);
332
+ assert(err == 0);
333
+
334
+ for (size_t i = 0; i < argc; i++) {
335
+ err = js_create_double(env, args[i], &argv[i + 1]);
336
+ assert(err == 0);
337
+ }
338
+
339
+ err = js_call_function(env, wrapper, emit, argc + 1, argv, NULL);
340
+ assert(err == 0 || err == js_pending_exception);
341
+ }
342
+
343
+ err = js_close_handle_scope(env, scope);
344
+ assert(err == 0);
345
+ }
346
+
347
+ #endif // BARE_GTK_BRIDGING_H
@@ -0,0 +1,22 @@
1
+ import GObject = require('./object')
2
+
3
+ /** A clipboard, as a `GdkClipboard`. Get one from a `GDKDisplay`. */
4
+ interface GDKClipboard extends GObject {
5
+ /**
6
+ * Read the text on the clipboard. `callback` is called with an error message, or with `null`
7
+ * and the text, which is `null` if there is none.
8
+ */
9
+ readTextAsync(callback: (error: string | null, text: string | null) => void): void
10
+
11
+ /** Put `text` on the clipboard. */
12
+ setText(text: string): this
13
+
14
+ /** The mime types of what the clipboard holds. */
15
+ readonly formats: string[]
16
+ }
17
+
18
+ declare class GDKClipboard {
19
+ protected constructor()
20
+ }
21
+
22
+ export = GDKClipboard
@@ -0,0 +1,176 @@
1
+ #ifndef BARE_GTK_CLIPBOARD_H
2
+ #define BARE_GTK_CLIPBOARD_H
3
+
4
+ #include <assert.h>
5
+ #include <js.h>
6
+
7
+ #include <gtk/gtk.h>
8
+
9
+ #include "bridging.h"
10
+
11
+ // GDK reads a clipboard through a callback, so the caller passes one in.
12
+ typedef struct {
13
+ bare_gtk_state_t *state;
14
+ js_ref_t *callback;
15
+ } bare_gtk_clipboard_read_t;
16
+
17
+ static void
18
+ bare_gtk_clipboard__on_read_text(GObject *source, GAsyncResult *result, gpointer data) {
19
+ int err;
20
+
21
+ bare_gtk_clipboard_read_t *read = data;
22
+
23
+ js_env_t *env = read->state->env;
24
+
25
+ js_handle_scope_t *scope;
26
+ err = js_open_handle_scope(env, &scope);
27
+ assert(err == 0);
28
+
29
+ js_value_t *callback;
30
+ err = js_get_reference_value(env, read->callback, &callback);
31
+ assert(err == 0);
32
+
33
+ GError *error = NULL;
34
+
35
+ char *text = gdk_clipboard_read_text_finish(GDK_CLIPBOARD(source), result, &error);
36
+
37
+ js_value_t *argv[2];
38
+
39
+ if (error == NULL) {
40
+ err = js_get_null(env, &argv[0]);
41
+ assert(err == 0);
42
+
43
+ if (text == NULL) {
44
+ err = js_get_null(env, &argv[1]);
45
+ } else {
46
+ err = js_create_string_utf8(env, (const utf8_t *) text, (size_t) -1, &argv[1]);
47
+ }
48
+
49
+ assert(err == 0);
50
+ } else {
51
+ err = js_create_string_utf8(env, (const utf8_t *) error->message, (size_t) -1, &argv[0]);
52
+ assert(err == 0);
53
+
54
+ err = js_get_null(env, &argv[1]);
55
+ assert(err == 0);
56
+
57
+ g_error_free(error);
58
+ }
59
+
60
+ g_free(text);
61
+
62
+ js_value_t *receiver;
63
+ err = js_get_null(env, &receiver);
64
+ assert(err == 0);
65
+
66
+ err = js_call_function(env, receiver, callback, 2, argv, NULL);
67
+ (void) err;
68
+
69
+ err = js_delete_reference(env, read->callback);
70
+ assert(err == 0);
71
+
72
+ err = js_close_handle_scope(env, scope);
73
+ assert(err == 0);
74
+
75
+ free(read);
76
+ }
77
+
78
+ static js_value_t *
79
+ bare_gtk_clipboard_read_text_async(js_env_t *env, js_callback_info_t *info) {
80
+ int err;
81
+
82
+ size_t argc = 2;
83
+ js_value_t *argv[2];
84
+
85
+ bare_gtk_state_t *state;
86
+ err = js_get_callback_info(env, info, &argc, argv, NULL, (void **) &state);
87
+ assert(err == 0);
88
+
89
+ assert(argc == 2);
90
+
91
+ GdkClipboard *clipboard;
92
+ err = bare_gobject_read_tag(env, state->registry, argv[0], "clipboard", (gpointer *) &clipboard);
93
+ if (err < 0) return NULL;
94
+
95
+ bare_gtk_clipboard_read_t *read = malloc(sizeof(bare_gtk_clipboard_read_t));
96
+
97
+ read->state = state;
98
+
99
+ err = js_create_reference(env, argv[1], 1, &read->callback);
100
+ assert(err == 0);
101
+
102
+ gdk_clipboard_read_text_async(clipboard, NULL, bare_gtk_clipboard__on_read_text, read);
103
+
104
+ return NULL;
105
+ }
106
+
107
+ static js_value_t *
108
+ bare_gtk_clipboard_set_text(js_env_t *env, js_callback_info_t *info) {
109
+ int err;
110
+
111
+ size_t argc = 2;
112
+ js_value_t *argv[2];
113
+
114
+ bare_gtk_state_t *state;
115
+ err = js_get_callback_info(env, info, &argc, argv, NULL, (void **) &state);
116
+ assert(err == 0);
117
+
118
+ assert(argc == 2);
119
+
120
+ GdkClipboard *clipboard;
121
+ err = bare_gobject_read_tag(env, state->registry, argv[0], "clipboard", (gpointer *) &clipboard);
122
+ if (err < 0) return NULL;
123
+
124
+ char *text;
125
+ err = bare_gtk__read_string(env, argv[1], "text", &text);
126
+ if (err < 0) return NULL;
127
+
128
+ gdk_clipboard_set_text(clipboard, text);
129
+
130
+ free(text);
131
+
132
+ return NULL;
133
+ }
134
+
135
+ // A `GdkContentFormats` is not a `GObject`, so it crosses as the list of mime
136
+ // types it holds.
137
+ static js_value_t *
138
+ bare_gtk_clipboard_formats(js_env_t *env, js_callback_info_t *info) {
139
+ int err;
140
+
141
+ size_t argc = 1;
142
+ js_value_t *argv[1];
143
+
144
+ bare_gtk_state_t *state;
145
+ err = js_get_callback_info(env, info, &argc, argv, NULL, (void **) &state);
146
+ assert(err == 0);
147
+
148
+ assert(argc == 1);
149
+
150
+ GdkClipboard *clipboard;
151
+ err = bare_gobject_read_tag(env, state->registry, argv[0], "clipboard", (gpointer *) &clipboard);
152
+ if (err < 0) return NULL;
153
+
154
+ GdkContentFormats *formats = gdk_clipboard_get_formats(clipboard);
155
+
156
+ gsize len = 0;
157
+
158
+ const char *const *mime_types = gdk_content_formats_get_mime_types(formats, &len);
159
+
160
+ js_value_t *result;
161
+ err = js_create_array_with_length(env, len, &result);
162
+ assert(err == 0);
163
+
164
+ for (gsize i = 0; i < len; i++) {
165
+ js_value_t *value;
166
+ err = js_create_string_utf8(env, (const utf8_t *) mime_types[i], (size_t) -1, &value);
167
+ assert(err == 0);
168
+
169
+ err = js_set_element(env, result, i, value);
170
+ assert(err == 0);
171
+ }
172
+
173
+ return result;
174
+ }
175
+
176
+ #endif // BARE_GTK_CLIPBOARD_H
@@ -0,0 +1,18 @@
1
+ const binding = require('../binding')
2
+ const GObject = require('./object')
3
+
4
+ module.exports = exports = class GDKClipboard extends GObject {
5
+ readTextAsync(callback) {
6
+ binding.clipboardReadTextAsync(this._tag, callback)
7
+ }
8
+
9
+ setText(text) {
10
+ binding.clipboardSetText(this._tag, text)
11
+
12
+ return this
13
+ }
14
+
15
+ get formats() {
16
+ return binding.clipboardFormats(this._tag)
17
+ }
18
+ }