45 |
|
* For safety purposes, we lock the X11 display in the emulator |
46 |
|
* thread during the whole GetScrap/PutScrap execution. Of course, we |
47 |
|
* temporarily release the lock when waiting for SelectioNotify. |
48 |
+ |
* |
49 |
+ |
* TODO: |
50 |
+ |
* - handle 'PICT' to image/png, image/ppm, PIXMAP (prefs order) |
51 |
+ |
* - handle 'styl' to text/richtext (OOo Writer) |
52 |
+ |
* - patch ZeroScrap so that we know when cached 'styl' is stale? |
53 |
|
*/ |
54 |
|
|
55 |
|
#include "sysdeps.h" |
80 |
|
// Do we replace GetScrap()? |
81 |
|
#define REPLACE_GETSCRAP 1 |
82 |
|
|
78 |
– |
// Do we want PutScrap() to ignore requests from klipper? |
79 |
– |
#define PUTSCRAP_IGNORES_KLIPPER 0 |
80 |
– |
|
83 |
|
// Do we want GetScrap() to check for TIMESTAMP and optimize out clipboard syncs? |
84 |
|
#define GETSCRAP_REQUESTS_TIMESTAMP 0 |
85 |
|
|
272 |
|
|
273 |
|
|
274 |
|
/* |
273 |
– |
* Check for a "klipper" window which, in older versions (3.1), was |
274 |
– |
* polling and retrieving clipboard data several times per second. |
275 |
– |
*/ |
276 |
– |
|
277 |
– |
static bool is_klipper_window_probe(Window w); |
278 |
– |
static bool is_klipper_window_check(Window w); |
279 |
– |
static bool (*is_klipper_window)(Window w) = is_klipper_window_probe; |
280 |
– |
static Window klipper_win = None; |
281 |
– |
|
282 |
– |
static bool is_klipper_window_probe(Window w) |
283 |
– |
{ |
284 |
– |
// We expect "klipper" to be within the first clients to request |
285 |
– |
// data from our clipboard |
286 |
– |
static int clients_countdown = 2; |
287 |
– |
|
288 |
– |
bool found = false; |
289 |
– |
char *window_name; |
290 |
– |
if (XFetchName(x_display, w, &window_name) && !strcmp(window_name, "klipper")) { |
291 |
– |
D(bug(" found and ignore clipboard requests from klipper window id: 0x%08x\n", w)); |
292 |
– |
klipper_win = w; |
293 |
– |
found = true; |
294 |
– |
} |
295 |
– |
|
296 |
– |
if (found || --clients_countdown <= 0) |
297 |
– |
is_klipper_window = is_klipper_window_check; |
298 |
– |
} |
299 |
– |
|
300 |
– |
static bool is_klipper_window_check(Window w) |
301 |
– |
{ |
302 |
– |
return w == klipper_win; |
303 |
– |
} |
304 |
– |
|
305 |
– |
|
306 |
– |
/* |
275 |
|
* Initialization |
276 |
|
*/ |
277 |
|
|
331 |
|
{ |
332 |
|
clip_data.type = None; |
333 |
|
switch (type) { |
334 |
< |
case FOURCC('T','E','X','T'): |
334 |
> |
case FOURCC('T','E','X','T'): { |
335 |
|
D(bug(" clipping TEXT\n")); |
336 |
|
clip_data.type = XA_STRING; |
337 |
|
clip_data.data.clear(); |
351 |
|
break; |
352 |
|
} |
353 |
|
|
354 |
+ |
case FOURCC('s','t','y','l'): { |
355 |
+ |
D(bug(" clipping styl\n")); |
356 |
+ |
uint16 *p = (uint16 *)scrap; |
357 |
+ |
uint16 n = ntohs(*p++); |
358 |
+ |
D(bug(" %d styles (%d bytes)\n", n, length)); |
359 |
+ |
for (int i = 0; i < n; i++) { |
360 |
+ |
uint32 offset = ntohl(*(uint32 *)p); p += 2; |
361 |
+ |
uint16 line_height = ntohs(*p++); |
362 |
+ |
uint16 font_ascent = ntohs(*p++); |
363 |
+ |
uint16 font_family = ntohs(*p++); |
364 |
+ |
uint16 style_code = ntohs(*p++); |
365 |
+ |
uint16 char_size = ntohs(*p++); |
366 |
+ |
uint16 r = ntohs(*p++); |
367 |
+ |
uint16 g = ntohs(*p++); |
368 |
+ |
uint16 b = ntohs(*p++); |
369 |
+ |
D(bug(" offset=%d, height=%d, font ascent=%d, id=%d, style=%x, size=%d, RGB=%x/%x/%x\n", |
370 |
+ |
offset, line_height, font_ascent, font_family, style_code, char_size, r, g, b)); |
371 |
+ |
} |
372 |
+ |
break; |
373 |
+ |
} |
374 |
+ |
} |
375 |
+ |
|
376 |
|
// Acquire selection ownership |
377 |
|
if (clip_data.type != None) { |
378 |
|
clip_data.time = CurrentTime; |
440 |
|
long *atoms = (long *)data.data(); |
441 |
|
for (int i = 0; i < n_atoms; i++) { |
442 |
|
Atom target = atoms[i]; |
443 |
+ |
D(bug(" target %08x (%s)\n", target, XGetAtomName(x_display, target))); |
444 |
|
switch (type) { |
445 |
|
case FOURCC('T','E','X','T'): |
446 |
|
D(bug(" clipping TEXT\n")); |
668 |
|
if (req->requestor == clip_win || req->selection != xa_clipboard) |
669 |
|
return; |
670 |
|
|
680 |
– |
#if PUTSCRAP_IGNORES_KLIPPER |
681 |
– |
if (is_klipper_window(req->requestor)) |
682 |
– |
return; |
683 |
– |
#endif |
684 |
– |
|
671 |
|
D(bug("Selection requested from 0x%lx to 0x%lx (%s) 0x%lx (%s)\n", |
672 |
|
req->requestor, |
673 |
|
req->selection, |