1111#include <stdio.h>
1212#include <stdint.h>
1313#include <string.h>
14+ #include <dlfcn.h>
1415#include <X11/Xlib.h>
1516#include <X11/Xatom.h>
1617
1718// syncStatus is a function from the Go side.
1819extern void syncStatus (uintptr_t handle , int status );
1920
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+
2063int clipboard_test () {
64+ if (!initX11 ()) {
65+ return -1 ;
66+ }
67+
2168 Display * d = NULL ;
2269 for (int i = 0 ; i < 42 ; i ++ ) {
23- d = XOpenDisplay (0 );
70+ d = ( * P_XOpenDisplay ) (0 );
2471 if (d == NULL ) {
2572 continue ;
2673 }
2774 break ;
2875 }
29-
3076 if (d == NULL ) {
3177 return -1 ;
3278 }
33- XCloseDisplay (d );
79+ ( * P_XCloseDisplay ) (d );
3480 return 0 ;
3581}
3682
3783// clipboard_write writes the given buf of size n as type typ.
3884// if start is provided, the value of start will be changed to 1 to indicate
3985// if the write is availiable for reading.
4086int clipboard_write (char * typ , unsigned char * buf , size_t n , uintptr_t handle ) {
87+ if (!initX11 ()) {
88+ return -1 ;
89+ }
90+
4191 Display * d = NULL ;
4292 for (int i = 0 ; i < 42 ; i ++ ) {
43- d = XOpenDisplay (0 );
93+ d = ( * P_XOpenDisplay ) (0 );
4494 if (d == NULL ) {
4595 continue ;
4696 }
@@ -50,26 +100,25 @@ int clipboard_write(char *typ, unsigned char *buf, size_t n, uintptr_t handle) {
50100 syncStatus (handle , -1 );
51101 return -1 ;
52102 }
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 );
55104
56105 // 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 );
61110
62111 // 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 );
64113 if (target == None ) {
65- XCloseDisplay (d );
114+ ( * P_XCloseDisplay ) (d );
66115 syncStatus (handle , -2 );
67116 return -2 ;
68117 }
69118
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 );
73122 syncStatus (handle , -3 );
74123 return -3 ;
75124 }
@@ -83,13 +132,13 @@ int clipboard_write(char *typ, unsigned char *buf, size_t n, uintptr_t handle) {
83132 notified = 1 ;
84133 }
85134
86- XNextEvent (d , & event );
135+ ( * P_XNextEvent ) (d , & event );
87136 switch (event .type ) {
88137 case SelectionClear :
89138 // For debugging:
90139 // printf("x11write: lost ownership of clipboard selection.\n");
91140 // fflush(stdout);
92- XCloseDisplay (d );
141+ ( * P_XCloseDisplay ) (d );
93142 return 0 ;
94143 case SelectionNotify :
95144 // For debugging:
@@ -114,24 +163,24 @@ int clipboard_write(char *typ, unsigned char *buf, size_t n, uintptr_t handle) {
114163 ev .property = xsr -> property ;
115164
116165 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 ,
118167 atomString , 8 , PropModeReplace , buf , n );
119168 } 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 ,
121170 atomImage , 8 , PropModeReplace , buf , n );
122171 } else if (ev .target == targetsAtom ) {
123172 // Reply atoms for supported targets, other clients should
124173 // request the clipboard again and obtain the data if their
125174 // implementation is correct.
126175 Atom targets [] = { atomString , atomImage };
127- R = XChangeProperty (ev .display , ev .requestor , ev .property ,
176+ R = ( * P_XChangeProperty ) (ev .display , ev .requestor , ev .property ,
128177 XA_ATOM , 32 , PropModeReplace ,
129178 (unsigned char * )& targets , sizeof (targets )/sizeof (Atom ));
130179 } else {
131180 ev .property = None ;
132181 }
133182
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 );
135184 break ;
136185 }
137186 }
@@ -140,6 +189,10 @@ int clipboard_write(char *typ, unsigned char *buf, size_t n, uintptr_t handle) {
140189// read_data reads the property of a selection if the target atom matches
141190// the actual atom.
142191unsigned long read_data (XSelectionEvent * sev , Atom sel , Atom prop , Atom target , char * * buf ) {
192+ if (!initX11 ()) {
193+ return -1 ;
194+ }
195+
143196 unsigned char * data ;
144197 Atom actual ;
145198 int format ;
@@ -149,7 +202,7 @@ unsigned long read_data(XSelectionEvent *sev, Atom sel, Atom prop, Atom target,
149202 return 0 ;
150203 }
151204
152- int ret = XGetWindowProperty (sev -> display , sev -> requestor , sev -> property ,
205+ int ret = ( * P_XGetWindowProperty ) (sev -> display , sev -> requestor , sev -> property ,
153206 0L , (~0L ), 0 , AnyPropertyType , & actual , & format , & size , & n , & data );
154207 if (ret != Success ) {
155208 return 0 ;
@@ -159,8 +212,8 @@ unsigned long read_data(XSelectionEvent *sev, Atom sel, Atom prop, Atom target,
159212 * buf = (char * )malloc (size * sizeof (char ));
160213 memcpy (* buf , data , size * sizeof (char ));
161214 }
162- XFree (data );
163- XDeleteProperty (sev -> display , sev -> requestor , sev -> property );
215+ ( * P_XFree ) (data );
216+ ( * P_XDeleteProperty ) (sev -> display , sev -> requestor , sev -> property );
164217 return size * sizeof (char );
165218}
166219
@@ -169,9 +222,13 @@ unsigned long read_data(XSelectionEvent *sev, Atom sel, Atom prop, Atom target,
169222//
170223// The caller of this function should responsible for the free of the buf.
171224unsigned long clipboard_read (char * typ , char * * buf ) {
225+ if (!initX11 ()) {
226+ return -1 ;
227+ }
228+
172229 Display * d = NULL ;
173230 for (int i = 0 ; i < 42 ; i ++ ) {
174- d = XOpenDisplay (0 );
231+ d = ( * P_XOpenDisplay ) (0 );
175232 if (d == NULL ) {
176233 continue ;
177234 }
@@ -181,27 +238,27 @@ unsigned long clipboard_read(char* typ, char **buf) {
181238 return -1 ;
182239 }
183240
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 );
185242
186243 // 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 );
189246
190247 // 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 );
192249 if (target == None ) {
193- XCloseDisplay (d );
250+ ( * P_XCloseDisplay ) (d );
194251 return -2 ;
195252 }
196253
197- XConvertSelection (d , sel , target , prop , w , CurrentTime );
254+ ( * P_XConvertSelection ) (d , sel , target , prop , w , CurrentTime );
198255 XEvent event ;
199256 for (;;) {
200- XNextEvent (d , & event );
257+ ( * P_XNextEvent ) (d , & event );
201258 if (event .type != SelectionNotify ) continue ;
202259 break ;
203260 }
204261 unsigned long n = read_data ((XSelectionEvent * )& event .xselection , sel , prop , target , buf );
205- XCloseDisplay (d );
262+ ( * P_XCloseDisplay ) (d );
206263 return n ;
207- }
264+ }
0 commit comments