1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // Configmenu.cc for Blackbox - An X11 Window Manager
3 // Copyright (c) 2001 - 2005 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000, 2002 - 2005
5 //         Bradley T Hughes <bhughes at trolltech.com>
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a
8 // copy of this software and associated documentation files (the "Software"),
9 // to deal in the Software without restriction, including without limitation
10 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 // and/or sell copies of the Software, and to permit persons to whom the
12 // Software is furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in
15 // all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 // DEALINGS IN THE SOFTWARE.
24 
25 #include "Configmenu.hh"
26 #include "Screen.hh"
27 #include "Slitmenu.hh"
28 #include "Toolbarmenu.hh"
29 
30 #include <Image.hh>
31 #include <Unicode.hh>
32 
33 
34 class ConfigFocusmenu : public bt::Menu {
35 public:
36   ConfigFocusmenu(bt::Application &app, unsigned int screen,
37                   BScreen *bscreen);
38 
39   void refresh(void);
40 
41 protected:
42   void itemClicked(unsigned int id, unsigned int);
43 
44 private:
45   BScreen *_bscreen;
46 };
47 
48 
49 class ConfigPlacementmenu : public bt::Menu {
50 public:
51   ConfigPlacementmenu(bt::Application &app, unsigned int screen,
52                       BScreen *bscreen);
53 
54   void refresh(void);
55 
56 protected:
57   void itemClicked(unsigned int id, unsigned int);
58 
59 private:
60   BScreen *_bscreen;
61 };
62 
63 
64 class ConfigDithermenu : public bt::Menu {
65 public:
66   ConfigDithermenu(bt::Application &app, unsigned int screen,
67                    BScreen *bscreen);
68 
69   void refresh(void);
70 
71 protected:
72   void itemClicked(unsigned int id, unsigned int);
73 
74 private:
75   BScreen *_bscreen;
76 };
77 
78 
79 enum {
80   FocusModel,
81   WindowPlacement,
82   ImageDithering,
83   OpaqueWindowMoving,
84   OpaqueWindowResizing,
85   FullMaximization,
86   FocusNewWindows,
87   FocusLastWindowOnWorkspace,
88   ChangeWorkspaceWithMouseWheel,
89   ShadeWindowWithMouseWheel,
90   ToolbarActionsWithMouseWheel,
91   DisableBindings,
92   ToolbarOptions,
93   SlitOptions,
94   ClickToFocus,
95   SloppyFocus,
96   AutoRaise,
97   ClickRaise,
98   IgnoreShadedWindows
99 };
100 
Configmenu(bt::Application & app,unsigned int screen,BScreen * bscreen)101 Configmenu::Configmenu(bt::Application &app, unsigned int screen,
102                        BScreen *bscreen)
103   : bt::Menu(app, screen), _bscreen(bscreen)
104 {
105   setAutoDelete(false);
106   setTitle(bt::toUnicode("Configuration Options"));
107   showTitle();
108 
109   ConfigFocusmenu *focusmenu =
110     new ConfigFocusmenu(app, screen, bscreen);
111   ConfigPlacementmenu *placementmenu =
112     new ConfigPlacementmenu(app, screen, bscreen);
113   ConfigDithermenu *dithermenu =
114     new ConfigDithermenu(app, screen, bscreen);
115 
116   insertItem(bt::toUnicode("Focus Model"), focusmenu, FocusModel);
117   insertItem(bt::toUnicode("Window Placement"),
118              placementmenu, WindowPlacement);
119   insertItem(bt::toUnicode("Image Dithering"), dithermenu, ImageDithering);
120   insertSeparator();
121   insertItem(bt::toUnicode("Opaque Window Moving"), OpaqueWindowMoving);
122   insertItem(bt::toUnicode("Opaque Window Resizing"), OpaqueWindowResizing);
123   insertItem(bt::toUnicode("Full Maximization"), FullMaximization);
124   insertItem(bt::toUnicode("Focus New Windows"), FocusNewWindows);
125   insertItem(bt::toUnicode("Focus Last Window on Workspace"),
126              FocusLastWindowOnWorkspace);
127   insertItem(bt::toUnicode("Change Workspace with Mouse Wheel"),
128              ChangeWorkspaceWithMouseWheel);
129   insertItem(bt::toUnicode("Shade Windows with Mouse Wheel"),
130              ShadeWindowWithMouseWheel);
131   insertItem(bt::toUnicode("Toolbar Actions with Mouse Wheel"),
132              ToolbarActionsWithMouseWheel);
133   insertItem(bt::toUnicode("Disable Bindings with Scroll Lock"),
134              DisableBindings);
135   insertSeparator();
136   insertItem(bt::toUnicode("Toolbar Options"),
137              bscreen->toolbarmenu(), ToolbarOptions);
138   insertItem(bt::toUnicode("Slit Options"), bscreen->slitmenu(), SlitOptions);
139 }
140 
141 
refresh(void)142 void Configmenu::refresh(void) {
143   const BlackboxResource &res = _bscreen->blackbox()->resource();
144   setItemChecked(OpaqueWindowMoving, res.opaqueMove());
145   setItemChecked(OpaqueWindowResizing, res.opaqueResize());
146   setItemChecked(FullMaximization, res.fullMaximization());
147   setItemChecked(FocusNewWindows, res.focusNewWindows());
148   setItemChecked(FocusLastWindowOnWorkspace, res.focusLastWindowOnWorkspace());
149   setItemChecked(ChangeWorkspaceWithMouseWheel,
150                  res.changeWorkspaceWithMouseWheel());
151   setItemChecked(ShadeWindowWithMouseWheel,
152                  res.shadeWindowWithMouseWheel());
153   setItemChecked(ToolbarActionsWithMouseWheel,
154                  res.toolbarActionsWithMouseWheel());
155   setItemChecked(DisableBindings, res.allowScrollLock());
156 }
157 
158 
itemClicked(unsigned int id,unsigned int)159 void Configmenu::itemClicked(unsigned int id, unsigned int) {
160   BlackboxResource &res = _bscreen->blackbox()->resource();
161   switch (id) {
162   case OpaqueWindowMoving: // opaque move
163     res.setOpaqueMove(!res.opaqueMove());
164     break;
165 
166   case OpaqueWindowResizing:
167     res.setOpaqueResize(!res.opaqueResize());
168     break;
169 
170   case FullMaximization: // full maximization
171     res.setFullMaximization(!res.fullMaximization());
172     break;
173 
174   case FocusNewWindows: // focus new windows
175     res.setFocusNewWindows(!res.focusNewWindows());
176     break;
177 
178   case FocusLastWindowOnWorkspace: // focus last window on workspace
179     res.setFocusLastWindowOnWorkspace(!res.focusLastWindowOnWorkspace());
180     break;
181 
182   case ChangeWorkspaceWithMouseWheel:
183     res.setChangeWorkspaceWithMouseWheel(!res.changeWorkspaceWithMouseWheel());
184     break;
185 
186   case ShadeWindowWithMouseWheel:
187     res.setShadeWindowWithMouseWheel(!res.shadeWindowWithMouseWheel());
188     break;
189 
190   case ToolbarActionsWithMouseWheel:
191     res.setToolbarActionsWithMouseWheel(!res.toolbarActionsWithMouseWheel());
192     break;
193 
194   case DisableBindings: // disable keybindings with Scroll Lock
195     res.setAllowScrollLock(!res.allowScrollLock());
196     _bscreen->blackbox()->reconfigure();
197     break;
198 
199   default:
200     return;
201   } // switch
202 
203   res.save(*_bscreen->blackbox());
204 }
205 
206 
ConfigFocusmenu(bt::Application & app,unsigned int screen,BScreen * bscreen)207 ConfigFocusmenu::ConfigFocusmenu(bt::Application &app, unsigned int screen,
208                                  BScreen *bscreen)
209   : bt::Menu(app, screen), _bscreen(bscreen)
210 {
211   setTitle(bt::toUnicode("Focus Model"));
212   showTitle();
213 
214   insertItem(bt::toUnicode("Click to Focus"), ClickToFocus);
215   insertItem(bt::toUnicode("Sloppy Focus"), SloppyFocus);
216   insertItem(bt::toUnicode("Auto Raise"), AutoRaise);
217   insertItem(bt::toUnicode("Click Raise"), ClickRaise);
218 }
219 
220 
refresh(void)221 void ConfigFocusmenu::refresh(void) {
222   const BlackboxResource &res = _bscreen->blackbox()->resource();
223 
224   setItemChecked(ClickToFocus, res.focusModel() == ClickToFocusModel);
225   setItemChecked(SloppyFocus, res.focusModel() == SloppyFocusModel);
226 
227   setItemEnabled(AutoRaise, res.focusModel() == SloppyFocusModel);
228   setItemChecked(AutoRaise, res.autoRaise());
229 
230   setItemEnabled(ClickRaise, res.focusModel() == SloppyFocusModel);
231   setItemChecked(ClickRaise, res.clickRaise());
232 }
233 
234 
itemClicked(unsigned int id,unsigned int)235 void ConfigFocusmenu::itemClicked(unsigned int id, unsigned int) {
236   BlackboxResource &res = _bscreen->blackbox()->resource();
237   switch (id) {
238   case ClickToFocus:
239     _bscreen->toggleFocusModel(ClickToFocusModel);
240     break;
241 
242   case SloppyFocus:
243     _bscreen->toggleFocusModel(SloppyFocusModel);
244     break;
245 
246   case AutoRaise: // auto raise with sloppy focus
247     res.setAutoRaise(!res.autoRaise());
248     break;
249 
250   case ClickRaise: // click raise with sloppy focus
251     res.setClickRaise(!res.clickRaise());
252     // make sure the appropriate mouse buttons are grabbed on the windows
253     _bscreen->toggleFocusModel(SloppyFocusModel);
254     break;
255 
256   default: return;
257   } // switch
258   res.save(*_bscreen->blackbox());
259 }
260 
261 
ConfigPlacementmenu(bt::Application & app,unsigned int screen,BScreen * bscreen)262 ConfigPlacementmenu::ConfigPlacementmenu(bt::Application &app,
263                                          unsigned int screen,
264                                          BScreen *bscreen)
265   : bt::Menu(app, screen), _bscreen(bscreen)
266 {
267   setTitle(bt::toUnicode("Window Placement"));
268   showTitle();
269 
270   insertItem(bt::toUnicode("Smart Placement (Rows)"), RowSmartPlacement);
271   insertItem(bt::toUnicode("Smart Placement (Columns)"), ColSmartPlacement);
272   insertItem(bt::toUnicode("Center Placement"), CenterPlacement);
273   insertItem(bt::toUnicode("Cascade Placement"), CascadePlacement);
274 
275   insertSeparator();
276 
277   insertItem(bt::toUnicode("Left to Right"), LeftRight);
278   insertItem(bt::toUnicode("Right to Left"), RightLeft);
279   insertItem(bt::toUnicode("Top to Bottom"), TopBottom);
280   insertItem(bt::toUnicode("Bottom to Top"), BottomTop);
281 
282   insertSeparator();
283 
284   insertItem(bt::toUnicode("Ignore Shaded Windows"), IgnoreShadedWindows);
285 }
286 
287 
refresh(void)288 void ConfigPlacementmenu::refresh(void) {
289   const BlackboxResource &res = _bscreen->blackbox()->resource();
290   bool rowsmart = res.windowPlacementPolicy() == RowSmartPlacement,
291        colsmart = res.windowPlacementPolicy() == ColSmartPlacement,
292          center = res.windowPlacementPolicy() == CenterPlacement,
293         cascade = res.windowPlacementPolicy() == CascadePlacement,
294              rl = res.rowPlacementDirection() == LeftRight,
295              tb = res.colPlacementDirection() == TopBottom;
296 
297   setItemChecked(RowSmartPlacement, rowsmart);
298   setItemChecked(ColSmartPlacement, colsmart);
299   setItemChecked(CenterPlacement, center);
300   setItemChecked(CascadePlacement, cascade);
301 
302   setItemEnabled(LeftRight, !center && !cascade);
303   setItemChecked(LeftRight, !center && (cascade || rl));
304 
305   setItemEnabled(RightLeft, !center && !cascade);
306   setItemChecked(RightLeft, !center && (!cascade && !rl));
307 
308   setItemEnabled(TopBottom, !center && !cascade);
309   setItemChecked(TopBottom, !center && (cascade || tb));
310 
311   setItemEnabled(BottomTop, !center && !cascade);
312   setItemChecked(BottomTop, !center && (!cascade && !tb));
313 
314   setItemEnabled(IgnoreShadedWindows, !center);
315   setItemChecked(IgnoreShadedWindows, !center && res.placementIgnoresShaded());
316 }
317 
318 
itemClicked(unsigned int id,unsigned int)319 void ConfigPlacementmenu::itemClicked(unsigned int id, unsigned int) {
320   BlackboxResource &res = _bscreen->blackbox()->resource();
321   switch (id) {
322   case RowSmartPlacement:
323   case ColSmartPlacement:
324   case CenterPlacement:
325   case CascadePlacement:
326     res.setWindowPlacementPolicy(id);
327     break;
328 
329   case LeftRight:
330   case RightLeft:
331     res.setRowPlacementDirection(id);
332     break;
333 
334   case TopBottom:
335   case BottomTop:
336     res.setColPlacementDirection(id);
337     break;
338 
339   case IgnoreShadedWindows:
340     res.setPlacementIgnoresShaded(! res.placementIgnoresShaded());
341     break;
342 
343   default:
344     return;
345   } // switch
346   res.save(*_bscreen->blackbox());
347 }
348 
349 
ConfigDithermenu(bt::Application & app,unsigned int screen,BScreen * bscreen)350 ConfigDithermenu::ConfigDithermenu(bt::Application &app, unsigned int screen,
351                                    BScreen *bscreen)
352   : bt::Menu(app, screen), _bscreen(bscreen)
353 {
354   setTitle(bt::toUnicode("Image Dithering"));
355   showTitle();
356 
357   insertItem(bt::toUnicode("Do not dither images"), bt::NoDither);
358   insertItem(bt::toUnicode("Use fast dither"), bt::OrderedDither);
359   insertItem(bt::toUnicode("Use high-quality dither"), bt::FloydSteinbergDither);
360 }
361 
362 
refresh(void)363 void ConfigDithermenu::refresh(void) {
364   setItemChecked(bt::NoDither,
365                  bt::Image::ditherMode() == bt::NoDither);
366   setItemChecked(bt::OrderedDither,
367                  bt::Image::ditherMode() == bt::OrderedDither);
368   setItemChecked(bt::FloydSteinbergDither,
369                  bt::Image::ditherMode() == bt::FloydSteinbergDither);
370 }
371 
372 
itemClicked(unsigned int id,unsigned int)373 void ConfigDithermenu::itemClicked(unsigned int id, unsigned int) {
374   bt::Image::setDitherMode((bt::DitherMode) id);
375   _bscreen->blackbox()->resource().save(*_bscreen->blackbox());
376 }
377