From 6371da9a61ef4fb98a84e145ab1e3d65a15ab252 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Thu, 18 Apr 2013 15:50:49 +0100 Subject: [PATCH] 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 | 208 +++++++++++++----------- 6 files changed, 186 insertions(+), 105 deletions(-) diff --git a/ChangeLog b/ChangeLog index 52ceaafb5..279bff5f9 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 c01ae23da..f055c17cb 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 17329a29a..97c05306e 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 b1a3f5648..3ba02984c 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 45ca1e718..502d5e6c5 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 9b9c52847..8e88f13bd 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 */ - - switch (notification_cfg->corner) - { - 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; - } - return pos + h + gap; -} - -static void -_notification_popups_place(void) -{ - Popup_Data *popup; + int x, y; Eina_List *l; - int pos = 0; + Evas_Object *o; - EINA_LIST_FOREACH(notification_cfg->popups, l, popup) - pos = _notification_popup_place(popup, pos); - - next_pos = pos; + _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) + { + 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 + 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); }