This source file includes following definitions.
- get_clipboard_object
- be_find_clipboard_data_1
- be_set_clipboard_data_1
- be_update_clipboard_count
- be_find_clipboard_data
- be_set_clipboard_data
- clipboard_owner_p
- primary_owner_p
- secondary_owner_p
- be_clipboard_owner_p
- be_clipboard_init
- be_enum_message
- be_get_refs_data
- be_get_point_data
- be_get_message_data
- be_get_message_type
- be_set_message_type
- be_get_message_message
- be_create_simple_message
- be_add_message_data
- be_add_refs_data
- be_add_point_data
- be_add_message_message
- be_lock_clipboard_message
- be_unlock_clipboard
- be_handle_clipboard_changed_message
- be_start_watching_selection
- be_selection_outdated_p
- be_get_clipboard_count
- type_for_type
- my_team_id
- be_display_notification
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <config.h>
20 #include <intprops.h>
21
22 #include <Application.h>
23 #include <Bitmap.h>
24 #include <Clipboard.h>
25 #include <Entry.h>
26 #include <Message.h>
27 #include <Notification.h>
28 #include <OS.h>
29 #include <Path.h>
30 #include <String.h>
31
32 #include <translation/TranslationUtils.h>
33
34 #include <cstdlib>
35 #include <cstring>
36 #include <cstdint>
37 #include <cstdio>
38
39 #include "haikuselect.h"
40
41
42 static BClipboard *primary = NULL;
43
44
45 static BClipboard *secondary = NULL;
46
47
48
49 static BClipboard *system_clipboard = NULL;
50
51
52 static int64 count_clipboard = -1;
53
54
55 static int64 count_primary = -1;
56
57
58 static int64 count_secondary = -1;
59
60
61
62 static bool owned_primary;
63
64
65 static bool owned_secondary;
66
67
68 static bool owned_clipboard;
69
70
71
72
73
74 static BClipboard *
75 get_clipboard_object (enum haiku_clipboard clipboard)
76 {
77 switch (clipboard)
78 {
79 case CLIPBOARD_PRIMARY:
80 return primary;
81
82 case CLIPBOARD_SECONDARY:
83 return secondary;
84
85 case CLIPBOARD_CLIPBOARD:
86 return system_clipboard;
87 }
88
89 abort ();
90 }
91
92 static char *
93 be_find_clipboard_data_1 (BClipboard *cb, const char *type, ssize_t *len)
94 {
95 BMessage *data;
96 const char *ptr;
97 ssize_t nbytes;
98 void *value;
99
100 if (!cb->Lock ())
101 return NULL;
102
103 data = cb->Data ();
104
105 if (!data)
106 {
107 cb->Unlock ();
108 return NULL;
109 }
110
111 data->FindData (type, B_MIME_TYPE, (const void **) &ptr,
112 &nbytes);
113
114 if (!ptr)
115 {
116 cb->Unlock ();
117 return NULL;
118 }
119
120 if (len)
121 *len = nbytes;
122
123 value = malloc (nbytes);
124
125 if (!data)
126 {
127 cb->Unlock ();
128 return NULL;
129 }
130
131 memcpy (value, ptr, nbytes);
132 cb->Unlock ();
133
134 return (char *) value;
135 }
136
137 static void
138 be_set_clipboard_data_1 (BClipboard *cb, const char *type, const char *data,
139 ssize_t len, bool clear)
140 {
141 BMessage *message_data;
142
143 if (!cb->Lock ())
144 return;
145
146 if (clear)
147 cb->Clear ();
148
149 message_data = cb->Data ();
150
151 if (!message_data)
152 {
153 cb->Unlock ();
154 return;
155 }
156
157 if (data)
158 {
159 if (message_data->ReplaceData (type, B_MIME_TYPE, data, len)
160 == B_NAME_NOT_FOUND)
161 message_data->AddData (type, B_MIME_TYPE, data, len);
162 }
163 else
164 message_data->RemoveName (type);
165
166 cb->Commit ();
167 cb->Unlock ();
168 }
169
170 void
171 be_update_clipboard_count (enum haiku_clipboard id)
172 {
173 switch (id)
174 {
175 case CLIPBOARD_CLIPBOARD:
176 count_clipboard = system_clipboard->SystemCount ();
177 owned_clipboard = true;
178 break;
179
180 case CLIPBOARD_PRIMARY:
181 count_primary = primary->SystemCount ();
182 owned_primary = true;
183 break;
184
185 case CLIPBOARD_SECONDARY:
186 count_secondary = secondary->SystemCount ();
187 owned_secondary = true;
188 break;
189 }
190 }
191
192 char *
193 be_find_clipboard_data (enum haiku_clipboard id, const char *type,
194 ssize_t *len)
195 {
196 return be_find_clipboard_data_1 (get_clipboard_object (id),
197 type, len);
198 }
199
200 void
201 be_set_clipboard_data (enum haiku_clipboard id, const char *type,
202 const char *data, ssize_t len, bool clear)
203 {
204 be_update_clipboard_count (id);
205
206 be_set_clipboard_data_1 (get_clipboard_object (id), type,
207 data, len, clear);
208 }
209
210 static bool
211 clipboard_owner_p (void)
212 {
213 return (count_clipboard >= 0
214 && (count_clipboard + 1
215 == system_clipboard->SystemCount ()));
216 }
217
218 static bool
219 primary_owner_p (void)
220 {
221 return (count_primary >= 0
222 && (count_primary + 1
223 == primary->SystemCount ()));
224 }
225
226 static bool
227 secondary_owner_p (void)
228 {
229 return (count_secondary >= 0
230 && (count_secondary + 1
231 == secondary->SystemCount ()));
232 }
233
234 bool
235 be_clipboard_owner_p (enum haiku_clipboard clipboard)
236 {
237 switch (clipboard)
238 {
239 case CLIPBOARD_PRIMARY:
240 return primary_owner_p ();
241
242 case CLIPBOARD_SECONDARY:
243 return secondary_owner_p ();
244
245 case CLIPBOARD_CLIPBOARD:
246 return clipboard_owner_p ();
247 }
248
249 abort ();
250 }
251
252 void
253 be_clipboard_init (void)
254 {
255 system_clipboard = new BClipboard ("system");
256 primary = new BClipboard ("primary");
257 secondary = new BClipboard ("secondary");
258 }
259
260 int
261 be_enum_message (void *message, int32 *tc, int32 index,
262 int32 *count, const char **name_return)
263 {
264 BMessage *msg = (BMessage *) message;
265 type_code type;
266 char *name;
267 status_t rc;
268
269 rc = msg->GetInfo (B_ANY_TYPE, index, &name, &type, count);
270
271 if (rc != B_OK)
272 return 1;
273
274 *tc = type;
275 *name_return = name;
276 return 0;
277 }
278
279 int
280 be_get_refs_data (void *message, const char *name,
281 int32 index, char **path_buffer)
282 {
283 status_t rc;
284 BEntry entry;
285 BPath path;
286 entry_ref ref;
287 BMessage *msg;
288
289 msg = (BMessage *) message;
290 rc = msg->FindRef (name, index, &ref);
291
292 if (rc != B_OK)
293 return 1;
294
295 rc = entry.SetTo (&ref, 0);
296
297 if (rc != B_OK)
298 return 1;
299
300 rc = entry.GetPath (&path);
301
302 if (rc != B_OK)
303 return 1;
304
305 *path_buffer = strdup (path.Path ());
306 return 0;
307 }
308
309 int
310 be_get_point_data (void *message, const char *name,
311 int32 index, float *x, float *y)
312 {
313 status_t rc;
314 BMessage *msg;
315 BPoint point;
316
317 msg = (BMessage *) message;
318 rc = msg->FindPoint (name, index, &point);
319
320 if (rc != B_OK)
321 return 1;
322
323 *x = point.x;
324 *y = point.y;
325
326 return 0;
327 }
328
329 int
330 be_get_message_data (void *message, const char *name,
331 int32 type_code, int32 index,
332 const void **buf_return,
333 ssize_t *size_return)
334 {
335 BMessage *msg = (BMessage *) message;
336
337 return msg->FindData (name, type_code,
338 index, buf_return, size_return) != B_OK;
339 }
340
341 uint32
342 be_get_message_type (void *message)
343 {
344 BMessage *msg = (BMessage *) message;
345
346 return msg->what;
347 }
348
349 void
350 be_set_message_type (void *message, uint32 what)
351 {
352 BMessage *msg = (BMessage *) message;
353
354 msg->what = what;
355 }
356
357 void *
358 be_get_message_message (void *message, const char *name,
359 int32 index)
360 {
361 BMessage *msg = (BMessage *) message;
362 BMessage *out = new (std::nothrow) BMessage;
363
364 if (!out)
365 return NULL;
366
367 if (msg->FindMessage (name, index, out) != B_OK)
368 {
369 delete out;
370 return NULL;
371 }
372
373 return out;
374 }
375
376 void *
377 be_create_simple_message (void)
378 {
379 return new BMessage (B_SIMPLE_DATA);
380 }
381
382 int
383 be_add_message_data (void *message, const char *name,
384 int32 type_code, const void *buf,
385 ssize_t buf_size)
386 {
387 BMessage *msg = (BMessage *) message;
388
389 return msg->AddData (name, type_code, buf, buf_size) != B_OK;
390 }
391
392 int
393 be_add_refs_data (void *message, const char *name,
394 const char *filename)
395 {
396 BEntry entry (filename);
397 entry_ref ref;
398 BMessage *msg = (BMessage *) message;
399
400 if (entry.InitCheck () != B_OK)
401 return 1;
402
403 if (entry.GetRef (&ref) != B_OK)
404 return 1;
405
406 return msg->AddRef (name, &ref) != B_OK;
407 }
408
409 int
410 be_add_point_data (void *message, const char *name,
411 float x, float y)
412 {
413 BMessage *msg = (BMessage *) message;
414
415 return msg->AddPoint (name, BPoint (x, y)) != B_OK;
416 }
417
418 int
419 be_add_message_message (void *message, const char *name,
420 void *data)
421 {
422 BMessage *msg = (BMessage *) message;
423 BMessage *data_message = (BMessage *) data;
424
425 if (msg->AddMessage (name, data_message) != B_OK)
426 return 1;
427
428 return 0;
429 }
430
431 int
432 be_lock_clipboard_message (enum haiku_clipboard clipboard,
433 void **message_return, bool clear)
434 {
435 BClipboard *board;
436
437 board = get_clipboard_object (clipboard);
438
439 if (!board->Lock ())
440 return 1;
441
442 if (clear)
443 board->Clear ();
444
445 *message_return = board->Data ();
446 return 0;
447 }
448
449 void
450 be_unlock_clipboard (enum haiku_clipboard clipboard, bool discard)
451 {
452 BClipboard *board;
453
454 board = get_clipboard_object (clipboard);
455
456 if (discard)
457 board->Revert ();
458 else
459 board->Commit ();
460
461 board->Unlock ();
462 }
463
464 void
465 be_handle_clipboard_changed_message (void)
466 {
467 int64 n_clipboard, n_primary, n_secondary;
468
469 n_clipboard = system_clipboard->SystemCount ();
470 n_primary = primary->SystemCount ();
471 n_secondary = secondary->SystemCount ();
472
473 if (count_clipboard != -1
474 && (n_clipboard > count_clipboard + 1)
475 && owned_clipboard)
476 {
477 owned_clipboard = false;
478 haiku_selection_disowned (CLIPBOARD_CLIPBOARD,
479 n_clipboard);
480 }
481
482 if (count_primary != -1
483 && (n_primary > count_primary + 1)
484 && owned_primary)
485 {
486 owned_primary = false;
487 haiku_selection_disowned (CLIPBOARD_PRIMARY,
488 n_primary);
489 }
490
491 if (count_secondary != -1
492 && (n_secondary > count_secondary + 1)
493 && owned_secondary)
494 {
495 owned_secondary = false;
496 haiku_selection_disowned (CLIPBOARD_SECONDARY,
497 n_secondary);
498 }
499 }
500
501 void
502 be_start_watching_selection (enum haiku_clipboard id)
503 {
504 BClipboard *clipboard;
505
506 clipboard = get_clipboard_object (id);
507 clipboard->StartWatching (be_app);
508 }
509
510 bool
511 be_selection_outdated_p (enum haiku_clipboard id, int64 count)
512 {
513 if (id == CLIPBOARD_CLIPBOARD && count_clipboard > count)
514 return true;
515
516 if (id == CLIPBOARD_PRIMARY && count_primary > count)
517 return true;
518
519 if (id == CLIPBOARD_SECONDARY && count_secondary > count)
520 return true;
521
522 return false;
523 }
524
525 int64
526 be_get_clipboard_count (enum haiku_clipboard id)
527 {
528 BClipboard *clipboard;
529
530 clipboard = get_clipboard_object (id);
531 return clipboard->SystemCount ();
532 }
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549 static intmax_t last_notification_id;
550
551
552
553
554 static enum notification_type
555 type_for_type (int type)
556 {
557 switch (type)
558 {
559 case 0:
560 return B_INFORMATION_NOTIFICATION;
561
562 case 1:
563 return B_IMPORTANT_NOTIFICATION;
564
565 case 2:
566 return B_ERROR_NOTIFICATION;
567 }
568
569 abort ();
570 }
571
572
573
574 static team_id
575 my_team_id (void)
576 {
577 thread_id id;
578 thread_info info;
579
580 id = find_thread (NULL);
581 get_thread_info (id, &info);
582
583 return info.team;
584 }
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606 intmax_t
607 be_display_notification (const char *title, const char *body,
608 intmax_t supersedes, int type, const char *icon)
609 {
610 intmax_t id;
611 BNotification notification (type_for_type (type));
612 char buffer[INT_STRLEN_BOUND (team_id)
613 + INT_STRLEN_BOUND (intmax_t)
614 + sizeof "."];
615 BBitmap *bitmap;
616
617 if (supersedes < 0)
618 {
619
620
621
622 INT_ADD_WRAPV (last_notification_id, 1,
623 &last_notification_id);
624 id = last_notification_id;
625 }
626 else
627 id = supersedes;
628
629
630 notification.SetTitle (title);
631 notification.SetContent (body);
632
633
634
635 sprintf (buffer, "%d.%jd", my_team_id (), id);
636 notification.SetMessageID (BString (buffer));
637
638
639
640 if (icon)
641 {
642 bitmap = BTranslationUtils::GetBitmap (icon);
643
644 if (bitmap)
645 {
646 notification.SetIcon (bitmap);
647 delete bitmap;
648 }
649 }
650
651
652
653
654
655 #if 0
656 notification.SetOnClickApp ("application/x-vnd.GNU-emacs");
657 notification.AddOnClickArg (BString ("-Notification,") += buffer);
658 #endif
659
660
661 notification.Send ();
662 return id;
663 }