diff --git a/src/bin/e_client.h b/src/bin/e_client.h index ea43b1835..4308c999b 100644 --- a/src/bin/e_client.h +++ b/src/bin/e_client.h @@ -671,6 +671,7 @@ struct E_Client Eina_Bool dialog : 1; Eina_Bool tooltip : 1; Eina_Bool redirected : 1; + Eina_Bool unredirected_single : 1; //window has been selectively unredirected Eina_Bool shape_changed : 1; Eina_Bool layer_block : 1; // client is doing crazy stuff and should not be relayered in protocol Eina_Bool ignored : 1; // client is comp-ignored diff --git a/src/bin/e_comp.c b/src/bin/e_comp.c index a49768943..4f744a3f8 100644 --- a/src/bin/e_comp.c +++ b/src/bin/e_comp.c @@ -1020,6 +1020,12 @@ _e_comp_act_opacity_set_go(E_Object * obj __UNUSED__, const char *params) evas_object_color_set(o, opacity, opacity, opacity, opacity); } +static void +_e_comp_act_redirect_toggle_go(E_Object * obj EINA_UNUSED, const char *params EINA_UNUSED) +{ + e_comp_client_redirect_toggle(e_client_focused_get()); +} + ////////////////////////////////////////////////////////////////////////// EINTERN Eina_Bool @@ -1088,6 +1094,11 @@ e_comp_init(void) e_action_predef_name_set(N_("Compositor"), N_("Set current window opacity"), "opacity_set", "255", "syntax: number between 0-255 to set for transparent-opaque", 1); + act = e_action_add("redirect_toggle"); + act->func.go = _e_comp_act_redirect_toggle_go; + e_action_predef_name_set(N_("Compositor"), + N_("Toggle focused client's redirect state"), "redirect_toggle", + NULL, NULL, 0); actions = eina_list_append(actions, act); } @@ -1753,3 +1764,15 @@ e_comp_button_bindings_grab_all(void) if (c->bindings_grab_cb) c->bindings_grab_cb(c); } + +EAPI void +e_comp_client_redirect_toggle(E_Client *ec) +{ + EINA_SAFETY_ON_NULL_RETURN(ec); + if (!conf->enable_advanced_features) return; + if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_X) return; + ec->unredirected_single = !ec->unredirected_single; + e_client_redirected_set(ec, !ec->redirected); + ec->no_shape_cut = !ec->redirected; + e_comp_shape_queue(ec->comp); +} diff --git a/src/bin/e_comp.h b/src/bin/e_comp.h index 0032d547a..dd869131c 100644 --- a/src/bin/e_comp.h +++ b/src/bin/e_comp.h @@ -163,6 +163,7 @@ EAPI E_Comp *e_comp_evas_find(const Evas *e); EAPI void e_comp_button_bindings_grab_all(void); EAPI void e_comp_button_bindings_ungrab_all(void); +EAPI void e_comp_client_redirect_toggle(E_Client *ec); EINTERN Evas_Object *e_comp_style_selector_create(Evas *evas, const char **source); EAPI E_Config_Dialog *e_int_config_comp(E_Comp *comp, const char *params); diff --git a/src/bin/e_comp_x.c b/src/bin/e_comp_x.c index c29130573..80b4eaad4 100644 --- a/src/bin/e_comp_x.c +++ b/src/bin/e_comp_x.c @@ -595,6 +595,7 @@ _e_comp_x_client_stack(E_Client *ec) Eina_List *l; if (ec->override && (!ec->internal)) return; //can't restack these + if (ec->comp_data->unredirected_single) return; ecore_x_window_shadow_tree_flush(); @@ -786,7 +787,7 @@ _e_comp_x_evas_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UN { E_Client *ec = data; - if (ec->comp_data->moving) + if (ec->comp_data->moving && (!ec->comp_data->unredirected_single)) { if (ec->comp_data->move_counter++ < MOVE_COUNTER_LIMIT) return; ec->comp_data->move_counter = 0; @@ -855,6 +856,9 @@ _e_comp_x_evas_hide_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UN EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp) evas_object_hide(tmp->frame); + if (ec->unredirected_single) + ecore_x_window_hide(_e_comp_x_client_window_get(ec)); + if (e_comp_config_get()->send_flush) ecore_x_e_comp_flush_send(e_client_util_pwin_get(ec)); if (e_comp_config_get()->send_dump) @@ -874,6 +878,8 @@ _e_comp_x_evas_show_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UN ecore_x_window_shadow_tree_flush(); if (!ec->comp_data->need_reparent) ecore_x_window_show(win); + if (ec->unredirected_single) + ecore_x_window_show(_e_comp_x_client_window_get(ec)); e_hints_window_visible_set(ec); ecore_x_window_prop_card32_set(win, E_ATOM_MAPPED, &visible, 1); @@ -1222,7 +1228,7 @@ _e_comp_x_hide(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Windo } return ECORE_CALLBACK_PASS_ON; } - if (!ec->visible) + if ((!ec->visible) || (ec->hidden && ec->unredirected_single)) { //INF("IGNORED"); return ECORE_CALLBACK_PASS_ON; @@ -4003,12 +4009,18 @@ static void _e_comp_x_hook_client_redirect(void *d EINA_UNUSED, E_Client *ec) { E_COMP_X_PIXMAP_CHECK; - if (ec->comp->nocomp) + if (ec->comp_data->unredirected_single) + { + ecore_x_composite_redirect_window(_e_comp_x_client_window_get(ec), ECORE_X_COMPOSITE_UPDATE_MANUAL); + ec->comp_data->unredirected_single = 0; + } + else if (ec->comp->nocomp) { /* first window */ ec->comp->nocomp = 0; ecore_x_composite_redirect_subwindows(ec->comp->man->root, ECORE_X_COMPOSITE_UPDATE_MANUAL); - ecore_x_window_show(ec->comp->win); + ecore_x_window_reparent(_e_comp_x_client_window_get(ec), ec->comp->man->root, ec->client.x, ec->client.y); + _e_comp_x_client_stack(ec); } if (!ec->comp_data->damage) _e_comp_x_client_damage_add(ec); @@ -4027,6 +4039,13 @@ _e_comp_x_hook_client_unredirect(void *d EINA_UNUSED, E_Client *ec) ecore_x_damage_free(ec->comp_data->damage); ec->comp_data->damage = 0; + if (ec->unredirected_single && (!ec->comp_data->unredirected_single)) + { + ecore_x_composite_unredirect_window(_e_comp_x_client_window_get(ec), ECORE_X_COMPOSITE_UPDATE_MANUAL); + ecore_x_window_reparent(_e_comp_x_client_window_get(ec), ec->comp->win, ec->client.x, ec->client.y); + ecore_x_window_raise(_e_comp_x_client_window_get(ec)); + ec->comp_data->unredirected_single = 1; + } if (!ec->comp->nocomp) return; //wait for it... ecore_x_composite_unredirect_subwindows(ec->comp->man->root, ECORE_X_COMPOSITE_UPDATE_MANUAL); ecore_x_window_hide(ec->comp->win); diff --git a/src/bin/e_comp_x.h b/src/bin/e_comp_x.h index 13d828cdd..2b7172908 100644 --- a/src/bin/e_comp_x.h +++ b/src/bin/e_comp_x.h @@ -100,6 +100,7 @@ struct _E_Comp_Client_Data Eina_Bool set_win_type : 1; Eina_Bool frame_update : 1; Eina_Bool evas_init : 1; + Eina_Bool unredirected_single : 1; }; EINTERN Eina_Bool e_comp_x_init(void); diff --git a/src/bin/e_int_client_menu.c b/src/bin/e_int_client_menu.c index f1b04a63d..31d94ec84 100644 --- a/src/bin/e_int_client_menu.c +++ b/src/bin/e_int_client_menu.c @@ -5,6 +5,7 @@ static void _e_client_menu_cb_locks(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_client_menu_cb_remember(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_client_menu_cb_borderless(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_client_menu_cb_border(void *data, E_Menu *m, E_Menu_Item *mi); +static void _e_client_menu_cb_redirect_set(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi EINA_UNUSED); static void _e_client_menu_cb_close(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_client_menu_cb_iconify(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_client_menu_cb_kill(void *data, E_Menu *m, E_Menu_Item *mi); @@ -200,6 +201,15 @@ e_int_client_menu_create(E_Client *ec) "e/widgets/border/default/borderless"); } + if (e_comp_config_get()->enable_advanced_features && (e_pixmap_type_get(ec->pixmap) == E_PIXMAP_TYPE_X)) + { + mi = e_menu_item_new(m); + e_menu_item_check_set(mi, 1); + e_menu_item_label_set(mi, _("Unredirected")); + e_menu_item_toggle_set(mi, !ec->redirected); + e_menu_item_callback_set(mi, _e_client_menu_cb_redirect_set, ec); + } + if (!ec->lock_close) { mi = e_menu_item_new(m); @@ -317,6 +327,13 @@ _e_client_menu_cb_borderless(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi) ec->borderless = mi->toggle; } + +static void +_e_client_menu_cb_redirect_set(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi EINA_UNUSED) +{ + e_comp_client_redirect_toggle(data); +} + static void _e_client_menu_cb_close(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__) {