2 wmgeneral was taken from wmppp.
4 It has a lot of routines which most of the wm* programs use.
6 ------------------------------------------------------------
8 Copyright (C) 1998 Martijn Pieterse (pieterse@xs4all.nl)
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
28 10/10/2003 (Simon Law, sfllaw@debian.org)
29 * changed the parse_rcfile function to use getline instead of
31 10/14/2000 (Chris Gray, cgray@tribsoft.com)
32 * Removed a bug from parse_rcfile. An extra
33 newline would cause a segfault.
34 14/09/1998 (Dave Clark, clarkd@skyia.com)
35 * Updated createXBMfromXPM routine
36 * Now supports >256 colors
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
41 * Changed the needed geometry string.
42 We don't use window size, and don't support
44 03/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
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
54 * debugged the parse_rc file.
55 30/04/1998 (Martijn Pieterse, pieterse@xs4all.nl)
56 * Ripped similar code from all the wm* programs,
57 and put them in a single file.
61 #include "wmgeneral.h"
62 #include <X11/Xlib.h> /* for XCopyArea, etc */
63 #include <X11/Xutil.h> /* for XSizeHints, XWMHints, etc */
64 #include <X11/extensions/shape.h> /* for XShapeCombineMask */
65 #include <X11/extensions/shapeconst.h> /* for ShapeBounding, ShapeSet */
66 #include <X11/xpm.h> /* for XpmAttributes, Pixel, etc */
67 #include <stddef.h> /* for size_t */
68 #include <stdio.h> /* for fprintf, stderr, NULL, etc */
69 #include <stdlib.h> /* for exit, free */
70 #include <string.h> /* for strcmp, strdup, strcspn, etc */
80 XSizeHints mysizehints
;
82 Pixel back_pix
, fore_pix
;
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(int, int, int, int, int);
111 int CheckMouseRegion(int, int);
113 /*******************************************************************************\
115 \*******************************************************************************/
117 void parse_rcfile(const char *filename
, rckeys
*keys
) {
122 fp
= fopen(filename
, "r");
126 while (fgets(temp
, 128, fp
)) {
128 char *tokens
= " :\t\n";
133 q
= strtok(q
, tokens
);
136 while (key
>= 0 && keys
[key
].label
) {
137 if ((!strcmp(q
, keys
[key
].label
))) {
140 p
= strstr(temp
, keys
[key
].label
);
141 p
+= strlen(keys
[key
].label
);
142 p
+= strspn(p
, tokens
);
143 if ((i
= strcspn(p
, "#\n"))) p
[i
] = '\0';
144 *keys
[key
].var
= strdup(p
);
153 /*******************************************************************************\
155 \*******************************************************************************/
157 void parse_rcfile2(const char *filename
, rckeys2
*keys
) {
161 size_t line_size
= 0;
165 fp
= fopen(filename
, "r");
167 while (getline(&line
, &line_size
, fp
) >= 0) {
171 while (key
>= 0 && keys
[key
].label
) {
172 if ((p
= strstr(line
, keys
[key
].label
))) {
173 char *tokens
= " :\t\n";
176 p
+= strlen(keys
[key
].label
);
177 p
+= strspn(p
, tokens
);
178 if ((i
= strcspn(p
, "#\n"))) p
[i
] = 0;
179 *keys
[key
].var
= strdup(p
);
189 /*******************************************************************************\
191 \*******************************************************************************/
193 static void GetXPM(XpmIcon
*wmgen
, char *pixmap_bytes
[]) {
195 XWindowAttributes attributes
;
198 /* For the colormap */
199 XGetWindowAttributes(display
, Root
, &attributes
);
201 wmgen
->attributes
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
203 err
= XpmCreatePixmapFromData(display
, Root
, pixmap_bytes
, &(wmgen
->pixmap
),
204 &(wmgen
->mask
), &(wmgen
->attributes
));
206 if (err
!= XpmSuccess
) {
207 fprintf(stderr
, "Not enough free colorcells.\n");
212 /*******************************************************************************\
214 \*******************************************************************************/
216 static Pixel
GetColor(char *name
) {
219 XWindowAttributes attributes
;
221 XGetWindowAttributes(display
, Root
, &attributes
);
224 if (!XParseColor(display
, attributes
.colormap
, name
, &color
)) {
225 fprintf(stderr
, "wm.app: can't parse %s.\n", name
);
226 } else if (!XAllocColor(display
, attributes
.colormap
, &color
)) {
227 fprintf(stderr
, "wm.app: can't allocate %s.\n", name
);
232 /*******************************************************************************\
234 \*******************************************************************************/
236 static int flush_expose(Window w
) {
241 while (XCheckTypedWindowEvent(display
, w
, Expose
, &dummy
))
247 /*******************************************************************************\
249 \*******************************************************************************/
251 void RedrawWindow(void) {
253 flush_expose(iconwin
);
254 XCopyArea(display
, wmgen
.pixmap
, iconwin
, NormalGC
,
255 0,0, wmgen
.attributes
.width
, wmgen
.attributes
.height
, 0,0);
257 XCopyArea(display
, wmgen
.pixmap
, win
, NormalGC
,
258 0,0, wmgen
.attributes
.width
, wmgen
.attributes
.height
, 0,0);
261 /*******************************************************************************\
263 \*******************************************************************************/
265 void RedrawWindowXY(int x
, int y
) {
267 flush_expose(iconwin
);
268 XCopyArea(display
, wmgen
.pixmap
, iconwin
, NormalGC
,
269 x
,y
, wmgen
.attributes
.width
, wmgen
.attributes
.height
, 0,0);
271 XCopyArea(display
, wmgen
.pixmap
, win
, NormalGC
,
272 x
,y
, wmgen
.attributes
.width
, wmgen
.attributes
.height
, 0,0);
275 /*******************************************************************************\
277 \*******************************************************************************/
279 void AddMouseRegion(int index
, int left
, int top
, int right
, int bottom
) {
281 if (index
< MAX_MOUSE_REGION
) {
282 mouse_region
[index
].enable
= 1;
283 mouse_region
[index
].top
= top
;
284 mouse_region
[index
].left
= left
;
285 mouse_region
[index
].bottom
= bottom
;
286 mouse_region
[index
].right
= right
;
290 /*******************************************************************************\
291 |* CheckMouseRegion *|
292 \*******************************************************************************/
294 int CheckMouseRegion(int x
, int y
) {
301 for (i
=0; i
<MAX_MOUSE_REGION
&& !found
; i
++) {
302 if (mouse_region
[i
].enable
&&
303 x
<= mouse_region
[i
].right
&&
304 x
>= mouse_region
[i
].left
&&
305 y
<= mouse_region
[i
].bottom
&&
306 y
>= mouse_region
[i
].top
)
309 if (!found
) return -1;
313 /*******************************************************************************\
314 |* createXBMfromXPM *|
315 \*******************************************************************************/
316 void createXBMfromXPM(char *xbm
, char **xpm
, int sx
, int sy
) {
319 int width
, height
, numcol
, depth
;
323 sscanf(*xpm
, "%10d %10d %10d %10d", &width
, &height
, &numcol
, &depth
);
326 for (k
=0; k
!=depth
; k
++)
332 for (i
=numcol
+1; i
< numcol
+sy
+1; i
++) {
333 unsigned char bwrite
;
338 for (j
=0; j
<sx
*depth
; j
+=depth
) {
342 for (k
=0; k
!=depth
; k
++)
345 curpixel
|= xpm
[i
][j
+k
];
348 if ( curpixel
!= zero
) {
362 /*******************************************************************************\
364 \*******************************************************************************/
366 void copyXPMArea(int x
, int y
, int sx
, int sy
, int dx
, int dy
) {
368 XCopyArea(display
, wmgen
.pixmap
, wmgen
.pixmap
, NormalGC
, x
, y
, sx
, sy
, dx
, dy
);
372 /*******************************************************************************\
374 \*******************************************************************************/
376 void copyXBMArea(int x
, int y
, int sx
, int sy
, int dx
, int dy
) {
378 XCopyArea(display
, wmgen
.mask
, wmgen
.pixmap
, NormalGC
, x
, y
, sx
, sy
, dx
, dy
);
382 /*******************************************************************************\
384 \*******************************************************************************/
386 void setMaskXY(int x
, int y
) {
388 XShapeCombineMask(display
, win
, ShapeBounding
, x
, y
, pixmask
, ShapeSet
);
389 XShapeCombineMask(display
, iconwin
, ShapeBounding
, x
, y
, pixmask
, ShapeSet
);
392 /*******************************************************************************\
394 \*******************************************************************************/
395 void openXwindow(int argc
, char *argv
[], char *pixmap_bytes
[], char *pixmask_bits
, int pixmask_width
, int pixmask_height
) {
397 unsigned int borderwidth
= 1;
398 XClassHint classHint
;
399 char *display_name
= NULL
;
400 char *wname
= argv
[0];
406 char *geometry
= NULL
;
411 for (i
=1; argv
[i
]; i
++) {
412 if (!strcmp(argv
[i
], "-display"))
413 display_name
= argv
[++i
];
414 else if (!strcmp(argv
[i
], "-geometry"))
415 geometry
= argv
[++i
];
418 if (!(display
= XOpenDisplay(display_name
))) {
419 fprintf(stderr
, "%s: can't open display %s\n",
420 wname
, XDisplayName(display_name
));
423 screen
= DefaultScreen(display
);
424 Root
= RootWindow(display
, screen
);
425 d_depth
= DefaultDepth(display
, screen
);
426 x_fd
= XConnectionNumber(display
);
428 /* Convert XPM to XImage */
429 GetXPM(&wmgen
, pixmap_bytes
);
431 /* Create a window to hold the stuff */
432 mysizehints
.flags
= USSize
| USPosition
;
436 back_pix
= GetColor("white");
437 fore_pix
= GetColor("black");
439 XWMGeometry(display
, screen
, Geometry
, NULL
, borderwidth
, &mysizehints
,
440 &mysizehints
.x
, &mysizehints
.y
,&mysizehints
.width
,&mysizehints
.height
, &dummy
);
442 XParseGeometry(geometry
, &mysizehints
.x
, &mysizehints
.y
,
443 (unsigned int *) &mysizehints
.width
, (unsigned int *) &mysizehints
.height
);
445 mysizehints
.width
= 64;
446 mysizehints
.height
= 64;
448 win
= XCreateSimpleWindow(display
, Root
, mysizehints
.x
, mysizehints
.y
,
449 mysizehints
.width
, mysizehints
.height
, borderwidth
, fore_pix
, back_pix
);
451 iconwin
= XCreateSimpleWindow(display
, win
, mysizehints
.x
, mysizehints
.y
,
452 mysizehints
.width
, mysizehints
.height
, borderwidth
, fore_pix
, back_pix
);
455 XSetWMNormalHints(display
, win
, &mysizehints
);
456 classHint
.res_name
= wname
;
457 classHint
.res_class
= wname
;
458 XSetClassHint(display
, win
, &classHint
);
460 XSelectInput(display
, win
, ButtonPressMask
| ExposureMask
| ButtonReleaseMask
| PointerMotionMask
| StructureNotifyMask
);
461 XSelectInput(display
, iconwin
, ButtonPressMask
| ExposureMask
| ButtonReleaseMask
| PointerMotionMask
| StructureNotifyMask
);
463 if (XStringListToTextProperty(&wname
, 1, &name
) == 0) {
464 fprintf(stderr
, "%s: can't allocate window name\n", wname
);
468 XSetWMName(display
, win
, &name
);
470 /* Create GC for drawing */
472 gcm
= GCForeground
| GCBackground
| GCGraphicsExposures
;
473 gcv
.foreground
= fore_pix
;
474 gcv
.background
= back_pix
;
475 gcv
.graphics_exposures
= 0;
476 NormalGC
= XCreateGC(display
, Root
, gcm
, &gcv
);
480 pixmask
= XCreateBitmapFromData(display
, win
, pixmask_bits
, pixmask_width
, pixmask_height
);
482 XShapeCombineMask(display
, win
, ShapeBounding
, 0, 0, pixmask
, ShapeSet
);
483 XShapeCombineMask(display
, iconwin
, ShapeBounding
, 0, 0, pixmask
, ShapeSet
);
487 mywmhints
.initial_state
= WithdrawnState
;
488 mywmhints
.icon_window
= iconwin
;
489 mywmhints
.icon_x
= mysizehints
.x
;
490 mywmhints
.icon_y
= mysizehints
.y
;
491 mywmhints
.window_group
= win
;
492 mywmhints
.flags
= StateHint
| IconWindowHint
| IconPositionHint
| WindowGroupHint
;
494 XSetWMHints(display
, win
, &mywmhints
);
496 XSetCommand(display
, win
, argv
, argc
);
497 XMapWindow(display
, win
);
500 if (sscanf(geometry
, "+%10d+%10d", &wx
, &wy
) != 2) {
501 fprintf(stderr
, "Bad geometry string.\n");
504 XMoveWindow(display
, win
, wx
, wy
);