Strip off version numbers from dir name
[dockapps.git] / wmcpuload / libdockapp / dockapp.c
blobb34c5042c7599547452941b2a07e886d6d72b7fd
1 /*
2 * Copyright (c) 1999 Alfredo K. Kojima
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 * This code is based on libdockapp-0.4.0
22 * modified by Seiichi SATO <ssato@sh.rim.or.jp>
25 #include "dockapp.h"
27 #define PANEL_SIZE_W 64
28 #define PANEL_SIZE_H 64
30 /* global */
31 Display *display = NULL;
32 Bool dockapp_isbrokenwm = False;
33 dockapp_status dockapp_stat;
34 Atom delete_win;
36 /* private */
37 static Window window = None;
38 static Window icon_window = None;
39 static GC gc = NULL;
40 static int depth = 0;
41 static int width, height;
42 static int offset_w, offset_h;
44 void
45 dockapp_open_window(char *display_specified, char *appname,
46 unsigned w, unsigned h, int argc, char **argv)
48 XClassHint *classhint;
49 XWMHints *wmhints;
50 Status stat;
51 XTextProperty title;
52 XSizeHints sizehints;
53 Window root;
54 int ww, wh;
56 /* Open Connection to X Server */
57 display = XOpenDisplay(display_specified);
58 if (!display) {
59 fprintf(stderr, "%s: can't open display %s!\n",
60 argv[0],
61 XDisplayName(display_specified));
62 exit(1);
64 root = DefaultRootWindow(display);
67 * ww, wh: window size
68 * width, height: drawble area size
70 width = w;
71 height = h;
72 if (dockapp_stat == WINDOWED_WITH_PANEL) {
73 ww = PANEL_SIZE_W;
74 wh = PANEL_SIZE_H;
75 } else {
76 ww = w;
77 wh = h;
79 offset_w = (ww - w) / 2;
80 offset_h = (wh - h) / 2;
82 /* Create Windows */
83 icon_window = XCreateSimpleWindow(display, root, 0, 0, ww, wh, 0, 0, 0);
84 if (dockapp_isbrokenwm) {
85 window = XCreateSimpleWindow(display, root, 0, 0, ww, wh, 0, 0, 0);
86 } else {
87 window = XCreateSimpleWindow(display, root, 0, 0, 1, 1, 0, 0, 0);
90 /* Set ClassHint */
91 classhint = XAllocClassHint();
92 if (classhint == NULL) {
93 fprintf(stderr, "%s: can't allocate memory for wm hints!\n", argv[0]);
94 exit(1);
96 classhint->res_class = "DockApp";
97 classhint->res_name = appname;
98 XSetClassHint(display, window, classhint);
99 XSetClassHint(display, icon_window, classhint);
100 XFree(classhint);
102 /* Set WMHints */
103 wmhints = XAllocWMHints();
104 if (wmhints == NULL) {
105 fprintf(stderr, "%s: can't allocate memory for wm hints!\n", argv[0]);
106 exit(1);
108 wmhints->flags = IconWindowHint | WindowGroupHint;
109 if (dockapp_stat == DOCKABLE_ICON) {
110 wmhints->flags |= StateHint;
111 wmhints->initial_state = WithdrawnState;
113 wmhints->window_group = window;
114 wmhints->icon_window = icon_window;
115 XSetWMHints(display, window, wmhints);
116 XFree(wmhints);
118 /* Set WM Protocols */
119 delete_win = XInternAtom(display, "WM_DELETE_WINDOW", False);
120 XSetWMProtocols (display, icon_window, &delete_win, 1);
122 /* Set Size Hints */
123 sizehints.flags = USSize;
124 switch(dockapp_stat) {
125 case DOCKABLE_ICON:
126 sizehints.flags |= USPosition;
127 sizehints.x = sizehints.y = 0;
128 break;
129 case WINDOWED:
130 case WINDOWED_WITH_PANEL:
131 sizehints.flags |= PMinSize | PMaxSize;
132 sizehints.min_width = sizehints.max_width = ww;
133 sizehints.min_height = sizehints.max_height = wh;
134 break;
136 sizehints.width = ww;
137 sizehints.height = wh;
138 XSetWMNormalHints(display, icon_window, &sizehints);
140 /* Set WindowTitle for AfterStep Wharf */
141 stat = XStringListToTextProperty(&appname, 1, &title);
142 XSetWMName(display, window, &title);
143 XSetWMName(display, icon_window, &title);
145 /* Set Command to start the app so it can be docked properly */
146 XSetCommand(display, window, argv, argc);
148 depth = DefaultDepth(display, DefaultScreen(display));
149 gc = DefaultGC(display, DefaultScreen(display));
151 XFlush(display);
155 void
156 dockapp_set_eventmask(long mask)
158 XSelectInput(display, icon_window, mask);
159 XSelectInput(display, window, mask);
163 static Pixmap
164 create_bgpanel_pixmap(void)
166 Pixmap bg;
168 bg = XCreatePixmap(display, icon_window, PANEL_SIZE_W, PANEL_SIZE_H,
169 depth);
170 XSetForeground(display, gc, dockapp_getcolor_pixel("rgb:ae/aa/ae"));
171 XFillRectangle(display, bg, gc, 0, 0, PANEL_SIZE_W, PANEL_SIZE_H);
172 XSetForeground(display, gc, dockapp_getcolor_pixel("rgb:ff/ff/ff"));
173 XDrawLine(display, bg, gc, 0, 0, 0, 63);
174 XDrawLine(display, bg, gc, 1, 0, 1, 62);
175 XDrawLine(display, bg, gc, 2, 0, 63, 0);
176 XDrawLine(display, bg, gc, 2, 1, 62, 1);
177 XSetForeground(display, gc, dockapp_getcolor_pixel("rgb:52/55/52"));
178 XDrawLine(display, bg, gc, 1, 63, 63, 63);
179 XDrawLine(display, bg, gc, 2, 62, 63, 62);
180 XDrawLine(display, bg, gc, 63, 1, 63, 61);
181 XDrawLine(display, bg, gc, 62, 2, 62, 61);
183 return bg;
187 void
188 dockapp_set_background(Pixmap pixmap)
190 if (dockapp_stat == WINDOWED_WITH_PANEL) {
191 Pixmap bg;
192 bg = create_bgpanel_pixmap();
193 XCopyArea(display, pixmap, bg, gc, 0, 0, width, height,
194 offset_w, offset_w);
195 XSetWindowBackgroundPixmap(display, icon_window, bg);
196 XSetWindowBackgroundPixmap(display, window, bg);
197 XFreePixmap(display, bg);
198 } else {
199 XSetWindowBackgroundPixmap(display, icon_window, pixmap);
200 XSetWindowBackgroundPixmap(display, window, pixmap);
202 XClearWindow(display, icon_window);
203 XFlush(display);
207 void
208 dockapp_show(void)
210 if (dockapp_stat == DOCKABLE_ICON)
211 XMapRaised(display, window);
212 else
213 XMapRaised(display, icon_window);
215 XFlush(display);
219 Bool
220 dockapp_xpm2pixmap(char **data, Pixmap *pixmap, Pixmap *mask,
221 XpmColorSymbol * colorSymbol, unsigned int nsymbols)
223 XpmAttributes xpmAttr;
224 xpmAttr.valuemask = XpmCloseness;
225 xpmAttr.closeness = 40000;
227 if (nsymbols) {
228 xpmAttr.colorsymbols = colorSymbol;
229 xpmAttr.numsymbols = nsymbols;
230 xpmAttr.valuemask |= XpmColorSymbols;
233 if (XpmCreatePixmapFromData(display, icon_window, data, pixmap, mask,
234 &xpmAttr) != 0) {
235 return False;
238 return True;
242 Pixmap
243 dockapp_XCreatePixmap(int w, int h)
245 return (XCreatePixmap(display, icon_window, w, h, depth));
249 void
250 dockapp_setshape(Pixmap mask, int x_ofs, int y_ofs)
252 XShapeCombineMask(display, icon_window, ShapeBounding, -x_ofs, -y_ofs,
253 mask, ShapeSet);
254 XShapeCombineMask(display, window, ShapeBounding, -x_ofs, -y_ofs,
255 mask, ShapeSet);
256 XFlush(display);
260 void
261 dockapp_copyarea(Pixmap src, Pixmap dist, int x_src, int y_src, int w, int h,
262 int x_dist, int y_dist)
264 XCopyArea(display, src, dist, gc, x_src, y_src, w, h, x_dist, y_dist);
268 void
269 dockapp_copy2window (Pixmap src)
271 if (dockapp_isbrokenwm) {
272 XCopyArea(display, src, window, gc, 0, 0, width, height, offset_w,
273 offset_h);
274 } else {
275 XCopyArea(display, src, icon_window, gc, 0, 0, width, height, offset_w,
276 offset_h);
281 Bool
282 dockapp_nextevent_or_timeout(XEvent *event, unsigned long miliseconds)
284 struct timeval timeout;
285 fd_set rset;
287 XSync(display, False);
288 if (XPending(display)) {
289 XNextEvent(display, event);
290 return True;
293 timeout.tv_sec = miliseconds / 1000;
294 timeout.tv_usec = (miliseconds % 1000) * 1000;
296 FD_ZERO(&rset);
297 FD_SET(ConnectionNumber(display), &rset);
298 if (select(ConnectionNumber(display)+1, &rset, NULL, NULL, &timeout) > 0) {
299 XNextEvent(display, event);
300 if (event->type == ClientMessage) {
301 if (event->xclient.data.l[0] == delete_win) {
302 XDestroyWindow(display, event->xclient.window);
303 XCloseDisplay(display);
304 exit(0);
307 event->xbutton.x -= offset_w;
308 event->xbutton.y -= offset_h;
309 return True;
312 return False;
315 static long
316 get_closest_color_pixel(unsigned long red, unsigned long green, unsigned long blue)
318 XColor *all_colors;
319 XColor closest_color;
321 int closest_index = -1;
322 unsigned long min_diff = 0xffffffff;
323 unsigned long diff;
324 unsigned long diff_r = 0, diff_g = 0, diff_b = 0;
326 int ncells = DisplayCells(display, DefaultScreen(display));
327 int i;
329 if ((all_colors = malloc(ncells * sizeof(XColor))) == NULL) {
330 perror("malloc");
331 return(1);
334 /* get all colors from default colormap */
335 for (i = 0; i < ncells; i++) {
336 all_colors[i].pixel = i;
338 XQueryColors( display , DefaultColormap(display, DefaultScreen(display)),
339 all_colors, ncells) ;
341 /* find the closest color */
342 for (i = 0; i < ncells; i++) {
343 diff_r = (red - all_colors[i].red) >> 8 ;
344 diff_g = (green - all_colors[i].green) >> 8 ;
345 diff_r = (blue - all_colors[i].blue) >> 8 ;
347 diff = diff_r * diff_r + diff_g * diff_g + diff_b * diff_b ;
349 if ( diff < min_diff) /* closest ? */
351 min_diff = diff ;
352 closest_index = i ;
356 if (closest_index == -1) { /* unable to find closest color */
357 fprintf(stderr, "can't allocate color #%lu/%lu/%lu, Using black\n",
358 red, green, blue);
359 free(all_colors);
360 return BlackPixel(display, DefaultScreen(display));
363 closest_color.red = all_colors[closest_index].red;
364 closest_color.green = all_colors[closest_index].green;
365 closest_color.blue = all_colors[closest_index].blue;
366 closest_color.flags = DoRed | DoGreen | DoBlue;
368 free(all_colors);
370 if (!XAllocColor(display, DefaultColormap(display, DefaultScreen(display)),
371 &closest_color)) {
372 return BlackPixel(display, DefaultScreen(display));
375 return closest_color.pixel;
378 unsigned long
379 dockapp_getcolor_pixel(char *color_name)
381 Visual *visual = DefaultVisual( display , DefaultScreen(display)) ;
382 XColor screen_color;
383 XColor exact_color;
385 if (!XAllocNamedColor(display,
386 DefaultColormap(display, DefaultScreen(display)),
387 color_name, &screen_color, &exact_color)) {
388 if (visual->class == PseudoColor || visual->class == GrayScale) {
389 return get_closest_color_pixel(screen_color.red,
390 screen_color.green,
391 screen_color.blue);
392 } else {
393 fprintf(stderr, "can't allocate color %s. Using black\n",
394 color_name);
395 return BlackPixel(display, DefaultScreen(display));
399 return exact_color.pixel;
403 unsigned long
404 dockapp_blendedcolor(char *color_name, int r, int g, int b, float fac)
406 Visual *visual = DefaultVisual( display , DefaultScreen(display)) ;
407 XColor color;
409 if ((r < -255 || r > 255)||(g < -255 || g > 255)||(b < -255 || b > 255)){
410 fprintf(stderr, "r:%d,g:%d,b:%d (r,g,b must be 0 to 255)", r, g, b);
411 exit(1);
414 r *= 255;
415 g *= 255;
416 b *= 255;
418 if (!XParseColor(display, DefaultColormap(display, DefaultScreen(display)),
419 color_name, &color))
420 fprintf(stderr, "can't parse color %s\n", color_name), exit(1);
422 /* red */
423 if (color.red + r > 0xffff) {
424 color.red = 0xffff;
425 } else if (color.red + r < 0) {
426 color.red = 0;
427 } else {
428 color.red = (unsigned short)(fac * color.red + r);
431 /* green */
432 if (color.green + g > 0xffff) {
433 color.green = 0xffff;
434 } else if (color.green + g < 0) {
435 color.green = 0;
436 } else {
437 color.green = (unsigned short)(fac * color.green + g);
440 /* blue */
441 if (color.blue + b > 0xffff) {
442 color.blue = 0xffff;
443 } else if (color.blue + b < 0) {
444 color.blue = 0;
445 } else {
446 color.blue = (unsigned short)(fac * color.blue + b);
449 if (visual->class == PseudoColor || visual->class == GrayScale) {
450 return get_closest_color_pixel(color.red, color.green, color.blue);
453 if (!XAllocColor(display, DefaultColormap(display, DefaultScreen(display)),
454 &color)) {
455 return BlackPixel(display, DefaultScreen(display));
458 return color.pixel;