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>
27 #define PANEL_SIZE_W 64
28 #define PANEL_SIZE_H 64
31 Display
*display
= NULL
;
32 Bool dockapp_isbrokenwm
= False
;
33 dockapp_status dockapp_stat
;
37 static Window window
= None
;
38 static Window icon_window
= None
;
41 static int width
, height
;
42 static int offset_w
, offset_h
;
45 dockapp_open_window(char *display_specified
, char *appname
,
46 unsigned w
, unsigned h
, int argc
, char **argv
)
48 XClassHint
*classhint
;
56 /* Open Connection to X Server */
57 display
= XOpenDisplay(display_specified
);
59 fprintf(stderr
, "%s: can't open display %s!\n",
61 XDisplayName(display_specified
));
64 root
= DefaultRootWindow(display
);
68 * width, height: drawble area size
72 if (dockapp_stat
== WINDOWED_WITH_PANEL
) {
79 offset_w
= (ww
- w
) / 2;
80 offset_h
= (wh
- h
) / 2;
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);
87 window
= XCreateSimpleWindow(display
, root
, 0, 0, 1, 1, 0, 0, 0);
91 classhint
= XAllocClassHint();
92 if (classhint
== NULL
) {
93 fprintf(stderr
, "%s: can't allocate memory for wm hints!\n", argv
[0]);
96 classhint
->res_class
= "DockApp";
97 classhint
->res_name
= appname
;
98 XSetClassHint(display
, window
, classhint
);
99 XSetClassHint(display
, icon_window
, classhint
);
103 wmhints
= XAllocWMHints();
104 if (wmhints
== NULL
) {
105 fprintf(stderr
, "%s: can't allocate memory for wm hints!\n", argv
[0]);
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
);
118 /* Set WM Protocols */
119 delete_win
= XInternAtom(display
, "WM_DELETE_WINDOW", False
);
120 XSetWMProtocols (display
, icon_window
, &delete_win
, 1);
123 sizehints
.flags
= USSize
;
124 switch(dockapp_stat
) {
126 sizehints
.flags
|= USPosition
;
127 sizehints
.x
= sizehints
.y
= 0;
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
;
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
));
156 dockapp_set_eventmask(long mask
)
158 XSelectInput(display
, icon_window
, mask
);
159 XSelectInput(display
, window
, mask
);
164 create_bgpanel_pixmap(void)
168 bg
= XCreatePixmap(display
, icon_window
, PANEL_SIZE_W
, PANEL_SIZE_H
,
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);
188 dockapp_set_background(Pixmap pixmap
)
190 if (dockapp_stat
== WINDOWED_WITH_PANEL
) {
192 bg
= create_bgpanel_pixmap();
193 XCopyArea(display
, pixmap
, bg
, gc
, 0, 0, width
, height
,
195 XSetWindowBackgroundPixmap(display
, icon_window
, bg
);
196 XSetWindowBackgroundPixmap(display
, window
, bg
);
197 XFreePixmap(display
, bg
);
199 XSetWindowBackgroundPixmap(display
, icon_window
, pixmap
);
200 XSetWindowBackgroundPixmap(display
, window
, pixmap
);
202 XClearWindow(display
, icon_window
);
210 if (dockapp_stat
== DOCKABLE_ICON
)
211 XMapRaised(display
, window
);
213 XMapRaised(display
, icon_window
);
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;
228 xpmAttr
.colorsymbols
= colorSymbol
;
229 xpmAttr
.numsymbols
= nsymbols
;
230 xpmAttr
.valuemask
|= XpmColorSymbols
;
233 if (XpmCreatePixmapFromData(display
, icon_window
, data
, pixmap
, mask
,
243 dockapp_XCreatePixmap(int w
, int h
)
245 return (XCreatePixmap(display
, icon_window
, w
, h
, depth
));
250 dockapp_setshape(Pixmap mask
, int x_ofs
, int y_ofs
)
252 XShapeCombineMask(display
, icon_window
, ShapeBounding
, -x_ofs
, -y_ofs
,
254 XShapeCombineMask(display
, window
, ShapeBounding
, -x_ofs
, -y_ofs
,
261 dockapp_copyarea(Pixmap src
, Pixmap dist
, int x_src
, int y_src
, int w
, int h
,
262 int x_dist
, int y_dist
)
266 win
= dockapp_isbrokenwm
? window
: icon_window
;
277 XCopyArea(display
, src
, dist
, gc
, x_src
, y_src
, w
, h
, x_dist
, y_dist
);
281 dockapp_copy2window(Pixmap src
, int x_src
, int y_src
, int w
, int h
, int x_dist
,
286 win
= dockapp_isbrokenwm
? window
: icon_window
;
288 XCopyArea(display
, src
, win
, gc
, x_src
, y_src
, w
, h
, offset_w
+ x_dist
,
295 return dockapp_isbrokenwm
? window
: icon_window
;
299 dockapp_nextevent_or_timeout(XEvent
*event
, unsigned long miliseconds
)
301 struct timeval timeout
;
304 XSync(display
, False
);
305 if (XPending(display
)) {
306 XNextEvent(display
, event
);
310 timeout
.tv_sec
= miliseconds
/ 1000;
311 timeout
.tv_usec
= (miliseconds
% 1000) * 1000;
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
);
324 event
->xbutton
.x
-= offset_w
;
325 event
->xbutton
.y
-= offset_h
;
333 get_closest_color_pixel(unsigned long red
, unsigned long green
, unsigned long blue
)
336 XColor closest_color
;
338 int closest_index
= -1;
339 unsigned long min_diff
= 0xffffffff;
341 unsigned long diff_r
= 0, diff_g
= 0, diff_b
= 0;
343 int ncells
= DisplayCells(display
, DefaultScreen(display
));
346 if ((all_colors
= malloc(ncells
* sizeof(XColor
))) == NULL
) {
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 ? */
373 if (closest_index
== -1) { /* unable to find closest color */
374 fprintf(stderr
, "can't allocate color #%lu/%lu/%lu, Using black\n",
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
;
387 if (!XAllocColor(display
, DefaultColormap(display
, DefaultScreen(display
)),
389 return BlackPixel(display
, DefaultScreen(display
));
392 return closest_color
.pixel
;
396 dockapp_getcolor_pixel(char *color_name
)
398 Visual
*visual
= DefaultVisual( display
, DefaultScreen(display
)) ;
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
,
410 fprintf(stderr
, "can't allocate color %s. Using black\n",
412 return BlackPixel(display
, DefaultScreen(display
));
416 return exact_color
.pixel
;
421 dockapp_blendedcolor(char *color_name
, int r
, int g
, int b
, float fac
)
423 Visual
*visual
= DefaultVisual( display
, DefaultScreen(display
)) ;
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
);
435 if (!XParseColor(display
, DefaultColormap(display
, DefaultScreen(display
)),
437 fprintf(stderr
, "can't parse color %s\n", color_name
), exit(1);
440 if (color
.red
+ r
> 0xffff) {
442 } else if (color
.red
+ r
< 0) {
445 color
.red
= (unsigned short)(fac
* color
.red
+ r
);
449 if (color
.green
+ g
> 0xffff) {
450 color
.green
= 0xffff;
451 } else if (color
.green
+ g
< 0) {
454 color
.green
= (unsigned short)(fac
* color
.green
+ g
);
458 if (color
.blue
+ b
> 0xffff) {
460 } else if (color
.blue
+ b
< 0) {
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
)),
472 return BlackPixel(display
, DefaultScreen(display
));
478 /* ex:set sw=4 softtabstop=4: */