wmail: call `XSetCommand()`.
[dockapps.git] / wmfu / dockapp.c
blob6a7f98bcae30a2fb080e5a9d7a7d22d3bcedba0e
1 /*
2 * Copyright (c) 1999 Alfredo K. Kojima
3 * Copyright (c) 2001, 2002 Seiichi SATO
4 * Copyright (c) 2007 Daniel Borca
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <X11/Xlib.h>
23 #include <X11/xpm.h>
24 #include <X11/extensions/shape.h>
26 #include "dockapp.h"
29 #define WINDOWED_SIZE_W 64
30 #define WINDOWED_SIZE_H 64
31 #define DOCKED_SIZE_W (WINDOWED_SIZE_W - 4)
32 #define DOCKED_SIZE_H (WINDOWED_SIZE_H - 4)
35 int
36 dockapp_open_window(DOCKAPP *d,
37 const char *display_specified,
38 char *appname, int iswindowed,
39 int argc, char **argv)
41 XSizeHints sizehints;
42 XClassHint classhint;
43 XWMHints wmhints;
44 XTextProperty title;
45 Window root;
46 int ww, wh;
48 /* Open Connection to X Server */
49 d->display = XOpenDisplay(display_specified);
50 if (d->display == NULL) {
51 return -1;
54 d->x_offset = d->y_offset = 0;
55 ww = DOCKED_SIZE_W;
56 wh = DOCKED_SIZE_H;
57 if (iswindowed) {
58 d->x_offset = (WINDOWED_SIZE_W - DOCKED_SIZE_W) / 2;
59 d->y_offset = (WINDOWED_SIZE_H - DOCKED_SIZE_H) / 2;
60 ww = WINDOWED_SIZE_W;
61 wh = WINDOWED_SIZE_H;
64 /* Create Windows */
65 root = DefaultRootWindow(d->display);
66 d->icon_window = XCreateSimpleWindow(d->display, root, 0, 0, ww, wh, 0, 0, 0);
67 d->window = XCreateSimpleWindow(d->display, root, 0, 0, 1, 1, 0, 0, 0);
69 /* Set ClassHint */
70 classhint.res_class = "DockApp";
71 classhint.res_name = appname;
72 XSetClassHint(d->display, d->window, &classhint);
74 /* Set WMHints */
75 wmhints.flags = IconWindowHint | WindowGroupHint;
76 if (!iswindowed) {
77 wmhints.flags |= StateHint;
78 wmhints.initial_state = WithdrawnState;
80 wmhints.window_group = d->window;
81 wmhints.icon_window = d->icon_window;
82 XSetWMHints(d->display, d->window, &wmhints);
84 /* Set Size Hints */
85 sizehints.flags = USSize;
86 if (!iswindowed) {
87 sizehints.flags |= USPosition;
88 sizehints.x = sizehints.y = 0;
89 } else {
90 sizehints.flags |= PMinSize | PMaxSize;
91 sizehints.min_width = sizehints.max_width = WINDOWED_SIZE_W;
92 sizehints.min_height = sizehints.max_height = WINDOWED_SIZE_H;
94 sizehints.width = ww;
95 sizehints.height = wh;
96 XSetWMNormalHints(d->display, d->icon_window, &sizehints);
98 /* Set WindowTitle for AfterStep Wharf */
99 XStringListToTextProperty(&appname, 1, &title);
100 XSetWMName(d->display, d->window, &title);
101 XSetWMName(d->display, d->icon_window, &title);
102 XFree(title.value);
104 /* Set WM Protocols */
105 d->delete_win = XInternAtom(d->display, "WM_DELETE_WINDOW", False);
106 XSetWMProtocols(d->display, d->icon_window, &d->delete_win, 1);
108 /* Set Command to start the app so it can be docked properly */
109 XSetCommand(d->display, d->window, argv, argc);
111 d->width = DOCKED_SIZE_W;
112 d->height = DOCKED_SIZE_H;
113 d->iswindowed = iswindowed;
114 d->depth = DefaultDepth(d->display, DefaultScreen(d->display));
115 d->gc = DefaultGC(d->display, DefaultScreen(d->display));
117 d->quit = False;
118 d->pixmap = dockapp_createpixmap(d, ww, wh);
119 XSetForeground(d->display, d->gc, dockapp_get_color(d, "rgb:ae/aa/ae"));
120 XFillRectangle(d->display, d->pixmap, d->gc, 0, 0, ww, wh);
121 XSetWindowBackgroundPixmap(d->display, d->icon_window, d->pixmap);
122 XSetWindowBackgroundPixmap(d->display, d->window, d->pixmap);
123 XClearWindow(d->display, d->icon_window);
125 if (!d->iswindowed) {
126 XMapRaised(d->display, d->window);
127 } else {
128 XMapRaised(d->display, d->icon_window);
131 XFlush(d->display);
133 return 0;
137 void
138 dockapp_set_eventmask(const DOCKAPP *d, long mask)
140 XSelectInput(d->display, d->icon_window, mask);
141 XSelectInput(d->display, d->window, mask);
145 void
146 dockapp_set_shape(const DOCKAPP *d, Pixmap mask)
148 XShapeCombineMask(d->display, d->icon_window, ShapeBounding,
149 d->x_offset, d->y_offset, mask, ShapeSet);
150 XShapeCombineMask(d->display, d->window, ShapeBounding,
151 d->x_offset, d->y_offset, mask, ShapeSet);
152 XFlush(d->display);
156 void
157 dockapp_copy_area(const DOCKAPP *d,
158 Pixmap src,
159 int x_src, int y_src, int w, int h, int x_dst, int y_dst)
161 XCopyArea(d->display, src, d->pixmap, d->gc, x_src, y_src, w, h, x_dst + d->x_offset, y_dst + d->y_offset);
165 void
166 dockapp_update(const DOCKAPP *d)
168 XClearWindow(d->display, d->icon_window);
172 Bool
173 dockapp_xpm2pixmap(const DOCKAPP *d,
174 char **data, Pixmap *pixmap, Pixmap *mask,
175 XpmColorSymbol *colorSymbol, unsigned int nsymbols)
177 XpmAttributes xpmAttr;
178 xpmAttr.valuemask = XpmCloseness;
179 xpmAttr.closeness = 1 << 15;
181 if (nsymbols) {
182 xpmAttr.colorsymbols = colorSymbol;
183 xpmAttr.numsymbols = nsymbols;
184 xpmAttr.valuemask |= XpmColorSymbols;
187 return (XpmCreatePixmapFromData(d->display, d->icon_window, data, pixmap, mask, &xpmAttr) == 0);
191 Pixmap
192 dockapp_createpixmap(const DOCKAPP *d, int width, int height)
194 return XCreatePixmap(d->display, d->icon_window, width, height, d->depth);
198 Bool
199 dockapp_nextevent_or_timeout(DOCKAPP *d,
200 XEvent *event, unsigned long millis)
202 struct timeval timeout;
203 fd_set rset;
205 XSync(d->display, False);
206 if (XPending(d->display)) {
207 XNextEvent(d->display, event);
208 return True;
211 timeout.tv_sec = millis / 1000;
212 timeout.tv_usec = (millis % 1000) * 1000;
214 FD_ZERO(&rset);
215 FD_SET(ConnectionNumber(d->display), &rset);
216 if (select(ConnectionNumber(d->display) + 1, &rset, NULL, NULL, &timeout) > 0) {
217 XNextEvent(d->display, event);
218 if (event->type == ClientMessage) {
219 if ((Atom)event->xclient.data.l[0] == d->delete_win) {
220 d->quit = True;
221 return False;
224 if (d->iswindowed) {
225 event->xbutton.x -= d->x_offset;
226 event->xbutton.y -= d->y_offset;
228 return True;
231 return False;
235 unsigned long
236 dockapp_get_color(const DOCKAPP *d, const char *color_name)
238 XColor color;
240 if (!XParseColor(d->display, DefaultColormap(d->display, DefaultScreen(d->display)), color_name, &color)) {
241 return BlackPixel(d->display, DefaultScreen(d->display));
244 if (!XAllocColor(d->display, DefaultColormap(d->display, DefaultScreen(d->display)), &color)) {
245 return BlackPixel(d->display, DefaultScreen(d->display));
248 return color.pixel;