enlightenment_my/src/cursors.c

242 lines
4.9 KiB
C

#include "cursors.h"
#include "config.h"
#include "util.h"
typedef struct _e_cursor E_Cursor;
struct _e_cursor
{
char *type;
Cursor cursor;
time_t mod;
};
static int cursor_change = 0;
static char *cur_cursor = NULL;
static char *prev_cursor = NULL;
static Evas_List cursors = NULL;
static void e_cursors_idle(void *data);
static void e_cursors_set(char *type);
static E_Cursor * e_cursors_find(char *type);
static void
e_cursors_idle(void *data)
{
int change = 0;
if (!cursor_change) return;
if ((prev_cursor) && (cur_cursor) && (strcmp(prev_cursor, cur_cursor)))
change = 1;
if ((prev_cursor) && (!cur_cursor))
change = 1;
if ((!prev_cursor) && (cur_cursor))
change = 1;
if (change) e_cursors_set(cur_cursor);
IF_FREE(prev_cursor);
e_strdup(prev_cursor, cur_cursor);
IF_FREE(cur_cursor);
cur_cursor = NULL;
cursor_change = 0;
return;
UN(data);
}
static void
e_cursors_set(char *type)
{
e_cursors_display_in_window(0, type);
}
static E_Cursor *
e_cursors_find(char *type)
{
Evas_List l;
for (l = cursors; l; l = l->next)
{
E_Cursor *c;
c = l->data;
if (!strcmp(c->type, type))
{
char buf[4096];
sprintf(buf, "%s/%s.db", e_config_get("cursors"), type);
if (e_file_modified_time(buf) > c->mod)
{
cursors = evas_list_remove(cursors, c);
IF_FREE(c->type);
e_cursor_free(c->cursor);
FREE(c);
return NULL;
}
return c;
}
}
return NULL;
}
void
e_cursors_display_in_window(Window win, char *type)
{
E_Cursor *c;
if (!type) type = "Default";
c = e_cursors_find(type);
if (!c)
{
Pixmap pmap, mask;
int hx = 0, hy = 0;
int fr = 255, fg = 255, fb = 255;
int br = 0, bg = 0, bb = 0;
int w = 32, h = 32;
int ok;
char buf[4096];
Imlib_Image im;
c = NEW(E_Cursor, 1);
ZERO(c, E_Cursor, 1);
e_strdup(c->type, type);
sprintf(buf, "%s/%s.db", e_config_get("cursors"), type);
c->mod = e_file_modified_time(buf);
E_DB_INT_GET(buf, "/cursor/x", hx, ok);
E_DB_INT_GET(buf, "/cursor/y", hy, ok);
sprintf(buf, "%s/%s.db:/cursor/image", e_config_get("cursors"), type);
im = imlib_load_image(buf);
if (im)
{
DATA32 *data;
int x, y;
GC gcf, gcb;
int have_bg = 0, have_fg = 0;
imlib_context_set_image(im);
w = imlib_image_get_width();
h = imlib_image_get_height();
pmap = e_pixmap_new(0, w, h, 1);
mask = e_pixmap_new(0, w, h, 1);
data = imlib_image_get_data_for_reading_only();
/* figure out fg & bg */
if (!data) goto done;
for (y = 0; y < h; y++)
{
for (x = 0; x < w; x++)
{
int r, g, b, a;
DATA32 pix;
pix = data[(y * w) + x];
r = (pix >> 16) & 0xff;
g = (pix >> 8 ) & 0xff;
b = (pix ) & 0xff;
a = (pix >> 24) & 0xff;
if (a > 127)
{
if (!have_bg)
{
br = r;
bg = g;
bb = b;
have_bg = 1;
}
if (!have_fg)
{
if ((have_bg) &&
((br != r) || (bg != g) || (bb != b)))
{
fr = r;
fg = g;
fb = b;
have_fg = 1;
goto done;
}
}
}
}
}
done:
/* FIXME: inefficient - using pixmaps and draw point... should */
/* use XImages & XShm */
/* get some gc's set up */
gcb = e_gc_new(pmap);
gcf = e_gc_new(pmap);
e_gc_set_fg(gcb, 0);
e_gc_set_fg(gcf, 1);
/* fill out cursor pixmap with 0's (bg) */
e_fill_rectangle(pmap, gcb, 0, 0, w, h);
e_fill_rectangle(mask, gcb, 0, 0, w, h);
if (!data) goto done2;
for (y = 0; y < h; y++)
{
for (x = 0; x < w; x++)
{
int r, g, b, a;
DATA32 pix;
pix = data[(y * w) + x];
r = (pix >> 16) & 0xff;
g = (pix >> 8 ) & 0xff;
b = (pix ) & 0xff;
a = (pix >> 24) & 0xff;
if (a > 127)
{
e_draw_point(mask, gcf, x, y);
if ((r == fr) && (g == fg) && (b == fb))
e_draw_point(pmap, gcf, x, y);
}
}
}
done2:
/* clean up */
e_gc_free(gcb);
e_gc_free(gcf);
imlib_image_put_back_data(data);
imlib_free_image();
}
else
{
IF_FREE(c->type);
FREE(c);
c = NULL;
}
if (c)
{
c->cursor = e_cursor_new(pmap, mask, hx, hy, fr, fg, fb, br, bg, bb);
e_pixmap_free(pmap);
e_pixmap_free(mask);
cursors = evas_list_append(cursors, c);
}
}
if (c)
e_cursor_set(win, c->cursor);
else
e_cursors_display_in_window(win, "Default");
}
void
e_cursors_display(char *type)
{
IF_FREE(cur_cursor);
e_strdup(cur_cursor, type);
printf("%s\n", type);
cursor_change = 1;
}
void
e_cursors_init(void)
{
e_event_filter_idle_handler_add(e_cursors_idle, NULL);
e_cursors_set("Default");
}