diff --git a/TODO b/TODO index faf30925d..e089bd0f6 100644 --- a/TODO +++ b/TODO @@ -312,7 +312,6 @@ TODO: * set governor for ac vs battery (or powerstate levels) * set pstate min and max for ac vs battery (or power state levels) * saving power - * when screen blanks set all apps to hidden state * have new property/atom for hidden but visible in a pager orsomething * efl - dont suspend render when this is the case but drop fps to 1/4 * look into x grabserver for long periods (eg 1s) then ungrab for diff --git a/src/bin/e_client.c b/src/bin/e_client.c index c2a1bd51e..1d7659964 100644 --- a/src/bin/e_client.c +++ b/src/bin/e_client.c @@ -1775,6 +1775,11 @@ _e_client_eval(E_Client *ec) if ((ec->new_client) && (!e_client_util_ignored_get(ec)) && (ec->zone)) { + if (e_comp->frozen) + { + ec->frozen = EINA_TRUE; + e_hints_window_state_set(ec); + } _e_client_event_simple(ec, E_EVENT_CLIENT_ADD); e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh); /* enforce wm size hints for initial sizing */ diff --git a/src/bin/e_client.h b/src/bin/e_client.h index 4725ba53c..af2823eb8 100644 --- a/src/bin/e_client.h +++ b/src/bin/e_client.h @@ -656,6 +656,8 @@ struct E_Client unsigned int stolen E_BITFIELD; + unsigned int frozen E_BITFIELD; + unsigned int internal E_BITFIELD; unsigned int internal_no_remember E_BITFIELD; unsigned int internal_no_reopen E_BITFIELD; diff --git a/src/bin/e_comp.h b/src/bin/e_comp.h index 347cbccb3..5bdfe45c3 100644 --- a/src/bin/e_comp.h +++ b/src/bin/e_comp.h @@ -190,6 +190,8 @@ struct _E_Comp Eina_Bool rendering E_BITFIELD; // we've received a pre-render callback but no post-render yet. Eina_Bool updating E_BITFIELD; // running client updates + + Eina_Bool frozen E_BITFIELD; // frozen - when power save freeze mode is on }; diff --git a/src/bin/e_comp_x.c b/src/bin/e_comp_x.c index fc740e7b5..dcdb49e8c 100644 --- a/src/bin/e_comp_x.c +++ b/src/bin/e_comp_x.c @@ -2520,6 +2520,72 @@ _e_comp_x_mapping_change(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_E return ECORE_CALLBACK_PASS_ON; } +static Eina_Bool +_e_comp_x_powersave(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) +{ + E_Event_Powersave_Update *ev = event; + Eina_List *l; + E_Client *ec; + + if (e_comp->comp_type == E_PIXMAP_TYPE_WL) return ECORE_CALLBACK_PASS_ON; + switch (ev->mode) + { + case E_POWERSAVE_MODE_NONE: + case E_POWERSAVE_MODE_LOW: + case E_POWERSAVE_MODE_MEDIUM: + case E_POWERSAVE_MODE_HIGH: + case E_POWERSAVE_MODE_EXTREME: + if (e_comp->frozen) + { + e_comp->frozen = EINA_FALSE; + EINA_LIST_FOREACH(e_comp->clients, l, ec) + { + if (ec->frozen) + { + ec->frozen = EINA_FALSE; + // XXX: update props + if (e_client_has_xwindow(ec)) + { + if (!ec->iconic) + { + ecore_x_icccm_state_set(e_client_util_win_get(ec), + ECORE_X_WINDOW_STATE_HINT_NORMAL); + } + e_hints_window_state_set(ec); + } + } + } + } + break; + case E_POWERSAVE_MODE_FREEZE: + if (!e_comp->frozen) + { + e_comp->frozen = EINA_TRUE; + EINA_LIST_FOREACH(e_comp->clients, l, ec) + { + if (!ec->frozen) + { + ec->frozen = EINA_TRUE; + // XXX: update props + if (e_client_has_xwindow(ec)) + { + if (!ec->iconic) + { + ecore_x_icccm_state_set(e_client_util_win_get(ec), + ECORE_X_WINDOW_STATE_HINT_ICONIC); + } + e_hints_window_state_set(ec); + } + } + } + } + break; + default: + break; + } + return ECORE_CALLBACK_PASS_ON; +} + static void _e_comp_x_mouse_in_job(void *d EINA_UNUSED) { @@ -6043,6 +6109,8 @@ e_comp_x_init(void) e_error_message_show(_("Enlightenment cannot initialize the XSettings system.\n")); E_LIST_HANDLER_APPEND(handlers, E_EVENT_RANDR_CHANGE, _e_comp_x_randr_change, NULL); + E_LIST_HANDLER_APPEND(handlers, E_EVENT_POWERSAVE_UPDATE, _e_comp_x_powersave, NULL); + ecore_x_sync(); _x_idle_flush = ecore_idle_enterer_add(_e_comp_x_flusher, NULL); diff --git a/src/bin/e_hints.c b/src/bin/e_hints.c index a7f010096..1e9bc08cd 100644 --- a/src/bin/e_hints.c +++ b/src/bin/e_hints.c @@ -599,7 +599,7 @@ e_hints_window_state_set(E_Client *ec) if (ec->netwm.state.skip_pager) state[num++] = ECORE_X_WINDOW_STATE_SKIP_PAGER; } - if (ec->netwm.state.hidden) + if ((ec->netwm.state.hidden) || (ec->frozen)) state[num++] = ECORE_X_WINDOW_STATE_HIDDEN; if (ec->netwm.state.fullscreen) state[num++] = ECORE_X_WINDOW_STATE_FULLSCREEN; @@ -1261,11 +1261,18 @@ e_hints_window_visible_set(E_Client *ec) (void)ec; #else if (!e_client_has_xwindow(ec)) return; - if (ec->icccm.state != ECORE_X_WINDOW_STATE_HINT_WITHDRAWN) + if ((ec->icccm.state != ECORE_X_WINDOW_STATE_HINT_WITHDRAWN) && + (!ec->frozen)) { ec->icccm.state = ECORE_X_WINDOW_STATE_HINT_NORMAL; ecore_x_icccm_state_set(e_client_util_win_get(ec), ECORE_X_WINDOW_STATE_HINT_NORMAL); } + else if (ec->frozen) + { + if (ec->icccm.state != ECORE_X_WINDOW_STATE_HINT_WITHDRAWN) + ec->icccm.state = ECORE_X_WINDOW_STATE_HINT_NORMAL; + ecore_x_icccm_state_set(e_client_util_win_get(ec), ECORE_X_WINDOW_STATE_HINT_ICONIC); + } if (ec->netwm.state.hidden) { ec->netwm.update.state = 1; @@ -1288,6 +1295,12 @@ e_hints_window_iconic_set(E_Client *ec) ec->icccm.state = ECORE_X_WINDOW_STATE_HINT_ICONIC; ecore_x_icccm_state_set(e_client_util_win_get(ec), ECORE_X_WINDOW_STATE_HINT_ICONIC); } + else if (ec->frozen) + { + if (ec->icccm.state != ECORE_X_WINDOW_STATE_HINT_WITHDRAWN) + ec->icccm.state = ECORE_X_WINDOW_STATE_HINT_ICONIC; + ecore_x_icccm_state_set(e_client_util_win_get(ec), ECORE_X_WINDOW_STATE_HINT_ICONIC); + } if (!ec->netwm.state.hidden) { ec->netwm.update.state = 1;