1 #include "e_mod_tiling.h"
2
3 /* HACK: Needed to get subobjs of the widget. Is there a better way? */
4 typedef struct _E_Widget_Smart_Data E_Widget_Smart_Data;
5
6 struct _E_Widget_Smart_Data
7 {
8 Evas_Object *parent_obj;
9 Evas_Coord x, y, w, h;
10 Evas_Coord minw, minh;
11 Eina_List *subobjs;
12 };
13
14 static void
_open_browser_help_cb(void * data EINA_UNUSED,void * obj EINA_UNUSED)15 _open_browser_help_cb(void *data EINA_UNUSED, void *obj EINA_UNUSED)
16 {
17 e_util_open("https://phab.enlightenment.org/w/emodules/tiling2/", NULL);
18 }
19
20 /* Some defines to make coding with the e_widget_* easier for configuration
21 * panel */
22 #define RADIO(title, value, radiogroup) \
23 e_widget_radio_add(evas, _(title), value, radiogroup)
24 #define LIST_ADD(list, object) \
25 e_widget_list_object_append(list, object, 1, 1, 0.5)
26
27 struct _Config_vdesk *
get_vdesk(Eina_List * vdesks,int x,int y,unsigned int zone_num)28 get_vdesk(Eina_List *vdesks, int x, int y, unsigned int zone_num)
29 {
30 Eina_List *l;
31
32 for (l = vdesks; l; l = l->next)
33 {
34 struct _Config_vdesk *vd = l->data;
35
36 if (!vd)
37 continue;
38 if (vd->nb_stacks < 0 || vd->nb_stacks > 1)
39 vd->nb_stacks = 0;
40 if (vd->x == x && vd->y == y && vd->zone_num == zone_num)
41 return vd;
42 }
43
44 return NULL;
45 }
46
47 /*
48 * Fills the E_Config_Dialog-struct with the data currently in use
49 *
50 */
51 static void *
_create_data(E_Config_Dialog * cfd EINA_UNUSED)52 _create_data(E_Config_Dialog *cfd EINA_UNUSED)
53 {
54 E_Config_Dialog_Data *cfdata;
55 Eina_List *l;
56
57 cfdata = E_NEW(E_Config_Dialog_Data, 1);
58
59 /* Because we save a lot of lines here by using memcpy, the structs have to
60 * be ordered the same */
61 memcpy(cfdata, tiling_g.config, sizeof(Config));
62
63 /* Handle things which can't be easily memcpy'd */
64 cfdata->config.vdesks = NULL;
65
66 for (l = tiling_g.config->vdesks; l; l = l->next)
67 {
68 struct _Config_vdesk *vd = l->data, *newvd;
69
70 if (!vd)
71 continue;
72
73 newvd = E_NEW(struct _Config_vdesk, 1);
74
75 newvd->x = vd->x;
76 newvd->y = vd->y;
77 newvd->zone_num = vd->zone_num;
78 newvd->nb_stacks = vd->nb_stacks;
79
80 EINA_LIST_APPEND(cfdata->config.vdesks, newvd);
81 }
82
83 return cfdata;
84 }
85
86 static void
_free_data(E_Config_Dialog * cfd EINA_UNUSED,E_Config_Dialog_Data * cfdata)87 _free_data(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata)
88 {
89 eina_list_free(cfdata->config.vdesks);
90 free(cfdata);
91 }
92
93 static void
_fill_zone_config(E_Zone * zone,E_Config_Dialog_Data * cfdata)94 _fill_zone_config(E_Zone *zone, E_Config_Dialog_Data *cfdata)
95 {
96 Evas *evas;
97 int i;
98
99 evas = cfdata->evas;
100
101 /* Clear old entries first */
102 evas_object_del(cfdata->o_desklist);
103
104 cfdata->o_desklist = e_widget_list_add(evas, 1, 0);
105
106 for (i = 0; i < zone->desk_y_count * zone->desk_x_count; i++)
107 {
108 E_Desk *desk = zone->desks[i];
109 struct _Config_vdesk *vd;
110 Evas_Object *list, *checkbox;
111
112 if (!desk)
113 continue;
114
115 vd = get_vdesk(cfdata->config.vdesks, desk->x, desk->y, zone->num);
116 if (!vd)
117 {
118 vd = E_NEW(struct _Config_vdesk, 1);
119
120 vd->x = desk->x;
121 vd->y = desk->y;
122 vd->zone_num = zone->num;
123 vd->nb_stacks = 0;
124
125 EINA_LIST_APPEND(cfdata->config.vdesks, vd);
126 }
127
128 list = e_widget_list_add(evas, false, true);
129
130 LIST_ADD(list, e_widget_label_add(evas, desk->name));
131 checkbox = e_widget_check_add(evas, "", &vd->nb_stacks);
132 LIST_ADD(list, checkbox);
133
134 LIST_ADD(cfdata->o_desklist, list);
135 }
136
137 /* Get the correct sizes of desklist and scrollframe */
138 LIST_ADD(cfdata->osf, cfdata->o_desklist);
139 }
140
141 static void
_cb_zone_change(void * data,Evas_Object * obj EINA_UNUSED)142 _cb_zone_change(void *data, Evas_Object *obj EINA_UNUSED)
143 {
144 int n;
145 E_Config_Dialog_Data *cfdata = data;
146 E_Zone *zone;
147
148 if (!cfdata || !cfdata->o_zonelist)
149 return;
150
151 n = e_widget_ilist_selected_get(cfdata->o_zonelist);
152 zone = e_widget_ilist_nth_data_get(cfdata->o_zonelist, n);
153 if (!zone)
154 return;
155 _fill_zone_config(zone, cfdata);
156 }
157
158 static Evas_Object *
_basic_create_widgets(E_Config_Dialog * cfd EINA_UNUSED,Evas * evas,E_Config_Dialog_Data * cfdata)159 _basic_create_widgets(E_Config_Dialog *cfd EINA_UNUSED, Evas *evas,
160 E_Config_Dialog_Data *cfdata)
161 {
162 Evas_Object *o, *oc, *of, *slider;
163 E_Zone *zone;
164 Eina_List *l;
165
166 o = e_widget_list_add(evas, 0, 0);
167
168 /* General settings */
169 of = e_widget_framelist_add(evas, _("General"), 0);
170 e_widget_framelist_object_append(of, e_widget_check_add(evas,
171 _("Show window titles"), &cfdata->config.show_titles));
172 e_widget_framelist_object_append(of, e_widget_check_add(evas,
173 _("Tile dialog windows"), &cfdata->config.tile_dialogs));
174 e_widget_framelist_object_append(of, e_widget_check_add(evas,
175 _("Enable floating split-mode"), &cfdata->config.have_floating_mode));
176
177 LIST_ADD(o, of);
178
179 /* Virtual desktop settings */
180 of = e_widget_label_add(evas, _("Enable/disable tiling per desktop."));
181 LIST_ADD(o, of);
182 of = e_widget_framelist_add(evas, _("Virtual Desktops"), 0);
183 cfdata->osf = e_widget_list_add(evas, 0, 1);
184
185 /* Zone list */
186 cfdata->o_zonelist = e_widget_ilist_add(evas, 0, 0, NULL);
187 e_widget_ilist_multi_select_set(cfdata->o_zonelist, false);
188 e_widget_size_min_set(cfdata->o_zonelist, 100, 100);
189 e_widget_on_change_hook_set(cfdata->o_zonelist, _cb_zone_change, cfdata);
190 for (l = e_comp->zones; l; l = l->next)
191 {
192 if (!(zone = l->data))
193 continue;
194 e_widget_ilist_append(cfdata->o_zonelist, NULL, zone->name, NULL, zone,
195 NULL);
196 }
197 e_widget_ilist_go(cfdata->o_zonelist);
198 e_widget_ilist_thaw(cfdata->o_zonelist);
199
200 LIST_ADD(cfdata->osf, cfdata->o_zonelist);
201
202 /* List of individual tiling modes */
203 cfdata->evas = evas;
204
205 _fill_zone_config(eina_list_data_get(e_comp->zones), cfdata);
206
207 e_widget_ilist_selected_set(cfdata->o_zonelist, 0);
208
209 e_widget_framelist_object_append(of, cfdata->osf);
210
211 LIST_ADD(o, of);
212
213 of = e_widget_label_add(evas, _("Padding between windows"));
214 LIST_ADD(o, of);
215 slider = e_widget_slider_add(evas, 1, 0, ("%1.0f px"), 0.0, TILING_MAX_PADDING,
216 1.0, 0, NULL, &cfdata->config.window_padding, 150);
217 LIST_ADD(o, slider);
218
219 oc = e_widget_button_add(evas, _("Help"), "help", _open_browser_help_cb,
220 NULL, NULL);
221 LIST_ADD(o, oc);
222
223 return o;
224 }
225
226 static int
_basic_apply_data(E_Config_Dialog * cfd EINA_UNUSED,E_Config_Dialog_Data * cfdata)227 _basic_apply_data(E_Config_Dialog *cfd EINA_UNUSED,
228 E_Config_Dialog_Data *cfdata)
229 {
230 struct _Config_vdesk *vd;
231 Eina_List *l, *vdesks;
232
233 tiling_g.config->tile_dialogs = cfdata->config.tile_dialogs;
234 tiling_g.config->show_titles = cfdata->config.show_titles;
235 tiling_g.config->have_floating_mode = cfdata->config.have_floating_mode;
236 tiling_g.config->window_padding = cfdata->config.window_padding;
237
238 /* Check if the layout for one of the vdesks has changed */
239 for (l = tiling_g.config->vdesks; l; l = l->next)
240 {
241 struct _Config_vdesk *newvd;
242
243 vd = l->data;
244
245 if (!vd)
246 continue;
247 if (!(newvd =
248 get_vdesk(cfdata->config.vdesks, vd->x, vd->y, vd->zone_num)))
249 {
250 change_desk_conf(vd);
251 continue;
252 }
253
254 if (newvd->nb_stacks != vd->nb_stacks)
255 {
256 DBG("number of columns for (%d, %d, %d) changed from %d" " to %d",
257 vd->x, vd->y, vd->zone_num, vd->nb_stacks, newvd->nb_stacks);
258 change_desk_conf(newvd);
259 free(vd);
260 l->data = NULL;
261 }
262 else if (vd->nb_stacks > 0)
263 {
264 change_desk_conf(vd);
265 }
266 }
267
268 vdesks = tiling_g.config->vdesks;
269 tiling_g.config->vdesks = NULL;
270
271 for (l = cfdata->config.vdesks; l; l = l->next)
272 {
273 struct _Config_vdesk *newvd;
274
275 vd = l->data;
276 if (!vd)
277 continue;
278
279 newvd = E_NEW(struct _Config_vdesk, 1);
280
281 newvd->x = vd->x;
282 newvd->y = vd->y;
283 newvd->zone_num = vd->zone_num;
284 newvd->nb_stacks = vd->nb_stacks;
285
286 EINA_LIST_APPEND(tiling_g.config->vdesks, newvd);
287 }
288
289 e_tiling_update_conf();
290
291 EINA_LIST_FREE(vdesks, vd)
292 {
293 free(vd);
294 }
295
296 e_config_save_queue();
297
298 return EINA_TRUE;
299 }
300
301 E_Config_Dialog *
e_int_config_tiling_module(Evas_Object * parent EINA_UNUSED,const char * params EINA_UNUSED)302 e_int_config_tiling_module(Evas_Object *parent EINA_UNUSED, const char *params EINA_UNUSED)
303 {
304 E_Config_Dialog *cfd;
305 E_Config_Dialog_View *v;
306 char buf[PATH_MAX];
307
308 if (e_config_dialog_find("E", "windows/tiling"))
309 return NULL;
310
311 v = E_NEW(E_Config_Dialog_View, 1);
312
313 v->create_cfdata = _create_data;
314 v->free_cfdata = _free_data;
315 v->basic.apply_cfdata = _basic_apply_data;
316 v->basic.create_widgets = _basic_create_widgets;
317
318 snprintf(buf, sizeof(buf), "%s/e-module-tiling.edj",
319 e_module_dir_get(tiling_g.module));
320 cfd =
321 e_config_dialog_new(NULL, _("Tiling Configuration"), "E",
322 "windows/tiling", buf, 0, v, NULL);
323 return cfd;
324 }
325
326