e16/src/buttons.c

1175 lines
25 KiB
C

/*
* Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
* Copyright (C) 2004-2007 Kim Woelders
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies of the Software, its documentation and marketing & publicity
* materials, and acknowledgment shall be given in the documentation, materials
* and software packages that this Software was used.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "E.h"
#include "aclass.h"
#include "buttons.h"
#include "cursors.h"
#include "desktops.h"
#include "e16-ecore_list.h"
#include "eimage.h"
#include "emodule.h"
#include "file.h"
#include "grabs.h"
#include "iclass.h"
#include "parse.h"
#include "tclass.h"
#include "tooltips.h"
#include "xwin.h"
#define BUTTON_EVENT_MASK \
(KeyPressMask | KeyReleaseMask | \
ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | \
PointerMotionMask)
typedef struct
{
Constraints width, height;
int xorigin, yorigin;
int xabs, xrel;
int yabs, yrel;
int xsizerel, xsizeabs;
int ysizerel, ysizeabs;
char size_from_image;
}
BGeometry;
struct _button
{
EObj o;
BGeometry geom;
ImageClass *iclass;
ActionClass *aclass;
TextClass *tclass;
char *label;
int id;
int flags;
char internal;
char default_show;
EObj *owner;
ButtonCbFunc *func;
int state;
Window inside_win;
Window event_win;
char left;
unsigned int ref_count;
};
static Ecore_List *button_list = NULL;
static struct
{
Button *button;
char loading_user;
char move_pending;
char action_inhibit;
int start_x, start_y;
} Mode_buttons;
static void ButtonHandleEvents(Win win, XEvent * ev, void *btn);
void
ButtonIncRefcount(Button * b)
{
b->ref_count++;
}
void
ButtonDecRefcount(Button * b)
{
b->ref_count--;
}
static int
ButtonIsFixed(const Button * b)
{
return b->flags & FLAG_FIXED;
}
static int
ButtonIsInternal(const Button * b)
{
return b->internal;
}
Button *
ButtonCreate(const char *name, int id, ImageClass * iclass,
ActionClass * aclass, TextClass * tclass, const char *label,
char ontop, int flags, int minw, int maxw, int minh, int maxh,
int xo, int yo, int xa, int xr, int ya, int yr, int xsr, int xsa,
int ysr, int ysa, char simg, int desk, char sticky)
{
Button *b;
if (desk < 0 || desk >= (int)DesksGetNumber())
return NULL;
if (sticky && ontop == 1)
desk = 0;
b = Ecalloc(1, sizeof(Button));
if (!button_list)
button_list = ecore_list_new();
ecore_list_append(button_list, b);
b->id = id;
b->label = Estrdup(label);
b->iclass = iclass;
if (!b->iclass)
b->iclass = ImageclassFind(NULL, 0);
if (b->iclass)
ImageclassIncRefcount(b->iclass);
b->aclass = aclass;
if (b->aclass)
ActionclassIncRefcount(b->aclass);
b->tclass = tclass;
if (!b->tclass && b->label)
b->tclass = TextclassFind(NULL, 0);
if (b->tclass)
TextclassIncRefcount(b->tclass);
b->flags = flags;
b->geom.width.min = minw;
b->geom.width.max = maxw;
b->geom.height.min = minh;
b->geom.height.max = maxh;
b->geom.xorigin = xo;
b->geom.yorigin = yo;
b->geom.xabs = xa;
b->geom.xrel = xr;
b->geom.yabs = ya;
b->geom.yrel = yr;
b->geom.xsizeabs = xsa;
b->geom.xsizerel = xsr;
b->geom.ysizeabs = ysa;
b->geom.ysizerel = ysr;
b->geom.size_from_image = simg;
b->default_show = 1;
EoSetSticky(b, sticky);
EoSetDesk(b, DeskGet(desk));
EoInit(b, EOBJ_TYPE_BUTTON, None, -100, -100, 50, 50, 0, name);
EoSetLayer(b, ontop);
EoSetShadow(b, 0);
ESelectInput(EoGetWin(b), BUTTON_EVENT_MASK);
EventCallbackRegister(EoGetWin(b), 0, ButtonHandleEvents, b);
return b;
}
void
ButtonDestroy(Button * b)
{
if (!b)
return;
if (b->ref_count > 0)
{
DialogOK("Button Error!", _("%u references remain\n"), b->ref_count);
return;
}
ecore_list_remove_node(button_list, b);
EoFini(b);
if (b->iclass)
ImageclassDecRefcount(b->iclass);
if (b->aclass)
ActionclassDecRefcount(b->aclass);
if (b->tclass)
TextclassDecRefcount(b->tclass);
if (b->label)
Efree(b->label);
Efree(b);
}
static int
_ButtonMatchName(const void *data, const void *match)
{
return strcmp(EoGetName((const Button *)data), match);
}
Button *
ButtonFind(const char *name)
{
return ecore_list_find(button_list, _ButtonMatchName, name);
}
static void
ButtonCalc(Button * b)
{
int w, h, x, y, xo, yo;
EImage *im;
x = 0;
y = 0;
w = 32;
h = 32;
if (b->geom.size_from_image)
{
im = ImageclassGetImage(b->iclass, 0, 0, 0);
if (im)
{
EImageGetSize(im, &w, &h);
EImageFree(im);
}
else
{
if (!b->iclass)
b->iclass = ImageclassFind(NULL, 0);
w = 32;
h = 32;
}
}
else
{
w = ((b->geom.xsizerel * VRoot.w) >> 10) + b->geom.xsizeabs;
h = ((b->geom.ysizerel * VRoot.h) >> 10) + b->geom.ysizeabs;
}
if (w > b->geom.width.max)
w = b->geom.width.max;
else if (w < b->geom.width.min)
w = b->geom.width.min;
if (h > b->geom.height.max)
h = b->geom.height.max;
else if (h < b->geom.height.min)
h = b->geom.height.min;
xo = (w * b->geom.xorigin) >> 10;
yo = (h * b->geom.yorigin) >> 10;
x = ((b->geom.xrel * VRoot.w) >> 10) + b->geom.xabs - xo;
y = ((b->geom.yrel * VRoot.h) >> 10) + b->geom.yabs - yo;
EoMoveResize(b, x, y, w, h);
}
static void
ButtonDraw(Button * b)
{
ITApply(EoGetWin(b), b->iclass, NULL, EoGetW(b), EoGetH(b),
b->state, 0, 0, ST_BUTTON, b->tclass, NULL, b->label);
EoShapeUpdate(b, 0);
}
#if 0 /* Unused */
void
ButtonDrawWithState(Button * b, int state)
{
b->state = state;
ButtonDraw(b);
}
#endif
void
ButtonShow(Button * b)
{
ButtonCalc(b);
ButtonDraw(b);
EoMap(b, 0);
}
void
ButtonSwallowInto(Button * b, EObj * eo)
{
b->internal = 1;
b->default_show = 0;
b->flags |= FLAG_FIXED;
b->owner = eo;
b->ref_count++;
EobjReparent(EoObj(b), eo, 0, 0);
ButtonCalc(b);
ButtonDraw(b);
EMapWindow(EoGetWin(b));
}
void
ButtonSetCallback(Button * b, ButtonCbFunc * func, EObj * eo)
{
b->owner = eo;
b->func = func;
}
static void
ButtonMoveToDesktop(Button * b, Desk * dsk)
{
if (EoIsSticky(b) && EoGetLayer(b) == 1)
dsk = DeskGet(0);
if (!dsk)
return;
if (EoGetDesk(b) != dsk)
EoReparent(b, EoObj(dsk), EoGetX(b), EoGetY(b));
}
void
ButtonHide(Button * b)
{
EoUnmap(b);
}
static void
ButtonToggle(Button * b)
{
if (b->internal)
return;
if (EoIsShown(b))
ButtonHide(b);
else
ButtonShow(b);
}
void
ButtonMoveToCoord(Button * b, int x, int y)
{
int rx, ry, relx, rely, absx, absy;
if (ButtonIsFixed(b))
return;
if ((x + (EoGetW(b) >> 1)) < (VRoot.w / 3))
relx = 0;
else if ((x + (EoGetW(b) >> 1)) > ((VRoot.w * 2) / 3))
relx = 1024;
else
relx = 512;
rx = (relx * VRoot.w) >> 10;
absx = x - rx;
if ((y + (EoGetH(b) >> 1)) < (VRoot.h / 3))
rely = 0;
else if ((y + (EoGetH(b) >> 1)) > ((VRoot.h * 2) / 3))
rely = 1024;
else
rely = 512;
ry = (rely * VRoot.h) >> 10;
absy = y - ry;
if (!(b->flags & FLAG_FIXED_HORIZ))
{
b->geom.xorigin = 0;
b->geom.xabs = absx;
b->geom.xrel = relx;
}
if (!(b->flags & FLAG_FIXED_VERT))
{
b->geom.yorigin = 0;
b->geom.yabs = absy;
b->geom.yrel = rely;
}
ButtonCalc(b);
}
void
ButtonMoveRelative(Button * b, int dx, int dy)
{
ButtonMoveToCoord(b, EoGetX(b) + dx, EoGetY(b) + dy);
}
int
ButtonDoShowDefault(const Button * b)
{
return !b->internal && b->default_show;
}
#if 0 /* Unused */
int
ButtonEmbedWindow(Button * b, Window WindowToEmbed)
{
int w, h;
EReparentWindow(WindowToEmbed, EoGetWin(b), 0, 0);
b->inside_win = WindowToEmbed;
EGetGeometry(WindowToEmbed, NULL, NULL, NULL, &w, &h, NULL, NULL);
EMoveWindow(b->inside_win, (EoGetW(b) - w) >> 1, (EoGetH(b) - h) >> 1);
b->event_win = ECreateEventWindow(EoGetWin(b), 0, 0, w, h);
EventCallbackRegister(b->event_win, 0, ButtonHandleEvents, b);
ESelectInput(b->event_win,
ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
LeaveWindowMask | ButtonMotionMask);
EMoveWindow(b->event_win, (EoGetW(b) - w) >> 1, (EoGetH(b) - h) >> 1);
EMapRaised(b->event_win);
return 0;
}
#endif
static void
ButtonDragStart(Button * b)
{
if (ButtonIsFixed(b))
return;
GrabPointerSet(EoGetWin(b), ECSR_GRAB, 0);
Mode.mode = MODE_BUTTONDRAG;
Mode_buttons.move_pending = 1;
Mode_buttons.start_x = Mode.events.x;
Mode_buttons.start_y = Mode.events.y;
}
static void
ButtonDragEnd(Button * b)
{
Desk *dsk;
Mode.mode = MODE_NONE;
if (!Mode_buttons.move_pending)
{
dsk = DesktopAt(Mode.events.x, Mode.events.y);
ButtonMoveToDesktop(b, dsk);
dsk = EoGetDesk(b);
ButtonMoveRelative(b, -EoGetX(dsk), -EoGetY(dsk));
}
else
Mode_buttons.move_pending = 0;
autosave();
}
void
ButtonsForeach(int id, Desk * dsk, void (*func) (Button * b))
{
Button *b;
ECORE_LIST_FOR_EACH(button_list, b)
{
if (id >= 0 && id != b->id)
continue;
if (dsk && dsk != EoGetDesk(b))
continue;
func(b);
}
}
void
ButtonsMoveStickyToDesk(Desk * dsk)
{
Button *b;
ECORE_LIST_FOR_EACH(button_list, b)
{
if (!EoIsSticky(b) || ButtonIsInternal(b))
continue;
ButtonMoveToDesktop(b, dsk);
}
}
/*
* Button event handlers
*/
static void
ButtonDoAction(Button * b, XEvent * ev)
{
if (b->owner && b->func)
b->func(b->owner, ev, b->aclass);
else
ActionclassEvent(b->aclass, ev, NULL);
}
static void
ButtonEventMouseDown(Button * b, XEvent * ev)
{
Mode_buttons.button = b;
GrabPointerSet(EoGetWin(b), ECSR_GRAB, 0);
if (b->inside_win)
{
Window win = ev->xbutton.window;
ev->xbutton.window = b->inside_win;
XSendEvent(disp, b->inside_win, False, ButtonPressMask, ev);
ev->xbutton.window = win;
}
b->state = STATE_CLICKED;
ButtonDraw(b);
if (!ButtonIsInternal(b))
{
ActionClass *ac;
ac = ActionclassFind("ACTION_BUTTON_DRAG");
if (ac && !Mode_buttons.action_inhibit)
ActionclassEvent(ac, ev, NULL);
}
if (b->aclass && !Mode_buttons.action_inhibit)
ButtonDoAction(b, ev);
}
static void
ButtonEventMouseUp(Button * b, XEvent * ev)
{
if (b->inside_win && !Mode_buttons.action_inhibit)
{
Window win = ev->xbutton.window;
ev->xbutton.window = b->inside_win;
XSendEvent(disp, b->inside_win, False, ButtonReleaseMask, ev);
ev->xbutton.window = win;
}
if ((b->state == STATE_CLICKED) && (!b->left))
b->state = STATE_HILITED;
else
b->state = STATE_NORMAL;
ButtonDraw(b);
GrabPointerRelease();
b->left = 0;
if (Mode.mode == MODE_BUTTONDRAG)
ButtonDragEnd(Mode_buttons.button);
Mode_buttons.button = NULL;
if (b->aclass && !b->left && !Mode_buttons.action_inhibit)
ButtonDoAction(b, ev);
Mode_buttons.action_inhibit = 0;
}
static void
ButtonEventMotion(Button * b, XEvent * ev __UNUSED__)
{
int dx, dy;
if (Mode.mode != MODE_BUTTONDRAG)
return;
dx = Mode.events.x - Mode.events.px;
dy = Mode.events.y - Mode.events.py;
if (Mode_buttons.move_pending)
{
int x, y;
x = Mode.events.x - Mode_buttons.start_x;
y = Mode.events.y - Mode_buttons.start_y;
if (x < 0)
x = -x;
if (y < 0)
y = -y;
if ((x > Conf.buttons.move_resistance) ||
(y > Conf.buttons.move_resistance))
Mode_buttons.move_pending = 0;
Mode_buttons.action_inhibit = 1;
}
if (!Mode_buttons.move_pending)
ButtonMoveRelative(b, dx, dy);
}
static void
ButtonEventMouseIn(Button * b, XEvent * ev)
{
if (b->state == STATE_CLICKED)
b->left = 0;
else
{
b->state = STATE_HILITED;
ButtonDraw(b);
if (b->aclass && !Mode_buttons.action_inhibit)
ActionclassEvent(b->aclass, ev, NULL);
}
}
static void
ButtonEventMouseOut(Button * b, XEvent * ev)
{
if (b->state == STATE_CLICKED)
b->left = 1;
else
{
b->state = STATE_NORMAL;
ButtonDraw(b);
if (b->aclass && !Mode_buttons.action_inhibit)
ActionclassEvent(b->aclass, ev, NULL);
}
}
static ActionClass *
ButtonGetAclass(void *data)
{
Button *b = data;
/* Validate button */
if (!ecore_list_goto(button_list, b))
return NULL;
return b->aclass;
}
static void
ButtonHandleTooltip(Button * b, int event)
{
switch (event)
{
case ButtonPress:
case LeaveNotify:
TooltipsSetPending(0, NULL, NULL);
break;
case ButtonRelease:
case EnterNotify:
case MotionNotify:
TooltipsSetPending(0, ButtonGetAclass, b);
break;
}
}
static void
ButtonHandleEvents(Win win __UNUSED__, XEvent * ev, void *prm)
{
Button *b = (Button *) prm;
switch (ev->type)
{
case ButtonPress:
ButtonEventMouseDown(b, ev);
break;
case ButtonRelease:
ButtonEventMouseUp(b, ev);
break;
case MotionNotify:
ButtonEventMotion(b, ev);
break;
case EnterNotify:
ButtonEventMouseIn(b, ev);
break;
case LeaveNotify:
ButtonEventMouseOut(b, ev);
break;
}
if (b->aclass)
ButtonHandleTooltip(b, ev->type);
if (b->func)
b->func(b->owner, ev, NULL);
}
/*
* Configuration load/save
*/
#include "conf.h"
int
ButtonsConfigLoad(FILE * ConfigFile)
{
int err = 0;
char s[FILEPATH_LEN_MAX];
char s2[FILEPATH_LEN_MAX];
int i1;
char *name = NULL;
char *label = NULL;
ActionClass *ac = NULL;
ImageClass *ic = NULL;
TextClass *tc = NULL;
Button *bt = NULL;
Button *pbt = NULL;
char ontop = 0;
int flags = 0, minw = 1, maxw = 99999, minh = 1;
int maxh = 99999, xo = 0, yo = 0, xa = 0;
int xr = 0, ya = 0, yr = 0;
int xsr = 0, xsa = 0, ysr = 0, ysa = 0;
char simg = 0;
int desk = 0;
char sticky = 0;
char show = 1;
char internal = 0;
int fields;
const char *ss;
while (GetLine(s, sizeof(s), ConfigFile))
{
s2[0] = 0;
i1 = CONFIG_INVALID;
fields = sscanf(s, "%i %4000s", &i1, s2);
if (fields < 1)
{
i1 = CONFIG_INVALID;
}
else if (i1 == CONFIG_CLOSE)
{
if (fields != 1)
{
RecoverUserConfig();
Alert(_("CONFIG: ignoring extra data in \"%s\"\n"), s);
}
}
else if (i1 != CONFIG_INVALID)
{
if (fields != 2)
{
RecoverUserConfig();
Alert(_("CONFIG: missing required data in \"%s\"\n"), s);
i1 = CONFIG_INVALID;
}
}
switch (i1)
{
case CONFIG_CLOSE:
if (!pbt && !Mode_buttons.loading_user)
{
bt = ButtonCreate(name, 0, ic, ac, tc, label, ontop, flags,
minw, maxw, minh, maxh, xo, yo, xa, xr,
ya, yr, xsr, xsa, ysr, ysa, simg, desk,
sticky);
bt->default_show = show;
bt->internal = internal;
}
goto done;
case CONFIG_TEXT:
tc = TextclassFind(s2, 1);
if (pbt)
pbt->tclass = tc;
break;
case BUTTON_LABEL:
_EFREE(label);
ss = atword(s, 2);
label = Estrdup(ss);
if (pbt)
{
_EFREE(pbt->label);
pbt->label = label;
}
break;
case BORDERPART_ONTOP:
ontop = atoi(s2);
if (pbt)
EoSetLayer(pbt, ontop);
break;
case CONFIG_CLASSNAME:
case BUTTON_NAME:
_EFREE(name);
name = Estrdup(s2);
pbt = ButtonFind(name);
break;
case CONFIG_ACTIONCLASS:
case BUTTON_ACLASS:
ac = ActionclassFind(s2);
if (pbt)
pbt->aclass = ac;
break;
case CONFIG_IMAGECLASS:
case BUTTON_ICLASS:
ic = ImageclassFind(s2, 1);
if (pbt)
pbt->iclass = ic;
break;
case BORDERPART_WMIN:
minw = atoi(s2);
if (pbt)
pbt->geom.width.min = minw;
break;
case BORDERPART_WMAX:
maxw = atoi(s2);
if (pbt)
pbt->geom.width.max = maxw;
break;
case BORDERPART_HMIN:
minh = atoi(s2);
if (pbt)
pbt->geom.height.min = minh;
break;
case BORDERPART_FLAGS:
flags = atoi(s2);
if (pbt)
pbt->flags = flags;
break;
case BORDERPART_HMAX:
maxh = atoi(s2);
if (pbt)
pbt->geom.height.max = maxh;
break;
case BUTTON_XO:
xo = atoi(s2);
if (pbt)
pbt->geom.xorigin = xo;
break;
case BUTTON_YO:
yo = atoi(s2);
if (pbt)
pbt->geom.yorigin = yo;
break;
case BUTTON_XA:
xa = atoi(s2);
if (pbt)
pbt->geom.xabs = xa;
break;
case BUTTON_XR:
xr = atoi(s2);
if (pbt)
pbt->geom.xrel = xr;
break;
case BUTTON_YA:
ya = atoi(s2);
if (pbt)
pbt->geom.yabs = ya;
break;
case BUTTON_YR:
yr = atoi(s2);
if (pbt)
pbt->geom.yrel = yr;
break;
case BUTTON_XSR:
xsr = atoi(s2);
if (pbt)
pbt->geom.xsizerel = xsr;
break;
case BUTTON_XSA:
xsa = atoi(s2);
if (pbt)
pbt->geom.xsizeabs = xsa;
break;
case BUTTON_YSR:
ysr = atoi(s2);
if (pbt)
pbt->geom.ysizerel = ysr;
break;
case BUTTON_YSA:
ysa = atoi(s2);
if (pbt)
pbt->geom.ysizeabs = ysa;
break;
case BUTTON_SIMG:
simg = atoi(s2);
if (pbt)
pbt->geom.size_from_image = simg;
break;
case BUTTON_DESK:
desk = atoi(s2);
if (pbt)
ButtonMoveToDesktop(pbt, DeskGet(desk));
break;
case BUTTON_STICKY:
sticky = atoi(s2);
if (pbt)
EoSetSticky(pbt, sticky);
break;
case BUTTON_INTERNAL:
internal = atoi(s2);
if (pbt)
pbt->internal = internal;
break;
case BUTTON_SHOW:
show = atoi(s2);
if (pbt)
pbt->default_show = show;
break;
default:
break;
}
}
err = -1;
done:
_EFREE(name);
_EFREE(label);
return err;
}
static void
ButtonsConfigLoadUser(void)
{
char s[4096];
Esnprintf(s, sizeof(s), "%s.buttons", EGetSavePrefix());
Mode_buttons.loading_user = 1;
ConfigFileLoad(s, NULL, ConfigFileRead, 0);
Mode_buttons.loading_user = 0;
}
static void
ButtonsConfigSave(void)
{
char s[FILEPATH_LEN_MAX], st[FILEPATH_LEN_MAX];
FILE *fs;
Button *b;
int flags;
if (ecore_list_nodes(button_list) <= 0)
return;
Etmp(st);
fs = fopen(st, "w");
if (!fs)
return;
ECORE_LIST_FOR_EACH(button_list, b)
{
if (b->id != 0 || b->internal)
continue;
fprintf(fs, "4 999\n");
fprintf(fs, "100 %s\n", EoGetName(b));
if (b->iclass)
fprintf(fs, "12 %s\n", ImageclassGetName(b->iclass));
if (b->aclass)
fprintf(fs, "11 %s\n", ActionclassGetName(b->aclass));
if (EoGetLayer(b) >= 0)
fprintf(fs, "453 %i\n", EoGetLayer(b));
fprintf(fs, "456 %i\n", b->geom.width.min);
fprintf(fs, "457 %i\n", b->geom.width.max);
fprintf(fs, "468 %i\n", b->geom.height.min);
fprintf(fs, "469 %i\n", b->geom.height.max);
fprintf(fs, "528 %i\n", b->geom.xorigin);
fprintf(fs, "529 %i\n", b->geom.yorigin);
fprintf(fs, "530 %i\n", b->geom.xabs);
fprintf(fs, "531 %i\n", b->geom.xrel);
fprintf(fs, "532 %i\n", b->geom.yabs);
fprintf(fs, "533 %i\n", b->geom.yrel);
fprintf(fs, "534 %i\n", b->geom.xsizerel);
fprintf(fs, "535 %i\n", b->geom.xsizeabs);
fprintf(fs, "536 %i\n", b->geom.ysizerel);
fprintf(fs, "537 %i\n", b->geom.ysizeabs);
fprintf(fs, "538 %i\n", b->geom.size_from_image);
fprintf(fs, "539 %i\n", EoGetDeskNum(b));
fprintf(fs, "540 %i\n", EoIsSticky(b));
fprintf(fs, "542 %i\n", EoIsShown(b));
if (b->flags)
{
flags = 0;
if (((b->flags & FLAG_FIXED_HORIZ) &&
(b->flags & FLAG_FIXED_VERT)) || (b->flags & FLAG_FIXED))
flags = 2;
else if (b->flags & FLAG_FIXED_HORIZ)
flags = 3;
else if (b->flags & FLAG_FIXED_VERT)
flags = 4;
else if (b->flags & FLAG_TITLE)
flags = 0;
else if (b->flags & FLAG_MINIICON)
flags = 1;
fprintf(fs, "454 %i\n", flags);
}
fprintf(fs, "1000\n");
}
fclose(fs);
Esnprintf(s, sizeof(s), "%s.buttons", EGetSavePrefix());
E_mv(st, s);
}
/*
* Buttons Module
*/
static void
ButtonsSighan(int sig, void *prm __UNUSED__)
{
switch (sig)
{
case ESIGNAL_INIT:
memset(&Mode_buttons, 0, sizeof(Mode_buttons));
break;
case ESIGNAL_CONFIGURE:
ButtonsConfigLoadUser();
break;
case ESIGNAL_EXIT:
if (Mode.wm.save_ok)
ButtonsConfigSave();
break;
}
}
typedef struct
{
int id;
int match;
const char *regex;
} button_match_data;
static void
_ButtonHideShow(void *data, void *prm)
{
Button *b = data;
button_match_data *bmd = prm;
int match;
if (bmd->id >= 0 && bmd->id != b->id)
return;
if (bmd->regex)
{
match = matchregexp(bmd->regex, EoGetName(b));
if ((match && !bmd->match) || (!match && bmd->match))
return;
if (!strcmp(EoGetName(b), "_DESKTOP_DESKRAY_DRAG_CONTROL")) /* FIXME - ??? */
return;
}
ButtonToggle(b);
}
static void
doHideShowButton(const char *params)
{
Button *b;
char s[1024];
const char *ss;
button_match_data bmd = { -1, 1, NULL };
if (!params)
{
bmd.id = 0;
ecore_list_for_each(button_list, _ButtonHideShow, &bmd);
goto done;
}
sscanf(params, "%1000s", s);
if (!strcmp(s, "button"))
{
sscanf(params, "%*s %1000s", s);
b = ButtonFind(s);
if (b)
ButtonToggle(b);
}
else if (!strcmp(s, "buttons"))
{
ss = atword(params, 2);
if (!ss)
return;
bmd.regex = ss;
ecore_list_for_each(button_list, _ButtonHideShow, &bmd);
}
else if (!strcmp(s, "all_buttons_except"))
{
ss = atword(params, 2);
if (!ss)
return;
bmd.id = 0;
bmd.match = 0;
bmd.regex = ss;
ecore_list_for_each(button_list, _ButtonHideShow, &bmd);
}
else if (!strcmp(s, "all"))
{
ecore_list_for_each(button_list, _ButtonHideShow, &bmd);
}
done:
autosave();
}
static void
ButtonsIpc(const char *params, Client * c __UNUSED__)
{
const char *p;
char cmd[128], prm[4096];
int len;
Button *b;
cmd[0] = prm[0] = '\0';
p = params;
if (p)
{
len = 0;
sscanf(p, "%100s %4000s %n", cmd, prm, &len);
p += len;
}
if (!p || cmd[0] == '?')
{
}
else if (!strncmp(cmd, "list", 2))
{
IpcPrintf("Win d s l x y w h name\n");
ECORE_LIST_FOR_EACH(button_list, b)
IpcPrintf("%#lx %2d %2d %2d %5d+%5d %5dx%5d %s\n",
EoGetXwin(b), EoGetDeskNum(b), EoIsSticky(b),
EoGetLayer(b), EoGetX(b), EoGetY(b), EoGetW(b), EoGetH(b),
EoGetName(b));
}
else if (!strncmp(cmd, "move", 2))
{
if (Mode_buttons.button)
ButtonDragStart(Mode_buttons.button);
}
}
static void
IPC_ButtonShow(const char *params, Client * c __UNUSED__)
{
doHideShowButton(params);
}
static const IpcItem ButtonsIpcArray[] = {
{
ButtonsIpc,
"button", "btn",
"Button functions",
" button list List buttons\n"},
{
IPC_ButtonShow,
"button_show", NULL,
"Show or Hide buttons on desktop",
"use \"button_show <button/buttons/all_buttons_except/all> "
"<BUTTON_STRING>\"\nexamples: \"button_show buttons all\" "
"(removes all buttons and the dragbar)\n\"button_show\" "
"(removes all buttons)\n \"button_show buttons CONFIG*\" "
"(removes all buttons with CONFIG in the start)\n"},
};
#define N_IPC_FUNCS (sizeof(ButtonsIpcArray)/sizeof(IpcItem))
#if 0
static const CfgItem ButtonsCfgItems[] = {
CFG_ITEM_BOOL(Conf.buttons, enable, 1),
};
#define N_CFG_ITEMS (sizeof(ButtonsCfgItems)/sizeof(CfgItem))
#endif
/*
* Module descriptor
*/
const EModule ModButtons = {
"buttons", "btn",
ButtonsSighan,
{N_IPC_FUNCS, ButtonsIpcArray},
{0, NULL}
};