#include #include #include #include #include #include #include #include #include #include "dockapp_imlib2.h" #include #include #ifdef GKRELLM #include #endif /* require ISO C99 compatibility */ #define DOCKIMLIB2_ERR(...) { fprintf(stderr, "DockImlib2 " DOCKIMLIB2_VERSION " error: "); \ fprintf(stderr, __VA_ARGS__); exit(1); } #define DOCKIMLIB2_WARN(...) { fprintf(stderr, "DockImlib2 " DOCKIMLIB2_VERSION " warning: "); \ fprintf(stderr, __VA_ARGS__); exit(1); } static void dockimlib2_set_rect_shape(DockImlib2 *dock, int x, int y, int w, int h) { Pixmap mask = XCreatePixmap(dock->display, dock->win, dock->win_width, dock->win_height, 1); assert(mask); GC gc = XCreateGC(dock->display, mask, 0, NULL); XSetForeground(dock->display, gc, BlackPixel(dock->display, dock->screennum)); XFillRectangle(dock->display, mask, gc, 0, 0, dock->win_width, dock->win_height); XSetForeground(dock->display, gc, WhitePixel(dock->display, dock->screennum)); XFillRectangle(dock->display, mask, gc, x,y,w,h); XFreeGC(dock->display,gc); /* setup shaped window */ XShapeCombineMask(dock->display, dock->normalwin, ShapeBounding, 0, 0, mask, ShapeSet); if (dock->iconwin) XShapeCombineMask(dock->display, dock->iconwin, ShapeBounding, 0, 0, mask, ShapeSet); XFreePixmap(dock->display, mask); } /* some general windowmanager related functions ...*/ void set_window_title(Display *display, Window win, char *window_title, char *icon_title) { int rc; XTextProperty window_title_property; /* window name */ rc = XStringListToTextProperty(&window_title,1, &window_title_property); assert(rc); XSetWMName(display, win, &window_title_property); XFree(window_title_property.value); /* icon window name */ rc = XStringListToTextProperty(&icon_title,1, &window_title_property); assert(rc); XSetWMIconName(display, win, &window_title_property); XFree(window_title_property.value); } void set_window_class_hint(Display *display, Window win, char *res_class, char *res_name) { XClassHint *class_hint; class_hint = XAllocClassHint(); class_hint->res_name = res_name; class_hint->res_class = res_class; XSetClassHint(display, win, class_hint); XFree(class_hint); } #ifndef GKRELLM static void dockimlib2_xinit(DockImlib2 *dock, DockImlib2Prefs *prefs) { XSizeHints *xsh; int i; char *sdisplay = getenv("DISPLAY"); char *pgeom = NULL; int undocked = 0; char sdockgeom[40]; assert(prefs->argv); // this should be always set .. if (prefs->flags & DOCKPREF_DISPLAY) sdisplay = prefs->display; if (prefs->flags & DOCKPREF_GEOMETRY) { pgeom = prefs->geometry; undocked = 1; } dock->display = XOpenDisplay(sdisplay); if(!dock->display) DOCKIMLIB2_ERR("Couldn't connect to display %s\n", sdisplay); dock->screennum = DefaultScreen(dock->display); dock->visual = DefaultVisual(dock->display, dock->screennum); dock->depth = DefaultDepth(dock->display, dock->screennum); dock->colormap = DefaultColormap(dock->display, dock->screennum); dock->rootwin = RootWindow(dock->display, dock->screennum); dock->atom_WM_DELETE_WINDOW = XInternAtom(dock->display, "WM_DELETE_WINDOW", False); dock->atom_WM_PROTOCOLS = XInternAtom(dock->display, "WM_PROTOCOLS", False); /* set size hints */ xsh = XAllocSizeHints(); assert(xsh); xsh->flags = 0; xsh->width = dock->w; xsh->height = dock->h; xsh->x = xsh->y = 0; snprintf(sdockgeom, sizeof sdockgeom, "%dx%d+0+0", prefs->dockapp_size, prefs->dockapp_size); xsh->flags = XWMGeometry(dock->display, dock->screennum, pgeom, sdockgeom, 0, xsh, &xsh->x, &xsh->y, &xsh->width, &xsh->height, &i); if (undocked) { dock->win_width = dock->w = xsh->width; dock->win_height = dock->h = xsh->height; dock->x0 = dock->y0 = 0; } xsh->base_width = xsh->width; xsh->base_height = xsh->height; xsh->flags |= USSize | PMinSize | PMaxSize | PSize; xsh->min_height = 24; xsh->min_height = 24; xsh->max_width = 500; xsh->max_height = 500; /* create the application window */ dock->normalwin = XCreateSimpleWindow(dock->display, dock->rootwin, xsh->x, xsh->y, xsh->width, xsh->height, 0, BlackPixel(dock->display, dock->screennum), WhitePixel(dock->display, dock->screennum)); if(!dock->normalwin) DOCKIMLIB2_ERR("Couldn't create window\n"); if (!undocked) { /* create icon window */ dock->iconwin = XCreateSimpleWindow(dock->display, dock->rootwin, xsh->x, xsh->y, xsh->width, xsh->height, 0, BlackPixel(dock->display, dock->screennum), WhitePixel(dock->display, dock->screennum)); if(!dock->iconwin) DOCKIMLIB2_ERR("Couldn't create icon window\n"); dock->win = dock->iconwin; } else { dock->iconwin = None; dock->win = dock->normalwin; } dock->iconwin_mapped = dock->normalwin_mapped = 1; /* by default */ /* start with an empty window in order to get the background pixmap */ dockimlib2_set_rect_shape(dock,32,32,1,0); /* set window manager hints */ if (!undocked) { XWMHints *xwmh; xwmh = XAllocWMHints(); xwmh->flags = WindowGroupHint | IconWindowHint | StateHint; xwmh->icon_window = dock->iconwin; xwmh->window_group = dock->normalwin; xwmh->initial_state = WithdrawnState; XSetWMHints(dock->display, dock->normalwin, xwmh); XFree(xwmh); xwmh = NULL; } set_window_class_hint(dock->display, dock->normalwin, prefs->argv[0], prefs->argv[0]); /* set size hints */ XSetWMNormalHints(dock->display, dock->normalwin, xsh); set_window_title(dock->display, dock->normalwin, "wmhdplop", "wmhdplop"); /* select events to catch */ { long evmask = ExposureMask | ButtonPressMask | ButtonReleaseMask | VisibilityChangeMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask | StructureNotifyMask; XSelectInput(dock->display, dock->normalwin, evmask); if (dock->iconwin) XSelectInput(dock->display, dock->iconwin, evmask); } XSetWMProtocols(dock->display, dock->normalwin, &dock->atom_WM_DELETE_WINDOW, 1); /* set the command line for restarting */ XSetCommand(dock->display, dock->normalwin, prefs->argv, prefs->argc); /* map the main window */ XMapWindow(dock->display, dock->normalwin); XFree(xsh); xsh = NULL; } #else /* GKRELLM */ void dockimlib2_gkrellm_xinit(DockImlib2 *dock, GdkDrawable *gkdrawable) { dock->display = GDK_WINDOW_XDISPLAY(gkdrawable); dock->visual = GDK_VISUAL_XVISUAL(gdk_drawable_get_visual(gkdrawable)); dock->depth = gdk_drawable_get_depth(gkdrawable); dock->colormap = GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(gkdrawable)); dock->screennum = DefaultScreen(dock->display); dock->rootwin = RootWindow(dock->display, dock->screennum); dock->normalwin = XCreateSimpleWindow(dock->display, GDK_PIXMAP_XID(gkdrawable), 0, 0, dock->w, dock->h, 0, BlackPixel(dock->display, dock->screennum), WhitePixel(dock->display, dock->screennum)); //dock->normalwin = GDK_PIXMAP_XID(gkdrawable); // CA CLIGNOTE !!! dock->iconwin = None; dock->iconwin_mapped = 0; dock->win = dock->normalwin; dock->normalwin_mapped = 1; /* start with an empty window in order to get the background pixmap */ dockimlib2_set_rect_shape(dock,32,32,1,0); /* map the main window */ XMapWindow(dock->display, dock->normalwin); } #endif /* GKRELLM */ static void add_fontpath(const char *path, int recurse) { struct stat st; if (stat(path,&st) != 0 || !S_ISDIR(st.st_mode)) return; if (recurse > 3) return; /* prevent scanning of whole hd/infinite recursions in case of a bad symlink */ printf("add font path: '%s'\n", path); imlib_add_path_to_font_path(path); if (recurse) { DIR *d = opendir(path); struct dirent *de; if (!d) return; while ((de = readdir(d))) { char s[1024]; if (strcmp(de->d_name,".") == 0 || strcmp(de->d_name,"..") == 0) continue; snprintf(s,sizeof s,"%s/%s",path, de->d_name); add_fontpath(s,recurse+1); } closedir(d); } } void dockimlib2_reset_imlib(DockImlib2 *dock) { imlib_free_image(); dock->img = imlib_create_image(dock->w, dock->h); imlib_context_set_image(dock->img); imlib_context_set_drawable(dock->win); dockimlib2_set_rect_shape(dock, dock->x0, dock->y0, dock->w, dock->h); } /* setup some default values for imlib2 */ static void dockimlib2_setup_imlib(DockImlib2 *dock) { char fp[512]; /* set the maximum number of colors to allocate for 8bpp and less to 32 */ imlib_set_color_usage(32); /* dither for depths < 24bpp */ imlib_context_set_dither(1); /* set the display , visual, colormap and drawable we are using */ imlib_context_set_display(dock->display); imlib_context_set_visual(dock->visual); imlib_context_set_colormap(dock->colormap); imlib_context_set_drawable(dock->win); dock->img = imlib_create_image(dock->w, dock->h); imlib_context_set_image(dock->img); /* some default font paths */ snprintf(fp, 512, "%s/.fonts", getenv("HOME")); add_fontpath(fp,1); /*add_fontpath("/usr/share/fonts/truetype",1); add_fontpath("/usr/share/fonts/ttf",1);*/ add_fontpath("/usr/share/fonts",1); add_fontpath("/usr/X11R6/lib/X11/fonts/truetype",1); add_fontpath("/usr/X11R6/lib/X11/fonts/TrueType",1); add_fontpath("/usr/X11R6/lib/X11/fonts/ttf",1); add_fontpath("/usr/X11R6/lib/X11/fonts/TTF",1); /*imlib_add_path_to_font_path(fp); imlib_add_path_to_font_path("/usr/share/fonts/truetype"); imlib_add_path_to_font_path("/usr/share/fonts/truetype/freefont"); imlib_add_path_to_font_path("/usr/share/fonts/truetype/ttf-bitstream-vera"); imlib_add_path_to_font_path("/usr/share/fonts/ttf/vera");*/ /* vera on mdk */ imlib_context_set_TTF_encoding(IMLIB_TTF_ENCODING_ISO_8859_1); //imlib_set_cache_size(0);imlib_set_font_cache_size(0); } /* wait for the dockapp to be swallowed and grab the background pixmap */ static void dockimlib2_xstartup(DockImlib2 *dock) { dock->bg = NULL; dockimlib2_set_rect_shape(dock, dock->x0, dock->y0, dock->w, dock->h); #if 0 Window parent = 0; int exposed = 0, mapped = 0; printf("xstartup..\n"); do { XEvent event; XNextEvent(dock->display, &event); switch (event.type) { case ReparentNotify: { XReparentEvent ev = event.xreparent; if (ev.window == dock->win) { parent = ev.parent; } } break; case MapNotify: { XMappingEvent ev = event.xmapping; printf("MapNotify: ev.win = %lx\n", ev.window); if (ev.window == dock->win) mapped = 1; } break; case Expose: { XExposeEvent ev = event.xexpose; printf("Expose: ev.win = %lx\n", ev.window); if (ev.window == dock->win) exposed = 1; } break; } } while (parent == 0 && !exposed && !mapped); if (parent == dock->rootwin) { printf("... oups, parent window is rootwin ... are you really running windowmaker?\n"); dock->bg = imlib_create_image(dock->w, dock->h); } else { imlib_context_set_drawable(parent); dock->bg = imlib_create_image_from_drawable(0, dock->x0, dock->y0, dock->w, dock->h, 1); imlib_context_set_drawable(dock->win); dockimlib2_set_rect_shape(dock, dock->x0, dock->y0, dock->w, dock->h); } printf("xstartup : success\n"); #endif } #ifndef GKRELLM DockImlib2* dockimlib2_setup(int x0, int y0, int w, int h, DockImlib2Prefs *prefs) { #else DockImlib2* dockimlib2_gkrellm_setup(int x0, int y0, int w, int h, DockImlib2Prefs *prefs, GdkDrawable *gkdrawable) { #endif DockImlib2 *dock = calloc(1,sizeof(DockImlib2)); assert(dock); //gdk_drawable_get_size(gkdrawable, &dock->win_width, &dock->win_height); //printf("x0=%d, y0=%d, width = %d,%d, height = %d,%d\n", x0,y0,w,h,dock->win_width, dock->win_height); dock->win_width = w+x0; dock->win_height = h+y0;//DOCK_WIDTH; dock->x0 = x0; dock->y0 = y0; dock->w = w; dock->h = h; #ifndef GKRELLM dockimlib2_xinit(dock, prefs); #else (void) prefs; dockimlib2_gkrellm_xinit(dock, gkdrawable); #endif dockimlib2_setup_imlib(dock); dockimlib2_xstartup(dock); return dock; } static char *last_font_name = 0; const char* dockimlib2_last_loaded_font() { return last_font_name; } Imlib_Font *imlib_load_font_nocase(const char *name) { Imlib_Font *f; int i; if (last_font_name) free(last_font_name); last_font_name = strdup(name); if ((f = imlib_load_font(last_font_name))) return f; for (i=0; last_font_name[i]; ++i) last_font_name[i] = tolower(last_font_name[i]); if ((f = imlib_load_font(last_font_name))) return f; for (i=0; last_font_name[i]; ++i) last_font_name[i] = toupper(last_font_name[i]); f = imlib_load_font(last_font_name); return f; } Imlib_Font *load_font(char *prefname, char **flist_) { Imlib_Font *f = NULL; char **flist = flist_; if (prefname) { f = imlib_load_font_nocase(prefname); if (!f) { int i,np; char **s; fprintf(stderr, "warning: could not find font '%s' in the font path:\n",prefname); s = imlib_list_font_path(&np); for (i=0; i < np; ++i) fprintf(stderr, " %s\n", s[i]); } else { printf("loaded font %s\n", prefname); } } if (!f) { for (; *flist; ++flist) { if ((f = imlib_load_font_nocase(*flist))) { printf("loaded font %s\n", *flist); break; } } if (!f) { fprintf(stderr, "could not load a default ttf font .. I tried "); flist = flist_; for (; *flist; ++flist) fprintf(stderr, "'%s'%s", *flist, (flist[1]?", ":"")); fprintf(stderr, "\nUse the --font* options to change the fontpath/fontnames\n"); } } return f; } /* merges dock->bg and dock->img, and renders the result on the window this function does not alter the imlib context */ void dockimlib2_render(DockImlib2 *dock) { Pixmap olddrawable = imlib_context_get_drawable(); Imlib_Image oldimage = imlib_context_get_image(); //imlib_context_set_drawable(dock->win); imlib_context_set_image(dock->img); if (imlib_image_has_alpha()) { imlib_context_set_image(dock->bg); Imlib_Image bg = imlib_clone_image(); imlib_context_set_image(bg); imlib_blend_image_onto_image(dock->img, 0, 0, 0, dock->w, dock->h, 0, 0, dock->w, dock->h); if (dock->normalwin) { imlib_context_set_drawable(dock->normalwin); imlib_render_image_on_drawable(dock->x0, dock->y0); } if (dock->iconwin) { imlib_context_set_drawable(dock->iconwin); imlib_render_image_on_drawable(dock->x0, dock->y0); } /* XSetWindowBackgroundPixmap(dock->display, dock->GKwin, dock->win); XClearWindow(dock->display, dock->GKWin); */ imlib_free_image(); } else { if (dock->normalwin_mapped && dock->normalwin) { imlib_context_set_drawable(dock->normalwin); imlib_render_image_on_drawable(dock->x0, dock->y0); /* imlib_render_image_on_drawable generates many pages faults !? */ } if (dock->iconwin_mapped && dock->iconwin) { imlib_context_set_drawable(dock->iconwin); imlib_render_image_on_drawable(dock->x0, dock->y0); } } imlib_context_set_image(oldimage); imlib_context_set_drawable(olddrawable); }