]> icculus.org git repositories - mikachu/openbox.git/blob - otk/style.cc
support the button pressed resources better
[mikachu/openbox.git] / otk / style.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #ifdef HAVE_CONFIG_H
4 # include "../config.h"
5 #endif
6
7 #include <assert.h>
8 #include <iostream>
9
10 #include "display.hh"
11 #include "util.hh"
12 #include "style.hh"
13
14 namespace otk {
15
16 Style::Style() : font(NULL)
17 {
18 }
19
20 Style::Style(BImageControl *ctrl)
21   : image_control(ctrl), font(0),
22     screen_number(ctrl->getScreenInfo()->screen())
23 {
24 }
25
26 Style::~Style() {
27   if (font)
28     delete font;
29
30   if (close_button.mask != None)
31     XFreePixmap(OBDisplay::display, close_button.mask);
32   if (max_button.mask != None)
33     XFreePixmap(OBDisplay::display, max_button.mask);
34   if (icon_button.mask != None)
35     XFreePixmap(OBDisplay::display, icon_button.mask);
36   if (stick_button.mask != None)
37     XFreePixmap(OBDisplay::display, stick_button.mask);
38
39   max_button.mask = None;
40   close_button.mask = None;
41   icon_button.mask = None;
42   stick_button.mask = None;
43 }
44
45 void Style::load(const Configuration &style) {
46   std::string s;
47
48   // load fonts/fontsets
49   if (font)
50     delete font;
51
52   font = readDatabaseFont("window.", style);
53
54   // load window config
55   t_focus = readDatabaseTexture("window.title.focus", "white", style);
56   t_unfocus = readDatabaseTexture("window.title.unfocus", "black", style);
57
58   l_focus = readDatabaseTexture("window.label.focus", "white", style);
59   l_unfocus = readDatabaseTexture("window.label.unfocus", "black", style);
60
61   h_focus = readDatabaseTexture("window.handle.focus", "white", style);
62   h_unfocus = readDatabaseTexture("window.handle.unfocus", "black", style);
63
64   g_focus = readDatabaseTexture("window.grip.focus", "white", style);
65   g_unfocus = readDatabaseTexture("window.grip.unfocus", "black", style);
66
67   b_focus = readDatabaseTexture("window.button.focus", "white", style);
68   b_unfocus = readDatabaseTexture("window.button.unfocus", "black", style);
69
70   //if neither of these can be found, we will use the previous resource
71   b_pressed_focus = readDatabaseTexture("window.button.pressed.focus",
72                                         "black", style, true);
73   if (b_pressed_focus.texture() == BTexture::NoTexture) {
74     b_pressed_focus = readDatabaseTexture("window.button.pressed", "black",
75                                           style);
76   }
77     
78   b_pressed_unfocus = readDatabaseTexture("window.button.pressed.unfocus",
79                                           "black", style, true);
80   if (b_pressed_unfocus.texture() == BTexture::NoTexture) {
81     b_pressed_unfocus = readDatabaseTexture("window.button.pressed", "black",
82                                             style);
83   }
84
85   if (close_button.mask != None)
86     XFreePixmap(OBDisplay::display, close_button.mask);
87   if (max_button.mask != None)
88     XFreePixmap(OBDisplay::display, max_button.mask);
89   if (icon_button.mask != None)
90     XFreePixmap(OBDisplay::display, icon_button.mask);
91   if (stick_button.mask != None)
92     XFreePixmap(OBDisplay::display, stick_button.mask);
93
94   close_button.mask = max_button.mask = icon_button.mask
95                     = icon_button.mask = None;
96   
97   readDatabaseMask("window.button.close.mask", close_button, style);
98   readDatabaseMask("window.button.max.mask", max_button, style);
99   readDatabaseMask("window.button.icon.mask", icon_button, style);
100   readDatabaseMask("window.button.stick.mask", stick_button, style);
101
102   // we create the window.frame texture by hand because it exists only to
103   // make the code cleaner and is not actually used for display
104   BColor color = readDatabaseColor("window.frame.focusColor", "white",
105                                         style);
106   f_focus = BTexture("solid flat", screen_number, image_control);
107   f_focus.setColor(color);
108
109   color = readDatabaseColor("window.frame.unfocusColor", "white", style);
110   f_unfocus = BTexture("solid flat", screen_number, image_control);
111   f_unfocus.setColor(color);
112
113   l_text_focus = readDatabaseColor("window.label.focus.textColor",
114                                    "black", style);
115   l_text_unfocus = readDatabaseColor("window.label.unfocus.textColor",
116                                      "white", style);
117
118   b_pic_focus = readDatabaseColor("window.button.focus.picColor",
119                                   "black", style);
120   b_pic_unfocus = readDatabaseColor("window.button.unfocus.picColor",
121                                     "white", style);
122
123   justify = LeftJustify;
124
125   if (style.getValue("window.justify", s)) {
126     if (s == "right" || s == "Right")
127       justify = RightJustify;
128     else if (s == "center" || s == "Center")
129       justify = CenterJustify;
130   }
131
132   // sanity checks
133   if (t_focus.texture() == BTexture::Parent_Relative)
134     t_focus = f_focus;
135   if (t_unfocus.texture() == BTexture::Parent_Relative)
136     t_unfocus = f_unfocus;
137   if (h_focus.texture() == BTexture::Parent_Relative)
138     h_focus = f_focus;
139   if (h_unfocus.texture() == BTexture::Parent_Relative)
140     h_unfocus = f_unfocus;
141
142   border_color = readDatabaseColor("borderColor", "black", style);
143
144   // load bevel, border and handle widths
145
146   const ScreenInfo *s_info = OBDisplay::screenInfo(screen_number);
147   unsigned int width = s_info->rect().width();
148
149   if (! style.getValue("handleWidth", handle_width) ||
150       handle_width > width/2 || handle_width == 0)
151     handle_width = 6;
152
153   if (! style.getValue("borderWidth", border_width))
154     border_width = 1;
155
156   if (! style.getValue("bevelWidth", bevel_width)
157       || bevel_width > width/2 || bevel_width == 0)
158     bevel_width = 3;
159
160   if (! style.getValue("frameWidth", frame_width)
161       || frame_width > width/2)
162     frame_width = bevel_width;
163
164   if (style.getValue("rootCommand", s))
165     bexec(s, s_info->displayString());
166 }
167
168
169 void Style::readDatabaseMask(const std::string &rname, PixmapMask &pixmapMask,
170                              const Configuration &style) {
171   Window root_window = OBDisplay::screenInfo(screen_number)->rootWindow();
172   std::string s;
173   int hx, hy; //ignored
174   int ret = BitmapOpenFailed; //default to failure.
175   
176   if (style.getValue(rname, s))
177   {
178     if (s[0] != '/' && s[0] != '~')
179     {
180       std::string xbmFile = std::string("~/.openbox/buttons/") + s;
181       ret = XReadBitmapFile(OBDisplay::display, root_window,
182                             expandTilde(xbmFile).c_str(), &pixmapMask.w,
183                             &pixmapMask.h, &pixmapMask.mask, &hx, &hy);
184     } else
185       ret = XReadBitmapFile(OBDisplay::display, root_window,
186                             expandTilde(s).c_str(), &pixmapMask.w,
187                             &pixmapMask.h, &pixmapMask.mask, &hx, &hy);
188     
189     if (ret == BitmapSuccess)
190       return;
191   }
192
193   pixmapMask.mask = None;
194   pixmapMask.w = pixmapMask.h = 0;
195 }
196
197
198 BTexture Style::readDatabaseTexture(const std::string &rname,
199                                          const std::string &default_color,
200                                          const Configuration &style, 
201                                          bool allowNoTexture)
202 {
203   BTexture texture;
204   std::string s;
205
206   if (style.getValue(rname, s))
207     texture = BTexture(s);
208   else if (allowNoTexture) //no default
209     texture.setTexture(BTexture::NoTexture);
210   else
211     texture.setTexture(BTexture::Solid | BTexture::Flat);
212
213   // associate this texture with this screen
214   texture.setScreen(screen_number);
215   texture.setImageControl(image_control);
216
217   if (texture.texture() != BTexture::NoTexture) {
218     texture.setColor(readDatabaseColor(rname + ".color", default_color,
219                                        style));
220     texture.setColorTo(readDatabaseColor(rname + ".colorTo", default_color,
221                                          style));
222     texture.setBorderColor(readDatabaseColor(rname + ".borderColor",
223                                              default_color, style));
224   }
225
226   return texture;
227 }
228
229
230 BColor Style::readDatabaseColor(const std::string &rname,
231                                      const std::string &default_color,
232                                      const Configuration &style) {
233   BColor color;
234   std::string s;
235   if (style.getValue(rname, s))
236     color = BColor(s, screen_number);
237   else
238     color = BColor(default_color, screen_number);
239   return color;
240 }
241
242
243 BFont *Style::readDatabaseFont(const std::string &rbasename,
244                                const Configuration &style) {
245   std::string fontstring, s;
246
247   // XXX: load all this font stuff from the style...
248
249   bool dropShadow = True;
250     
251   unsigned char offset = 1;
252   if (style.getValue(rbasename + "xft.shadow.offset", s)) {
253     offset = atoi(s.c_str()); //doesn't detect errors
254     if (offset > CHAR_MAX)
255       offset = 1;
256   }
257
258   unsigned char tint = 0x40;
259   if (style.getValue(rbasename + "xft.shadow.tint", s)) {
260     tint = atoi(s.c_str());
261   }
262
263   fontstring = "Arial,Sans-9:bold";
264
265   // if this fails, it ::exit()'s
266   return new BFont(screen_number, fontstring, dropShadow, offset, tint);
267 }
268
269 }