#include "e_mod_tiling.h" /* HACK: Needed to get subobjs of the widget. Is there a better way? */ typedef struct _E_Widget_Smart_Data E_Widget_Smart_Data; struct _E_Widget_Smart_Data { Evas_Object *parent_obj; Evas_Coord x, y, w, h; Evas_Coord minw, minh; Eina_List *subobjs; }; /* Some defines to make coding with the e_widget_* easier for * configuration panel */ #define RADIO(title, value, radiogroup) \ e_widget_radio_add(evas, _(title), value, radiogroup) #define LIST_ADD(list, object) \ e_widget_list_object_append(list, object, 1, 1, 0.5) struct _Config_vdesk * get_vdesk(Eina_List *vdesks, int x, int y, unsigned int zone_num) { for (Eina_List *l = vdesks; l; l = l->next) { struct _Config_vdesk *vd = l->data; if (!vd) continue; if (vd->nb_stacks < 0 || vd->nb_stacks > TILING_MAX_STACKS) vd->nb_stacks = 0; if (vd->x == x && vd->y == y && vd->zone_num == zone_num) return vd; } return NULL; } /* * Fills the E_Config_Dialog-struct with the data currently in use * */ static void * _create_data(E_Config_Dialog *cfd __UNUSED__) { E_Config_Dialog_Data *cfdata = E_NEW(E_Config_Dialog_Data, 1); /* Because we save a lot of lines here by using memcpy, * the structs have to be ordered the same */ memcpy(cfdata, tiling_g.config, sizeof(Config)); cfdata->config.keyhints = strdup(tiling_g.config->keyhints); /* Handle things which can't be easily memcpy'd */ cfdata->config.vdesks = NULL; for (Eina_List *l = tiling_g.config->vdesks; l; l = l->next) { struct _Config_vdesk *vd = l->data, *newvd; if (!vd) continue; newvd = E_NEW(struct _Config_vdesk, 1); newvd->x = vd->x; newvd->y = vd->y; newvd->zone_num = vd->zone_num; newvd->nb_stacks = vd->nb_stacks; newvd->use_rows = vd->use_rows; cfdata->config.vdesks = eina_list_append(cfdata->config.vdesks, newvd); } return cfdata; } static void _free_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata) { eina_list_free(cfdata->config.vdesks); free(cfdata->config.keyhints); free(cfdata); } static void _fill_zone_config(E_Zone *zone, E_Config_Dialog_Data *cfdata) { Evas *evas = cfdata->evas; /* Clear old entries first */ evas_object_del(cfdata->o_desklist); cfdata->o_desklist = e_widget_list_add(evas, 1, 0); for (int i = 0; i < zone->desk_y_count * zone->desk_x_count; i++) { E_Desk *desk = zone->desks[i]; struct _Config_vdesk *vd; Evas_Object *list, *slider, *radio; E_Radio_Group *rg; if (!desk) continue; vd = get_vdesk(cfdata->config.vdesks, desk->x, desk->y, zone->num); if (!vd) { vd = E_NEW(struct _Config_vdesk, 1); vd->x = desk->x; vd->y = desk->y; vd->zone_num = zone->num; vd->nb_stacks = 0; vd->use_rows = 0; cfdata->config.vdesks = eina_list_append(cfdata->config.vdesks, vd); } list = e_widget_list_add(evas, false, true); LIST_ADD(list, e_widget_label_add(evas, desk->name)); slider = e_widget_slider_add(evas, 1, 0, _("%1.0f"), 0.0, 8.0, 1.0, 0, NULL, &vd->nb_stacks, 150); LIST_ADD(list, slider); rg = e_widget_radio_group_new(&vd->use_rows); radio = e_widget_radio_add(evas, _("columns"), 0, rg); LIST_ADD(list, radio); radio = e_widget_radio_add(evas, _("rows"), 1, rg); LIST_ADD(list, radio); LIST_ADD(cfdata->o_desklist, list); } /* Get the correct sizes of desklist and scrollframe */ LIST_ADD(cfdata->osf, cfdata->o_desklist); } static void _cb_zone_change(void *data, Evas_Object *obj __UNUSED__) { int n; E_Config_Dialog_Data *cfdata = data; E_Zone *zone; if (!cfdata || !cfdata->o_zonelist) return; n = e_widget_ilist_selected_get(cfdata->o_zonelist); zone = e_widget_ilist_nth_data_get(cfdata->o_zonelist, n); if (!zone) return; _fill_zone_config(zone, cfdata); } static Evas_Object * _basic_create_widgets(E_Config_Dialog *cfd __UNUSED__, Evas *evas, E_Config_Dialog_Data *cfdata) { Evas_Object *o, *oc, *of; E_Container *con = e_container_current_get(e_manager_current_get()); E_Zone *zone; o = e_widget_list_add(evas, 0, 0); /* General settings */ of = e_widget_framelist_add(evas, _("General"), 0); e_widget_framelist_object_append(of, e_widget_check_add(evas, _("Tile dialog windows as well"), &cfdata->config.tile_dialogs)); e_widget_framelist_object_append(of, e_widget_check_add(evas, _("Show window titles"), &cfdata->config.show_titles)); oc = e_widget_list_add(evas, false, true); e_widget_list_object_append(oc, e_widget_label_add(evas, _("Key hints")), 1, 0, 0.5); e_widget_list_object_append(oc, e_widget_entry_add(evas, &cfdata->config.keyhints, NULL, NULL, NULL), 1, 1, 0.5); e_widget_framelist_object_append(of, oc); LIST_ADD(o, of); /* Virtual desktop settings */ of = e_widget_framelist_add(evas, _("Virtual Desktops"), 0); e_widget_label_add(evas, _("Number of columns used to tile per desk" " (0 → tiling disabled):")); cfdata->osf = e_widget_list_add(evas, 0, 1); /* Zone list */ cfdata->o_zonelist = e_widget_ilist_add(evas, 0, 0, NULL); e_widget_ilist_multi_select_set(cfdata->o_zonelist, false); e_widget_size_min_set(cfdata->o_zonelist, 100, 100); e_widget_on_change_hook_set(cfdata->o_zonelist, _cb_zone_change, cfdata); for (Eina_List *l = con->zones; l; l = l->next) { if (!(zone = l->data)) continue; e_widget_ilist_append(cfdata->o_zonelist, NULL, zone->name, NULL, zone, NULL); } e_widget_ilist_go(cfdata->o_zonelist); e_widget_ilist_thaw(cfdata->o_zonelist); LIST_ADD(cfdata->osf, cfdata->o_zonelist); /* List of individual tiling modes */ cfdata->evas = evas; _fill_zone_config(con->zones->data, cfdata); e_widget_ilist_selected_set(cfdata->o_zonelist, 0); e_widget_framelist_object_append(of, cfdata->osf); LIST_ADD(o, of); return o; } static int _basic_apply_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata) { struct _Config_vdesk *vd; tiling_g.config->tile_dialogs = cfdata->config.tile_dialogs; tiling_g.config->show_titles = cfdata->config.show_titles; if (strcmp(tiling_g.config->keyhints, cfdata->config.keyhints)) { free(tiling_g.config->keyhints); if (!cfdata->config.keyhints || !*cfdata->config.keyhints) { tiling_g.config->keyhints = strdup(tiling_g.default_keyhints); } else { char *c = cfdata->config.keyhints; int len = strlen(cfdata->config.keyhints); /* Remove duplicates */ while (*c) { char *f = c + 1; while ((f = strchr(f, *c))) { *f = cfdata->config.keyhints[--len]; cfdata->config.keyhints[len] = '\0'; } c++; } tiling_g.config->keyhints = strdup(cfdata->config.keyhints); } } /* Check if the layout for one of the vdesks has changed */ for (Eina_List *l = tiling_g.config->vdesks; l; l = l->next) { struct _Config_vdesk *newvd; vd = l->data; if (!vd) continue; if (!(newvd = get_vdesk(cfdata->config.vdesks, vd->x, vd->y, vd->zone_num))) { change_desk_conf(vd); continue; } if (newvd->nb_stacks != vd->nb_stacks || newvd->use_rows != vd->use_rows) { DBG("number of columns for (%d, %d, %d) changed from %d|%d" " to %d|%d", vd->x, vd->y, vd->zone_num, vd->nb_stacks, vd->use_rows, newvd->nb_stacks, newvd->use_rows); change_desk_conf(newvd); free(vd); l->data = NULL; } } for (Eina_List *l = cfdata->config.vdesks; l; l = l->next) { vd = l->data; if (!vd) continue; if (!get_vdesk(tiling_g.config->vdesks, vd->x, vd->y, vd->zone_num)) { change_desk_conf(vd); continue; } } EINA_LIST_FREE(tiling_g.config->vdesks, vd) { free(vd); } tiling_g.config->vdesks = cfdata->config.vdesks; cfdata->config.vdesks = NULL; /* we don't want this list to be freed */ e_tiling_update_conf(); e_config_save_queue(); return EINA_TRUE; } E_Config_Dialog * e_int_config_tiling_module(E_Container *con, const char *params __UNUSED__) { E_Config_Dialog *cfd; E_Config_Dialog_View *v; char buf[PATH_MAX]; if (e_config_dialog_find("E", "windows/tiling")) return NULL; v = E_NEW(E_Config_Dialog_View, 1); v->create_cfdata = _create_data; v->free_cfdata = _free_data; v->basic.apply_cfdata = _basic_apply_data; v->basic.create_widgets = _basic_create_widgets; snprintf(buf, sizeof(buf), "%s/e-module-tiling.edj", e_module_dir_get(tiling_g.module)); cfd = e_config_dialog_new(con, _("Tiling Configuration"), "E", "windows/tiling", buf, 0, v, NULL); return cfd; }