Mod+Wheel Window Resize
[wmaker-crm.git] / WPrefs.app / WindowHandling.c
1 /* WindowHandling.c- options for handling windows
2  *
3  *  WPrefs - Window Maker Preferences Program
4  *
5  *  Copyright (c) 1998-2003 Alfredo K. Kojima
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20  *  USA.
21  */
22
23 #include "WPrefs.h"
24
25 typedef struct _Panel {
26         WMBox *box;
27
28         char *sectionName;
29
30         char *description;
31
32         CallbackRec callbacks;
33
34         WMWidget *parent;
35
36         WMFrame *placF;
37         WMPopUpButton *placP;
38         WMLabel *porigL;
39         WMLabel *porigvL;
40         WMFrame *porigF;
41         WMLabel *porigW;
42
43         WMSlider *vsli;
44         WMSlider *hsli;
45
46         WMFrame *resF;
47         WMSlider *resS;
48         WMLabel *resL;
49         WMButton *resaB;
50         WMButton *resrB;
51
52         WMFrame *maxiF;
53         WMButton *miconB;
54         WMButton *mdockB;
55
56         WMLabel *resizeL;
57         WMLabel *resizeTextL;
58         WMSlider *resizeS;
59
60         WMFrame *opaqF;
61         WMButton *opaqB;
62
63         WMFrame *tranF;
64         WMButton *tranB;
65 } _Panel;
66
67 #define ICON_FILE "whandling"
68
69 #define OPAQUE_MOVE_PIXMAP "opaque"
70
71 #define NON_OPAQUE_MOVE_PIXMAP "nonopaque"
72
73 #define THUMB_SIZE      16
74
75 static char *placements[] = {
76         "auto",
77         "random",
78         "manual",
79         "cascade",
80         "smart"
81 };
82
83 static void sliderCallback(WMWidget * w, void *data)
84 {
85         _Panel *panel = (_Panel *) data;
86         int x, y, rx, ry;
87         char buffer[64];
88         int swidth = WMGetSliderMaxValue(panel->hsli);
89         int sheight = WMGetSliderMaxValue(panel->vsli);
90
91         x = WMGetSliderValue(panel->hsli);
92         y = WMGetSliderValue(panel->vsli);
93
94         rx = x * (WMWidgetWidth(panel->porigF) - 3) / swidth + 2;
95         ry = y * (WMWidgetHeight(panel->porigF) - 3) / sheight + 2;
96         WMMoveWidget(panel->porigW, rx, ry);
97
98         sprintf(buffer, "(%i,%i)", x, y);
99         WMSetLabelText(panel->porigvL, buffer);
100 }
101
102 static void resistanceCallback(WMWidget * w, void *data)
103 {
104         _Panel *panel = (_Panel *) data;
105         char buffer[64];
106         int i;
107
108         i = WMGetSliderValue(panel->resS);
109
110         if (i == 0)
111                 WMSetLabelText(panel->resL, "OFF");
112         else {
113                 sprintf(buffer, "%i", i);
114                 WMSetLabelText(panel->resL, buffer);
115         }
116 }
117
118 static void resizeCallback(WMWidget * w, void *data)
119 {
120         _Panel *panel = (_Panel *) data;
121         char buffer[64];
122         int i;
123
124         i = WMGetSliderValue(panel->resizeS);
125
126         if (i == 0)
127                 WMSetLabelText(panel->resizeL, "OFF");
128         else {
129                 sprintf(buffer, "%i", i);
130                 WMSetLabelText(panel->resizeL, buffer);
131         }
132 }
133
134 static int getPlacement(char *str)
135 {
136         if (!str)
137                 return 0;
138
139         if (strcasecmp(str, "auto") == 0)
140                 return 0;
141         else if (strcasecmp(str, "random") == 0)
142                 return 1;
143         else if (strcasecmp(str, "manual") == 0)
144                 return 2;
145         else if (strcasecmp(str, "cascade") == 0)
146                 return 3;
147         else if (strcasecmp(str, "smart") == 0)
148                 return 4;
149         else
150                 wwarning(_("bad option value %s in WindowPlacement. Using default value"), str);
151         return 0;
152 }
153
154 static void showData(_Panel * panel)
155 {
156         char *str;
157         WMPropList *arr;
158         int x, y;
159
160         str = GetStringForKey("WindowPlacement");
161
162         WMSetPopUpButtonSelectedItem(panel->placP, getPlacement(str));
163
164         arr = GetObjectForKey("WindowPlaceOrigin");
165
166         x = 0;
167         y = 0;
168         if (arr && (!WMIsPLArray(arr) || WMGetPropListItemCount(arr) != 2)) {
169                 wwarning(_("invalid data in option WindowPlaceOrigin. Using default (0,0)"));
170         } else {
171                 if (arr) {
172                         x = atoi(WMGetFromPLString(WMGetFromPLArray(arr, 0)));
173                         y = atoi(WMGetFromPLString(WMGetFromPLArray(arr, 1)));
174                 }
175         }
176
177         WMSetSliderValue(panel->hsli, x);
178         WMSetSliderValue(panel->vsli, y);
179
180         sliderCallback(NULL, panel);
181
182         x = GetIntegerForKey("EdgeResistance");
183         WMSetSliderValue(panel->resS, x);
184         resistanceCallback(NULL, panel);
185
186         x = GetIntegerForKey("ResizeIncrement");
187         WMSetSliderValue(panel->resizeS, x);
188         resizeCallback(NULL, panel);
189
190         WMSetButtonSelected(panel->tranB, GetBoolForKey("OpenTransientOnOwnerWorkspace"));
191
192         WMSetButtonSelected(panel->opaqB, GetBoolForKey("OpaqueMove"));
193
194         WMSetButtonSelected(panel->miconB, GetBoolForKey("NoWindowOverIcons"));
195
196         WMSetButtonSelected(panel->mdockB, GetBoolForKey("NoWindowOverDock"));
197
198         if (GetBoolForKey("Attraction"))
199                 WMPerformButtonClick(panel->resrB);
200         else
201                 WMPerformButtonClick(panel->resaB);
202 }
203
204 static void storeData(_Panel * panel)
205 {
206         WMPropList *arr;
207         char x[16], y[16];
208
209         SetBoolForKey(WMGetButtonSelected(panel->miconB), "NoWindowOverIcons");
210         SetBoolForKey(WMGetButtonSelected(panel->mdockB), "NoWindowOverDock");
211         SetBoolForKey(WMGetButtonSelected(panel->opaqB), "OpaqueMove");
212         SetBoolForKey(WMGetButtonSelected(panel->tranB), "OpenTransientOnOwnerWorkspace");
213         SetStringForKey(placements[WMGetPopUpButtonSelectedItem(panel->placP)], "WindowPlacement");
214         sprintf(x, "%i", WMGetSliderValue(panel->hsli));
215         sprintf(y, "%i", WMGetSliderValue(panel->vsli));
216         arr = WMCreatePLArray(WMCreatePLString(x), WMCreatePLString(y), NULL);
217         SetObjectForKey(arr, "WindowPlaceOrigin");
218         SetIntegerForKey(WMGetSliderValue(panel->resS), "EdgeResistance");
219         SetIntegerForKey(WMGetSliderValue(panel->resizeS), "ResizeIncrement");
220         SetBoolForKey(WMGetButtonSelected(panel->resrB), "Attraction");
221         WMReleasePropList(arr);
222 }
223
224 static void createPanel(Panel * p)
225 {
226         _Panel *panel = (Panel *) p;
227         WMScreen *scr = WMWidgetScreen(panel->parent);
228         WMColor *color;
229         WMPixmap *pixmap;
230         int width, height;
231         int swidth, sheight;
232         char *path;
233         WMBox *hbox;
234
235         panel->box = WMCreateBox(panel->parent);
236         WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
237         WMSetBoxHorizontal(panel->box, False);
238         WMSetBoxBorderWidth(panel->box, 8);
239
240         hbox = WMCreateBox(panel->box);
241         WMSetBoxHorizontal(hbox, True);
242         WMAddBoxSubview(panel->box, WMWidgetView(hbox), False, True, 110, 0, 10);
243
244     /************** Window Placement ***************/
245         panel->placF = WMCreateFrame(hbox);
246         WMMapWidget(panel->placF);
247         WMAddBoxSubview(hbox, WMWidgetView(panel->placF), True, True, 100, 0, 10);
248
249         WMSetFrameTitle(panel->placF, _("Window Placement"));
250         WMSetBalloonTextForView(_("How to place windows when they are first put\n"
251                                   "on screen."), WMWidgetView(panel->placF));
252
253         panel->placP = WMCreatePopUpButton(panel->placF);
254         WMResizeWidget(panel->placP, 105, 20);
255         WMMoveWidget(panel->placP, 15, 20);
256         WMAddPopUpButtonItem(panel->placP, _("Automatic"));
257         WMAddPopUpButtonItem(panel->placP, _("Random"));
258         WMAddPopUpButtonItem(panel->placP, _("Manual"));
259         WMAddPopUpButtonItem(panel->placP, _("Cascade"));
260         WMAddPopUpButtonItem(panel->placP, _("Smart"));
261
262         panel->porigL = WMCreateLabel(panel->placF);
263         WMResizeWidget(panel->porigL, 120, 32);
264         WMMoveWidget(panel->porigL, 5, 45);
265         WMSetLabelTextAlignment(panel->porigL, WACenter);
266         WMSetLabelText(panel->porigL, _("Placement Origin"));
267
268         panel->porigvL = WMCreateLabel(panel->placF);
269         WMResizeWidget(panel->porigvL, 80, 20);
270         WMMoveWidget(panel->porigvL, 30, 75);
271         WMSetLabelTextAlignment(panel->porigvL, WACenter);
272
273         color = WMCreateRGBColor(scr, 0x5100, 0x5100, 0x7100, True);
274         panel->porigF = WMCreateFrame(panel->placF);
275         WMSetWidgetBackgroundColor(panel->porigF, color);
276         WMReleaseColor(color);
277         WMSetFrameRelief(panel->porigF, WRSunken);
278
279         swidth = WidthOfScreen(DefaultScreenOfDisplay(WMScreenDisplay(scr)));
280         sheight = HeightOfScreen(DefaultScreenOfDisplay(WMScreenDisplay(scr)));
281
282         if (sheight > swidth) {
283                 height = 70;
284                 width = 70 * swidth / sheight;
285                 if (width > 240)
286                         width = 240;
287                 height = 240 * sheight / swidth;
288         } else {
289                 width = 240;
290                 height = 240 * sheight / swidth;
291                 if (height > 70)
292                         height = 70;
293                 width = 70 * swidth / sheight;
294         }
295         WMResizeWidget(panel->porigF, width, height);
296         WMMoveWidget(panel->porigF, 130 + (240 - width) / 2, 20 + (70 - height) / 2);
297
298         panel->porigW = WMCreateLabel(panel->porigF);
299         WMResizeWidget(panel->porigW, THUMB_SIZE, THUMB_SIZE);
300         WMMoveWidget(panel->porigW, 2, 2);
301         WMSetLabelRelief(panel->porigW, WRRaised);
302
303         panel->hsli = WMCreateSlider(panel->placF);
304         WMResizeWidget(panel->hsli, width, 12);
305         WMMoveWidget(panel->hsli, 130 + (240 - width) / 2, 20 + (70 - height) / 2 + height + 2);
306         WMSetSliderAction(panel->hsli, sliderCallback, panel);
307         WMSetSliderMinValue(panel->hsli, 0);
308         WMSetSliderMaxValue(panel->hsli, swidth);
309
310         panel->vsli = WMCreateSlider(panel->placF);
311         WMResizeWidget(panel->vsli, 12, height);
312         WMMoveWidget(panel->vsli, 130 + (240 - width) / 2 + width + 2, 20 + (70 - height) / 2);
313         WMSetSliderAction(panel->vsli, sliderCallback, panel);
314         WMSetSliderMinValue(panel->vsli, 0);
315         WMSetSliderMaxValue(panel->vsli, sheight);
316
317         WMMapSubwidgets(panel->porigF);
318
319         WMMapSubwidgets(panel->placF);
320
321     /************** Opaque Move ***************/
322         panel->opaqF = WMCreateFrame(hbox);
323         WMMapWidget(panel->opaqF);
324         WMAddBoxSubview(hbox, WMWidgetView(panel->opaqF), False, True, 110, 0, 0);
325
326         WMSetFrameTitle(panel->opaqF, _("Opaque Move"));
327         WMSetBalloonTextForView(_("Whether the window contents should be moved\n"
328                                   "when dragging windows aroung or if only a\n"
329                                   "frame should be displayed.\n"), WMWidgetView(panel->opaqF));
330
331         panel->opaqB = WMCreateButton(panel->opaqF, WBTToggle);
332         WMResizeWidget(panel->opaqB, 64, 64);
333         WMMoveWidget(panel->opaqB, 24, 25);
334         WMSetButtonImagePosition(panel->opaqB, WIPImageOnly);
335
336         path = LocateImage(NON_OPAQUE_MOVE_PIXMAP);
337         if (path) {
338                 pixmap = WMCreatePixmapFromFile(scr, path);
339                 if (pixmap) {
340                         WMSetButtonImage(panel->opaqB, pixmap);
341                         WMReleasePixmap(pixmap);
342                 } else {
343                         wwarning(_("could not load icon %s"), path);
344                 }
345                 wfree(path);
346         }
347
348         path = LocateImage(OPAQUE_MOVE_PIXMAP);
349         if (path) {
350                 pixmap = WMCreatePixmapFromFile(scr, path);
351                 if (pixmap) {
352                         WMSetButtonAltImage(panel->opaqB, pixmap);
353                         WMReleasePixmap(pixmap);
354                 } else {
355                         wwarning(_("could not load icon %s"), path);
356                 }
357                 wfree(path);
358         }
359         WMMapSubwidgets(panel->opaqF);
360
361     /**************** Account for Icon/Dock ***************/
362         panel->maxiF = WMCreateFrame(panel->box);
363         WMResizeWidget(panel->maxiF, 205, 95);
364         WMMoveWidget(panel->maxiF, 305, 125);
365         WMSetFrameTitle(panel->maxiF, _("When maximizing..."));
366
367         panel->miconB = WMCreateSwitchButton(panel->maxiF);
368         WMResizeWidget(panel->miconB, 190, 30);
369         WMMoveWidget(panel->miconB, 10, 12);
370         WMSetButtonText(panel->miconB, _("...do not cover icons"));
371
372         panel->mdockB = WMCreateSwitchButton(panel->maxiF);
373         WMResizeWidget(panel->mdockB, 190, 30);
374         WMMoveWidget(panel->mdockB, 10, 35);
375
376         WMSetButtonText(panel->mdockB, _("...do not cover dock"));
377
378         panel->resizeS = WMCreateSlider(panel->maxiF);
379         WMResizeWidget(panel->resizeS, 50, 15);
380         WMMoveWidget(panel->resizeS, 10, 70);
381         WMSetSliderMinValue(panel->resizeS, 0);
382         WMSetSliderMaxValue(panel->resizeS, 100);
383         WMSetSliderAction(panel->resizeS, resizeCallback, panel);
384
385         panel->resizeL = WMCreateLabel(panel->maxiF);
386         WMResizeWidget(panel->resizeL, 30, 15);
387         WMMoveWidget(panel->resizeL, 60, 70);
388
389         panel->resizeTextL = WMCreateLabel(panel->maxiF);
390         WMSetLabelText(panel->resizeTextL, "Mod+Wheel\nresize increment");
391         WMResizeWidget(panel->resizeTextL, 110, 30);
392         WMMoveWidget(panel->resizeTextL, 90, 62);
393
394         WMMapSubwidgets(panel->maxiF);
395
396     /**************** Edge Resistance  ****************/
397
398         panel->resF = WMCreateFrame(panel->box);
399         WMResizeWidget(panel->resF, 285, 45);
400         WMMoveWidget(panel->resF, 8, 125);
401         WMSetFrameTitle(panel->resF, _("Edge Resistance"));
402
403         WMSetBalloonTextForView(_("Edge resistance will make windows `resist'\n"
404                                   "being moved further for the defined threshold\n"
405                                   "when moved against other windows or the edges\n"
406                                   "of the screen."), WMWidgetView(panel->resF));
407
408         panel->resS = WMCreateSlider(panel->resF);
409         WMResizeWidget(panel->resS, 80, 15);
410         WMMoveWidget(panel->resS, 10, 20);
411         WMSetSliderMinValue(panel->resS, 0);
412         WMSetSliderMaxValue(panel->resS, 80);
413         WMSetSliderAction(panel->resS, resistanceCallback, panel);
414
415         panel->resL = WMCreateLabel(panel->resF);
416         WMResizeWidget(panel->resL, 30, 15);
417         WMMoveWidget(panel->resL, 95, 20);
418
419         panel->resaB = WMCreateRadioButton(panel->resF);
420         WMMoveWidget(panel->resaB, 130, 15);
421         WMResizeWidget(panel->resaB, 70, 25);
422         WMSetButtonText(panel->resaB, _("Resist"));
423
424         panel->resrB = WMCreateRadioButton(panel->resF);
425         WMMoveWidget(panel->resrB, 200, 15);
426         WMResizeWidget(panel->resrB, 70, 25);
427         WMSetButtonText(panel->resrB, _("Attract"));
428         WMGroupButtons(panel->resrB, panel->resaB);
429
430         WMMapSubwidgets(panel->resF);
431
432     /**************** Transients on Parent Workspace ****************/
433
434         panel->tranF = WMCreateFrame(panel->box);
435         WMResizeWidget(panel->tranF, 285, 40);
436         WMMoveWidget(panel->tranF, 8, 180);
437
438         panel->tranB = WMCreateSwitchButton(panel->tranF);
439         WMMoveWidget(panel->tranB, 10, 5);
440         WMResizeWidget(panel->tranB, 250, 30);
441         WMSetButtonText(panel->tranB, _("Open dialogs in the same workspace\nas their owners"));
442
443         WMMapSubwidgets(panel->tranF);
444
445         WMRealizeWidget(panel->box);
446         WMMapSubwidgets(panel->box);
447
448         /* show the config data */
449         showData(panel);
450 }
451
452 static void undo(_Panel * panel)
453 {
454         showData(panel);
455 }
456
457 Panel *InitWindowHandling(WMScreen * scr, WMWidget * parent)
458 {
459         _Panel *panel;
460
461         panel = wmalloc(sizeof(_Panel));
462         memset(panel, 0, sizeof(_Panel));
463
464         panel->sectionName = _("Window Handling Preferences");
465
466         panel->description = _("Window handling options. Initial placement style\n"
467                                "edge resistance, opaque move etc.");
468
469         panel->parent = parent;
470
471         panel->callbacks.createWidgets = createPanel;
472         panel->callbacks.updateDomain = storeData;
473         panel->callbacks.undoChanges = undo;
474
475         AddSection(panel, ICON_FILE);
476
477         return panel;
478 }