enlightenment/src/cursors.c

355 lines
7.5 KiB
C

#include "debug.h"
#include "cursors.h"
#include "config.h"
#include "util.h"
#include "file.h"
#include <X11/cursorfont.h>
#if 0
/* XCursor */
#include <X11/Xcursor/Xcursor.h>
#endif
typedef struct _e_cursor E_Cursor;
struct _e_cursor
{
char *type;
Cursor cursor;
time_t mod;
int x_cursor_id;
};
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;
D_ENTER;
if (!cursor_change)
D_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;
D_RETURN;
UN(data);
}
static void
e_cursors_set(char *type)
{
D_ENTER;
e_cursors_display_in_window(0, type);
D_RETURN;
}
static E_Cursor *
e_cursors_find(char *type)
{
Evas_List * l;
D_ENTER;
for (l = cursors; l; l = l->next)
{
E_Cursor *c;
c = l->data;
if (!strcmp(c->type, type))
{
char buf[PATH_MAX];
snprintf(buf, PATH_MAX, "%s/%s.db", e_config_get("cursors"), type);
if (e_file_mod_time(buf) > c->mod)
{
cursors = evas_list_remove(cursors, c);
IF_FREE(c->type);
ecore_cursor_free(c->cursor);
FREE(c);
D_RETURN_(NULL);
}
D_RETURN_(c);
}
}
D_RETURN_(NULL);
}
void
e_cursors_display_in_window(Window win, char *type)
{
E_Cursor *c;
D_ENTER;
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[PATH_MAX];
Imlib_Image im;
c = NEW(E_Cursor, 1);
ZERO(c, E_Cursor, 1);
e_strdup(c->type, type);
snprintf(buf, PATH_MAX, "%s/%s.db", e_config_get("cursors"), type);
c->mod = e_file_mod_time(buf);
E_DB_INT_GET(buf, "/cursor/x", hx, ok);
E_DB_INT_GET(buf, "/cursor/y", hy, ok);
/* Handle x_cursor if available */
E_DB_INT_GET(buf, "/cursor/x_id", c->x_cursor_id, ok);
if(!ok)
c->x_cursor_id = XC_arrow;
/* Some sample code to load XCursor data directly. */
/* This works, but shading and colorization is different */
/* than native XFree86 XCursors. It appears the xcursorgen */
/* program does some preprocessing. We could do the same. */
#if 0
/* XCursor */
if(0)
{
Evas *ic_e;
Evas_Object *e_im;
int *idata;
int wid, hei;
XcursorImage * xcur;
snprintf(buf, PATH_MAX, "%s/%s.db",
e_config_get("cursors"), type);
ic_e = e_evas_new_all(ecore_display_get(), 0,
0, 0, 200, 200, "");
e_im = evas_object_image_add(ic_e);
evas_object_image_file_set(e_im, buf, "/cursor/image");
idata = evas_object_image_data_get(e_im, 1);
evas_object_image_size_get(e_im, &wid, &hei);
/* Make sure width and height are sane, protect ourselves.*/
if(wid > 128) wid=128;
if(hei > 128) hei=128;
xcur = XcursorImageCreate( wid, hei);
xcur->pixels = /*Xmalloc ? */(int *) malloc(wid * hei * 4);
if(!xcur->pixels)
D("Failed alloc!!!!!!!!!!\n");
memcpy(xcur->pixels, idata, wid*hei*4);
xcur->xhot = hx;
xcur->yhot = hy;
c->cursor = XcursorImageLoadCursor(ecore_display_get(), xcur);
evas_object_del(e_im);
}
else
{
#endif
/* Only load images for native cursors */
if(config_data->desktops->e_native_cursors)
{
snprintf(buf, PATH_MAX, "%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 = ecore_pixmap_new(0, w, h, 1);
mask = ecore_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 = ecore_gc_new(pmap);
gcf = ecore_gc_new(pmap);
ecore_gc_set_fg(gcb, 0);
ecore_gc_set_fg(gcf, 1);
/* fill out cursor pixmap with 0's (bg) */
ecore_fill_rectangle(pmap, gcb, 0, 0, w, h);
ecore_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)
{
ecore_draw_point(mask, gcf, x, y);
if ((r == fr) && (g == fg) && (b == fb))
ecore_draw_point(pmap, gcf, x, y);
}
}
}
done2:
/* clean up */
ecore_gc_free(gcb);
ecore_gc_free(gcf);
imlib_image_put_back_data(data);
imlib_free_image();
}
else
{
IF_FREE(c->type);
FREE(c);
c = NULL;
}
}
/* end native cursors */
if (c)
{
c->cursor =
ecore_cursor_new(pmap, mask, hx, hy, fr, fg, fb, br, bg, bb);
ecore_pixmap_free(pmap);
ecore_pixmap_free(mask);
cursors = evas_list_append(cursors, c);
}
#if 0
} /* XCursor */
#endif
}
if (c)
{
/* If behavior.db has /desktops/cursors/native == 1, then use */
/* images installed */
/* by E, else use X cursors by cursorfont id. */
if(config_data->desktops->e_native_cursors)
ecore_cursor_set(win, c->cursor);
else
{
Cursor x_cursor;
x_cursor = XCreateFontCursor(ecore_display_get(), c->x_cursor_id);
ecore_cursor_set(win, x_cursor);
}
}
else
{
if (!strcmp(type, "Default"))
D_RETURN;
e_cursors_display_in_window(win, "Default");
}
D_RETURN;
}
void
e_cursors_display(char *type)
{
D_ENTER;
IF_FREE(cur_cursor);
e_strdup(cur_cursor, type);
cursor_change = 1;
D_RETURN;
}
void
e_cursors_init(void)
{
D_ENTER;
ecore_event_filter_idle_handler_add(e_cursors_idle, NULL);
e_cursors_set("Default");
D_RETURN;
}