diff options
Diffstat (limited to 'src/RootTheme.cc')
-rw-r--r-- | src/RootTheme.cc | 208 |
1 files changed, 193 insertions, 15 deletions
diff --git a/src/RootTheme.cc b/src/RootTheme.cc index 9d73477..dea61cf 100644 --- a/src/RootTheme.cc +++ b/src/RootTheme.cc | |||
@@ -23,38 +23,216 @@ | |||
23 | 23 | ||
24 | #include "RootTheme.hh" | 24 | #include "RootTheme.hh" |
25 | 25 | ||
26 | #include "FbRootWindow.hh" | ||
26 | #include "FbCommands.hh" | 27 | #include "FbCommands.hh" |
28 | |||
27 | #include "FbTk/App.hh" | 29 | #include "FbTk/App.hh" |
30 | #include "FbTk/Font.hh" | ||
31 | #include "FbTk/ImageControl.hh" | ||
32 | #include "FbTk/Resource.hh" | ||
33 | #include "FbTk/FileUtil.hh" | ||
34 | #include "FbTk/StringUtil.hh" | ||
35 | #include "FbTk/TextureRender.hh" | ||
36 | |||
37 | |||
38 | #include <X11/Xatom.h> | ||
39 | |||
40 | using std::string; | ||
41 | |||
42 | class BackgroundItem: public FbTk::ThemeItem<FbTk::Texture> { | ||
43 | public: | ||
44 | BackgroundItem(FbTk::Theme &tm, const std::string &name, const std::string &altname): | ||
45 | FbTk::ThemeItem<FbTk::Texture>(tm, name, altname) { | ||
46 | |||
47 | } | ||
48 | |||
49 | void load(const std::string *o_name = 0, const std::string *o_altname = 0) { | ||
50 | const string &m_name = (o_name == 0) ? name() : *o_name; | ||
51 | const string &m_altname = (o_altname == 0) ? altName() : *o_altname; | ||
52 | |||
53 | // create subnames | ||
54 | string color_name(FbTk::ThemeManager::instance(). | ||
55 | resourceValue(m_name + ".color", m_altname + ".Color")); | ||
56 | string colorto_name(FbTk::ThemeManager::instance(). | ||
57 | resourceValue(m_name + ".colorTo", m_altname + ".ColorTo")); | ||
58 | string pixmap_name(FbTk::ThemeManager::instance(). | ||
59 | resourceValue(m_name + ".pixmap", m_altname + ".Pixmap")); | ||
60 | |||
61 | |||
62 | // set default value if we failed to load colors | ||
63 | if (!(*this)->color().setFromString(color_name.c_str(), | ||
64 | theme().screenNum())) | ||
65 | (*this)->color().setFromString("darkgray", theme().screenNum()); | ||
66 | |||
67 | if (!(*this)->colorTo().setFromString(colorto_name.c_str(), | ||
68 | theme().screenNum())) | ||
69 | (*this)->colorTo().setFromString("white", theme().screenNum()); | ||
70 | |||
71 | |||
72 | if (((*this)->type() & FbTk::Texture::SOLID) != 0 && ((*this)->type() & FbTk::Texture::FLAT) == 0) | ||
73 | (*this)->calcHiLoColors(theme().screenNum()); | ||
74 | |||
75 | // remove whitespace and set filename | ||
76 | FbTk::StringUtil::removeFirstWhitespace(pixmap_name); | ||
77 | FbTk::StringUtil::removeTrailingWhitespace(pixmap_name); | ||
78 | m_filename = pixmap_name; | ||
79 | |||
80 | // we dont load any pixmap, using external command to set background pixmap | ||
81 | (*this)->pixmap() = 0; | ||
82 | } | ||
83 | |||
84 | void setFromString(const char *str) { | ||
85 | m_options = str; // save option string | ||
86 | FbTk::ThemeItem<FbTk::Texture>::setFromString(str); | ||
87 | } | ||
88 | const std::string &filename() const { return m_filename; } | ||
89 | const std::string &options() const { return m_options; } | ||
90 | private: | ||
91 | std::string m_filename, m_options; | ||
92 | }; | ||
93 | |||
94 | |||
95 | RootTheme::RootTheme(const std::string &root_command, | ||
96 | FbTk::ImageControl &image_control): | ||
97 | FbTk::Theme(image_control.screenNumber()), | ||
98 | m_background(new BackgroundItem(*this, "background", "Background")), | ||
99 | m_opgc(RootWindow(FbTk::App::instance()->display(), image_control.screenNumber())), | ||
100 | m_root_command(root_command), | ||
101 | m_image_ctrl(image_control), | ||
102 | m_lock(false), | ||
103 | m_background_loaded(true) { | ||
28 | 104 | ||
29 | RootTheme::RootTheme(int screen_num, std::string &screen_root_command): | ||
30 | FbTk::Theme(screen_num), | ||
31 | m_root_command(*this, "rootCommand", "RootCommand"), | ||
32 | m_screen_root_command(screen_root_command), | ||
33 | m_opgc(RootWindow(FbTk::App::instance()->display(), screen_num)), | ||
34 | m_lock(false) { | ||
35 | |||
36 | Display *disp = FbTk::App::instance()->display(); | 105 | Display *disp = FbTk::App::instance()->display(); |
37 | m_opgc.setForeground(WhitePixel(disp, screen_num)^BlackPixel(disp, screen_num)); | 106 | m_opgc.setForeground(WhitePixel(disp, screenNum())^BlackPixel(disp, screenNum())); |
38 | m_opgc.setFunction(GXxor); | 107 | m_opgc.setFunction(GXxor); |
39 | m_opgc.setSubwindowMode(IncludeInferiors); | 108 | m_opgc.setSubwindowMode(IncludeInferiors); |
40 | m_opgc.setLineAttributes(1, LineSolid, CapNotLast, JoinMiter); | 109 | m_opgc.setLineAttributes(1, LineSolid, CapNotLast, JoinMiter); |
41 | } | 110 | } |
42 | 111 | ||
43 | RootTheme::~RootTheme() { | 112 | RootTheme::~RootTheme() { |
113 | delete m_background; | ||
114 | } | ||
44 | 115 | ||
116 | bool RootTheme::fallback(FbTk::ThemeItem_base &item) { | ||
117 | // if background theme item was not found in the | ||
118 | // style then mark background as not loaded so | ||
119 | // we can deal with it in reconfigureTheme() | ||
120 | if (item.name() == "background") { | ||
121 | // mark no background loaded | ||
122 | m_background_loaded = false; | ||
123 | return true; | ||
124 | } | ||
125 | return false; | ||
45 | } | 126 | } |
46 | 127 | ||
47 | void RootTheme::reconfigTheme() { | 128 | void RootTheme::reconfigTheme() { |
48 | if (m_lock) | 129 | if (m_lock) |
49 | return; | 130 | return; |
50 | 131 | // if user specified background in the config then use it | |
51 | // override resource root command? | 132 | // instead of style background |
52 | if (m_screen_root_command == "") { | 133 | if (!m_root_command.empty()) { |
53 | // do root command | 134 | FbCommands::ExecuteCmd cmd(m_root_command, screenNum()); |
54 | FbCommands::ExecuteCmd cmd(*m_root_command, screenNum()); | ||
55 | cmd.execute(); | 135 | cmd.execute(); |
136 | return; | ||
137 | } | ||
138 | |||
139 | // | ||
140 | // Else parse background from style | ||
141 | // | ||
142 | |||
143 | // root window helper | ||
144 | FbRootWindow rootwin(screenNum()); | ||
145 | |||
146 | // if the background theme item was not loaded | ||
147 | // then generate an image with a text that | ||
148 | // notifies the user about it | ||
149 | |||
150 | if (!m_background_loaded) { | ||
151 | FbTk::FbPixmap root(FbTk::FbPixmap::getRootPixmap(screenNum())); | ||
152 | // if there is no root background pixmap | ||
153 | // then we need to create one | ||
154 | if (root.drawable() == None) { | ||
155 | root.create(rootwin.window(), | ||
156 | rootwin.width(), rootwin.height(), | ||
157 | rootwin.depth()); | ||
158 | |||
159 | FbTk::FbPixmap::setRootPixmap(screenNum(), root.drawable()); | ||
160 | } | ||
161 | |||
162 | // setup root window property | ||
163 | Atom atom_root = XInternAtom(rootwin.display(), "_XROOTPMAP_ID", false); | ||
164 | Pixmap pm = root.drawable(); | ||
165 | rootwin.changeProperty(atom_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *)&pm, 1); | ||
166 | rootwin.setBackgroundPixmap(root.drawable()); | ||
167 | |||
168 | |||
169 | FbTk::GContext gc(root); | ||
170 | |||
171 | // fill background color | ||
172 | gc.setForeground(FbTk::Color("black", screenNum())); | ||
173 | root.fillRectangle(gc.gc(), | ||
174 | 0, 0, | ||
175 | root.width(), root.height()); | ||
176 | // text color | ||
177 | gc.setForeground(FbTk::Color("white", screenNum())); | ||
178 | // render text | ||
179 | const char errormsg[] = | ||
180 | "There is no background option specified in this style. Please consult the manual or read the FAQ."; | ||
181 | FbTk::Font font; | ||
182 | font.drawText(root, screenNum(), gc.gc(), | ||
183 | errormsg, strlen(errormsg), | ||
184 | 2, font.height() + 2); // added some extra pixels for better visibility | ||
185 | |||
186 | |||
187 | // reset background mark | ||
188 | m_background_loaded = true; | ||
189 | root.release(); // we dont want to destroy this pixmap | ||
56 | } else { | 190 | } else { |
57 | FbCommands::ExecuteCmd cmd(m_screen_root_command, screenNum()); | 191 | // handle background option in style |
58 | cmd.execute(); | 192 | std::string filename = m_background->filename(); |
193 | FbTk::StringUtil::removeTrailingWhitespace(filename); | ||
194 | FbTk::StringUtil::removeFirstWhitespace(filename); | ||
195 | // if background argument is a file then | ||
196 | // parse image options and call image setting | ||
197 | // command specified in the resources | ||
198 | if (FbTk::FileUtil::isRegularFile(filename.c_str())) { | ||
199 | // parse options | ||
200 | std::string options; | ||
201 | if (strstr(m_background->options().c_str(), "tiled") != 0) | ||
202 | options += "-t "; | ||
203 | if (strstr(m_background->options().c_str(), "centered") != 0) | ||
204 | options += "-c "; | ||
205 | |||
206 | // compose wallpaper application "fbsetbg" with argumetns | ||
207 | std::string commandargs = "fbsetbg " + options + " " + filename; | ||
208 | |||
209 | // call command with options | ||
210 | FbCommands::ExecuteCmd exec(commandargs, screenNum()); | ||
211 | exec.execute(); | ||
212 | |||
213 | } else { | ||
214 | // render normal texture | ||
215 | |||
216 | // we override the image control renderImage since | ||
217 | // since we do not want to cache this pixmap | ||
218 | XColor *colors; | ||
219 | int num_colors; | ||
220 | m_image_ctrl.getXColorTable(&colors, &num_colors); | ||
221 | FbTk::TextureRender image(m_image_ctrl, rootwin.width(), rootwin.height(), | ||
222 | colors, num_colors); | ||
223 | Pixmap pixmap = image.render(*(*m_background)); | ||
224 | // setup root window property | ||
225 | Atom atom_root = XInternAtom(rootwin.display(), "_XROOTPMAP_ID", false); | ||
226 | rootwin.changeProperty(atom_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *)&pixmap, 1); | ||
227 | rootwin.setBackgroundPixmap(pixmap); | ||
228 | |||
229 | } | ||
230 | |||
59 | } | 231 | } |
232 | |||
233 | // clear root window | ||
234 | rootwin.clear(); | ||
235 | |||
236 | |||
237 | |||
60 | } | 238 | } |