1 /*
2 * wmslib/src/but/rcur.c, part of wmslib (Library functions)
3 * Copyright (C) 1994 William Shubert.
4 * See "configure.h.in" for more copyright information.
5 */
6
7 #include <configure.h>
8
9 #ifdef X11_DISP
10
11 #ifdef STDC_HEADERS
12 #include <stdlib.h>
13 #include <unistd.h>
14 #endif /* STDC_HEADERS */
15 #include <stdio.h>
16 #include <X11/Xlib.h>
17 #include <X11/Xutil.h>
18 #include <X11/cursorfont.h>
19 #include <X11/Xatom.h>
20 #include <X11/keysym.h>
21 #include <sys/time.h>
22 #ifdef HAVE_SYS_SELECT_H
23 #include <sys/select.h>
24 #endif
25 #include <wms.h>
26 #include <but/but.h>
27 #include <but/net.h>
28 #include <but/canvas.h>
29
30
31 typedef struct Curs_struct {
32 int fontcurnum;
33 int hotX, hotY, w, h;
34 char *pic, *mask;
35 } Curs;
36
37
38 #define ntm_width 16
39 #define ntm_height 16
40 #define ntm_bits ((char *)ntm_ubits)
41 static uchar ntm_ubits[] = {
42 0x03, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x3f, 0x00, 0x7f, 0x00,
43 0xff, 0x00, 0xff, 0x01, 0xff, 0x03, 0xff, 0x03, 0x7f, 0x00, 0xf7, 0x00,
44 0xf3, 0x00, 0xe0, 0x01, 0xe0, 0x01, 0xc0, 0x01};
45
46 #define ntp_width 16
47 #define ntp_height 16
48 #define ntp_bits ((char *)ntp_ubits)
49 static uchar ntp_ubits[] = {
50 0x00, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x1e, 0x00, 0x3e, 0x00,
51 0x7e, 0x00, 0xfe, 0x00, 0xfe, 0x01, 0x3e, 0x00, 0x36, 0x00, 0x62, 0x00,
52 0x60, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x00, 0x00};
53
54 #define tm_width 16
55 #define tm_height 16
56 #define tm_bits ((char *)tm_ubits)
57 static uchar tm_ubits[] = {
58 0x00, 0xe0, 0x00, 0xf8, 0x00, 0xfe, 0x80, 0x7f, 0xe0, 0x7f, 0xf8, 0x3f,
59 0xfc, 0x3f, 0xf8, 0x1f, 0xe0, 0x1f, 0xf0, 0x0f, 0xf8, 0x0f, 0x7c, 0x07,
60 0x3e, 0x07, 0x1f, 0x02, 0x0e, 0x00, 0x04, 0x00};
61
62 #define tp_width 16
63 #define tp_height 16
64 #define tp_bits ((char *)tp_ubits)
65 static uchar tp_ubits[] = {
66 0x00, 0x00, 0x00, 0x60, 0x00, 0x78, 0x00, 0x3e, 0x80, 0x3f, 0xe0, 0x1f,
67 0xf8, 0x1f, 0x80, 0x0f, 0xc0, 0x0f, 0xe0, 0x06, 0x70, 0x06, 0x38, 0x02,
68 0x1c, 0x02, 0x0e, 0x00, 0x04, 0x00, 0x00, 0x00};
69
70 #define txtp_width 16
71 #define txtp_height 16
72 #define txtp_bits ((char *)txtp_ubits)
73 static uchar txtp_ubits[] = {
74 0x00, 0x00, 0xee, 0x00, 0x38, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00,
75 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00,
76 0x10, 0x00, 0x38, 0x00, 0xee, 0x00, 0x00, 0x00};
77
78 #define txtm_width 16
79 #define txtm_height 16
80 #define txtm_bits ((char *)txtm_ubits)
81 static uchar txtm_ubits[] = {
82 0xef, 0x01, 0xff, 0x01, 0xff, 0x01, 0x7c, 0x00, 0x38, 0x00, 0x38, 0x00,
83 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00,
84 0x7c, 0x00, 0xff, 0x01, 0xff, 0x01, 0xef, 0x01};
85
86 static Curs cursors[BUTCUR_NUM];
87
88 static void draw(ButRcur *rc);
89 static void erase(ButRcur *rc);
90 static void butRcur_hideForRedraw(ButRcur *rc, int winId, int x,int y,
91 int w,int h);
92
93
butEnv_rcInit(ButEnv * env)94 void butEnv_rcInit(ButEnv *env) {
95 Drawable d = RootWindow(env->dpy, DefaultScreen(env->dpy));
96 static bool first_time = TRUE;
97 ButCur i;
98 int dataWidth, j, k;
99
100 if (first_time) {
101 first_time = FALSE;
102 for (i = butCur_idle; i < butCur_bogus; ++i)
103 cursors[i].pic = NULL;
104
105 cursors[butCur_idle].fontcurnum = XC_left_ptr;
106 cursors[butCur_idle].hotX = 1;
107 cursors[butCur_idle].hotY = 1;
108 cursors[butCur_idle].w = 16;
109 cursors[butCur_idle].h = 16;
110 cursors[butCur_idle].pic = ntp_bits;
111 cursors[butCur_idle].mask = ntm_bits;
112
113 cursors[butCur_twitch].fontcurnum = XC_arrow;
114 cursors[butCur_twitch].hotX = 14;
115 cursors[butCur_twitch].hotY = 1;
116 cursors[butCur_twitch].w = 16;
117 cursors[butCur_twitch].h = 16;
118 cursors[butCur_twitch].pic = tp_bits;
119 cursors[butCur_twitch].mask = tm_bits;
120
121 cursors[butCur_text].fontcurnum = XC_xterm;
122 cursors[butCur_text].hotX = 4;
123 cursors[butCur_text].hotY = 8;
124 cursors[butCur_text].w = 16;
125 cursors[butCur_text].h = 16;
126 cursors[butCur_text].pic = txtp_bits;
127 cursors[butCur_text].mask = txtm_bits;
128
129 cursors[butCur_up].fontcurnum = XC_sb_up_arrow;
130 cursors[butCur_up].hotX = 14;
131 cursors[butCur_up].hotY = 14;
132 cursors[butCur_up].w = 16;
133 cursors[butCur_up].h = 16;
134 cursors[butCur_up].pic = ntp_bits;
135 cursors[butCur_up].mask = ntm_bits;
136
137 cursors[butCur_down].fontcurnum = XC_sb_down_arrow;
138 cursors[butCur_down].hotX = 14;
139 cursors[butCur_down].hotY = 14;
140 cursors[butCur_down].w = 16;
141 cursors[butCur_down].h = 16;
142 cursors[butCur_down].pic = ntp_bits;
143 cursors[butCur_down].mask = ntm_bits;
144
145 cursors[butCur_left].fontcurnum = XC_sb_left_arrow;
146 cursors[butCur_left].hotX = 14;
147 cursors[butCur_left].hotY = 14;
148 cursors[butCur_left].w = 16;
149 cursors[butCur_left].h = 16;
150 cursors[butCur_left].pic = ntp_bits;
151 cursors[butCur_left].mask = ntm_bits;
152
153 cursors[butCur_right].fontcurnum = XC_sb_right_arrow;
154 cursors[butCur_right].hotX = 14;
155 cursors[butCur_right].hotY = 14;
156 cursors[butCur_right].w = 16;
157 cursors[butCur_right].h = 16;
158 cursors[butCur_right].pic = ntp_bits;
159 cursors[butCur_right].mask = ntm_bits;
160
161 cursors[butCur_lr].fontcurnum = XC_sb_h_double_arrow;
162 cursors[butCur_lr].hotX = 14;
163 cursors[butCur_lr].hotY = 14;
164 cursors[butCur_lr].w = 16;
165 cursors[butCur_lr].h = 16;
166 cursors[butCur_lr].pic = ntp_bits;
167 cursors[butCur_lr].mask = ntm_bits;
168
169 cursors[butCur_ud].fontcurnum = XC_sb_v_double_arrow;
170 cursors[butCur_ud].hotX = 14;
171 cursors[butCur_ud].hotY = 14;
172 cursors[butCur_ud].w = 16;
173 cursors[butCur_ud].h = 16;
174 cursors[butCur_ud].pic = ntp_bits;
175 cursors[butCur_ud].mask = ntm_bits;
176
177 cursors[butCur_grab].fontcurnum = XC_fleur;
178 cursors[butCur_grab].hotX = 14;
179 cursors[butCur_grab].hotY = 14;
180 cursors[butCur_grab].w = 16;
181 cursors[butCur_grab].h = 16;
182 cursors[butCur_grab].pic = ntp_bits;
183 cursors[butCur_grab].mask = ntm_bits;
184 }
185
186 for (i = butCur_idle; i < butCur_bogus; ++i) {
187 /* "Grey out" the remote cursors. */
188 dataWidth = (cursors[i].w + 7) / 8;
189 for (j = 0; j < cursors[i].h; j += 2) {
190 for (k = 0; k < dataWidth; ++k) {
191 cursors[i].mask[j*dataWidth + k] &= 0x55;
192 if (j+1 < cursors[i].h) {
193 cursors[i].mask[(j+1)*dataWidth + k] &= 0xaa;
194 }
195 }
196 }
197 env->cursors[i] = XCreateFontCursor(env->dpy, cursors[i].fontcurnum);
198 env->cpic[i] = XCreateBitmapFromData(env->dpy, d, cursors[i].pic,
199 cursors[i].w, cursors[i].h);
200 env->cmask[i] = XCreateBitmapFromData(env->dpy, d, cursors[i].mask,
201 cursors[i].w, cursors[i].h);
202 }
203 env->curnum = butCur_idle;
204 env->curwin = None;
205 env->curhold = NULL;
206 env->curlast = butCur_bogus;
207 }
208
209
210 /* Erase the cursor if it is in the area specified. */
butRcur_create(ButRcur * rc,ButEnv * env)211 void butRcur_create(ButRcur *rc, ButEnv *env) {
212 MAGIC_SET(rc);
213 rc->env = env;
214 rc->winId = -2;
215 rc->drawn = FALSE;
216 rc->under = XCreatePixmap(env->dpy, DefaultRootWindow(env->dpy),
217 16,16, env->depth);
218 }
219
220
butRcur_move(ButRcur * rc,int winId,int rx,int ry,int rw,int rh,ButCur type)221 void butRcur_move(ButRcur *rc, int winId, int rx,int ry, int rw,int rh,
222 ButCur type) {
223 ButEnv *env = rc->env;
224
225 assert(MAGIC(rc));
226 if ((winId < 0) || (winId >= env->maxWinIds))
227 winId = -2;
228 else if (env->id2Win[winId] == NULL)
229 winId = -2;
230 if ((winId == rc->winId) && (rx == rc->rx) && (ry == rc->ry) &&
231 (rw == rc->rw) && (rh == rc->rh) && (type == rc->type))
232 return;
233 if (rc->drawn)
234 erase(rc);
235 rc->winId = winId;
236 rc->rx = rx;
237 rc->ry = ry;
238 rc->rw = rw;
239 rc->rh = rh;
240 rc->type = type;
241 if (winId != -2) {
242 rc->lx = (rx * env->id2Win[winId]->w + rw/2) / rw - cursors[type].hotX;
243 rc->ly = (ry * env->id2Win[winId]->h + rh/2) / rh - cursors[type].hotY;
244 draw(rc);
245 }
246 }
247
248
butRcur_redraw(ButEnv * env,int winId,int x,int y,int w,int h)249 void butRcur_redraw(ButEnv *env, int winId, int x,int y, int w,int h) {
250 int i;
251
252 if (winId == -2)
253 return;
254 for (i = 0; i < env->numPartners; ++i) {
255 if (env->partners[i]) {
256 if (butRnet_valid(env->partners[i]) &&
257 (winId == env->partners[i]->rc.winId))
258 butRcur_hideForRedraw(&env->partners[i]->rc, winId, x,y, w,h);
259 }
260 }
261 }
262
263
butRcur_hideForRedraw(ButRcur * rc,int winId,int x,int y,int w,int h)264 static void butRcur_hideForRedraw(ButRcur *rc, int winId, int x,int y,
265 int w,int h) {
266 assert(MAGIC(rc));
267 if (rc->drawn && (rc->winId == winId) &&
268 (x < rc->lx+16) &&
269 (y < rc->ly+16) &&
270 (x+w > rc->lx) && (y+h > rc->ly)) {
271 /* We need to erase it. Will the redraw erase it for us? */
272 if ((x <= rc->lx) && (y <= rc->ly) &&
273 (x+w >= rc->lx+16) &&
274 (y+h >= rc->ly+16)) {
275 rc->drawn = FALSE;
276 } else
277 erase(rc);
278 }
279 }
280
281
282 /* xio is the I/O context that the move got reported in. */
draw(ButRcur * rc)283 static void draw(ButRcur *rc) {
284 ButEnv *env = rc->env;
285
286 assert(!rc->drawn);
287 assert(MAGIC(rc));
288 XCopyArea(env->dpy, env->id2Win[rc->winId]->win, rc->under, env->gc2,
289 rc->lx,rc->ly, 16,16, 0,0);
290 if (!env->colorp)
291 XSetFillStyle(env->dpy, env->gc2, FillSolid);
292 XSetClipMask(env->dpy, env->gc2, env->cmask[rc->type]);
293 XSetClipOrigin(env->dpy, env->gc2, rc->lx,rc->ly);
294 XSetForeground(env->dpy, env->gc2, env->colors[BUT_FG]);
295 XSetBackground(env->dpy, env->gc2, env->colors[BUT_LIT]);
296 XCopyPlane(env->dpy, env->cpic[rc->type],env->id2Win[rc->winId]->win,
297 env->gc2, 0,0, 16,16, rc->lx,rc->ly, 1L);
298 XSetClipMask(env->dpy, env->gc2, None);
299 if (!env->colorp)
300 XSetFillStyle(env->dpy, env->gc2, FillTiled);
301 rc->drawn = TRUE;
302 }
303
304
erase(ButRcur * rc)305 static void erase(ButRcur *rc) {
306 ButEnv *env = rc->env;
307
308 assert(MAGIC(rc));
309 assert(rc->drawn);
310 XCopyArea(env->dpy, rc->under, env->id2Win[rc->winId]->win, env->gc2,
311 0,0, 16,16, rc->lx,rc->ly);
312 rc->drawn = FALSE;
313 }
314
315
316 /* Change the cursor to make it twitched or not twitched. */
butEnv_setCursor(ButEnv * env,But * but,ButCur newcursor)317 void butEnv_setCursor(ButEnv *env, But *but, ButCur newcursor) {
318 if (newcursor == butCur_idle) {
319 if (but == env->curhold) {
320 env->curnum = newcursor;
321 env->curhold = NULL;
322 }
323 } else {
324 env->curnum = newcursor;
325 env->curhold = but;
326 }
327 env->curwin = but->win->physWin;
328 }
329
330
331 /* Set up any cursor changes that may have occurred. */
butEnv_rcActivate(ButEnv * env)332 void butEnv_rcActivate(ButEnv *env) {
333 int i;
334
335 if ((env->curlast != env->curnum) && (env->curwin != None)) {
336 assert(env->curnum < butCur_bogus);
337 env->curlast = env->curnum;
338 XDefineCursor(env->dpy, env->curwin, env->cursors[env->curlast]);
339 butRnet_mMove(env, -1, -1,-1, -1,-1, env->curnum);
340 }
341 for (i = 0; i < env->numPartners; ++i) {
342 if (env->partners[i]) {
343 if (butRnet_valid(env->partners[i]) &&
344 (env->partners[i]->rc.winId >= 0) &&
345 !env->partners[i]->rc.drawn)
346 draw(&env->partners[i]->rc);
347 }
348 }
349 }
350
351
352 #endif
353