1 /*
2 Best viewed with vim5, using ts=4
3
4 wmgeneral was taken from wmppp.
5
6 It has a lot of routines which most of the wm* programs use.
7
8 ------------------------------------------------------------
9
10 Author: Martijn Pieterse (pieterse@xs4all.nl)
11
12 ---
13 CHANGES:
14 ---
15 05/02/2002 (Remi Broemeling, remi@penguinscratch.com)
16 * Added check so that -display or -geometry with no arguments at the
17 end of argv doesn't case a seg fault.
18 14/09/1998 (Dave Clark, clarkd@skyia.com)
19 * Updated createXBMfromXPM routine
20 * Now supports >256 colors
21 11/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
22 * Removed a bug from parse_rcfile. You could
23 not use "start" in a command if a label was
24 also start.
25 * Changed the needed geometry string.
26 We don't use window size, and don't support
27 negative positions.
28 03/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
29 * Added parse_rcfile2
30 02/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
31 * Added -geometry support (untested)
32 28/08/1998 (Martijn Pieterse, pieterse@xs4all.nl)
33 * Added createXBMfromXPM routine
34 * Saves a lot of work with changing xpm's.
35 02/05/1998 (Martijn Pieterse, pieterse@xs4all.nl)
36 * changed the read_rc_file to parse_rcfile, as suggested by Marcelo E. Magallon
37 * debugged the parse_rc file.
38 30/04/1998 (Martijn Pieterse, pieterse@xs4all.nl)
39 * Ripped similar code from all the wm* programs,
40 and put them in a single file.
41
42 */
43
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <unistd.h>
48 #include <ctype.h>
49 #include <stdarg.h>
50
51 #include <X11/Xlib.h>
52 #include <X11/xpm.h>
53 #include <X11/extensions/shape.h>
54
55 #include "wmgeneral.h"
56
57 /*****************/
58 /* X11 Variables */
59 /*****************/
60
61 Window Root;
62 int screen;
63 int x_fd;
64 int d_depth;
65 XSizeHints mysizehints;
66 XWMHints mywmhints;
67 Pixel back_pix, fore_pix;
68 char *Geometry = "";
69 Window iconwin, win;
70 GC NormalGC;
71 XpmIcon wmgen;
72 Pixmap pixmask;
73
74 /*****************/
75 /* Mouse Regions */
76 /*****************/
77
78 typedef struct {
79 int enable;
80 int top;
81 int bottom;
82 int left;
83 int right;
84 } MOUSE_REGION;
85
86 MOUSE_REGION mouse_region[MAX_MOUSE_REGION];
87
88 /***********************/
89 /* Function Prototypes */
90 /***********************/
91
92 static void GetXPM(XpmIcon *, char **);
93 static Pixel GetColor(char *);
94 void RedrawWindow(void);
95 void AddMouseRegion(int, int, int, int, int);
96 int CheckMouseRegion(int, int);
97
98 /*******************************************************************************\
99 |* parse_rcfile *|
100 \*******************************************************************************/
101
parse_rcfile(const char * filename,rckeys * keys)102 void parse_rcfile(const char *filename, rckeys *keys) {
103
104 char *p,*q;
105 char temp[128];
106 char *tokens = " :\t\n";
107 FILE *fp;
108 int i,key;
109
110 fp = fopen(filename, "r");
111 if (fp) {
112 while (fgets(temp, 128, fp)) {
113 key = 0;
114 q = strdup(temp);
115 q = strtok(q, tokens);
116 while (key >= 0 && keys[key].label) {
117 if ((!strcmp(q, keys[key].label))) {
118 p = strstr(temp, keys[key].label);
119 p += strlen(keys[key].label);
120 p += strspn(p, tokens);
121 if ((i = strcspn(p, "#\n"))) p[i] = 0;
122 free(*keys[key].var);
123 *keys[key].var = strdup(p);
124 key = -1;
125 } else key++;
126 }
127 free(q);
128 }
129 fclose(fp);
130 }
131 }
132
133 /*******************************************************************************\
134 |* parse_rcfile2 *|
135 \*******************************************************************************/
136
parse_rcfile2(const char * filename,rckeys2 * keys)137 void parse_rcfile2(const char *filename, rckeys2 *keys) {
138
139 char *p;
140 char temp[128];
141 char *tokens = " :\t\n";
142 FILE *fp;
143 int i,key;
144 char *family = NULL;
145
146 fp = fopen(filename, "r");
147 if (fp) {
148 while (fgets(temp, 128, fp)) {
149 key = 0;
150 while (key >= 0 && keys[key].label) {
151 if ((p = strstr(temp, keys[key].label))) {
152 p += strlen(keys[key].label);
153 p += strspn(p, tokens);
154 if ((i = strcspn(p, "#\n"))) p[i] = 0;
155 free(*keys[key].var);
156 *keys[key].var = strdup(p);
157 key = -1;
158 } else key++;
159 }
160 }
161 fclose(fp);
162 }
163 free(family);
164 }
165
166
167 /*******************************************************************************\
168 |* GetXPM *|
169 \*******************************************************************************/
170
GetXPM(XpmIcon * wmgen,char * pixmap_bytes[])171 static void GetXPM(XpmIcon *wmgen, char *pixmap_bytes[]) {
172
173 XWindowAttributes attributes;
174 int err;
175
176 /* For the colormap */
177 XGetWindowAttributes(display, Root, &attributes);
178
179 wmgen->attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
180
181 err = XpmCreatePixmapFromData(display, Root, pixmap_bytes, &(wmgen->pixmap),
182 &(wmgen->mask), &(wmgen->attributes));
183
184 if (err != XpmSuccess) {
185 fprintf(stderr, "Not enough free colorcells.\n");
186 exit(1);
187 }
188 }
189
190 /*******************************************************************************\
191 |* GetColor *|
192 \*******************************************************************************/
193
GetColor(char * name)194 static Pixel GetColor(char *name) {
195
196 XColor color;
197 XWindowAttributes attributes;
198
199 XGetWindowAttributes(display, Root, &attributes);
200
201 color.pixel = 0;
202 if (!XParseColor(display, attributes.colormap, name, &color)) {
203 fprintf(stderr, "wm.app: can't parse %s.\n", name);
204 } else if (!XAllocColor(display, attributes.colormap, &color)) {
205 fprintf(stderr, "wm.app: can't allocate %s.\n", name);
206 }
207 return color.pixel;
208 }
209
210 /*******************************************************************************\
211 |* flush_expose *|
212 \*******************************************************************************/
213
flush_expose(Window w)214 static int flush_expose(Window w) {
215
216 XEvent dummy;
217 int i=0;
218
219 while (XCheckTypedWindowEvent(display, w, Expose, &dummy))
220 i++;
221
222 return i;
223 }
224
225 /*******************************************************************************\
226 |* RedrawWindow *|
227 \*******************************************************************************/
228
RedrawWindow(void)229 void RedrawWindow(void) {
230
231 flush_expose(iconwin);
232 XCopyArea(display, wmgen.pixmap, iconwin, NormalGC,
233 0,0, wmgen.attributes.width, wmgen.attributes.height, 0,0);
234 flush_expose(win);
235 XCopyArea(display, wmgen.pixmap, win, NormalGC,
236 0,0, wmgen.attributes.width, wmgen.attributes.height, 0,0);
237 }
238
239 /*******************************************************************************\
240 |* RedrawWindowXY *|
241 \*******************************************************************************/
242
RedrawWindowXY(int x,int y)243 void RedrawWindowXY(int x, int y) {
244
245 flush_expose(iconwin);
246 XCopyArea(display, wmgen.pixmap, iconwin, NormalGC,
247 x,y, wmgen.attributes.width, wmgen.attributes.height, 0,0);
248 flush_expose(win);
249 XCopyArea(display, wmgen.pixmap, win, NormalGC,
250 x,y, wmgen.attributes.width, wmgen.attributes.height, 0,0);
251 }
252
253 /*******************************************************************************\
254 |* AddMouseRegion *|
255 \*******************************************************************************/
256
AddMouseRegion(int index,int left,int top,int right,int bottom)257 void AddMouseRegion(int index, int left, int top, int right, int bottom) {
258
259 if (index < MAX_MOUSE_REGION) {
260 mouse_region[index].enable = 1;
261 mouse_region[index].top = top;
262 mouse_region[index].left = left;
263 mouse_region[index].bottom = bottom;
264 mouse_region[index].right = right;
265 }
266 }
267
268 /*******************************************************************************\
269 |* CheckMouseRegion *|
270 \*******************************************************************************/
271
CheckMouseRegion(int x,int y)272 int CheckMouseRegion(int x, int y) {
273
274 int i;
275 int found;
276
277 found = 0;
278
279 for (i=0; i<MAX_MOUSE_REGION && !found; i++) {
280 if (mouse_region[i].enable &&
281 x <= mouse_region[i].right &&
282 x >= mouse_region[i].left &&
283 y <= mouse_region[i].bottom &&
284 y >= mouse_region[i].top)
285 found = 1;
286 }
287 if (!found) return -1;
288 return (i-1);
289 }
290
291 /*******************************************************************************\
292 |* createXBMfromXPM *|
293 \*******************************************************************************/
createXBMfromXPM(char * xbm,char ** xpm,int sx,int sy)294 void createXBMfromXPM(char *xbm, char **xpm, int sx, int sy) {
295
296 int i,j,k;
297 int width, height, numcol, depth;
298 int zero=0;
299 unsigned char bwrite;
300 int bcount;
301 int curpixel;
302
303 sscanf(*xpm, "%d %d %d %d", &width, &height, &numcol, &depth);
304
305
306 for (k=0; k!=depth; k++)
307 {
308 zero <<=8;
309 zero |= xpm[1][k];
310 }
311
312 for (i=numcol+1; i < numcol+sy+1; i++) {
313 bcount = 0;
314 bwrite = 0;
315 for (j=0; j<sx*depth; j+=depth) {
316 bwrite >>= 1;
317
318 curpixel=0;
319 for (k=0; k!=depth; k++)
320 {
321 curpixel <<=8;
322 curpixel |= xpm[i][j+k];
323 }
324
325 if ( curpixel != zero ) {
326 bwrite += 128;
327 }
328 bcount++;
329 if (bcount == 8) {
330 *xbm = bwrite;
331 xbm++;
332 bcount = 0;
333 bwrite = 0;
334 }
335 }
336 }
337 }
338
339 /*******************************************************************************\
340 |* copyXPMArea *|
341 \*******************************************************************************/
342
copyXPMArea(int x,int y,int sx,int sy,int dx,int dy)343 void copyXPMArea(int x, int y, int sx, int sy, int dx, int dy) {
344
345 XCopyArea(display, wmgen.pixmap, wmgen.pixmap, NormalGC, x, y, sx, sy, dx, dy);
346
347 }
348
349 /*******************************************************************************\
350 |* copyXBMArea *|
351 \*******************************************************************************/
352
copyXBMArea(int x,int y,int sx,int sy,int dx,int dy)353 void copyXBMArea(int x, int y, int sx, int sy, int dx, int dy) {
354
355 XCopyArea(display, wmgen.mask, wmgen.pixmap, NormalGC, x, y, sx, sy, dx, dy);
356 }
357
358
359 /*******************************************************************************\
360 |* setMaskXY *|
361 \*******************************************************************************/
362
setMaskXY(int x,int y)363 void setMaskXY(int x, int y) {
364
365 XShapeCombineMask(display, win, ShapeBounding, x, y, pixmask, ShapeSet);
366 XShapeCombineMask(display, iconwin, ShapeBounding, x, y, pixmask, ShapeSet);
367 }
368
369 /*******************************************************************************\
370 |* openXwindow *|
371 \*******************************************************************************/
openXwindow(int argc,char * argv[],char * pixmap_bytes[],char * pixmask_bits,int pixmask_width,int pixmask_height)372 void openXwindow(int argc, char *argv[], char *pixmap_bytes[], char *pixmask_bits, int pixmask_width, int pixmask_height) {
373
374 unsigned int borderwidth = 1;
375 XClassHint classHint;
376 char *display_name = NULL;
377 char *wname = argv[0];
378 XTextProperty name;
379
380 XGCValues gcv;
381 unsigned long gcm;
382
383 char *geometry = NULL;
384
385 int dummy=0;
386 int i, wx, wy;
387
388 for (i=1; argv[i]; i++) {
389 if (!strcmp(argv[i], "-display")) {
390 if ((i + 1) < argc) {
391 display_name = argv[i+1];
392 i++;
393 }
394 }
395 if (!strcmp(argv[i], "-geometry")) {
396 if ((i + 1) < argc) {
397 geometry = argv[i+1];
398 i++;
399 }
400 }
401 }
402
403 if (!(display = XOpenDisplay(display_name))) {
404 fprintf(stderr, "%s: can't open display %s\n",
405 wname, XDisplayName(display_name));
406 exit(1);
407 }
408 screen = DefaultScreen(display);
409 Root = RootWindow(display, screen);
410 d_depth = DefaultDepth(display, screen);
411 x_fd = XConnectionNumber(display);
412
413 /* Convert XPM to XImage */
414 GetXPM(&wmgen, pixmap_bytes);
415
416 /* Create a window to hold the stuff */
417 mysizehints.flags = USSize | USPosition;
418 mysizehints.x = 0;
419 mysizehints.y = 0;
420
421 back_pix = GetColor("white");
422 fore_pix = GetColor("black");
423
424 XWMGeometry(display, screen, Geometry, NULL, borderwidth, &mysizehints,
425 &mysizehints.x, &mysizehints.y,&mysizehints.width,&mysizehints.height, &dummy);
426
427 mysizehints.width = 16;
428 mysizehints.height = 16;
429
430 win = XCreateSimpleWindow(display, Root, mysizehints.x, mysizehints.y,
431 mysizehints.width, mysizehints.height, borderwidth, fore_pix, back_pix);
432
433 iconwin = XCreateSimpleWindow(display, win, mysizehints.x, mysizehints.y,
434 mysizehints.width, mysizehints.height, borderwidth, fore_pix, back_pix);
435
436 /* Activate hints */
437 XSetWMNormalHints(display, win, &mysizehints);
438 classHint.res_name = wname;
439 classHint.res_class = wname;
440 XSetClassHint(display, win, &classHint);
441
442 XSelectInput(display, win, ButtonPressMask | ExposureMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask);
443 XSelectInput(display, iconwin, ButtonPressMask | ExposureMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask);
444
445 if (XStringListToTextProperty(&wname, 1, &name) == 0) {
446 fprintf(stderr, "%s: can't allocate window name\n", wname);
447 exit(1);
448 }
449
450 XSetWMName(display, win, &name);
451
452 /* Create GC for drawing */
453
454 gcm = GCForeground | GCBackground | GCGraphicsExposures;
455 gcv.foreground = fore_pix;
456 gcv.background = back_pix;
457 gcv.graphics_exposures = 0;
458 NormalGC = XCreateGC(display, Root, gcm, &gcv);
459
460 /* ONLYSHAPE ON */
461
462 pixmask = XCreateBitmapFromData(display, win, pixmask_bits, pixmask_width, pixmask_height);
463
464 XShapeCombineMask(display, win, ShapeBounding, 0, 0, pixmask, ShapeSet);
465 XShapeCombineMask(display, iconwin, ShapeBounding, 0, 0, pixmask, ShapeSet);
466
467 /* ONLYSHAPE OFF */
468
469 mywmhints.initial_state = WithdrawnState;
470 mywmhints.icon_window = iconwin;
471 mywmhints.icon_x = mysizehints.x;
472 mywmhints.icon_y = mysizehints.y;
473 mywmhints.window_group = win;
474 mywmhints.flags = StateHint | IconWindowHint | IconPositionHint | WindowGroupHint;
475
476 XSetWMHints(display, win, &mywmhints);
477
478 XSetCommand(display, win, argv, argc);
479 XMapWindow(display, win);
480
481 if (geometry) {
482 if (sscanf(geometry, "+%d+%d", &wx, &wy) != 2) {
483 fprintf(stderr, "Bad geometry string.\n");
484 exit(1);
485 }
486 XMoveWindow(display, win, wx, wy);
487 }
488 }
489