/* Skippy - Seduces Kids Into Perversion
*
* Copyright (C) 2004 Hyriand <hyriand@thegraveyard.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "skippy.h"
#define TT_BORDER(tt) tt->pixels[0]
#define TT_BACKGROUND(tt) tt->pixels[1]
void
tooltip_destroy(Tooltip *tt)
{
if(tt->text)
free(tt->text);
if(tt->font)
XftFontClose(tt->mainwin->dpy, tt->font);
if(tt->draw)
XftDrawDestroy(tt->draw);
if(tt->color_allocated)
XftColorFree(tt->mainwin->dpy,
tt->mainwin->visual,
tt->mainwin->colormap,
&tt->color);
if(tt->window != None)
XDestroyWindow(tt->mainwin->dpy, tt->window);
if(! tt->no_free_color)
XFreeColors(tt->mainwin->dpy, tt->mainwin->colormap, tt->pixels, 2, 0);
else {
if(! (tt->no_free_color & 1))
XFreeColors(tt->mainwin->dpy, tt->mainwin->colormap, &TT_BORDER(tt), 1, 0);
if(! (tt->no_free_color & 2))
XFreeColors(tt->mainwin->dpy, tt->mainwin->colormap, &TT_BACKGROUND(tt), 1, 0);
}
free(tt);
}
Tooltip *
tooltip_create(MainWin *mw, dlist *config)
{
Tooltip *tt;
XSetWindowAttributes attr;
const char *tmp, *text_color;
XColor screen_color, exact_color;
tt = (Tooltip *)malloc(sizeof(Tooltip));
if(! tt)
return 0;
tt->mainwin = mw;
tt->window = None;
tt->font = 0;
tt->draw = 0;
tt->color_allocated = False;
tt->text = 0;
tt->no_free_color = 0;
tmp = config_get(config, "tooltip", "border", "black");
if(! XAllocNamedColor(mw->dpy, mw->colormap, tmp, &screen_color, &exact_color))
{
fprintf(stderr, "WARNING: Invalid color '%s', reverting to black.\n", tmp);
TT_BORDER(tt) = BlackPixel(mw->dpy, mw->screen);
tt->no_free_color |= 1;
} else
TT_BORDER(tt) = screen_color.pixel;
tmp = config_get(config, "tooltip", "background", "#e0e0ff");
if(! XAllocNamedColor(mw->dpy, mw->colormap, tmp, &screen_color, &exact_color))
{
fprintf(stderr, "WARNING: Invalid color '%s', reverting to white.\n", tmp);
TT_BACKGROUND(tt) = WhitePixel(mw->dpy, mw->screen);
tt->no_free_color |= 2;
} else
TT_BACKGROUND(tt) = screen_color.pixel;
text_color = config_get(config, "tooltip", "text", "black");
attr.override_redirect = True;
attr.border_pixel = TT_BORDER(tt);
attr.background_pixel = TT_BACKGROUND(tt);
attr.event_mask = ExposureMask;
tt->window = XCreateWindow(mw->dpy, mw->root,
0, 0, 1, 1,
1, mw->depth,
InputOutput, mw->visual,
CWBorderPixel|CWBackPixel|CWOverrideRedirect|CWEventMask,
&attr);
if(tt->window == None)
{
fprintf(stderr, "WARNING: Couldn't create tooltip window.\n");
tooltip_destroy(tt);
return 0;
}
if(! XftColorAllocName(mw->dpy, mw->visual, mw->colormap, text_color, &tt->color))
{
fprintf(stderr, "WARNING: Couldn't allocate color '%s'.\n", text_color);
tooltip_destroy(tt);
return 0;
}
tt->color_allocated = True;
tt->draw = XftDrawCreate(mw->dpy, tt->window, mw->visual, mw->colormap);
if(! tt->draw)
{
fprintf(stderr, "WARNING: Couldn't create Xft draw surface.\n");
tooltip_destroy(tt);
return 0;
}
tt->font = XftFontOpenName(mw->dpy, mw->screen, config_get(config, "tooltip", "font", "fixed-11:weight=bold"));
if(! tt->font)
{
fprintf(stderr, "WARNING: Couldn't open Xft font.\n");
tooltip_destroy(tt);
return 0;
}
tt->font_height = tt->font->ascent + tt->font->descent;
return tt;
}
void
tooltip_map(Tooltip *tt, int x, int y, const FcChar8 *text, int len)
{
XUnmapWindow(tt->mainwin->dpy, tt->window);
XftTextExtents8(tt->mainwin->dpy, tt->font, text, len, &tt->extents);
XResizeWindow(tt->mainwin->dpy, tt->window, tt->extents.width + 6, tt->font_height + 4);
tooltip_move(tt, x, y);
if(tt->text)
free(tt->text);
tt->text = (FcChar8 *)malloc(len);
memcpy(tt->text, text, len);
tt->text_len = len;
XMapWindow(tt->mainwin->dpy, tt->window);
XRaiseWindow(tt->mainwin->dpy, tt->window);
}
void
tooltip_move(Tooltip *tt, int x, int y)
{
if(x + tt->extents.width + 7 > tt->mainwin->x + tt->mainwin->width)
x = tt->mainwin->x + tt->mainwin->width - tt->extents.width - 7;
x = MAX(0, x);
if(y + tt->extents.height + 8 > tt->mainwin->y + tt->mainwin->height)
y = tt->mainwin->height + tt->mainwin->y - tt->extents.height - 8;
y = MAX(0, y);
XMoveWindow(tt->mainwin->dpy, tt->window, x, y);
}
void
tooltip_unmap(Tooltip *tt)
{
XUnmapWindow(tt->mainwin->dpy, tt->window);
if(tt->text)
free(tt->text);
tt->text = 0;
tt->text_len = 0;
}
void
tooltip_handle(Tooltip *tt, XEvent *ev)
{
if(! tt->text)
return;
if(ev->type == Expose && ev->xexpose.count == 0)
{
XClearWindow(tt->mainwin->dpy, tt->window);
XftDrawString8(tt->draw, &tt->color, tt->font, 3, tt->extents.y + (tt->font_height - tt->extents.y + 4) / 2, tt->text, tt->text_len);
}
}
syntax highlighted by Code2HTML, v. 0.9.1