Mercurial > projects > dynamin
annotate dynamin/gui/x_clipboard.d @ 106:acdbb30fee7e
Port to D2.
Most of the effort was dealing with immutable and const.
author | Jordan Miner <jminer7@gmail.com> |
---|---|
date | Mon, 17 Dec 2012 23:41:50 -0600 |
parents | 73060bc3f004 |
children |
rev | line source |
---|---|
0 | 1 |
2 /* | |
103
73060bc3f004
Change license to Boost 1.0 and MPL 2.0.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
3 * Copyright Jordan Miner |
0 | 4 * |
103
73060bc3f004
Change license to Boost 1.0 and MPL 2.0.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
5 * This Source Code Form is subject to the terms of the Mozilla Public |
73060bc3f004
Change license to Boost 1.0 and MPL 2.0.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
6 * License, v. 2.0. If a copy of the MPL was not distributed with this |
73060bc3f004
Change license to Boost 1.0 and MPL 2.0.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
0 | 8 * |
9 */ | |
10 | |
11 module dynamin.gui.x_clipboard; | |
12 | |
13 public import dynamin.core.string; | |
14 public import dynamin.core.environment; | |
15 public import dynamin.gui.x_window; | |
16 | |
17 // TODO: get notified of selection changes by using the XFixes extension | |
18 // TODO: use the ClipboardManager to ensure that the clipboard data stays after | |
19 // the program is closed | |
20 | |
21 /* Fairly obvious, but: | |
22 selecting but with no explicit copy should only set PRIMARY, | |
23 never CLIPBOARD | |
24 | |
25 middle mouse button should paste PRIMARY, never CLIPBOARD | |
26 | |
27 explicit cut/copy commands (i.e. menu items, toolbar buttons) | |
28 should always set CLIPBOARD to the currently-selected data (i.e. conceptually copy PRIMARY to CLIPBOARD) | |
29 | |
30 explicit paste commands should paste CLIPBOARD, not PRIMARY | |
31 | |
32 possibly contradicting the ICCCM, clients don't need to support | |
33 SECONDARY, though if anyone can figure out what it's good for they should feel free to use it for that | |
34 */ | |
35 extern(C) XBool isRequestOrNotify(XDisplay* d, XEvent* e, XPointer arg) { | |
36 // either | |
37 // - SelectionRequest & the msgWin is the owner | |
38 // - SelectionNotify & another program is owner is giving data | |
39 return (e.type == SelectionRequest || e.type == SelectionNotify) && | |
40 e.xany.window == msgWin; | |
41 | |
42 } | |
43 | |
106 | 44 mstring backend_getSelText(XAtom sel, ref ClipboardData data) { |
0 | 45 XConvertSelection(display, sel, XA.UTF8_STRING, XA.DYNAMIN_SELECTION, msgWin, CurrentTime); |
46 XSync(display, false); | |
47 auto start = Environment.runningTime; | |
48 XEvent ev; | |
49 while(true) { | |
50 // don't wait more than a second | |
51 if(Environment.runningTime - start > 1000) | |
52 return null; | |
53 if(!XCheckIfEvent(display, &ev, &isRequestOrNotify, null)) | |
54 continue; | |
55 if(ev.type == SelectionRequest) | |
56 return data.data[0..data.length]; | |
57 // must be SelectionNotify past here | |
58 | |
59 auto selEv = &ev.xselection; | |
60 if(selEv.property == None) | |
61 return null; | |
62 | |
63 int count; | |
64 char* propData = cast(char*)getXWindowProperty(display, msgWin, | |
65 selEv.property, &count); | |
66 scope(exit) XFree(propData); | |
67 XDeleteProperty(display, msgWin, selEv.property); | |
68 | |
106 | 69 mstring str = new char[count]; |
0 | 70 str[] = propData[0..count]; |
71 return str; | |
72 } | |
73 } | |
74 struct ClipboardData { | |
75 XAtom target; | |
76 char* data; | |
77 uint length; // number of bytes in data | |
78 } | |
79 // always called from the event thread...don't have to avoid static data | |
106 | 80 void backend_setSelText(XAtom sel, cstring text, ref ClipboardData data) { |
0 | 81 XSetSelectionOwner(display, sel, msgWin, CurrentTime); |
82 data.target = XA.UTF8_STRING; | |
83 data.data = text.ptr; | |
84 data.length = text.length; | |
85 | |
86 XConvertSelection(display, XA.CLIPBOARD_MANAGER, XA.SAVE_TARGETS, None, msgWin, CurrentTime); | |
87 } | |
88 | |
89 template ClipboardBackend() { | |
90 ClipboardData data; // make array when supporting multiple types (PNG & BMP) | |
106 | 91 void backend_setText(cstring text) { |
0 | 92 backend_setSelText(XA.CLIPBOARD, text, data); |
93 } | |
106 | 94 mstring backend_getText() { |
0 | 95 return backend_getSelText(XA.CLIPBOARD, data); |
96 } | |
97 bool backend_containsText() { | |
98 return backend_getText() != null; | |
99 } | |
100 } | |
101 | |
102 template SelectionBackend() { | |
103 ClipboardData data; // make array when supporting multiple types (PNG & BMP) | |
106 | 104 void backend_setText(cstring text) { |
0 | 105 backend_setSelText(XA.PRIMARY, text, data); |
106 } | |
106 | 107 mstring backend_getText() { |
0 | 108 return backend_getSelText(XA.PRIMARY, data); |
109 } | |
110 bool backend_containsText() { | |
111 return backend_getText() != null; | |
112 } | |
113 } | |
114 |