10 #include "dockapp_imlib2.h"
11 #include <X11/extensions/shape.h>
12 #include <X11/Xutil.h>
17 /* require ISO C99 compatibility */
18 #define DOCKIMLIB2_ERR(...) { fprintf(stderr, "DockImlib2 " DOCKIMLIB2_VERSION " error: "); \
19 fprintf(stderr, __VA_ARGS__); exit(1); }
20 #define DOCKIMLIB2_WARN(...) { fprintf(stderr, "DockImlib2 " DOCKIMLIB2_VERSION " warning: "); \
21 fprintf(stderr, __VA_ARGS__); exit(1); }
23 static void dockimlib2_set_rect_shape(DockImlib2
*dock
, int x
, int y
, int w
, int h
) {
24 Pixmap mask
= XCreatePixmap(dock
->display
, dock
->win
, dock
->win_width
, dock
->win_height
, 1); assert(mask
);
25 GC gc
= XCreateGC(dock
->display
, mask
, 0, NULL
);
26 XSetForeground(dock
->display
, gc
, BlackPixel(dock
->display
, dock
->screennum
));
27 XFillRectangle(dock
->display
, mask
, gc
, 0, 0, dock
->win_width
, dock
->win_height
);
28 XSetForeground(dock
->display
, gc
, WhitePixel(dock
->display
, dock
->screennum
));
29 XFillRectangle(dock
->display
, mask
, gc
, x
,y
,w
,h
);
30 XFreeGC(dock
->display
,gc
);
31 /* setup shaped window */
32 XShapeCombineMask(dock
->display
, dock
->normalwin
, ShapeBounding
,
33 0, 0, mask
, ShapeSet
);
35 XShapeCombineMask(dock
->display
, dock
->iconwin
, ShapeBounding
,
36 0, 0, mask
, ShapeSet
);
37 XFreePixmap(dock
->display
, mask
);
40 /* some general windowmanager related functions ...*/
41 void set_window_title(Display
*display
, Window win
, char *window_title
, char *icon_title
) {
43 XTextProperty window_title_property
;
45 rc
= XStringListToTextProperty(&window_title
,1, &window_title_property
); assert(rc
);
46 XSetWMName(display
, win
, &window_title_property
);
47 XFree(window_title_property
.value
);
49 /* icon window name */
50 rc
= XStringListToTextProperty(&icon_title
,1, &window_title_property
); assert(rc
);
51 XSetWMIconName(display
, win
, &window_title_property
);
52 XFree(window_title_property
.value
);
56 set_window_class_hint(Display
*display
, Window win
, char *res_class
, char *res_name
) {
57 XClassHint
*class_hint
;
58 class_hint
= XAllocClassHint();
59 class_hint
->res_name
= res_name
;
60 class_hint
->res_class
= res_class
;
61 XSetClassHint(display
, win
, class_hint
);
66 static void dockimlib2_xinit(DockImlib2
*dock
, DockImlib2Prefs
*prefs
) {
69 char *sdisplay
= getenv("DISPLAY");
74 assert(prefs
->argv
); // this should be always set ..
76 if (prefs
->flags
& DOCKPREF_DISPLAY
) sdisplay
= prefs
->display
;
77 if (prefs
->flags
& DOCKPREF_GEOMETRY
) { pgeom
= prefs
->geometry
; undocked
= 1; }
79 dock
->display
= XOpenDisplay(sdisplay
);
80 if(!dock
->display
) DOCKIMLIB2_ERR("Couldn't connect to display %s\n", sdisplay
);
81 dock
->screennum
= DefaultScreen(dock
->display
);
82 dock
->visual
= DefaultVisual(dock
->display
, dock
->screennum
);
83 dock
->depth
= DefaultDepth(dock
->display
, dock
->screennum
);
84 dock
->colormap
= DefaultColormap(dock
->display
, dock
->screennum
);
85 dock
->rootwin
= RootWindow(dock
->display
, dock
->screennum
);
87 dock
->atom_WM_DELETE_WINDOW
= XInternAtom(dock
->display
, "WM_DELETE_WINDOW", False
);
88 dock
->atom_WM_PROTOCOLS
= XInternAtom(dock
->display
, "WM_PROTOCOLS", False
);
91 xsh
= XAllocSizeHints(); assert(xsh
);
94 xsh
->height
= dock
->h
;
97 snprintf(sdockgeom
, sizeof sdockgeom
, "%dx%d+0+0", prefs
->dockapp_size
, prefs
->dockapp_size
);
99 xsh
->flags
= XWMGeometry(dock
->display
, dock
->screennum
, pgeom
, sdockgeom
, 0,
100 xsh
, &xsh
->x
, &xsh
->y
, &xsh
->width
, &xsh
->height
, &i
);
102 dock
->win_width
= dock
->w
= xsh
->width
;
103 dock
->win_height
= dock
->h
= xsh
->height
;
104 dock
->x0
= dock
->y0
= 0;
106 xsh
->base_width
= xsh
->width
;
107 xsh
->base_height
= xsh
->height
;
108 xsh
->flags
|= USSize
| PMinSize
| PMaxSize
| PSize
;
109 xsh
->min_height
= 24; xsh
->min_height
= 24;
110 xsh
->max_width
= 500;
111 xsh
->max_height
= 500;
113 /* create the application window */
114 dock
->normalwin
= XCreateSimpleWindow(dock
->display
, dock
->rootwin
,
115 xsh
->x
, xsh
->y
, xsh
->width
, xsh
->height
, 0,
116 BlackPixel(dock
->display
, dock
->screennum
),
117 WhitePixel(dock
->display
, dock
->screennum
));
119 if(!dock
->normalwin
) DOCKIMLIB2_ERR("Couldn't create window\n");
121 /* create icon window */
122 dock
->iconwin
= XCreateSimpleWindow(dock
->display
, dock
->rootwin
,
123 xsh
->x
, xsh
->y
, xsh
->width
, xsh
->height
, 0,
124 BlackPixel(dock
->display
, dock
->screennum
),
125 WhitePixel(dock
->display
, dock
->screennum
));
126 if(!dock
->iconwin
) DOCKIMLIB2_ERR("Couldn't create icon window\n");
127 dock
->win
= dock
->iconwin
;
129 dock
->iconwin
= None
;
130 dock
->win
= dock
->normalwin
;
132 dock
->iconwin_mapped
= dock
->normalwin_mapped
= 1; /* by default */
134 /* start with an empty window in order to get the background pixmap */
135 dockimlib2_set_rect_shape(dock
,32,32,1,0);
137 /* set window manager hints */
140 xwmh
= XAllocWMHints();
141 xwmh
->flags
= WindowGroupHint
| IconWindowHint
| StateHint
;
142 xwmh
->icon_window
= dock
->iconwin
;
143 xwmh
->window_group
= dock
->normalwin
;
144 xwmh
->initial_state
= WithdrawnState
;
145 XSetWMHints(dock
->display
, dock
->normalwin
, xwmh
);
146 XFree(xwmh
); xwmh
= NULL
;
148 set_window_class_hint(dock
->display
, dock
->normalwin
, prefs
->argv
[0], prefs
->argv
[0]);
151 XSetWMNormalHints(dock
->display
, dock
->normalwin
, xsh
);
153 set_window_title(dock
->display
, dock
->normalwin
, "wmhdplop", "wmhdplop");
155 /* select events to catch */
157 long evmask
= ExposureMask
| ButtonPressMask
| ButtonReleaseMask
| VisibilityChangeMask
|
158 PointerMotionMask
| EnterWindowMask
| LeaveWindowMask
| StructureNotifyMask
;
159 XSelectInput(dock
->display
, dock
->normalwin
, evmask
);
161 XSelectInput(dock
->display
, dock
->iconwin
, evmask
);
163 XSetWMProtocols(dock
->display
, dock
->normalwin
, &dock
->atom_WM_DELETE_WINDOW
, 1);
165 /* set the command line for restarting */
166 XSetCommand(dock
->display
, dock
->normalwin
, prefs
->argv
, prefs
->argc
);
168 /* map the main window */
169 XMapWindow(dock
->display
, dock
->normalwin
);
171 XFree(xsh
); xsh
= NULL
;
175 void dockimlib2_gkrellm_xinit(DockImlib2
*dock
, GdkDrawable
*gkdrawable
) {
177 dock
->display
= GDK_WINDOW_XDISPLAY(gkdrawable
);
178 dock
->visual
= GDK_VISUAL_XVISUAL(gdk_drawable_get_visual(gkdrawable
));
179 dock
->depth
= gdk_drawable_get_depth(gkdrawable
);
180 dock
->colormap
= GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(gkdrawable
));
181 dock
->screennum
= DefaultScreen(dock
->display
);
182 dock
->rootwin
= RootWindow(dock
->display
, dock
->screennum
);
184 dock
->normalwin
= XCreateSimpleWindow(dock
->display
, GDK_PIXMAP_XID(gkdrawable
),
185 0, 0, dock
->w
, dock
->h
, 0,
186 BlackPixel(dock
->display
, dock
->screennum
),
187 WhitePixel(dock
->display
, dock
->screennum
));
188 //dock->normalwin = GDK_PIXMAP_XID(gkdrawable); // CA CLIGNOTE !!!
189 dock
->iconwin
= None
; dock
->iconwin_mapped
= 0;
190 dock
->win
= dock
->normalwin
; dock
->normalwin_mapped
= 1;
192 /* start with an empty window in order to get the background pixmap */
193 dockimlib2_set_rect_shape(dock
,32,32,1,0);
195 /* map the main window */
196 XMapWindow(dock
->display
, dock
->normalwin
);
200 static void add_fontpath(const char *path
, int recurse
) {
203 if (stat(path
,&st
) != 0 ||
204 !S_ISDIR(st
.st_mode
)) return;
205 if (recurse
> 3) return; /* prevent scanning of whole hd/infinite recursions in case of a bad symlink */
206 printf("add font path: '%s'\n", path
);
207 imlib_add_path_to_font_path(path
);
209 DIR *d
= opendir(path
);
212 while ((de
= readdir(d
))) {
214 if (strcmp(de
->d_name
,".") == 0 ||
215 strcmp(de
->d_name
,"..") == 0) continue;
216 snprintf(s
,sizeof s
,"%s/%s",path
, de
->d_name
);
217 add_fontpath(s
,recurse
+1);
223 void dockimlib2_reset_imlib(DockImlib2
*dock
) {
225 dock
->img
= imlib_create_image(dock
->w
, dock
->h
);
226 imlib_context_set_image(dock
->img
);
227 imlib_context_set_drawable(dock
->win
);
228 dockimlib2_set_rect_shape(dock
, dock
->x0
, dock
->y0
, dock
->w
, dock
->h
);
231 /* setup some default values for imlib2 */
232 static void dockimlib2_setup_imlib(DockImlib2
*dock
) {
234 /* set the maximum number of colors to allocate for 8bpp and less to 32 */
235 imlib_set_color_usage(32);
236 /* dither for depths < 24bpp */
237 imlib_context_set_dither(1);
238 /* set the display , visual, colormap and drawable we are using */
239 imlib_context_set_display(dock
->display
);
240 imlib_context_set_visual(dock
->visual
);
241 imlib_context_set_colormap(dock
->colormap
);
242 imlib_context_set_drawable(dock
->win
);
243 dock
->img
= imlib_create_image(dock
->w
, dock
->h
);
244 imlib_context_set_image(dock
->img
);
246 /* some default font paths */
247 snprintf(fp
, 512, "%s/.fonts", getenv("HOME"));
249 /*add_fontpath("/usr/share/fonts/truetype",1);
250 add_fontpath("/usr/share/fonts/ttf",1);*/
251 add_fontpath("/usr/share/fonts",1);
252 add_fontpath("/usr/X11R6/lib/X11/fonts/truetype",1);
253 add_fontpath("/usr/X11R6/lib/X11/fonts/TrueType",1);
254 add_fontpath("/usr/X11R6/lib/X11/fonts/ttf",1);
255 add_fontpath("/usr/X11R6/lib/X11/fonts/TTF",1);
256 /*imlib_add_path_to_font_path(fp);
257 imlib_add_path_to_font_path("/usr/share/fonts/truetype");
258 imlib_add_path_to_font_path("/usr/share/fonts/truetype/freefont");
259 imlib_add_path_to_font_path("/usr/share/fonts/truetype/ttf-bitstream-vera");
260 imlib_add_path_to_font_path("/usr/share/fonts/ttf/vera");*/ /* vera on mdk */
261 imlib_context_set_TTF_encoding(IMLIB_TTF_ENCODING_ISO_8859_1
);
262 //imlib_set_cache_size(0);imlib_set_font_cache_size(0);
265 /* wait for the dockapp to be swallowed and grab the background pixmap */
266 static void dockimlib2_xstartup(DockImlib2
*dock
) {
268 dockimlib2_set_rect_shape(dock
, dock
->x0
, dock
->y0
, dock
->w
, dock
->h
);
271 int exposed
= 0, mapped
= 0;
272 printf("xstartup..\n");
275 XNextEvent(dock
->display
, &event
);
276 switch (event
.type
) {
277 case ReparentNotify
: {
278 XReparentEvent ev
= event
.xreparent
;
279 if (ev
.window
== dock
->win
) {
284 XMappingEvent ev
= event
.xmapping
;
285 printf("MapNotify: ev.win = %lx\n", ev
.window
);
286 if (ev
.window
== dock
->win
) mapped
= 1;
289 XExposeEvent ev
= event
.xexpose
;
290 printf("Expose: ev.win = %lx\n", ev
.window
);
291 if (ev
.window
== dock
->win
) exposed
= 1;
294 } while (parent
== 0 && !exposed
&& !mapped
);
295 if (parent
== dock
->rootwin
) {
296 printf("... oups, parent window is rootwin ... are you really running windowmaker?\n");
297 dock
->bg
= imlib_create_image(dock
->w
, dock
->h
);
299 imlib_context_set_drawable(parent
);
300 dock
->bg
= imlib_create_image_from_drawable(0, dock
->x0
, dock
->y0
, dock
->w
, dock
->h
, 1);
301 imlib_context_set_drawable(dock
->win
);
302 dockimlib2_set_rect_shape(dock
, dock
->x0
, dock
->y0
, dock
->w
, dock
->h
);
304 printf("xstartup : success\n");
309 DockImlib2
* dockimlib2_setup(int x0
, int y0
, int w
, int h
, DockImlib2Prefs
*prefs
) {
311 DockImlib2
* dockimlib2_gkrellm_setup(int x0
, int y0
, int w
, int h
, DockImlib2Prefs
*prefs
, GdkDrawable
*gkdrawable
) {
313 DockImlib2
*dock
= calloc(1,sizeof(DockImlib2
)); assert(dock
);
314 //gdk_drawable_get_size(gkdrawable, &dock->win_width, &dock->win_height);
315 //printf("x0=%d, y0=%d, width = %d,%d, height = %d,%d\n", x0,y0,w,h,dock->win_width, dock->win_height);
316 dock
->win_width
= w
+x0
; dock
->win_height
= h
+y0
;//DOCK_WIDTH;
317 dock
->x0
= x0
; dock
->y0
= y0
;
318 dock
->w
= w
; dock
->h
= h
;
320 dockimlib2_xinit(dock
, prefs
);
323 dockimlib2_gkrellm_xinit(dock
, gkdrawable
);
325 dockimlib2_setup_imlib(dock
);
326 dockimlib2_xstartup(dock
);
330 static char *last_font_name
= 0;
332 const char* dockimlib2_last_loaded_font() { return last_font_name
; }
334 Imlib_Font
*imlib_load_font_nocase(const char *name
) {
337 if (last_font_name
) free(last_font_name
);
338 last_font_name
= strdup(name
);
339 if ((f
= imlib_load_font(last_font_name
))) return f
;
340 for (i
=0; last_font_name
[i
]; ++i
) last_font_name
[i
] = tolower(last_font_name
[i
]);
341 if ((f
= imlib_load_font(last_font_name
))) return f
;
342 for (i
=0; last_font_name
[i
]; ++i
) last_font_name
[i
] = toupper(last_font_name
[i
]);
343 f
= imlib_load_font(last_font_name
);
347 Imlib_Font
*load_font(char *prefname
, char **flist_
) {
348 Imlib_Font
*f
= NULL
;
349 char **flist
= flist_
;
351 f
= imlib_load_font_nocase(prefname
);
354 fprintf(stderr
, "warning: could not find font '%s' in the font path:\n",prefname
);
355 s
= imlib_list_font_path(&np
);
356 for (i
=0; i
< np
; ++i
) fprintf(stderr
, " %s\n", s
[i
]);
358 printf("loaded font %s\n", prefname
);
362 for (; *flist
; ++flist
) {
363 if ((f
= imlib_load_font_nocase(*flist
))) {
364 printf("loaded font %s\n", *flist
); break;
368 fprintf(stderr
, "could not load a default ttf font .. I tried ");
370 for (; *flist
; ++flist
)
371 fprintf(stderr
, "'%s'%s", *flist
, (flist
[1]?", ":""));
372 fprintf(stderr
, "\nUse the --font* options to change the fontpath/fontnames\n");
379 merges dock->bg and dock->img, and renders the result on the window
380 this function does not alter the imlib context
382 void dockimlib2_render(DockImlib2
*dock
) {
383 Pixmap olddrawable
= imlib_context_get_drawable();
384 Imlib_Image oldimage
= imlib_context_get_image();
385 //imlib_context_set_drawable(dock->win);
386 imlib_context_set_image(dock
->img
);
387 if (imlib_image_has_alpha()) {
388 imlib_context_set_image(dock
->bg
);
389 Imlib_Image bg
= imlib_clone_image();
390 imlib_context_set_image(bg
);
391 imlib_blend_image_onto_image(dock
->img
, 0, 0, 0, dock
->w
, dock
->h
, 0, 0, dock
->w
, dock
->h
);
393 if (dock
->normalwin
) {
394 imlib_context_set_drawable(dock
->normalwin
);
395 imlib_render_image_on_drawable(dock
->x0
, dock
->y0
);
398 imlib_context_set_drawable(dock
->iconwin
);
399 imlib_render_image_on_drawable(dock
->x0
, dock
->y0
);
401 /* XSetWindowBackgroundPixmap(dock->display, dock->GKwin, dock->win);
402 XClearWindow(dock->display, dock->GKWin); */
405 if (dock
->normalwin_mapped
&& dock
->normalwin
) {
406 imlib_context_set_drawable(dock
->normalwin
);
407 imlib_render_image_on_drawable(dock
->x0
, dock
->y0
); /* imlib_render_image_on_drawable generates many pages faults !? */
409 if (dock
->iconwin_mapped
&& dock
->iconwin
) {
410 imlib_context_set_drawable(dock
->iconwin
);
411 imlib_render_image_on_drawable(dock
->x0
, dock
->y0
);
414 imlib_context_set_image(oldimage
);
415 imlib_context_set_drawable(olddrawable
);