2 * 2006 - changes by Sergei Golubchik
3 * + set window title, better wm hints
4 * + multi-window support
8 * Copyright (c) 1999 Alfredo K. Kojima
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
24 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 #include <X11/extensions/shape.h>
34 #include <X11/Xatom.h>
36 #include <sys/types.h>
40 static char *progName
= NULL
;
41 static unsigned d_width
, d_height
;
42 static DACallbacks d_callbacks
= {NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
43 static int d_iswmaker
= 0;
44 static int d_timeout
= 0;
46 Display
*DADisplay
= NULL
;
49 PropGetCheckProperty(Display
*dpy
, Window window
, Atom hint
, Atom type
,
50 int format
, int count
, int *retCount
)
54 unsigned long nitems_ret
;
55 unsigned long bytes_after_ret
;
64 if (XGetWindowProperty(dpy
, window
, hint
, 0, tmp
, False
, type
,
65 &type_ret
, &fmt_ret
, &nitems_ret
, &bytes_after_ret
,
66 (unsigned char **)&data
)!=Success
|| !data
)
69 if ((type
!=AnyPropertyType
&& type
!=type_ret
)
70 || (count
> 0 && nitems_ret
!= count
)
71 || (format
!= 0 && format
!= fmt_ret
)) {
77 *retCount
= nitems_ret
;
84 iswmaker(Display
*dpy
)
91 atom
= XInternAtom(dpy
, "_WINDOWMAKER_WM_PROTOCOLS", False
);
92 noticeboard
= XInternAtom(dpy
, "_WINDOWMAKER_NOTICEBOARD", False
);
94 data
= (Atom
*)PropGetCheckProperty(dpy
, DefaultRootWindow(dpy
), atom
,
95 XA_ATOM
, 32, -1, &count
);
100 for (i
= 0; i
< count
; i
++) {
101 if (data
[i
] == noticeboard
) {
107 win
= (Window
*)PropGetCheckProperty(dpy
, DefaultRootWindow(dpy
),
108 noticeboard
, XA_WINDOW
, 32, -1,
115 d
= PropGetCheckProperty(dpy
, *win
, noticeboard
, XA_WINDOW
, 32, 1,
135 DAInitialize(char *display
, char *name
, unsigned width
, unsigned height
,
136 int argc
, char **argv
, Window
*out
)
141 Window DAWindow
, DALeader
;
149 DADisplay
= XOpenDisplay(display
);
151 printf("%s: could not open display %s!\n", progName
,
152 XDisplayName(display
));
157 d_iswmaker
= iswmaker(DADisplay
);
159 DAWindow
= XCreateSimpleWindow(DADisplay
, DefaultRootWindow(DADisplay
),
160 0, 0, width
, height
, 0, 0, 0);
161 DALeader
= XCreateSimpleWindow(DADisplay
, DefaultRootWindow(DADisplay
),
162 0, 0, 1, 1, 0, 0, 0);
164 chint
= XAllocClassHint();
166 printf("%s: cant allocate memory for class hints!\n", progName
);
169 chint
->res_class
= name
;
170 chint
->res_name
= strrchr(argv
[0], '/');
171 if (!chint
->res_name
)
172 chint
->res_name
= argv
[0];
176 XSetClassHint(DADisplay
, DAWindow
, chint
);
177 XSetClassHint(DADisplay
, DALeader
, chint
);
180 hints
= XAllocWMHints();
182 printf("%s: cant allocate memory for hints!\n", progName
);
185 hints
->flags
= StateHint
| IconWindowHint
| IconPositionHint
| WindowGroupHint
;
186 hints
->initial_state
= WithdrawnState
;
187 hints
->window_group
= DALeader
;
188 hints
->icon_window
= DAWindow
;
190 XSetWMHints(DADisplay
, DALeader
, hints
);
191 XSetWMHints(DADisplay
, DAWindow
, hints
);
193 XSetCommand(DADisplay
, DALeader
, argv
, argc
);
194 XSetCommand(DADisplay
, DAWindow
, argv
, argc
);
196 if (XStringListToTextProperty(&name
, 1, &wname
) == 0) {
197 fprintf(stderr
, "%s: can't allocate window name\n", name
);
201 XSetWMName(DADisplay
, DALeader
, &wname
);
202 XSetWMName(DADisplay
, DAWindow
, &wname
);
211 DASetShape(Window
*window
, Pixmap shapeMask
)
213 XShapeCombineMask(DADisplay
, *window
, ShapeBounding
, 0, 0, shapeMask
,
220 DASetPixmap(Window
*window
, Pixmap pixmap
)
222 XSetWindowBackgroundPixmap(DADisplay
, *window
, pixmap
);
223 XClearWindow(DADisplay
, *window
);
229 DAMakePixmap(Window
*window
)
233 p
= XCreatePixmap(DADisplay
, *window
, d_width
, d_height
,
234 DefaultDepth(DADisplay
, DefaultScreen(DADisplay
)));
242 DAMakePixmapFromData(Window
*window
, char **data
, Pixmap
*pixmap
, Pixmap
*mask
,
243 unsigned *width
, unsigned *height
)
251 xpmat
.valuemask
= XpmCloseness
;
252 xpmat
.closeness
= 40000;
254 if (XpmCreatePixmapFromData(DADisplay
, *window
, data
, pixmap
, mask
,
259 *width
= xpmat
.width
;
260 *height
= xpmat
.height
;
267 DAShow(Window
*window
)
269 XMapRaised(DADisplay
, window
[d_iswmaker
]);
276 DASetCallbacks(Window
*window
, DACallbacks
*callbacks
)
280 d_callbacks
= *callbacks
;
282 if (callbacks
->buttonPress
)
283 mask
|= ButtonPressMask
;
285 if (callbacks
->buttonRelease
)
286 mask
|= ButtonReleaseMask
;
288 XSelectInput(DADisplay
, *window
, mask
);
294 DAProcessEvent(Window
*window
, XEvent
*event
)
296 if (event
->xany
.window
!= window
[0] && event
->xany
.window
!= window
[1])
299 switch (event
->type
) {
301 if (d_callbacks
.destroy
) {
302 (*d_callbacks
.destroy
)(window
[0]);
308 if (d_callbacks
.buttonPress
) {
309 (*d_callbacks
.buttonPress
)(window
[0], event
->xbutton
.button
, event
->xbutton
.state
,
310 event
->xbutton
.x
, event
->xbutton
.y
);
315 if (d_callbacks
.buttonRelease
) {
316 (*d_callbacks
.buttonRelease
)(window
[0], event
->xbutton
.button
, event
->xbutton
.state
,
317 event
->xbutton
.x
, event
->xbutton
.y
);
322 if (d_callbacks
.motion
) {
323 (*d_callbacks
.motion
)(window
[0], event
->xbutton
.x
, event
->xbutton
.y
);
328 if (d_callbacks
.enter
) {
329 (*d_callbacks
.enter
)(window
[0]);
334 if (d_callbacks
.leave
) {
335 (*d_callbacks
.leave
)(window
[0]);
349 DAEventLoop(Window
*window
)
354 if (d_timeout
>= 0) {
355 if (!DANextEventOrTimeout(&ev
, d_timeout
)) {
356 if (d_callbacks
.timeout
)
357 (*d_callbacks
.timeout
)(window
[0]);
361 XNextEvent(DADisplay
, &ev
);
363 DAProcessEvent(window
, &ev
);
368 static DAProgramOption defaultOptions
[]= {
369 {"-h", "--help", "shows this help text and exit", DONone
, False
,
371 {"-v", "--version", "shows program version and exit", DONone
, False
,
377 printHelp(char *prog
, char *description
, DAProgramOption
*options
,
382 printf("Usage: %s [OPTIONS]\n", prog
);
386 for (j
= 0; j
< count
+ 2; j
++) {
392 options
= defaultOptions
;
398 if (options
[i
].shortForm
&& options
[i
].longForm
)
399 c
= printf(" %s, %s", options
[i
].shortForm
, options
[i
].longForm
);
400 else if (options
[i
].shortForm
)
401 c
= printf(" %s", options
[i
].shortForm
);
402 else if (options
[i
].longForm
)
403 c
= printf(" %s", options
[i
].longForm
);
407 if (options
[i
].type
!= DONone
) {
408 switch (options
[i
].type
) {
410 c
+= printf(" <integer>");
413 c
+= printf(" <string>");
416 c
+= printf(" <number>");
421 memset(blank
, ' ', 30);
425 printf("%s %s\n", blank
, options
[i
].description
);
431 DAParseArguments(int argc
, char **argv
, DAProgramOption
*options
,
432 int count
, char *programDescription
, char *versionDescription
)
437 for (i
= 1; i
< argc
; i
++) {
438 if (strcmp(argv
[i
], "-h")==0 || strcmp(argv
[i
], "--help")==0) {
440 printHelp(argv
[0], programDescription
, options
, count
);
443 } else if (strcmp(argv
[i
],"-v")==0 || strcmp(argv
[i
], "--version")==0) {
445 puts(versionDescription
);
451 for (j
= 0; j
< count
; j
++) {
452 if ((options
[j
].shortForm
453 && strcmp(options
[j
].shortForm
, argv
[i
])==0)
456 && strcmp(options
[j
].longForm
, argv
[i
])==0)) {
460 options
[j
].used
= True
;
462 if (options
[j
].type
== DONone
)
467 printf("%s: missing argument for option '%s'\n", argv
[0],
472 switch (options
[j
].type
) {
477 if (sscanf(argv
[i
], "%i", &integer
)!=1) {
478 printf("%s: error parsing argument for option %s\n",
482 *options
[j
].value
.integer
= integer
;
489 if (sscanf(argv
[i
], "%i", &integer
)!=1) {
490 printf("%s: error parsing argument for option %s\n",
495 printf("%s: argument %s must be >= 0\n",
499 *options
[j
].value
.integer
= integer
;
503 *options
[j
].value
.string
= argv
[i
];
510 printf("%s: unrecognized option '%s'\n", argv
[0], argv
[i
]);
511 printHelp(argv
[0], programDescription
, options
, count
);
519 DAGetColor(char *colorName
)
523 if (!XParseColor(DADisplay
,
524 DefaultColormap(DADisplay
, DefaultScreen(DADisplay
)),
525 colorName
, &color
)) {
526 printf("%s: could not parse color %s\n", progName
, colorName
);
530 if (!XAllocColor(DADisplay
, DefaultColormap(DADisplay
, DefaultScreen(DADisplay
)),
532 printf("%s: could not allocate color %s. Using black\n", progName
, colorName
);
533 return BlackPixel(DADisplay
, DefaultScreen(DADisplay
));
541 DASetTimeout(int milliseconds
)
543 d_timeout
= milliseconds
;
549 DANextEventOrTimeout(XEvent
*event
, unsigned long millisec
)
551 struct timeval timeout
;
554 XSync(DADisplay
, False
);
555 if (XPending(DADisplay
)) {
556 XNextEvent(DADisplay
, event
);
560 timeout
.tv_sec
= millisec
/1000;
561 timeout
.tv_usec
= (millisec
%1000)*10;
564 FD_SET(ConnectionNumber(DADisplay
), &rset
);
566 if (select(ConnectionNumber(DADisplay
)+1, &rset
, NULL
, NULL
,
568 XNextEvent(DADisplay
, event
);