From 47283e55188a7470138b3a96eb640bea5571b5e2 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Thu, 25 Apr 2013 11:21:22 +0100 Subject: [PATCH] add deskmirror, a new widget which breaks evas in a number of terrifying ways to experience the terror, uncomment the define in e_deskmirror.h --- ChangeLog | 4 + NEWS | 1 + data/themes/Makefile.am | 1 + data/themes/default.edc | 1 + data/themes/edc/deskmirror.edc | 406 +++++++++++++++++++++ src/bin/Makefile.am | 2 + src/bin/e_deskmirror.c | 627 +++++++++++++++++++++++++++++++++ src/bin/e_deskmirror.h | 8 + src/bin/e_includes.h | 1 + src/bin/e_int_border_menu.c | 24 +- src/bin/e_test.c | 23 ++ 11 files changed, 1092 insertions(+), 6 deletions(-) create mode 100644 data/themes/edc/deskmirror.edc create mode 100644 src/bin/e_deskmirror.c create mode 100644 src/bin/e_deskmirror.h diff --git a/ChangeLog b/ChangeLog index a93d47af4..bc6af85b0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2013-04-25 Mike Blumenkrantz + + * added deskmirror + 2013-04-19 Mike Blumenkrantz * deskpreview renamed to bgpreview diff --git a/NEWS b/NEWS index 548fb0be8..fa5104040 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,7 @@ Additions: * added e_object_ref_debug_set * added e_gadcon_repopulate * added e_comp_win_effect* api + * added deskmirror Config: * Added option for disabling icons in menus * Added option for disabling pointer warping when performing directional focus changes using winlist diff --git a/data/themes/Makefile.am b/data/themes/Makefile.am index 0be183e8d..8018c6762 100644 --- a/data/themes/Makefile.am +++ b/data/themes/Makefile.am @@ -37,6 +37,7 @@ edc/connman.edc \ edc/cpufreq.edc \ edc/cslider.edc \ edc/desklock.edc \ +edc/deskmirror.edc \ edc/deskpreview.edc \ edc/dialog.edc \ edc/edgebindings.edc \ diff --git a/data/themes/default.edc b/data/themes/default.edc index c90f99b77..39c566ba5 100644 --- a/data/themes/default.edc +++ b/data/themes/default.edc @@ -4,6 +4,7 @@ collections { #include "colorclasses.edc" // desktop in general #include "edc/comp.edc" +#include "edc/deskmirror.edc" #include "edc/background.edc" #include "edc/shelf.edc" #include "edc/border.edc" diff --git a/data/themes/edc/deskmirror.edc b/data/themes/edc/deskmirror.edc new file mode 100644 index 000000000..e79de0373 --- /dev/null +++ b/data/themes/edc/deskmirror.edc @@ -0,0 +1,406 @@ +group { name: "e/deskmirror/frame/default"; + alias: "e/deskmirror/frame/dialog"; + script { + public message(Msg_Type:type, id, ...) { + /* set scale */ + new sc; + + sc = getarg(2); + custom_state(PART:"title2", "default", 0.0); + custom_state(PART:"top", "default", 0.0); + custom_state(PART:"e.text.title", "default", 0.0); + custom_state(PART:"bottom", "default", 0.0); + set_state_val(PART:"title2", STATE_REL1, 0, 0.0 - sc); + set_state_val(PART:"top", STATE_REL1, 0, 0.0 - sc); + set_state_val(PART:"e.text.title", STATE_REL1, 0, 0.0 - sc); + set_state_val(PART:"bottom", STATE_REL2, 1, sc); + set_state(PART:"title2", "custom", 0.0); + set_state(PART:"top", "custom", 0.0); + set_state(PART:"e.text.title", "custom", 0.0); + set_state(PART:"e.swallow.client", "custom", 0.0); + set_state(PART:"bottom", "custom", 0.0); + } + } + parts { + part { name: "client_clip"; type: RECT; + description { state: "default" 0.0; + rel1.to_y: "e.swallow.client"; + rel2.to_y: "e.swallow.client"; + } + } + part { name: "e.swallow.client"; type: SWALLOW; + clip_to: "client_clip"; + description { state: "default" 0.0; + rel1.to_y: "top"; + rel1.relative: 0 1; + } + } + part { name: "top"; + description { state: "default" 0.0; + color_class: "border_top"; + image.normal: "vgrad_med_lighter.png"; + fill.smooth: 0; + TILED_HORIZ(120) + rel2.to_y: "title2"; + rel2.offset: -1 -4; + min: 0 1; + } + } + part { name: "bevel"; mouse_events: 0; + description { state: "default" 0.0; + image.normal: "bevel_out.png"; + image.border: 1 1 1 1; + image.middle: 0; + rel1.to: "top"; + rel2.to: "top"; + fill.smooth: 0; + } + } + part { name: "e.text.title"; type: TEXT; mouse_events: 0; + scale: 1; + effect: SHADOW BOTTOM; + description { state: "default" 0.0; + color_class: "border_title"; + rel1.offset: 1 3; + rel2.relative: 1.0 0.0; + rel2.offset: -2 3; + align: 0.5 0.0; + color: 21 21 21 255; + color3: 255 255 255 25; + text { font: "Sans:style=Bold"; + fit: 0 1; + text_class: "title_bar"; + align: 0.5 0.0; + min: 0 1; + } + fixed: 0 1; + } + } + part { name: "title2"; type: TEXT; mouse_events: 0; + scale: 1; + effect: SOFT_SHADOW BOTTOM; + description { state: "default" 0.0; + color_class: "border_title_active"; + rel1.offset: 1 2; + rel2.relative: 1.0 0.0; + rel2.offset: -1 2; + align: 0.5 0.0; + color: 255 255 255 255; + color3: 0 0 0 18; + text { font: "Sans:style=Bold"; + fit: 0 1; + text_source: "e.text.title"; + text_class: "title_bar"; + align: 0.5 0.0; + min: 0 1; + } + visible: 0; + fixed: 0 1; + } + } + part { name: "bottom"; type: RECT; mouse_events: 0; + description { state: "default" 0.0; + color_class: "border_bottom"; + rel1.to_y: "e.swallow.client"; + rel1.relative: 0.0 1.0; + rel1.offset: 0 -3; + min: 0 1; + color: 64 64 64 255; + fixed: 0 1; + } + } + part { name: "bevel2"; mouse_events: 0; + description { state: "default" 0.0; + image.normal: "bevel_dark_out.png"; + image.border: 1 1 1 1; + image.middle: 0; + rel1.to: "bottom"; + rel2.to: "bottom"; + fill.smooth: 0; + } + } + part { name: "shadow"; + mouse_events: 0; + description { state: "default" 0.0; + image.normal: "win_shadow.png"; + image.border: 14 14 14 14; + image.middle: 0; + rel1.to: "top"; + rel1.offset: -7 -3; + rel2.to: "bottom"; + rel2.offset: 6 11; + fill.smooth: 0; + } + } + } + programs { + program { name: "shon"; + signal: "e,state,shadow,on"; source: "e"; + script { + custom_state(PART:"shadow", "default", 0.0); + set_state_val(PART:"shadow", STATE_VISIBLE, 1); + set_state(PART:"shadow", "custom", 0.0); + } + } + program { name: "shoff"; + signal: "e,state,shadow,off"; source: "e"; + script { + custom_state(PART:"shadow", "default", 0.0); + set_state_val(PART:"shadow", STATE_VISIBLE, 0); + set_state(PART:"shadow", "custom", 0.0); + } + } + program { + name: "focus"; + signal: "e,state,focused"; source: "e"; + script { + custom_state(PART:"top", "default", 0.0); + set_state_val(PART:"top", STATE_IMAGE, get_image_id("vgrad_med_dark.png")); + set_state(PART:"top", "custom", 0.0); + custom_state(PART:"title2", "default", 0.0); + set_state_val(PART:"title2", STATE_VISIBLE, 1); + set_state(PART:"title2", "custom", 0.0); + custom_state(PART:"e.text.title", "default", 0.0); + set_state_val(PART:"e.text.title", STATE_VISIBLE, 0); + set_state(PART:"e.text.title", "custom", 0.0); + } + } + program { + name: "unfocus"; + signal: "e,state,unfocused"; source: "e"; + script { + custom_state(PART:"top", "default", 0.0); + set_state_val(PART:"top", STATE_IMAGE, get_image_id("vgrad_med_lighter.png")); + set_state(PART:"top", "custom", 0.0); + custom_state(PART:"title2", "default", 0.0); + set_state_val(PART:"title2", STATE_VISIBLE, 0); + set_state(PART:"title2", "custom", 0.0); + custom_state(PART:"e.text.title", "default", 0.0); + set_state_val(PART:"e.text.title", STATE_VISIBLE, 1); + set_state(PART:"e.text.title", "custom", 0.0); + } + } + program { + name: "shade"; + signal: "e,state,shaded"; source: "e"; + script { + custom_state(PART:"e.swallow.client", "default", 0.0); + set_state_val(PART:"e.swallow.client", STATE_MAX, 1, 1); + set_state_val(PART:"e.swallow.client", STATE_VISIBLE, 0); + set_state(PART:"e.swallow.client", "custom", 0.0); + custom_state(PART:"client_clip", "default", 0.0); + set_state_val(PART:"client_clip", STATE_REL1_TO, get_part_id("top"), get_part_id("top")); + set_state_val(PART:"client_clip", STATE_REL2_TO, get_part_id("top"), get_part_id("top")); + set_state(PART:"client_clip", "custom", 0.0); + custom_state(PART:"bottom", "default", 0.0); + set_state_val(PART:"bottom", STATE_VISIBLE, 0); + set_state_val(PART:"bottom", STATE_MIN, 0, 0); + set_state_val(PART:"bottom", STATE_REL1_OFFSET, 0, 0); + set_state(PART:"bottom", "custom", 0.0); + custom_state(PART:"bevel2", "default", 0.0); + set_state_val(PART:"bevel2", STATE_VISIBLE, 0); + set_state_val(PART:"bevel2", STATE_MIN, 0, 0); + set_state(PART:"bevel2", "custom", 0.0); + custom_state(PART:"shadow", "default", 0.0); + set_state_val(PART:"shadow", STATE_REL2_TO, get_part_id("top"), get_part_id("top")); + set_state(PART:"shadow", "custom", 0.0); + } + } + program { + signal: "e,state,maximize*"; source: "e"; + script { + custom_state(PART:"bottom", "default", 0.0); + set_state_val(PART:"bottom", STATE_VISIBLE, 0); + set_state_val(PART:"bottom", STATE_MIN, 0, 0); + set_state_val(PART:"bottom", STATE_REL1_OFFSET, 0, 0); + set_state(PART:"bottom", "custom", 0.0); + custom_state(PART:"bevel2", "default", 0.0); + set_state_val(PART:"bevel2", STATE_VISIBLE, 0); + set_state_val(PART:"bevel2", STATE_MIN, 0, 0); + set_state(PART:"bevel2", "custom", 0.0); + } + } + program { + signal: "e,state,unmaximize*"; source: "e"; + after: "unshade"; + } + program { + signal: "e,state,unshaded"; source: "e"; + after: "unshade"; + } + program { + name: "unshade"; + signal: "e,state,unshading"; source: "e"; + script { + custom_state(PART:"e.swallow.client", "default", 0.0); + set_state_val(PART:"e.swallow.client", STATE_MAX, 99999, 99999); + set_state_val(PART:"e.swallow.client", STATE_VISIBLE, 1); + set_state(PART:"e.swallow.client", "custom", 0.0); + custom_state(PART:"client_clip", "default", 0.0); + set_state_val(PART:"client_clip", STATE_REL1_TO, get_part_id("e.swallow.client"), get_part_id("e.swallow.client")); + set_state_val(PART:"client_clip", STATE_REL2_TO, get_part_id("e.swallow.client"), get_part_id("e.swallow.client")); + set_state(PART:"client_clip", "custom", 0.0); + custom_state(PART:"bottom", "default", 0.0); + set_state_val(PART:"bottom", STATE_VISIBLE, 1); + set_state_val(PART:"bottom", STATE_MIN, 0, 1); + set_state_val(PART:"bottom", STATE_REL1_OFFSET, 0, -3); + set_state(PART:"bottom", "custom", 0.0); + custom_state(PART:"bevel2", "default", 0.0); + set_state_val(PART:"bevel2", STATE_VISIBLE, 1); + set_state_val(PART:"bevel2", STATE_MIN, 0, 1); + set_state(PART:"bevel2", "custom", 0.0); + custom_state(PART:"shadow", "default", 0.0); + set_state_val(PART:"shadow", STATE_REL2_TO, get_part_id("bottom"), get_part_id("bottom")); + set_state(PART:"shadow", "custom", 0.0); + } + } + program { + signal: "e,action,maximize*"; source: "e"; + action: STATE_SET "max" 0.0; + target: "e.swallow.client"; + target: "bottom"; + target: "bevel2"; + } + program { + signal: "e,action,unmaximize*"; source: "e"; + action: STATE_SET "default" 0.0; + target: "e.swallow.client"; + target: "bottom"; + target: "bevel2"; + } + } +} + +group { name: "e/deskmirror/frame/noresize"; + inherit: "e/deskmirror/frame/default"; + parts { + part { name: "e.swallow.client"; type: SWALLOW; + description { state: "default" 0.0; + rel2.relative: 1.0 1.0; + } + } + part { name: "bottom"; type: RECT; + description { state: "default" 0.0; + color_class: "border_bottom"; + rel1.relative: 0.0 1.0; + rel1.offset: 0 -1; + rel2.relative: 1.0 1.0; + min: 0 0; + fixed: 0 1; + visible: 0; + } + } + part { name: "bevel2"; + description { state: "default" 0.0; + visible: 0; + } + } + } +} + +group { name: "e/deskmirror/frame/noresize_dialog"; + inherit: "e/deskmirror/frame/default"; + parts { + part { name: "e.swallow.client"; type: SWALLOW; + description { state: "default" 0.0; + rel2.relative: 1.0 1.0; + } + } + part { name: "bottom"; type: RECT; + description { state: "default" 0.0; + color_class: "border_bottom"; + rel1.relative: 0.0 1.0; + rel1.offset: 0 -1; + rel2.relative: 1.0 1.0; + min: 0 0; + fixed: 0 1; + visible: 0; + } + } + part { name: "bevel2"; + description { state: "default" 0.0; + visible: 0; + } + } + } +} + +group { name: "e/deskmirror/frame/pixel"; + parts { + part { name: "client_clip"; type: RECT; + description { state: "default" 0.0; + rel1.to_y: "e.swallow.client"; + rel2.to_y: "e.swallow.client"; + } + } + part { name: "e.swallow.client"; type: SWALLOW; + clip_to: "client_clip"; + description { state: "default" 0.0; + rel1.offset: 1 1; + rel2.offset: -2 -2; + } + } + part { name: "top"; type: RECT; + description { state: "default" 0.0; + color: 0 0 0 255; + align: 0.0 0.0; + max: 99999 1; + } + description { state: "focused" 0.0; + inherit: "default" 0.0; + color: 51 153 255 255; + } + } + part { name: "bottom"; type: RECT; + description { state: "default" 0.0; + color: 0 0 0 255; + align: 0.0 1.0; + max: 99999 1; + } + description { state: "focused" 0.0; + inherit: "default" 0.0; + color: 51 153 255 255; + } + } + part { name: "left"; type: RECT; + description { state: "default" 0.0; + color: 0 0 0 255; + align: 0.0 0.0; + max: 1 99999; + } + description { state: "focused" 0.0; + inherit: "default" 0.0; + color: 51 153 255 255; + } + } + part { name: "right"; type: RECT; + description { state: "default" 0.0; + color: 0 0 0 255; + align: 1.0 0.0; + max: 1 99999; + } + description { state: "focused" 0.0; + inherit: "default" 0.0; + color: 51 153 255 255; + } + } + } + programs { + program { + signal: "e,state,focused"; source: "e"; + action: STATE_SET "focused" 0.0; + target: "top"; + target: "bottom"; + target: "left"; + target: "right"; + } + program { + signal: "e,state,unfocused"; source: "e"; + action: STATE_SET "default" 0.0; + target: "top"; + target: "bottom"; + target: "left"; + target: "right"; + } + } +} diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index 0987d8963..098f4393f 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -71,6 +71,7 @@ e_dbusmenu.h \ e_desk.h \ e_deskenv.h \ e_desklock.h \ +e_deskmirror.h \ e_dialog.h \ e_dnd.h \ e_dpms.h \ @@ -241,6 +242,7 @@ e_dbusmenu.c \ e_desk.c \ e_deskenv.c \ e_desklock.c \ +e_deskmirror.c \ e_dialog.c \ e_dnd.c \ e_dpms.c \ diff --git a/src/bin/e_deskmirror.c b/src/bin/e_deskmirror.c new file mode 100644 index 000000000..6306f9665 --- /dev/null +++ b/src/bin/e_deskmirror.c @@ -0,0 +1,627 @@ +#include "e.h" + +#define INTERNAL_ENTRY E_Smart_Data * sd; sd = evas_object_smart_data_get(obj); if (!sd) return; + +typedef struct E_Smart_Data +{ + Evas *e; + Evas_Object *obj; + Evas_Object *clip; + Evas_Object *bgpreview; + Evas_Object *layout; + Eina_Inlist *mirrors; + Eina_Hash *mirror_hash; + + Eina_List *handlers; + + Evas_Coord x, y; + int w, h; + + E_Desk *desk; + E_Object_Delfn *desk_delfn; + + Eina_Bool pager : 1; + Eina_Bool taskbar : 1; + + Eina_Bool resize : 1; +} E_Smart_Data; + +typedef struct Mirror +{ + EINA_INLIST; + E_Smart_Data *sd; + E_Comp_Win *cw; + Evas_Object *mirror; + int x, y, w, h; + Eina_Bool frame : 1; +} Mirror; + +typedef struct Mirror_Border +{ + Mirror *m; + Evas_Object *mirror; + Evas_Object *frame; + Evas_Object *obj; +} Mirror_Border; + +/* local subsystem globals */ +static Evas_Smart *_e_deskmirror_smart = NULL; +static Evas_Smart *_mirror_border_smart = NULL; + +/* local subsystem functions */ +static void +_mirror_scale_set(Mirror *m, float sc) +{ + Edje_Message_Float_Set msg; + Mirror_Border *mb; + + if (!m->frame) return; + + mb = evas_object_smart_data_get(m->mirror); + msg.count = 1; + msg.val[0] = sc; + edje_object_message_send(mb->frame, EDJE_MESSAGE_FLOAT_SET, 0, &msg); +} + +static void +_e_deskmirror_smart_reconfigure(E_Smart_Data *sd) +{ + e_layout_freeze(sd->layout); + evas_object_move(sd->clip, sd->x, sd->y); + evas_object_move(sd->bgpreview, sd->x, sd->y); + evas_object_move(sd->layout, sd->x, sd->y); + + if (sd->resize) + { + Mirror *m; + + evas_object_resize(sd->clip, sd->w, sd->h); + evas_object_resize(sd->bgpreview, sd->w, sd->h); + evas_object_resize(sd->layout, sd->w, sd->h); + EINA_INLIST_FOREACH(sd->mirrors, m) + _mirror_scale_set(m, (float)sd->h / (float)sd->desk->zone->h); + } + e_layout_thaw(sd->layout); + sd->resize = 0; +} + +/////////////////////////////////////////////// + +static void +_e_deskmirror_smart_add(Evas_Object *obj) +{ + E_Smart_Data *sd; + + sd = E_NEW(E_Smart_Data, 1); + if (!sd) return; + sd->obj = obj; + sd->e = evas_object_evas_get(obj); + sd->x = sd->y = sd->w = sd->h = 0; + sd->clip = evas_object_rectangle_add(sd->e); + evas_object_smart_member_add(sd->clip, sd->obj); + evas_object_smart_data_set(obj, sd); +} + +static void +_e_deskmirror_smart_del(Evas_Object *obj) +{ + INTERNAL_ENTRY; + if (sd->desk_delfn) + { + e_object_delfn_del(E_OBJECT(sd->desk), sd->desk_delfn); + sd->desk_delfn = NULL; + sd->desk = NULL; + } + E_FREE_LIST(sd->handlers, ecore_event_handler_del); + eina_hash_free(sd->mirror_hash); + free(sd); +} + +static void +_e_deskmirror_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y) +{ + INTERNAL_ENTRY; + sd->x = x; + sd->y = y; + _e_deskmirror_smart_reconfigure(sd); +} + +static void +_e_deskmirror_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h) +{ + INTERNAL_ENTRY; + sd->w = w; + sd->h = h; + sd->resize = 1; + _e_deskmirror_smart_reconfigure(sd); +} + +static void +_e_deskmirror_smart_show(Evas_Object *obj) +{ + INTERNAL_ENTRY; + evas_object_show(sd->clip); +} + +static void +_e_deskmirror_smart_hide(Evas_Object *obj) +{ + INTERNAL_ENTRY; + evas_object_hide(sd->clip); +} + +static void +_e_deskmirror_smart_color_set(Evas_Object *obj, int r, int g, int b, int a) +{ + INTERNAL_ENTRY; + evas_object_color_set(sd->clip, r, g, b, a); +} + +static void +_e_deskmirror_smart_clip_set(Evas_Object *obj, Evas_Object *clip) +{ + INTERNAL_ENTRY; + evas_object_clip_set(sd->clip, clip); +} + +static void +_e_deskmirror_smart_clip_unset(Evas_Object *obj) +{ + INTERNAL_ENTRY; + evas_object_clip_unset(sd->clip); +} + +//////////////////////////////////////////////////////// + +static void +_e_deskmirror_mirror_frame_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Mirror_Border *mb = data; + + if (mb->m->cw->bd && (!e_object_is_del(E_OBJECT(mb->m->cw->bd)))) + { + evas_object_smart_member_del(mb->mirror); + mb->m->mirror = mb->mirror; + mb->m->frame = 0; + } + else + mb->m->cw = NULL; + evas_object_del(mb->obj); +} + +static void +_mirror_border_smart_add(Evas_Object *obj) +{ + Mirror_Border *mb; + + mb = E_NEW(Mirror_Border, 1); + mb->obj = obj; + evas_object_smart_data_set(obj, mb); +} + +static void +_mirror_border_signal_cb(void *data, Evas_Object *obj EINA_UNUSED, const char *emission, const char *src) +{ + Mirror_Border *mb = data; + edje_object_signal_emit(mb->frame, emission, src); + edje_object_message_signal_process(mb->frame); + edje_object_calc_force(mb->frame); +} + +static void +_mirror_border_smart_del(Evas_Object *obj) +{ + Mirror_Border *mb = evas_object_smart_data_get(obj); + if (mb->m->cw && mb->m->cw->bd) + { + evas_object_event_callback_del_full(mb->m->cw->bd->bg_object, EVAS_CALLBACK_DEL, _e_deskmirror_mirror_frame_del_cb, mb); + edje_object_signal_callback_del_full(mb->m->cw->bd->bg_object, "*", "*", _mirror_border_signal_cb, mb); + } + free(mb); +} + +static void +_mirror_border_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y) +{ + Mirror_Border *mb = evas_object_smart_data_get(obj); + + evas_object_move(mb->frame, x, y); +} + +static void +_mirror_border_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h) +{ + Mirror_Border *mb = evas_object_smart_data_get(obj); + evas_object_resize(mb->frame, w, h); +} + +static void +_mirror_border_smart_show(Evas_Object *obj) +{ + Mirror_Border *mb = evas_object_smart_data_get(obj); + evas_object_show(mb->frame); + evas_object_show(mb->mirror); +} + +static void +_mirror_border_smart_hide(Evas_Object *obj) +{ + Mirror_Border *mb = evas_object_smart_data_get(obj); + evas_object_hide(mb->frame); + evas_object_hide(mb->mirror); +} + +static void +_mirror_border_smart_color_set(Evas_Object *obj, int r, int g, int b, int a) +{ + Mirror_Border *mb = evas_object_smart_data_get(obj); + evas_object_color_set(mb->frame, r, g, b, a); + evas_object_color_set(mb->mirror, r, g, b, a); +} + +static void +_mirror_border_smart_clip_set(Evas_Object *obj, Evas_Object *clip) +{ + Mirror_Border *mb = evas_object_smart_data_get(obj); + evas_object_clip_set(mb->frame, clip); + evas_object_clip_set(mb->mirror, clip); +} + +static void +_mirror_border_smart_clip_unset(Evas_Object *obj) +{ + Mirror_Border *mb = evas_object_smart_data_get(obj); + evas_object_clip_unset(mb->frame); + evas_object_clip_unset(mb->mirror); +} + +static void +_mirror_border_smart_init(void) +{ + static const Evas_Smart_Class sc = + { + "mirror_border", EVAS_SMART_CLASS_VERSION, + _mirror_border_smart_add, _mirror_border_smart_del, _mirror_border_smart_move, _mirror_border_smart_resize, + _mirror_border_smart_show, _mirror_border_smart_hide, _mirror_border_smart_color_set, _mirror_border_smart_clip_set, + _mirror_border_smart_clip_unset, NULL, NULL, NULL, NULL, NULL, NULL, NULL + }; + if (_mirror_border_smart) return; + _mirror_border_smart = evas_smart_class_new(&sc); +} + +static void +_e_deskmirror_smart_init(void) +{ + static const Evas_Smart_Class sc = + { + "e_deskmirror", EVAS_SMART_CLASS_VERSION, + _e_deskmirror_smart_add, _e_deskmirror_smart_del, _e_deskmirror_smart_move, _e_deskmirror_smart_resize, + _e_deskmirror_smart_show, _e_deskmirror_smart_hide, _e_deskmirror_smart_color_set, _e_deskmirror_smart_clip_set, + _e_deskmirror_smart_clip_unset, NULL, NULL, NULL, NULL, NULL, NULL, NULL + }; + if (_e_deskmirror_smart) return; + _e_deskmirror_smart = evas_smart_class_new(&sc); +} + +static void +_e_deskmirror_delfn(E_Smart_Data *sd, void *desk EINA_UNUSED) +{ + sd->desk_delfn = NULL; + sd->desk = NULL; + evas_object_del(sd->obj); +} + +static Eina_Bool +_e_deskmirror_win_visible_get(E_Smart_Data *sd, E_Comp_Win *cw) +{ + Eina_Bool visible = cw->visible; + if (cw->bd) + { + if (visible) + { + if (sd->pager) + visible = !cw->bd->client.netwm.state.skip_pager; + if (visible && sd->taskbar) + visible = !cw->bd->client.netwm.state.skip_taskbar; + } + } + return visible; +} + +static void +_e_deskmirror_mirror_del(Mirror *m) +{ + eina_hash_del_by_key(m->sd->mirror_hash, &m->cw); +} + +static void +_e_deskmirror_mirror_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + _e_deskmirror_mirror_del(data); +} + +static void +_e_deskmirror_mirror_del_hash(Mirror *m) +{ + m->sd->mirrors = eina_inlist_remove(m->sd->mirrors, EINA_INLIST_GET(m)); + evas_object_event_callback_del_full(m->mirror, EVAS_CALLBACK_DEL, _e_deskmirror_mirror_del_cb, m); + evas_object_del(m->mirror); + free(m); +} + +static void +_e_deskmirror_mirror_geometry_get(Mirror *m) +{ + if (m->cw->bd) + { + m->x = m->cw->bd->x; + m->y = m->cw->bd->y; + m->w = m->cw->bd->w; + if (m->cw->bd->shaded) + m->h = m->cw->bd->client_inset.t; + else + m->h = m->cw->bd->h; + } + else if (m->cw->not_in_layout) + evas_object_geometry_get(m->cw->effect_obj, &m->x, &m->y, &m->w, &m->h); + else + e_layout_child_geometry_get(m->cw->effect_obj, &m->x, &m->y, &m->w, &m->h); + /* double check here if we get zeroes */ + if ((!m->w) || (!m->h)) + { + m->w = m->cw->w, m->h = m->cw->h; + m->x = m->cw->x, m->y = m->cw->y; + } +} + +static void +_e_deskmirror_mirror_reconfigure(Mirror *m) +{ + _e_deskmirror_mirror_geometry_get(m); + e_layout_child_move(m->mirror, m->x, m->y); + e_layout_child_resize(m->mirror, m->w, m->h); + if (_e_deskmirror_win_visible_get(m->sd, m->cw) && m->w && m->h) + evas_object_show(m->mirror); + else + evas_object_hide(m->mirror); +} + +static Evas_Object * +_mirror_border_new(Mirror *m) +{ + Evas_Object *o; + Mirror_Border *mb; + char buf[4096]; + + _mirror_border_smart_init(); + o = evas_object_smart_add(m->sd->e, _mirror_border_smart); + mb = evas_object_smart_data_get(o); + mb->m = m; + mb->frame = edje_object_add(m->sd->e); + evas_object_name_set(mb->frame, "mirror_border"); + snprintf(buf, sizeof(buf), "e/deskmirror/frame/%s", m->cw->bd->client.border.name); + e_theme_edje_object_set(mb->frame, "base/theme/borders", buf); + if (e_util_border_shadow_state_get(m->cw->bd)) + edje_object_signal_emit(mb->frame, "e,state,shadow,on", "e"); + else + edje_object_signal_emit(mb->frame, "e,state,shadow,off", "e"); + edje_object_signal_callback_add(mb->m->cw->bd->bg_object, "*", "*", _mirror_border_signal_cb, mb); + if (e_border_focused_get() == mb->m->cw->bd) + edje_object_signal_emit(mb->frame, "e,state,focused", "e"); + if (mb->m->cw->bd->shaded) + edje_object_signal_emit(mb->frame, "e,state,shaded", "e"); + if (mb->m->cw->bd->maximized) + edje_object_signal_emit(mb->frame, "e,action,maximize", "e"); + if (mb->m->cw->bd->sticky) + edje_object_signal_emit(mb->frame, "e,state,sticky", "e"); + + mb->mirror = m->mirror; + evas_object_smart_member_add(mb->frame, o); + evas_object_name_set(mb->mirror, "mirror"); + evas_object_smart_member_add(mb->mirror, o); + edje_object_part_swallow(mb->frame, "e.swallow.client", m->mirror); + edje_object_part_text_set(mb->frame, "e.text.title", m->cw->bd->client.netwm.name ?: m->cw->bd->client.icccm.name); + _mirror_scale_set(m, (double)m->sd->h / (double)m->sd->desk->zone->h); + evas_object_event_callback_add(m->cw->bd->bg_object, EVAS_CALLBACK_DEL, _e_deskmirror_mirror_frame_del_cb, mb); + return o; +} + +static void +_e_deskmirror_mirror_setup(Mirror *m) +{ + if (!m->mirror) return; + if (m->cw->bd && m->cw->bd->bg_object) + { + m->mirror = _mirror_border_new(m); + m->frame = 1; + } + else + evas_object_pass_events_set(m->mirror, 1); + e_layout_pack(m->sd->layout, m->mirror); + evas_object_event_callback_add(m->mirror, EVAS_CALLBACK_DEL, _e_deskmirror_mirror_del_cb, m); + _e_deskmirror_mirror_reconfigure(m); +} + +static Mirror * +_e_deskmirror_mirror_add(E_Smart_Data *sd, E_Comp_Win *cw) +{ + Mirror *m; + Evas_Object *o = NULL; + + if (cw->bd) + { + if ((cw->bd->zone != sd->desk->zone) || ((cw->bd->desk != sd->desk) && (!cw->bd->sticky))) + return NULL; + } + else + { + int x, y; + + if (!sd->desk->visible) return NULL; + if (cw->not_in_layout) + evas_object_geometry_get(cw->effect_obj, &x, &y, NULL, NULL); + else + e_layout_child_geometry_get(cw->effect_obj, &x, &y, NULL, NULL); + if (!E_INSIDE(x, y, sd->desk->zone->x, sd->desk->zone->y, sd->desk->zone->w, sd->desk->zone->h)) return NULL; + } + if ((cw->w > 1) && (cw->h > 1)) + { + o = e_comp_win_image_mirror_add(cw); + if (!o) return NULL; + } + m = calloc(1, sizeof(Mirror)); + m->cw = cw; + m->sd = sd; + m->mirror = o; + sd->mirrors = eina_inlist_append(sd->mirrors, EINA_INLIST_GET(m)); + eina_hash_direct_add(sd->mirror_hash, &m->cw, m); + _e_deskmirror_mirror_setup(m); + return m; +} + +static Eina_Bool +_comp_source_add(E_Smart_Data *sd, int type EINA_UNUSED, E_Event_Comp *ev) +{ + if (eina_hash_find(sd->mirror_hash, &ev->cw)) return ECORE_CALLBACK_RENEW; + _e_deskmirror_mirror_add(sd, ev->cw); + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_comp_source_visible(E_Smart_Data *sd, int type EINA_UNUSED, E_Event_Comp *ev) +{ + Mirror *m; + + m = eina_hash_find(sd->mirror_hash, &ev->cw); + if (!m) return ECORE_CALLBACK_RENEW; + if (!m->mirror) + { + if ((m->cw->w < 2) || (m->cw->h < 2)) return ECORE_CALLBACK_RENEW; + m->mirror = e_comp_win_image_mirror_add(m->cw); + _e_deskmirror_mirror_setup(m); + } + if (_e_deskmirror_win_visible_get(m->sd, m->cw)) + evas_object_show(m->mirror); + else + evas_object_hide(m->mirror); + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_comp_source_stack(E_Smart_Data *sd, int type EINA_UNUSED, E_Event_Comp *ev) +{ + Mirror *m, *m2; + E_Comp_Win *cw; + + m = eina_hash_find(sd->mirror_hash, &ev->cw); + if (!m) return ECORE_CALLBACK_RENEW; + if (!m->mirror) + { + if ((m->cw->w < 2) || (m->cw->h < 2)) return ECORE_CALLBACK_RENEW; + m->mirror = e_comp_win_image_mirror_add(m->cw); + _e_deskmirror_mirror_setup(m); + } + if (!EINA_INLIST_GET(ev->cw)->next) + e_layout_child_raise(m->mirror); + else if (!EINA_INLIST_GET(ev->cw)->prev) + e_layout_child_lower(m->mirror); + else + { + EINA_INLIST_FOREACH(EINA_INLIST_GET(ev->cw)->next, cw) + { + m2 = eina_hash_find(sd->mirror_hash, &cw); + if ((!m2) || (!m2->mirror)) continue; + e_layout_child_lower_below(m->mirror, m2->mirror); + return ECORE_CALLBACK_RENEW; + } + e_layout_child_raise(m->mirror); + } + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_comp_source_configure(E_Smart_Data *sd, int type EINA_UNUSED, E_Event_Comp *ev) +{ + Mirror *m; + + m = eina_hash_find(sd->mirror_hash, &ev->cw); + if (m) + { + if (!m->mirror) + { + if ((m->cw->w < 2) || (m->cw->h < 2)) return ECORE_CALLBACK_RENEW; + m->mirror = e_comp_win_image_mirror_add(m->cw); + _e_deskmirror_mirror_setup(m); + } + _e_deskmirror_mirror_reconfigure(m); + } + return ECORE_CALLBACK_RENEW; +} + +/* externally accessible functions */ +EAPI Evas_Object * +e_deskmirror_add(E_Desk *desk) +{ + E_Smart_Data *sd; + Evas_Object *o; + Evas *e; + E_Comp_Win *cw; + + e = e_comp_get(desk)->evas; + _e_deskmirror_smart_init(); + o = evas_object_smart_add(e, _e_deskmirror_smart); + sd = evas_object_smart_data_get(o); + sd->desk = desk; + sd->mirror_hash = eina_hash_pointer_new((Eina_Free_Cb)_e_deskmirror_mirror_del_hash); + sd->desk_delfn = e_object_delfn_add(E_OBJECT(desk), (Ecore_End_Cb)_e_deskmirror_delfn, sd); + sd->bgpreview = e_widget_bgpreview_desk_add(e, desk->zone, desk->x, desk->y); + evas_object_clip_set(sd->bgpreview, sd->clip); + evas_object_smart_member_add(sd->bgpreview, o); + evas_object_show(sd->bgpreview); + sd->layout = e_layout_add(e); + evas_object_clip_set(sd->layout, sd->clip); + e_layout_virtual_size_set(sd->layout, desk->zone->w, desk->zone->h); + evas_object_smart_member_add(sd->layout, o); + evas_object_show(sd->layout); + + e_layout_freeze(sd->layout); + + EINA_INLIST_FOREACH(e_comp_get(desk)->wins, cw) + { + Mirror *m; + + m = _e_deskmirror_mirror_add(sd, cw); + if (m) e_layout_child_raise(m->mirror); + } + + e_layout_thaw(sd->layout); + + E_LIST_HANDLER_APPEND(sd->handlers, E_EVENT_COMP_SOURCE_ADD, _comp_source_add, sd); + E_LIST_HANDLER_APPEND(sd->handlers, E_EVENT_COMP_SOURCE_CONFIGURE, _comp_source_configure, sd); + E_LIST_HANDLER_APPEND(sd->handlers, E_EVENT_COMP_SOURCE_STACK, _comp_source_stack, sd); + E_LIST_HANDLER_APPEND(sd->handlers, E_EVENT_COMP_SOURCE_VISIBILITY, _comp_source_visible, sd); + return o; +} + +EAPI void +e_deskmirror_util_wins_print(Evas_Object *obj) +{ + E_Smart_Data *sd; + Mirror *m; + + EINA_SAFETY_ON_NULL_RETURN(obj); + sd = evas_object_smart_data_get(obj); + EINA_INLIST_FOREACH(sd->mirrors, m) + { + if (m->cw->bd) + fprintf(stderr, "MIRROR BD: %p - %u '%s:%s'\n", m->cw, m->cw->win, m->cw->bd->client.icccm.name, m->cw->bd->client.icccm.class); + else if (m->cw->pop) + fprintf(stderr, "MIRROR POP: %p - %s\n", m->cw, m->cw->pop->name); + else if (m->cw->menu) + fprintf(stderr, "MIRROR MENU: %p - %s\n", m->cw, m->cw->menu->header.title); + else if (m->cw->real_obj) + fprintf(stderr, "MIRROR OBJ: %p - %s\n", m->cw, evas_object_name_get(m->cw->obj)); + else + fprintf(stderr, "MIRROR WIN: %p - %u%s\n", m->cw, m->cw->win, m->cw->input_only ? " INPUT" : ""); + } +} diff --git a/src/bin/e_deskmirror.h b/src/bin/e_deskmirror.h new file mode 100644 index 000000000..aabbc7720 --- /dev/null +++ b/src/bin/e_deskmirror.h @@ -0,0 +1,8 @@ +#ifndef E_WIDGET_DESKMIRROR_H +#define E_WIDGET_DESKMIRROR_H + +EAPI Evas_Object *e_deskmirror_add(E_Desk *desk); +EAPI void e_deskmirror_util_wins_print(Evas_Object *obj); +//#define DESKMIRROR_TEST + +#endif diff --git a/src/bin/e_includes.h b/src/bin/e_includes.h index 809caa7c0..68b72783d 100644 --- a/src/bin/e_includes.h +++ b/src/bin/e_includes.h @@ -120,6 +120,7 @@ #include "e_filereg.h" #include "e_widget_aspect.h" #include "e_widget_bgpreview.h" +#include "e_deskmirror.h" #include "e_fm_prop.h" #include "e_mouse.h" #include "e_order.h" diff --git a/src/bin/e_int_border_menu.c b/src/bin/e_int_border_menu.c index a8faaa6e2..3586a1bbe 100644 --- a/src/bin/e_int_border_menu.c +++ b/src/bin/e_int_border_menu.c @@ -31,7 +31,6 @@ static void _e_border_menu_cb_fullscreen(void *data, E_Menu *m, E_Menu_Item *mi) static void _e_border_menu_cb_skip_winlist(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_border_menu_cb_skip_pager(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_border_menu_cb_skip_taskbar(void *data, E_Menu *m, E_Menu_Item *mi); -static void _e_border_menu_cb_sendto_icon_pre(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_border_menu_cb_sendto_pre(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_border_menu_cb_sendto(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_border_menu_cb_pin(void *data, E_Menu *m, E_Menu_Item *mi); @@ -881,7 +880,8 @@ _e_border_menu_cb_skip_taskbar(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi e_remember_update(bd); } -static void +#ifndef DESKMIRROR_TEST + static void _e_border_menu_cb_sendto_icon_pre(void *data, E_Menu *m, E_Menu_Item *mi) { E_Desk *desk = NULL; @@ -903,6 +903,7 @@ _e_border_menu_cb_sendto_icon_pre(void *data, E_Menu *m, E_Menu_Item *mi) e_thumb_icon_begin(o); mi->icon_object = o; } +#endif static void _e_border_menu_cb_sendto_pre(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi) @@ -935,24 +936,35 @@ _e_border_menu_cb_sendto_pre(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi) e_menu_item_disabled_set(submi, EINA_TRUE); } -// FIXME: Remove labels and add bgpreview to menu. -// Evas_Object *o = e_widget_bgpreview_add(m->evas, 4, 2); - for (i = 0; i < zone->desk_x_count * zone->desk_y_count; i++) { E_Desk *desk; - +#ifdef DESKMIRROR_TEST + int tw = 50, th; +#endif desk = zone->desks[i]; +#ifdef DESKMIRROR_TEST + th = (tw * desk->zone->h) / desk->zone->w; +#endif submi = e_menu_item_new(subm); e_menu_item_label_set(submi, desk->name); e_menu_item_radio_set(submi, 1); e_menu_item_radio_group_set(submi, 2); +#ifdef DESKMIRROR_TEST + e_menu_item_icon_file_set(submi, "sup"); +#endif if ((bd->zone == zone) && (desk_cur == desk)) e_menu_item_toggle_set(submi, 1); else e_menu_item_callback_set(submi, _e_border_menu_cb_sendto, desk); +#ifdef DESKMIRROR_TEST + submi->icon_object = e_deskmirror_add(desk); + edje_extern_object_min_size_set(submi->icon_object, tw, th); + evas_object_show(submi->icon_object); +#else e_menu_item_realize_callback_set(submi, _e_border_menu_cb_sendto_icon_pre, desk); +#endif } } } diff --git a/src/bin/e_test.c b/src/bin/e_test.c index 8a5fe3423..4d9a14c57 100644 --- a/src/bin/e_test.c +++ b/src/bin/e_test.c @@ -2,6 +2,25 @@ static void _e_test_internal(E_Container *con); +#ifdef DESKMIRROR_TEST + +static Eina_Bool +deskmirror_test(void *d EINA_UNUSED) +{ + E_Zone *zone; + Evas_Object *o; + E_Popup *pop; + + zone = e_util_zone_current_get(e_manager_current_get()); + pop = e_popup_new(zone, zone->x + zone->w / 4, zone->y + zone->h / 4, zone->w / 2, zone->h / 2); + o = e_deskmirror_add(e_desk_current_get(zone)); + e_popup_content_set(pop, o); + e_popup_show(pop); + return EINA_FALSE; +} + +#endif + EAPI void e_test(void) { @@ -16,6 +35,10 @@ e_test(void) _e_test_internal(con); } } + +#ifdef DESKMIRROR_TEST + ecore_timer_add(2.0, deskmirror_test, NULL); +#endif } #if 0