Split iconbox into container, iconbox, and systray.

SVN revision: 25181
This commit is contained in:
Kim Woelders 2006-08-28 22:32:48 +00:00
parent bbbf2d7a38
commit c58980b6b1
5 changed files with 2815 additions and 2631 deletions

View File

@ -31,6 +31,8 @@ e16_SOURCES = \
comms.c \
conf.h \
config.c \
container.c \
container.h \
coords.c \
cursors.c \
desktops.c \
@ -112,6 +114,7 @@ e16_SOURCES = \
sound.c \
stacking.c \
startup.c \
systray.c \
tclass.c \
tclass.h \
text.c \

2022
src/container.c Normal file

File diff suppressed because it is too large Load Diff

131
src/container.h Normal file
View File

@ -0,0 +1,131 @@
/*
* Copyright (C) 2000-2006 Carsten Haitzler, Geoff Harrison and various contributors
* Copyright (C) 2004-2006 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.
*/
#ifndef _CONTAINER_H_
#define _CONTAINER_H_
#include "eimage.h"
typedef struct _container Container;
typedef struct
{
void *obj;
int xo, yo, wo, ho; /* Outer */
int xi, yi, wi, hi; /* Inner */
EImage *im;
} ContainerObject;
typedef struct
{
void (*Init) (Container * ct);
void (*Exit) (Container * ct, int wm_exit);
void (*Signal) (Container * ct, int signal, void *prm);
void (*Event) (Container * ct, XEvent * ev);
void (*ObjSizeCalc) (Container * ct, ContainerObject * cto);
void (*ObjPlace) (Container * ct, ContainerObject * cto,
EImage * im);
} ContainerOps;
struct _container
{
const ContainerOps *ops;
const char *wm_name;
const char *menu_title;
const char *dlg_title;
/* user settings */
char *name;
char type;
char orientation;
char animate;
char scrollbar_side;
char arrow_side;
char shownames;
char nobg;
int iconsize;
int icon_mode;
char auto_resize;
char draw_icon_base;
char scrollbar_hide;
char cover_hide;
int auto_resize_anchor;
/* internally set stuff */
EWin *ewin;
int w, h;
int pos;
int max, max_min;
ImageClass *ic_box;
ImageClass *ic_item_base;
EImage *im_item_base;
char arrow1_hilited;
char arrow1_clicked;
char arrow2_hilited;
char arrow2_clicked;
char icon_clicked;
char scrollbar_hilited;
char scrollbar_clicked;
char scrollbox_clicked;
Win win;
Win cover_win;
Win icon_win;
Win scroll_win;
Win arrow1_win;
Win arrow2_win;
Win scrollbar_win;
Win scrollbarknob_win;
int num_objs;
ContainerObject *objs;
/* these are theme-settable parameters */
int scroll_thickness;
int arrow_thickness;
int bar_thickness;
int knob_length;
/* State flags */
char do_update;
};
void ContainerRedraw(Container * ct);
typedef int (ContainerIterator) (Container * ct, void *data);
Container *ContainersIterate(ContainerIterator * cti, int type,
void *data);
Container **ContainersGetList(int *pnum);
int ContainerObjectAdd(Container * ct, void *obj);
int ContainerObjectDel(Container * ct, void *obj);
int ContainerObjectFind(Container * ct, void *obj);
void *ContainerObjectFindByXY(Container * ct, int x, int y);
/* Here? */
#define IB_TYPE_ICONBOX 0
#define IB_TYPE_SYSTRAY 1
#endif /* _CONTAINER_H_ */

File diff suppressed because it is too large Load Diff

516
src/systray.c Normal file
View File

@ -0,0 +1,516 @@
/*
* Copyright (C) 2004-2006 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 "container.h"
#include "e16-ecore_hints.h"
#include "xwin.h"
#include <math.h>
#define DEBUG_SYSTRAY 0
/* Systray object info */
typedef struct
{
Win win;
char mapped;
} SWin;
#define StObjGetWin(o) (((SWin*)(o))->win)
#define StObjIsMapped(o) (((SWin*)(o))->mapped)
/* Selection atoms */
static Atom E_XA_MANAGER = 0;
/* XEmbed atoms */
static Atom E_XA__XEMBED = 0;
static Atom E_XA__XEMBED_INFO = 0;
/* Systray atoms */
static Atom _NET_SYSTEM_TRAY_Sx = 0;
static Atom _NET_SYSTEM_TRAY_OPCODE = 0;
static Atom _NET_SYSTEM_TRAY_MESSAGE_DATA = 0;
static Win systray_sel_win = NoWin;
static Time systray_sel_time = 0;
static void SystrayItemEvent(Win win, XEvent * ev, void *prm);
#define SYSTEM_TRAY_REQUEST_DOCK 0
#define SYSTEM_TRAY_BEGIN_MESSAGE 1
#define SYSTEM_TRAY_CANCEL_MESSAGE 2
/* _XEMBED client message */
#define XEMBED_EMBEDDED_NOTIFY 0
/* _XEMBED_INFO property */
#define XEMBED_MAPPED (1 << 0)
static int
SystrayGetXembedInfo(Window win, int *info)
{
unsigned char *prop_ret;
Atom type_ret;
unsigned long bytes_after, num_ret;
int format_ret;
prop_ret = NULL;
if (XGetWindowProperty(disp, win, E_XA__XEMBED_INFO, 0, 0x7fffffff,
False, E_XA__XEMBED_INFO, &type_ret, &format_ret,
&num_ret, &bytes_after, &prop_ret) != Success)
return -1;
if (prop_ret && type_ret == E_XA__XEMBED_INFO && format_ret == 32
&& num_ret >= 2)
{
info[0] = ((unsigned long *)prop_ret)[0];
info[1] = ((unsigned long *)prop_ret)[1];
}
else
{
/* Property invalid or not there. I doubt we ever get here */
info[0] = 0; /* Set protocol version 0 */
info[1] = 1; /* Set mapped */
num_ret = 0;
}
if (prop_ret)
XFree(prop_ret);
return num_ret;
}
/*
* Return index, -1 if not found.
*/
static int
SystrayObjFind(Container * ct, Window win)
{
int i;
for (i = 0; i < ct->num_objs; i++)
if (win == WinGetXwin(StObjGetWin(ct->objs[i].obj)))
return i;
return -1;
}
static Win
SystrayObjManage(Container * ct, Window xwin)
{
Win win;
#if DEBUG_SYSTRAY
Eprintf("SystrayObjManage %#lx\n", xwin);
#endif
win = ERegisterWindow(xwin, NULL);
if (win == NoWin)
return win;
ESelectInput(win, StructureNotifyMask | PropertyChangeMask);
EventCallbackRegister(win, 0, SystrayItemEvent, ct);
EReparentWindow(win, ct->icon_win, 0, 0);
XAddToSaveSet(disp, xwin);
return win;
}
static void
SystrayObjUnmanage(Container * ct __UNUSED__, Win win, int gone)
{
#if DEBUG_SYSTRAY
Eprintf("SystrayObjUnmanage %#lx gone=%d\n", WinGetXwin(win), gone);
#endif
if (!gone)
{
ESelectInput(win, NoEventMask);
EUnmapWindow(win);
EReparentWindow(win, VRoot.win, 0, 0);
XRemoveFromSaveSet(disp, WinGetXwin(win));
}
EventCallbackUnregister(win, 0, SystrayItemEvent, ct);
EUnregisterWindow(win);
}
static void
SystrayObjAdd(Container * ct, Window xwin)
{
SWin *swin = NULL;
Win win;
int xembed_info[2];
/* Not if already there */
if (SystrayObjFind(ct, xwin) >= 0)
return;
EGrabServer();
switch (SystrayGetXembedInfo(xwin, xembed_info))
{
case -1: /* Error - assume invalid window */
Eprintf("SystrayObjAdd: Hmm.. Invalid window? Ignoring %#lx\n", xwin);
goto bail_out;
case 0: /* Assume broken - proceed anyway */
Eprintf("SystrayObjAdd: Hmm.. No _XEMBED_INFO?\n");
break;
default:
if (EventDebug(EDBUG_TYPE_ICONBOX))
Eprintf("SystrayObjAdd: _XEMBED_INFO: %#lx: %d %d\n", xwin,
xembed_info[0], xembed_info[1]);
break;
}
swin = Emalloc(sizeof(SWin));
if (!swin)
goto bail_out;
if (ContainerObjectAdd(ct, swin) < 0)
goto bail_out;
win = SystrayObjManage(ct, xwin);
if (win == NoWin)
goto bail_out;
swin->win = win;
swin->mapped = (xembed_info[1] & XEMBED_MAPPED) != 0;
if (swin->mapped)
EMapWindow(win);
/* TBD - Always set protocol version as reported by client */
ecore_x_client_message32_send(xwin, E_XA__XEMBED, NoEventMask,
CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0,
xwin, xembed_info[0]);
EUngrabServer();
return; /* Success */
bail_out:
EUngrabServer();
if (!swin)
return;
ContainerObjectDel(ct, swin);
Efree(swin);
}
static void
SystrayObjDel(Container * ct, Win win, int gone)
{
int i;
SWin *swin;
i = SystrayObjFind(ct, WinGetXwin(win));
if (i < 0)
return;
if (EventDebug(EDBUG_TYPE_ICONBOX))
Eprintf("SystrayObjDel %#lx\n", WinGetXwin(win));
swin = ct->objs[i].obj;
ContainerObjectDel(ct, swin);
if (disp)
SystrayObjUnmanage(ct, swin->win, gone);
Efree(swin);
}
static void
SystrayObjMapUnmap(Container * ct, Window win)
{
int i, map;
SWin *swin;
int xembed_info[2];
i = SystrayObjFind(ct, win);
if (i < 0)
return;
swin = ct->objs[i].obj;
if (SystrayGetXembedInfo(win, xembed_info) >= 0)
{
if (EventDebug(EDBUG_TYPE_ICONBOX))
Eprintf("SystrayObjMapUnmap: _XEMBED_INFO: %#lx: %d %d\n", win,
xembed_info[0], xembed_info[1]);
map = (xembed_info[1] & XEMBED_MAPPED) != 0;
if (map == swin->mapped)
return;
if (map)
EMapWindow(swin->win);
else
EUnmapWindow(swin->win);
}
else
{
if (EventDebug(EDBUG_TYPE_ICONBOX))
Eprintf("SystrayObjMapUnmap: _XEMBED_INFO: %#lx: gone?\n", win);
map = 0;
if (map == swin->mapped)
return;
}
swin->mapped = map;
ContainerRedraw(ct);
}
static void
SystrayEventClientMessage(Container * ct, XClientMessageEvent * ev)
{
Window win;
if (EventDebug(EDBUG_TYPE_ICONBOX))
Eprintf
("SystrayEventClientMessage: ev->type=%ld ev->data.l: %#lx %#lx %#lx %#lx\n",
ev->message_type, ev->data.l[0], ev->data.l[1], ev->data.l[2],
ev->data.l[3]);
if (ev->message_type == _NET_SYSTEM_TRAY_OPCODE)
{
win = ev->data.l[2];
if (win == None)
goto done;
SystrayObjAdd(ct, win);
}
else if (ev->message_type == _NET_SYSTEM_TRAY_MESSAGE_DATA)
{
if (EventDebug(EDBUG_TYPE_ICONBOX))
Eprintf("SystrayEventClientMessage: Got data message\n");
}
done:
;
}
static void
SystrayEventClientProperty(Container * ct, XPropertyEvent * ev)
{
if (EventDebug(EDBUG_TYPE_ICONBOX))
Eprintf("SystrayEventClientProperty %#lx %ld\n", ev->window, ev->atom);
if (ev->atom == E_XA__XEMBED_INFO)
{
SystrayObjMapUnmap(ct, ev->window);
}
}
static void
SystraySelectionEvent(Win win __UNUSED__, XEvent * ev, void *prm)
{
if (EventDebug(EDBUG_TYPE_ICONBOX))
Eprintf("SystraySelectionEvent %2d %#lx\n", ev->type, ev->xany.window);
switch (ev->type)
{
default:
Eprintf(" ??? SystraySelectionEvent %2d %#lx\n", ev->type,
ev->xany.window);
break;
case ClientMessage:
SystrayEventClientMessage(prm, &(ev->xclient));
break;
}
}
static void
SystrayEvent(Win _win __UNUSED__, XEvent * ev, void *prm __UNUSED__)
{
if (EventDebug(EDBUG_TYPE_ICONBOX))
Eprintf("SystrayEvent %2d %#lx\n", ev->type, ev->xany.window);
#if 0 /* FIXME - Need this one at all? ConfigureRequest? */
Window win;
switch (ev->type)
{
case MapNotify:
EWindowSync(ELookupXwin(ev->xmap.window));
ContainerRedraw(prm);
break;
case DestroyNotify:
win = ev->xdestroywindow.window;
goto do_terminate;
case ReparentNotify:
case EX_EVENT_REPARENT_GONE:
/* Terminate if reparenting away from systray */
if (ev->xreparent.parent == ev->xreparent.event)
break;
win = ev->xreparent.window;
goto do_terminate;
do_terminate:
SystrayObjDel(prm, win);
break;
}
#endif
}
static void
SystrayItemEvent(Win win, XEvent * ev, void *prm)
{
Container *ct = prm;
if (EventDebug(EDBUG_TYPE_ICONBOX))
Eprintf("SystrayItemEvent %2d %#lx\n", ev->type, ev->xany.window);
switch (ev->type)
{
case MapNotify:
EWindowSync(win);
ContainerRedraw(ct);
break;
case DestroyNotify:
goto do_terminate;
case ReparentNotify:
case EX_EVENT_REPARENT_GONE:
/* Terminate if reparenting away from systray */
if (ev->xreparent.parent == WinGetXwin(ct->icon_win))
break;
goto do_terminate;
case ClientMessage:
SystrayEventClientMessage(ct, &(ev->xclient));
break;
case PropertyNotify:
SystrayEventClientProperty(ct, &(ev->xproperty));
break;
do_terminate:
SystrayObjDel(ct, win, ev->type != ReparentNotify);
ContainerRedraw(ct);
break;
}
}
static void
SystrayInit(Container * ct)
{
char buf[32];
Win win;
Esnprintf(buf, sizeof(buf), "_NET_SYSTEM_TRAY_S%d", VRoot.scr);
E_XA_MANAGER = XInternAtom(disp, "MANAGER", False);
E_XA__XEMBED = XInternAtom(disp, "_XEMBED", False);
E_XA__XEMBED_INFO = XInternAtom(disp, "_XEMBED_INFO", False);
_NET_SYSTEM_TRAY_Sx = XInternAtom(disp, buf, False);
_NET_SYSTEM_TRAY_OPCODE =
XInternAtom(disp, "_NET_SYSTEM_TRAY_OPCODE", False);
_NET_SYSTEM_TRAY_MESSAGE_DATA =
XInternAtom(disp, "_NET_SYSTEM_TRAY_MESSAGE_DATA", False);
/* Acquire selection */
if (systray_sel_win != None)
{
DialogOK(_("Systray Error!"), _("Only one systray is allowed"));
return;
}
systray_sel_win = ECreateEventWindow(VRoot.win, -100, -100, 1, 1);
systray_sel_time = EGetTimestamp();
XSetSelectionOwner(disp, _NET_SYSTEM_TRAY_Sx, WinGetXwin(systray_sel_win),
systray_sel_time);
if (XGetSelectionOwner(disp, _NET_SYSTEM_TRAY_Sx) !=
WinGetXwin(systray_sel_win))
{
DialogOK(_("Systray Error!"), _("Could not activate systray"));
Eprintf("Failed to acquire selection %s\n", buf);
EDestroyWindow(systray_sel_win);
systray_sel_win = None;
return;
}
if (EventDebug(EDBUG_TYPE_ICONBOX))
Eprintf("Window %#lx is now %s owner, time=%ld\n",
WinGetXwin(systray_sel_win), buf, systray_sel_time);
ESelectInput(systray_sel_win,
SubstructureRedirectMask | SubstructureNotifyMask);
EventCallbackRegister(systray_sel_win, 0, SystraySelectionEvent, ct);
win = ct->icon_win;
ESelectInputAdd(win,
SubstructureRedirectMask /* | SubstructureNotifyMask */ );
EventCallbackRegister(win, 0, SystrayEvent, ct);
ecore_x_client_message32_send(VRoot.xwin, E_XA_MANAGER, StructureNotifyMask,
CurrentTime, _NET_SYSTEM_TRAY_Sx,
WinGetXwin(systray_sel_win), 0, 0);
/* Container parameter setup */
ct->wm_name = "Systray";
ct->menu_title = _("Systray Options");
ct->dlg_title = _("Systray Settings");
ct->iconsize = 24;
}
static void
SystrayExit(Container * ct, int wm_exit __UNUSED__)
{
XSetSelectionOwner(disp, _NET_SYSTEM_TRAY_Sx, None, systray_sel_time);
EventCallbackUnregister(systray_sel_win, 0, SystraySelectionEvent, ct);
EventCallbackUnregister(ct->win, 0, SystrayEvent, ct);
EDestroyWindow(systray_sel_win);
systray_sel_win = None;
while (ct->num_objs)
{
SystrayObjDel(ct, StObjGetWin(ct->objs[0].obj), 0);
}
}
static void
SystrayObjSizeCalc(Container * ct, ContainerObject * cto)
{
/* Inner size */
if (StObjIsMapped(cto->obj))
cto->wi = cto->hi = ct->iconsize;
else
cto->wi = cto->hi = 0;
}
static void
SystrayObjPlace(Container * ct __UNUSED__, ContainerObject * cto,
EImage * im __UNUSED__)
{
if (StObjIsMapped(cto->obj))
{
EMoveResizeWindow(StObjGetWin(cto->obj), cto->xi, cto->yi, cto->wi,
cto->hi);
}
}
const ContainerOps SystrayOps = {
SystrayInit,
SystrayExit,
NULL,
NULL,
SystrayObjSizeCalc,
SystrayObjPlace,
};