Blame


1 50923426 2020-01-13 rsc #include <u.h>
2 50923426 2020-01-13 rsc #include "x11-inc.h"
3 50923426 2020-01-13 rsc #include "x11-keysym2ucs.h"
4 50923426 2020-01-13 rsc #include <errno.h>
5 50923426 2020-01-13 rsc #include <libc.h>
6 50923426 2020-01-13 rsc #include <draw.h>
7 50923426 2020-01-13 rsc #include <memdraw.h>
8 50923426 2020-01-13 rsc #include <memlayer.h>
9 50923426 2020-01-13 rsc #include <keyboard.h>
10 50923426 2020-01-13 rsc #include <mouse.h>
11 50923426 2020-01-13 rsc #include <cursor.h>
12 50923426 2020-01-13 rsc #include <thread.h>
13 50923426 2020-01-13 rsc #include "x11-memdraw.h"
14 50923426 2020-01-13 rsc #include "devdraw.h"
15 50923426 2020-01-13 rsc
16 50923426 2020-01-13 rsc #undef time
17 50923426 2020-01-13 rsc
18 50923426 2020-01-13 rsc static void plan9cmap(void);
19 50923426 2020-01-13 rsc static int setupcmap(XWindow);
20 50923426 2020-01-13 rsc static XGC xgc(XDrawable, int, int);
21 50923426 2020-01-13 rsc #define Mask MouseMask|ExposureMask|StructureNotifyMask|KeyPressMask|KeyReleaseMask|EnterWindowMask|LeaveWindowMask|FocusChangeMask
22 50923426 2020-01-13 rsc
23 50923426 2020-01-13 rsc #define MouseMask (\
24 50923426 2020-01-13 rsc ButtonPressMask|\
25 50923426 2020-01-13 rsc ButtonReleaseMask|\
26 50923426 2020-01-13 rsc PointerMotionMask|\
27 50923426 2020-01-13 rsc Button1MotionMask|\
28 50923426 2020-01-13 rsc Button2MotionMask|\
29 50923426 2020-01-13 rsc Button3MotionMask)
30 50923426 2020-01-13 rsc
31 50923426 2020-01-13 rsc Xprivate _x;
32 50923426 2020-01-13 rsc
33 50923426 2020-01-13 rsc static void runxevent(XEvent *xev);
34 50923426 2020-01-13 rsc static int _xconfigure(Xwin *w, XEvent *e);
35 50923426 2020-01-13 rsc static int _xdestroy(Xwin *w, XEvent *e);
36 50923426 2020-01-13 rsc static void _xexpose(Xwin *w, XEvent *e);
37 50923426 2020-01-13 rsc static int _xreplacescreenimage(Client *client);
38 50923426 2020-01-13 rsc static int _xtoplan9mouse(Xwin *w, XEvent *e, Mouse *m);
39 50923426 2020-01-13 rsc static void _xmovewindow(Xwin *w, Rectangle r);
40 50923426 2020-01-13 rsc static int _xtoplan9kbd(XEvent *e);
41 50923426 2020-01-13 rsc static int _xselect(XEvent *e);
42 50923426 2020-01-13 rsc
43 84167be4 2020-05-18 rsc static void rpc_resizeimg(Client*);
44 84167be4 2020-05-18 rsc static void rpc_resizewindow(Client*, Rectangle);
45 84167be4 2020-05-18 rsc static void rpc_setcursor(Client*, Cursor*, Cursor2*);
46 84167be4 2020-05-18 rsc static void rpc_setlabel(Client*, char*);
47 84167be4 2020-05-18 rsc static void rpc_setmouse(Client*, Point);
48 84167be4 2020-05-18 rsc static void rpc_topwin(Client*);
49 84167be4 2020-05-18 rsc static void rpc_bouncemouse(Client*, Mouse);
50 84167be4 2020-05-18 rsc static void rpc_flush(Client*, Rectangle);
51 84167be4 2020-05-18 rsc
52 84167be4 2020-05-18 rsc static ClientImpl x11impl = {
53 84167be4 2020-05-18 rsc rpc_resizeimg,
54 84167be4 2020-05-18 rsc rpc_resizewindow,
55 84167be4 2020-05-18 rsc rpc_setcursor,
56 84167be4 2020-05-18 rsc rpc_setlabel,
57 84167be4 2020-05-18 rsc rpc_setmouse,
58 84167be4 2020-05-18 rsc rpc_topwin,
59 84167be4 2020-05-18 rsc rpc_bouncemouse,
60 84167be4 2020-05-18 rsc rpc_flush
61 84167be4 2020-05-18 rsc };
62 84167be4 2020-05-18 rsc
63 50923426 2020-01-13 rsc static Xwin*
64 50923426 2020-01-13 rsc newxwin(Client *c)
65 50923426 2020-01-13 rsc {
66 50923426 2020-01-13 rsc Xwin *w;
67 1f799495 2020-01-15 rsc
68 50923426 2020-01-13 rsc w = mallocz(sizeof *w, 1);
69 50923426 2020-01-13 rsc if(w == nil)
70 50923426 2020-01-13 rsc sysfatal("out of memory");
71 50923426 2020-01-13 rsc w->client = c;
72 50923426 2020-01-13 rsc w->next = _x.windows;
73 50923426 2020-01-13 rsc _x.windows = w;
74 84167be4 2020-05-18 rsc c->impl = &x11impl;
75 50923426 2020-01-13 rsc c->view = w;
76 50923426 2020-01-13 rsc return w;
77 50923426 2020-01-13 rsc }
78 50923426 2020-01-13 rsc
79 50923426 2020-01-13 rsc static Xwin*
80 50923426 2020-01-13 rsc findxwin(XDrawable d)
81 50923426 2020-01-13 rsc {
82 50923426 2020-01-13 rsc Xwin *w, **l;
83 1f799495 2020-01-15 rsc
84 50923426 2020-01-13 rsc for(l=&_x.windows; (w=*l) != nil; l=&w->next) {
85 50923426 2020-01-13 rsc if(w->drawable == d) {
86 50923426 2020-01-13 rsc /* move to front */
87 50923426 2020-01-13 rsc *l = w->next;
88 50923426 2020-01-13 rsc w->next = _x.windows;
89 50923426 2020-01-13 rsc _x.windows = w;
90 50923426 2020-01-13 rsc return w;
91 50923426 2020-01-13 rsc }
92 50923426 2020-01-13 rsc }
93 50923426 2020-01-13 rsc return nil;
94 50923426 2020-01-13 rsc }
95 50923426 2020-01-13 rsc
96 50923426 2020-01-13 rsc static int
97 50923426 2020-01-13 rsc xerror(XDisplay *d, XErrorEvent *e)
98 50923426 2020-01-13 rsc {
99 50923426 2020-01-13 rsc char buf[200];
100 50923426 2020-01-13 rsc
101 50923426 2020-01-13 rsc if(e->request_code == 42) /* XSetInputFocus */
102 50923426 2020-01-13 rsc return 0;
103 50923426 2020-01-13 rsc if(e->request_code == 18) /* XChangeProperty */
104 50923426 2020-01-13 rsc return 0;
105 50923426 2020-01-13 rsc /*
106 50923426 2020-01-13 rsc * BadDrawable happens in apps that get resized a LOT,
107 50923426 2020-01-13 rsc * e.g. when KDE is configured to resize continuously
108 50923426 2020-01-13 rsc * during a window drag.
109 50923426 2020-01-13 rsc */
110 50923426 2020-01-13 rsc if(e->error_code == 9) /* BadDrawable */
111 50923426 2020-01-13 rsc return 0;
112 50923426 2020-01-13 rsc
113 50923426 2020-01-13 rsc fprint(2, "X error: error_code=%d, request_code=%d, minor=%d disp=%p\n",
114 50923426 2020-01-13 rsc e->error_code, e->request_code, e->minor_code, d);
115 50923426 2020-01-13 rsc XGetErrorText(d, e->error_code, buf, sizeof buf);
116 50923426 2020-01-13 rsc fprint(2, "%s\n", buf);
117 50923426 2020-01-13 rsc return 0;
118 50923426 2020-01-13 rsc }
119 50923426 2020-01-13 rsc
120 50923426 2020-01-13 rsc static int
121 50923426 2020-01-13 rsc xioerror(XDisplay *d)
122 50923426 2020-01-13 rsc {
123 50923426 2020-01-13 rsc /*print("X I/O error\n"); */
124 50923426 2020-01-13 rsc exit(0);
125 50923426 2020-01-13 rsc /*sysfatal("X I/O error\n");*/
126 50923426 2020-01-13 rsc abort();
127 50923426 2020-01-13 rsc return -1;
128 50923426 2020-01-13 rsc }
129 50923426 2020-01-13 rsc
130 50923426 2020-01-13 rsc static void xloop(void);
131 50923426 2020-01-13 rsc
132 50923426 2020-01-13 rsc static QLock xlk;
133 50923426 2020-01-13 rsc
134 50923426 2020-01-13 rsc void
135 50923426 2020-01-13 rsc xlock(void)
136 50923426 2020-01-13 rsc {
137 50923426 2020-01-13 rsc qlock(&xlk);
138 50923426 2020-01-13 rsc }
139 50923426 2020-01-13 rsc
140 50923426 2020-01-13 rsc void
141 50923426 2020-01-13 rsc xunlock(void)
142 50923426 2020-01-13 rsc {
143 50923426 2020-01-13 rsc qunlock(&xlk);
144 50923426 2020-01-13 rsc }
145 50923426 2020-01-13 rsc
146 50923426 2020-01-13 rsc void
147 50923426 2020-01-13 rsc gfx_main(void)
148 50923426 2020-01-13 rsc {
149 50923426 2020-01-13 rsc char *disp;
150 50923426 2020-01-13 rsc int i, n, xrootid;
151 50923426 2020-01-13 rsc XPixmapFormatValues *pfmt;
152 50923426 2020-01-13 rsc XScreen *xscreen;
153 50923426 2020-01-13 rsc XVisualInfo xvi;
154 50923426 2020-01-13 rsc XWindow xrootwin;
155 50923426 2020-01-13 rsc
156 50923426 2020-01-13 rsc /*
157 50923426 2020-01-13 rsc if(XInitThreads() == 0)
158 50923426 2020-01-13 rsc sysfatal("XInitThread: %r");
159 50923426 2020-01-13 rsc */
160 50923426 2020-01-13 rsc
161 50923426 2020-01-13 rsc /*
162 50923426 2020-01-13 rsc * Connect to X server.
163 50923426 2020-01-13 rsc */
164 50923426 2020-01-13 rsc _x.display = XOpenDisplay(NULL);
165 50923426 2020-01-13 rsc if(_x.display == nil){
166 50923426 2020-01-13 rsc disp = getenv("DISPLAY");
167 50923426 2020-01-13 rsc werrstr("XOpenDisplay %s: %r", disp ? disp : ":0");
168 50923426 2020-01-13 rsc free(disp);
169 50923426 2020-01-13 rsc sysfatal("%r");
170 50923426 2020-01-13 rsc }
171 50923426 2020-01-13 rsc _x.fd = ConnectionNumber(_x.display);
172 50923426 2020-01-13 rsc XSetErrorHandler(xerror);
173 50923426 2020-01-13 rsc XSetIOErrorHandler(xioerror);
174 50923426 2020-01-13 rsc xrootid = DefaultScreen(_x.display);
175 50923426 2020-01-13 rsc xrootwin = DefaultRootWindow(_x.display);
176 50923426 2020-01-13 rsc
177 50923426 2020-01-13 rsc /*
178 50923426 2020-01-13 rsc * Figure out underlying screen format.
179 50923426 2020-01-13 rsc */
180 50923426 2020-01-13 rsc if(XMatchVisualInfo(_x.display, xrootid, 24, TrueColor, &xvi)
181 50923426 2020-01-13 rsc || XMatchVisualInfo(_x.display, xrootid, 24, DirectColor, &xvi)){
182 50923426 2020-01-13 rsc _x.vis = xvi.visual;
183 50923426 2020-01-13 rsc _x.depth = 24;
184 50923426 2020-01-13 rsc }
185 50923426 2020-01-13 rsc else
186 50923426 2020-01-13 rsc if(XMatchVisualInfo(_x.display, xrootid, 16, TrueColor, &xvi)
187 50923426 2020-01-13 rsc || XMatchVisualInfo(_x.display, xrootid, 16, DirectColor, &xvi)){
188 50923426 2020-01-13 rsc _x.vis = xvi.visual;
189 50923426 2020-01-13 rsc _x.depth = 16;
190 50923426 2020-01-13 rsc }
191 50923426 2020-01-13 rsc else
192 50923426 2020-01-13 rsc if(XMatchVisualInfo(_x.display, xrootid, 15, TrueColor, &xvi)
193 50923426 2020-01-13 rsc || XMatchVisualInfo(_x.display, xrootid, 15, DirectColor, &xvi)){
194 50923426 2020-01-13 rsc _x.vis = xvi.visual;
195 50923426 2020-01-13 rsc _x.depth = 15;
196 50923426 2020-01-13 rsc }
197 50923426 2020-01-13 rsc else
198 50923426 2020-01-13 rsc if(XMatchVisualInfo(_x.display, xrootid, 8, PseudoColor, &xvi)
199 50923426 2020-01-13 rsc || XMatchVisualInfo(_x.display, xrootid, 8, StaticColor, &xvi)){
200 50923426 2020-01-13 rsc if(_x.depth > 8){
201 50923426 2020-01-13 rsc werrstr("can't deal with colormapped depth %d screens",
202 50923426 2020-01-13 rsc _x.depth);
203 50923426 2020-01-13 rsc goto err0;
204 50923426 2020-01-13 rsc }
205 50923426 2020-01-13 rsc _x.vis = xvi.visual;
206 50923426 2020-01-13 rsc _x.depth = 8;
207 50923426 2020-01-13 rsc }
208 50923426 2020-01-13 rsc else{
209 50923426 2020-01-13 rsc _x.depth = DefaultDepth(_x.display, xrootid);
210 50923426 2020-01-13 rsc if(_x.depth != 8){
211 50923426 2020-01-13 rsc werrstr("can't understand depth %d screen", _x.depth);
212 50923426 2020-01-13 rsc goto err0;
213 50923426 2020-01-13 rsc }
214 50923426 2020-01-13 rsc _x.vis = DefaultVisual(_x.display, xrootid);
215 50923426 2020-01-13 rsc }
216 50923426 2020-01-13 rsc
217 50923426 2020-01-13 rsc if(DefaultDepth(_x.display, xrootid) == _x.depth)
218 50923426 2020-01-13 rsc _x.usetable = 1;
219 50923426 2020-01-13 rsc
220 50923426 2020-01-13 rsc /*
221 50923426 2020-01-13 rsc * _x.depth is only the number of significant pixel bits,
222 50923426 2020-01-13 rsc * not the total number of pixel bits. We need to walk the
223 50923426 2020-01-13 rsc * display list to find how many actual bits are used
224 50923426 2020-01-13 rsc * per pixel.
225 50923426 2020-01-13 rsc */
226 50923426 2020-01-13 rsc _x.chan = 0;
227 50923426 2020-01-13 rsc pfmt = XListPixmapFormats(_x.display, &n);
228 50923426 2020-01-13 rsc for(i=0; i<n; i++){
229 50923426 2020-01-13 rsc if(pfmt[i].depth == _x.depth){
230 50923426 2020-01-13 rsc switch(pfmt[i].bits_per_pixel){
231 50923426 2020-01-13 rsc case 1: /* untested */
232 50923426 2020-01-13 rsc _x.chan = GREY1;
233 50923426 2020-01-13 rsc break;
234 50923426 2020-01-13 rsc case 2: /* untested */
235 50923426 2020-01-13 rsc _x.chan = GREY2;
236 50923426 2020-01-13 rsc break;
237 50923426 2020-01-13 rsc case 4: /* untested */
238 50923426 2020-01-13 rsc _x.chan = GREY4;
239 50923426 2020-01-13 rsc break;
240 50923426 2020-01-13 rsc case 8:
241 50923426 2020-01-13 rsc _x.chan = CMAP8;
242 50923426 2020-01-13 rsc break;
243 50923426 2020-01-13 rsc case 15:
244 50923426 2020-01-13 rsc _x.chan = RGB15;
245 50923426 2020-01-13 rsc break;
246 50923426 2020-01-13 rsc case 16: /* how to tell RGB15? */
247 50923426 2020-01-13 rsc _x.chan = RGB16;
248 50923426 2020-01-13 rsc break;
249 50923426 2020-01-13 rsc case 24: /* untested (impossible?) */
250 50923426 2020-01-13 rsc _x.chan = RGB24;
251 50923426 2020-01-13 rsc break;
252 50923426 2020-01-13 rsc case 32:
253 50923426 2020-01-13 rsc _x.chan = XRGB32;
254 50923426 2020-01-13 rsc break;
255 50923426 2020-01-13 rsc }
256 50923426 2020-01-13 rsc }
257 50923426 2020-01-13 rsc }
258 50923426 2020-01-13 rsc XFree(pfmt);
259 50923426 2020-01-13 rsc if(_x.chan == 0){
260 50923426 2020-01-13 rsc werrstr("could not determine screen pixel format");
261 50923426 2020-01-13 rsc goto err0;
262 50923426 2020-01-13 rsc }
263 50923426 2020-01-13 rsc
264 50923426 2020-01-13 rsc /*
265 50923426 2020-01-13 rsc * Set up color map if necessary.
266 50923426 2020-01-13 rsc */
267 50923426 2020-01-13 rsc xscreen = DefaultScreenOfDisplay(_x.display);
268 50923426 2020-01-13 rsc _x.cmap = DefaultColormapOfScreen(xscreen);
269 50923426 2020-01-13 rsc if(_x.vis->class != StaticColor){
270 50923426 2020-01-13 rsc plan9cmap();
271 50923426 2020-01-13 rsc setupcmap(xrootwin);
272 50923426 2020-01-13 rsc }
273 50923426 2020-01-13 rsc gfx_started();
274 50923426 2020-01-13 rsc xloop();
275 50923426 2020-01-13 rsc
276 50923426 2020-01-13 rsc err0:
277 50923426 2020-01-13 rsc XCloseDisplay(_x.display);
278 50923426 2020-01-13 rsc sysfatal("%r");
279 50923426 2020-01-13 rsc }
280 50923426 2020-01-13 rsc
281 50923426 2020-01-13 rsc static void
282 50923426 2020-01-13 rsc xloop(void)
283 50923426 2020-01-13 rsc {
284 50923426 2020-01-13 rsc fd_set rd, wr, xx;
285 50923426 2020-01-13 rsc XEvent event;
286 50923426 2020-01-13 rsc
287 50923426 2020-01-13 rsc xlock();
288 50923426 2020-01-13 rsc _x.fd = ConnectionNumber(_x.display);
289 50923426 2020-01-13 rsc for(;;) {
290 50923426 2020-01-13 rsc FD_ZERO(&rd);
291 50923426 2020-01-13 rsc FD_ZERO(&wr);
292 50923426 2020-01-13 rsc FD_ZERO(&xx);
293 50923426 2020-01-13 rsc FD_SET(_x.fd, &rd);
294 50923426 2020-01-13 rsc FD_SET(_x.fd, &xx);
295 50923426 2020-01-13 rsc if(_x.windows != nil)
296 50923426 2020-01-13 rsc XSelectInput(_x.display, _x.windows->drawable, Mask); // TODO: when is this needed?
297 50923426 2020-01-13 rsc XFlush(_x.display);
298 50923426 2020-01-13 rsc xunlock();
299 50923426 2020-01-13 rsc
300 50923426 2020-01-13 rsc again:
301 50923426 2020-01-13 rsc if(select(_x.fd+1, &rd, &wr, &xx, nil) < 0) {
302 50923426 2020-01-13 rsc if(errno == EINTR)
303 50923426 2020-01-13 rsc goto again;
304 50923426 2020-01-13 rsc sysfatal("select: %r"); // TODO: quiet exit?
305 50923426 2020-01-13 rsc }
306 50923426 2020-01-13 rsc
307 50923426 2020-01-13 rsc xlock();
308 50923426 2020-01-13 rsc while(XPending(_x.display)) {
309 50923426 2020-01-13 rsc XNextEvent(_x.display, &event);
310 50923426 2020-01-13 rsc runxevent(&event);
311 50923426 2020-01-13 rsc }
312 50923426 2020-01-13 rsc }
313 50923426 2020-01-13 rsc }
314 50923426 2020-01-13 rsc
315 50923426 2020-01-13 rsc /*
316 50923426 2020-01-13 rsc * Handle an incoming X event.
317 50923426 2020-01-13 rsc */
318 50923426 2020-01-13 rsc static void
319 50923426 2020-01-13 rsc runxevent(XEvent *xev)
320 50923426 2020-01-13 rsc {
321 50923426 2020-01-13 rsc int c;
322 50923426 2020-01-13 rsc KeySym k;
323 50923426 2020-01-13 rsc static Mouse m;
324 50923426 2020-01-13 rsc XButtonEvent *be;
325 50923426 2020-01-13 rsc XKeyEvent *ke;
326 50923426 2020-01-13 rsc Xwin *w;
327 50923426 2020-01-13 rsc
328 50923426 2020-01-13 rsc #ifdef SHOWEVENT
329 50923426 2020-01-13 rsc static int first = 1;
330 50923426 2020-01-13 rsc if(first){
331 50923426 2020-01-13 rsc dup(create("/tmp/devdraw.out", OWRITE, 0666), 1);
332 50923426 2020-01-13 rsc setbuf(stdout, 0);
333 50923426 2020-01-13 rsc first = 0;
334 50923426 2020-01-13 rsc }
335 50923426 2020-01-13 rsc #endif
336 50923426 2020-01-13 rsc
337 50923426 2020-01-13 rsc if(xev == 0)
338 50923426 2020-01-13 rsc return;
339 50923426 2020-01-13 rsc
340 50923426 2020-01-13 rsc #ifdef SHOWEVENT
341 50923426 2020-01-13 rsc print("\n");
342 50923426 2020-01-13 rsc ShowEvent(xev);
343 50923426 2020-01-13 rsc #endif
344 50923426 2020-01-13 rsc
345 50923426 2020-01-13 rsc w = nil;
346 50923426 2020-01-13 rsc switch(xev->type){
347 50923426 2020-01-13 rsc case Expose:
348 50923426 2020-01-13 rsc w = findxwin(((XExposeEvent*)xev)->window);
349 50923426 2020-01-13 rsc break;
350 50923426 2020-01-13 rsc case DestroyNotify:
351 50923426 2020-01-13 rsc w = findxwin(((XDestroyWindowEvent*)xev)->window);
352 50923426 2020-01-13 rsc break;
353 50923426 2020-01-13 rsc case ConfigureNotify:
354 50923426 2020-01-13 rsc w = findxwin(((XConfigureEvent*)xev)->window);
355 50923426 2020-01-13 rsc break;
356 50923426 2020-01-13 rsc case ButtonPress:
357 50923426 2020-01-13 rsc case ButtonRelease:
358 50923426 2020-01-13 rsc w = findxwin(((XButtonEvent*)xev)->window);
359 50923426 2020-01-13 rsc break;
360 50923426 2020-01-13 rsc case MotionNotify:
361 50923426 2020-01-13 rsc w = findxwin(((XMotionEvent*)xev)->window);
362 50923426 2020-01-13 rsc break;
363 50923426 2020-01-13 rsc case KeyRelease:
364 50923426 2020-01-13 rsc case KeyPress:
365 50923426 2020-01-13 rsc w = findxwin(((XKeyEvent*)xev)->window);
366 50923426 2020-01-13 rsc break;
367 50923426 2020-01-13 rsc case FocusOut:
368 50923426 2020-01-13 rsc w = findxwin(((XFocusChangeEvent*)xev)->window);
369 50923426 2020-01-13 rsc break;
370 50923426 2020-01-13 rsc }
371 50923426 2020-01-13 rsc if(w == nil)
372 50923426 2020-01-13 rsc w = _x.windows;
373 50923426 2020-01-13 rsc
374 50923426 2020-01-13 rsc switch(xev->type){
375 50923426 2020-01-13 rsc case Expose:
376 50923426 2020-01-13 rsc _xexpose(w, xev);
377 50923426 2020-01-13 rsc break;
378 50923426 2020-01-13 rsc
379 50923426 2020-01-13 rsc case DestroyNotify:
380 50923426 2020-01-13 rsc if(_xdestroy(w, xev))
381 50923426 2020-01-13 rsc threadexitsall(nil);
382 50923426 2020-01-13 rsc break;
383 50923426 2020-01-13 rsc
384 50923426 2020-01-13 rsc case ConfigureNotify:
385 50923426 2020-01-13 rsc if(_xconfigure(w, xev))
386 50923426 2020-01-13 rsc _xreplacescreenimage(w->client);
387 50923426 2020-01-13 rsc break;
388 50923426 2020-01-13 rsc
389 50923426 2020-01-13 rsc case ButtonPress:
390 50923426 2020-01-13 rsc be = (XButtonEvent*)xev;
391 50923426 2020-01-13 rsc if(be->button == 1) {
392 50923426 2020-01-13 rsc if(_x.kstate & ControlMask)
393 50923426 2020-01-13 rsc be->button = 2;
394 50923426 2020-01-13 rsc else if(_x.kstate & Mod1Mask)
395 50923426 2020-01-13 rsc be->button = 3;
396 50923426 2020-01-13 rsc }
397 50923426 2020-01-13 rsc // fall through
398 50923426 2020-01-13 rsc case ButtonRelease:
399 50923426 2020-01-13 rsc _x.altdown = 0;
400 50923426 2020-01-13 rsc // fall through
401 50923426 2020-01-13 rsc case MotionNotify:
402 50923426 2020-01-13 rsc if(_xtoplan9mouse(w, xev, &m) < 0)
403 50923426 2020-01-13 rsc return;
404 50923426 2020-01-13 rsc gfx_mousetrack(w->client, m.xy.x, m.xy.y, m.buttons|_x.kbuttons, m.msec);
405 50923426 2020-01-13 rsc break;
406 50923426 2020-01-13 rsc
407 50923426 2020-01-13 rsc case KeyRelease:
408 50923426 2020-01-13 rsc case KeyPress:
409 50923426 2020-01-13 rsc ke = (XKeyEvent*)xev;
410 50923426 2020-01-13 rsc XLookupString(ke, NULL, 0, &k, NULL);
411 50923426 2020-01-13 rsc c = ke->state;
412 50923426 2020-01-13 rsc switch(k) {
413 50923426 2020-01-13 rsc case XK_Alt_L:
414 50923426 2020-01-13 rsc case XK_Meta_L: /* Shift Alt on PCs */
415 50923426 2020-01-13 rsc case XK_Alt_R:
416 50923426 2020-01-13 rsc case XK_Meta_R: /* Shift Alt on PCs */
417 50923426 2020-01-13 rsc case XK_Multi_key:
418 50923426 2020-01-13 rsc if(xev->type == KeyPress)
419 50923426 2020-01-13 rsc _x.altdown = 1;
420 50923426 2020-01-13 rsc else if(_x.altdown) {
421 50923426 2020-01-13 rsc _x.altdown = 0;
422 50923426 2020-01-13 rsc gfx_keystroke(w->client, Kalt);
423 50923426 2020-01-13 rsc }
424 50923426 2020-01-13 rsc break;
425 50923426 2020-01-13 rsc }
426 50923426 2020-01-13 rsc
427 50923426 2020-01-13 rsc switch(k) {
428 50923426 2020-01-13 rsc case XK_Control_L:
429 50923426 2020-01-13 rsc if(xev->type == KeyPress)
430 50923426 2020-01-13 rsc c |= ControlMask;
431 50923426 2020-01-13 rsc else
432 50923426 2020-01-13 rsc c &= ~ControlMask;
433 50923426 2020-01-13 rsc goto kbutton;
434 50923426 2020-01-13 rsc case XK_Alt_L:
435 50923426 2020-01-13 rsc case XK_Shift_L:
436 50923426 2020-01-13 rsc if(xev->type == KeyPress)
437 50923426 2020-01-13 rsc c |= Mod1Mask;
438 50923426 2020-01-13 rsc else
439 50923426 2020-01-13 rsc c &= ~Mod1Mask;
440 50923426 2020-01-13 rsc kbutton:
441 50923426 2020-01-13 rsc _x.kstate = c;
442 50923426 2020-01-13 rsc if(m.buttons || _x.kbuttons) {
443 50923426 2020-01-13 rsc _x.altdown = 0; // used alt
444 50923426 2020-01-13 rsc _x.kbuttons = 0;
445 50923426 2020-01-13 rsc if(c & ControlMask)
446 50923426 2020-01-13 rsc _x.kbuttons |= 2;
447 50923426 2020-01-13 rsc if(c & Mod1Mask)
448 50923426 2020-01-13 rsc _x.kbuttons |= 4;
449 50923426 2020-01-13 rsc gfx_mousetrack(w->client, m.xy.x, m.xy.y, m.buttons|_x.kbuttons, m.msec);
450 50923426 2020-01-13 rsc break;
451 50923426 2020-01-13 rsc }
452 50923426 2020-01-13 rsc }
453 50923426 2020-01-13 rsc
454 50923426 2020-01-13 rsc if(xev->type != KeyPress)
455 50923426 2020-01-13 rsc break;
456 50923426 2020-01-13 rsc if(k == XK_F11){
457 50923426 2020-01-13 rsc w->fullscreen = !w->fullscreen;
458 50923426 2020-01-13 rsc _xmovewindow(w, w->fullscreen ? w->screenrect : w->windowrect);
459 50923426 2020-01-13 rsc return;
460 50923426 2020-01-13 rsc }
461 50923426 2020-01-13 rsc if((c = _xtoplan9kbd(xev)) < 0)
462 50923426 2020-01-13 rsc return;
463 50923426 2020-01-13 rsc gfx_keystroke(w->client, c);
464 50923426 2020-01-13 rsc break;
465 50923426 2020-01-13 rsc
466 50923426 2020-01-13 rsc case FocusOut:
467 50923426 2020-01-13 rsc /*
468 50923426 2020-01-13 rsc * Some key combinations (e.g. Alt-Tab) can cause us
469 50923426 2020-01-13 rsc * to see the key down event without the key up event,
470 50923426 2020-01-13 rsc * so clear out the keyboard state when we lose the focus.
471 50923426 2020-01-13 rsc */
472 50923426 2020-01-13 rsc _x.kstate = 0;
473 50923426 2020-01-13 rsc _x.altdown = 0;
474 50923426 2020-01-13 rsc gfx_abortcompose(w->client);
475 50923426 2020-01-13 rsc break;
476 50923426 2020-01-13 rsc
477 50923426 2020-01-13 rsc case SelectionRequest:
478 50923426 2020-01-13 rsc _xselect(xev);
479 50923426 2020-01-13 rsc break;
480 50923426 2020-01-13 rsc }
481 50923426 2020-01-13 rsc }
482 50923426 2020-01-13 rsc
483 50923426 2020-01-13 rsc
484 50923426 2020-01-13 rsc static Memimage*
485 50923426 2020-01-13 rsc xattach(Client *client, char *label, char *winsize)
486 50923426 2020-01-13 rsc {
487 50923426 2020-01-13 rsc char *argv[2];
488 50923426 2020-01-13 rsc int havemin, height, mask, width, x, y;
489 50923426 2020-01-13 rsc Rectangle r;
490 50923426 2020-01-13 rsc XClassHint classhint;
491 50923426 2020-01-13 rsc XDrawable pmid;
492 50923426 2020-01-13 rsc XScreen *xscreen;
493 50923426 2020-01-13 rsc XSetWindowAttributes attr;
494 50923426 2020-01-13 rsc XSizeHints normalhint;
495 50923426 2020-01-13 rsc XTextProperty name;
496 50923426 2020-01-13 rsc XWindow xrootwin;
497 50923426 2020-01-13 rsc XWindowAttributes wattr;
498 50923426 2020-01-13 rsc XWMHints hint;
499 50923426 2020-01-13 rsc Atom atoms[2];
500 50923426 2020-01-13 rsc Xwin *w;
501 50923426 2020-01-13 rsc
502 50923426 2020-01-13 rsc USED(client);
503 50923426 2020-01-13 rsc xscreen = DefaultScreenOfDisplay(_x.display);
504 50923426 2020-01-13 rsc xrootwin = DefaultRootWindow(_x.display);
505 50923426 2020-01-13 rsc
506 50923426 2020-01-13 rsc /*
507 50923426 2020-01-13 rsc * We get to choose the initial rectangle size.
508 50923426 2020-01-13 rsc * This is arbitrary. In theory we should read the
509 50923426 2020-01-13 rsc * command line and allow the traditional X options.
510 50923426 2020-01-13 rsc */
511 50923426 2020-01-13 rsc mask = 0;
512 50923426 2020-01-13 rsc x = 0;
513 50923426 2020-01-13 rsc y = 0;
514 50923426 2020-01-13 rsc if(winsize && winsize[0]){
515 50923426 2020-01-13 rsc if(parsewinsize(winsize, &r, &havemin) < 0)
516 50923426 2020-01-13 rsc sysfatal("%r");
517 50923426 2020-01-13 rsc }else{
518 50923426 2020-01-13 rsc /*
519 50923426 2020-01-13 rsc * Parse the various X resources. Thanks to Peter Canning.
520 50923426 2020-01-13 rsc */
521 50923426 2020-01-13 rsc char *screen_resources, *display_resources, *geom,
522 50923426 2020-01-13 rsc *geomrestype, *home, *file, *dpitype;
523 50923426 2020-01-13 rsc XrmDatabase database;
524 50923426 2020-01-13 rsc XrmValue geomres, dpires;
525 50923426 2020-01-13 rsc
526 50923426 2020-01-13 rsc database = XrmGetDatabase(_x.display);
527 50923426 2020-01-13 rsc screen_resources = XScreenResourceString(xscreen);
528 50923426 2020-01-13 rsc if(screen_resources != nil){
529 50923426 2020-01-13 rsc XrmCombineDatabase(XrmGetStringDatabase(screen_resources), &database, False);
530 50923426 2020-01-13 rsc XFree(screen_resources);
531 50923426 2020-01-13 rsc }
532 50923426 2020-01-13 rsc
533 50923426 2020-01-13 rsc display_resources = XResourceManagerString(_x.display);
534 50923426 2020-01-13 rsc if(display_resources == nil){
535 50923426 2020-01-13 rsc home = getenv("HOME");
536 50923426 2020-01-13 rsc if(home!=nil && (file=smprint("%s/.Xdefaults", home)) != nil){
537 50923426 2020-01-13 rsc XrmCombineFileDatabase(file, &database, False);
538 50923426 2020-01-13 rsc free(file);
539 50923426 2020-01-13 rsc }
540 50923426 2020-01-13 rsc free(home);
541 50923426 2020-01-13 rsc }else
542 50923426 2020-01-13 rsc XrmCombineDatabase(XrmGetStringDatabase(display_resources), &database, False);
543 50923426 2020-01-13 rsc
544 50923426 2020-01-13 rsc if (XrmGetResource(database, "Xft.dpi", "String", &dpitype, &dpires) == True) {
545 50923426 2020-01-13 rsc if (dpires.addr) {
546 50923426 2020-01-13 rsc client->displaydpi = atoi(dpires.addr);
547 50923426 2020-01-13 rsc }
548 50923426 2020-01-13 rsc }
549 50923426 2020-01-13 rsc geom = smprint("%s.geometry", label);
550 50923426 2020-01-13 rsc if(geom && XrmGetResource(database, geom, nil, &geomrestype, &geomres))
551 50923426 2020-01-13 rsc mask = XParseGeometry(geomres.addr, &x, &y, (uint*)&width, (uint*)&height);
552 50923426 2020-01-13 rsc XrmDestroyDatabase(database);
553 50923426 2020-01-13 rsc free(geom);
554 50923426 2020-01-13 rsc
555 50923426 2020-01-13 rsc if((mask & WidthValue) && (mask & HeightValue)){
556 50923426 2020-01-13 rsc r = Rect(0, 0, width, height);
557 50923426 2020-01-13 rsc }else{
558 50923426 2020-01-13 rsc r = Rect(0, 0, WidthOfScreen(xscreen)*3/4,
559 50923426 2020-01-13 rsc HeightOfScreen(xscreen)*3/4);
560 50923426 2020-01-13 rsc if(Dx(r) > Dy(r)*3/2)
561 50923426 2020-01-13 rsc r.max.x = r.min.x + Dy(r)*3/2;
562 50923426 2020-01-13 rsc if(Dy(r) > Dx(r)*3/2)
563 50923426 2020-01-13 rsc r.max.y = r.min.y + Dx(r)*3/2;
564 50923426 2020-01-13 rsc }
565 50923426 2020-01-13 rsc if(mask & XNegative){
566 50923426 2020-01-13 rsc x += WidthOfScreen(xscreen);
567 50923426 2020-01-13 rsc }
568 50923426 2020-01-13 rsc if(mask & YNegative){
569 50923426 2020-01-13 rsc y += HeightOfScreen(xscreen);
570 50923426 2020-01-13 rsc }
571 50923426 2020-01-13 rsc havemin = 0;
572 50923426 2020-01-13 rsc }
573 50923426 2020-01-13 rsc w = newxwin(client);
574 50923426 2020-01-13 rsc
575 50923426 2020-01-13 rsc memset(&attr, 0, sizeof attr);
576 50923426 2020-01-13 rsc attr.colormap = _x.cmap;
577 50923426 2020-01-13 rsc attr.background_pixel = ~0;
578 50923426 2020-01-13 rsc attr.border_pixel = 0;
579 50923426 2020-01-13 rsc w->drawable = XCreateWindow(
580 50923426 2020-01-13 rsc _x.display, /* display */
581 50923426 2020-01-13 rsc xrootwin, /* parent */
582 50923426 2020-01-13 rsc x, /* x */
583 50923426 2020-01-13 rsc y, /* y */
584 50923426 2020-01-13 rsc Dx(r), /* width */
585 50923426 2020-01-13 rsc Dy(r), /* height */
586 50923426 2020-01-13 rsc 0, /* border width */
587 50923426 2020-01-13 rsc _x.depth, /* depth */
588 50923426 2020-01-13 rsc InputOutput, /* class */
589 50923426 2020-01-13 rsc _x.vis, /* visual */
590 50923426 2020-01-13 rsc /* valuemask */
591 50923426 2020-01-13 rsc CWBackPixel|CWBorderPixel|CWColormap,
592 50923426 2020-01-13 rsc &attr /* attributes (the above aren't?!) */
593 50923426 2020-01-13 rsc );
594 50923426 2020-01-13 rsc
595 50923426 2020-01-13 rsc /*
596 50923426 2020-01-13 rsc * Label and other properties required by ICCCCM.
597 50923426 2020-01-13 rsc */
598 50923426 2020-01-13 rsc memset(&name, 0, sizeof name);
599 50923426 2020-01-13 rsc if(label == nil)
600 50923426 2020-01-13 rsc label = "pjw-face-here";
601 50923426 2020-01-13 rsc name.value = (uchar*)label;
602 50923426 2020-01-13 rsc name.encoding = XA_STRING;
603 50923426 2020-01-13 rsc name.format = 8;
604 50923426 2020-01-13 rsc name.nitems = strlen((char*)name.value);
605 50923426 2020-01-13 rsc
606 50923426 2020-01-13 rsc memset(&normalhint, 0, sizeof normalhint);
607 50923426 2020-01-13 rsc normalhint.flags = PSize|PMaxSize;
608 50923426 2020-01-13 rsc if(winsize && winsize[0]){
609 50923426 2020-01-13 rsc normalhint.flags &= ~PSize;
610 50923426 2020-01-13 rsc normalhint.flags |= USSize;
611 50923426 2020-01-13 rsc normalhint.width = Dx(r);
612 50923426 2020-01-13 rsc normalhint.height = Dy(r);
613 50923426 2020-01-13 rsc }else{
614 50923426 2020-01-13 rsc if((mask & WidthValue) && (mask & HeightValue)){
615 50923426 2020-01-13 rsc normalhint.flags &= ~PSize;
616 50923426 2020-01-13 rsc normalhint.flags |= USSize;
617 50923426 2020-01-13 rsc normalhint.width = width;
618 50923426 2020-01-13 rsc normalhint.height = height;
619 50923426 2020-01-13 rsc }
620 50923426 2020-01-13 rsc if((mask & WidthValue) && (mask & HeightValue)){
621 50923426 2020-01-13 rsc normalhint.flags |= USPosition;
622 50923426 2020-01-13 rsc normalhint.x = x;
623 50923426 2020-01-13 rsc normalhint.y = y;
624 50923426 2020-01-13 rsc }
625 50923426 2020-01-13 rsc }
626 50923426 2020-01-13 rsc
627 50923426 2020-01-13 rsc normalhint.max_width = WidthOfScreen(xscreen);
628 50923426 2020-01-13 rsc normalhint.max_height = HeightOfScreen(xscreen);
629 50923426 2020-01-13 rsc
630 50923426 2020-01-13 rsc memset(&hint, 0, sizeof hint);
631 50923426 2020-01-13 rsc hint.flags = InputHint|StateHint;
632 50923426 2020-01-13 rsc hint.input = 1;
633 50923426 2020-01-13 rsc hint.initial_state = NormalState;
634 50923426 2020-01-13 rsc
635 50923426 2020-01-13 rsc memset(&classhint, 0, sizeof classhint);
636 50923426 2020-01-13 rsc classhint.res_name = label;
637 50923426 2020-01-13 rsc classhint.res_class = label;
638 50923426 2020-01-13 rsc
639 50923426 2020-01-13 rsc argv[0] = label;
640 50923426 2020-01-13 rsc argv[1] = nil;
641 50923426 2020-01-13 rsc
642 50923426 2020-01-13 rsc XSetWMProperties(
643 50923426 2020-01-13 rsc _x.display, /* display */
644 50923426 2020-01-13 rsc w->drawable, /* window */
645 50923426 2020-01-13 rsc &name, /* XA_WM_NAME property */
646 50923426 2020-01-13 rsc &name, /* XA_WM_ICON_NAME property */
647 50923426 2020-01-13 rsc argv, /* XA_WM_COMMAND */
648 50923426 2020-01-13 rsc 1, /* argc */
649 50923426 2020-01-13 rsc &normalhint, /* XA_WM_NORMAL_HINTS */
650 50923426 2020-01-13 rsc &hint, /* XA_WM_HINTS */
651 50923426 2020-01-13 rsc &classhint /* XA_WM_CLASSHINTS */
652 50923426 2020-01-13 rsc );
653 50923426 2020-01-13 rsc XFlush(_x.display);
654 50923426 2020-01-13 rsc
655 50923426 2020-01-13 rsc if(havemin){
656 50923426 2020-01-13 rsc XWindowChanges ch;
657 50923426 2020-01-13 rsc
658 50923426 2020-01-13 rsc memset(&ch, 0, sizeof ch);
659 50923426 2020-01-13 rsc ch.x = r.min.x;
660 50923426 2020-01-13 rsc ch.y = r.min.y;
661 50923426 2020-01-13 rsc XConfigureWindow(_x.display, w->drawable, CWX|CWY, &ch);
662 50923426 2020-01-13 rsc /*
663 50923426 2020-01-13 rsc * Must pretend origin is 0,0 for X.
664 50923426 2020-01-13 rsc */
665 50923426 2020-01-13 rsc r = Rect(0,0,Dx(r),Dy(r));
666 50923426 2020-01-13 rsc }
667 50923426 2020-01-13 rsc /*
668 50923426 2020-01-13 rsc * Look up clipboard atom.
669 50923426 2020-01-13 rsc */
670 50923426 2020-01-13 rsc if(_x.clipboard == 0) {
671 50923426 2020-01-13 rsc _x.clipboard = XInternAtom(_x.display, "CLIPBOARD", False);
672 50923426 2020-01-13 rsc _x.utf8string = XInternAtom(_x.display, "UTF8_STRING", False);
673 50923426 2020-01-13 rsc _x.targets = XInternAtom(_x.display, "TARGETS", False);
674 50923426 2020-01-13 rsc _x.text = XInternAtom(_x.display, "TEXT", False);
675 50923426 2020-01-13 rsc _x.compoundtext = XInternAtom(_x.display, "COMPOUND_TEXT", False);
676 50923426 2020-01-13 rsc _x.takefocus = XInternAtom(_x.display, "WM_TAKE_FOCUS", False);
677 50923426 2020-01-13 rsc _x.losefocus = XInternAtom(_x.display, "_9WM_LOSE_FOCUS", False);
678 50923426 2020-01-13 rsc _x.wmprotos = XInternAtom(_x.display, "WM_PROTOCOLS", False);
679 50923426 2020-01-13 rsc }
680 1f799495 2020-01-15 rsc
681 50923426 2020-01-13 rsc atoms[0] = _x.takefocus;
682 50923426 2020-01-13 rsc atoms[1] = _x.losefocus;
683 50923426 2020-01-13 rsc XChangeProperty(_x.display, w->drawable, _x.wmprotos, XA_ATOM, 32,
684 50923426 2020-01-13 rsc PropModeReplace, (uchar*)atoms, 2);
685 50923426 2020-01-13 rsc
686 50923426 2020-01-13 rsc /*
687 50923426 2020-01-13 rsc * Put the window on the screen, check to see what size we actually got.
688 50923426 2020-01-13 rsc */
689 50923426 2020-01-13 rsc XMapWindow(_x.display, w->drawable);
690 50923426 2020-01-13 rsc XSync(_x.display, False);
691 50923426 2020-01-13 rsc
692 50923426 2020-01-13 rsc if(!XGetWindowAttributes(_x.display, w->drawable, &wattr))
693 50923426 2020-01-13 rsc fprint(2, "XGetWindowAttributes failed\n");
694 50923426 2020-01-13 rsc else if(wattr.width && wattr.height){
695 50923426 2020-01-13 rsc if(wattr.width != Dx(r) || wattr.height != Dy(r)){
696 50923426 2020-01-13 rsc r.max.x = wattr.width;
697 50923426 2020-01-13 rsc r.max.y = wattr.height;
698 50923426 2020-01-13 rsc }
699 50923426 2020-01-13 rsc }else
700 50923426 2020-01-13 rsc fprint(2, "XGetWindowAttributes: bad attrs\n");
701 fe2b2de9 2020-01-15 rsc w->screenrect = Rect(0, 0, WidthOfScreen(xscreen), HeightOfScreen(xscreen));
702 fe2b2de9 2020-01-15 rsc w->windowrect = r;
703 50923426 2020-01-13 rsc
704 50923426 2020-01-13 rsc /*
705 50923426 2020-01-13 rsc * Allocate our local backing store.
706 50923426 2020-01-13 rsc */
707 50923426 2020-01-13 rsc w->screenr = r;
708 50923426 2020-01-13 rsc w->screenpm = XCreatePixmap(_x.display, w->drawable, Dx(r), Dy(r), _x.depth);
709 50923426 2020-01-13 rsc w->nextscreenpm = w->screenpm;
710 50923426 2020-01-13 rsc w->screenimage = _xallocmemimage(r, _x.chan, w->screenpm);
711 50923426 2020-01-13 rsc client->mouserect = r;
712 50923426 2020-01-13 rsc
713 50923426 2020-01-13 rsc /*
714 50923426 2020-01-13 rsc * Allocate some useful graphics contexts for the future.
715 50923426 2020-01-13 rsc * These can be used with any drawable matching w->drawable's
716 50923426 2020-01-13 rsc * pixel format (which is all the drawables we create).
717 50923426 2020-01-13 rsc */
718 50923426 2020-01-13 rsc if(_x.gcfill == 0) {
719 50923426 2020-01-13 rsc _x.gcfill = xgc(w->screenpm, FillSolid, -1);
720 50923426 2020-01-13 rsc _x.gccopy = xgc(w->screenpm, -1, -1);
721 50923426 2020-01-13 rsc _x.gcsimplesrc = xgc(w->screenpm, FillStippled, -1);
722 50923426 2020-01-13 rsc _x.gczero = xgc(w->screenpm, -1, -1);
723 50923426 2020-01-13 rsc _x.gcreplsrc = xgc(w->screenpm, FillTiled, -1);
724 1f799495 2020-01-15 rsc
725 50923426 2020-01-13 rsc pmid = XCreatePixmap(_x.display, w->drawable, 1, 1, 1);
726 50923426 2020-01-13 rsc _x.gcfill0 = xgc(pmid, FillSolid, 0);
727 50923426 2020-01-13 rsc _x.gccopy0 = xgc(pmid, -1, -1);
728 50923426 2020-01-13 rsc _x.gcsimplesrc0 = xgc(pmid, FillStippled, -1);
729 50923426 2020-01-13 rsc _x.gczero0 = xgc(pmid, -1, -1);
730 50923426 2020-01-13 rsc _x.gcreplsrc0 = xgc(pmid, FillTiled, -1);
731 50923426 2020-01-13 rsc XFreePixmap(_x.display, pmid);
732 50923426 2020-01-13 rsc }
733 50923426 2020-01-13 rsc
734 50923426 2020-01-13 rsc return w->screenimage;
735 50923426 2020-01-13 rsc }
736 50923426 2020-01-13 rsc
737 50923426 2020-01-13 rsc Memimage*
738 50923426 2020-01-13 rsc rpc_attach(Client *client, char *label, char *winsize)
739 50923426 2020-01-13 rsc {
740 50923426 2020-01-13 rsc Memimage *m;
741 50923426 2020-01-13 rsc
742 50923426 2020-01-13 rsc xlock();
743 50923426 2020-01-13 rsc m = xattach(client, label, winsize);
744 50923426 2020-01-13 rsc xunlock();
745 50923426 2020-01-13 rsc return m;
746 50923426 2020-01-13 rsc }
747 50923426 2020-01-13 rsc
748 50923426 2020-01-13 rsc void
749 50923426 2020-01-13 rsc rpc_setlabel(Client *client, char *label)
750 50923426 2020-01-13 rsc {
751 50923426 2020-01-13 rsc Xwin *w = (Xwin*)client->view;
752 50923426 2020-01-13 rsc XTextProperty name;
753 1f799495 2020-01-15 rsc
754 50923426 2020-01-13 rsc /*
755 50923426 2020-01-13 rsc * Label and other properties required by ICCCCM.
756 50923426 2020-01-13 rsc */
757 50923426 2020-01-13 rsc xlock();
758 50923426 2020-01-13 rsc memset(&name, 0, sizeof name);
759 50923426 2020-01-13 rsc if(label == nil)
760 50923426 2020-01-13 rsc label = "pjw-face-here";
761 50923426 2020-01-13 rsc name.value = (uchar*)label;
762 50923426 2020-01-13 rsc name.encoding = XA_STRING;
763 50923426 2020-01-13 rsc name.format = 8;
764 50923426 2020-01-13 rsc name.nitems = strlen((char*)name.value);
765 50923426 2020-01-13 rsc
766 50923426 2020-01-13 rsc XSetWMProperties(
767 50923426 2020-01-13 rsc _x.display, /* display */
768 50923426 2020-01-13 rsc w->drawable, /* window */
769 50923426 2020-01-13 rsc &name, /* XA_WM_NAME property */
770 50923426 2020-01-13 rsc &name, /* XA_WM_ICON_NAME property */
771 50923426 2020-01-13 rsc nil, /* XA_WM_COMMAND */
772 50923426 2020-01-13 rsc 0, /* argc */
773 50923426 2020-01-13 rsc nil, /* XA_WM_NORMAL_HINTS */
774 50923426 2020-01-13 rsc nil, /* XA_WM_HINTS */
775 50923426 2020-01-13 rsc nil /* XA_WM_CLASSHINTS */
776 50923426 2020-01-13 rsc );
777 50923426 2020-01-13 rsc XFlush(_x.display);
778 50923426 2020-01-13 rsc xunlock();
779 50923426 2020-01-13 rsc }
780 50923426 2020-01-13 rsc
781 50923426 2020-01-13 rsc /*
782 50923426 2020-01-13 rsc * Create a GC with a particular fill style and XXX.
783 50923426 2020-01-13 rsc * Disable generation of GraphicsExpose/NoExpose events in the GC.
784 50923426 2020-01-13 rsc */
785 50923426 2020-01-13 rsc static XGC
786 50923426 2020-01-13 rsc xgc(XDrawable d, int fillstyle, int foreground)
787 50923426 2020-01-13 rsc {
788 50923426 2020-01-13 rsc XGC gc;
789 50923426 2020-01-13 rsc XGCValues v;
790 50923426 2020-01-13 rsc
791 50923426 2020-01-13 rsc memset(&v, 0, sizeof v);
792 50923426 2020-01-13 rsc v.function = GXcopy;
793 50923426 2020-01-13 rsc v.graphics_exposures = False;
794 50923426 2020-01-13 rsc gc = XCreateGC(_x.display, d, GCFunction|GCGraphicsExposures, &v);
795 50923426 2020-01-13 rsc if(fillstyle != -1)
796 50923426 2020-01-13 rsc XSetFillStyle(_x.display, gc, fillstyle);
797 50923426 2020-01-13 rsc if(foreground != -1)
798 50923426 2020-01-13 rsc XSetForeground(_x.display, gc, 0);
799 50923426 2020-01-13 rsc return gc;
800 50923426 2020-01-13 rsc }
801 50923426 2020-01-13 rsc
802 50923426 2020-01-13 rsc
803 50923426 2020-01-13 rsc /*
804 50923426 2020-01-13 rsc * Initialize map with the Plan 9 rgbv color map.
805 50923426 2020-01-13 rsc */
806 50923426 2020-01-13 rsc static void
807 50923426 2020-01-13 rsc plan9cmap(void)
808 50923426 2020-01-13 rsc {
809 50923426 2020-01-13 rsc int r, g, b, cr, cg, cb, v, num, den, idx, v7, idx7;
810 50923426 2020-01-13 rsc static int once;
811 50923426 2020-01-13 rsc
812 50923426 2020-01-13 rsc if(once)
813 50923426 2020-01-13 rsc return;
814 50923426 2020-01-13 rsc once = 1;
815 50923426 2020-01-13 rsc
816 50923426 2020-01-13 rsc for(r=0; r!=4; r++)
817 50923426 2020-01-13 rsc for(g = 0; g != 4; g++)
818 50923426 2020-01-13 rsc for(b = 0; b!=4; b++)
819 50923426 2020-01-13 rsc for(v = 0; v!=4; v++){
820 50923426 2020-01-13 rsc den=r;
821 50923426 2020-01-13 rsc if(g > den)
822 50923426 2020-01-13 rsc den=g;
823 50923426 2020-01-13 rsc if(b > den)
824 50923426 2020-01-13 rsc den=b;
825 50923426 2020-01-13 rsc /* divide check -- pick grey shades */
826 50923426 2020-01-13 rsc if(den==0)
827 50923426 2020-01-13 rsc cr=cg=cb=v*17;
828 50923426 2020-01-13 rsc else {
829 50923426 2020-01-13 rsc num=17*(4*den+v);
830 50923426 2020-01-13 rsc cr=r*num/den;
831 50923426 2020-01-13 rsc cg=g*num/den;
832 50923426 2020-01-13 rsc cb=b*num/den;
833 50923426 2020-01-13 rsc }
834 50923426 2020-01-13 rsc idx = r*64 + v*16 + ((g*4 + b + v - r) & 15);
835 50923426 2020-01-13 rsc _x.map[idx].red = cr*0x0101;
836 50923426 2020-01-13 rsc _x.map[idx].green = cg*0x0101;
837 50923426 2020-01-13 rsc _x.map[idx].blue = cb*0x0101;
838 50923426 2020-01-13 rsc _x.map[idx].pixel = idx;
839 50923426 2020-01-13 rsc _x.map[idx].flags = DoRed|DoGreen|DoBlue;
840 50923426 2020-01-13 rsc
841 50923426 2020-01-13 rsc v7 = v >> 1;
842 50923426 2020-01-13 rsc idx7 = r*32 + v7*16 + g*4 + b;
843 50923426 2020-01-13 rsc if((v & 1) == v7){
844 50923426 2020-01-13 rsc _x.map7to8[idx7][0] = idx;
845 50923426 2020-01-13 rsc if(den == 0) { /* divide check -- pick grey shades */
846 50923426 2020-01-13 rsc cr = ((255.0/7.0)*v7)+0.5;
847 50923426 2020-01-13 rsc cg = cr;
848 50923426 2020-01-13 rsc cb = cr;
849 50923426 2020-01-13 rsc }
850 50923426 2020-01-13 rsc else {
851 50923426 2020-01-13 rsc num=17*15*(4*den+v7*2)/14;
852 50923426 2020-01-13 rsc cr=r*num/den;
853 50923426 2020-01-13 rsc cg=g*num/den;
854 50923426 2020-01-13 rsc cb=b*num/den;
855 50923426 2020-01-13 rsc }
856 50923426 2020-01-13 rsc _x.map7[idx7].red = cr*0x0101;
857 50923426 2020-01-13 rsc _x.map7[idx7].green = cg*0x0101;
858 50923426 2020-01-13 rsc _x.map7[idx7].blue = cb*0x0101;
859 50923426 2020-01-13 rsc _x.map7[idx7].pixel = idx7;
860 50923426 2020-01-13 rsc _x.map7[idx7].flags = DoRed|DoGreen|DoBlue;
861 50923426 2020-01-13 rsc }
862 50923426 2020-01-13 rsc else
863 50923426 2020-01-13 rsc _x.map7to8[idx7][1] = idx;
864 50923426 2020-01-13 rsc }
865 50923426 2020-01-13 rsc }
866 50923426 2020-01-13 rsc
867 50923426 2020-01-13 rsc /*
868 50923426 2020-01-13 rsc * Initialize and install the rgbv color map as a private color map
869 50923426 2020-01-13 rsc * for this application. It gets the best colors when it has the
870 50923426 2020-01-13 rsc * cursor focus.
871 50923426 2020-01-13 rsc *
872 50923426 2020-01-13 rsc * We always choose the best depth possible, but that might not
873 50923426 2020-01-13 rsc * be the default depth. On such "suboptimal" systems, we have to allocate an
874 50923426 2020-01-13 rsc * empty color map anyway, according to Axel Belinfante.
875 50923426 2020-01-13 rsc */
876 50923426 2020-01-13 rsc static int
877 50923426 2020-01-13 rsc setupcmap(XWindow w)
878 50923426 2020-01-13 rsc {
879 50923426 2020-01-13 rsc char buf[30];
880 50923426 2020-01-13 rsc int i;
881 50923426 2020-01-13 rsc u32int p, pp;
882 50923426 2020-01-13 rsc XColor c;
883 50923426 2020-01-13 rsc
884 50923426 2020-01-13 rsc if(_x.depth <= 1)
885 50923426 2020-01-13 rsc return 0;
886 50923426 2020-01-13 rsc
887 50923426 2020-01-13 rsc if(_x.depth >= 24) {
888 50923426 2020-01-13 rsc if(_x.usetable == 0)
889 50923426 2020-01-13 rsc _x.cmap = XCreateColormap(_x.display, w, _x.vis, AllocNone);
890 50923426 2020-01-13 rsc
891 50923426 2020-01-13 rsc /*
892 50923426 2020-01-13 rsc * The pixel value returned from XGetPixel needs to
893 50923426 2020-01-13 rsc * be converted to RGB so we can call rgb2cmap()
894 50923426 2020-01-13 rsc * to translate between 24 bit X and our color. Unfortunately,
895 50923426 2020-01-13 rsc * the return value appears to be display server endian
896 50923426 2020-01-13 rsc * dependant. Therefore, we run some heuristics to later
897 50923426 2020-01-13 rsc * determine how to mask the int value correctly.
898 50923426 2020-01-13 rsc * Yeah, I know we can look at _x.vis->byte_order but
899 50923426 2020-01-13 rsc * some displays say MSB even though they run on LSB.
900 50923426 2020-01-13 rsc * Besides, this is more anal.
901 50923426 2020-01-13 rsc */
902 50923426 2020-01-13 rsc c = _x.map[19]; /* known to have different R, G, B values */
903 50923426 2020-01-13 rsc if(!XAllocColor(_x.display, _x.cmap, &c)){
904 50923426 2020-01-13 rsc werrstr("XAllocColor: %r");
905 50923426 2020-01-13 rsc return -1;
906 50923426 2020-01-13 rsc }
907 50923426 2020-01-13 rsc p = c.pixel;
908 50923426 2020-01-13 rsc pp = rgb2cmap((p>>16)&0xff,(p>>8)&0xff,p&0xff);
909 50923426 2020-01-13 rsc if(pp != _x.map[19].pixel) {
910 50923426 2020-01-13 rsc /* check if endian is other way */
911 50923426 2020-01-13 rsc pp = rgb2cmap(p&0xff,(p>>8)&0xff,(p>>16)&0xff);
912 50923426 2020-01-13 rsc if(pp != _x.map[19].pixel){
913 50923426 2020-01-13 rsc werrstr("cannot detect X server byte order");
914 50923426 2020-01-13 rsc return -1;
915 50923426 2020-01-13 rsc }
916 50923426 2020-01-13 rsc
917 50923426 2020-01-13 rsc switch(_x.chan){
918 50923426 2020-01-13 rsc case RGB24:
919 50923426 2020-01-13 rsc _x.chan = BGR24;
920 50923426 2020-01-13 rsc break;
921 50923426 2020-01-13 rsc case XRGB32:
922 50923426 2020-01-13 rsc _x.chan = XBGR32;
923 50923426 2020-01-13 rsc break;
924 50923426 2020-01-13 rsc default:
925 50923426 2020-01-13 rsc werrstr("cannot byteswap channel %s",
926 50923426 2020-01-13 rsc chantostr(buf, _x.chan));
927 50923426 2020-01-13 rsc break;
928 50923426 2020-01-13 rsc }
929 50923426 2020-01-13 rsc }
930 50923426 2020-01-13 rsc }else if(_x.vis->class == TrueColor || _x.vis->class == DirectColor){
931 50923426 2020-01-13 rsc /*
932 50923426 2020-01-13 rsc * Do nothing. We have no way to express a
933 50923426 2020-01-13 rsc * mixed-endian 16-bit screen, so pretend they don't exist.
934 50923426 2020-01-13 rsc */
935 50923426 2020-01-13 rsc if(_x.usetable == 0)
936 50923426 2020-01-13 rsc _x.cmap = XCreateColormap(_x.display, w, _x.vis, AllocNone);
937 50923426 2020-01-13 rsc }else if(_x.vis->class == PseudoColor){
938 50923426 2020-01-13 rsc if(_x.usetable == 0){
939 50923426 2020-01-13 rsc _x.cmap = XCreateColormap(_x.display, w, _x.vis, AllocAll);
940 50923426 2020-01-13 rsc XStoreColors(_x.display, _x.cmap, _x.map, 256);
941 50923426 2020-01-13 rsc for(i = 0; i < 256; i++){
942 50923426 2020-01-13 rsc _x.tox11[i] = i;
943 50923426 2020-01-13 rsc _x.toplan9[i] = i;
944 50923426 2020-01-13 rsc }
945 50923426 2020-01-13 rsc }else{
946 50923426 2020-01-13 rsc for(i = 0; i < 128; i++){
947 50923426 2020-01-13 rsc c = _x.map7[i];
948 50923426 2020-01-13 rsc if(!XAllocColor(_x.display, _x.cmap, &c)){
949 50923426 2020-01-13 rsc werrstr("can't allocate colors in 7-bit map");
950 50923426 2020-01-13 rsc return -1;
951 50923426 2020-01-13 rsc }
952 50923426 2020-01-13 rsc _x.tox11[_x.map7to8[i][0]] = c.pixel;
953 50923426 2020-01-13 rsc _x.tox11[_x.map7to8[i][1]] = c.pixel;
954 50923426 2020-01-13 rsc _x.toplan9[c.pixel] = _x.map7to8[i][0];
955 50923426 2020-01-13 rsc }
956 50923426 2020-01-13 rsc }
957 50923426 2020-01-13 rsc }else{
958 50923426 2020-01-13 rsc werrstr("unsupported visual class %d", _x.vis->class);
959 50923426 2020-01-13 rsc return -1;
960 50923426 2020-01-13 rsc }
961 50923426 2020-01-13 rsc return 0;
962 50923426 2020-01-13 rsc }
963 50923426 2020-01-13 rsc
964 50923426 2020-01-13 rsc void
965 50923426 2020-01-13 rsc rpc_shutdown(void)
966 50923426 2020-01-13 rsc {
967 50923426 2020-01-13 rsc }
968 50923426 2020-01-13 rsc
969 50923426 2020-01-13 rsc void
970 50923426 2020-01-13 rsc rpc_flush(Client *client, Rectangle r)
971 50923426 2020-01-13 rsc {
972 50923426 2020-01-13 rsc Xwin *w = (Xwin*)client->view;
973 50923426 2020-01-13 rsc
974 50923426 2020-01-13 rsc xlock();
975 50923426 2020-01-13 rsc if(w->nextscreenpm != w->screenpm){
976 50923426 2020-01-13 rsc XSync(_x.display, False);
977 50923426 2020-01-13 rsc XFreePixmap(_x.display, w->screenpm);
978 50923426 2020-01-13 rsc w->screenpm = w->nextscreenpm;
979 50923426 2020-01-13 rsc }
980 50923426 2020-01-13 rsc
981 50923426 2020-01-13 rsc if(r.min.x >= r.max.x || r.min.y >= r.max.y) {
982 50923426 2020-01-13 rsc xunlock();
983 50923426 2020-01-13 rsc return;
984 50923426 2020-01-13 rsc }
985 50923426 2020-01-13 rsc
986 50923426 2020-01-13 rsc XCopyArea(_x.display, w->screenpm, w->drawable, _x.gccopy, r.min.x, r.min.y,
987 50923426 2020-01-13 rsc Dx(r), Dy(r), r.min.x, r.min.y);
988 50923426 2020-01-13 rsc XFlush(_x.display);
989 50923426 2020-01-13 rsc xunlock();
990 50923426 2020-01-13 rsc }
991 50923426 2020-01-13 rsc
992 50923426 2020-01-13 rsc static void
993 50923426 2020-01-13 rsc _xexpose(Xwin *w, XEvent *e)
994 50923426 2020-01-13 rsc {
995 50923426 2020-01-13 rsc XExposeEvent *xe;
996 50923426 2020-01-13 rsc Rectangle r;
997 50923426 2020-01-13 rsc
998 50923426 2020-01-13 rsc if(w->screenpm != w->nextscreenpm)
999 50923426 2020-01-13 rsc return;
1000 50923426 2020-01-13 rsc xe = (XExposeEvent*)e;
1001 50923426 2020-01-13 rsc r.min.x = xe->x;
1002 50923426 2020-01-13 rsc r.min.y = xe->y;
1003 50923426 2020-01-13 rsc r.max.x = xe->x+xe->width;
1004 50923426 2020-01-13 rsc r.max.y = xe->y+xe->height;
1005 50923426 2020-01-13 rsc XCopyArea(_x.display, w->screenpm, w->drawable, _x.gccopy, r.min.x, r.min.y,
1006 50923426 2020-01-13 rsc Dx(r), Dy(r), r.min.x, r.min.y);
1007 50923426 2020-01-13 rsc XSync(_x.display, False);
1008 50923426 2020-01-13 rsc }
1009 50923426 2020-01-13 rsc
1010 50923426 2020-01-13 rsc static int
1011 50923426 2020-01-13 rsc _xdestroy(Xwin *w, XEvent *e)
1012 50923426 2020-01-13 rsc {
1013 50923426 2020-01-13 rsc XDestroyWindowEvent *xe;
1014 50923426 2020-01-13 rsc
1015 50923426 2020-01-13 rsc xe = (XDestroyWindowEvent*)e;
1016 50923426 2020-01-13 rsc if(xe->window == w->drawable){
1017 50923426 2020-01-13 rsc w->destroyed = 1;
1018 50923426 2020-01-13 rsc return 1;
1019 50923426 2020-01-13 rsc }
1020 50923426 2020-01-13 rsc return 0;
1021 50923426 2020-01-13 rsc }
1022 50923426 2020-01-13 rsc
1023 50923426 2020-01-13 rsc static int
1024 50923426 2020-01-13 rsc _xconfigure(Xwin *w, XEvent *e)
1025 50923426 2020-01-13 rsc {
1026 50923426 2020-01-13 rsc Rectangle r;
1027 50923426 2020-01-13 rsc XConfigureEvent *xe = (XConfigureEvent*)e;
1028 50923426 2020-01-13 rsc
1029 50923426 2020-01-13 rsc if(!w->fullscreen){
1030 50923426 2020-01-13 rsc int rx, ry;
1031 50923426 2020-01-13 rsc XWindow xw;
1032 50923426 2020-01-13 rsc if(XTranslateCoordinates(_x.display, w->drawable, DefaultRootWindow(_x.display), 0, 0, &rx, &ry, &xw))
1033 50923426 2020-01-13 rsc w->windowrect = Rect(rx, ry, rx+xe->width, ry+xe->height);
1034 50923426 2020-01-13 rsc }
1035 50923426 2020-01-13 rsc
1036 50923426 2020-01-13 rsc if(xe->width == Dx(w->screenr) && xe->height == Dy(w->screenr))
1037 50923426 2020-01-13 rsc return 0;
1038 50923426 2020-01-13 rsc r = Rect(0, 0, xe->width, xe->height);
1039 50923426 2020-01-13 rsc
1040 50923426 2020-01-13 rsc if(w->screenpm != w->nextscreenpm){
1041 50923426 2020-01-13 rsc XCopyArea(_x.display, w->screenpm, w->drawable, _x.gccopy, r.min.x, r.min.y,
1042 50923426 2020-01-13 rsc Dx(r), Dy(r), r.min.x, r.min.y);
1043 50923426 2020-01-13 rsc XSync(_x.display, False);
1044 50923426 2020-01-13 rsc }
1045 50923426 2020-01-13 rsc w->newscreenr = r;
1046 50923426 2020-01-13 rsc return 1;
1047 50923426 2020-01-13 rsc }
1048 50923426 2020-01-13 rsc
1049 50923426 2020-01-13 rsc static int
1050 50923426 2020-01-13 rsc _xreplacescreenimage(Client *client)
1051 50923426 2020-01-13 rsc {
1052 50923426 2020-01-13 rsc Memimage *m;
1053 50923426 2020-01-13 rsc XDrawable pixmap;
1054 50923426 2020-01-13 rsc Rectangle r;
1055 50923426 2020-01-13 rsc Xwin *w;
1056 1f799495 2020-01-15 rsc
1057 50923426 2020-01-13 rsc w = (Xwin*)client->view;
1058 50923426 2020-01-13 rsc r = w->newscreenr;
1059 50923426 2020-01-13 rsc pixmap = XCreatePixmap(_x.display, w->drawable, Dx(r), Dy(r), _x.depth);
1060 50923426 2020-01-13 rsc m = _xallocmemimage(r, _x.chan, pixmap);
1061 50923426 2020-01-13 rsc if(w->nextscreenpm != w->screenpm)
1062 50923426 2020-01-13 rsc XFreePixmap(_x.display, w->nextscreenpm);
1063 50923426 2020-01-13 rsc w->nextscreenpm = pixmap;
1064 50923426 2020-01-13 rsc w->screenr = r;
1065 50923426 2020-01-13 rsc client->mouserect = r;
1066 0be57355 2020-01-15 rsc xunlock();
1067 50923426 2020-01-13 rsc gfx_replacescreenimage(client, m);
1068 0be57355 2020-01-15 rsc xlock();
1069 50923426 2020-01-13 rsc return 1;
1070 50923426 2020-01-13 rsc }
1071 50923426 2020-01-13 rsc
1072 50923426 2020-01-13 rsc void
1073 50923426 2020-01-13 rsc rpc_resizeimg(Client *client)
1074 50923426 2020-01-13 rsc {
1075 50923426 2020-01-13 rsc xlock();
1076 50923426 2020-01-13 rsc _xreplacescreenimage(client);
1077 50923426 2020-01-13 rsc xunlock();
1078 50923426 2020-01-13 rsc }
1079 50923426 2020-01-13 rsc
1080 50923426 2020-01-13 rsc void
1081 50923426 2020-01-13 rsc rpc_gfxdrawlock(void)
1082 50923426 2020-01-13 rsc {
1083 50923426 2020-01-13 rsc xlock();
1084 50923426 2020-01-13 rsc }
1085 50923426 2020-01-13 rsc
1086 50923426 2020-01-13 rsc void
1087 50923426 2020-01-13 rsc rpc_gfxdrawunlock(void)
1088 50923426 2020-01-13 rsc {
1089 50923426 2020-01-13 rsc xunlock();
1090 50923426 2020-01-13 rsc }
1091 50923426 2020-01-13 rsc void
1092 50923426 2020-01-13 rsc rpc_topwin(Client *client)
1093 50923426 2020-01-13 rsc {
1094 50923426 2020-01-13 rsc Xwin *w = (Xwin*)client->view;
1095 50923426 2020-01-13 rsc
1096 50923426 2020-01-13 rsc xlock();
1097 50923426 2020-01-13 rsc XMapRaised(_x.display, w->drawable);
1098 50923426 2020-01-13 rsc XSetInputFocus(_x.display, w->drawable, RevertToPointerRoot,
1099 50923426 2020-01-13 rsc CurrentTime);
1100 50923426 2020-01-13 rsc XFlush(_x.display);
1101 50923426 2020-01-13 rsc xunlock();
1102 50923426 2020-01-13 rsc }
1103 50923426 2020-01-13 rsc
1104 50923426 2020-01-13 rsc void
1105 50923426 2020-01-13 rsc rpc_resizewindow(Client *client, Rectangle r)
1106 50923426 2020-01-13 rsc {
1107 50923426 2020-01-13 rsc Xwin *w = (Xwin*)client->view;
1108 50923426 2020-01-13 rsc XWindowChanges e;
1109 50923426 2020-01-13 rsc int value_mask;
1110 50923426 2020-01-13 rsc
1111 50923426 2020-01-13 rsc xlock();
1112 50923426 2020-01-13 rsc memset(&e, 0, sizeof e);
1113 50923426 2020-01-13 rsc value_mask = CWX|CWY|CWWidth|CWHeight;
1114 50923426 2020-01-13 rsc e.width = Dx(r);
1115 50923426 2020-01-13 rsc e.height = Dy(r);
1116 50923426 2020-01-13 rsc XConfigureWindow(_x.display, w->drawable, value_mask, &e);
1117 50923426 2020-01-13 rsc XFlush(_x.display);
1118 50923426 2020-01-13 rsc xunlock();
1119 50923426 2020-01-13 rsc }
1120 50923426 2020-01-13 rsc
1121 50923426 2020-01-13 rsc static void
1122 50923426 2020-01-13 rsc _xmovewindow(Xwin *w, Rectangle r)
1123 50923426 2020-01-13 rsc {
1124 50923426 2020-01-13 rsc XWindowChanges e;
1125 50923426 2020-01-13 rsc int value_mask;
1126 50923426 2020-01-13 rsc
1127 50923426 2020-01-13 rsc memset(&e, 0, sizeof e);
1128 50923426 2020-01-13 rsc value_mask = CWX|CWY|CWWidth|CWHeight;
1129 50923426 2020-01-13 rsc e.x = r.min.x;
1130 50923426 2020-01-13 rsc e.y = r.min.y;
1131 50923426 2020-01-13 rsc e.width = Dx(r);
1132 50923426 2020-01-13 rsc e.height = Dy(r);
1133 50923426 2020-01-13 rsc XConfigureWindow(_x.display, w->drawable, value_mask, &e);
1134 50923426 2020-01-13 rsc XFlush(_x.display);
1135 50923426 2020-01-13 rsc }
1136 50923426 2020-01-13 rsc
1137 50923426 2020-01-13 rsc static int
1138 50923426 2020-01-13 rsc _xtoplan9kbd(XEvent *e)
1139 50923426 2020-01-13 rsc {
1140 50923426 2020-01-13 rsc KeySym k;
1141 50923426 2020-01-13 rsc
1142 50923426 2020-01-13 rsc if(e->xany.type != KeyPress)
1143 50923426 2020-01-13 rsc return -1;
1144 50923426 2020-01-13 rsc needstack(64*1024); /* X has some *huge* buffers in openobject */
1145 50923426 2020-01-13 rsc /* and they're even bigger on SuSE */
1146 50923426 2020-01-13 rsc XLookupString((XKeyEvent*)e,NULL,0,&k,NULL);
1147 50923426 2020-01-13 rsc if(k == NoSymbol)
1148 50923426 2020-01-13 rsc return -1;
1149 50923426 2020-01-13 rsc
1150 50923426 2020-01-13 rsc if(k&0xFF00){
1151 50923426 2020-01-13 rsc switch(k){
1152 50923426 2020-01-13 rsc case XK_BackSpace:
1153 50923426 2020-01-13 rsc case XK_Tab:
1154 50923426 2020-01-13 rsc case XK_Escape:
1155 50923426 2020-01-13 rsc case XK_Delete:
1156 50923426 2020-01-13 rsc case XK_KP_0:
1157 50923426 2020-01-13 rsc case XK_KP_1:
1158 50923426 2020-01-13 rsc case XK_KP_2:
1159 50923426 2020-01-13 rsc case XK_KP_3:
1160 50923426 2020-01-13 rsc case XK_KP_4:
1161 50923426 2020-01-13 rsc case XK_KP_5:
1162 50923426 2020-01-13 rsc case XK_KP_6:
1163 50923426 2020-01-13 rsc case XK_KP_7:
1164 50923426 2020-01-13 rsc case XK_KP_8:
1165 50923426 2020-01-13 rsc case XK_KP_9:
1166 50923426 2020-01-13 rsc case XK_KP_Divide:
1167 50923426 2020-01-13 rsc case XK_KP_Multiply:
1168 50923426 2020-01-13 rsc case XK_KP_Subtract:
1169 50923426 2020-01-13 rsc case XK_KP_Add:
1170 50923426 2020-01-13 rsc case XK_KP_Decimal:
1171 50923426 2020-01-13 rsc k &= 0x7F;
1172 50923426 2020-01-13 rsc break;
1173 50923426 2020-01-13 rsc case XK_Linefeed:
1174 50923426 2020-01-13 rsc k = '\r';
1175 50923426 2020-01-13 rsc break;
1176 50923426 2020-01-13 rsc case XK_KP_Space:
1177 50923426 2020-01-13 rsc k = ' ';
1178 50923426 2020-01-13 rsc break;
1179 50923426 2020-01-13 rsc case XK_Home:
1180 50923426 2020-01-13 rsc case XK_KP_Home:
1181 50923426 2020-01-13 rsc k = Khome;
1182 50923426 2020-01-13 rsc break;
1183 50923426 2020-01-13 rsc case XK_Left:
1184 50923426 2020-01-13 rsc case XK_KP_Left:
1185 50923426 2020-01-13 rsc k = Kleft;
1186 50923426 2020-01-13 rsc break;
1187 50923426 2020-01-13 rsc case XK_Up:
1188 50923426 2020-01-13 rsc case XK_KP_Up:
1189 50923426 2020-01-13 rsc k = Kup;
1190 50923426 2020-01-13 rsc break;
1191 50923426 2020-01-13 rsc case XK_Down:
1192 50923426 2020-01-13 rsc case XK_KP_Down:
1193 50923426 2020-01-13 rsc k = Kdown;
1194 50923426 2020-01-13 rsc break;
1195 50923426 2020-01-13 rsc case XK_Right:
1196 50923426 2020-01-13 rsc case XK_KP_Right:
1197 50923426 2020-01-13 rsc k = Kright;
1198 50923426 2020-01-13 rsc break;
1199 50923426 2020-01-13 rsc case XK_Page_Down:
1200 50923426 2020-01-13 rsc case XK_KP_Page_Down:
1201 50923426 2020-01-13 rsc k = Kpgdown;
1202 50923426 2020-01-13 rsc break;
1203 50923426 2020-01-13 rsc case XK_End:
1204 50923426 2020-01-13 rsc case XK_KP_End:
1205 50923426 2020-01-13 rsc k = Kend;
1206 50923426 2020-01-13 rsc break;
1207 50923426 2020-01-13 rsc case XK_Page_Up:
1208 50923426 2020-01-13 rsc case XK_KP_Page_Up:
1209 50923426 2020-01-13 rsc k = Kpgup;
1210 50923426 2020-01-13 rsc break;
1211 50923426 2020-01-13 rsc case XK_Insert:
1212 50923426 2020-01-13 rsc case XK_KP_Insert:
1213 50923426 2020-01-13 rsc k = Kins;
1214 50923426 2020-01-13 rsc break;
1215 50923426 2020-01-13 rsc case XK_KP_Enter:
1216 50923426 2020-01-13 rsc case XK_Return:
1217 50923426 2020-01-13 rsc k = '\n';
1218 50923426 2020-01-13 rsc break;
1219 50923426 2020-01-13 rsc case XK_Alt_L:
1220 50923426 2020-01-13 rsc case XK_Meta_L: /* Shift Alt on PCs */
1221 50923426 2020-01-13 rsc case XK_Alt_R:
1222 50923426 2020-01-13 rsc case XK_Meta_R: /* Shift Alt on PCs */
1223 50923426 2020-01-13 rsc case XK_Multi_key:
1224 50923426 2020-01-13 rsc return -1;
1225 50923426 2020-01-13 rsc default: /* not ISO-1 or tty control */
1226 50923426 2020-01-13 rsc if(k>0xff) {
1227 50923426 2020-01-13 rsc k = _p9keysym2ucs(k);
1228 50923426 2020-01-13 rsc if(k==-1) return -1;
1229 50923426 2020-01-13 rsc }
1230 50923426 2020-01-13 rsc }
1231 50923426 2020-01-13 rsc }
1232 50923426 2020-01-13 rsc
1233 50923426 2020-01-13 rsc /* Compensate for servers that call a minus a hyphen */
1234 50923426 2020-01-13 rsc if(k == XK_hyphen)
1235 50923426 2020-01-13 rsc k = XK_minus;
1236 50923426 2020-01-13 rsc /* Do control mapping ourselves if translator doesn't */
1237 50923426 2020-01-13 rsc if(e->xkey.state&ControlMask)
1238 50923426 2020-01-13 rsc k &= 0x9f;
1239 50923426 2020-01-13 rsc if(k == NoSymbol) {
1240 50923426 2020-01-13 rsc return -1;
1241 50923426 2020-01-13 rsc }
1242 50923426 2020-01-13 rsc
1243 50923426 2020-01-13 rsc return k+0;
1244 50923426 2020-01-13 rsc }
1245 50923426 2020-01-13 rsc
1246 50923426 2020-01-13 rsc static int
1247 50923426 2020-01-13 rsc _xtoplan9mouse(Xwin *w, XEvent *e, Mouse *m)
1248 50923426 2020-01-13 rsc {
1249 50923426 2020-01-13 rsc int s;
1250 50923426 2020-01-13 rsc XButtonEvent *be;
1251 50923426 2020-01-13 rsc XMotionEvent *me;
1252 50923426 2020-01-13 rsc
1253 50923426 2020-01-13 rsc if(_x.putsnarf != _x.assertsnarf){
1254 50923426 2020-01-13 rsc _x.assertsnarf = _x.putsnarf;
1255 50923426 2020-01-13 rsc XSetSelectionOwner(_x.display, XA_PRIMARY, w->drawable, CurrentTime);
1256 50923426 2020-01-13 rsc if(_x.clipboard != None)
1257 50923426 2020-01-13 rsc XSetSelectionOwner(_x.display, _x.clipboard, w->drawable, CurrentTime);
1258 50923426 2020-01-13 rsc XFlush(_x.display);
1259 50923426 2020-01-13 rsc }
1260 50923426 2020-01-13 rsc
1261 50923426 2020-01-13 rsc switch(e->type){
1262 50923426 2020-01-13 rsc case ButtonPress:
1263 50923426 2020-01-13 rsc be = (XButtonEvent*)e;
1264 50923426 2020-01-13 rsc
1265 50923426 2020-01-13 rsc /*
1266 50923426 2020-01-13 rsc * Fake message, just sent to make us announce snarf.
1267 50923426 2020-01-13 rsc * Apparently state and button are 16 and 8 bits on
1268 50923426 2020-01-13 rsc * the wire, since they are truncated by the time they
1269 50923426 2020-01-13 rsc * get to us.
1270 50923426 2020-01-13 rsc */
1271 50923426 2020-01-13 rsc if(be->send_event
1272 50923426 2020-01-13 rsc && (~be->state&0xFFFF)==0
1273 50923426 2020-01-13 rsc && (~be->button&0xFF)==0)
1274 50923426 2020-01-13 rsc return -1;
1275 50923426 2020-01-13 rsc /* BUG? on mac need to inherit these from elsewhere? */
1276 50923426 2020-01-13 rsc m->xy.x = be->x;
1277 50923426 2020-01-13 rsc m->xy.y = be->y;
1278 50923426 2020-01-13 rsc s = be->state;
1279 50923426 2020-01-13 rsc m->msec = be->time;
1280 50923426 2020-01-13 rsc switch(be->button){
1281 50923426 2020-01-13 rsc case 1:
1282 50923426 2020-01-13 rsc s |= Button1Mask;
1283 50923426 2020-01-13 rsc break;
1284 50923426 2020-01-13 rsc case 2:
1285 50923426 2020-01-13 rsc s |= Button2Mask;
1286 50923426 2020-01-13 rsc break;
1287 50923426 2020-01-13 rsc case 3:
1288 50923426 2020-01-13 rsc s |= Button3Mask;
1289 50923426 2020-01-13 rsc break;
1290 50923426 2020-01-13 rsc case 4:
1291 50923426 2020-01-13 rsc s |= Button4Mask;
1292 50923426 2020-01-13 rsc break;
1293 50923426 2020-01-13 rsc case 5:
1294 50923426 2020-01-13 rsc s |= Button5Mask;
1295 50923426 2020-01-13 rsc break;
1296 50923426 2020-01-13 rsc }
1297 50923426 2020-01-13 rsc break;
1298 50923426 2020-01-13 rsc case ButtonRelease:
1299 50923426 2020-01-13 rsc be = (XButtonEvent*)e;
1300 50923426 2020-01-13 rsc m->xy.x = be->x;
1301 50923426 2020-01-13 rsc m->xy.y = be->y;
1302 50923426 2020-01-13 rsc s = be->state;
1303 50923426 2020-01-13 rsc m->msec = be->time;
1304 50923426 2020-01-13 rsc switch(be->button){
1305 50923426 2020-01-13 rsc case 1:
1306 50923426 2020-01-13 rsc s &= ~Button1Mask;
1307 50923426 2020-01-13 rsc break;
1308 50923426 2020-01-13 rsc case 2:
1309 50923426 2020-01-13 rsc s &= ~Button2Mask;
1310 50923426 2020-01-13 rsc break;
1311 50923426 2020-01-13 rsc case 3:
1312 50923426 2020-01-13 rsc s &= ~Button3Mask;
1313 50923426 2020-01-13 rsc break;
1314 50923426 2020-01-13 rsc case 4:
1315 50923426 2020-01-13 rsc s &= ~Button4Mask;
1316 50923426 2020-01-13 rsc break;
1317 50923426 2020-01-13 rsc case 5:
1318 50923426 2020-01-13 rsc s &= ~Button5Mask;
1319 50923426 2020-01-13 rsc break;
1320 50923426 2020-01-13 rsc }
1321 50923426 2020-01-13 rsc break;
1322 50923426 2020-01-13 rsc
1323 50923426 2020-01-13 rsc case MotionNotify:
1324 50923426 2020-01-13 rsc me = (XMotionEvent*)e;
1325 50923426 2020-01-13 rsc s = me->state;
1326 50923426 2020-01-13 rsc m->xy.x = me->x;
1327 50923426 2020-01-13 rsc m->xy.y = me->y;
1328 50923426 2020-01-13 rsc m->msec = me->time;
1329 50923426 2020-01-13 rsc return 0; // do not set buttons
1330 50923426 2020-01-13 rsc
1331 50923426 2020-01-13 rsc default:
1332 50923426 2020-01-13 rsc return -1;
1333 50923426 2020-01-13 rsc }
1334 50923426 2020-01-13 rsc
1335 50923426 2020-01-13 rsc m->buttons = 0;
1336 50923426 2020-01-13 rsc if(s & Button1Mask)
1337 50923426 2020-01-13 rsc m->buttons |= 1;
1338 50923426 2020-01-13 rsc if(s & Button2Mask)
1339 50923426 2020-01-13 rsc m->buttons |= 2;
1340 50923426 2020-01-13 rsc if(s & Button3Mask)
1341 50923426 2020-01-13 rsc m->buttons |= 4;
1342 50923426 2020-01-13 rsc if(s & Button4Mask)
1343 50923426 2020-01-13 rsc m->buttons |= 8;
1344 50923426 2020-01-13 rsc if(s & Button5Mask)
1345 50923426 2020-01-13 rsc m->buttons |= 16;
1346 50923426 2020-01-13 rsc return 0;
1347 50923426 2020-01-13 rsc }
1348 50923426 2020-01-13 rsc
1349 50923426 2020-01-13 rsc void
1350 50923426 2020-01-13 rsc rpc_setmouse(Client *client, Point p)
1351 50923426 2020-01-13 rsc {
1352 50923426 2020-01-13 rsc Xwin *w = (Xwin*)client->view;
1353 50923426 2020-01-13 rsc
1354 50923426 2020-01-13 rsc xlock();
1355 50923426 2020-01-13 rsc XWarpPointer(_x.display, None, w->drawable, 0, 0, 0, 0, p.x, p.y);
1356 50923426 2020-01-13 rsc XFlush(_x.display);
1357 50923426 2020-01-13 rsc xunlock();
1358 50923426 2020-01-13 rsc }
1359 50923426 2020-01-13 rsc
1360 50923426 2020-01-13 rsc static int
1361 50923426 2020-01-13 rsc revbyte(int b)
1362 50923426 2020-01-13 rsc {
1363 50923426 2020-01-13 rsc int r;
1364 50923426 2020-01-13 rsc
1365 50923426 2020-01-13 rsc r = 0;
1366 50923426 2020-01-13 rsc r |= (b&0x01) << 7;
1367 50923426 2020-01-13 rsc r |= (b&0x02) << 5;
1368 50923426 2020-01-13 rsc r |= (b&0x04) << 3;
1369 50923426 2020-01-13 rsc r |= (b&0x08) << 1;
1370 50923426 2020-01-13 rsc r |= (b&0x10) >> 1;
1371 50923426 2020-01-13 rsc r |= (b&0x20) >> 3;
1372 50923426 2020-01-13 rsc r |= (b&0x40) >> 5;
1373 50923426 2020-01-13 rsc r |= (b&0x80) >> 7;
1374 50923426 2020-01-13 rsc return r;
1375 50923426 2020-01-13 rsc }
1376 50923426 2020-01-13 rsc
1377 50923426 2020-01-13 rsc static void
1378 50923426 2020-01-13 rsc xcursorarrow(Xwin *w)
1379 50923426 2020-01-13 rsc {
1380 50923426 2020-01-13 rsc if(_x.cursor != 0){
1381 50923426 2020-01-13 rsc XFreeCursor(_x.display, _x.cursor);
1382 50923426 2020-01-13 rsc _x.cursor = 0;
1383 50923426 2020-01-13 rsc }
1384 50923426 2020-01-13 rsc XUndefineCursor(_x.display, w->drawable);
1385 50923426 2020-01-13 rsc XFlush(_x.display);
1386 50923426 2020-01-13 rsc }
1387 50923426 2020-01-13 rsc
1388 50923426 2020-01-13 rsc
1389 50923426 2020-01-13 rsc void
1390 50923426 2020-01-13 rsc rpc_setcursor(Client *client, Cursor *c, Cursor2 *c2)
1391 50923426 2020-01-13 rsc {
1392 50923426 2020-01-13 rsc Xwin *w = (Xwin*)client->view;
1393 50923426 2020-01-13 rsc XColor fg, bg;
1394 50923426 2020-01-13 rsc XCursor xc;
1395 50923426 2020-01-13 rsc Pixmap xsrc, xmask;
1396 50923426 2020-01-13 rsc int i;
1397 50923426 2020-01-13 rsc uchar src[2*16], mask[2*16];
1398 50923426 2020-01-13 rsc
1399 50923426 2020-01-13 rsc USED(c2);
1400 50923426 2020-01-13 rsc
1401 50923426 2020-01-13 rsc xlock();
1402 50923426 2020-01-13 rsc if(c == nil){
1403 50923426 2020-01-13 rsc xcursorarrow(w);
1404 50923426 2020-01-13 rsc xunlock();
1405 50923426 2020-01-13 rsc return;
1406 50923426 2020-01-13 rsc }
1407 50923426 2020-01-13 rsc for(i=0; i<2*16; i++){
1408 50923426 2020-01-13 rsc src[i] = revbyte(c->set[i]);
1409 50923426 2020-01-13 rsc mask[i] = revbyte(c->set[i] | c->clr[i]);
1410 50923426 2020-01-13 rsc }
1411 50923426 2020-01-13 rsc
1412 50923426 2020-01-13 rsc fg = _x.map[0];
1413 50923426 2020-01-13 rsc bg = _x.map[255];
1414 50923426 2020-01-13 rsc xsrc = XCreateBitmapFromData(_x.display, w->drawable, (char*)src, 16, 16);
1415 50923426 2020-01-13 rsc xmask = XCreateBitmapFromData(_x.display, w->drawable, (char*)mask, 16, 16);
1416 50923426 2020-01-13 rsc xc = XCreatePixmapCursor(_x.display, xsrc, xmask, &fg, &bg, -c->offset.x, -c->offset.y);
1417 50923426 2020-01-13 rsc if(xc != 0) {
1418 50923426 2020-01-13 rsc XDefineCursor(_x.display, w->drawable, xc);
1419 50923426 2020-01-13 rsc if(_x.cursor != 0)
1420 50923426 2020-01-13 rsc XFreeCursor(_x.display, _x.cursor);
1421 50923426 2020-01-13 rsc _x.cursor = xc;
1422 50923426 2020-01-13 rsc }
1423 50923426 2020-01-13 rsc XFreePixmap(_x.display, xsrc);
1424 50923426 2020-01-13 rsc XFreePixmap(_x.display, xmask);
1425 50923426 2020-01-13 rsc XFlush(_x.display);
1426 50923426 2020-01-13 rsc xunlock();
1427 50923426 2020-01-13 rsc }
1428 50923426 2020-01-13 rsc
1429 50923426 2020-01-13 rsc struct {
1430 50923426 2020-01-13 rsc QLock lk;
1431 50923426 2020-01-13 rsc char buf[SnarfSize];
1432 50923426 2020-01-13 rsc #ifdef APPLESNARF
1433 50923426 2020-01-13 rsc Rune rbuf[SnarfSize];
1434 50923426 2020-01-13 rsc PasteboardRef apple;
1435 50923426 2020-01-13 rsc #endif
1436 50923426 2020-01-13 rsc } clip;
1437 50923426 2020-01-13 rsc
1438 50923426 2020-01-13 rsc static uchar*
1439 50923426 2020-01-13 rsc _xgetsnarffrom(Xwin *w, XWindow xw, Atom clipboard, Atom target, int timeout0, int timeout)
1440 50923426 2020-01-13 rsc {
1441 50923426 2020-01-13 rsc Atom prop, type;
1442 50923426 2020-01-13 rsc ulong len, lastlen, dummy;
1443 50923426 2020-01-13 rsc int fmt, i;
1444 50923426 2020-01-13 rsc uchar *data, *xdata;
1445 50923426 2020-01-13 rsc
1446 50923426 2020-01-13 rsc /*
1447 50923426 2020-01-13 rsc * We should be waiting for SelectionNotify here, but it might never
1448 50923426 2020-01-13 rsc * come, and we have no way to time out. Instead, we will clear
1449 50923426 2020-01-13 rsc * local property #1, request our buddy to fill it in for us, and poll
1450 50923426 2020-01-13 rsc * until he's done or we get tired of waiting.
1451 50923426 2020-01-13 rsc */
1452 50923426 2020-01-13 rsc prop = 1;
1453 50923426 2020-01-13 rsc XChangeProperty(_x.display, w->drawable, prop, target, 8, PropModeReplace, (uchar*)"", 0);
1454 50923426 2020-01-13 rsc XConvertSelection(_x.display, clipboard, target, prop, w->drawable, CurrentTime);
1455 50923426 2020-01-13 rsc XFlush(_x.display);
1456 50923426 2020-01-13 rsc lastlen = 0;
1457 50923426 2020-01-13 rsc timeout0 = (timeout0 + 9)/10;
1458 50923426 2020-01-13 rsc timeout = (timeout + 9)/10;
1459 50923426 2020-01-13 rsc for(i=0; i<timeout0 || (lastlen!=0 && i<timeout); i++){
1460 50923426 2020-01-13 rsc usleep(10*1000);
1461 50923426 2020-01-13 rsc XGetWindowProperty(_x.display, w->drawable, prop, 0, 0, 0, AnyPropertyType,
1462 50923426 2020-01-13 rsc &type, &fmt, &dummy, &len, &xdata);
1463 50923426 2020-01-13 rsc if(lastlen == len && len > 0){
1464 50923426 2020-01-13 rsc XFree(xdata);
1465 50923426 2020-01-13 rsc break;
1466 50923426 2020-01-13 rsc }
1467 50923426 2020-01-13 rsc lastlen = len;
1468 50923426 2020-01-13 rsc XFree(xdata);
1469 50923426 2020-01-13 rsc }
1470 50923426 2020-01-13 rsc if(len == 0)
1471 50923426 2020-01-13 rsc return nil;
1472 50923426 2020-01-13 rsc
1473 50923426 2020-01-13 rsc /* get the property */
1474 50923426 2020-01-13 rsc xdata = nil;
1475 50923426 2020-01-13 rsc XGetWindowProperty(_x.display, w->drawable, prop, 0, SnarfSize/sizeof(ulong), 0,
1476 50923426 2020-01-13 rsc AnyPropertyType, &type, &fmt, &len, &dummy, &xdata);
1477 50923426 2020-01-13 rsc if((type != target && type != XA_STRING && type != _x.utf8string) || len == 0){
1478 50923426 2020-01-13 rsc if(xdata)
1479 50923426 2020-01-13 rsc XFree(xdata);
1480 50923426 2020-01-13 rsc return nil;
1481 50923426 2020-01-13 rsc }
1482 50923426 2020-01-13 rsc if(xdata){
1483 50923426 2020-01-13 rsc data = (uchar*)strdup((char*)xdata);
1484 50923426 2020-01-13 rsc XFree(xdata);
1485 50923426 2020-01-13 rsc return data;
1486 50923426 2020-01-13 rsc }
1487 50923426 2020-01-13 rsc return nil;
1488 50923426 2020-01-13 rsc }
1489 50923426 2020-01-13 rsc
1490 50923426 2020-01-13 rsc char*
1491 50923426 2020-01-13 rsc rpc_getsnarf(void)
1492 50923426 2020-01-13 rsc {
1493 50923426 2020-01-13 rsc uchar *data;
1494 50923426 2020-01-13 rsc Atom clipboard;
1495 50923426 2020-01-13 rsc XWindow xw;
1496 50923426 2020-01-13 rsc Xwin *w;
1497 50923426 2020-01-13 rsc
1498 50923426 2020-01-13 rsc qlock(&clip.lk);
1499 50923426 2020-01-13 rsc xlock();
1500 50923426 2020-01-13 rsc w = _x.windows;
1501 50923426 2020-01-13 rsc /*
1502 50923426 2020-01-13 rsc * Have we snarfed recently and the X server hasn't caught up?
1503 50923426 2020-01-13 rsc */
1504 50923426 2020-01-13 rsc if(_x.putsnarf != _x.assertsnarf)
1505 50923426 2020-01-13 rsc goto mine;
1506 50923426 2020-01-13 rsc
1507 50923426 2020-01-13 rsc /*
1508 50923426 2020-01-13 rsc * Is there a primary selection (highlighted text in an xterm)?
1509 50923426 2020-01-13 rsc */
1510 50923426 2020-01-13 rsc clipboard = XA_PRIMARY;
1511 50923426 2020-01-13 rsc xw = XGetSelectionOwner(_x.display, XA_PRIMARY);
1512 50923426 2020-01-13 rsc // TODO check more
1513 50923426 2020-01-13 rsc if(xw == w->drawable){
1514 50923426 2020-01-13 rsc mine:
1515 50923426 2020-01-13 rsc data = (uchar*)strdup(clip.buf);
1516 50923426 2020-01-13 rsc goto out;
1517 50923426 2020-01-13 rsc }
1518 50923426 2020-01-13 rsc
1519 50923426 2020-01-13 rsc /*
1520 50923426 2020-01-13 rsc * If not, is there a clipboard selection?
1521 50923426 2020-01-13 rsc */
1522 50923426 2020-01-13 rsc if(xw == None && _x.clipboard != None){
1523 50923426 2020-01-13 rsc clipboard = _x.clipboard;
1524 50923426 2020-01-13 rsc xw = XGetSelectionOwner(_x.display, _x.clipboard);
1525 50923426 2020-01-13 rsc if(xw == w->drawable)
1526 50923426 2020-01-13 rsc goto mine;
1527 50923426 2020-01-13 rsc }
1528 50923426 2020-01-13 rsc
1529 50923426 2020-01-13 rsc /*
1530 50923426 2020-01-13 rsc * If not, give up.
1531 50923426 2020-01-13 rsc */
1532 50923426 2020-01-13 rsc if(xw == None){
1533 50923426 2020-01-13 rsc data = nil;
1534 50923426 2020-01-13 rsc goto out;
1535 50923426 2020-01-13 rsc }
1536 50923426 2020-01-13 rsc
1537 50923426 2020-01-13 rsc if((data = _xgetsnarffrom(w, xw, clipboard, _x.utf8string, 10, 100)) == nil)
1538 50923426 2020-01-13 rsc if((data = _xgetsnarffrom(w, xw, clipboard, XA_STRING, 10, 100)) == nil){
1539 50923426 2020-01-13 rsc /* nothing left to do */
1540 50923426 2020-01-13 rsc }
1541 50923426 2020-01-13 rsc
1542 50923426 2020-01-13 rsc out:
1543 50923426 2020-01-13 rsc xunlock();
1544 50923426 2020-01-13 rsc qunlock(&clip.lk);
1545 50923426 2020-01-13 rsc return (char*)data;
1546 50923426 2020-01-13 rsc }
1547 50923426 2020-01-13 rsc
1548 50923426 2020-01-13 rsc void
1549 50923426 2020-01-13 rsc __xputsnarf(char *data)
1550 50923426 2020-01-13 rsc {
1551 50923426 2020-01-13 rsc XButtonEvent e;
1552 50923426 2020-01-13 rsc Xwin *w;
1553 1f799495 2020-01-15 rsc
1554 50923426 2020-01-13 rsc if(strlen(data) >= SnarfSize)
1555 50923426 2020-01-13 rsc return;
1556 50923426 2020-01-13 rsc qlock(&clip.lk);
1557 50923426 2020-01-13 rsc xlock();
1558 50923426 2020-01-13 rsc w = _x.windows;
1559 50923426 2020-01-13 rsc strcpy(clip.buf, data);
1560 50923426 2020-01-13 rsc /* leave note for mouse proc to assert selection ownership */
1561 50923426 2020-01-13 rsc _x.putsnarf++;
1562 50923426 2020-01-13 rsc
1563 50923426 2020-01-13 rsc /* send mouse a fake event so snarf is announced */
1564 50923426 2020-01-13 rsc memset(&e, 0, sizeof e);
1565 50923426 2020-01-13 rsc e.type = ButtonPress;
1566 50923426 2020-01-13 rsc e.window = w->drawable;
1567 50923426 2020-01-13 rsc e.state = ~0;
1568 50923426 2020-01-13 rsc e.button = ~0;
1569 50923426 2020-01-13 rsc XSendEvent(_x.display, w->drawable, True, ButtonPressMask, (XEvent*)&e);
1570 50923426 2020-01-13 rsc XFlush(_x.display);
1571 50923426 2020-01-13 rsc xunlock();
1572 50923426 2020-01-13 rsc qunlock(&clip.lk);
1573 50923426 2020-01-13 rsc }
1574 50923426 2020-01-13 rsc
1575 50923426 2020-01-13 rsc static int
1576 50923426 2020-01-13 rsc _xselect(XEvent *e)
1577 50923426 2020-01-13 rsc {
1578 50923426 2020-01-13 rsc char *name;
1579 50923426 2020-01-13 rsc XEvent r;
1580 50923426 2020-01-13 rsc XSelectionRequestEvent *xe;
1581 50923426 2020-01-13 rsc Atom a[4];
1582 50923426 2020-01-13 rsc
1583 50923426 2020-01-13 rsc memset(&r, 0, sizeof r);
1584 50923426 2020-01-13 rsc xe = (XSelectionRequestEvent*)e;
1585 50923426 2020-01-13 rsc if(0) fprint(2, "xselect target=%d requestor=%d property=%d selection=%d (sizeof atom=%d)\n",
1586 50923426 2020-01-13 rsc xe->target, xe->requestor, xe->property, xe->selection, sizeof a[0]);
1587 50923426 2020-01-13 rsc r.xselection.property = xe->property;
1588 50923426 2020-01-13 rsc if(xe->target == _x.targets){
1589 50923426 2020-01-13 rsc a[0] = _x.utf8string;
1590 50923426 2020-01-13 rsc a[1] = XA_STRING;
1591 50923426 2020-01-13 rsc a[2] = _x.text;
1592 50923426 2020-01-13 rsc a[3] = _x.compoundtext;
1593 50923426 2020-01-13 rsc XChangeProperty(_x.display, xe->requestor, xe->property, XA_ATOM,
1594 50923426 2020-01-13 rsc 32, PropModeReplace, (uchar*)a, nelem(a));
1595 50923426 2020-01-13 rsc }else if(xe->target == XA_STRING
1596 50923426 2020-01-13 rsc || xe->target == _x.utf8string
1597 50923426 2020-01-13 rsc || xe->target == _x.text
1598 50923426 2020-01-13 rsc || xe->target == _x.compoundtext
1599 50923426 2020-01-13 rsc || ((name = XGetAtomName(_x.display, xe->target)) && strcmp(name, "text/plain;charset=UTF-8") == 0)){
1600 50923426 2020-01-13 rsc /* text/plain;charset=UTF-8 seems nonstandard but is used by Synergy */
1601 50923426 2020-01-13 rsc /* if the target is STRING we're supposed to reply with Latin1 XXX */
1602 50923426 2020-01-13 rsc qlock(&clip.lk);
1603 50923426 2020-01-13 rsc XChangeProperty(_x.display, xe->requestor, xe->property, xe->target,
1604 50923426 2020-01-13 rsc 8, PropModeReplace, (uchar*)clip.buf, strlen(clip.buf));
1605 50923426 2020-01-13 rsc qunlock(&clip.lk);
1606 50923426 2020-01-13 rsc }else{
1607 50923426 2020-01-13 rsc if(strcmp(name, "TIMESTAMP") != 0)
1608 50923426 2020-01-13 rsc fprint(2, "%s: cannot handle selection request for '%s' (%d)\n", argv0, name, (int)xe->target);
1609 50923426 2020-01-13 rsc r.xselection.property = None;
1610 50923426 2020-01-13 rsc }
1611 50923426 2020-01-13 rsc
1612 50923426 2020-01-13 rsc r.xselection.display = xe->display;
1613 50923426 2020-01-13 rsc /* r.xselection.property filled above */
1614 50923426 2020-01-13 rsc r.xselection.target = xe->target;
1615 50923426 2020-01-13 rsc r.xselection.type = SelectionNotify;
1616 50923426 2020-01-13 rsc r.xselection.requestor = xe->requestor;
1617 50923426 2020-01-13 rsc r.xselection.time = xe->time;
1618 50923426 2020-01-13 rsc r.xselection.send_event = True;
1619 50923426 2020-01-13 rsc r.xselection.selection = xe->selection;
1620 50923426 2020-01-13 rsc XSendEvent(_x.display, xe->requestor, False, 0, &r);
1621 50923426 2020-01-13 rsc XFlush(_x.display);
1622 50923426 2020-01-13 rsc return 0;
1623 50923426 2020-01-13 rsc }
1624 50923426 2020-01-13 rsc
1625 50923426 2020-01-13 rsc #ifdef APPLESNARF
1626 50923426 2020-01-13 rsc char*
1627 50923426 2020-01-13 rsc _applegetsnarf(void)
1628 50923426 2020-01-13 rsc {
1629 50923426 2020-01-13 rsc char *s, *t;
1630 50923426 2020-01-13 rsc CFArrayRef flavors;
1631 50923426 2020-01-13 rsc CFDataRef data;
1632 50923426 2020-01-13 rsc CFIndex nflavor, ndata, j;
1633 50923426 2020-01-13 rsc CFStringRef type;
1634 50923426 2020-01-13 rsc ItemCount nitem;
1635 50923426 2020-01-13 rsc PasteboardItemID id;
1636 50923426 2020-01-13 rsc PasteboardSyncFlags flags;
1637 50923426 2020-01-13 rsc UInt32 i;
1638 50923426 2020-01-13 rsc
1639 50923426 2020-01-13 rsc /* fprint(2, "applegetsnarf\n"); */
1640 50923426 2020-01-13 rsc qlock(&clip.lk);
1641 50923426 2020-01-13 rsc if(clip.apple == nil){
1642 50923426 2020-01-13 rsc if(PasteboardCreate(kPasteboardClipboard, &clip.apple) != noErr){
1643 50923426 2020-01-13 rsc fprint(2, "apple pasteboard create failed\n");
1644 50923426 2020-01-13 rsc qunlock(&clip.lk);
1645 50923426 2020-01-13 rsc return nil;
1646 50923426 2020-01-13 rsc }
1647 50923426 2020-01-13 rsc }
1648 50923426 2020-01-13 rsc flags = PasteboardSynchronize(clip.apple);
1649 50923426 2020-01-13 rsc if(flags&kPasteboardClientIsOwner){
1650 50923426 2020-01-13 rsc s = strdup(clip.buf);
1651 50923426 2020-01-13 rsc qunlock(&clip.lk);
1652 50923426 2020-01-13 rsc return s;
1653 50923426 2020-01-13 rsc }
1654 50923426 2020-01-13 rsc if(PasteboardGetItemCount(clip.apple, &nitem) != noErr){
1655 50923426 2020-01-13 rsc fprint(2, "apple pasteboard get item count failed\n");
1656 50923426 2020-01-13 rsc qunlock(&clip.lk);
1657 50923426 2020-01-13 rsc return nil;
1658 50923426 2020-01-13 rsc }
1659 50923426 2020-01-13 rsc for(i=1; i<=nitem; i++){
1660 50923426 2020-01-13 rsc if(PasteboardGetItemIdentifier(clip.apple, i, &id) != noErr)
1661 50923426 2020-01-13 rsc continue;
1662 50923426 2020-01-13 rsc if(PasteboardCopyItemFlavors(clip.apple, id, &flavors) != noErr)
1663 50923426 2020-01-13 rsc continue;
1664 50923426 2020-01-13 rsc nflavor = CFArrayGetCount(flavors);
1665 50923426 2020-01-13 rsc for(j=0; j<nflavor; j++){
1666 50923426 2020-01-13 rsc type = (CFStringRef)CFArrayGetValueAtIndex(flavors, j);
1667 50923426 2020-01-13 rsc if(!UTTypeConformsTo(type, CFSTR("public.utf16-plain-text")))
1668 50923426 2020-01-13 rsc continue;
1669 50923426 2020-01-13 rsc if(PasteboardCopyItemFlavorData(clip.apple, id, type, &data) != noErr)
1670 50923426 2020-01-13 rsc continue;
1671 50923426 2020-01-13 rsc ndata = CFDataGetLength(data);
1672 50923426 2020-01-13 rsc qunlock(&clip.lk);
1673 50923426 2020-01-13 rsc s = smprint("%.*S", ndata/2, (Rune*)CFDataGetBytePtr(data));
1674 50923426 2020-01-13 rsc CFRelease(flavors);
1675 50923426 2020-01-13 rsc CFRelease(data);
1676 50923426 2020-01-13 rsc for(t=s; *t; t++)
1677 50923426 2020-01-13 rsc if(*t == '\r')
1678 50923426 2020-01-13 rsc *t = '\n';
1679 50923426 2020-01-13 rsc return s;
1680 50923426 2020-01-13 rsc }
1681 50923426 2020-01-13 rsc CFRelease(flavors);
1682 50923426 2020-01-13 rsc }
1683 50923426 2020-01-13 rsc qunlock(&clip.lk);
1684 50923426 2020-01-13 rsc return nil;
1685 50923426 2020-01-13 rsc }
1686 50923426 2020-01-13 rsc
1687 50923426 2020-01-13 rsc void
1688 50923426 2020-01-13 rsc _appleputsnarf(char *s)
1689 50923426 2020-01-13 rsc {
1690 50923426 2020-01-13 rsc CFDataRef cfdata;
1691 50923426 2020-01-13 rsc PasteboardSyncFlags flags;
1692 50923426 2020-01-13 rsc
1693 50923426 2020-01-13 rsc /* fprint(2, "appleputsnarf\n"); */
1694 50923426 2020-01-13 rsc
1695 50923426 2020-01-13 rsc if(strlen(s) >= SnarfSize)
1696 50923426 2020-01-13 rsc return;
1697 50923426 2020-01-13 rsc qlock(&clip.lk);
1698 50923426 2020-01-13 rsc strcpy(clip.buf, s);
1699 50923426 2020-01-13 rsc runesnprint(clip.rbuf, nelem(clip.rbuf), "%s", s);
1700 50923426 2020-01-13 rsc if(clip.apple == nil){
1701 50923426 2020-01-13 rsc if(PasteboardCreate(kPasteboardClipboard, &clip.apple) != noErr){
1702 50923426 2020-01-13 rsc fprint(2, "apple pasteboard create failed\n");
1703 50923426 2020-01-13 rsc qunlock(&clip.lk);
1704 50923426 2020-01-13 rsc return;
1705 50923426 2020-01-13 rsc }
1706 50923426 2020-01-13 rsc }
1707 50923426 2020-01-13 rsc if(PasteboardClear(clip.apple) != noErr){
1708 50923426 2020-01-13 rsc fprint(2, "apple pasteboard clear failed\n");
1709 50923426 2020-01-13 rsc qunlock(&clip.lk);
1710 50923426 2020-01-13 rsc return;
1711 50923426 2020-01-13 rsc }
1712 50923426 2020-01-13 rsc flags = PasteboardSynchronize(clip.apple);
1713 50923426 2020-01-13 rsc if((flags&kPasteboardModified) || !(flags&kPasteboardClientIsOwner)){
1714 50923426 2020-01-13 rsc fprint(2, "apple pasteboard cannot assert ownership\n");
1715 50923426 2020-01-13 rsc qunlock(&clip.lk);
1716 50923426 2020-01-13 rsc return;
1717 50923426 2020-01-13 rsc }
1718 50923426 2020-01-13 rsc cfdata = CFDataCreate(kCFAllocatorDefault,
1719 50923426 2020-01-13 rsc (uchar*)clip.rbuf, runestrlen(clip.rbuf)*2);
1720 50923426 2020-01-13 rsc if(cfdata == nil){
1721 50923426 2020-01-13 rsc fprint(2, "apple pasteboard cfdatacreate failed\n");
1722 50923426 2020-01-13 rsc qunlock(&clip.lk);
1723 50923426 2020-01-13 rsc return;
1724 50923426 2020-01-13 rsc }
1725 50923426 2020-01-13 rsc if(PasteboardPutItemFlavor(clip.apple, (PasteboardItemID)1,
1726 50923426 2020-01-13 rsc CFSTR("public.utf16-plain-text"), cfdata, 0) != noErr){
1727 50923426 2020-01-13 rsc fprint(2, "apple pasteboard putitem failed\n");
1728 50923426 2020-01-13 rsc CFRelease(cfdata);
1729 50923426 2020-01-13 rsc qunlock(&clip.lk);
1730 50923426 2020-01-13 rsc return;
1731 50923426 2020-01-13 rsc }
1732 50923426 2020-01-13 rsc /* CFRelease(cfdata); ??? */
1733 50923426 2020-01-13 rsc qunlock(&clip.lk);
1734 50923426 2020-01-13 rsc }
1735 50923426 2020-01-13 rsc #endif /* APPLESNARF */
1736 50923426 2020-01-13 rsc
1737 50923426 2020-01-13 rsc void
1738 50923426 2020-01-13 rsc rpc_putsnarf(char *data)
1739 50923426 2020-01-13 rsc {
1740 50923426 2020-01-13 rsc #ifdef APPLESNARF
1741 50923426 2020-01-13 rsc _appleputsnarf(data);
1742 50923426 2020-01-13 rsc #endif
1743 50923426 2020-01-13 rsc __xputsnarf(data);
1744 50923426 2020-01-13 rsc }
1745 50923426 2020-01-13 rsc
1746 50923426 2020-01-13 rsc /*
1747 50923426 2020-01-13 rsc * Send the mouse event back to the window manager.
1748 50923426 2020-01-13 rsc * So that 9term can tell rio to pop up its button3 menu.
1749 50923426 2020-01-13 rsc */
1750 50923426 2020-01-13 rsc void
1751 50923426 2020-01-13 rsc rpc_bouncemouse(Client *c, Mouse m)
1752 50923426 2020-01-13 rsc {
1753 50923426 2020-01-13 rsc Xwin *w = (Xwin*)c->view;
1754 50923426 2020-01-13 rsc XButtonEvent e;
1755 50923426 2020-01-13 rsc XWindow dw;
1756 1f799495 2020-01-15 rsc
1757 50923426 2020-01-13 rsc xlock();
1758 50923426 2020-01-13 rsc e.type = ButtonPress;
1759 50923426 2020-01-13 rsc e.state = 0;
1760 50923426 2020-01-13 rsc e.button = 0;
1761 50923426 2020-01-13 rsc if(m.buttons&1)
1762 50923426 2020-01-13 rsc e.button = 1;
1763 50923426 2020-01-13 rsc else if(m.buttons&2)
1764 50923426 2020-01-13 rsc e.button = 2;
1765 50923426 2020-01-13 rsc else if(m.buttons&4)
1766 50923426 2020-01-13 rsc e.button = 3;
1767 50923426 2020-01-13 rsc e.same_screen = 1;
1768 50923426 2020-01-13 rsc XTranslateCoordinates(_x.display, w->drawable,
1769 50923426 2020-01-13 rsc DefaultRootWindow(_x.display),
1770 50923426 2020-01-13 rsc m.xy.x, m.xy.y, &e.x_root, &e.y_root, &dw);
1771 50923426 2020-01-13 rsc e.root = DefaultRootWindow(_x.display);
1772 50923426 2020-01-13 rsc e.window = e.root;
1773 50923426 2020-01-13 rsc e.subwindow = None;
1774 50923426 2020-01-13 rsc e.x = e.x_root;
1775 50923426 2020-01-13 rsc e.y = e.y_root;
1776 50923426 2020-01-13 rsc #undef time
1777 50923426 2020-01-13 rsc e.time = CurrentTime;
1778 50923426 2020-01-13 rsc XUngrabPointer(_x.display, m.msec);
1779 50923426 2020-01-13 rsc XSendEvent(_x.display, e.root, True, ButtonPressMask, (XEvent*)&e);
1780 50923426 2020-01-13 rsc XFlush(_x.display);
1781 50923426 2020-01-13 rsc xunlock();
1782 50923426 2020-01-13 rsc }