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"
72 XSizeHints mysizehints
;
74 Pixel back_pix
, fore_pix
;
75 // static const char *Geometry = "";
94 MOUSE_REGION mouse_region
[MAX_MOUSE_REGION
];
96 /***********************/
97 /* Function Prototypes */
98 /***********************/
100 static void GetXPM(XpmIcon
*, const char **);
101 Pixel
GetColor(const char *);
102 void RedrawWindow(void);
103 int CheckMouseRegion(int, int);
105 /*******************************************************************************\
107 \*******************************************************************************/
109 void parse_rcfile(const char *filename
, rckeys
* keys
)
114 const char *tokens
= " :\t\n";
118 fp
= fopen(filename
, "r");
120 while (fgets(temp
, 128, fp
)) {
123 q
= strtok(q
, tokens
);
124 while (key
>= 0 && keys
[key
].label
) {
125 if ((!strcmp(q
, keys
[key
].label
))) {
126 p
= strstr(temp
, keys
[key
].label
);
127 p
+= strlen(keys
[key
].label
);
128 p
+= strspn(p
, tokens
);
129 if ((i
= strcspn(p
, "#\n")))
131 free(*keys
[key
].var
);
132 *keys
[key
].var
= strdup(p
);
143 /*******************************************************************************\
145 \*******************************************************************************/
147 void parse_rcfile2(const char *filename
, rckeys2
* keys
)
152 const char *tokens
= " :\t\n";
157 fp
= fopen(filename
, "r");
159 while (fgets(temp
, 128, fp
)) {
161 while (key
>= 0 && keys
[key
].label
) {
162 if ((p
= strstr(temp
, keys
[key
].label
))) {
163 p
+= strlen(keys
[key
].label
);
164 p
+= strspn(p
, tokens
);
165 if ((i
= strcspn(p
, "#\n")))
167 free(*keys
[key
].var
);
168 *keys
[key
].var
= strdup(p
);
180 /*******************************************************************************\
182 \*******************************************************************************/
184 static void GetXPM(XpmIcon
* wmgen_local
, const char *pixmap_bytes
[])
187 XWindowAttributes attributes
;
190 /* For the colormap */
191 XGetWindowAttributes(display
, Root
, &attributes
);
192 /* despite the comment, I still don't understand...
193 attributes is subsequently unused in this function -ns 11/2002 */
195 wmgen_local
->attributes
.valuemask
|=
196 (XpmReturnPixels
| XpmReturnExtensions
);
198 err
= XpmCreatePixmapFromData(display
, Root
, (char **) pixmap_bytes
,
199 &(wmgen_local
->pixmap
),
200 &(wmgen_local
->mask
),
201 &(wmgen_local
->attributes
));
203 if (err
!= XpmSuccess
) {
205 "Not enough free colorcells to create pixmap from data (err=%d).\n",
211 /*******************************************************************************\
213 \*******************************************************************************/
215 Pixel
GetColor(const char *name
)
219 XWindowAttributes attributes
;
221 XGetWindowAttributes(display
, Root
, &attributes
);
224 if (!XParseColor(display
, attributes
.colormap
, name
, &color
)) {
225 fprintf(stderr
, "wm.app: GetColor() can't parse %s.\n", name
);
226 } else if (!XAllocColor(display
, attributes
.colormap
, &color
)) {
227 fprintf(stderr
, "wm.app: GetColor() can't allocate %s.\n", name
);
232 /*******************************************************************************\
234 \*******************************************************************************/
236 static int flush_expose(Window w
)
242 while (XCheckTypedWindowEvent(display
, w
, Expose
, &dummy
))
248 /*******************************************************************************\
250 \*******************************************************************************/
252 void RedrawWindow(void)
255 flush_expose(iconwin
);
256 XCopyArea(display
, wmgen_bkg
.pixmap
, iconwin
, NormalGC
,
257 0, 0, wmgen_bkg
.attributes
.width
,
258 wmgen_bkg
.attributes
.height
, 0, 0);
260 XCopyArea(display
, wmgen_bkg
.pixmap
, win
, NormalGC
,
261 0, 0, wmgen_bkg
.attributes
.width
,
262 wmgen_bkg
.attributes
.height
, 0, 0);
265 /*******************************************************************************\
267 \*******************************************************************************/
269 void RedrawWindowXY(int x
, int y
)
272 flush_expose(iconwin
);
273 XCopyArea(display
, wmgen_bkg
.pixmap
, iconwin
, NormalGC
,
274 x
, y
, wmgen_bkg
.attributes
.width
,
275 wmgen_bkg
.attributes
.height
, 0, 0);
277 XCopyArea(display
, wmgen_bkg
.pixmap
, win
, NormalGC
,
278 x
, y
, wmgen_bkg
.attributes
.width
,
279 wmgen_bkg
.attributes
.height
, 0, 0);
282 /*******************************************************************************\
284 \*******************************************************************************/
286 void AddMouseRegion(unsigned int region_idx
, int left
, int top
, int right
,
290 if (region_idx
< MAX_MOUSE_REGION
) {
291 mouse_region
[region_idx
].enable
= 1;
292 mouse_region
[region_idx
].top
= top
;
293 mouse_region
[region_idx
].left
= left
;
294 mouse_region
[region_idx
].bottom
= bottom
;
295 mouse_region
[region_idx
].right
= right
;
299 /*******************************************************************************\
300 |* CheckMouseRegion *|
301 \*******************************************************************************/
303 int CheckMouseRegion(int x
, int y
)
311 for (i
= 0; i
< MAX_MOUSE_REGION
&& !found
; i
++) {
312 if (mouse_region
[i
].enable
&&
313 x
<= mouse_region
[i
].right
&&
314 x
>= mouse_region
[i
].left
&&
315 y
<= mouse_region
[i
].bottom
&& y
>= mouse_region
[i
].top
)
323 /*******************************************************************************\
324 |* createXBMfromXPM *|
325 \*******************************************************************************/
326 void createXBMfromXPM(char *xbm
, const char **xpm
, int sx
, int sy
)
330 int width
, height
, numcol
, depth
;
332 unsigned char bwrite
;
336 sscanf(*xpm
, "%d %d %d %d", &width
, &height
, &numcol
, &depth
);
339 for (k
= 0; k
!= depth
; k
++) {
344 for (i
= numcol
+ 1; i
< numcol
+ sy
+ 1; i
++) {
347 for (j
= 0; j
< sx
* depth
; j
+= depth
) {
351 for (k
= 0; k
!= depth
; k
++) {
353 curpixel
|= xpm
[i
][j
+ k
];
356 if (curpixel
!= zero
) {
370 /*******************************************************************************\
372 \*******************************************************************************/
374 void copyXPMArea(int src_x
, int src_y
, int width
, int height
, int dest_x
,
378 XCopyArea(display
, wmgen_src
.pixmap
, wmgen_bkg
.pixmap
, NormalGC
, src_x
,
379 src_y
, width
, height
, dest_x
, dest_y
);
383 /*******************************************************************************\
385 \*******************************************************************************/
387 void copyXBMArea(int src_x
, int src_y
, int width
, int height
, int dest_x
,
391 XCopyArea(display
, wmgen_src
.mask
, wmgen_bkg
.pixmap
, NormalGC
, src_x
,
392 src_y
, width
, height
, dest_x
, dest_y
);
396 /* added for wmbiff */
398 int loadFont(const char *fontname
)
400 if (display
!= NULL
) {
401 f
= XLoadQueryFont(display
, fontname
);
403 XSetFont(display
, NormalGC
, f
->fid
);
406 printf("couldn't set font!\n");
412 void drawString(int dest_x
, int dest_y
, const char *string
,
413 const char *colorname
, const char *bgcolorname
,
416 int len
= strlen(string
);
417 assert(colorname
!= NULL
);
418 XSetForeground(display
, NormalGC
, GetColor(colorname
));
419 XSetBackground(display
, NormalGC
, GetColor(bgcolorname
));
421 dest_x
-= XTextWidth(f
, string
, len
);
422 XDrawImageString(display
, wmgen_bkg
.pixmap
, NormalGC
, dest_x
, dest_y
,
426 void eraseRect(int x
, int y
, int x2
, int y2
, const char *bgcolorname
)
428 XSetForeground(display
, NormalGC
, GetColor(bgcolorname
));
429 XFillRectangle(display
, wmgen_bkg
.pixmap
, NormalGC
, x
, y
, x2
- x
,
433 /* end wmbiff additions */
435 /*******************************************************************************\
437 \*******************************************************************************/
439 void setMaskXY(int x
, int y
)
442 XShapeCombineMask(display
, win
, ShapeBounding
, x
, y
, pixmask
,
444 XShapeCombineMask(display
, iconwin
, ShapeBounding
, x
, y
, pixmask
,
448 /*******************************************************************************\
450 \*******************************************************************************/
451 void openXwindow(int argc
, const char *argv
[],
452 const char *pixmap_bytes_bkg
[],
453 const char *pixmap_bytes_src
[], char *pixmask_bits
,
454 int pixmask_width
, int pixmask_height
, int notWithdrawn
)
457 unsigned int borderwidth
= 1;
458 XClassHint classHint
;
459 const char *display_name
= NULL
;
460 char *wname
= strdup(argv
[0]);
466 const char *geometry
= NULL
;
467 char default_geometry
[128];
473 fprintf(stderr
, "Unable to allocate memory for window name!\n");
477 for (i
= 1; argv
[i
]; i
++) {
478 if (!strcmp(argv
[i
], "-display") && i
< argc
- 1) {
479 display_name
= argv
[i
+ 1];
482 if (!strcmp(argv
[i
], "-geometry") && i
< argc
- 1) {
483 geometry
= argv
[i
+ 1];
488 sprintf(default_geometry
, "%dx%d+0+0", pixmask_width
, pixmask_height
);
490 if (!(display
= XOpenDisplay(display_name
))) {
491 fprintf(stderr
, "%s: can't open display %s\n",
492 wname
, XDisplayName(display_name
));
495 screen
= DefaultScreen(display
);
496 Root
= RootWindow(display
, screen
);
497 d_depth
= DefaultDepth(display
, screen
);
498 x_fd
= XConnectionNumber(display
);
500 /* Convert XPM to XImage */
501 GetXPM(&wmgen_bkg
, pixmap_bytes_bkg
);
502 GetXPM(&wmgen_src
, pixmap_bytes_src
);
504 /* Create a window to hold the stuff */
505 mysizehints
.flags
= USSize
| USPosition
;
509 back_pix
= GetColor("black");
510 fore_pix
= GetColor("cyan");
512 XWMGeometry(display
, screen
, geometry
, default_geometry
, borderwidth
,
513 &mysizehints
, &mysizehints
.x
, &mysizehints
.y
,
514 &mysizehints
.width
, &mysizehints
.height
, &dummy
);
516 mysizehints
.width
= pixmask_width
; /* changed 11/2002 for wmbiff non 64x64-ness */
517 mysizehints
.height
= pixmask_height
; /* was statically 64. */
519 win
= XCreateSimpleWindow(display
, Root
, mysizehints
.x
, mysizehints
.y
,
520 mysizehints
.width
, mysizehints
.height
,
521 borderwidth
, fore_pix
, back_pix
);
524 XCreateSimpleWindow(display
, win
, mysizehints
.x
, mysizehints
.y
,
525 mysizehints
.width
, mysizehints
.height
,
526 borderwidth
, fore_pix
, back_pix
);
529 XSetWMNormalHints(display
, win
, &mysizehints
);
530 classHint
.res_name
= wname
;
531 classHint
.res_class
= wname
;
532 XSetClassHint(display
, win
, &classHint
);
534 /* Was PointerMotionMask instead of KeyPressMask, but pointer motion is irrelevant,
535 and if the user went to the trouble of giving us keypresses, the least we can do
537 XSelectInput(display
, win
,
538 ButtonPressMask
| ExposureMask
| ButtonReleaseMask
|
539 KeyPressMask
| StructureNotifyMask
);
540 XSelectInput(display
, iconwin
,
541 ButtonPressMask
| ExposureMask
| ButtonReleaseMask
|
542 KeyPressMask
| StructureNotifyMask
);
544 /* wname is argv[0] */
545 if (XStringListToTextProperty(&wname
, 1, &name
) == 0) {
546 fprintf(stderr
, "%s: can't allocate window name\n", wname
);
550 XSetWMName(display
, win
, &name
);
553 /* Create GC for drawing */
555 gcm
= GCForeground
| GCBackground
| GCGraphicsExposures
;
556 gcv
.foreground
= fore_pix
;
557 gcv
.background
= back_pix
;
558 gcv
.graphics_exposures
= 0;
559 NormalGC
= XCreateGC(display
, Root
, gcm
, &gcv
);
564 XCreateBitmapFromData(display
, win
, pixmask_bits
, pixmask_width
,
567 XShapeCombineMask(display
, win
, ShapeBounding
, 0, 0, pixmask
,
569 XShapeCombineMask(display
, iconwin
, ShapeBounding
, 0, 0, pixmask
,
574 mywmhints
.initial_state
= WithdrawnState
;
575 mywmhints
.icon_window
= iconwin
;
576 mywmhints
.icon_x
= mysizehints
.x
;
577 mywmhints
.icon_y
= mysizehints
.y
;
578 mywmhints
.window_group
= win
;
580 (notWithdrawn
? 0 : StateHint
) | IconWindowHint
|
581 IconPositionHint
| WindowGroupHint
;
583 XSetWMHints(display
, win
, &mywmhints
);
585 XSetCommand(display
, win
, (char **) argv
, argc
);
586 XMapWindow(display
, win
);
589 /* we'll silently drop width and height as well as negative positions */
590 /* mostly because I don't know how to deal with them */
593 int specified = XParseGeometry(geometry, &x, &y, &wx, &wy);
594 printf("%d %d %d %d\n", x, y, wx, wy);
595 if( specified & XNegative ) {
596 x = DisplayWidth(display, DefaultScreen(display)) - x - pixmask_width;
598 if( specified & YNegative ) {
599 y = DisplayHeight(display, DefaultScreen(display)) - y - pixmask_height;
601 if( specified & XValue || specified & YValue ) {
602 XMoveWindow(display, win, x, y);
606 if (sscanf(geometry, "+%d+%d", &wx, &wy) == 2) {
607 XMoveWindow(display, win, wx, wy);
608 } else if (sscanf(geometry, "%dx%d+%d+%d", &x, &y, &wx, &wy) == 4) {
609 XMoveWindow(display, win, wx, wy);
610 } else if (sscanf(geometry, "+%d-%d", &wx, &wy) == 2) {
611 XMoveWindow(display, win, wx, 0 - wy);
613 fprintf(stderr, "Unsupported geometry string '%s'\n",