1 /* WindowHandling.c- options for handling windows
3 * WPrefs - Window Maker Preferences Program
5 * Copyright (c) 1998-2003 Alfredo K. Kojima
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.
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.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 typedef struct _Panel
{
31 CallbackRec callbacks
;
63 WMButton
*opaqresizeB
;
67 WMPopUpButton
*dragmaxP
;
70 #define ICON_FILE "whandling"
72 #define OPAQUE_MOVE_PIXMAP "opaque"
74 #define NON_OPAQUE_MOVE_PIXMAP "nonopaque"
76 #define OPAQUE_RESIZE_PIXMAP "opaqueresize"
78 #define NON_OPAQUE_RESIZE_PIXMAP "noopaqueresize"
85 } window_placements
[] = {
86 { "auto", N_("Automatic") },
87 { "random", N_("Random") },
88 { "manual", N_("Manual") },
89 { "cascade", N_("Cascade") },
90 { "smart", N_("Smart") },
91 { "center", N_("Center") }
97 } drag_maximized_window_options
[] = {
98 { "Move", N_("...change position (normal behavior)") },
99 { "RestoreGeometry", N_("...restore unmaximized geometry") },
100 { "Unmaximize", N_("...consider the window unmaximized") },
101 { "NoMove", N_("...do not move the window") }
104 static void sliderCallback(WMWidget
* w
, void *data
)
106 _Panel
*panel
= (_Panel
*) data
;
109 int swidth
= WMGetSliderMaxValue(panel
->hsli
);
110 int sheight
= WMGetSliderMaxValue(panel
->vsli
);
112 /* Parameter not used, but tell the compiler that it is ok */
115 x
= WMGetSliderValue(panel
->hsli
);
116 y
= WMGetSliderValue(panel
->vsli
);
118 rx
= x
* (WMWidgetWidth(panel
->porigF
) - 3) / swidth
+ 2;
119 ry
= y
* (WMWidgetHeight(panel
->porigF
) - 3) / sheight
+ 2;
120 WMMoveWidget(panel
->porigW
, rx
, ry
);
122 sprintf(buffer
, "(%i,%i)", x
, y
);
123 WMSetLabelText(panel
->porigvL
, buffer
);
126 static void resistanceCallback(WMWidget
* w
, void *data
)
128 _Panel
*panel
= (_Panel
*) data
;
132 /* Parameter not used, but tell the compiler that it is ok */
135 i
= WMGetSliderValue(panel
->resS
);
138 WMSetLabelText(panel
->resL
, _("OFF"));
140 sprintf(buffer
, "%i", i
);
141 WMSetLabelText(panel
->resL
, buffer
);
145 static void resizeCallback(WMWidget
* w
, void *data
)
147 _Panel
*panel
= (_Panel
*) data
;
151 /* Parameter not used, but tell the compiler that it is ok */
154 i
= WMGetSliderValue(panel
->resizeS
);
157 WMSetLabelText(panel
->resizeL
, _("OFF"));
159 sprintf(buffer
, "%i", i
);
160 WMSetLabelText(panel
->resizeL
, buffer
);
164 static int getPlacement(const char *str
)
171 for (i
= 0; i
< wlengthof(window_placements
); i
++) {
172 if (strcasecmp(str
, window_placements
[i
].db_value
) == 0)
176 wwarning(_("bad option value %s in WindowPlacement. Using default value"), str
);
180 static int getDragMaximizedWindow(const char *str
)
187 for (i
= 0; i
< wlengthof(drag_maximized_window_options
); i
++) {
188 if (strcasecmp(str
, drag_maximized_window_options
[i
].db_value
) == 0)
192 wwarning(_("bad option value %s in WindowPlacement. Using default value"), str
);
197 static void showData(_Panel
* panel
)
203 str
= GetStringForKey("WindowPlacement");
205 WMSetPopUpButtonSelectedItem(panel
->placP
, getPlacement(str
));
207 arr
= GetObjectForKey("WindowPlaceOrigin");
211 if (arr
&& (!WMIsPLArray(arr
) || WMGetPropListItemCount(arr
) != 2)) {
212 wwarning(_("invalid data in option WindowPlaceOrigin. Using default (0,0)"));
215 x
= atoi(WMGetFromPLString(WMGetFromPLArray(arr
, 0)));
216 y
= atoi(WMGetFromPLString(WMGetFromPLArray(arr
, 1)));
220 WMSetSliderValue(panel
->hsli
, x
);
221 WMSetSliderValue(panel
->vsli
, y
);
223 sliderCallback(NULL
, panel
);
225 x
= GetIntegerForKey("EdgeResistance");
226 WMSetSliderValue(panel
->resS
, x
);
227 resistanceCallback(NULL
, panel
);
229 str
= GetStringForKey("DragMaximizedWindow");
230 WMSetPopUpButtonSelectedItem(panel
->dragmaxP
, getDragMaximizedWindow(str
));
232 x
= GetIntegerForKey("ResizeIncrement");
233 WMSetSliderValue(panel
->resizeS
, x
);
234 resizeCallback(NULL
, panel
);
236 WMSetButtonSelected(panel
->opaqB
, GetBoolForKey("OpaqueMove"));
237 WMSetButtonSelected(panel
->opaqresizeB
, GetBoolForKey("OpaqueResize"));
238 WMSetButtonSelected(panel
->opaqkeybB
, GetBoolForKey("OpaqueMoveResizeKeyboard"));
240 WMSetButtonSelected(panel
->miconB
, GetBoolForKey("NoWindowOverIcons"));
241 WMSetButtonSelected(panel
->mdockB
, GetBoolForKey("NoWindowOverDock"));
243 if (GetBoolForKey("Attraction"))
244 WMPerformButtonClick(panel
->resrB
);
246 WMPerformButtonClick(panel
->resaB
);
249 static void storeData(_Panel
* panel
)
255 SetBoolForKey(WMGetButtonSelected(panel
->miconB
), "NoWindowOverIcons");
256 SetBoolForKey(WMGetButtonSelected(panel
->mdockB
), "NoWindowOverDock");
258 SetBoolForKey(WMGetButtonSelected(panel
->opaqB
), "OpaqueMove");
259 SetBoolForKey(WMGetButtonSelected(panel
->opaqresizeB
), "OpaqueResize");
260 SetBoolForKey(WMGetButtonSelected(panel
->opaqkeybB
), "OpaqueMoveResizeKeyboard");
262 SetStringForKey(window_placements
[WMGetPopUpButtonSelectedItem(panel
->placP
)].db_value
, "WindowPlacement");
263 sprintf(buf
, "%i", WMGetSliderValue(panel
->hsli
));
264 x
= WMCreatePLString(buf
);
265 sprintf(buf
, "%i", WMGetSliderValue(panel
->vsli
));
266 y
= WMCreatePLString(buf
);
267 arr
= WMCreatePLArray(x
, y
, NULL
);
268 WMReleasePropList(x
);
269 WMReleasePropList(y
);
270 SetObjectForKey(arr
, "WindowPlaceOrigin");
272 SetIntegerForKey(WMGetSliderValue(panel
->resS
), "EdgeResistance");
274 SetStringForKey(drag_maximized_window_options
[WMGetPopUpButtonSelectedItem(panel
->dragmaxP
)].db_value
,
275 "DragMaximizedWindow");
277 SetIntegerForKey(WMGetSliderValue(panel
->resizeS
), "ResizeIncrement");
278 SetBoolForKey(WMGetButtonSelected(panel
->resrB
), "Attraction");
280 WMReleasePropList(arr
);
283 static void createPanel(Panel
* p
)
285 _Panel
*panel
= (Panel
*) p
;
286 WMScreen
*scr
= WMWidgetScreen(panel
->parent
);
295 panel
->box
= WMCreateBox(panel
->parent
);
296 WMSetViewExpandsToParent(WMWidgetView(panel
->box
), 2, 2, 2, 2);
297 WMSetBoxHorizontal(panel
->box
, False
);
298 WMSetBoxBorderWidth(panel
->box
, 8);
300 hbox
= WMCreateBox(panel
->box
);
301 WMSetBoxHorizontal(hbox
, True
);
302 WMAddBoxSubview(panel
->box
, WMWidgetView(hbox
), False
, True
, 110, 0, 10);
304 /************** Window Placement ***************/
305 panel
->placF
= WMCreateFrame(panel
->box
);
306 WMResizeWidget(panel
->placF
, 222, 163);
307 WMMoveWidget(panel
->placF
, 8, 6);
308 WMSetFrameTitle(panel
->placF
, _("Window Placement"));
309 WMSetBalloonTextForView(_("How to place windows when they are first put\n"
310 "on screen."), WMWidgetView(panel
->placF
));
312 panel
->placP
= WMCreatePopUpButton(panel
->placF
);
313 WMResizeWidget(panel
->placP
, 90, 20);
314 WMMoveWidget(panel
->placP
, 9, 19);
316 for (i
= 0; i
< wlengthof(window_placements
); i
++)
317 WMAddPopUpButtonItem(panel
->placP
, _(window_placements
[i
].label
));
319 panel
->porigL
= WMCreateLabel(panel
->placF
);
320 WMResizeWidget(panel
->porigL
, 50, 20);
321 WMMoveWidget(panel
->porigL
, 100, 19);
322 WMSetLabelTextAlignment(panel
->porigL
, WARight
);
323 WMSetLabelText(panel
->porigL
, _("Origin:"));
325 panel
->porigvL
= WMCreateLabel(panel
->placF
);
326 WMResizeWidget(panel
->porigvL
, 69, 20);
327 WMMoveWidget(panel
->porigvL
, 150, 19);
328 WMSetLabelTextAlignment(panel
->porigvL
, WACenter
);
330 color
= WMCreateRGBColor(scr
, 0x5100, 0x5100, 0x7100, True
);
331 panel
->porigF
= WMCreateFrame(panel
->placF
);
332 WMSetWidgetBackgroundColor(panel
->porigF
, color
);
333 WMReleaseColor(color
);
334 WMSetFrameRelief(panel
->porigF
, WRSunken
);
337 * There is an available area of 204 x 109, starting at x=9 y=45
338 * We have to keep 12 pixels in each direction for the sliders,
339 * and an extra pixel for spacing.
340 * In this area, we want to have a rectangle with the same aspect
341 * ratio as the screen.
343 swidth
= WidthOfScreen(DefaultScreenOfDisplay(WMScreenDisplay(scr
)));
344 sheight
= HeightOfScreen(DefaultScreenOfDisplay(WMScreenDisplay(scr
)));
346 width
= swidth
* (109 - 13) / sheight
;
347 if (width
<= (204 - 13)) {
351 height
= sheight
* (204 - 13) / swidth
;
353 WMResizeWidget(panel
->porigF
, width
, height
);
354 WMMoveWidget(panel
->porigF
, 9 + (204 - 13 - width
) / 2, 45 + (109 - 13 - height
) / 2);
356 panel
->porigW
= WMCreateLabel(panel
->porigF
);
357 WMResizeWidget(panel
->porigW
, THUMB_SIZE
, THUMB_SIZE
);
358 WMMoveWidget(panel
->porigW
, 2, 2);
359 WMSetLabelRelief(panel
->porigW
, WRRaised
);
361 panel
->hsli
= WMCreateSlider(panel
->placF
);
362 WMResizeWidget(panel
->hsli
, width
, 12);
363 WMMoveWidget(panel
->hsli
, 9 + (204 - 13 - width
) / 2, 45 + (109 - 13 - height
) / 2 + height
+ 1);
364 WMSetSliderAction(panel
->hsli
, sliderCallback
, panel
);
365 WMSetSliderMinValue(panel
->hsli
, 0);
366 WMSetSliderMaxValue(panel
->hsli
, swidth
);
368 panel
->vsli
= WMCreateSlider(panel
->placF
);
369 WMResizeWidget(panel
->vsli
, 12, height
);
370 WMMoveWidget(panel
->vsli
, 9 + (204 - 13 - width
) / 2 + width
+ 1, 45 + (109 - 13 - height
) / 2);
371 WMSetSliderAction(panel
->vsli
, sliderCallback
, panel
);
372 WMSetSliderMinValue(panel
->vsli
, 0);
373 WMSetSliderMaxValue(panel
->vsli
, sheight
);
375 WMMapSubwidgets(panel
->porigF
);
377 WMMapSubwidgets(panel
->placF
);
379 /************** Opaque Move, Resize ***************/
380 panel
->opaqF
= WMCreateFrame(panel
->box
);
381 WMResizeWidget(panel
->opaqF
, 140, 118);
382 WMMoveWidget(panel
->opaqF
, 372, 103);
384 WMSetFrameTitle(panel
->opaqF
, _("Opaque Move/Resize"));
385 WMSetBalloonTextForView(_("Whether the window contents or only a frame should\n"
386 "be displayed during a move or resize.\n"),
387 WMWidgetView(panel
->opaqF
));
389 panel
->opaqB
= WMCreateButton(panel
->opaqF
, WBTToggle
);
390 WMResizeWidget(panel
->opaqB
, 54, 54);
391 WMMoveWidget(panel
->opaqB
, 11, 22);
392 WMSetButtonImagePosition(panel
->opaqB
, WIPImageOnly
);
394 path
= LocateImage(NON_OPAQUE_MOVE_PIXMAP
);
396 pixmap
= WMCreatePixmapFromFile(scr
, path
);
398 WMSetButtonImage(panel
->opaqB
, pixmap
);
399 WMReleasePixmap(pixmap
);
401 wwarning(_("could not load icon %s"), path
);
406 path
= LocateImage(OPAQUE_MOVE_PIXMAP
);
408 pixmap
= WMCreatePixmapFromFile(scr
, path
);
410 WMSetButtonAltImage(panel
->opaqB
, pixmap
);
411 WMReleasePixmap(pixmap
);
413 wwarning(_("could not load icon %s"), path
);
420 panel
->opaqresizeB
= WMCreateButton(panel
->opaqF
, WBTToggle
);
421 WMResizeWidget(panel
->opaqresizeB
, 54, 54);
422 WMMoveWidget(panel
->opaqresizeB
, 75, 22);
423 WMSetButtonImagePosition(panel
->opaqresizeB
, WIPImageOnly
);
425 path
= LocateImage(NON_OPAQUE_RESIZE_PIXMAP
);
427 pixmap
= WMCreatePixmapFromFile(scr
, path
);
429 WMSetButtonImage(panel
->opaqresizeB
, pixmap
);
430 WMReleasePixmap(pixmap
);
432 wwarning(_("could not load icon %s"), path
);
437 path
= LocateImage(OPAQUE_RESIZE_PIXMAP
);
439 pixmap
= WMCreatePixmapFromFile(scr
, path
);
441 WMSetButtonAltImage(panel
->opaqresizeB
, pixmap
);
442 WMReleasePixmap(pixmap
);
444 wwarning(_("could not load icon %s"), path
);
449 panel
->opaqkeybB
= WMCreateSwitchButton(panel
->opaqF
);
450 WMResizeWidget(panel
->opaqkeybB
, 122, 25);
451 WMMoveWidget(panel
->opaqkeybB
, 11, 85);
452 WMSetButtonText(panel
->opaqkeybB
, _("by keyboard"));
454 WMSetBalloonTextForView(_("When selected, moving or resizing windows\n"
455 "using keyboard shortcuts will also display its\n"
456 "content instead of just a frame."), WMWidgetView(panel
->opaqkeybB
));
458 WMMapSubwidgets(panel
->opaqF
);
461 /**************** Account for Icon/Dock ***************/
462 panel
->maxiF
= WMCreateFrame(panel
->box
);
463 WMResizeWidget(panel
->maxiF
, 140, 92);
464 WMMoveWidget(panel
->maxiF
, 372, 6);
465 WMSetFrameTitle(panel
->maxiF
, _("When maximizing..."));
467 panel
->maxiL
= WMCreateLabel(panel
->maxiF
);
468 WMSetLabelText(panel
->maxiL
, _("...do not cover:"));
469 WMResizeWidget(panel
->maxiL
, 120, 20);
470 WMMoveWidget(panel
->maxiL
, 10, 16);
472 panel
->miconB
= WMCreateSwitchButton(panel
->maxiF
);
473 WMResizeWidget(panel
->miconB
, 120, 25);
474 WMMoveWidget(panel
->miconB
, 10, 36);
475 WMSetButtonText(panel
->miconB
, _("Icons"));
477 panel
->mdockB
= WMCreateSwitchButton(panel
->maxiF
);
478 WMResizeWidget(panel
->mdockB
, 120, 25);
479 WMMoveWidget(panel
->mdockB
, 10, 61);
480 WMSetButtonText(panel
->mdockB
, _("The dock"));
482 WMMapSubwidgets(panel
->maxiF
);
484 /**************** Resize with Mod+Wheel ***************/
485 panel
->resizeF
= WMCreateFrame(panel
->box
);
486 WMResizeWidget(panel
->resizeF
, 127, 66);
487 WMMoveWidget(panel
->resizeF
, 238, 103);
488 WMSetFrameTitle(panel
->resizeF
, _("Mod+Wheel"));
490 panel
->resizeTextL
= WMCreateLabel(panel
->resizeF
);
491 WMSetLabelText(panel
->resizeTextL
, _("Resize increment:"));
492 WMResizeWidget(panel
->resizeTextL
, 118, 20);
493 WMMoveWidget(panel
->resizeTextL
, 5, 16);
495 panel
->resizeS
= WMCreateSlider(panel
->resizeF
);
496 WMResizeWidget(panel
->resizeS
, 80, 15);
497 WMMoveWidget(panel
->resizeS
, 9, 40);
498 WMSetSliderMinValue(panel
->resizeS
, 0);
499 WMSetSliderMaxValue(panel
->resizeS
, 100);
500 WMSetSliderAction(panel
->resizeS
, resizeCallback
, panel
);
502 panel
->resizeL
= WMCreateLabel(panel
->resizeF
);
503 WMResizeWidget(panel
->resizeL
, 30, 15);
504 WMMoveWidget(panel
->resizeL
, 90, 40);
506 WMMapSubwidgets(panel
->resizeF
);
508 /**************** Edge Resistance ****************/
509 panel
->resF
= WMCreateFrame(panel
->box
);
510 WMResizeWidget(panel
->resF
, 127, 92);
511 WMMoveWidget(panel
->resF
, 238, 6);
512 WMSetFrameTitle(panel
->resF
, _("Edge Resistance"));
514 WMSetBalloonTextForView(_("Edge resistance will make windows `resist'\n"
515 "being moved further for the defined threshold\n"
516 "when moved against other windows or the edges\n"
517 "of the screen."), WMWidgetView(panel
->resF
));
519 panel
->resS
= WMCreateSlider(panel
->resF
);
520 WMResizeWidget(panel
->resS
, 80, 15);
521 WMMoveWidget(panel
->resS
, 9, 20);
522 WMSetSliderMinValue(panel
->resS
, 0);
523 WMSetSliderMaxValue(panel
->resS
, 80);
524 WMSetSliderAction(panel
->resS
, resistanceCallback
, panel
);
526 panel
->resL
= WMCreateLabel(panel
->resF
);
527 WMResizeWidget(panel
->resL
, 30, 15);
528 WMMoveWidget(panel
->resL
, 90, 22);
530 panel
->resaB
= WMCreateRadioButton(panel
->resF
);
531 WMMoveWidget(panel
->resaB
, 9, 39);
532 WMResizeWidget(panel
->resaB
, 107, 23);
533 WMSetButtonText(panel
->resaB
, _("Resist"));
535 panel
->resrB
= WMCreateRadioButton(panel
->resF
);
536 WMMoveWidget(panel
->resrB
, 9, 62);
537 WMResizeWidget(panel
->resrB
, 107, 23);
538 WMSetButtonText(panel
->resrB
, _("Attract"));
539 WMGroupButtons(panel
->resrB
, panel
->resaB
);
541 WMMapSubwidgets(panel
->resF
);
543 /**************** Dragging a Maximized Window ****************/
544 panel
->dragmaxF
= WMCreateFrame(panel
->box
);
545 WMResizeWidget(panel
->dragmaxF
, 357, 49);
546 WMMoveWidget(panel
->dragmaxF
, 8, 172);
547 WMSetFrameTitle(panel
->dragmaxF
, _("When dragging a maximized window..."));
549 panel
->dragmaxP
= WMCreatePopUpButton(panel
->dragmaxF
);
550 WMResizeWidget(panel
->dragmaxP
, 328, 20);
551 WMMoveWidget(panel
->dragmaxP
, 15, 18);
553 for (i
= 0; i
< wlengthof(drag_maximized_window_options
); i
++)
554 WMAddPopUpButtonItem(panel
->dragmaxP
, _(drag_maximized_window_options
[i
].label
));
556 WMMapSubwidgets(panel
->dragmaxF
);
558 WMRealizeWidget(panel
->box
);
559 WMMapSubwidgets(panel
->box
);
561 /* show the config data */
565 static void undo(_Panel
* panel
)
570 Panel
*InitWindowHandling(WMWidget
*parent
)
574 panel
= wmalloc(sizeof(_Panel
));
576 panel
->sectionName
= _("Window Handling Preferences");
578 panel
->description
= _("Window handling options. Initial placement style\n"
579 "edge resistance, opaque move etc.");
581 panel
->parent
= parent
;
583 panel
->callbacks
.createWidgets
= createPanel
;
584 panel
->callbacks
.updateDomain
= storeData
;
585 panel
->callbacks
.undoChanges
= undo
;
587 AddSection(panel
, ICON_FILE
);