wmshutdown: Destroy dialog window before shutting down. This is especially useful...
[dockapps.git] / wmhdplop / dockapp_imlib2.c
blob3af45d901565fc74c5cc6533be0af6f74aa77198
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <string.h>
5 #include <sys/types.h>
6 #include <dirent.h>
7 #include <sys/stat.h>
8 #include <unistd.h>
9 #include <ctype.h>
10 #include "dockapp_imlib2.h"
11 #include <X11/extensions/shape.h>
12 #include <X11/Xutil.h>
13 #ifdef GKRELLM
14 #include <gdk/gdkx.h>
15 #endif
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);
34 if (dock->iconwin)
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) {
42 int rc;
43 XTextProperty window_title_property;
44 /* window name */
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);
55 void
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);
62 XFree(class_hint);
65 #ifndef GKRELLM
66 static void dockimlib2_xinit(DockImlib2 *dock, DockImlib2Prefs *prefs) {
67 XSizeHints *xsh;
68 int i;
69 char *sdisplay = getenv("DISPLAY");
70 char *pgeom = NULL;
71 int undocked = 0;
72 char sdockgeom[40];
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);
90 /* set size hints */
91 xsh = XAllocSizeHints(); assert(xsh);
92 xsh->flags = 0;
93 xsh->width = dock->w;
94 xsh->height = dock->h;
95 xsh->x = xsh->y = 0;
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);
101 if (undocked) {
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");
120 if (!undocked) {
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;
128 } else {
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 */
138 if (!undocked) {
139 XWMHints *xwmh;
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]);
150 /* set size hints */
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);
160 if (dock->iconwin)
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;
174 #else /* GKRELLM */
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);
198 #endif /* GKRELLM */
200 static void add_fontpath(const char *path, int recurse) {
201 struct stat st;
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);
208 if (recurse) {
209 DIR *d = opendir(path);
210 struct dirent *de;
211 if (!d) return;
212 while ((de = readdir(d))) {
213 char s[1024];
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);
219 closedir(d);
223 void dockimlib2_reset_imlib(DockImlib2 *dock) {
224 imlib_free_image();
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) {
233 char fp[512];
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"));
248 add_fontpath(fp,1);
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) {
267 dock->bg = NULL;
268 dockimlib2_set_rect_shape(dock, dock->x0, dock->y0, dock->w, dock->h);
269 #if 0
270 Window parent = 0;
271 int exposed = 0, mapped = 0;
272 printf("xstartup..\n");
273 do {
274 XEvent event;
275 XNextEvent(dock->display, &event);
276 switch (event.type) {
277 case ReparentNotify: {
278 XReparentEvent ev = event.xreparent;
279 if (ev.window == dock->win) {
280 parent = ev.parent;
282 } break;
283 case MapNotify: {
284 XMappingEvent ev = event.xmapping;
285 printf("MapNotify: ev.win = %lx\n", ev.window);
286 if (ev.window == dock->win) mapped = 1;
287 } break;
288 case Expose: {
289 XExposeEvent ev = event.xexpose;
290 printf("Expose: ev.win = %lx\n", ev.window);
291 if (ev.window == dock->win) exposed = 1;
292 } break;
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);
298 } else {
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");
305 #endif
308 #ifndef GKRELLM
309 DockImlib2* dockimlib2_setup(int x0, int y0, int w, int h, DockImlib2Prefs *prefs) {
310 #else
311 DockImlib2* dockimlib2_gkrellm_setup(int x0, int y0, int w, int h, DockImlib2Prefs *prefs, GdkDrawable *gkdrawable) {
312 #endif
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;
319 #ifndef GKRELLM
320 dockimlib2_xinit(dock, prefs);
321 #else
322 (void) prefs;
323 dockimlib2_gkrellm_xinit(dock, gkdrawable);
324 #endif
325 dockimlib2_setup_imlib(dock);
326 dockimlib2_xstartup(dock);
327 return 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) {
335 Imlib_Font *f;
336 int i;
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);
344 return f;
347 Imlib_Font *load_font(char *prefname, char **flist_) {
348 Imlib_Font *f = NULL;
349 char **flist = flist_;
350 if (prefname) {
351 f = imlib_load_font_nocase(prefname);
352 if (!f) {
353 int i,np; char **s;
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]);
357 } else {
358 printf("loaded font %s\n", prefname);
361 if (!f) {
362 for (; *flist; ++flist) {
363 if ((f = imlib_load_font_nocase(*flist))) {
364 printf("loaded font %s\n", *flist); break;
367 if (!f) {
368 fprintf(stderr, "could not load a default ttf font .. I tried ");
369 flist = flist_;
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");
375 return f;
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);
397 if (dock->iconwin) {
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); */
403 imlib_free_image();
404 } else {
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);