Add missing libraries to examples' Makefiles
[dockapps.git] / wmwork / src / wmgeneral.c
blob1dafa82288efffce4c5c017d9c2b0abc5e3a996f
1 /*
2 Best viewed with vim5, using ts=4
4 wmgeneral was taken from wmppp.
6 It has a lot of routines which most of the wm* programs use.
8 ------------------------------------------------------------
10 Author: Martijn Pieterse (pieterse@xs4all.nl)
12 ---
13 CHANGES:
14 ---
15 25/08/2002 (Martin A. Godisch, godisch@tcs.inf.tu-dresden.de)
16 * Fixed --display handling.
17 23/08/2002 (Martin A. Godisch, godisch@tcs.inf.tu-dresden.de)
18 * Fixed --geometry handling.
19 05/07/2002 (Martin A. Godisch, godisch@tcs.inf.tu-dresden.de)
20 * Fixed --geometry handling.
21 23/05/2002 (Martin A. Godisch, godisch@tcs.inf.tu-dresden.de)
22 * Added missing prototype for parse_rcfile2.
23 18/04/2002 (Martin A. Godisch, godisch@tcs.inf.tu-dresden.de)
24 * Improved bugfix in createXBMfromXPM from 17/04/2002.
25 17/04/2002 (Martin A. Godisch, godisch@tcs.inf.tu-dresden.de)
26 * Fixed a bug in createXBMfromXPM, introduced on 10/03/2002.
27 31/03/2002 (Martin A. Godisch, godisch@tcs.inf.tu-dresden.de)
28 * Some changes to make this file work with wmweather v1.31 and v2.0:
29 + extracted initXwindow from openXwindow,
30 + added XpmColorSymbols to valuemask in GetXPM,
31 + added colorspec to colorsymbols in openXwindow.
32 10/03/2002 (Martin A. Godisch, godisch@tcs.inf.tu-dresden.de)
33 * Added > 1 char/pixel support in createXBMfromXPM.
34 09/03/2002 (Martin A. Godisch, godisch@tcs.inf.tu-dresden.de)
35 * Added EnterWindowMask, LeaveWindowMask, KeyPressMask,
36 KeyReleaseMask in XSelectInput
37 11/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
38 * Removed a bug from parse_rcfile. You could
39 not use "start" in a command if a label was
40 also start.
41 * Changed the needed geometry string.
42 We don't use window size, and don't support
43 negative positions.
44 03/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
45 * Added parse_rcfile2
46 02/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
47 * Added -geometry support (untested)
48 28/08/1998 (Martijn Pieterse, pieterse@xs4all.nl)
49 * Added createXBMfromXPM routine
50 * Saves a lot of work with changing xpm's.
51 02/05/1998 (Martijn Pieterse, pieterse@xs4all.nl)
52 * changed the read_rc_file to parse_rcfile, as suggested by Marcelo E. Magallon
53 * debugged the parse_rc file.
54 30/04/1998 (Martijn Pieterse, pieterse@xs4all.nl)
55 * Ripped similar code from all the wm* programs,
56 and put them in a single file.
60 #include <stdlib.h>
61 #include <stdio.h>
62 #include <string.h>
63 #include <unistd.h>
64 #include <ctype.h>
65 #include <stdarg.h>
67 #include <X11/Xlib.h>
68 #include <X11/xpm.h>
69 #include <X11/extensions/shape.h>
71 #include "wmgeneral.h"
73 /*****************/
74 /* X11 Variables */
75 /*****************/
77 Window Root;
78 int screen;
79 int x_fd;
80 int d_depth;
81 XSizeHints mysizehints;
82 XWMHints mywmhints;
83 Pixel back_pix, fore_pix;
84 Window iconwin, win;
85 GC NormalGC;
86 XpmIcon wmgen;
87 Pixmap pixmask;
89 /*****************/
90 /* Mouse Regions */
91 /*****************/
93 typedef struct {
94 int enable;
95 int top;
96 int bottom;
97 int left;
98 int right;
99 } MOUSE_REGION;
101 MOUSE_REGION mouse_region[MAX_MOUSE_REGION];
103 /***********************/
104 /* Function Prototypes */
105 /***********************/
107 static void GetXPM(XpmIcon *, char **);
108 static Pixel GetColor(char *);
109 void RedrawWindow(void);
110 void AddMouseRegion(unsigned, int, int, int, int);
111 int CheckMouseRegion(int, int);
113 /*******************************************************************************\
114 |* parse_rcfile *|
115 \*******************************************************************************/
117 void parse_rcfile(const char *filename, rckeys *keys) {
119 char *p,*q;
120 char temp[128];
121 char *tokens = " :\t\n";
122 FILE *fp;
123 int i,key;
125 fp = fopen(filename, "r");
126 if (fp) {
127 while (fgets(temp, 128, fp)) {
128 key = 0;
129 q = strdup(temp);
130 q = strtok(q, tokens);
131 while (key >= 0 && keys[key].label) {
132 if ((!strcmp(q, keys[key].label))) {
133 p = strstr(temp, keys[key].label);
134 p += strlen(keys[key].label);
135 p += strspn(p, tokens);
136 if ((i = strcspn(p, "#\n"))) p[i] = 0;
137 free(*keys[key].var);
138 *keys[key].var = strdup(p);
139 key = -1;
140 } else key++;
142 free(q);
144 fclose(fp);
148 /*******************************************************************************\
149 |* parse_rcfile2 *|
150 \*******************************************************************************/
152 void parse_rcfile2(const char *filename, rckeys2 *keys) {
154 char *p;
155 char temp[128];
156 char *tokens = " :\t\n";
157 FILE *fp;
158 int i,key;
159 char *family = NULL;
161 fp = fopen(filename, "r");
162 if (fp) {
163 while (fgets(temp, 128, fp)) {
164 key = 0;
165 while (key >= 0 && keys[key].label) {
166 if ((p = strstr(temp, keys[key].label))) {
167 p += strlen(keys[key].label);
168 p += strspn(p, tokens);
169 if ((i = strcspn(p, "#\n"))) p[i] = 0;
170 free(*keys[key].var);
171 *keys[key].var = strdup(p);
172 key = -1;
173 } else key++;
176 fclose(fp);
178 free(family);
182 /*******************************************************************************\
183 |* GetXPM *|
184 \*******************************************************************************/
186 static void GetXPM(XpmIcon *wmgen, char *pixmap_bytes[]) {
188 XWindowAttributes attributes;
189 int err;
191 /* For the colormap */
192 XGetWindowAttributes(display, Root, &attributes);
194 wmgen->attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions | XpmColorSymbols);
196 err = XpmCreatePixmapFromData(display, Root, pixmap_bytes, &(wmgen->pixmap),
197 &(wmgen->mask), &(wmgen->attributes));
199 if (err != XpmSuccess) {
200 fprintf(stderr, "wm.app: not enough free colorcells.\n");
201 exit(1);
205 /*******************************************************************************\
206 |* GetColor *|
207 \*******************************************************************************/
209 static Pixel GetColor(char *name) {
211 XColor color;
212 XWindowAttributes attributes;
214 XGetWindowAttributes(display, Root, &attributes);
216 color.pixel = 0;
217 if (!XParseColor(display, attributes.colormap, name, &color)) {
218 fprintf(stderr, "wm.app: can't parse %s.\n", name);
219 } else if (!XAllocColor(display, attributes.colormap, &color)) {
220 fprintf(stderr, "wm.app: can't allocate %s.\n", name);
222 return color.pixel;
225 /*******************************************************************************\
226 |* flush_expose *|
227 \*******************************************************************************/
229 static int flush_expose(Window w) {
231 XEvent dummy;
232 int i=0;
234 while (XCheckTypedWindowEvent(display, w, Expose, &dummy))
235 i++;
237 return i;
240 /*******************************************************************************\
241 |* RedrawWindow *|
242 \*******************************************************************************/
244 void RedrawWindow(void) {
246 flush_expose(iconwin);
247 XCopyArea(display, wmgen.pixmap, iconwin, NormalGC,
248 0,0, wmgen.attributes.width, wmgen.attributes.height, 0,0);
249 flush_expose(win);
250 XCopyArea(display, wmgen.pixmap, win, NormalGC,
251 0,0, wmgen.attributes.width, wmgen.attributes.height, 0,0);
254 /*******************************************************************************\
255 |* RedrawWindowXY *|
256 \*******************************************************************************/
258 void RedrawWindowXY(int x, int y) {
260 flush_expose(iconwin);
261 XCopyArea(display, wmgen.pixmap, iconwin, NormalGC,
262 x,y, wmgen.attributes.width, wmgen.attributes.height, 0,0);
263 flush_expose(win);
264 XCopyArea(display, wmgen.pixmap, win, NormalGC,
265 x,y, wmgen.attributes.width, wmgen.attributes.height, 0,0);
268 /*******************************************************************************\
269 |* AddMouseRegion *|
270 \*******************************************************************************/
272 void AddMouseRegion(unsigned index, int left, int top, int right, int bottom) {
274 if (index < MAX_MOUSE_REGION) {
275 mouse_region[index].enable = 1;
276 mouse_region[index].top = top;
277 mouse_region[index].left = left;
278 mouse_region[index].bottom = bottom;
279 mouse_region[index].right = right;
283 /*******************************************************************************\
284 |* CheckMouseRegion *|
285 \*******************************************************************************/
287 int CheckMouseRegion(int x, int y) {
289 int i;
290 int found;
292 found = 0;
294 for (i=0; i<MAX_MOUSE_REGION && !found; i++) {
295 if (mouse_region[i].enable &&
296 x <= mouse_region[i].right &&
297 x >= mouse_region[i].left &&
298 y <= mouse_region[i].bottom &&
299 y >= mouse_region[i].top)
300 found = 1;
302 if (!found) return -1;
303 return (i-1);
306 /*******************************************************************************\
307 |* createXBMfromXPM *|
308 \*******************************************************************************/
310 void createXBMfromXPM(char *xbm, char **xpm, int sx, int sy) {
312 int i,j;
313 int width, height, numcol, chars;
314 char *zero, *color, *pos;
315 unsigned char bwrite;
316 int bcount;
319 sscanf(*xpm, "%d %d %d %d", &width, &height, &numcol, &chars);
321 zero = malloc(chars * sizeof(char));
322 color = malloc(chars * sizeof(char));
323 memcpy(zero, xpm[1], chars);
324 for (i = numcol+1; i < numcol+sy+1; i++) {
325 bcount = 0;
326 bwrite = 0;
327 pos = xpm[i];
328 for (j = 0; j < sx; j++) {
329 bwrite >>= 1;
330 memcpy(color, pos, chars);
331 if (memcmp(color, zero, chars)) {
332 bwrite += 128;
334 bcount++;
335 if (bcount == 8) {
336 *xbm = bwrite;
337 xbm++;
338 bcount = 0;
339 bwrite = 0;
341 pos += chars * sizeof(char);
344 free(zero);
345 free(color);
348 /*******************************************************************************\
349 |* copyXPMArea *|
350 \*******************************************************************************/
352 void copyXPMArea(int x, int y, int sx, int sy, int dx, int dy) {
354 XCopyArea(display, wmgen.pixmap, wmgen.pixmap, NormalGC, x, y, sx, sy, dx, dy);
358 /*******************************************************************************\
359 |* copyXBMArea *|
360 \*******************************************************************************/
362 void copyXBMArea(int x, int y, int sx, int sy, int dx, int dy) {
364 XCopyArea(display, wmgen.mask, wmgen.pixmap, NormalGC, x, y, sx, sy, dx, dy);
367 /*******************************************************************************\
368 |* setMaskXY *|
369 \*******************************************************************************/
371 void setMaskXY(int x, int y) {
373 XShapeCombineMask(display, win, ShapeBounding, x, y, pixmask, ShapeSet);
374 XShapeCombineMask(display, iconwin, ShapeBounding, x, y, pixmask, ShapeSet);
377 /*******************************************************************************\
378 |* initXwindow *|
379 \*******************************************************************************/
381 void initXwindow(char *display_name) {
383 if (!(display = XOpenDisplay(display_name))) {
384 fprintf(stderr, "wm.app: can't open display %s\n",
385 XDisplayName(display_name));
386 exit(1);
388 screen = DefaultScreen(display);
389 Root = RootWindow(display, screen);
390 d_depth = DefaultDepth(display, screen);
391 x_fd = XConnectionNumber(display);
395 /*******************************************************************************\
396 |* openXwindow *|
397 \*******************************************************************************/
399 void openXwindow(int argc, char *argv[], char *pixmap_bytes[], char *pixmask_bits, int pixmask_width, int pixmask_height, char *geometry, XpmColorSymbol *colorspec) {
401 unsigned int borderwidth = 1;
402 XClassHint classHint;
403 char *wname = argv[0];
404 XTextProperty name;
406 XGCValues gcv;
407 unsigned long gcm;
409 int dummy=0;
410 int i;
412 /* Convert XPM to XImage */
413 if (colorspec) {
414 for (i = 0; colorspec[i].name; i++)
415 colorspec[i].pixel = GetColor(colorspec[i].value);
416 wmgen.attributes.numsymbols = i;
417 wmgen.attributes.colorsymbols = colorspec;
419 GetXPM(&wmgen, pixmap_bytes);
421 /* Create a window to hold the stuff */
422 mysizehints.flags = USSize | USPosition;
423 mysizehints.x = 0;
424 mysizehints.y = 0;
426 back_pix = GetColor("white");
427 fore_pix = GetColor("black");
429 XWMGeometry(display, screen, geometry, NULL, borderwidth, &mysizehints,
430 &mysizehints.x, &mysizehints.y,&mysizehints.width,&mysizehints.height, &dummy);
432 mysizehints.width = 64;
433 mysizehints.height = 64;
435 win = XCreateSimpleWindow(display, Root, mysizehints.x, mysizehints.y,
436 mysizehints.width, mysizehints.height, borderwidth, fore_pix, back_pix);
438 iconwin = XCreateSimpleWindow(display, win, mysizehints.x, mysizehints.y,
439 mysizehints.width, mysizehints.height, borderwidth, fore_pix, back_pix);
441 /* Activate hints */
442 XSetWMNormalHints(display, win, &mysizehints);
443 classHint.res_name = wname;
444 classHint.res_class = wname;
445 XSetClassHint(display, win, &classHint);
447 XSelectInput(display, win, ButtonPressMask | ExposureMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask | KeyPressMask | KeyReleaseMask);
448 XSelectInput(display, iconwin, ButtonPressMask | ExposureMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask | KeyPressMask | KeyReleaseMask);
450 if (XStringListToTextProperty(&wname, 1, &name) == 0) {
451 fprintf(stderr, "%s: can't allocate window name\n", wname);
452 exit(1);
455 XSetWMName(display, win, &name);
457 /* Create GC for drawing */
459 gcm = GCForeground | GCBackground | GCGraphicsExposures;
460 gcv.foreground = fore_pix;
461 gcv.background = back_pix;
462 gcv.graphics_exposures = 0;
463 NormalGC = XCreateGC(display, Root, gcm, &gcv);
465 /* ONLYSHAPE ON */
467 pixmask = XCreateBitmapFromData(display, win, pixmask_bits, pixmask_width, pixmask_height);
469 XShapeCombineMask(display, win, ShapeBounding, 0, 0, pixmask, ShapeSet);
470 XShapeCombineMask(display, iconwin, ShapeBounding, 0, 0, pixmask, ShapeSet);
472 /* ONLYSHAPE OFF */
474 mywmhints.initial_state = WithdrawnState;
475 mywmhints.icon_window = iconwin;
476 mywmhints.icon_x = mysizehints.x;
477 mywmhints.icon_y = mysizehints.y;
478 mywmhints.window_group = win;
479 mywmhints.flags = StateHint | IconWindowHint | IconPositionHint | WindowGroupHint;
481 XSetWMHints(display, win, &mywmhints);
483 XSetCommand(display, win, argv, argc);
484 XMapWindow(display, win);