comparison dynamin/gui/x_clipboard.d @ 0:aa4efef0f0b1

Initial commit of code.
author Jordan Miner <jminer7@gmail.com>
date Mon, 15 Jun 2009 22:10:48 -0500
parents
children 73060bc3f004
comparison
equal deleted inserted replaced
-1:000000000000 0:aa4efef0f0b1
1 // Written in the D programming language
2 // www.digitalmars.com/d/
3
4 /*
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is the Dynamin library.
16 *
17 * The Initial Developer of the Original Code is Jordan Miner.
18 * Portions created by the Initial Developer are Copyright (C) 2007-2009
19 * the Initial Developer. All Rights Reserved.
20 *
21 * Contributor(s):
22 * Jordan Miner <jminer7@gmail.com>
23 *
24 */
25
26 module dynamin.gui.x_clipboard;
27
28 public import dynamin.core.string;
29 public import dynamin.core.environment;
30 public import dynamin.gui.x_window;
31
32 // TODO: get notified of selection changes by using the XFixes extension
33 // TODO: use the ClipboardManager to ensure that the clipboard data stays after
34 // the program is closed
35
36 /* Fairly obvious, but:
37 selecting but with no explicit copy should only set PRIMARY,
38 never CLIPBOARD
39
40 middle mouse button should paste PRIMARY, never CLIPBOARD
41
42 explicit cut/copy commands (i.e. menu items, toolbar buttons)
43 should always set CLIPBOARD to the currently-selected data (i.e. conceptually copy PRIMARY to CLIPBOARD)
44
45 explicit paste commands should paste CLIPBOARD, not PRIMARY
46
47 possibly contradicting the ICCCM, clients don't need to support
48 SECONDARY, though if anyone can figure out what it's good for they should feel free to use it for that
49 */
50 extern(C) XBool isRequestOrNotify(XDisplay* d, XEvent* e, XPointer arg) {
51 // either
52 // - SelectionRequest & the msgWin is the owner
53 // - SelectionNotify & another program is owner is giving data
54 return (e.type == SelectionRequest || e.type == SelectionNotify) &&
55 e.xany.window == msgWin;
56
57 }
58
59 string backend_getSelText(XAtom sel, ref ClipboardData data) {
60 XConvertSelection(display, sel, XA.UTF8_STRING, XA.DYNAMIN_SELECTION, msgWin, CurrentTime);
61 XSync(display, false);
62 auto start = Environment.runningTime;
63 XEvent ev;
64 while(true) {
65 // don't wait more than a second
66 if(Environment.runningTime - start > 1000)
67 return null;
68 if(!XCheckIfEvent(display, &ev, &isRequestOrNotify, null))
69 continue;
70 if(ev.type == SelectionRequest)
71 return data.data[0..data.length];
72 // must be SelectionNotify past here
73
74 auto selEv = &ev.xselection;
75 if(selEv.property == None)
76 return null;
77
78 int count;
79 char* propData = cast(char*)getXWindowProperty(display, msgWin,
80 selEv.property, &count);
81 scope(exit) XFree(propData);
82 XDeleteProperty(display, msgWin, selEv.property);
83
84 string str = new char[count];
85 str[] = propData[0..count];
86 return str;
87 }
88 }
89 struct ClipboardData {
90 XAtom target;
91 char* data;
92 uint length; // number of bytes in data
93 }
94 // always called from the event thread...don't have to avoid static data
95 void backend_setSelText(XAtom sel, string text, ref ClipboardData data) {
96 XSetSelectionOwner(display, sel, msgWin, CurrentTime);
97 data.target = XA.UTF8_STRING;
98 data.data = text.ptr;
99 data.length = text.length;
100
101 XConvertSelection(display, XA.CLIPBOARD_MANAGER, XA.SAVE_TARGETS, None, msgWin, CurrentTime);
102 }
103
104 template ClipboardBackend() {
105 ClipboardData data; // make array when supporting multiple types (PNG & BMP)
106 void backend_setText(string text) {
107 backend_setSelText(XA.CLIPBOARD, text, data);
108 }
109 string backend_getText() {
110 return backend_getSelText(XA.CLIPBOARD, data);
111 }
112 bool backend_containsText() {
113 return backend_getText() != null;
114 }
115 }
116
117 template SelectionBackend() {
118 ClipboardData data; // make array when supporting multiple types (PNG & BMP)
119 void backend_setText(string text) {
120 backend_setSelText(XA.PRIMARY, text, data);
121 }
122 string backend_getText() {
123 return backend_getSelText(XA.PRIMARY, data);
124 }
125 bool backend_containsText() {
126 return backend_getText() != null;
127 }
128 }
129