wmclockmon: update change-log
[dockapps.git] / wmcpuload / libdockapp / dockapp.c
blob5b8571ec2ed35b995ae774863607bfcc50ac2095
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 Window win;
266 win = dockapp_isbrokenwm ? window : icon_window;
268 if (src == win) {
269 x_src += offset_w;
270 y_src += offset_h;
272 if (dist == win) {
273 x_dist += offset_w;
274 y_dist += offset_h;
277 XCopyArea(display, src, dist, gc, x_src, y_src, w, h, x_dist, y_dist);
280 void
281 dockapp_copy2window(Pixmap src, int x_src, int y_src, int w, int h, int x_dist,
282 int y_dist)
284 Window win;
286 win = dockapp_isbrokenwm ? window : icon_window;
288 XCopyArea(display, src, win, gc, x_src, y_src, w, h, offset_w + x_dist,
289 offset_h + y_dist);
292 Window
293 dockapp_win(void)
295 return dockapp_isbrokenwm ? window : icon_window;
298 Bool
299 dockapp_nextevent_or_timeout(XEvent *event, unsigned long miliseconds)
301 struct timeval timeout;
302 fd_set rset;
304 XSync(display, False);
305 if (XPending(display)) {
306 XNextEvent(display, event);
307 return True;
310 timeout.tv_sec = miliseconds / 1000;
311 timeout.tv_usec = (miliseconds % 1000) * 1000;
313 FD_ZERO(&rset);
314 FD_SET(ConnectionNumber(display), &rset);
315 if (select(ConnectionNumber(display)+1, &rset, NULL, NULL, &timeout) > 0) {
316 XNextEvent(display, event);
317 if (event->type == ClientMessage) {
318 if (event->xclient.data.l[0] == delete_win) {
319 XDestroyWindow(display, event->xclient.window);
320 XCloseDisplay(display);
321 exit(0);
324 event->xbutton.x -= offset_w;
325 event->xbutton.y -= offset_h;
326 return True;
329 return False;
332 static long
333 get_closest_color_pixel(unsigned long red, unsigned long green, unsigned long blue)
335 XColor *all_colors;
336 XColor closest_color;
338 int closest_index = -1;
339 unsigned long min_diff = 0xffffffff;
340 unsigned long diff;
341 unsigned long diff_r = 0, diff_g = 0, diff_b = 0;
343 int ncells = DisplayCells(display, DefaultScreen(display));
344 int i;
346 if ((all_colors = malloc(ncells * sizeof(XColor))) == NULL) {
347 perror("malloc");
348 return(1);
351 /* get all colors from default colormap */
352 for (i = 0; i < ncells; i++) {
353 all_colors[i].pixel = i;
355 XQueryColors( display , DefaultColormap(display, DefaultScreen(display)),
356 all_colors, ncells) ;
358 /* find the closest color */
359 for (i = 0; i < ncells; i++) {
360 diff_r = (red - all_colors[i].red) >> 8 ;
361 diff_g = (green - all_colors[i].green) >> 8 ;
362 diff_r = (blue - all_colors[i].blue) >> 8 ;
364 diff = diff_r * diff_r + diff_g * diff_g + diff_b * diff_b ;
366 if ( diff < min_diff) /* closest ? */
368 min_diff = diff ;
369 closest_index = i ;
373 if (closest_index == -1) { /* unable to find closest color */
374 fprintf(stderr, "can't allocate color #%lu/%lu/%lu, Using black\n",
375 red, green, blue);
376 free(all_colors);
377 return BlackPixel(display, DefaultScreen(display));
380 closest_color.red = all_colors[closest_index].red;
381 closest_color.green = all_colors[closest_index].green;
382 closest_color.blue = all_colors[closest_index].blue;
383 closest_color.flags = DoRed | DoGreen | DoBlue;
385 free(all_colors);
387 if (!XAllocColor(display, DefaultColormap(display, DefaultScreen(display)),
388 &closest_color)) {
389 return BlackPixel(display, DefaultScreen(display));
392 return closest_color.pixel;
395 unsigned long
396 dockapp_getcolor_pixel(char *color_name)
398 Visual *visual = DefaultVisual( display , DefaultScreen(display)) ;
399 XColor screen_color;
400 XColor exact_color;
402 if (!XAllocNamedColor(display,
403 DefaultColormap(display, DefaultScreen(display)),
404 color_name, &screen_color, &exact_color)) {
405 if (visual->class == PseudoColor || visual->class == GrayScale) {
406 return get_closest_color_pixel(screen_color.red,
407 screen_color.green,
408 screen_color.blue);
409 } else {
410 fprintf(stderr, "can't allocate color %s. Using black\n",
411 color_name);
412 return BlackPixel(display, DefaultScreen(display));
416 return exact_color.pixel;
420 unsigned long
421 dockapp_blendedcolor(char *color_name, int r, int g, int b, float fac)
423 Visual *visual = DefaultVisual( display , DefaultScreen(display)) ;
424 XColor color;
426 if ((r < -255 || r > 255)||(g < -255 || g > 255)||(b < -255 || b > 255)){
427 fprintf(stderr, "r:%d,g:%d,b:%d (r,g,b must be 0 to 255)", r, g, b);
428 exit(1);
431 r *= 255;
432 g *= 255;
433 b *= 255;
435 if (!XParseColor(display, DefaultColormap(display, DefaultScreen(display)),
436 color_name, &color))
437 fprintf(stderr, "can't parse color %s\n", color_name), exit(1);
439 /* red */
440 if (color.red + r > 0xffff) {
441 color.red = 0xffff;
442 } else if (color.red + r < 0) {
443 color.red = 0;
444 } else {
445 color.red = (unsigned short)(fac * color.red + r);
448 /* green */
449 if (color.green + g > 0xffff) {
450 color.green = 0xffff;
451 } else if (color.green + g < 0) {
452 color.green = 0;
453 } else {
454 color.green = (unsigned short)(fac * color.green + g);
457 /* blue */
458 if (color.blue + b > 0xffff) {
459 color.blue = 0xffff;
460 } else if (color.blue + b < 0) {
461 color.blue = 0;
462 } else {
463 color.blue = (unsigned short)(fac * color.blue + b);
466 if (visual->class == PseudoColor || visual->class == GrayScale) {
467 return get_closest_color_pixel(color.red, color.green, color.blue);
470 if (!XAllocColor(display, DefaultColormap(display, DefaultScreen(display)),
471 &color)) {
472 return BlackPixel(display, DefaultScreen(display));
475 return color.pixel;
478 /* ex:set sw=4 softtabstop=4: */