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)
15 14/09/1998 (Dave Clark, clarkd@skyia.com)
16 * Updated createXBMfromXPM routine
17 * Now supports >256 colors
18 11/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
19 * Removed a bug from parse_rcfile. You could
20 not use "start" in a command if a label was
22 * Changed the needed geometry string.
23 We don't use window size, and don't support
25 03/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
27 02/09/1998 (Martijn Pieterse, pieterse@xs4all.nl)
28 * Added -geometry support (untested)
29 28/08/1998 (Martijn Pieterse, pieterse@xs4all.nl)
30 * Added createXBMfromXPM routine
31 * Saves a lot of work with changing xpm's.
32 02/05/1998 (Martijn Pieterse, pieterse@xs4all.nl)
33 * changed the read_rc_file to parse_rcfile, as suggested by Marcelo E. Magallon
34 * debugged the parse_rc file.
35 30/04/1998 (Martijn Pieterse, pieterse@xs4all.nl)
36 * Ripped similar code from all the wm* programs,
37 and put them in a single file.
59 #include <X11/Xutil.h> /* needed for Region on solaris? */
60 #include <X11/extensions/shape.h>
62 #include "wmgeneral.h"
73 XSizeHints mysizehints
;
75 Pixel back_pix
, fore_pix
;
76 // static const char *Geometry = "";
95 MOUSE_REGION mouse_region
[MAX_MOUSE_REGION
];
97 /***********************/
98 /* Function Prototypes */
99 /***********************/
101 static void GetXPM(XpmIcon
*, const char **);
102 Pixel
GetColor(const char *);
103 void RedrawWindow(void);
104 int CheckMouseRegion(int, int);
106 /*******************************************************************************\
108 \*******************************************************************************/
110 void parse_rcfile(const char *filename
, rckeys
* keys
)
115 const char *tokens
= " :\t\n";
119 fp
= fopen(filename
, "r");
121 while (fgets(temp
, 128, fp
)) {
123 char *t
= strdup(temp
);
124 q
= strtok(t
, tokens
);
125 while (key
>= 0 && keys
[key
].label
) {
126 if ((!strcmp(q
, keys
[key
].label
))) {
127 p
= strstr(temp
, keys
[key
].label
);
128 p
+= strlen(keys
[key
].label
);
129 p
+= strspn(p
, tokens
);
130 if ((i
= strcspn(p
, "#\n")))
132 free(*keys
[key
].var
);
133 *keys
[key
].var
= strdup(p
);
144 /*******************************************************************************\
146 \*******************************************************************************/
148 void parse_rcfile2(const char *filename
, rckeys2
* keys
)
153 const char *tokens
= " :\t\n";
158 fp
= fopen(filename
, "r");
160 while (fgets(temp
, 128, fp
)) {
162 while (key
>= 0 && keys
[key
].label
) {
163 if ((p
= strstr(temp
, keys
[key
].label
))) {
164 p
+= strlen(keys
[key
].label
);
165 p
+= strspn(p
, tokens
);
166 if ((i
= strcspn(p
, "#\n")))
168 free(*keys
[key
].var
);
169 *keys
[key
].var
= strdup(p
);
181 /*******************************************************************************\
183 \*******************************************************************************/
185 static void GetXPM(XpmIcon
* wmgen_local
, const char *pixmap_bytes
[])
188 XWindowAttributes attributes
;
191 /* For the colormap */
192 XGetWindowAttributes(display
, Root
, &attributes
);
193 /* despite the comment, I still don't understand...
194 attributes is subsequently unused in this function -ns 11/2002 */
196 wmgen_local
->attributes
.valuemask
|=
197 (XpmReturnPixels
| XpmReturnExtensions
);
199 err
= XpmCreatePixmapFromData(display
, Root
, (char **) pixmap_bytes
,
200 &(wmgen_local
->pixmap
),
201 &(wmgen_local
->mask
),
202 &(wmgen_local
->attributes
));
204 if (err
!= XpmSuccess
) {
206 "Not enough free colorcells to create pixmap from data (err=%d).\n",
212 /*******************************************************************************\
214 \*******************************************************************************/
216 Pixel
GetColor(const char *name
)
220 XWindowAttributes attributes
;
222 XGetWindowAttributes(display
, Root
, &attributes
);
225 if (!XParseColor(display
, attributes
.colormap
, name
, &color
)) {
226 fprintf(stderr
, "wm.app: GetColor() can't parse %s.\n", name
);
227 } else if (!XAllocColor(display
, attributes
.colormap
, &color
)) {
228 fprintf(stderr
, "wm.app: GetColor() can't allocate %s.\n", name
);
233 /*******************************************************************************\
235 \*******************************************************************************/
237 static int flush_expose(Window w
)
243 while (XCheckTypedWindowEvent(display
, w
, Expose
, &dummy
))
249 /*******************************************************************************\
251 \*******************************************************************************/
253 void RedrawWindow(void)
256 flush_expose(iconwin
);
257 XCopyArea(display
, wmgen_bkg
.pixmap
, iconwin
, NormalGC
,
258 0, 0, wmgen_bkg
.attributes
.width
,
259 wmgen_bkg
.attributes
.height
, 0, 0);
261 XCopyArea(display
, wmgen_bkg
.pixmap
, win
, NormalGC
,
262 0, 0, wmgen_bkg
.attributes
.width
,
263 wmgen_bkg
.attributes
.height
, 0, 0);
266 /*******************************************************************************\
268 \*******************************************************************************/
270 void RedrawWindowXY(int x
, int y
)
273 flush_expose(iconwin
);
274 XCopyArea(display
, wmgen_bkg
.pixmap
, iconwin
, NormalGC
,
275 x
, y
, wmgen_bkg
.attributes
.width
,
276 wmgen_bkg
.attributes
.height
, 0, 0);
278 XCopyArea(display
, wmgen_bkg
.pixmap
, win
, NormalGC
,
279 x
, y
, wmgen_bkg
.attributes
.width
,
280 wmgen_bkg
.attributes
.height
, 0, 0);
283 /*******************************************************************************\
285 \*******************************************************************************/
287 void AddMouseRegion(unsigned int region_idx
, int left
, int top
, int right
,
291 if (region_idx
< MAX_MOUSE_REGION
) {
292 mouse_region
[region_idx
].enable
= 1;
293 mouse_region
[region_idx
].top
= top
;
294 mouse_region
[region_idx
].left
= left
;
295 mouse_region
[region_idx
].bottom
= bottom
;
296 mouse_region
[region_idx
].right
= right
;
300 /*******************************************************************************\
301 |* CheckMouseRegion *|
302 \*******************************************************************************/
304 int CheckMouseRegion(int x
, int y
)
312 for (i
= 0; i
< MAX_MOUSE_REGION
&& !found
; i
++) {
313 if (mouse_region
[i
].enable
&&
314 x
<= mouse_region
[i
].right
&&
315 x
>= mouse_region
[i
].left
&&
316 y
<= mouse_region
[i
].bottom
&& y
>= mouse_region
[i
].top
)
324 /*******************************************************************************\
325 |* createXBMfromXPM *|
326 \*******************************************************************************/
327 void createXBMfromXPM(char *xbm
, const char **xpm
, int sx
, int sy
)
331 int width
, height
, numcol
, depth
;
333 unsigned char bwrite
;
337 sscanf(*xpm
, "%d %d %d %d", &width
, &height
, &numcol
, &depth
);
340 for (k
= 0; k
!= depth
; k
++) {
345 for (i
= numcol
+ 1; i
< numcol
+ sy
+ 1; i
++) {
348 for (j
= 0; j
< sx
* depth
; j
+= depth
) {
352 for (k
= 0; k
!= depth
; k
++) {
354 curpixel
|= xpm
[i
][j
+ k
];
357 if (curpixel
!= zero
) {
371 /*******************************************************************************\
373 \*******************************************************************************/
375 void copyXPMArea(int src_x
, int src_y
, int width
, int height
, int dest_x
,
379 XCopyArea(display
, wmgen_src
.pixmap
, wmgen_bkg
.pixmap
, NormalGC
, src_x
,
380 src_y
, width
, height
, dest_x
, dest_y
);
384 /*******************************************************************************\
386 \*******************************************************************************/
388 void copyXBMArea(int src_x
, int src_y
, int width
, int height
, int dest_x
,
392 XCopyArea(display
, wmgen_src
.mask
, wmgen_bkg
.pixmap
, NormalGC
, src_x
,
393 src_y
, width
, height
, dest_x
, dest_y
);
397 /* added for wmbiff */
399 int loadFont(const char *fontname
)
401 if (display
!= NULL
) {
402 f
= XLoadQueryFont(display
, fontname
);
404 XSetFont(display
, NormalGC
, f
->fid
);
407 printf("couldn't set font!\n");
413 void drawString(int dest_x
, int dest_y
, const char *string
,
414 const char *colorname
, const char *bgcolorname
,
417 int len
= strlen(string
);
418 assert(colorname
!= NULL
);
419 XSetForeground(display
, NormalGC
, GetColor(colorname
));
420 XSetBackground(display
, NormalGC
, GetColor(bgcolorname
));
422 dest_x
-= XTextWidth(f
, string
, len
);
423 XDrawImageString(display
, wmgen_bkg
.pixmap
, NormalGC
, dest_x
, dest_y
,
427 void eraseRect(int x
, int y
, int x2
, int y2
, const char *bgcolorname
)
429 XSetForeground(display
, NormalGC
, GetColor(bgcolorname
));
430 XFillRectangle(display
, wmgen_bkg
.pixmap
, NormalGC
, x
, y
, x2
- x
,
434 /* end wmbiff additions */
436 /*******************************************************************************\
438 \*******************************************************************************/
440 void setMaskXY(int x
, int y
)
443 XShapeCombineMask(display
, win
, ShapeBounding
, x
, y
, pixmask
,
445 XShapeCombineMask(display
, iconwin
, ShapeBounding
, x
, y
, pixmask
,
449 /*******************************************************************************\
451 \*******************************************************************************/
452 void openXwindow(int argc
, const char *argv
[],
453 const char *pixmap_bytes_bkg
[],
454 const char *pixmap_bytes_src
[], char *pixmask_bits
,
455 int pixmask_width
, int pixmask_height
, int notWithdrawn
)
458 unsigned int borderwidth
= 1;
459 XClassHint classHint
;
460 const char *display_name
= NULL
;
461 char *wname
= strdup(argv
[0]);
467 const char *geometry
= NULL
;
468 char default_geometry
[128];
474 fprintf(stderr
, "Unable to allocate memory for window name!\n");
478 for (i
= 1; argv
[i
]; i
++) {
479 if (!strcmp(argv
[i
], "-display") && i
< argc
- 1) {
480 display_name
= argv
[i
+ 1];
483 if (!strcmp(argv
[i
], "-geometry") && i
< argc
- 1) {
484 geometry
= argv
[i
+ 1];
489 sprintf(default_geometry
, "%dx%d+0+0", pixmask_width
, pixmask_height
);
491 if (!(display
= XOpenDisplay(display_name
))) {
492 fprintf(stderr
, "%s: can't open display %s\n",
493 wname
, XDisplayName(display_name
));
496 screen
= DefaultScreen(display
);
497 Root
= RootWindow(display
, screen
);
498 d_depth
= DefaultDepth(display
, screen
);
499 x_fd
= XConnectionNumber(display
);
501 /* Convert XPM to XImage */
502 GetXPM(&wmgen_bkg
, pixmap_bytes_bkg
);
503 GetXPM(&wmgen_src
, pixmap_bytes_src
);
505 /* Create a window to hold the stuff */
506 mysizehints
.flags
= USSize
| USPosition
;
510 back_pix
= GetColor("black");
511 fore_pix
= GetColor("cyan");
513 XWMGeometry(display
, screen
, geometry
, default_geometry
, borderwidth
,
514 &mysizehints
, &mysizehints
.x
, &mysizehints
.y
,
515 &mysizehints
.width
, &mysizehints
.height
, &dummy
);
517 mysizehints
.width
= pixmask_width
; /* changed 11/2002 for wmbiff non 64x64-ness */
518 mysizehints
.height
= pixmask_height
; /* was statically 64. */
520 win
= XCreateSimpleWindow(display
, Root
, mysizehints
.x
, mysizehints
.y
,
521 mysizehints
.width
, mysizehints
.height
,
522 borderwidth
, fore_pix
, back_pix
);
525 XCreateSimpleWindow(display
, win
, mysizehints
.x
, mysizehints
.y
,
526 mysizehints
.width
, mysizehints
.height
,
527 borderwidth
, fore_pix
, back_pix
);
530 XSetWMNormalHints(display
, win
, &mysizehints
);
531 classHint
.res_name
= wname
;
532 classHint
.res_class
= wname
;
533 XSetClassHint(display
, win
, &classHint
);
535 /* Was PointerMotionMask instead of KeyPressMask, but pointer motion is irrelevant,
536 and if the user went to the trouble of giving us keypresses, the least we can do
538 XSelectInput(display
, win
,
539 ButtonPressMask
| ExposureMask
| ButtonReleaseMask
|
540 KeyPressMask
| StructureNotifyMask
);
541 XSelectInput(display
, iconwin
,
542 ButtonPressMask
| ExposureMask
| ButtonReleaseMask
|
543 KeyPressMask
| StructureNotifyMask
);
545 /* wname is argv[0] */
546 if (XStringListToTextProperty(&wname
, 1, &name
) == 0) {
547 fprintf(stderr
, "%s: can't allocate window name\n", wname
);
551 XSetWMName(display
, win
, &name
);
554 /* Create GC for drawing */
556 gcm
= GCForeground
| GCBackground
| GCGraphicsExposures
;
557 gcv
.foreground
= fore_pix
;
558 gcv
.background
= back_pix
;
559 gcv
.graphics_exposures
= 0;
560 NormalGC
= XCreateGC(display
, Root
, gcm
, &gcv
);
565 XCreateBitmapFromData(display
, win
, pixmask_bits
, pixmask_width
,
568 XShapeCombineMask(display
, win
, ShapeBounding
, 0, 0, pixmask
,
570 XShapeCombineMask(display
, iconwin
, ShapeBounding
, 0, 0, pixmask
,
575 mywmhints
.initial_state
= WithdrawnState
;
576 mywmhints
.icon_window
= iconwin
;
577 mywmhints
.icon_x
= mysizehints
.x
;
578 mywmhints
.icon_y
= mysizehints
.y
;
579 mywmhints
.window_group
= win
;
581 (notWithdrawn
? 0 : StateHint
) | IconWindowHint
|
582 IconPositionHint
| WindowGroupHint
;
584 XSetWMHints(display
, win
, &mywmhints
);
586 XSetCommand(display
, win
, (char **) argv
, argc
);
587 XMapWindow(display
, win
);
590 /* we'll silently drop width and height as well as negative positions */
591 /* mostly because I don't know how to deal with them */
594 int specified = XParseGeometry(geometry, &x, &y, &wx, &wy);
595 printf("%d %d %d %d\n", x, y, wx, wy);
596 if( specified & XNegative ) {
597 x = DisplayWidth(display, DefaultScreen(display)) - x - pixmask_width;
599 if( specified & YNegative ) {
600 y = DisplayHeight(display, DefaultScreen(display)) - y - pixmask_height;
602 if( specified & XValue || specified & YValue ) {
603 XMoveWindow(display, win, x, y);
607 if (sscanf(geometry, "+%d+%d", &wx, &wy) == 2) {
608 XMoveWindow(display, win, wx, wy);
609 } else if (sscanf(geometry, "%dx%d+%d+%d", &x, &y, &wx, &wy) == 4) {
610 XMoveWindow(display, win, wx, wy);
611 } else if (sscanf(geometry, "+%d-%d", &wx, &wy) == 2) {
612 XMoveWindow(display, win, wx, 0 - wy);
614 fprintf(stderr, "Unsupported geometry string '%s'\n",