1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // ScreenResource.ccfor 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 "ScreenResource.hh"
26 
27 #include "Screen.hh"
28 #include "Slit.hh"
29 #include "Toolbar.hh"
30 
31 #include <cstring>
32 #include <Menu.hh>
33 #include <Resource.hh>
34 
35 #include <assert.h>
36 
37 
38 static const int iconify_width  = 9;
39 static const int iconify_height = 9;
40 static const unsigned char iconify_bits[] =
41   { 0x00, 0x00, 0x82, 0x00, 0xc6, 0x00, 0x6c, 0x00, 0x38,
42     0x00, 0x10, 0x00, 0x00, 0x00, 0xff, 0x01, 0xff, 0x01 };
43 
44 static const int maximize_width  = 9;
45 static const int maximize_height = 9;
46 static const unsigned char maximize_bits[] =
47   { 0xff, 0x01, 0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
48     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xff, 0x01 };
49 
50 static const int restore_width  = 9;
51 static const int restore_height = 9;
52 static const unsigned char restore_bits[] =
53   { 0xf8, 0x01, 0xf8, 0x01, 0x08, 0x01, 0x3f, 0x01, 0x3f,
54     0x01, 0xe1, 0x01, 0x21, 0x00, 0x21, 0x00, 0x3f, 0x00 };
55 
56 static const int close_width  = 9;
57 static const int close_height = 9;
58 static const unsigned char close_bits[] =
59   { 0x83, 0x01, 0xc7, 0x01, 0xee, 0x00, 0x7c, 0x00, 0x38,
60     0x00, 0x7c, 0x00, 0xee, 0x00, 0xc7, 0x01, 0x83, 0x01 };
61 
62 
save(bt::Resource & res,BScreen * screen)63 void ScreenResource::save(bt::Resource& res, BScreen* screen) {
64   char rc_string[128];
65   char *placement = (char *) 0;
66   unsigned int number = screen->screenNumber();
67 
68   switch (_slitOptions.placement) {
69   case Slit::TopLeft: placement = "TopLeft"; break;
70   case Slit::CenterLeft: placement = "CenterLeft"; break;
71   case Slit::BottomLeft: placement = "BottomLeft"; break;
72   case Slit::TopCenter: placement = "TopCenter"; break;
73   case Slit::BottomCenter: placement = "BottomCenter"; break;
74   case Slit::TopRight: placement = "TopRight"; break;
75   case Slit::BottomRight: placement = "BottomRight"; break;
76   case Slit::CenterRight: default: placement = "CenterRight"; break;
77   }
78 
79   sprintf(rc_string, "session.screen%u.slit.placement", number);
80   res.write(rc_string, placement);
81 
82   sprintf(rc_string, "session.screen%u.slit.direction", number);
83   res.write(rc_string, (_slitOptions.direction == Slit::Horizontal) ?
84             "Horizontal" : "Vertical");
85 
86   sprintf(rc_string, "session.screen%u.slit.onTop", number);
87   res.write(rc_string, _slitOptions.always_on_top);
88 
89   sprintf(rc_string, "session.screen%u.slit.autoHide", number);
90   res.write(rc_string, _slitOptions.auto_hide);
91 
92 
93   sprintf(rc_string,  "session.screen%u.enableToolbar", number);
94   res.write(rc_string, _toolbarOptions.enabled);
95 
96   sprintf(rc_string, "session.screen%u.toolbar.onTop", number);
97   res.write(rc_string, _toolbarOptions.always_on_top);
98 
99   sprintf(rc_string, "session.screen%u.toolbar.autoHide", number);
100   res.write(rc_string, _toolbarOptions.auto_hide);
101 
102   switch (_toolbarOptions.placement) {
103   case Toolbar::TopLeft: placement = "TopLeft"; break;
104   case Toolbar::BottomLeft: placement = "BottomLeft"; break;
105   case Toolbar::TopCenter: placement = "TopCenter"; break;
106   case Toolbar::TopRight: placement = "TopRight"; break;
107   case Toolbar::BottomRight: placement = "BottomRight"; break;
108   case Toolbar::BottomCenter: default: placement = "BottomCenter"; break;
109   }
110 
111   sprintf(rc_string, "session.screen%u.toolbar.placement", number);
112   res.write(rc_string, placement);
113 
114   sprintf(rc_string, "session.screen%u.workspaces", number);
115   res.write(rc_string, workspace_count);
116 
117   std::vector<bt::ustring>::const_iterator it = workspace_names.begin(),
118                                           end = workspace_names.end();
119   bt::ustring save_string = *it++;
120   for (; it != end; ++it) {
121     save_string += ',';
122     save_string += *it;
123   }
124 
125   sprintf(rc_string, "session.screen%u.workspaceNames", number);
126   res.write(rc_string, bt::toLocale(save_string).c_str());
127 
128   // these options can not be modified at runtime currently
129 
130   sprintf(rc_string, "session.screen%u.toolbar.widthPercent", number);
131   res.write(rc_string, _toolbarOptions.width_percent);
132 
133   sprintf(rc_string, "session.screen%u.strftimeFormat", number);
134   res.write(rc_string, _toolbarOptions.strftime_format.c_str());
135 }
136 
load(bt::Resource & res,unsigned int screen)137 void ScreenResource::load(bt::Resource& res, unsigned int screen) {
138   char name_lookup[128], class_lookup[128];
139   std::string str;
140 
141   // toolbar settings
142   sprintf(name_lookup,  "session.screen%u.enableToolbar", screen);
143   sprintf(class_lookup, "Session.screen%u.enableToolbar", screen);
144   _toolbarOptions.enabled = res.read(name_lookup, class_lookup, true);
145 
146   sprintf(name_lookup,  "session.screen%u.toolbar.widthPercent", screen);
147   sprintf(class_lookup, "Session.screen%u.Toolbar.WidthPercent", screen);
148   _toolbarOptions.width_percent = res.read(name_lookup, class_lookup, 66);
149 
150   sprintf(name_lookup, "session.screen%u.toolbar.placement", screen);
151   sprintf(class_lookup, "Session.screen%u.Toolbar.Placement", screen);
152   str = res.read(name_lookup, class_lookup, "BottomCenter");
153   if (! strcasecmp(str.c_str(), "TopLeft"))
154     _toolbarOptions.placement = Toolbar::TopLeft;
155   else if (! strcasecmp(str.c_str(), "BottomLeft"))
156     _toolbarOptions.placement = Toolbar::BottomLeft;
157   else if (! strcasecmp(str.c_str(), "TopCenter"))
158     _toolbarOptions.placement = Toolbar::TopCenter;
159   else if (! strcasecmp(str.c_str(), "TopRight"))
160     _toolbarOptions.placement = Toolbar::TopRight;
161   else if (! strcasecmp(str.c_str(), "BottomRight"))
162     _toolbarOptions.placement = Toolbar::BottomRight;
163   else
164     _toolbarOptions.placement = Toolbar::BottomCenter;
165 
166   sprintf(name_lookup,  "session.screen%u.toolbar.onTop", screen);
167   sprintf(class_lookup, "Session.screen%u.Toolbar.OnTop", screen);
168   _toolbarOptions.always_on_top = res.read(name_lookup, class_lookup, false);
169 
170   sprintf(name_lookup,  "session.screen%u.toolbar.autoHide", screen);
171   sprintf(class_lookup, "Session.screen%u.Toolbar.autoHide", screen);
172   _toolbarOptions.auto_hide = res.read(name_lookup, class_lookup, false);
173 
174   sprintf(name_lookup,  "session.screen%u.strftimeFormat", screen);
175   sprintf(class_lookup, "Session.screen%u.StrftimeFormat", screen);
176   _toolbarOptions.strftime_format =
177     res.read(name_lookup, class_lookup, "%I:%M %p");
178 
179   // slit settings
180   sprintf(name_lookup, "session.screen%u.slit.placement", screen);
181   sprintf(class_lookup, "Session.screen%u.Slit.Placement", screen);
182   str = res.read(name_lookup, class_lookup, "CenterRight");
183   if (! strcasecmp(str.c_str(), "TopLeft"))
184     _slitOptions.placement = Slit::TopLeft;
185   else if (! strcasecmp(str.c_str(), "CenterLeft"))
186     _slitOptions.placement = Slit::CenterLeft;
187   else if (! strcasecmp(str.c_str(), "BottomLeft"))
188     _slitOptions.placement = Slit::BottomLeft;
189   else if (! strcasecmp(str.c_str(), "TopCenter"))
190     _slitOptions.placement = Slit::TopCenter;
191   else if (! strcasecmp(str.c_str(), "BottomCenter"))
192     _slitOptions.placement = Slit::BottomCenter;
193   else if (! strcasecmp(str.c_str(), "TopRight"))
194     _slitOptions.placement = Slit::TopRight;
195   else if (! strcasecmp(str.c_str(), "BottomRight"))
196     _slitOptions.placement = Slit::BottomRight;
197   else
198     _slitOptions.placement = Slit::CenterRight;
199 
200   sprintf(name_lookup, "session.screen%u.slit.direction", screen);
201   sprintf(class_lookup, "Session.screen%u.Slit.Direction", screen);
202   str = res.read(name_lookup, class_lookup, "Vertical");
203   if (! strcasecmp(str.c_str(), "Horizontal"))
204     _slitOptions.direction = Slit::Horizontal;
205   else
206     _slitOptions.direction = Slit::Vertical;
207 
208   sprintf(name_lookup, "session.screen%u.slit.onTop", screen);
209   sprintf(class_lookup, "Session.screen%u.Slit.OnTop", screen);
210   _slitOptions.always_on_top = res.read(name_lookup, class_lookup, false);
211 
212   sprintf(name_lookup, "session.screen%u.slit.autoHide", screen);
213   sprintf(class_lookup, "Session.screen%u.Slit.AutoHide", screen);
214   _slitOptions.auto_hide = res.read(name_lookup, class_lookup, false);
215 
216   // general screen settings
217 
218   sprintf(name_lookup,  "session.screen%u.workspaces", screen);
219   sprintf(class_lookup, "Session.screen%u.Workspaces", screen);
220   workspace_count = res.read(name_lookup, class_lookup, 4);
221 
222   if (! workspace_names.empty())
223     workspace_names.clear();
224 
225   sprintf(name_lookup,  "session.screen%u.workspaceNames", screen);
226   sprintf(class_lookup, "Session.screen%u.WorkspaceNames", screen);
227   bt::ustring ustr = bt::toUnicode(res.read(name_lookup, class_lookup));
228   if (!ustr.empty()) {
229     bt::ustring::const_iterator it = ustr.begin();
230     const bt::ustring::const_iterator end = ustr.end();
231     for (;;) {
232       const bt::ustring::const_iterator i =
233         std::find(it, end, static_cast<bt::ustring::value_type>(','));
234       workspace_names.push_back(bt::ustring(it, i));
235       it = i;
236       if (it == end)
237         break;
238       ++it;
239     }
240   }
241 }
242 
243 
loadStyle(BScreen * screen,const std::string & style)244 void ScreenResource::loadStyle(BScreen* screen, const std::string& style) {
245   const bt::Display& display = screen->blackbox()->display();
246   unsigned int screen_num = screen->screenNumber();
247 
248   // use the user selected style
249   bt::Resource res(style);
250   if (!res.valid())
251     res.load(DEFAULTSTYLE);
252 
253   // load menu style
254   bt::MenuStyle::get(*screen->blackbox(), screen_num)->load(res);
255 
256   // load window style
257   _windowStyle.font.setFontName(res.read("window.font", "Window.Font"));
258 
259   _windowStyle.iconify.load(screen_num, iconify_bits,
260                             iconify_width, iconify_height);
261   _windowStyle.maximize.load(screen_num, maximize_bits,
262                              maximize_width, maximize_height);
263   _windowStyle.restore.load(screen_num, restore_bits,
264                             restore_width, restore_height);
265   _windowStyle.close.load(screen_num, close_bits,
266                           close_width, close_height);
267 
268   // focused window style
269   _windowStyle.focus.text =
270     bt::Color::namedColor(display, screen_num,
271                           res.read("window.label.focus.textColor",
272                                    "Window.Label.Focus.TextColor",
273                                    "black"));
274   _windowStyle.focus.foreground =
275     bt::Color::namedColor(display, screen_num,
276                           res.read("window.button.focus.foregroundColor",
277                                    "Window.Button.Focus.ForegroundColor",
278                                    res.read("window.button.focus.picColor",
279                                             "Window.Button.Focus.PicColor",
280                                             "black")));
281   _windowStyle.focus.title =
282     bt::textureResource(display, screen_num, res,
283                         "window.title.focus",
284                         "Window.Title.Focus",
285                         "white");
286   _windowStyle.focus.label =
287     bt::textureResource(display, screen_num, res,
288                         "window.label.focus",
289                         "Window.Label.Focus",
290                         "white");
291   _windowStyle.focus.button =
292     bt::textureResource(display, screen_num, res,
293                         "window.button.focus",
294                         "Window.Button.Focus",
295                         "white");
296   _windowStyle.focus.handle =
297     bt::textureResource(display, screen_num, res,
298                         "window.handle.focus",
299                         "Window.Handle.Focus",
300                         "white");
301   _windowStyle.focus.grip =
302     bt::textureResource(display, screen_num, res,
303                         "window.grip.focus",
304                         "Window.Grip.Focus",
305                         "white");
306   _windowStyle.focus.frame_border =
307     bt::Color::namedColor(display, screen_num,
308                           res.read("window.frame.focus.borderColor",
309                                    "Window.Frame.Focus.BorderColor",
310                                    "white"));
311 
312   // unfocused window style
313   _windowStyle.unfocus.text =
314     bt::Color::namedColor(display, screen_num,
315                           res.read("window.label.unfocus.textColor",
316                                    "Window.Label.Unfocus.TextColor",
317                                    "white"));
318   _windowStyle.unfocus.foreground =
319     bt::Color::namedColor(display, screen_num,
320                           res.read("window.button.unfocus.foregroundColor",
321                                    "Window.Button.Unfocus.ForegroundColor",
322                                    res.read("window.button.unfocus.picColor",
323                                             "Window.Button.Unfocus.PicColor",
324                                             "white")));
325   _windowStyle.unfocus.title =
326     bt::textureResource(display, screen_num, res,
327                         "window.title.unfocus",
328                         "Window.Title.Unfocus",
329                         "black");
330   _windowStyle.unfocus.label =
331     bt::textureResource(display, screen_num, res,
332                         "window.label.unfocus",
333                         "Window.Label.Unfocus",
334                         "black");
335   _windowStyle.unfocus.button =
336     bt::textureResource(display, screen_num, res,
337                         "window.button.unfocus",
338                         "Window.Button.Unfocus",
339                         "black");
340   _windowStyle.unfocus.handle =
341     bt::textureResource(display, screen_num, res,
342                         "window.handle.unfocus",
343                         "Window.Handle.Unfocus",
344                         "black");
345   _windowStyle.unfocus.grip =
346     bt::textureResource(display, screen_num, res,
347                         "window.grip.unfocus",
348                         "Window.Grip.Unfocus",
349                         "black");
350   _windowStyle.unfocus.frame_border =
351     bt::Color::namedColor(display, screen_num,
352 			  res.read("window.frame.unfocus.borderColor",
353                                    "Window.Frame.Unfocus.BorderColor",
354                                    "black"));
355 
356   _windowStyle.pressed =
357     bt::textureResource(display, screen_num, res,
358                         "window.button.pressed",
359                         "Window.Button.Pressed",
360                         "black");
361 
362   _windowStyle.alignment =
363     bt::alignResource(res, "window.alignment", "Window.Alignment");
364 
365   _windowStyle.title_margin =
366     res.read("window.title.marginWidth", "Window.Title.MarginWidth", 2);
367   _windowStyle.label_margin =
368     res.read("window.label.marginWidth", "Window.Label.MarginWidth", 2);
369   _windowStyle.button_margin =
370     res.read("window.button.marginWidth", "Window.Button.MarginWidth", 2);
371   _windowStyle.frame_border_width =
372     res.read("window.frame.borderWidth", "Window.Frame.BorderWidth", 1);
373   _windowStyle.handle_height =
374     res.read("window.handleHeight", "Window.HandleHeight", 6);
375 
376   // the height of the titlebar is based upon the height of the font being
377   // used to display the window's title
378   _windowStyle.button_width =
379     std::max(std::max(std::max(std::max(_windowStyle.iconify.width(),
380                                         _windowStyle.iconify.height()),
381                                std::max(_windowStyle.maximize.width(),
382                                         _windowStyle.maximize.height())),
383                       std::max(_windowStyle.restore.width(),
384                                _windowStyle.restore.height())),
385              std::max(_windowStyle.close.width(),
386                       _windowStyle.close.height())) +
387     ((std::max(_windowStyle.focus.button.borderWidth(),
388                _windowStyle.unfocus.button.borderWidth()) +
389       _windowStyle.button_margin) * 2);
390   _windowStyle.label_height =
391     std::max(bt::textHeight(screen_num, _windowStyle.font) +
392              ((std::max(_windowStyle.focus.label.borderWidth(),
393                         _windowStyle.unfocus.label.borderWidth()) +
394                _windowStyle.label_margin) * 2),
395              _windowStyle.button_width);
396   _windowStyle.button_width = std::max(_windowStyle.button_width,
397                                        _windowStyle.label_height);
398   _windowStyle.title_height =
399     _windowStyle.label_height +
400     ((std::max(_windowStyle.focus.title.borderWidth(),
401                _windowStyle.unfocus.title.borderWidth()) +
402       _windowStyle.title_margin) * 2);
403   _windowStyle.grip_width = (_windowStyle.button_width * 2);
404   _windowStyle.handle_height +=
405     (std::max(_windowStyle.focus.handle.borderWidth(),
406               _windowStyle.unfocus.handle.borderWidth()) * 2);
407 
408   // load toolbar style
409   _toolbarStyle.font.setFontName(res.read("toolbar.font", "Toolbar.Font"));
410 
411   _toolbarStyle.toolbar =
412     bt::textureResource(display, screen_num, res,
413                         "toolbar",
414                         "Toolbar",
415                         "white");
416   _toolbarStyle.slabel =
417     bt::textureResource(display, screen_num, res,
418                         "toolbar.label",
419                         "Toolbar.Label",
420                         "white");
421   _toolbarStyle.wlabel =
422     bt::textureResource(display, screen_num, res,
423                         "toolbar.windowLabel",
424                         "Toolbar.Label",
425                         "white");
426   _toolbarStyle.button =
427     bt::textureResource(display, screen_num, res,
428                         "toolbar.button",
429                         "Toolbar.Button",
430                         "white");
431   _toolbarStyle.pressed =
432     bt::textureResource(display, screen_num, res,
433                         "toolbar.button.pressed",
434                         "Toolbar.Button.Pressed",
435                         "black");
436 
437   _toolbarStyle.clock =
438     bt::textureResource(display, screen_num, res,
439                         "toolbar.clock",
440                         "Toolbar.Label",
441                         "white");
442 
443   _toolbarStyle.slabel_text =
444     bt::Color::namedColor(display, screen_num,
445                           res.read("toolbar.label.textColor",
446                                    "Toolbar.Label.TextColor",
447                                    "black"));
448   _toolbarStyle.wlabel_text =
449     bt::Color::namedColor(display, screen_num,
450                           res.read("toolbar.windowLabel.textColor",
451                                    "Toolbar.Label.TextColor",
452                                    "black"));
453   _toolbarStyle.clock_text =
454     bt::Color::namedColor(display, screen_num,
455                           res.read("toolbar.clock.textColor",
456                                    "Toolbar.Label.TextColor",
457                                    "black"));
458   _toolbarStyle.foreground =
459     bt::Color::namedColor(display, screen_num,
460                           res.read("toolbar.button.foregroundColor",
461                                    "Toolbar.Button.ForegroundColor",
462                                    res.read("toolbar.button.picColor",
463                                             "Toolbar.Button.PicColor",
464                                             "black")));
465   _toolbarStyle.alignment =
466     bt::alignResource(res, "toolbar.alignment", "Toolbar.Alignment");
467 
468   _toolbarStyle.frame_margin =
469     res.read("toolbar.marginWidth", "Toolbar.MarginWidth", 2);
470   _toolbarStyle.label_margin =
471     res.read("toolbar.label.marginWidth", "Toolbar.Label.MarginWidth", 2);
472   _toolbarStyle.button_margin =
473     res.read("toolbar.button.marginWidth", "Toolbar.Button.MarginWidth", 2);
474 
475   const bt::Bitmap &left = bt::Bitmap::leftArrow(screen_num),
476                   &right = bt::Bitmap::rightArrow(screen_num);
477   _toolbarStyle.button_width =
478     std::max(std::max(left.width(), left.height()),
479              std::max(right.width(), right.height()))
480     + ((_toolbarStyle.button.borderWidth() + _toolbarStyle.button_margin) * 2);
481   _toolbarStyle.label_height =
482     std::max(bt::textHeight(screen_num, _toolbarStyle.font)
483              + ((std::max(std::max(_toolbarStyle.slabel.borderWidth(),
484                                    _toolbarStyle.wlabel.borderWidth()),
485                           _toolbarStyle.clock.borderWidth())
486                  + _toolbarStyle.label_margin) * 2),
487              _toolbarStyle.button_width);
488   _toolbarStyle.button_width = std::max(_toolbarStyle.button_width,
489                                         _toolbarStyle.label_height);
490   _toolbarStyle.toolbar_height = _toolbarStyle.label_height
491                                  + ((_toolbarStyle.toolbar.borderWidth()
492                                      + _toolbarStyle.frame_margin) * 2);
493   _toolbarStyle.hidden_height =
494     std::max(_toolbarStyle.toolbar.borderWidth()
495              + _toolbarStyle.frame_margin, 1u);
496 
497   // load slit style
498   _slitStyle.slit = bt::textureResource(display,
499                                         screen_num,
500                                         res,
501                                         "slit",
502                                         "Slit",
503                                         _toolbarStyle.toolbar);
504   _slitStyle.margin = res.read("slit.marginWidth", "Slit.MarginWidth", 2);
505 
506   const std::string rc_file = screen->blackbox()->resource().rcFilename();
507   root_command =
508     bt::Resource(rc_file).read("rootCommand",
509                                "RootCommand",
510                                res.read("rootCommand",
511                                         "RootCommand"));
512 
513   // sanity checks
514   bt::Texture flat_black;
515   flat_black.setDescription("flat solid");
516   flat_black.setColor1(bt::Color(0, 0, 0));
517 
518   if (_windowStyle.focus.title.texture() == bt::Texture::Parent_Relative)
519     _windowStyle.focus.title = flat_black;
520   if (_windowStyle.unfocus.title.texture() == bt::Texture::Parent_Relative)
521     _windowStyle.unfocus.title = flat_black;
522   if (_windowStyle.focus.handle.texture() == bt::Texture::Parent_Relative)
523     _windowStyle.focus.handle = flat_black;
524   if (_windowStyle.unfocus.handle.texture() == bt::Texture::Parent_Relative)
525     _windowStyle.unfocus.handle = flat_black;
526   if (_windowStyle.focus.grip.texture() == bt::Texture::Parent_Relative)
527     _windowStyle.focus.grip = flat_black;
528   if (_windowStyle.unfocus.grip.texture() == bt::Texture::Parent_Relative)
529     _windowStyle.unfocus.grip = flat_black;
530 
531   if (_toolbarStyle.toolbar.texture() == bt::Texture::Parent_Relative)
532     _toolbarStyle.toolbar = flat_black;
533 
534   if (_slitStyle.slit.texture() == bt::Texture::Parent_Relative)
535     _slitStyle.slit = flat_black;
536 }
537 
workspaceName(unsigned int i) const538 const bt::ustring ScreenResource::workspaceName(unsigned int i) const {
539   // handle both requests for new workspaces beyond what we started with
540   // and for those that lack a name
541   if (i > workspace_count || i >= workspace_names.size())
542     return bt::ustring();
543   return workspace_names[i];
544 }
545 
setWorkspaceName(unsigned int i,const bt::ustring & name)546 void ScreenResource::setWorkspaceName(unsigned int i,
547                                       const bt::ustring &name) {
548     if (i >= workspace_names.size()) {
549         workspace_names.reserve(i + 1);
550         workspace_names.insert(workspace_names.begin() + i, name);
551     } else {
552         workspace_names[i] = name;
553     }
554 }
555