discomfitor pushed a commit to branch master.

commit 6371da9a61ef4fb98a84e145ab1e3d65a15ab252
Author: Mike Blumenkrantz <[email protected]>
Date:   Thu Apr 18 15:50:49 2013 +0100

    add new modes for notification display when using multiple monitors, shows 
a TODO bug for comp zoomap mirrors
---
 ChangeLog                               |   5 +
 NEWS                                    |   2 +
 src/modules/notification/e_mod_config.c |  16 ++-
 src/modules/notification/e_mod_main.c   |  33 ++++-
 src/modules/notification/e_mod_main.h   |  27 +++--
 src/modules/notification/e_mod_popup.c  | 206 ++++++++++++++++++--------------
 6 files changed, 185 insertions(+), 104 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 52ceaaf..279bff5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2013-04-18 Mike Blumenkrantz
+
+        * startup splash screen moved to compositor canvas
+        * added new modes for notification display on multiple monitors
+
 2013-04-16 Chris Michael
 
        * added support for the Enlightenment compositor to render Wayland 
Clients
diff --git a/NEWS b/NEWS
index c01ae23..f055c17 100644
--- a/NEWS
+++ b/NEWS
@@ -129,6 +129,8 @@ Improvements:
     * menus are now drawn directly on the compositor canvas
     * window borders now drawn on compositor canvas
     * desk flip animations moved to edje
+    * startup splash screen moved to compositor canvas
+    * added new modes for notification display on multiple monitors
 
 Fixes:
     * IBar menu didn't allow to configure different icon sources, show 
contents menu even on empty IBar.
diff --git a/src/modules/notification/e_mod_config.c 
b/src/modules/notification/e_mod_config.c
index 17329a2..97c0530 100644
--- a/src/modules/notification/e_mod_config.c
+++ b/src/modules/notification/e_mod_config.c
@@ -7,7 +7,7 @@ struct _E_Config_Dialog_Data
    int    show_critical;
    int    force_timeout;
    int    ignore_replacement;
-   int    dual_screen;
+   Popup_Display_Policy dual_screen;
    double timeout;
    int    corner;
    Evas_Object *force_timeout_slider;
@@ -127,6 +127,18 @@ _basic_create(E_Config_Dialog      *cfd __UNUSED__,
     * e_widget_framelist_object_append(of, ow);
     * e_widget_list_object_append(o, of, 1, 1, 0.5); */
 
+   of = e_widget_framelist_add(evas, _("Screen Policy"), 0);
+   rg = e_widget_radio_group_new((int*)&cfdata->dual_screen);
+   ow = e_widget_radio_add(evas, _("Primary screen"), 
POPUP_DISPLAY_POLICY_FIRST, rg);
+   e_widget_framelist_object_append(of, ow);
+   ow = e_widget_radio_add(evas, _("Current screen"), 
POPUP_DISPLAY_POLICY_CURRENT, rg);
+   e_widget_framelist_object_append(of, ow);
+   ow = e_widget_radio_add(evas, _("All screens"), POPUP_DISPLAY_POLICY_ALL, 
rg);
+   e_widget_framelist_object_append(of, ow);
+   ow = e_widget_radio_add(evas, _("Xinerama"), POPUP_DISPLAY_POLICY_MULTI, 
rg);
+   e_widget_framelist_object_append(of, ow);
+   e_widget_list_object_append(o, of, 1, 1, 0.5);
+
    of = e_widget_framelist_add(evas, _("Popup Corner"), 0);
    rg = e_widget_radio_group_new(&(cfdata->corner));
    ow = e_widget_radio_add(evas, _("Top left"), CORNER_TL, rg);
@@ -149,8 +161,6 @@ _basic_create(E_Config_Dialog      *cfd __UNUSED__,
    of = e_widget_framelist_add(evas, _("Miscellaneous"), 0);
    ow = e_widget_check_add(evas, _("Ignore replace ID"), 
&(cfdata->ignore_replacement));
    e_widget_framelist_object_append(of, ow);
-   ow = e_widget_check_add(evas, _("Use multiple monitor geometry"), 
&(cfdata->dual_screen));
-   e_widget_framelist_object_append(of, ow);
    e_widget_list_object_append(o, of, 1, 1, 0.5);
 
 
diff --git a/src/modules/notification/e_mod_main.c 
b/src/modules/notification/e_mod_main.c
index b1a3f56..3ba0298 100644
--- a/src/modules/notification/e_mod_main.c
+++ b/src/modules/notification/e_mod_main.c
@@ -146,6 +146,29 @@ _notification_corner_info_cb(E_Configure_Option *co)
    return ret;
 }
 
+static Eina_List *
+_notification_screen_info_cb(E_Configure_Option *co)
+{
+   Eina_List *ret = NULL;
+   E_Configure_Option_Info *oi;
+   int x;
+   const char *name[] =
+   {
+    "Primary screen",
+    "Current screen",
+    "All screens",
+    "Xinerama",
+   };
+
+   for (x = 0; x <= POPUP_DISPLAY_POLICY_MULTI; x++)
+     {
+        oi = e_configure_option_info_new(co, _(name[x]), (intptr_t*)(long)x);
+        oi->current = (*(int*)co->valptr == x);
+        ret = eina_list_append(ret, oi);
+     }
+   return ret;
+}
+
 /* Module Api Functions */
 EAPI E_Module_Api e_modapi = {E_MODULE_API_VERSION, "Notification"};
 
@@ -212,6 +235,11 @@ e_modapi_init(E_Module *m)
 
    if (!notification_cfg)
      notification_cfg = _notification_cfg_new();
+   /* upgrades */
+   if (notification_cfg->version - (MOD_CONFIG_FILE_EPOCH * 1000000) < 1)
+     {
+        if (notification_cfg->dual_screen) notification_cfg->dual_screen = 
POPUP_DISPLAY_POLICY_MULTI;
+     }
    notification_cfg->version = MOD_CONFIG_FILE_VERSION;
 
    /* set up the notification daemon */
@@ -243,6 +271,9 @@ e_modapi_init(E_Module *m)
    E_CONFIGURE_OPTION_ADD(co, BOOL, force_timeout, notification_cfg, _("Force 
a specified timeout on all notifications"), _("notification"), _("delay"));
    E_CONFIGURE_OPTION_ADD(co, DOUBLE, timeout, notification_cfg, _("Timeout to 
force on notifications"), _("notification"), _("delay"));
    E_CONFIGURE_OPTION_MINMAX_STEP_FMT(co, 0.0, 15.0, 0.1, _("%.1f seconds"));
+   E_CONFIGURE_OPTION_ADD(co, ENUM, dual_screen, notification_cfg, 
_("Screen(s) on which to display notifications"), _("notification"), 
_("screen"));
+   co->info_cb = _notification_screen_info_cb;
+   E_CONFIGURE_OPTION_ICON(co, buf);
    E_CONFIGURE_OPTION_ADD(co, ENUM, corner, notification_cfg, _("Corner in 
which to display notifications"), _("notification"), _("screen"));
    co->info_cb = _notification_corner_info_cb;
    E_CONFIGURE_OPTION_ICON(co, buf);
@@ -301,7 +332,7 @@ _notification_cfg_new(void)
    cfg->timeout = 5.0;
    cfg->force_timeout = 0;
    cfg->ignore_replacement = 0;
-   cfg->dual_screen = 0;
+   cfg->dual_screen = POPUP_DISPLAY_POLICY_FIRST;
    cfg->corner = CORNER_TR;
 
    return cfg;
diff --git a/src/modules/notification/e_mod_main.h 
b/src/modules/notification/e_mod_main.h
index 45ca1e7..502d5e6 100644
--- a/src/modules/notification/e_mod_main.h
+++ b/src/modules/notification/e_mod_main.h
@@ -6,7 +6,7 @@
 /* Increment for Major Changes */
 #define MOD_CONFIG_FILE_EPOCH      1
 /* Increment for Minor Changes (ie: user doesn't need a new config) */
-#define MOD_CONFIG_FILE_GENERATION 0
+#define MOD_CONFIG_FILE_GENERATION 1
 #define MOD_CONFIG_FILE_VERSION    ((MOD_CONFIG_FILE_EPOCH * 1000000) + 
MOD_CONFIG_FILE_GENERATION)
 
 typedef enum   _Popup_Corner Popup_Corner;
@@ -14,12 +14,20 @@ typedef struct _Config Config;
 typedef struct _Popup_Data Popup_Data;
 
 enum _Popup_Corner
-  {
-    CORNER_TL,
-    CORNER_TR,
-    CORNER_BL,
-    CORNER_BR
-  };
+ {
+   CORNER_TL,
+   CORNER_TR,
+   CORNER_BL,
+   CORNER_BR
+ };
+
+typedef enum
+{
+   POPUP_DISPLAY_POLICY_FIRST,
+   POPUP_DISPLAY_POLICY_CURRENT,
+   POPUP_DISPLAY_POLICY_ALL,
+   POPUP_DISPLAY_POLICY_MULTI
+} Popup_Display_Policy;
 
 struct _Config 
 {
@@ -31,7 +39,7 @@ struct _Config
   int show_critical;
   int force_timeout;
   int ignore_replacement;
-  int dual_screen;
+  Popup_Display_Policy dual_screen;
   float timeout;
   Popup_Corner corner;
 
@@ -53,12 +61,13 @@ struct _Popup_Data
   unsigned id;
   E_Notification_Notify *notif;
   E_Popup *win;
+  Eina_List *mirrors;
   Evas *e;
   Evas_Object *theme;
   const char  *app_name;
   Evas_Object *app_icon;
   Ecore_Timer *timer;
-  E_Zone *zone;
+  Eina_Bool pending : 1;
 };
 
 
diff --git a/src/modules/notification/e_mod_popup.c 
b/src/modules/notification/e_mod_popup.c
index 9b9c528..8e88f13 100644
--- a/src/modules/notification/e_mod_popup.c
+++ b/src/modules/notification/e_mod_popup.c
@@ -12,7 +12,8 @@ static void        _notification_popup_del(unsigned int       
          id,
 static void        _notification_popdown(Popup_Data                  *popup,
                                          E_Notification_Notify_Closed_Reason 
reason);
 
-#define POPUP_LIMIT 7
+#define POPUP_GAP 10
+#define POPUP_TO_EDGE 15
 static int popups_displayed = 0;
 
 /* Util function protos */
@@ -157,42 +158,67 @@ _notification_theme_cb_find(Popup_Data *popup,
      }
 }
 
+static void
+_notification_popup_place_coords_get(int zw, int zh, int ow, int oh, int pos, 
int *x, int *y)
+{
+   /* XXX for now ignore placement requests */
+
+   switch (notification_cfg->corner)
+     {
+      case CORNER_TL:
+        *x = 15, *y = 15 + pos;
+        break;
+      case CORNER_TR:
+        *x = zw - (ow + 15), *y = 15 + pos;
+        break;
+      case CORNER_BL:
+        *x = 15, *y = (zh - oh) - (15 + pos);
+        break;
+      case CORNER_BR:
+        *x = zw - (ow + 15), *y = (zh - oh) - (15 + pos);
+        break;
+     }
+}
+
 static Popup_Data *
 _notification_popup_new(E_Notification_Notify *n, unsigned id)
 {
    E_Container *con;
    Popup_Data *popup;
    char buf[PATH_MAX];
-   const Eina_List *l, *screens;
-   E_Screen *scr;
+   Eina_List *l;
+   int pos = next_pos;
+   E_Manager *man;
    E_Zone *zone = NULL;
 
-   EINA_SAFETY_ON_TRUE_RETURN_VAL(popups_displayed > POPUP_LIMIT, NULL);
+   switch (notification_cfg->dual_screen)
+     {
+      case POPUP_DISPLAY_POLICY_FIRST:
+        man = eina_list_data_get(e_manager_list());
+        con = eina_list_data_get(man->containers);
+        zone = eina_list_data_get(con->zones);
+        break;
+      case POPUP_DISPLAY_POLICY_CURRENT:
+      case POPUP_DISPLAY_POLICY_ALL:
+        zone = e_util_zone_current_get(e_manager_current_get());
+        break;
+      case POPUP_DISPLAY_POLICY_MULTI:
+        if ((notification_cfg->corner == CORNER_BR) ||
+            (notification_cfg->corner == CORNER_TR))
+          zone = 
eina_list_last_data_get(e_util_container_current_get()->zones);
+        else
+          zone = eina_list_data_get(e_util_container_current_get()->zones);
+        break;
+     }
+
+   /* prevent popups if they would go offscreen
+    * FIXME: this can be improved...
+    */
+   if (next_pos + 30 >= zone->h) return NULL;
    popup = E_NEW(Popup_Data, 1);
    EINA_SAFETY_ON_NULL_RETURN_VAL(popup, NULL);
    popup->notif = n;
    popup->id = id;
-
-   con = e_container_current_get(e_manager_current_get());
-   screens = e_xinerama_screens_get();
-   if (notification_cfg->dual_screen &&
-       ((notification_cfg->corner == CORNER_BR) ||
-       (notification_cfg->corner == CORNER_TR)))
-     l = eina_list_last(screens);
-   else
-     l = screens;
-   if (l)
-     {
-        scr = eina_list_data_get(l);
-        EINA_SAFETY_ON_NULL_GOTO(scr, error);
-        EINA_LIST_FOREACH(con->zones, l, zone)
-          if ((int)zone->num == scr->screen) break;
-        if (zone && ((int)zone->num != scr->screen)) goto error;
-     }
-   if (!zone)
-     zone = e_zone_current_get(con);
-   popup->zone = zone;
-
    /* Create the popup window */
    popup->win = e_popup_new(zone, 0, 0, 0, 0);
    e_popup_name_set(popup->win, "_e_popup_notification");
@@ -227,66 +253,45 @@ _notification_popup_new(E_Notification_Notify *n, 
unsigned id)
    _notification_popup_refresh(popup);
    next_pos = _notification_popup_place(popup, next_pos);
    e_popup_show(popup->win);
+   if (notification_cfg->dual_screen == POPUP_DISPLAY_POLICY_ALL)
+     {
+        EINA_LIST_FOREACH(popup->win->zone->container->zones, l, zone)
+          {
+             Evas_Object *o;
+             int x, y;
+
+             if (zone == popup->win->zone) continue;
+             o = e_comp_win_image_mirror_add(popup->win->cw);
+             evas_object_data_set(o, "zone", zone);
+             evas_object_resize(o, popup->win->w, popup->win->h);
+             _notification_popup_place_coords_get(zone->w, zone->h, 
popup->win->w, popup->win->h, pos, &x, &y);
+             evas_object_move(o, zone->x + x, zone->y + y);
+             evas_object_show(o);
+             popup->mirrors = eina_list_append(popup->mirrors, o);
+          }
+     }
    popups_displayed++;
 
    return popup;
-error:
-   free(popup);
-   return NULL;
 }
 
 static int
 _notification_popup_place(Popup_Data *popup,
                           int         pos)
 {
-   int w, h, sw, sh;
-   int gap = 10;
-   int to_edge = 15;
-
-   sw = popup->zone->w;
-   sh = popup->zone->h;
-   evas_object_geometry_get(popup->theme, NULL, NULL, &w, &h);
-
-   /* XXX for now ignore placement requests */
+   int x, y;
+   Eina_List *l;
+   Evas_Object *o;
 
-   switch (notification_cfg->corner)
+   _notification_popup_place_coords_get(popup->win->zone->w, 
popup->win->zone->h, popup->win->w, popup->win->h, pos, &x, &y);
+   e_popup_move(popup->win, x, y);
+   EINA_LIST_FOREACH(popup->mirrors, l, o)
      {
-      case CORNER_TL:
-        e_popup_move(popup->win,
-                     to_edge, to_edge + pos);
-        break;
-      case CORNER_TR:
-        e_popup_move(popup->win,
-                     sw - (w + to_edge),
-                     to_edge + pos);
-        break;
-      case CORNER_BL:
-        e_popup_move(popup->win,
-                     to_edge,
-                     (sh - h) - (to_edge + pos));
-        break;
-      case CORNER_BR:
-        e_popup_move(popup->win,
-                     sw - (w + to_edge),
-                     (sh - h) - (to_edge + pos));
-        break;
-      default:
-        break;
+        E_Zone *zone = evas_object_data_get(o, "zone");
+        _notification_popup_place_coords_get(zone->w, zone->h, popup->win->w, 
popup->win->h, pos, &x, &y);
+        evas_object_move(o, zone->x + x, zone->y + y);
      }
-   return pos + h + gap;
-}
-
-static void
-_notification_popups_place(void)
-{
-   Popup_Data *popup;
-   Eina_List *l;
-   int pos = 0;
-
-   EINA_LIST_FOREACH(notification_cfg->popups, l, popup)
-     pos = _notification_popup_place(popup, pos);
-
-   next_pos = pos;
+   return pos + popup->win->h + 10;
 }
 
 static void
@@ -302,6 +307,7 @@ _notification_popup_refresh(Popup_Data *popup)
 
    if (popup->app_icon)
      {
+        e_popup_object_remove(popup->win, popup->app_icon);
         evas_object_del(popup->app_icon);
         popup->app_icon = NULL;
      }
@@ -403,6 +409,7 @@ _notification_popup_refresh(Popup_Data *popup)
         h = height;
      }
 
+   e_popup_object_add(popup->win, popup->app_icon);
    if ((w > width) || (h > height))
      {
         int v;
@@ -413,7 +420,6 @@ _notification_popup_refresh(Popup_Data *popup)
    edje_extern_object_min_size_set(popup->app_icon, w, h);
    edje_extern_object_max_size_set(popup->app_icon, w, h);
 
-   edje_object_calc_force(popup->theme);
    edje_object_part_swallow(popup->theme, "notification.swallow.app_icon", 
                             popup->app_icon);
    edje_object_signal_emit(popup->theme, "notification,icon", "notification");
@@ -424,12 +430,9 @@ _notification_popup_refresh(Popup_Data *popup)
    /* Compute the new size of the popup */
    edje_object_calc_force(popup->theme);
    edje_object_size_min_calc(popup->theme, &w, &h);
-   w = MIN(w, popup->zone->w / 2);
-   h = MIN(h, popup->zone->h / 2);
+   w = MIN(w, popup->win->zone->w / 2);
+   h = MIN(h, popup->win->zone->h / 2);
    e_popup_resize(popup->win, w, h);
-   evas_object_resize(popup->theme, w, h);
-
-   _notification_popups_place();
 }
 
 static Popup_Data *
@@ -446,8 +449,7 @@ _notification_popup_find(unsigned int id)
 }
 
 static void
-_notification_popup_del(unsigned int                 id,
-                        E_Notification_Notify_Closed_Reason reason)
+_notification_reshuffle_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, 
Evas_Object *obj, void *event_info EINA_UNUSED)
 {
    Popup_Data *popup;
    Eina_List *l, *l2;
@@ -455,30 +457,52 @@ _notification_popup_del(unsigned int                 id,
 
    EINA_LIST_FOREACH_SAFE(notification_cfg->popups, l, l2, popup)
      {
-        if (popup->id == id)
+        if (popup->theme == obj)
           {
-             _notification_popdown(popup, reason);
+             popup->pending = 0;
+             _notification_popdown(popup, 0);
              notification_cfg->popups = 
eina_list_remove_list(notification_cfg->popups, l);
           }
         else
           pos = _notification_popup_place(popup, pos);
      }
-
    next_pos = pos;
 }
 
 static void
+_notification_popup_del(unsigned int                 id,
+                        E_Notification_Notify_Closed_Reason reason)
+{
+   Popup_Data *popup;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(notification_cfg->popups, l, popup)
+     {
+        if (popup->id == id)
+          {
+             popup->pending = 1;
+             evas_object_event_callback_add(popup->theme, EVAS_CALLBACK_DEL, 
_notification_reshuffle_cb, NULL);
+             _notification_popdown(popup, reason);
+             break;
+          }
+     }
+}
+
+static void
 _notification_popdown(Popup_Data                  *popup,
                       E_Notification_Notify_Closed_Reason reason)
 {
-   if (popup->timer) ecore_timer_del(popup->timer);
-   e_popup_hide(popup->win);
-   popups_displayed--;
-   evas_object_del(popup->app_icon);
-   evas_object_del(popup->theme);
+   E_FREE_FUNC(popup->timer, ecore_timer_del);
+   popup->mirrors = eina_list_free(popup->mirrors);
    e_object_del(E_OBJECT(popup->win));
-   e_notification_notify_close(popup->notif, reason);
-   e_notification_notify_free(popup->notif);
+   if (popup->notif)
+     {
+        e_notification_notify_close(popup->notif, reason);
+        e_notification_notify_free(popup->notif);
+     }
+   popup->notif = NULL;
+   if (popup->pending) return;
+   popups_displayed--;
    free(popup);
 }
 

-- 

------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter

Reply via email to