forked from enlightenment/enlightenment
537 lines
12 KiB
C
537 lines
12 KiB
C
#include "debug.h"
|
|
#include "desktops.h"
|
|
#include "config.h"
|
|
#include "actions.h"
|
|
#include "border.h"
|
|
#include "view.h"
|
|
#include "icccm.h"
|
|
#include "util.h"
|
|
#include "object.h"
|
|
#include "e_view_machine.h"
|
|
|
|
static Evas_List desktops = NULL;
|
|
static Window e_base_win = 0;
|
|
static int screen_w, screen_h;
|
|
|
|
static void ecore_idle(void *data);
|
|
|
|
static void
|
|
ecore_idle(void *data)
|
|
{
|
|
D_ENTER;
|
|
/* FIXME -- Raster, how is this related to the desktop code? */
|
|
|
|
e_db_runtime_flush();
|
|
D_RETURN;
|
|
UN(data);
|
|
}
|
|
|
|
void
|
|
e_desktops_init(void)
|
|
{
|
|
E_Desktop *desk;
|
|
|
|
D_ENTER;
|
|
|
|
ecore_window_get_geometry(0, NULL, NULL, &screen_w, &screen_h);
|
|
e_base_win = ecore_window_override_new(0, 0, 0, screen_w, screen_h);
|
|
ecore_window_show(e_base_win);
|
|
desk = e_desktops_new();
|
|
e_desktops_show(desk);
|
|
ecore_event_filter_idle_handler_add(ecore_idle, NULL);
|
|
|
|
e_icccm_advertise_e_compat();
|
|
e_icccm_advertise_mwm_compat();
|
|
e_icccm_advertise_gnome_compat();
|
|
e_icccm_advertise_kde_compat();
|
|
e_icccm_advertise_net_compat();
|
|
|
|
e_icccm_set_desk_area_size(0, 1, 1);
|
|
e_icccm_set_desk_area(0, 0, 0);
|
|
e_icccm_set_desk(0, 0);
|
|
|
|
D_RETURN;
|
|
}
|
|
|
|
void
|
|
e_desktops_scroll(E_Desktop * desk, int dx, int dy)
|
|
{
|
|
Evas_List l;
|
|
int xd, yd, wd, hd;
|
|
int grav, grav_stick;
|
|
|
|
D_ENTER;
|
|
|
|
/* set grav */
|
|
if ((dx == 0) && (dy == 0))
|
|
D_RETURN;
|
|
desk->x -= dx;
|
|
desk->y -= dy;
|
|
xd = yd = wd = hd = 0;
|
|
grav = NorthWestGravity;
|
|
grav_stick = SouthEastGravity;
|
|
if ((dx <= 0) && (dy <= 0))
|
|
{
|
|
grav = NorthWestGravity;
|
|
grav_stick = SouthEastGravity;
|
|
xd = dx;
|
|
yd = dy;
|
|
wd = -dx;
|
|
hd = -dy;
|
|
}
|
|
else if ((dx >= 0) && (dy <= 0))
|
|
{
|
|
grav = NorthEastGravity;
|
|
grav_stick = SouthWestGravity;
|
|
xd = 0;
|
|
yd = dy;
|
|
wd = dx;
|
|
hd = -dy;
|
|
}
|
|
else if ((dx >= 0) && (dy >= 0))
|
|
{
|
|
grav = SouthEastGravity;
|
|
grav_stick = NorthWestGravity;
|
|
xd = 0;
|
|
yd = 0;
|
|
wd = dx;
|
|
hd = dy;
|
|
}
|
|
else if ((dx <= 0) && (dy >= 0))
|
|
{
|
|
grav = SouthWestGravity;
|
|
grav_stick = NorthEastGravity;
|
|
xd = dx;
|
|
yd = 0;
|
|
wd = -dx;
|
|
hd = dy;
|
|
}
|
|
for (l = desk->windows; l; l = l->next)
|
|
{
|
|
E_Border *b;
|
|
|
|
b = l->data;
|
|
/* if sticky */
|
|
if ((b->client.sticky) && (!b->mode.move))
|
|
ecore_window_gravity_set(b->win.main, StaticGravity);
|
|
else
|
|
ecore_window_gravity_set(b->win.main, grav);
|
|
}
|
|
grav_stick = StaticGravity;
|
|
/* scroll */
|
|
ecore_window_move_resize(desk->win.container,
|
|
xd, yd, screen_w + wd, screen_h + hd);
|
|
/* reset */
|
|
for (l = desk->windows; l; l = l->next)
|
|
{
|
|
E_Border *b;
|
|
|
|
b = l->data;
|
|
/* if sticky */
|
|
if (b->client.sticky)
|
|
ecore_window_gravity_set(b->win.main, StaticGravity);
|
|
else
|
|
ecore_window_gravity_set(b->win.main, grav_stick);
|
|
/* ecore_window_gravity_set(b->win.main, grav_stick);*/
|
|
}
|
|
ecore_window_move_resize(desk->win.container, 0, 0, screen_w, screen_h);
|
|
for (l = desk->windows; l; l = l->next)
|
|
{
|
|
E_Border *b;
|
|
|
|
b = l->data;
|
|
ecore_window_gravity_reset(b->win.main);
|
|
if ((!b->client.sticky) && (!b->mode.move))
|
|
{
|
|
b->current.requested.x += dx;
|
|
b->current.requested.y += dy;
|
|
b->current.x = b->current.requested.x;
|
|
b->current.y = b->current.requested.y;
|
|
b->previous.requested.x = b->current.requested.x;
|
|
b->previous.requested.y = b->current.requested.y;
|
|
b->previous.x = b->current.x;
|
|
b->previous.y = b->current.y;
|
|
b->changed = 1;
|
|
}
|
|
}
|
|
|
|
D_RETURN;
|
|
}
|
|
|
|
void
|
|
e_desktops_cleanup(E_Desktop * desk)
|
|
{
|
|
D_ENTER;
|
|
|
|
while (desk->windows)
|
|
{
|
|
E_Border *b;
|
|
|
|
b = desk->windows->data;
|
|
e_action_stop_by_object(E_OBJECT(b), NULL, 0, 0, 0, 0);
|
|
|
|
if (e_object_get_usecount(E_OBJECT(b)) == 1)
|
|
e_border_release(b);
|
|
e_object_unref(E_OBJECT(b));
|
|
}
|
|
|
|
ecore_window_destroy(desk->win.main);
|
|
IF_FREE(desk->name);
|
|
IF_FREE(desk->dir);
|
|
|
|
e_object_cleanup(E_OBJECT(desk));
|
|
|
|
D_RETURN;
|
|
}
|
|
|
|
/* 2002/04/23 Azundris <hacks@azundris.com> Transparency for legacy apps
|
|
*
|
|
* Since we have new fancy ways of drawing stuff, we technically don't
|
|
* use the root window any more, in the X meaning of the word. This
|
|
* results in legacy apps (xchat, xemacs, konsole, ...) failing to find
|
|
* a root pixmap, thereby breaking pseudo-transparency. Since we're
|
|
* using a pixmap below anyway, we may as well export it to unbreak
|
|
* the legacy thingies. This code reuses parts of Esetroot (written
|
|
* by Nat Friedman <ndf@mit.edu> with modifications by Gerald Britton
|
|
* <gbritton@mit.edu> and Michael Jennings <mej@eterm.org>). raster
|
|
* intensely dislikes the pseudo-transparency hacks, so don't go to him
|
|
* if you need to discuss them. : )
|
|
*
|
|
* THIS CODE IS CONSIDERED EXPERIMENTAL (alpha).
|
|
* */
|
|
|
|
static void
|
|
e_desktops_set_fake_root(Pixmap p)
|
|
{
|
|
Display *Xdisplay;
|
|
Screen *scr;
|
|
Window Xroot;
|
|
int screen;
|
|
Atom prop_root, prop_esetroot, type;
|
|
int format;
|
|
unsigned long length, after;
|
|
unsigned char *data_root, *data_esetroot;
|
|
|
|
D_ENTER;
|
|
|
|
Xdisplay = ecore_display_get();
|
|
|
|
screen = DefaultScreen(Xdisplay);
|
|
Xroot = RootWindow(Xdisplay, screen);
|
|
scr = ScreenOfDisplay(Xdisplay, screen);
|
|
|
|
XGrabServer(Xdisplay);
|
|
|
|
prop_root = XInternAtom(Xdisplay, "_XROOTPMAP_ID", True);
|
|
prop_esetroot = XInternAtom(Xdisplay, "ESETROOT_PMAP_ID", True);
|
|
|
|
if (prop_root != None && prop_esetroot != None)
|
|
{
|
|
XGetWindowProperty(Xdisplay, Xroot, prop_root, 0L, 1L, False,
|
|
AnyPropertyType, &type, &format, &length, &after,
|
|
&data_root);
|
|
if (type == XA_PIXMAP)
|
|
{
|
|
XGetWindowProperty(Xdisplay, Xroot, prop_esetroot, 0L, 1L, False,
|
|
AnyPropertyType, &type, &format, &length,
|
|
&after, &data_esetroot);
|
|
if (data_root && data_esetroot)
|
|
{
|
|
if (type == XA_PIXMAP
|
|
&& *((Pixmap *) data_root) == *((Pixmap *) data_esetroot))
|
|
{
|
|
XKillClient(Xdisplay, *((Pixmap *) data_root));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* This will locate the property, creating it if it doesn't exist */
|
|
prop_root = XInternAtom(Xdisplay, "_XROOTPMAP_ID", False);
|
|
prop_esetroot = XInternAtom(Xdisplay, "ESETROOT_PMAP_ID", False);
|
|
|
|
/* The call above should have created it. If that failed, we can't
|
|
* continue. */
|
|
if (prop_root == None || prop_esetroot == None)
|
|
{
|
|
fprintf(stderr,
|
|
"E17: Creation of pixmap property failed in internal Esetroot.\n");
|
|
D_RETURN;
|
|
}
|
|
|
|
XChangeProperty(Xdisplay, Xroot, prop_root, XA_PIXMAP, 32, PropModeReplace,
|
|
(unsigned char *)&p, 1);
|
|
XChangeProperty(Xdisplay, Xroot, prop_esetroot, XA_PIXMAP, 32,
|
|
PropModeReplace, (unsigned char *)&p, 1);
|
|
XSetCloseDownMode(Xdisplay, RetainPermanent);
|
|
XFlush(Xdisplay);
|
|
|
|
XSetWindowBackgroundPixmap(Xdisplay, Xroot, p);
|
|
XClearWindow(Xdisplay, Xroot);
|
|
XUngrabServer(Xdisplay);
|
|
XFlush(Xdisplay);
|
|
|
|
D_RETURN;
|
|
}
|
|
|
|
void
|
|
e_desktops_init_file_display(E_Desktop * desk)
|
|
{
|
|
E_View *v;
|
|
E_Border *b;
|
|
char buf[PATH_MAX];
|
|
|
|
D_ENTER;
|
|
|
|
v = e_view_new();
|
|
v->size.w = desk->real.w;
|
|
v->size.h = desk->real.h;
|
|
v->options.back_pixmap = 1;
|
|
|
|
desk->view = v;
|
|
/* fixme: later */
|
|
/* uncomment this and comment out the next line for some tress testing */
|
|
/* e_strdup(v->dir, "/dev"); */
|
|
/* e_strdup(v->dir, e_file_home()); */
|
|
snprintf(buf, PATH_MAX, "%s/desktop/default", e_config_user_dir());
|
|
|
|
e_view_set_dir(v, buf);
|
|
v->is_desktop = 1;
|
|
e_view_realize(v);
|
|
e_view_populate(v);
|
|
e_view_set_look(v, NULL);
|
|
|
|
ecore_window_hint_set_borderless(v->win.base);
|
|
ecore_window_hint_set_sticky(v->win.base, 1);
|
|
ecore_window_hint_set_layer(v->win.base, 1);
|
|
ecore_window_set_title(v->win.base, "Desktop");
|
|
ecore_window_set_name_class(v->win.base, "FileView", "Desktop");
|
|
ecore_window_set_min_size(v->win.base, desk->real.w, desk->real.h);
|
|
ecore_window_set_max_size(v->win.base, desk->real.w, desk->real.h);
|
|
b = e_border_adopt(v->win.base, 1);
|
|
b->client.internal = 1;
|
|
e_border_remove_click_grab(b);
|
|
b->client.sticky = 1;
|
|
b->client.fixed = 1;
|
|
b->client.is_desktop = 1;
|
|
|
|
if (v->options.back_pixmap)
|
|
{
|
|
e_view_update(v);
|
|
if (v->pmap)
|
|
e_desktops_set_fake_root(v->pmap);
|
|
}
|
|
|
|
D_RETURN;
|
|
}
|
|
|
|
E_Desktop *
|
|
e_desktops_new(void)
|
|
{
|
|
E_Desktop *desk;
|
|
|
|
D_ENTER;
|
|
|
|
desk = NEW(E_Desktop, 1);
|
|
ZERO(desk, E_Desktop, 1);
|
|
|
|
e_observee_init(E_OBSERVEE(desk), (E_Cleanup_Func) e_desktops_cleanup);
|
|
|
|
desk->win.main =
|
|
ecore_window_override_new(e_base_win, 0, 0, screen_w, screen_h);
|
|
desk->win.container =
|
|
ecore_window_override_new(desk->win.main, 0, 0, screen_w, screen_h);
|
|
ecore_window_lower(desk->win.container);
|
|
|
|
ecore_window_show(desk->win.container);
|
|
|
|
desk->x = 0;
|
|
desk->y = 0;
|
|
desk->real.w = screen_w;
|
|
desk->real.h = screen_h;
|
|
desk->virt.w = screen_w;
|
|
desk->virt.h = screen_h;
|
|
|
|
desktops = evas_list_append(desktops, desk);
|
|
|
|
D_RETURN_(desk);
|
|
}
|
|
|
|
void
|
|
e_desktops_add_border(E_Desktop * d, E_Border * b)
|
|
{
|
|
D_ENTER;
|
|
|
|
if ((!d) || (!b))
|
|
D_RETURN;
|
|
b->desk = d;
|
|
b->client.desk = d->desk.desk;
|
|
b->client.area.x = d->desk.area.x;
|
|
b->client.area.y = d->desk.area.y;
|
|
e_border_raise(b);
|
|
|
|
D_RETURN;
|
|
}
|
|
|
|
void
|
|
e_desktops_del_border(E_Desktop * d, E_Border * b)
|
|
{
|
|
D_ENTER;
|
|
|
|
if ((!d) || (!b))
|
|
D_RETURN;
|
|
d->windows = evas_list_remove(d->windows, b);
|
|
b->desk = NULL;
|
|
|
|
D_RETURN;
|
|
}
|
|
|
|
void
|
|
e_desktops_delete(E_Desktop * d)
|
|
{
|
|
D_ENTER;
|
|
|
|
e_object_unref(E_OBJECT(d));
|
|
|
|
D_RETURN;
|
|
}
|
|
|
|
void
|
|
e_desktops_show(E_Desktop * d)
|
|
{
|
|
D_ENTER;
|
|
|
|
ecore_window_show(d->win.main);
|
|
|
|
D_RETURN;
|
|
}
|
|
|
|
void
|
|
e_desktops_hide(E_Desktop * d)
|
|
{
|
|
D_ENTER;
|
|
|
|
ecore_window_hide(d->win.main);
|
|
|
|
D_RETURN;
|
|
}
|
|
|
|
int
|
|
e_desktops_get_num(void)
|
|
{
|
|
D_ENTER;
|
|
D_RETURN_(8);
|
|
}
|
|
|
|
E_Desktop *
|
|
e_desktops_get(int d)
|
|
{
|
|
Evas_List l;
|
|
int i;
|
|
|
|
D_ENTER;
|
|
|
|
for (i = 0, l = desktops; l; l = l->next, i++)
|
|
{
|
|
if (i == d)
|
|
D_RETURN_((E_Desktop *) l->data);
|
|
}
|
|
|
|
D_RETURN_(NULL);
|
|
}
|
|
|
|
int
|
|
e_desktops_get_current(void)
|
|
{
|
|
E_Desktop *desk;
|
|
|
|
D_ENTER;
|
|
|
|
desk = e_desktops_get(0);
|
|
if (desk)
|
|
D_RETURN_(desk->desk.desk);
|
|
|
|
D_RETURN_(0);
|
|
}
|
|
|
|
void
|
|
e_desktops_goto_desk(int d)
|
|
{
|
|
D_ENTER;
|
|
|
|
e_desktops_goto(d, 0, 0);
|
|
|
|
D_RETURN;
|
|
}
|
|
|
|
void
|
|
e_desktops_goto(int d, int ax, int ay)
|
|
{
|
|
E_Desktop *desk;
|
|
|
|
D_ENTER;
|
|
|
|
desk = e_desktops_get(0);
|
|
if (desk)
|
|
{
|
|
int dx, dy;
|
|
Evas_List l;
|
|
|
|
if ((d == desk->desk.desk) &&
|
|
(ax == desk->desk.area.x) && (ay == desk->desk.area.y))
|
|
D_RETURN;
|
|
|
|
dx = ax - desk->desk.area.x;
|
|
dy = ay - desk->desk.area.y;
|
|
|
|
for (l = desk->windows; l; l = l->next)
|
|
{
|
|
E_Border *b;
|
|
|
|
b = l->data;
|
|
if ((!b->client.sticky) && (!b->mode.move)
|
|
&& (!b->client.iconified))
|
|
{
|
|
if (b->client.desk != d)
|
|
{
|
|
if (b->current.requested.visible)
|
|
{
|
|
b->current.requested.visible = 0;
|
|
b->changed = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!b->current.requested.visible)
|
|
{
|
|
b->current.requested.visible = 1;
|
|
b->changed = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
e_border_update_borders();
|
|
|
|
/* if no scrolling... */
|
|
e_desktops_scroll(desk, -(dx * desk->real.w), -(dy * desk->real.h));
|
|
/* if scrolling.. need to setup a timeout etc. */
|
|
|
|
desk->desk.desk = d;
|
|
desk->desk.area.x = ax;
|
|
desk->desk.area.y = ay;
|
|
e_icccm_set_desk_area(0, desk->desk.area.x, desk->desk.area.y);
|
|
e_icccm_set_desk(0, desk->desk.desk);
|
|
e_observee_notify_observers(E_OBSERVEE(desk), E_EVENT_DESKTOP_SWITCH,
|
|
NULL);
|
|
}
|
|
|
|
D_RETURN;
|
|
}
|
|
|
|
Evas_List
|
|
e_desktops_get_desktops_list()
|
|
{
|
|
D_ENTER;
|
|
D_RETURN_(desktops);
|
|
}
|