brace yourselves: E WINDOW PHYSICS MODULE!

if you have ephysics installed, a new module 'Physics' will be available under Look which provides some fun physics effects on windows such as:
*velocity based on drag direction/speed
*collisions
*gravity
note that the edges of the screen are considered boundaries, and so windows will bounce off or get stuck in them; you will have to drag a window out if it gets stuck because I've disabled physics effects in edge areas to both 1) prevent windows from sneaking past the screen limits and flying off into space 2) actually getting stuck to the point that you can't get them out

help needed!


SVN revision: 73365
This commit is contained in:
Mike Blumenkrantz 2012-07-05 15:01:58 +00:00
parent a977ceecf0
commit cfaf0c12b5
13 changed files with 1253 additions and 0 deletions

View File

@ -690,6 +690,37 @@ define([CHECK_MODULE_NOTIFICATION],
fi
])
have_ephysics=no
AM_CONDITIONAL([HAVE_EPHYSICS], [false])
AC_ARG_ENABLE([ephysics],
AC_HELP_STRING([--disable-ephysics], [disable Ephysics support @<:@default=detect@:>@]),
[e_cv_want_ephysics=$enableval],
AC_CACHE_VAL([e_cv_want_ephysics], [e_cv_want_ephysics=yes])
)
if test "x$e_cv_want_ephysics" != "xno" ; then
AC_E_CHECK_PKG(EPHYSICS, [ ephysics ],
[
AC_DEFINE_UNQUOTED([HAVE_EPHYSICS], [1], [enable ephysics])
],
[
AC_MSG_NOTICE([ephysics disabled])
e_cv_want_ephysics=no
])
else
AC_MSG_NOTICE([ephysics disabled])
e_cv_want_ephysics=no
fi
AC_SUBST([EPHYSICS_CFLAGS])
AC_SUBST([EPHYSICS_LIBS])
AM_CONDITIONAL(HAVE_PHYSICS, false)
define([CHECK_MODULE_PHYSICS],
[
if test "x$e_cv_want_ephysics" = "xno" ; then
PHYSICS=false
fi
])
AM_CONDITIONAL(HAVE_ALSA, false)
define([CHECK_MODULE_MIXER],
[
@ -806,6 +837,7 @@ AC_E_OPTIONAL_MODULE([syscon], true)
AC_E_OPTIONAL_MODULE([everything], true)
AC_E_OPTIONAL_MODULE([systray], true)
AC_E_OPTIONAL_MODULE([comp], true)
AC_E_OPTIONAL_MODULE([physics], true, [CHECK_MODULE_PHYSICS])
AC_E_OPTIONAL_MODULE([shot], true)
AC_E_OPTIONAL_MODULE([backlight], true)
AC_E_OPTIONAL_MODULE([tasks], true)
@ -961,6 +993,8 @@ src/modules/systray/Makefile
src/modules/systray/module.desktop
src/modules/comp/Makefile
src/modules/comp/module.desktop
src/modules/physics/Makefile
src/modules/physics/module.desktop
src/modules/shot/Makefile
src/modules/shot/module.desktop
src/modules/backlight/Makefile

View File

@ -175,6 +175,10 @@ if USE_MODULE_COMP
SUBDIRS += comp
endif
if USE_MODULE_PHYSICS
SUBDIRS += physics
endif
if USE_MODULE_OFONO
SUBDIRS += ofono
endif

View File

@ -0,0 +1,36 @@
MAINTAINERCLEANFILES = Makefile.in
MODULE = physics
# data files for the module
filesdir = $(libdir)/enlightenment/modules/$(MODULE)
files_DATA = e-module-$(MODULE).edj module.desktop
EXTRA_DIST = $(files_DATA)
# the module .so file
INCLUDES = -I. \
-I$(top_srcdir) \
-I$(top_srcdir)/src/modules/$(MODULE) \
-I$(top_srcdir)/src/bin \
-I$(top_builddir)/src/bin \
-I$(top_srcdir)/src/modules \
@e_cflags@ @EPHYSICS_CFLAGS@
pkgdir = $(libdir)/enlightenment/modules/$(MODULE)/$(MODULE_ARCH)
pkg_LTLIBRARIES = module.la
module_la_SOURCES = e_mod_main.c \
e_mod_main.h \
e_mod_config.c \
e_mod_config.h \
e_mod_physics_cfdata.c \
e_mod_physics_cfdata.h \
e_mod_physics.c \
e_mod_physics.h
module_la_LIBADD = @e_libs@ @dlopen_libs@ @EPHYSICS_LIBS@
module_la_LDFLAGS = -module -avoid-version
module_la_DEPENDENCIES = $(top_builddir)/config.h
uninstall:
rm -rf $(DESTDIR)$(libdir)/enlightenment/modules/$(MODULE)

Binary file not shown.

View File

@ -0,0 +1,142 @@
#include "e.h"
#include "e_mod_main.h"
#include "e_mod_config.h"
#include "e_mod_physics.h"
struct _E_Config_Dialog_Data
{
double delay;
double max_mass;
double gravity;
Eina_Bool ignore_fullscreen;
Eina_Bool ignore_maximized;
};
/* Protos */
static void *_create_data(E_Config_Dialog *cfd);
static void _free_data(E_Config_Dialog *cfd,
E_Config_Dialog_Data *cfdata);
static Evas_Object *_basic_create_widgets(E_Config_Dialog *cfd,
Evas *evas,
E_Config_Dialog_Data *cfdata);
static int _basic_apply_data(E_Config_Dialog *cfd,
E_Config_Dialog_Data *cfdata);
E_Config_Dialog *
e_int_config_physics_module(E_Container *con,
const char *params __UNUSED__)
{
E_Config_Dialog *cfd;
E_Config_Dialog_View *v;
char buf[4096];
Mod *mod = _physics_mod;
if (e_config_dialog_find("E", "appearance/physics")) return NULL;
v = E_NEW(E_Config_Dialog_View, 1);
v->create_cfdata = _create_data;
v->free_cfdata = _free_data;
v->basic.apply_cfdata = _basic_apply_data;
v->basic.create_widgets = _basic_create_widgets;
cfd = e_config_dialog_new(con, _("Physics Settings"),
"E", "appearance/physics", buf, 0, v, mod);
mod->config_dialog = cfd;
return cfd;
}
static void *
_create_data(E_Config_Dialog *cfd __UNUSED__)
{
E_Config_Dialog_Data *cfdata;
cfdata = E_NEW(E_Config_Dialog_Data, 1);
cfdata->delay = _physics_mod->conf->delay;
cfdata->max_mass = _physics_mod->conf->max_mass;
return cfdata;
}
static void
_free_data(E_Config_Dialog *cfd __UNUSED__,
E_Config_Dialog_Data *cfdata)
{
_physics_mod->config_dialog = NULL;
free(cfdata);
}
static Evas_Object *
_basic_create_widgets(E_Config_Dialog *cfd,
Evas *evas,
E_Config_Dialog_Data *cfdata)
{
Evas_Object *ob, *ol, *otb, *tab;
tab = e_widget_table_add(evas, 0);
evas_object_name_set(tab, "dia_table");
otb = e_widget_toolbook_add(evas, 48 * e_scale, 48 * e_scale);
///////////////////////////////////////////
ol = e_widget_list_add(evas, 0, 0);
ob = e_widget_label_add(evas, _("Physics delay after drag"));
e_widget_list_object_append(ol, ob, 1, 1, 0.5);
ob = e_widget_slider_add(evas, 1, 0, _("%2.0f Frames"), 5, 20, 1, 0, &(cfdata->delay), NULL, 150);
e_widget_list_object_append(ol, ob, 1, 1, 0.5);
ob = e_widget_label_add(evas, _("Maximum window mass"));
e_widget_list_object_append(ol, ob, 1, 1, 0.5);
ob = e_widget_slider_add(evas, 1, 0, _("%2.1f Kg"), 1, 6, 1, 0, &(cfdata->max_mass), NULL, 150);
e_widget_list_object_append(ol, ob, 1, 1, 0.5);
ob = e_widget_label_add(evas, _("Desktop gravity"));
e_widget_list_object_append(ol, ob, 1, 1, 0.5);
ob = e_widget_slider_add(evas, 1, 0, _("%1.1f m/s^2"), -5, 5, 1, 0, &(cfdata->gravity), NULL, 150);
e_widget_list_object_append(ol, ob, 1, 1, 0.5);
e_widget_toolbook_page_append(otb, NULL, _("General"), ol, 1, 1, 1, 1, 0.5, 0.5);
///////////////////////////////////////////
ol = e_widget_list_add(evas, 0, 0);
ob = e_widget_check_add(evas, _("Ignore Fullscreen"), (int*)&(cfdata->ignore_fullscreen));
e_widget_list_object_append(ol, ob, 1, 0, 0.5);
ob = e_widget_check_add(evas, _("Ignore Maximized"), (int*)&(cfdata->ignore_maximized));
e_widget_list_object_append(ol, ob, 1, 0, 0.5);
e_widget_toolbook_page_append(otb, NULL, _("Ignore"), ol, 1, 1, 1, 1, 0.5, 0.5);
e_widget_toolbook_page_show(otb, 0);
e_dialog_resizable_set(cfd->dia, 1);
e_widget_table_object_append(tab, otb, 0, 0, 1, 1, 1, 1, 1, 1);
return tab;
}
static int
_basic_apply_data(E_Config_Dialog *cfd __UNUSED__,
E_Config_Dialog_Data *cfdata)
{
if ((cfdata->delay != _physics_mod->conf->delay) ||
(cfdata->max_mass != _physics_mod->conf->max_mass) ||
(cfdata->ignore_fullscreen != _physics_mod->conf->ignore_fullscreen) ||
(cfdata->ignore_maximized != _physics_mod->conf->ignore_maximized) ||
(cfdata->gravity != _physics_mod->conf->gravity)
)
{
#define SET(X) _physics_mod->conf->X = cfdata->X
_physics_mod->conf->delay = (unsigned int)cfdata->delay;
SET(max_mass);
SET(ignore_fullscreen);
SET(ignore_maximized);
SET(gravity);
e_mod_physics_shutdown();
e_mod_physics_init();
}
e_config_save_queue();
return 1;
}

View File

@ -0,0 +1,8 @@
#ifdef E_TYPEDEFS
#else
#ifndef E_MOD_CONFIG_H
#define E_MOD_CONFIG_H
E_Config_Dialog *e_int_config_physics_module(E_Container *con,
const char *params __UNUSED__);
#endif
#endif

View File

@ -0,0 +1,101 @@
#include "e.h"
#include "e_mod_main.h"
#include "e_mod_physics.h"
#include "e_mod_config.h"
#include <EPhysics.h>
/* module private routines */
Mod *_physics_mod = NULL;
/* public module routines. all modules must have these */
EAPI E_Module_Api e_modapi =
{
E_MODULE_API_VERSION,
"Physics"
};
EAPI void *
e_modapi_init(E_Module *m)
{
Mod *mod;
char buf[4096];
if (!ephysics_init()) return NULL;
mod = calloc(1, sizeof(Mod));
m->data = mod;
mod->module = m;
snprintf(buf, sizeof(buf), "%s/e-module-physics.edj", e_module_dir_get(m));
e_configure_registry_category_add("appearance", 10, _("Look"), NULL,
"preferences-look");
e_configure_registry_item_add("appearance/physics", 120, _("Physics"), NULL,
buf, e_int_config_physics_module);
mod->conf_edd = e_mod_physics_cfdata_edd_init();
mod->conf = e_config_domain_load("module.physics", mod->conf_edd);
if (!mod->conf) _e_mod_config_new(m);
_physics_mod = mod;
if (!e_mod_physics_init())
{
e_util_dialog_internal(_("Physics Error"), _("The physics module could not be started"));
e_modapi_shutdown(mod->module);
return NULL;
}
e_module_delayed_set(m, 0);
e_module_priority_set(m, -1000);
return mod;
}
void
_e_mod_config_new(E_Module *m)
{
Mod *mod = m->data;
mod->conf = e_mod_physics_cfdata_config_new();
}
void
_e_mod_config_free(E_Module *m)
{
Mod *mod = m->data;
e_mod_cfdata_config_free(mod->conf);
mod->conf = NULL;
}
EAPI int
e_modapi_shutdown(E_Module *m)
{
Mod *mod = m->data;
e_mod_physics_shutdown();
e_configure_registry_item_del("appearance/physics");
e_configure_registry_category_del("appearance");
if (mod->config_dialog)
{
e_object_del(E_OBJECT(mod->config_dialog));
mod->config_dialog = NULL;
}
_e_mod_config_free(m);
E_CONFIG_DD_FREE(mod->conf_edd);
free(mod);
if (mod == _physics_mod) _physics_mod = NULL;
return 1;
}
EAPI int
e_modapi_save(E_Module *m)
{
Mod *mod = m->data;
e_config_domain_save("module.physics", mod->conf_edd, mod->conf);
return 1;
}

View File

@ -0,0 +1,31 @@
#ifndef E_MOD_MAIN_H
#define E_MOD_MAIN_H
#include "e_mod_physics_cfdata.h"
typedef struct _Mod Mod;
struct _Mod
{
E_Module *module;
E_Config_DD *conf_edd;
E_Config_DD *conf_match_edd;
Config *conf;
E_Config_Dialog *config_dialog;
};
extern Mod *_physics_mod;
EAPI extern E_Module_Api e_modapi;
EAPI void *e_modapi_init(E_Module *m);
EAPI int e_modapi_shutdown(E_Module *m);
EAPI int e_modapi_save(E_Module *m);
EAPI int e_modapi_info(E_Module *m);
void _e_mod_config_new(E_Module *m);
void _e_mod_config_free(E_Module *m);
#endif

View File

@ -0,0 +1,815 @@
#include "e.h"
#include "e_mod_main.h"
#include "e_mod_physics.h"
#include <EPhysics.h>
struct _E_Physics
{
EPhysics_World *world;
Ecore_X_Window win;
E_Manager *man;
Eina_Inlist *wins;
};
struct _E_Physics_Win
{
EINA_INLIST;
E_Physics *p; // parent compositor
Ecore_X_Window win; // raw window - for menus etc.
E_Border *bd; // if its a border - later
E_Popup *pop; // if its a popup - later
E_Menu *menu; // if it is a menu - later
EPhysics_Body *body; // physics body
int x, y, w, h; // geometry
int ix, iy; // impulse geometry (next move coord */
struct
{
int x, y, w, h; // hidden geometry (used when its unmapped and re-instated on map)
} hidden;
int border; // border width
E_Object_Delfn *dfn; // delete function handle for objects being tracked
E_Border_Hook *begin; // begin move
E_Border_Hook *end; // end move
E_Maximize maximize;
unsigned int stopped; /* number of frames window has been stopped for */
unsigned int started; /* number of frames window has been moving for */
double impulse_x, impulse_y; /* x,y for impulse vector */
Eina_Bool visible : 1; // is visible
Eina_Bool inhash : 1; // is in the windows hash
Eina_Bool show_ready : 1; // is this window ready for its first show
Eina_Bool moving : 1;
Eina_Bool impulse : 1;
};
static Eina_List *handlers = NULL;
static Eina_List *physicists = NULL;
static Eina_Hash *borders = NULL;
//////////////////////////////////////////////////////////////////////////
#undef DBG
#if 1
#define DBG(f, x ...) printf(f, ##x)
#else
#define DBG(f, x ...)
#endif
static Eina_Bool _e_mod_physics_bd_fullscreen(void *data __UNUSED__, int type, void *event);
static void _e_mod_physics_bd_move_intercept_cb(E_Border *bd, int x, int y);
static void _e_mod_physics_win_update_cb(E_Physics_Win *pw, EPhysics_Body *body, void *event_info __UNUSED__);
static void _e_mod_physics_win_del(E_Physics_Win *pw);
static void _e_mod_physics_win_show(E_Physics_Win *pw);
static void _e_mod_physics_win_hide(E_Physics_Win *pw);
static void _e_mod_physics_win_configure(E_Physics_Win *pw,
int x,
int y,
int w,
int h,
int border);
/* TODO
static void
_e_mod_physics_fps_update(E_Physics *p)
{
if (_comp_mod->conf->fps_show)
{
if (!p->fps_bg)
{
p->fps_bg = evas_object_rectangle_add(p->evas);
evas_object_color_set(p->fps_bg, 0, 0, 0, 128);
evas_object_layer_set(p->fps_bg, EVAS_LAYER_MAX);
evas_object_show(p->fps_bg);
p->fps_fg = evas_object_text_add(p->evas);
evas_object_text_font_set(p->fps_fg, "Sans", 10);
evas_object_text_text_set(p->fps_fg, "???");
evas_object_color_set(p->fps_fg, 255, 255, 255, 255);
evas_object_layer_set(p->fps_fg, EVAS_LAYER_MAX);
evas_object_show(p->fps_fg);
}
}
else
{
if (p->fps_fg)
{
evas_object_del(p->fps_fg);
p->fps_fg = NULL;
}
if (p->fps_bg)
{
evas_object_del(p->fps_bg);
p->fps_bg = NULL;
}
}
}
*/
static void
_e_mod_physics_move_end(void *p_w, void *b_d)
{
E_Physics_Win *pw = p_w;
/* wrong border */
if (b_d != pw->bd) return;
DBG("PHYS: DRAG END %d\n", pw->win);
pw->impulse = pw->moving = EINA_FALSE;
}
static void
_e_mod_physics_move_begin(void *p_w, void *b_d)
{
E_Physics_Win *pw = p_w;
/* wrong border */
if (b_d != pw->bd) return;
DBG("PHYS: DRAG BEGIN %d\n", pw->win);
pw->moving = EINA_TRUE;
pw->started = 0;
/* hacks! */
if ((!pw->impulse_x) && (!pw->impulse_y)) return;
_e_mod_physics_win_hide(pw);
_e_mod_physics_win_show(pw);
pw->show_ready = 0;
_e_mod_physics_win_configure(pw, pw->bd->x, pw->bd->y, pw->bd->w, pw->bd->h, pw->border);
pw->impulse_x = pw->impulse_y = 0;
}
static E_Physics *
_e_mod_physics_find(Ecore_X_Window root)
{
Eina_List *l;
E_Physics *p;
// fixme: use hash if physicists list > 4
EINA_LIST_FOREACH (physicists, l, p)
{
if (p->man->root == root) return p;
}
return NULL;
}
static E_Physics_Win *
_e_mod_physics_win_find(Ecore_X_Window win)
{
return eina_hash_find(borders, e_util_winid_str_get(win));
}
static void
_e_mod_physics_win_show(E_Physics_Win *pw)
{
if (pw->visible) return;
DBG("PHYS: SHOW %d\n", pw->win);
pw->visible = 1;
pw->body = ephysics_body_box_add(pw->p->world);
ephysics_body_friction_set(pw->body, 1.0);
ephysics_body_rotation_on_z_axis_enable_set(pw->body, EINA_FALSE);
ephysics_body_event_callback_add(pw->body, EPHYSICS_CALLBACK_BODY_UPDATE, (EPhysics_Body_Event_Cb)_e_mod_physics_win_update_cb, pw);
pw->begin = e_border_hook_add(E_BORDER_HOOK_MOVE_BEGIN, _e_mod_physics_move_begin, pw);
pw->end = e_border_hook_add(E_BORDER_HOOK_MOVE_END, _e_mod_physics_move_end, pw);
e_border_move_intercept_cb_set(pw->bd, _e_mod_physics_bd_move_intercept_cb);
}
static void
_e_mod_physics_bd_move_intercept_cb(E_Border *bd, int x, int y)
{
E_Physics_Win *pw;
pw = _e_mod_physics_win_find(bd->client.win);
if ((bd->x == x) && (bd->y == y))
{
DBG("PHYS: STOPPED %d\n", pw->win);
if (pw->moving) pw->started = 0;
pw->show_ready = 0;
_e_mod_physics_win_configure(pw, x, y, pw->bd->w, pw->bd->h, pw->border);
return;
}
if (!pw) return;
DBG("PHYS: MOVE %d - (%d,%d) ->(WANT) (%d,%d)\n", pw->win, bd->x, bd->y, x, y);
if ((!pw->body) || (!pw->moving) || (pw->started < _physics_mod->conf->delay))
{
DBG("PHYS: MOVE THROUGH\n");
bd->x = x, bd->y = y;
if (pw->moving) pw->started++;
pw->show_ready = 0;
_e_mod_physics_win_configure(pw, x, y, pw->bd->w, pw->bd->h, pw->border);
return;
}
if (!pw->impulse)
{
DBG("PHYS: IMPULSE APPLY\n");
pw->impulse_x = (x - bd->x) * 5;
pw->impulse_y = (bd->y - y) * 5;
ephysics_body_central_impulse_apply(pw->body, pw->impulse_x, pw->impulse_y);
bd->x = x, bd->y = y;
pw->impulse = EINA_TRUE;
return;
}
if ((pw->ix == x) && (pw->iy == y))
bd->x = x, bd->y = y;
else
{
if (E_INSIDE(bd->x, bd->y, pw->p->man->x, pw->p->man->y, pw->p->man->w, pw->p->man->h) &&
E_INSIDE(bd->x + bd->w, bd->y, pw->p->man->x, pw->p->man->y, pw->p->man->w, pw->p->man->h) &&
E_INSIDE(bd->x, bd->y + bd->h, pw->p->man->x, pw->p->man->y, pw->p->man->w, pw->p->man->h) &&
E_INSIDE(bd->x + bd->w, bd->y + bd->h, pw->p->man->x, pw->p->man->y, pw->p->man->w, pw->p->man->h))
DBG("REJECTED!\n");
else if (pw->moving)
{
DBG("UPDATE\n");
bd->x = x, bd->y = y;
pw->show_ready = 0;
_e_mod_physics_win_configure(pw, x, y, pw->bd->w, pw->bd->h, pw->border);
}
}
}
static E_Physics_Win *
_e_mod_physics_win_add(E_Physics *p, E_Border *bd)
{
Ecore_X_Window_Attributes att;
E_Physics_Win *pw;
memset((&att), 0, sizeof(Ecore_X_Window_Attributes));
if (!ecore_x_window_attributes_get(bd->client.win, &att))
return NULL;
/* don't physics on input grab windows or tooltips */
if (att.input_only || att.override) return NULL;
pw = calloc(1, sizeof(E_Physics_Win));
if (!pw) return NULL;
pw->win = bd->client.win;
pw->p = p;
pw->bd = bd;
eina_hash_add(borders, e_util_winid_str_get(pw->bd->client.win), pw);
if (pw->bd->visible)
_e_mod_physics_win_show(pw);
DBG("PHYS: WIN %d ADD\n", bd->client.win);
p->wins = eina_inlist_append(p->wins, EINA_INLIST_GET(pw));
return pw;
}
static void
_e_mod_physics_win_del(E_Physics_Win *pw)
{
if (pw->dfn)
{
eina_hash_del(borders, e_util_winid_str_get(pw->bd->client.win), pw);
e_object_delfn_del(E_OBJECT(pw->bd), pw->dfn);
pw->bd = NULL;
pw->dfn = NULL;
}
e_border_move_intercept_cb_set(pw->bd, NULL);
pw->p->wins = eina_inlist_remove(pw->p->wins, EINA_INLIST_GET(pw));
if (pw->body) ephysics_body_del(pw->body);
memset(pw, 0, sizeof(E_Physics_Win));
free(pw);
}
static void
_e_mod_physics_win_hide(E_Physics_Win *pw)
{
if (!pw->visible) return;
DBG("PHYS: HIDE %d\n", pw->win);
pw->show_ready = pw->visible = 0;
ephysics_body_del(pw->body);
pw->body = NULL;
e_border_hook_del(pw->begin);
e_border_hook_del(pw->end);
pw->begin = pw->end = NULL;
e_border_move_intercept_cb_set(pw->bd, NULL);
}
#if 0
static void
_e_mod_physics_win_raise_above(E_Physics_Win *pw,
E_Physics_Win *cw2)
{
DBG(" [0x%x] abv [0x%x]\n", pw->win, cw2->win);
pw->p->wins_invalid = 1;
pw->p->wins = eina_inlist_remove(pw->p->wins, EINA_INLIST_GET(pw));
pw->p->wins = eina_inlist_append_relative(pw->p->wins,
EINA_INLIST_GET(pw),
EINA_INLIST_GET(cw2));
evas_object_stack_above(pw->shobj, cw2->shobj);
if (pw->bd)
{
Eina_List *l;
E_Border *tmp;
EINA_LIST_FOREACH (pw->bd->client.e.state.video_child, l, tmp)
{
E_Physics_Win *tcw;
tcw = eina_hash_find(borders, e_util_winid_str_get(tmp->client.win));
if (!tcw) continue;
evas_object_stack_below(tcw->shobj, pw->shobj);
}
}
_e_mod_physics_win_render_queue(pw);
pw->pending_count++;
e_manager_comp_event_src_config_send
(pw->p->man, (E_Manager_Comp_Source *)pw,
_e_mod_physics_cb_pending_after, pw->p);
}
static void
_e_mod_physics_win_raise(E_Physics_Win *pw)
{
DBG(" [0x%x] rai\n", pw->win);
pw->p->wins_invalid = 1;
pw->p->wins = eina_inlist_remove(pw->p->wins, EINA_INLIST_GET(pw));
pw->p->wins = eina_inlist_append(pw->p->wins, EINA_INLIST_GET(pw));
evas_object_raise(pw->shobj);
if (pw->bd)
{
Eina_List *l;
E_Border *tmp;
EINA_LIST_FOREACH (pw->bd->client.e.state.video_child, l, tmp)
{
E_Physics_Win *tcw;
tcw = eina_hash_find(borders, e_util_winid_str_get(tmp->client.win));
if (!tcw) continue;
evas_object_stack_below(tcw->shobj, pw->shobj);
}
}
_e_mod_physics_win_render_queue(pw);
pw->pending_count++;
e_manager_comp_event_src_config_send
(pw->p->man, (E_Manager_Comp_Source *)pw,
_e_mod_physics_cb_pending_after, pw->p);
}
static void
_e_mod_physics_win_lower(E_Physics_Win *pw)
{
DBG(" [0x%x] low\n", pw->win);
pw->p->wins_invalid = 1;
pw->p->wins = eina_inlist_remove(pw->p->wins, EINA_INLIST_GET(pw));
pw->p->wins = eina_inlist_prepend(pw->p->wins, EINA_INLIST_GET(pw));
evas_object_lower(pw->shobj);
if (pw->bd)
{
Eina_List *l;
E_Border *tmp;
EINA_LIST_FOREACH (pw->bd->client.e.state.video_child, l, tmp)
{
E_Physics_Win *tcw;
tcw = eina_hash_find(borders, e_util_winid_str_get(tmp->client.win));
if (!tcw) continue;
evas_object_stack_below(tcw->shobj, pw->shobj);
}
}
_e_mod_physics_win_render_queue(pw);
pw->pending_count++;
e_manager_comp_event_src_config_send
(pw->p->man, (E_Manager_Comp_Source *)pw,
_e_mod_physics_cb_pending_after, pw->p);
}
#endif
static void
_e_mod_physics_win_mass_set(E_Physics_Win *pw)
{
double mass;
mass = _physics_mod->conf->max_mass * (((double)pw->w / (double)pw->p->man->w) + ((double)pw->h / (double)pw->p->man->h) / 2.);
DBG("PHYS: WIN %d MASS %g\n", pw->win, mass);
ephysics_body_mass_set(pw->body, mass);
}
static void
_e_mod_physics_win_configure(E_Physics_Win *pw,
int x,
int y,
int w,
int h,
int border)
{
//DBG("PHYS: CONFIG %d\n", pw->win);
if (!pw->visible)
{
pw->hidden.x = x;
pw->hidden.y = y;
pw->border = border;
}
else
{
if (!((x == pw->x) && (y == pw->y)))
{
pw->x = x;
pw->y = y;
}
pw->hidden.x = x;
pw->hidden.y = y;
}
pw->maximize = pw->bd->maximized;
pw->hidden.w = w;
pw->hidden.h = h;
if (!((w == pw->w) && (h == pw->h)))
{
pw->w = w;
pw->h = h;
}
if (pw->border != border)
{
pw->border = border;
}
if ((!pw->show_ready) && pw->body)
{
_e_mod_physics_win_mass_set(pw);
ephysics_body_geometry_set(pw->body, x, y, w, border + h);
pw->show_ready = 1;
}
}
//////////////////////////////////////////////////////////////////////////
static Eina_Bool
_e_mod_physics_bd_property(void *data __UNUSED__, int type __UNUSED__, void *event)
{
E_Event_Border_Property *ev = event;
E_Physics_Win *pw = _e_mod_physics_win_find(ev->border->client.win);
if (pw->maximize == ev->border->maximized) return ECORE_CALLBACK_PASS_ON;
if (ev->border->maximized)
_e_mod_physics_win_del(pw);
else
{
E_Physics *p = _e_mod_physics_find(ev->border->zone->container->manager->root);
pw = _e_mod_physics_win_add(p, ev->border);
if (!pw) return ECORE_CALLBACK_PASS_ON;
_e_mod_physics_win_configure(pw, pw->bd->x, pw->bd->y,
pw->bd->w, pw->bd->h,
ecore_x_window_border_width_get(pw->bd->client.win));
}
out:
pw->maximize = ev->border->maximized;
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_mod_physics_bd_fullscreen(void *data __UNUSED__, int type, void *event)
{
E_Event_Border_Fullscreen *ev = event;
E_Physics_Win *pw = _e_mod_physics_win_find(ev->border->client.win);
if (type == E_EVENT_BORDER_FULLSCREEN)
{
if (pw)
_e_mod_physics_win_del(pw);
}
else
{
E_Physics *p = _e_mod_physics_find(ev->border->zone->container->manager->root);
if (!pw)
{
pw = _e_mod_physics_win_add(p, ev->border);
if (!pw) return ECORE_CALLBACK_PASS_ON;
_e_mod_physics_win_configure(pw, pw->bd->x, pw->bd->y,
pw->bd->w, pw->bd->h,
ecore_x_window_border_width_get(pw->bd->client.win));
}
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_mod_physics_bd_add(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
E_Event_Border_Add *ev = event;
DBG("PHYS: NEW %d\n", ev->border->client.win);
E_Physics *p = _e_mod_physics_find(ev->border->zone->container->manager->root);
E_Physics_Win *pw = _e_mod_physics_win_find(ev->border->client.win);
if (pw) return ECORE_CALLBACK_PASS_ON;
pw = _e_mod_physics_win_add(p, ev->border);
if (pw) _e_mod_physics_win_configure(pw, ev->border->x, ev->border->y, ev->border->w, ev->border->h,
ecore_x_window_border_width_get(ev->border->client.win));
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_mod_physics_bd_del(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
E_Event_Border_Add *ev = event;
DBG("PHYS: DEL %d\n", ev->border->client.win);
E_Physics_Win *pw = _e_mod_physics_win_find(ev->border->client.win);
if (!pw) return ECORE_CALLBACK_PASS_ON;
_e_mod_physics_win_del(pw);
return ECORE_CALLBACK_PASS_ON;
}
/*
static Eina_Bool
_e_mod_physics_reparent(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
Ecore_X_Event_Window_Reparent *ev = event;
E_Physics_Win *pw = _e_mod_physics_win_find(ev->win);
if (!pw) return ECORE_CALLBACK_PASS_ON;
if (ev->parent != pw->p->man->root)
_e_mod_physics_win_del(pw);
return ECORE_CALLBACK_PASS_ON;
}
*/
static Eina_Bool
_e_mod_physics_configure(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
Ecore_X_Event_Window_Configure *ev = event;
E_Physics_Win *pw = _e_mod_physics_win_find(ev->win);
if (!pw) return ECORE_CALLBACK_PASS_ON;
/* TODO: stacking
if (ev->abovewin == 0)
{
if (EINA_INLIST_GET(pw)->prev) _e_mod_physics_win_lower(pw);
}
else
{
E_Physics_Win *cw2 = _e_mod_physics_win_find(ev->abovewin);
if (cw2)
{
E_Physics_Win *cw3 = (E_Physics_Win *)(EINA_INLIST_GET(pw)->prev);
if (cw3 != cw2) _e_mod_physics_win_raise_above(pw, cw2);
}
}
*/
if (!((pw->x == ev->x) && (pw->y == ev->y) &&
(pw->w == ev->w) && (pw->h == ev->h) &&
(pw->border == ev->border)))
{
_e_mod_physics_win_configure(pw, ev->x, ev->y, ev->w, ev->h, ev->border);
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_mod_physics_stack(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
Ecore_X_Event_Window_Stack *ev = event;
E_Physics_Win *pw = _e_mod_physics_win_find(ev->win);
if (!pw) return ECORE_CALLBACK_PASS_ON;
/* TODO
if (ev->detail == ECORE_X_WINDOW_STACK_ABOVE) _e_mod_physics_win_raise(pw);
else _e_mod_physics_win_lower(pw);
*/
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_mod_physics_randr(void *data __UNUSED__,
int type __UNUSED__,
__UNUSED__ void *event __UNUSED__)
{
Eina_List *l;
E_Physics *p;
EINA_LIST_FOREACH(physicists, l, p)
ephysics_world_render_geometry_set(p->world, 0, 0, p->man->w, p->man->h);
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_mod_physics_bd_resize(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
E_Event_Border_Move *ev = event;
E_Physics_Win *pw = _e_mod_physics_win_find(ev->border->client.win);
if (!pw) return ECORE_CALLBACK_PASS_ON;
if (!pw->visible) return ECORE_CALLBACK_PASS_ON;
pw->show_ready = 0;
_e_mod_physics_win_configure(pw, pw->x, pw->y, ev->border->w, ev->border->h, pw->border);
pw->show_ready = 1;
return ECORE_CALLBACK_PASS_ON;
}
/*
static Eina_Bool
_e_mod_physics_bd_move(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
E_Event_Border_Move *ev = event;
E_Physics_Win *pw = _e_mod_physics_win_find(ev->border->client.win);
if (!pw) return ECORE_CALLBACK_PASS_ON;
if (!pw->visible) return ECORE_CALLBACK_PASS_ON;
_e_mod_physics_win_configure(pw, pw->x, pw->y, ev->border->w, ev->border->h, pw->border);
return ECORE_CALLBACK_PASS_ON;
}
*/
static Eina_Bool
_e_mod_physics_bd_show(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
E_Event_Border_Hide *ev = event;
E_Physics_Win *pw = _e_mod_physics_win_find(ev->border->client.win);
if (!pw) return ECORE_CALLBACK_PASS_ON;
_e_mod_physics_win_show(pw);
_e_mod_physics_win_configure(pw, pw->bd->x, pw->bd->y, pw->bd->w, pw->bd->h, pw->border);
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_mod_physics_bd_hide(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
E_Event_Border_Hide *ev = event;
E_Physics_Win *pw = _e_mod_physics_win_find(ev->border->client.win);
if (!pw) return ECORE_CALLBACK_PASS_ON;
_e_mod_physics_win_hide(pw);
return ECORE_CALLBACK_PASS_ON;
}
#if 0
static Eina_Bool
_e_mod_physics_bd_iconify(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
E_Event_Border_Iconify *ev = event;
E_Physics_Win *pw = _e_mod_physics_win_find(ev->border->client.win);
if (!pw) return ECORE_CALLBACK_PASS_ON;
// fimxe: special iconfiy anim
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_mod_physics_bd_uniconify(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
E_Event_Border_Uniconify *ev = event;
E_Physics_Win *pw = _e_mod_physics_win_find(ev->border->client.win);
if (!pw) return ECORE_CALLBACK_PASS_ON;
// fimxe: special uniconfiy anim
return ECORE_CALLBACK_PASS_ON;
}
#endif
static E_Physics *
_e_mod_physics_add(E_Manager *man)
{
E_Physics *p;
EPhysics_Body *bound;
Eina_List *l;
E_Border *bd;
p = calloc(1, sizeof(E_Physics));
if (!p) return NULL;
p->man = man;
p->world = ephysics_world_new();
/* TODO: world per zone */
DBG("PHYS: world++ || %dx%d\n", man->w, man->h);
ephysics_world_render_geometry_set(p->world, 0, 0, man->w, man->h);
ephysics_world_gravity_set(p->world, 0, _physics_mod->conf->gravity);
bound = ephysics_body_left_boundary_add(p->world);
ephysics_body_restitution_set(bound, 1);
ephysics_body_friction_set(bound, 3);
bound = ephysics_body_right_boundary_add(p->world);
ephysics_body_restitution_set(bound, 1);
ephysics_body_friction_set(bound, 3);
bound = ephysics_body_top_boundary_add(p->world);
ephysics_body_restitution_set(bound, 1);
ephysics_body_friction_set(bound, 3);
bound = ephysics_body_bottom_boundary_add(p->world);
ephysics_body_restitution_set(bound, 1);
ephysics_body_friction_set(bound, 3);
EINA_LIST_FOREACH(e_border_client_list(), l, bd)
{
E_Physics_Win *pw;
int border;
pw = _e_mod_physics_win_add(p, bd);
if (!pw) continue;
border = ecore_x_window_border_width_get(bd->client.win);
_e_mod_physics_win_configure(pw, bd->x, bd->y, bd->w, bd->h, border);
}
return p;
}
static void
_e_mod_physics_del(E_Physics *p)
{
E_Physics_Win *pw;
while (p->wins)
{
pw = (E_Physics_Win *)(p->wins);
_e_mod_physics_win_del(pw);
}
free(p);
}
static void
_e_mod_physics_win_update_cb(E_Physics_Win *pw, EPhysics_Body *body, void *event_info __UNUSED__)
{
//DBG("PHYS: TICKER %d\n", pw->win);
if (pw->moving && (pw->started < _physics_mod->conf->delay))
{
pw->show_ready = 0;
_e_mod_physics_win_configure(pw, pw->x, pw->y, pw->w, pw->h, pw->border);
return;
}
ephysics_body_geometry_get(body, &pw->ix, &pw->iy, NULL, NULL);
e_border_move(pw->bd, pw->ix, pw->iy);
}
//////////////////////////////////////////////////////////////////////////
void
e_mod_physics_mass_update(void)
{
Eina_List *l;
E_Physics *p;
E_Physics_Win *pw;
EINA_LIST_FOREACH(physicists, l, p)
EINA_INLIST_FOREACH(p->wins, pw)
_e_mod_physics_win_mass_set(pw);
}
Eina_Bool
e_mod_physics_init(void)
{
Eina_List *l;
E_Manager *man;
borders = eina_hash_string_superfast_new(NULL);
// handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_REPARENT, _e_mod_physics_reparent, NULL));
handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE, _e_mod_physics_configure, NULL));
//handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_STACK, _e_mod_physics_stack, NULL));
if (_physics_mod->conf->ignore_maximized)
handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_PROPERTY, _e_mod_physics_bd_property, NULL));
if (_physics_mod->conf->ignore_fullscreen)
{
handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_FULLSCREEN, _e_mod_physics_bd_fullscreen, NULL));
handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_UNFULLSCREEN, _e_mod_physics_bd_fullscreen, NULL));
}
handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_CONTAINER_RESIZE, _e_mod_physics_randr, NULL));
handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_ADD, _e_mod_physics_bd_add, NULL));
handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_REMOVE, _e_mod_physics_bd_del, NULL));
handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_SHOW, _e_mod_physics_bd_show, NULL));
handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_HIDE, _e_mod_physics_bd_hide, NULL));
// handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_MOVE, _e_mod_physics_bd_move, NULL));
handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_RESIZE, _e_mod_physics_bd_resize, NULL));
#if 0
handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_ICONIFY, _e_mod_physics_bd_iconify, NULL));
handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_UNICONIFY, _e_mod_physics_bd_uniconify, NULL));
#endif
EINA_LIST_FOREACH (e_manager_list(), l, man)
{
E_Physics *p;
p = _e_mod_physics_add(man);
if (p) physicists = eina_list_append(physicists, p);
}
ecore_x_sync();
return 1;
}
void
e_mod_physics_shutdown(void)
{
E_Physics *p;
EINA_LIST_FREE (physicists, p)
_e_mod_physics_del(p);
E_FREE_LIST(handlers, ecore_event_handler_del);
if (borders) eina_hash_free(borders);
borders = NULL;
}

View File

@ -0,0 +1,14 @@
#ifdef E_TYPEDEFS
#else
#ifndef E_MOD_PHYSICS_H
#define E_MOD_PHYSICS_H
typedef struct _E_Physics E_Physics;
typedef struct _E_Physics_Win E_Physics_Win;
void e_mod_physics_mass_update(void);
Eina_Bool e_mod_physics_init(void);
void e_mod_physics_shutdown(void);
#endif
#endif

View File

@ -0,0 +1,43 @@
#include "e.h"
#include "e_mod_main.h"
#include "e_mod_physics_cfdata.h"
EAPI E_Config_DD *
e_mod_physics_cfdata_edd_init(void)
{
E_Config_DD *conf_edd;
conf_edd = E_CONFIG_DD_NEW("Physics_Config", Config);
#undef T
#undef D
#define T Config
#define D conf_edd
E_CONFIG_VAL(D, T, delay, UINT);
E_CONFIG_VAL(D, T, max_mass, DOUBLE);
E_CONFIG_VAL(D, T, gravity, DOUBLE);
E_CONFIG_VAL(D, T, ignore_fullscreen, UCHAR);
E_CONFIG_VAL(D, T, ignore_maximized, UCHAR);
return conf_edd;
}
EAPI Config *
e_mod_physics_cfdata_config_new(void)
{
Config *cfg;
cfg = E_NEW(Config, 1);
cfg->delay = 10;
cfg->max_mass = 3.0;
cfg->gravity = 0.0;
cfg->ignore_fullscreen = EINA_TRUE;
cfg->ignore_maximized = EINA_TRUE;
return cfg;
}
EAPI void
e_mod_cfdata_config_free(Config *cfg)
{
free(cfg);
}

View File

@ -0,0 +1,19 @@
#ifndef E_MOD_PHYSICS_CFDATA_H
#define E_MOD_PHYSICS_CFDATA_H
typedef struct _Config Config;
struct _Config
{
unsigned int delay; /* delay before applying physics */
double max_mass; /* maximum mass for a window */
double gravity; /* maximum mass for a window */
Eina_Bool ignore_fullscreen;
Eina_Bool ignore_maximized;
};
EAPI E_Config_DD *e_mod_physics_cfdata_edd_init(void);
EAPI Config *e_mod_physics_cfdata_config_new(void);
EAPI void e_mod_cfdata_config_free(Config *cfg);
#endif

View File

@ -0,0 +1,6 @@
[Desktop Entry]
Type=Link
Name=Physics
Icon=e-module-physics
Comment=Enlightenment Physics Professor
X-Enlightenment-ModuleType=look