e16/src/hints.c

643 lines
14 KiB
C

/*
* Copyright (C) 2003-2008 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.
*/
/*
* Feeble attempt to collect hint stuff in one place
*/
#include "E.h"
#include "borders.h" /* FIXME - Should not be here */
#include "desktops.h" /* FIXME - Should not be here */
#include "e16-ecore_hints.h"
#include "events.h"
#include "ewins.h"
#include "hints.h"
#include "xwin.h"
#include <X11/Xatom.h>
#define N_ITEMS(x) (sizeof(x)/sizeof(x[0]))
static const char *const atoms_misc_names[] = {
/* Misc atoms */
"MANAGER",
/* Root background atoms */
"_XROOTPMAP_ID",
"_XROOTCOLOR_PIXEL",
/* E16 atoms */
"ENLIGHTENMENT_VERSION",
"ENLIGHTENMENT_COMMS",
"ENL_MSG",
"ENL_INTERNAL_AREA_DATA",
"ENL_INTERNAL_DESK_DATA",
"ENL_WIN_DATA",
"ENL_WIN_BORDER"
};
unsigned int atoms_misc[10];
void
AtomListIntern(const char *const *names, unsigned int num, unsigned int *atoms)
{
#if SIZEOF_INT == SIZEOF_LONG
XInternAtoms(disp, (char **)names, num, False, (Atom *) atoms);
#else
unsigned int i;
Atom *_atoms;
_atoms = EMALLOC(Atom, num);
if (!_atoms)
return;
XInternAtoms(disp, (char **)names, num, False, _atoms);
for (i = 0; i < num; i++)
atoms[i] = _atoms[i];
Efree(_atoms);
#endif
}
void
HintsInit(void)
{
Window win;
AtomListIntern(atoms_misc_names, N_ITEMS(atoms_misc_names), atoms_misc);
win = XCreateSimpleWindow(disp, VRoot.xwin, -200, -200, 5, 5, 0, 0, 0);
ICCCM_Init();
MWM_SetInfo();
#if ENABLE_GNOME
GNOME_SetHints(win);
#endif
EWMH_Init(win);
ecore_x_window_prop_string_set(VRoot.xwin, E16_ATOM_VERSION, e_wm_version);
if (Mode.wm.window)
{
HintsSetWindowName(VRoot.win, "Enlightenment");
HintsSetWindowClass(VRoot.win, "Virtual-Root", "Enlightenment");
}
Mode.root.ext_pmap = HintsGetRootPixmap(VRoot.win);
Mode.root.ext_pmap_valid = EDrawableCheck(Mode.root.ext_pmap, 0);
}
/*
* Functions that set X11-properties from E-internals
*/
void
HintsSetRootHints(Win win __UNUSED__)
{
/* Nothing done here for now */
}
void
HintsSetClientList(void)
{
#if ENABLE_GNOME
GNOME_SetClientList();
#endif
EWMH_SetClientList();
EWMH_SetClientStacking();
}
void
HintsSetClientStacking(void)
{
EWMH_SetClientStacking();
}
void
HintsSetDesktopConfig(void)
{
#if ENABLE_GNOME
GNOME_SetDeskCount();
GNOME_SetDeskNames();
#endif
EWMH_SetDesktopCount();
EWMH_SetDesktopRoots();
EWMH_SetDesktopNames();
EWMH_SetWorkArea();
}
void
HintsSetViewportConfig(void)
{
#if ENABLE_GNOME
GNOME_SetAreaCount();
#endif
EWMH_SetDesktopSize();
}
void
HintsSetCurrentDesktop(void)
{
#if ENABLE_GNOME
GNOME_SetCurrentDesk();
#endif
EWMH_SetCurrentDesktop();
HintsSetDesktopViewport();
}
void
HintsSetDesktopViewport(void)
{
#if ENABLE_GNOME
GNOME_SetCurrentArea();
#endif
EWMH_SetDesktopViewport();
}
void
HintsSetActiveWindow(Window win)
{
EWMH_SetActiveWindow(win);
}
void
HintsSetWindowName(Win win, const char *name)
{
if (!name)
return;
ecore_x_icccm_title_set(WinGetXwin(win), name);
EWMH_SetWindowName(WinGetXwin(win), name);
}
void
HintsSetWindowClass(Win win, const char *name, const char *clss)
{
if (!name)
name = "NoName";
if (!clss)
clss = "NoClass";
ecore_x_icccm_name_class_set(WinGetXwin(win), name, clss);
}
void
HintsSetWindowDesktop(const EWin * ewin)
{
#if ENABLE_GNOME
GNOME_SetEwinDesk(ewin);
#endif
EWMH_SetWindowDesktop(ewin);
}
void
HintsSetWindowArea(const EWin * ewin __UNUSED__)
{
#if ENABLE_GNOME
GNOME_SetEwinArea(ewin);
#endif
}
void
HintsSetWindowState(const EWin * ewin)
{
#if ENABLE_GNOME
GNOME_SetHint(ewin);
#endif
EWMH_SetWindowState(ewin);
EWMH_SetWindowActions(ewin);
}
void
HintsSetWindowOpacity(const EWin * ewin)
{
EWMH_SetWindowOpacity(ewin);
}
void
HintsSetWindowBorder(const EWin * ewin)
{
EWMH_SetWindowBorder(ewin);
}
/*
* Functions that set E-internals from X11-properties
*/
void
HintsGetWindowHints(EWin * ewin)
{
#if ENABLE_GNOME
GNOME_GetHints(ewin, 0);
#endif
EWMH_GetWindowHints(ewin);
}
/*
* Functions that delete X11-properties
*/
void
HintsDelWindowHints(const EWin * ewin)
{
#if ENABLE_GNOME
GNOME_DelHints(ewin);
#endif
EWMH_DelWindowHints(ewin);
}
/*
* Functions processing received X11 messages
*/
void
HintsProcessPropertyChange(EWin * ewin, XEvent * ev)
{
if (ICCCM_ProcessPropertyChange(ewin, ev->xproperty.atom))
return;
if (EWMH_ProcessPropertyChange(ewin, ev->xproperty.atom))
return;
#if 0 /* No! - ENABLE_GNOME */
if (GNOME_GetHints(ewin, ev->xproperty.atom))
return;
#endif
#if 0
if (EDebug(1))
{
Eprintf("HintsProcessPropertyChange:\n");
EventShow(ev);
}
#endif
}
void
HintsProcessClientClientMessage(EWin * ewin, XClientMessageEvent * event)
{
if (ICCCM_ProcessClientClientMessage(ewin, event))
return;
if (EWMH_ProcessClientClientMessage(ewin, event))
return;
#if ENABLE_GNOME
if (GNOME_ProcessClientClientMessage(ewin, event))
return;
#endif
if (EDebug(1))
{
Eprintf("HintsProcessClientClientMessage:\n");
EventShow((XEvent *) event);
}
}
void
HintsProcessRootClientMessage(XClientMessageEvent * event)
{
if (ICCCM_ProcessRootClientMessage(event))
return;
if (EWMH_ProcessRootClientMessage(event))
return;
#if ENABLE_GNOME
if (GNOME_ProcessRootClientMessage(event))
return;
#endif
if (EDebug(1))
{
Eprintf("HintsProcessRootClientMessage:\n");
EventShow((XEvent *) event);
}
}
Pixmap
HintsGetRootPixmap(Win win)
{
Ecore_X_Pixmap pm;
int num;
pm = None;
num =
ecore_x_window_prop_xid_get(WinGetXwin(win), E_XROOTPMAP_ID, XA_PIXMAP,
&pm, 1);
return pm;
}
void
HintsSetRootInfo(Win win, Pixmap pmap, unsigned int color)
{
Ecore_X_Pixmap pm;
pm = pmap;
ecore_x_window_prop_xid_set(WinGetXwin(win), E_XROOTPMAP_ID, XA_PIXMAP, &pm,
1);
ecore_x_window_prop_card32_set(WinGetXwin(win), E_XROOTCOLOR_PIXEL, &color,
1);
}
typedef union
{
struct
{
unsigned version:8;
unsigned rsvd:22;
unsigned docked:1;
unsigned iconified:1;
} b;
int all:32;
} EWinInfoFlags;
#define ENL_DATA_ITEMS 12
#define ENL_DATA_VERSION 0
void
EHintsSetInfo(const EWin * ewin)
{
int c[ENL_DATA_ITEMS];
unsigned int flags[2];
EWinInfoFlags f;
if (EwinIsInternal(ewin))
return;
f.all = 0;
f.b.version = ENL_DATA_VERSION;
f.b.docked = ewin->state.docked;
f.b.iconified = ewin->state.iconified;
c[0] = f.all;
EwinFlagsEncode(ewin, flags);
c[1] = flags[0];
c[2] = flags[1];
c[3] = ewin->save_max.x;
c[4] = ewin->save_max.y;
c[5] = ewin->save_max.w;
c[6] = ewin->save_max.h;
c[7] = ewin->save_fs.x;
c[8] = ewin->save_fs.y;
c[9] = ewin->save_fs.w;
c[10] = ewin->save_fs.h;
c[11] = ewin->save_fs.layer;
ecore_x_window_prop_card32_set(EwinGetClientXwin(ewin), E16_ATOM_WIN_DATA,
(unsigned int *)c, ENL_DATA_ITEMS);
ecore_x_window_prop_string_set(EwinGetClientXwin(ewin), E16_ATOM_WIN_BORDER,
ewin->normal_border->name);
if (EDebug(EDBUG_TYPE_SNAPS))
Eprintf("Snap set einf %#lx: %4d+%4d %4dx%4d: %s\n",
EwinGetClientXwin(ewin), ewin->client.x, ewin->client.y,
ewin->client.w, ewin->client.h, EwinGetTitle(ewin));
}
void
EHintsGetInfo(EWin * ewin)
{
char *str;
int num;
int c[ENL_DATA_ITEMS + 1];
unsigned int flags[2];
EWinInfoFlags f;
if (EwinIsInternal(ewin))
return;
num =
ecore_x_window_prop_card32_get(EwinGetClientXwin(ewin), E16_ATOM_WIN_DATA,
(unsigned int *)c, ENL_DATA_ITEMS + 1);
if (num < 0)
return;
ewin->state.identified = 1;
ewin->client.grav = StaticGravity;
ewin->state.placed = 1;
if (num < 2)
return;
f.all = c[0];
if (f.b.version != ENL_DATA_VERSION)
return;
ewin->icccm.start_iconified = f.b.iconified;
ewin->state.docked = f.b.docked;
flags[0] = c[1];
flags[1] = c[2];
EwinFlagsDecode(ewin, flags);
if (num == ENL_DATA_ITEMS)
{
ewin->save_max.x = c[3];
ewin->save_max.y = c[4];
ewin->save_max.w = c[5];
ewin->save_max.h = c[6];
ewin->save_fs.x = c[7];
ewin->save_fs.y = c[8];
ewin->save_fs.w = c[9];
ewin->save_fs.h = c[10];
ewin->save_fs.layer = c[11];
}
str =
ecore_x_window_prop_string_get(EwinGetClientXwin(ewin),
E16_ATOM_WIN_BORDER);
if (str)
EwinSetBorderByName(ewin, str);
Efree(str);
if (EDebug(EDBUG_TYPE_SNAPS))
Eprintf("Snap get einf %#lx: %4d+%4d %4dx%4d: %s\n",
EwinGetClientXwin(ewin), ewin->client.x, ewin->client.y,
ewin->client.w, ewin->client.h, EwinGetTitle(ewin));
}
void
EHintsSetDeskInfo(void)
{
int i, ax, ay, n_desks;
unsigned int *c;
if (!DesksGetCurrent()) /* Quit if current desk isn't assigned yet */
return;
n_desks = DesksGetNumber();
if (n_desks <= 0)
return;
c = EMALLOC(unsigned int, 2 * n_desks);
if (!c)
return;
for (i = 0; i < n_desks; i++)
{
DeskGetArea(DeskGet(i), &ax, &ay);
c[(i * 2)] = ax;
c[(i * 2) + 1] = ay;
}
ecore_x_window_prop_card32_set(VRoot.xwin, E16_ATOM_INTERNAL_AREA_DATA,
c, 2 * n_desks);
c[0] = DesksGetCurrentNum();
ecore_x_window_prop_card32_set(VRoot.xwin, E16_ATOM_INTERNAL_DESK_DATA, c,
1);
Efree(c);
if (Mode.root.ext_pmap_valid)
{
HintsSetRootInfo(VRoot.win, Mode.root.ext_pmap, 0);
ESetWindowBackgroundPixmap(VRoot.win, Mode.root.ext_pmap);
}
}
void
EHintsGetDeskInfo(void)
{
unsigned int *c;
int num, i, n_desks;
n_desks = DesksGetNumber();
c = EMALLOC(unsigned int, 2 * n_desks);
if (!c)
return;
num = ecore_x_window_prop_card32_get(VRoot.xwin, E16_ATOM_INTERNAL_AREA_DATA,
c, 2 * n_desks);
if (num > 0)
{
for (i = 0; i < (num / 2); i++)
DeskSetArea(DeskGet(i), c[(i * 2)], c[(i * 2) + 1]);
}
num = ecore_x_window_prop_card32_get(VRoot.xwin, E16_ATOM_INTERNAL_DESK_DATA,
c, 1);
if (num > 0)
{
DesksSetCurrent(DeskGet(c[0]));
}
else
{
/* Used to test if we should run cmd_init */
Mode.wm.session_start = 1;
}
Efree(c);
}
void
EHintsSetInfoOnAll(void)
{
int i, num;
EWin *const *lst;
if (EDebug(EDBUG_TYPE_SESSION))
Eprintf("SetEInfoOnAll\n");
lst = EwinListGetAll(&num);
for (i = 0; i < num; i++)
if (!EwinIsInternal(lst[i]))
EHintsSetInfo(lst[i]);
EHintsSetDeskInfo();
}
/*
* Selections.
*/
struct _selection
{
Atom atom;
Time time;
Win win;
EventCallbackFunc *func;
void *data;
};
ESelection *
SelectionAcquire(const char *name, EventCallbackFunc * func, void *data)
{
ESelection *sel;
char buf[128];
sel = ECALLOC(ESelection, 1);
if (!sel)
return sel;
Esnprintf(buf, sizeof(buf), "%s%d", name, VRoot.scr);
sel->atom = XInternAtom(disp, buf, False);
sel->time = EGetTimestamp();
sel->win = ECreateEventWindow(VRoot.win, -100, -100, 1, 1);
sel->func = func;
sel->data = data;
XSetSelectionOwner(disp, sel->atom, WinGetXwin(sel->win), sel->time);
if (XGetSelectionOwner(disp, sel->atom) != WinGetXwin(sel->win))
{
DialogOK(_("Selection Error!"), _("Could not acquire selection: %s"),
buf);
EDestroyWindow(sel->win);
Efree(sel);
return NULL;
}
if (sel->func)
{
ESelectInput(sel->win, SubstructureNotifyMask);
EventCallbackRegister(sel->win, 0, sel->func, sel->data);
}
ecore_x_client_message32_send(VRoot.xwin, E_XA_MANAGER,
StructureNotifyMask, CurrentTime, sel->atom,
WinGetXwin(sel->win), 0, 0);
if (EDebug(EDBUG_TYPE_SELECTION))
Eprintf("Window %#lx is now %s owner, time=%lu\n",
WinGetXwin(sel->win), buf, sel->time);
return sel;
}
void
SelectionRelease(ESelection * sel)
{
if (!sel)
return;
if (EDebug(EDBUG_TYPE_SELECTION))
Eprintf("Window %#lx is no longer %s owner\n",
WinGetXwin(sel->win), XGetAtomName(disp, sel->atom));
XSetSelectionOwner(disp, sel->atom, None, sel->time);
if (sel->func)
{
EventCallbackUnregister(sel->win, 0, sel->func, sel->data);
}
EDestroyWindow(sel->win);
Efree(sel);
}