11
11
#include <stdio.h>
12
12
#include <stdint.h>
13
13
#include <string.h>
14
+ #include <dlfcn.h>
14
15
#include <X11/Xlib.h>
15
16
#include <X11/Xatom.h>
16
17
17
18
// syncStatus is a function from the Go side.
18
19
extern void syncStatus (uintptr_t handle , int status );
19
20
21
+ void * libX11 ;
22
+
23
+ Display * (* P_XOpenDisplay )(int );
24
+ void (* P_XCloseDisplay )(Display * );
25
+ Window (* P_XDefaultRootWindow )(Display * );
26
+ Window (* P_XCreateSimpleWindow )(Display * , Window , int , int , int , int , int , int , int );
27
+ Atom (* P_XInternAtom )(Display * , char * , int );
28
+ void (* P_XSetSelectionOwner )(Display * , Atom , Window , unsigned long );
29
+ Window (* P_XGetSelectionOwner )(Display * , Atom );
30
+ void (* P_XNextEvent )(Display * , XEvent * );
31
+ int (* P_XChangeProperty )(Display * , Window , Atom , Atom , int , int , unsigned char * , int );
32
+ void (* P_XSendEvent )(Display * , Window , int , long , XEvent * );
33
+ int (* P_XGetWindowProperty ) (Display * , Window , Atom , long , long , Bool , Atom , Atom * , int * , unsigned long * , unsigned long * , unsigned char * * );
34
+ void (* P_XFree ) (void * );
35
+ void (* P_XDeleteProperty ) (Display * , Window , Atom );
36
+ void (* P_XConvertSelection )(Display * , Atom , Atom , Atom , Window , Time );
37
+
38
+ int initX11 () {
39
+ if (libX11 ) {
40
+ return 1 ;
41
+ }
42
+ libX11 = dlopen ("libX11.so" , RTLD_LAZY );
43
+ if (!libX11 ) {
44
+ return -1 ;
45
+ }
46
+ P_XOpenDisplay = (Display * (* )(int )) dlsym (libX11 , "XOpenDisplay" );
47
+ P_XCloseDisplay = (void (* )(Display * )) dlsym (libX11 , "XCloseDisplay" );
48
+ P_XDefaultRootWindow = (Window (* )(Display * )) dlsym (libX11 , "XDefaultRootWindow" );
49
+ P_XCreateSimpleWindow = (Window (* )(Display * , Window , int , int , int , int , int , int , int )) dlsym (libX11 , "XCreateSimpleWindow" );
50
+ P_XInternAtom = (Atom (* )(Display * , char * , int )) dlsym (libX11 , "XInternAtom" );
51
+ P_XSetSelectionOwner = (void (* )(Display * , Atom , Window , unsigned long )) dlsym (libX11 , "XSetSelectionOwner" );
52
+ P_XGetSelectionOwner = (Window (* )(Display * , Atom )) dlsym (libX11 , "XGetSelectionOwner" );
53
+ P_XNextEvent = (void (* )(Display * , XEvent * )) dlsym (libX11 , "XNextEvent" );
54
+ P_XChangeProperty = (int (* )(Display * , Window , Atom , Atom , int , int , unsigned char * , int )) dlsym (libX11 , "XChangeProperty" );
55
+ P_XSendEvent = (void (* )(Display * , Window , int , long , XEvent * )) dlsym (libX11 , "XSendEvent" );
56
+ P_XGetWindowProperty = (int (* )(Display * , Window , Atom , long , long , Bool , Atom , Atom * , int * , unsigned long * , unsigned long * , unsigned char * * )) dlsym (libX11 , "XGetWindowProperty" );
57
+ P_XFree = (void (* )(void * )) dlsym (libX11 , "XFree" );
58
+ P_XDeleteProperty = (void (* )(Display * , Window , Atom )) dlsym (libX11 , "XDeleteProperty" );
59
+ P_XConvertSelection = (void (* )(Display * , Atom , Atom , Atom , Window , Time )) dlsym (libX11 , "XConvertSelection" );
60
+ return 1 ;
61
+ }
62
+
20
63
int clipboard_test () {
64
+ if (!initX11 ()) {
65
+ return -1 ;
66
+ }
67
+
21
68
Display * d = NULL ;
22
69
for (int i = 0 ; i < 42 ; i ++ ) {
23
- d = XOpenDisplay (0 );
70
+ d = ( * P_XOpenDisplay ) (0 );
24
71
if (d == NULL ) {
25
72
continue ;
26
73
}
27
74
break ;
28
75
}
29
-
30
76
if (d == NULL ) {
31
77
return -1 ;
32
78
}
33
- XCloseDisplay (d );
79
+ ( * P_XCloseDisplay ) (d );
34
80
return 0 ;
35
81
}
36
82
37
83
// clipboard_write writes the given buf of size n as type typ.
38
84
// if start is provided, the value of start will be changed to 1 to indicate
39
85
// if the write is availiable for reading.
40
86
int clipboard_write (char * typ , unsigned char * buf , size_t n , uintptr_t handle ) {
87
+ if (!initX11 ()) {
88
+ return -1 ;
89
+ }
90
+
41
91
Display * d = NULL ;
42
92
for (int i = 0 ; i < 42 ; i ++ ) {
43
- d = XOpenDisplay (0 );
93
+ d = ( * P_XOpenDisplay ) (0 );
44
94
if (d == NULL ) {
45
95
continue ;
46
96
}
@@ -50,26 +100,25 @@ int clipboard_write(char *typ, unsigned char *buf, size_t n, uintptr_t handle) {
50
100
syncStatus (handle , -1 );
51
101
return -1 ;
52
102
}
53
-
54
- Window w = XCreateSimpleWindow (d , DefaultRootWindow (d ), 0 , 0 , 1 , 1 , 0 , 0 , 0 );
103
+ Window w = (* P_XCreateSimpleWindow )(d , (* P_XDefaultRootWindow )(d ), 0 , 0 , 1 , 1 , 0 , 0 , 0 );
55
104
56
105
// Use False because these may not available for the first time.
57
- Atom sel = XInternAtom ( d , "CLIPBOARD" , False );
58
- Atom atomString = XInternAtom ( d , "UTF8_STRING" , False );
59
- Atom atomImage = XInternAtom ( d , "image/png" , False );
60
- Atom targetsAtom = XInternAtom ( d , "TARGETS" , False );
106
+ Atom sel = ( * P_XInternAtom )( d , "CLIPBOARD" , 0 );
107
+ Atom atomString = ( * P_XInternAtom )( d , "UTF8_STRING" , 0 );
108
+ Atom atomImage = ( * P_XInternAtom )( d , "image/png" , 0 );
109
+ Atom targetsAtom = ( * P_XInternAtom )( d , "TARGETS" , 0 );
61
110
62
111
// Use True to makesure the requested type is a valid type.
63
- Atom target = XInternAtom ( d , typ , True );
112
+ Atom target = ( * P_XInternAtom )( d , typ , 1 );
64
113
if (target == None ) {
65
- XCloseDisplay (d );
114
+ ( * P_XCloseDisplay ) (d );
66
115
syncStatus (handle , -2 );
67
116
return -2 ;
68
117
}
69
118
70
- XSetSelectionOwner (d , sel , w , CurrentTime );
71
- if (XGetSelectionOwner (d , sel ) != w ) {
72
- XCloseDisplay (d );
119
+ ( * P_XSetSelectionOwner ) (d , sel , w , CurrentTime );
120
+ if (( * P_XGetSelectionOwner ) (d , sel ) != w ) {
121
+ ( * P_XCloseDisplay ) (d );
73
122
syncStatus (handle , -3 );
74
123
return -3 ;
75
124
}
@@ -83,13 +132,13 @@ int clipboard_write(char *typ, unsigned char *buf, size_t n, uintptr_t handle) {
83
132
notified = 1 ;
84
133
}
85
134
86
- XNextEvent (d , & event );
135
+ ( * P_XNextEvent ) (d , & event );
87
136
switch (event .type ) {
88
137
case SelectionClear :
89
138
// For debugging:
90
139
// printf("x11write: lost ownership of clipboard selection.\n");
91
140
// fflush(stdout);
92
- XCloseDisplay (d );
141
+ ( * P_XCloseDisplay ) (d );
93
142
return 0 ;
94
143
case SelectionNotify :
95
144
// For debugging:
@@ -114,24 +163,24 @@ int clipboard_write(char *typ, unsigned char *buf, size_t n, uintptr_t handle) {
114
163
ev .property = xsr -> property ;
115
164
116
165
if (ev .target == atomString && ev .target == target ) {
117
- R = XChangeProperty (ev .display , ev .requestor , ev .property ,
166
+ R = ( * P_XChangeProperty ) (ev .display , ev .requestor , ev .property ,
118
167
atomString , 8 , PropModeReplace , buf , n );
119
168
} else if (ev .target == atomImage && ev .target == target ) {
120
- R = XChangeProperty (ev .display , ev .requestor , ev .property ,
169
+ R = ( * P_XChangeProperty ) (ev .display , ev .requestor , ev .property ,
121
170
atomImage , 8 , PropModeReplace , buf , n );
122
171
} else if (ev .target == targetsAtom ) {
123
172
// Reply atoms for supported targets, other clients should
124
173
// request the clipboard again and obtain the data if their
125
174
// implementation is correct.
126
175
Atom targets [] = { atomString , atomImage };
127
- R = XChangeProperty (ev .display , ev .requestor , ev .property ,
176
+ R = ( * P_XChangeProperty ) (ev .display , ev .requestor , ev .property ,
128
177
XA_ATOM , 32 , PropModeReplace ,
129
178
(unsigned char * )& targets , sizeof (targets )/sizeof (Atom ));
130
179
} else {
131
180
ev .property = None ;
132
181
}
133
182
134
- if ((R & 2 ) == 0 ) XSendEvent (d , ev .requestor , 0 , 0 , (XEvent * )& ev );
183
+ if ((R & 2 ) == 0 ) ( * P_XSendEvent ) (d , ev .requestor , 0 , 0 , (XEvent * )& ev );
135
184
break ;
136
185
}
137
186
}
@@ -140,6 +189,10 @@ int clipboard_write(char *typ, unsigned char *buf, size_t n, uintptr_t handle) {
140
189
// read_data reads the property of a selection if the target atom matches
141
190
// the actual atom.
142
191
unsigned long read_data (XSelectionEvent * sev , Atom sel , Atom prop , Atom target , char * * buf ) {
192
+ if (!initX11 ()) {
193
+ return -1 ;
194
+ }
195
+
143
196
unsigned char * data ;
144
197
Atom actual ;
145
198
int format ;
@@ -149,7 +202,7 @@ unsigned long read_data(XSelectionEvent *sev, Atom sel, Atom prop, Atom target,
149
202
return 0 ;
150
203
}
151
204
152
- int ret = XGetWindowProperty (sev -> display , sev -> requestor , sev -> property ,
205
+ int ret = ( * P_XGetWindowProperty ) (sev -> display , sev -> requestor , sev -> property ,
153
206
0L , (~0L ), 0 , AnyPropertyType , & actual , & format , & size , & n , & data );
154
207
if (ret != Success ) {
155
208
return 0 ;
@@ -159,8 +212,8 @@ unsigned long read_data(XSelectionEvent *sev, Atom sel, Atom prop, Atom target,
159
212
* buf = (char * )malloc (size * sizeof (char ));
160
213
memcpy (* buf , data , size * sizeof (char ));
161
214
}
162
- XFree (data );
163
- XDeleteProperty (sev -> display , sev -> requestor , sev -> property );
215
+ ( * P_XFree ) (data );
216
+ ( * P_XDeleteProperty ) (sev -> display , sev -> requestor , sev -> property );
164
217
return size * sizeof (char );
165
218
}
166
219
@@ -169,9 +222,13 @@ unsigned long read_data(XSelectionEvent *sev, Atom sel, Atom prop, Atom target,
169
222
//
170
223
// The caller of this function should responsible for the free of the buf.
171
224
unsigned long clipboard_read (char * typ , char * * buf ) {
225
+ if (!initX11 ()) {
226
+ return -1 ;
227
+ }
228
+
172
229
Display * d = NULL ;
173
230
for (int i = 0 ; i < 42 ; i ++ ) {
174
- d = XOpenDisplay (0 );
231
+ d = ( * P_XOpenDisplay ) (0 );
175
232
if (d == NULL ) {
176
233
continue ;
177
234
}
@@ -181,27 +238,27 @@ unsigned long clipboard_read(char* typ, char **buf) {
181
238
return -1 ;
182
239
}
183
240
184
- Window w = XCreateSimpleWindow ( d , DefaultRootWindow (d ), 0 , 0 , 1 , 1 , 0 , 0 , 0 );
241
+ Window w = ( * P_XCreateSimpleWindow )( d , ( * P_XDefaultRootWindow ) (d ), 0 , 0 , 1 , 1 , 0 , 0 , 0 );
185
242
186
243
// Use False because these may not available for the first time.
187
- Atom sel = XInternAtom (d , "CLIPBOARD" , False );
188
- Atom prop = XInternAtom (d , "GOLANG_DESIGN_DATA" , False );
244
+ Atom sel = ( * P_XInternAtom ) (d , "CLIPBOARD" , False );
245
+ Atom prop = ( * P_XInternAtom ) (d , "GOLANG_DESIGN_DATA" , False );
189
246
190
247
// Use True to makesure the requested type is a valid type.
191
- Atom target = XInternAtom (d , typ , True );
248
+ Atom target = ( * P_XInternAtom ) (d , typ , True );
192
249
if (target == None ) {
193
- XCloseDisplay (d );
250
+ ( * P_XCloseDisplay ) (d );
194
251
return -2 ;
195
252
}
196
253
197
- XConvertSelection (d , sel , target , prop , w , CurrentTime );
254
+ ( * P_XConvertSelection ) (d , sel , target , prop , w , CurrentTime );
198
255
XEvent event ;
199
256
for (;;) {
200
- XNextEvent (d , & event );
257
+ ( * P_XNextEvent ) (d , & event );
201
258
if (event .type != SelectionNotify ) continue ;
202
259
break ;
203
260
}
204
261
unsigned long n = read_data ((XSelectionEvent * )& event .xselection , sel , prop , target , buf );
205
- XCloseDisplay (d );
262
+ ( * P_XCloseDisplay ) (d );
206
263
return n ;
207
- }
264
+ }
0 commit comments