Change to the linux kernel coding style
[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         WMFrame *opaqF;
57         WMButton *opaqB;
58
59         WMFrame *tranF;
60         WMButton *tranB;
61 } _Panel;
62
63 #define ICON_FILE "whandling"
64
65 #define OPAQUE_MOVE_PIXMAP "opaque"
66
67 #define NON_OPAQUE_MOVE_PIXMAP "nonopaque"
68
69 #define THUMB_SIZE      16
70
71 static char *placements[] = {
72         "auto",
73         "random",
74         "manual",
75         "cascade",
76         "smart"
77 };
78
79 static void sliderCallback(WMWidget * w, void *data)
80 {
81         _Panel *panel = (_Panel *) data;
82         int x, y, rx, ry;
83         char buffer[64];
84         int swidth = WMGetSliderMaxValue(panel->hsli);
85         int sheight = WMGetSliderMaxValue(panel->vsli);
86
87         x = WMGetSliderValue(panel->hsli);
88         y = WMGetSliderValue(panel->vsli);
89
90         rx = x * (WMWidgetWidth(panel->porigF) - 3) / swidth + 2;
91         ry = y * (WMWidgetHeight(panel->porigF) - 3) / sheight + 2;
92         WMMoveWidget(panel->porigW, rx, ry);
93
94         sprintf(buffer, "(%i,%i)", x, y);
95         WMSetLabelText(panel->porigvL, buffer);
96 }
97
98 static void resistanceCallback(WMWidget * w, void *data)
99 {
100         _Panel *panel = (_Panel *) data;
101         char buffer[64];
102         int i;
103
104         i = WMGetSliderValue(panel->resS);
105
106         if (i == 0)
107                 WMSetLabelText(panel->resL, "OFF");
108         else {
109                 sprintf(buffer, "%i", i);
110                 WMSetLabelText(panel->resL, buffer);
111         }
112 }
113
114 static int getPlacement(char *str)
115 {
116         if (!str)
117                 return 0;
118
119         if (strcasecmp(str, "auto") == 0)
120                 return 0;
121         else if (strcasecmp(str, "random") == 0)
122                 return 1;
123         else if (strcasecmp(str, "manual") == 0)
124                 return 2;
125         else if (strcasecmp(str, "cascade") == 0)
126                 return 3;
127         else if (strcasecmp(str, "smart") == 0)
128                 return 4;
129         else
130                 wwarning(_("bad option value %s in WindowPlacement. Using default value"), str);
131         return 0;
132 }
133
134 static void showData(_Panel * panel)
135 {
136         char *str;
137         WMPropList *arr;
138         int x, y;
139
140         str = GetStringForKey("WindowPlacement");
141
142         WMSetPopUpButtonSelectedItem(panel->placP, getPlacement(str));
143
144         arr = GetObjectForKey("WindowPlaceOrigin");
145
146         x = 0;
147         y = 0;
148         if (arr && (!WMIsPLArray(arr) || WMGetPropListItemCount(arr) != 2)) {
149                 wwarning(_("invalid data in option WindowPlaceOrigin. Using default (0,0)"));
150         } else {
151                 if (arr) {
152                         x = atoi(WMGetFromPLString(WMGetFromPLArray(arr, 0)));
153                         y = atoi(WMGetFromPLString(WMGetFromPLArray(arr, 1)));
154                 }
155         }
156
157         WMSetSliderValue(panel->hsli, x);
158         WMSetSliderValue(panel->vsli, y);
159
160         sliderCallback(NULL, panel);
161
162         x = GetIntegerForKey("EdgeResistance");
163         WMSetSliderValue(panel->resS, x);
164         resistanceCallback(NULL, panel);
165
166         WMSetButtonSelected(panel->tranB, GetBoolForKey("OpenTransientOnOwnerWorkspace"));
167
168         WMSetButtonSelected(panel->opaqB, GetBoolForKey("OpaqueMove"));
169
170         WMSetButtonSelected(panel->miconB, GetBoolForKey("NoWindowOverIcons"));
171
172         WMSetButtonSelected(panel->mdockB, GetBoolForKey("NoWindowOverDock"));
173
174         if (GetBoolForKey("Attraction"))
175                 WMPerformButtonClick(panel->resrB);
176         else
177                 WMPerformButtonClick(panel->resaB);
178 }
179
180 static void storeData(_Panel * panel)
181 {
182         WMPropList *arr;
183         char x[16], y[16];
184
185         SetBoolForKey(WMGetButtonSelected(panel->miconB), "NoWindowOverIcons");
186         SetBoolForKey(WMGetButtonSelected(panel->mdockB), "NoWindowOverDock");
187         SetBoolForKey(WMGetButtonSelected(panel->opaqB), "OpaqueMove");
188         SetBoolForKey(WMGetButtonSelected(panel->tranB), "OpenTransientOnOwnerWorkspace");
189         SetStringForKey(placements[WMGetPopUpButtonSelectedItem(panel->placP)], "WindowPlacement");
190         sprintf(x, "%i", WMGetSliderValue(panel->hsli));
191         sprintf(y, "%i", WMGetSliderValue(panel->vsli));
192         arr = WMCreatePLArray(WMCreatePLString(x), WMCreatePLString(y), NULL);
193         SetObjectForKey(arr, "WindowPlaceOrigin");
194         SetIntegerForKey(WMGetSliderValue(panel->resS), "EdgeResistance");
195         SetBoolForKey(WMGetButtonSelected(panel->resrB), "Attraction");
196         WMReleasePropList(arr);
197 }
198
199 static void createPanel(Panel * p)
200 {
201         _Panel *panel = (Panel *) p;
202         WMScreen *scr = WMWidgetScreen(panel->parent);
203         WMColor *color;
204         WMPixmap *pixmap;
205         int width, height;
206         int swidth, sheight;
207         char *path;
208         WMBox *hbox;
209
210         panel->box = WMCreateBox(panel->parent);
211         WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
212         WMSetBoxHorizontal(panel->box, False);
213         WMSetBoxBorderWidth(panel->box, 8);
214
215         hbox = WMCreateBox(panel->box);
216         WMSetBoxHorizontal(hbox, True);
217         WMAddBoxSubview(panel->box, WMWidgetView(hbox), False, True, 110, 0, 10);
218
219     /************** Window Placement ***************/
220         panel->placF = WMCreateFrame(hbox);
221         WMMapWidget(panel->placF);
222         WMAddBoxSubview(hbox, WMWidgetView(panel->placF), True, True, 100, 0, 10);
223
224         WMSetFrameTitle(panel->placF, _("Window Placement"));
225         WMSetBalloonTextForView(_("How to place windows when they are first put\n"
226                                   "on screen."), WMWidgetView(panel->placF));
227
228         panel->placP = WMCreatePopUpButton(panel->placF);
229         WMResizeWidget(panel->placP, 105, 20);
230         WMMoveWidget(panel->placP, 15, 20);
231         WMAddPopUpButtonItem(panel->placP, _("Automatic"));
232         WMAddPopUpButtonItem(panel->placP, _("Random"));
233         WMAddPopUpButtonItem(panel->placP, _("Manual"));
234         WMAddPopUpButtonItem(panel->placP, _("Cascade"));
235         WMAddPopUpButtonItem(panel->placP, _("Smart"));
236
237         panel->porigL = WMCreateLabel(panel->placF);
238         WMResizeWidget(panel->porigL, 120, 32);
239         WMMoveWidget(panel->porigL, 5, 45);
240         WMSetLabelTextAlignment(panel->porigL, WACenter);
241         WMSetLabelText(panel->porigL, _("Placement Origin"));
242
243         panel->porigvL = WMCreateLabel(panel->placF);
244         WMResizeWidget(panel->porigvL, 80, 20);
245         WMMoveWidget(panel->porigvL, 30, 75);
246         WMSetLabelTextAlignment(panel->porigvL, WACenter);
247
248         color = WMCreateRGBColor(scr, 0x5100, 0x5100, 0x7100, True);
249         panel->porigF = WMCreateFrame(panel->placF);
250         WMSetWidgetBackgroundColor(panel->porigF, color);
251         WMReleaseColor(color);
252         WMSetFrameRelief(panel->porigF, WRSunken);
253
254         swidth = WidthOfScreen(DefaultScreenOfDisplay(WMScreenDisplay(scr)));
255         sheight = HeightOfScreen(DefaultScreenOfDisplay(WMScreenDisplay(scr)));
256
257         if (sheight > swidth) {
258                 height = 70;
259                 width = 70 * swidth / sheight;
260                 if (width > 240)
261                         width = 240;
262                 height = 240 * sheight / swidth;
263         } else {
264                 width = 240;
265                 height = 240 * sheight / swidth;
266                 if (height > 70)
267                         height = 70;
268                 width = 70 * swidth / sheight;
269         }
270         WMResizeWidget(panel->porigF, width, height);
271         WMMoveWidget(panel->porigF, 130 + (240 - width) / 2, 20 + (70 - height) / 2);
272
273         panel->porigW = WMCreateLabel(panel->porigF);
274         WMResizeWidget(panel->porigW, THUMB_SIZE, THUMB_SIZE);
275         WMMoveWidget(panel->porigW, 2, 2);
276         WMSetLabelRelief(panel->porigW, WRRaised);
277
278         panel->hsli = WMCreateSlider(panel->placF);
279         WMResizeWidget(panel->hsli, width, 12);
280         WMMoveWidget(panel->hsli, 130 + (240 - width) / 2, 20 + (70 - height) / 2 + height + 2);
281         WMSetSliderAction(panel->hsli, sliderCallback, panel);
282         WMSetSliderMinValue(panel->hsli, 0);
283         WMSetSliderMaxValue(panel->hsli, swidth);
284
285         panel->vsli = WMCreateSlider(panel->placF);
286         WMResizeWidget(panel->vsli, 12, height);
287         WMMoveWidget(panel->vsli, 130 + (240 - width) / 2 + width + 2, 20 + (70 - height) / 2);
288         WMSetSliderAction(panel->vsli, sliderCallback, panel);
289         WMSetSliderMinValue(panel->vsli, 0);
290         WMSetSliderMaxValue(panel->vsli, sheight);
291
292         WMMapSubwidgets(panel->porigF);
293
294         WMMapSubwidgets(panel->placF);
295
296     /************** Opaque Move ***************/
297         panel->opaqF = WMCreateFrame(hbox);
298         WMMapWidget(panel->opaqF);
299         WMAddBoxSubview(hbox, WMWidgetView(panel->opaqF), False, True, 110, 0, 0);
300
301         WMSetFrameTitle(panel->opaqF, _("Opaque Move"));
302         WMSetBalloonTextForView(_("Whether the window contents should be moved\n"
303                                   "when dragging windows aroung or if only a\n"
304                                   "frame should be displayed.\n"), WMWidgetView(panel->opaqF));
305
306         panel->opaqB = WMCreateButton(panel->opaqF, WBTToggle);
307         WMResizeWidget(panel->opaqB, 64, 64);
308         WMMoveWidget(panel->opaqB, 24, 25);
309         WMSetButtonImagePosition(panel->opaqB, WIPImageOnly);
310
311         path = LocateImage(NON_OPAQUE_MOVE_PIXMAP);
312         if (path) {
313                 pixmap = WMCreatePixmapFromFile(scr, path);
314                 if (pixmap) {
315                         WMSetButtonImage(panel->opaqB, pixmap);
316                         WMReleasePixmap(pixmap);
317                 } else {
318                         wwarning(_("could not load icon %s"), path);
319                 }
320                 wfree(path);
321         }
322
323         path = LocateImage(OPAQUE_MOVE_PIXMAP);
324         if (path) {
325                 pixmap = WMCreatePixmapFromFile(scr, path);
326                 if (pixmap) {
327                         WMSetButtonAltImage(panel->opaqB, pixmap);
328                         WMReleasePixmap(pixmap);
329                 } else {
330                         wwarning(_("could not load icon %s"), path);
331                 }
332                 wfree(path);
333         }
334         WMMapSubwidgets(panel->opaqF);
335
336     /**************** Account for Icon/Dock ***************/
337         panel->maxiF = WMCreateFrame(panel->box);
338         WMResizeWidget(panel->maxiF, 205, 95);
339         WMMoveWidget(panel->maxiF, 305, 125);
340         WMSetFrameTitle(panel->maxiF, _("When maximizing..."));
341
342         panel->miconB = WMCreateSwitchButton(panel->maxiF);
343         WMResizeWidget(panel->miconB, 190, 30);
344         WMMoveWidget(panel->miconB, 10, 18);
345         WMSetButtonText(panel->miconB, _("...do not cover icons"));
346
347         panel->mdockB = WMCreateSwitchButton(panel->maxiF);
348         WMResizeWidget(panel->mdockB, 190, 30);
349         WMMoveWidget(panel->mdockB, 10, 53);
350
351         WMSetButtonText(panel->mdockB, _("...do not cover dock"));
352
353         WMMapSubwidgets(panel->maxiF);
354
355     /**************** Edge Resistance  ****************/
356
357         panel->resF = WMCreateFrame(panel->box);
358         WMResizeWidget(panel->resF, 285, 45);
359         WMMoveWidget(panel->resF, 8, 125);
360         WMSetFrameTitle(panel->resF, _("Edge Resistance"));
361
362         WMSetBalloonTextForView(_("Edge resistance will make windows `resist'\n"
363                                   "being moved further for the defined threshold\n"
364                                   "when moved against other windows or the edges\n"
365                                   "of the screen."), WMWidgetView(panel->resF));
366
367         panel->resS = WMCreateSlider(panel->resF);
368         WMResizeWidget(panel->resS, 80, 15);
369         WMMoveWidget(panel->resS, 10, 20);
370         WMSetSliderMinValue(panel->resS, 0);
371         WMSetSliderMaxValue(panel->resS, 80);
372         WMSetSliderAction(panel->resS, resistanceCallback, panel);
373
374         panel->resL = WMCreateLabel(panel->resF);
375         WMResizeWidget(panel->resL, 30, 15);
376         WMMoveWidget(panel->resL, 95, 20);
377
378         panel->resaB = WMCreateRadioButton(panel->resF);
379         WMMoveWidget(panel->resaB, 130, 15);
380         WMResizeWidget(panel->resaB, 70, 25);
381         WMSetButtonText(panel->resaB, _("Resist"));
382
383         panel->resrB = WMCreateRadioButton(panel->resF);
384         WMMoveWidget(panel->resrB, 200, 15);
385         WMResizeWidget(panel->resrB, 70, 25);
386         WMSetButtonText(panel->resrB, _("Attract"));
387         WMGroupButtons(panel->resrB, panel->resaB);
388
389         WMMapSubwidgets(panel->resF);
390
391     /**************** Transients on Parent Workspace ****************/
392
393         panel->tranF = WMCreateFrame(panel->box);
394         WMResizeWidget(panel->tranF, 285, 40);
395         WMMoveWidget(panel->tranF, 8, 180);
396
397         panel->tranB = WMCreateSwitchButton(panel->tranF);
398         WMMoveWidget(panel->tranB, 10, 5);
399         WMResizeWidget(panel->tranB, 250, 30);
400         WMSetButtonText(panel->tranB, _("Open dialogs in the same workspace\nas their owners"));
401
402         WMMapSubwidgets(panel->tranF);
403
404         WMRealizeWidget(panel->box);
405         WMMapSubwidgets(panel->box);
406
407         /* show the config data */
408         showData(panel);
409 }
410
411 static void undo(_Panel * panel)
412 {
413         showData(panel);
414 }
415
416 Panel *InitWindowHandling(WMScreen * scr, WMWidget * parent)
417 {
418         _Panel *panel;
419
420         panel = wmalloc(sizeof(_Panel));
421         memset(panel, 0, sizeof(_Panel));
422
423         panel->sectionName = _("Window Handling Preferences");
424
425         panel->description = _("Window handling options. Initial placement style\n"
426                                "edge resistance, opaque move etc.");
427
428         panel->parent = parent;
429
430         panel->callbacks.createWidgets = createPanel;
431         panel->callbacks.updateDomain = storeData;
432         panel->callbacks.undoChanges = undo;
433
434         AddSection(panel, ICON_FILE);
435
436         return panel;
437 }