diff options
author | markt <markt> | 2007-10-13 21:51:37 (GMT) |
---|---|---|
committer | markt <markt> | 2007-10-13 21:51:37 (GMT) |
commit | a59428d67a95a9df16554962f0a6257d6378328a (patch) | |
tree | f856ed9300c34f7a17d499f22d895610cfbc08e5 /src/ClientPattern.cc | |
parent | 41b5c6dadb1f474675660cef18b812d4c2338ed2 (diff) | |
download | fluxbox-a59428d67a95a9df16554962f0a6257d6378328a.zip fluxbox-a59428d67a95a9df16554962f0a6257d6378328a.tar.bz2 |
merged changes from pre-devel
Diffstat (limited to 'src/ClientPattern.cc')
-rw-r--r-- | src/ClientPattern.cc | 175 |
1 files changed, 136 insertions, 39 deletions
diff --git a/src/ClientPattern.cc b/src/ClientPattern.cc index d644767..9324bee 100644 --- a/src/ClientPattern.cc +++ b/src/ClientPattern.cc | |||
@@ -24,7 +24,12 @@ | |||
24 | 24 | ||
25 | #include "ClientPattern.hh" | 25 | #include "ClientPattern.hh" |
26 | #include "RegExp.hh" | 26 | #include "RegExp.hh" |
27 | |||
28 | #include "FocusControl.hh" | ||
29 | #include "Layer.hh" | ||
30 | #include "Screen.hh" | ||
27 | #include "WinClient.hh" | 31 | #include "WinClient.hh" |
32 | #include "Workspace.hh" | ||
28 | 33 | ||
29 | #include "FbTk/StringUtil.hh" | 34 | #include "FbTk/StringUtil.hh" |
30 | #include "FbTk/App.hh" | 35 | #include "FbTk/App.hh" |
@@ -73,54 +78,67 @@ ClientPattern::ClientPattern(const char *str): | |||
73 | If no limit is specified, no limit is applied (i.e. limit = infinity) | 78 | If no limit is specified, no limit is applied (i.e. limit = infinity) |
74 | */ | 79 | */ |
75 | 80 | ||
76 | int had_error = 0; | 81 | bool had_error = false; |
77 | 82 | ||
78 | int pos = 0; | 83 | int pos = 0; |
79 | string match; | 84 | string match; |
80 | int err = 1; // for starting first loop | 85 | int err = 1; // for starting first loop |
81 | while (had_error == 0 && err > 0) { | 86 | while (!had_error && err > 0) { |
82 | err = FbTk::StringUtil::getStringBetween(match, | 87 | err = FbTk::StringUtil::getStringBetween(match, |
83 | str + pos, | 88 | str + pos, |
84 | '(', ')', " \t\n", true); | 89 | '(', ')', " \t\n", true); |
85 | if (err > 0) { | 90 | if (err > 0) { |
86 | size_t eq = match.find_first_of('='); | 91 | // need to determine the property used |
92 | string memstr, expr; | ||
93 | WinProperty prop; | ||
94 | string::size_type eq = match.find_first_of('='); | ||
87 | if (eq == match.npos) { | 95 | if (eq == match.npos) { |
88 | if (!addTerm(match, NAME)) { | 96 | memstr = match; |
89 | had_error = pos + match.find_first_of('(') + 1; | 97 | expr = "[current]"; |
90 | break; | ||
91 | } | ||
92 | } else { | 98 | } else { |
93 | // need to determine the property used | ||
94 | string memstr, expr; | ||
95 | WinProperty prop; | ||
96 | memstr.assign(match, 0, eq); // memstr = our identifier | 99 | memstr.assign(match, 0, eq); // memstr = our identifier |
97 | expr.assign(match, eq+1, match.length()); | 100 | expr.assign(match, eq+1, match.length()); |
98 | if (strcasecmp(memstr.c_str(), "name") == 0) { | ||
99 | prop = NAME; | ||
100 | } else if (strcasecmp(memstr.c_str(), "class") == 0) { | ||
101 | prop = CLASS; | ||
102 | } else if (strcasecmp(memstr.c_str(), "title") == 0) { | ||
103 | prop = TITLE; | ||
104 | } else if (strcasecmp(memstr.c_str(), "role") == 0) { | ||
105 | prop = ROLE; | ||
106 | } else { | ||
107 | had_error = pos + match.find_first_of('(') + 1; | ||
108 | break; | ||
109 | } | ||
110 | if (!addTerm(expr, prop)) { | ||
111 | had_error = pos + ((str+pos) - index(str+pos, '=')) + 1; | ||
112 | break; | ||
113 | } | ||
114 | } | 101 | } |
102 | if (strcasecmp(memstr.c_str(), "name") == 0) { | ||
103 | prop = NAME; | ||
104 | } else if (strcasecmp(memstr.c_str(), "class") == 0) { | ||
105 | prop = CLASS; | ||
106 | } else if (strcasecmp(memstr.c_str(), "title") == 0) { | ||
107 | prop = TITLE; | ||
108 | } else if (strcasecmp(memstr.c_str(), "role") == 0) { | ||
109 | prop = ROLE; | ||
110 | } else if (strcasecmp(memstr.c_str(), "maximized") == 0) { | ||
111 | prop = MAXIMIZED; | ||
112 | } else if (strcasecmp(memstr.c_str(), "minimized") == 0) { | ||
113 | prop = MINIMIZED; | ||
114 | } else if (strcasecmp(memstr.c_str(), "shaded") == 0) { | ||
115 | prop = SHADED; | ||
116 | } else if (strcasecmp(memstr.c_str(), "stuck") == 0) { | ||
117 | prop = STUCK; | ||
118 | } else if (strcasecmp(memstr.c_str(), "focushidden") == 0) { | ||
119 | prop = FOCUSHIDDEN; | ||
120 | } else if (strcasecmp(memstr.c_str(), "iconhidden") == 0) { | ||
121 | prop = ICONHIDDEN; | ||
122 | } else if (strcasecmp(memstr.c_str(), "workspace") == 0) { | ||
123 | prop = WORKSPACE; | ||
124 | } else if (strcasecmp(memstr.c_str(), "head") == 0) { | ||
125 | prop = HEAD; | ||
126 | } else if (strcasecmp(memstr.c_str(), "layer") == 0) { | ||
127 | prop = LAYER; | ||
128 | } else { | ||
129 | prop = NAME; | ||
130 | expr = match; | ||
131 | } | ||
132 | had_error = !addTerm(expr, prop); | ||
115 | pos += err; | 133 | pos += err; |
116 | } | 134 | } |
117 | } | 135 | } |
118 | if (pos == 0 && had_error == 0) { | 136 | if (pos == 0 && !had_error) { |
119 | // no match terms given, this is not allowed | 137 | // no match terms given, this is not allowed |
120 | had_error = 1; | 138 | had_error = true; |
121 | } | 139 | } |
122 | 140 | ||
123 | if (had_error == 0) { | 141 | if (!had_error) { |
124 | // otherwise, we check for a number | 142 | // otherwise, we check for a number |
125 | string number; | 143 | string number; |
126 | err = FbTk::StringUtil::getStringBetween(number, | 144 | err = FbTk::StringUtil::getStringBetween(number, |
@@ -139,12 +157,11 @@ ClientPattern::ClientPattern(const char *str): | |||
139 | uerr = match.find_first_not_of(" \t\n", pos); | 157 | uerr = match.find_first_not_of(" \t\n", pos); |
140 | if (uerr != match.npos) { | 158 | if (uerr != match.npos) { |
141 | // found something, not good | 159 | // found something, not good |
142 | had_error++; | 160 | had_error = true; |
143 | } | 161 | } |
144 | } | 162 | } |
145 | 163 | ||
146 | if (had_error > 0) { | 164 | if (had_error) { |
147 | m_matchlimit = had_error; | ||
148 | // delete all the terms | 165 | // delete all the terms |
149 | while (!m_terms.empty()) { | 166 | while (!m_terms.empty()) { |
150 | Term * term = m_terms.back(); | 167 | Term * term = m_terms.back(); |
@@ -183,6 +200,34 @@ string ClientPattern::toString() const { | |||
183 | break; | 200 | break; |
184 | case ROLE: | 201 | case ROLE: |
185 | pat.append("role="); | 202 | pat.append("role="); |
203 | break; | ||
204 | case MAXIMIZED: | ||
205 | pat.append("maximized="); | ||
206 | break; | ||
207 | case MINIMIZED: | ||
208 | pat.append("minimized="); | ||
209 | break; | ||
210 | case SHADED: | ||
211 | pat.append("shaded="); | ||
212 | break; | ||
213 | case STUCK: | ||
214 | pat.append("stuck="); | ||
215 | break; | ||
216 | case FOCUSHIDDEN: | ||
217 | pat.append("focushidden="); | ||
218 | break; | ||
219 | case ICONHIDDEN: | ||
220 | pat.append("iconhidden="); | ||
221 | break; | ||
222 | case WORKSPACE: | ||
223 | pat.append("workspace="); | ||
224 | break; | ||
225 | case HEAD: | ||
226 | pat.append("head="); | ||
227 | break; | ||
228 | case LAYER: | ||
229 | pat.append("layer="); | ||
230 | break; | ||
186 | } | 231 | } |
187 | 232 | ||
188 | pat.append((*it)->orig); | 233 | pat.append((*it)->orig); |
@@ -198,9 +243,8 @@ string ClientPattern::toString() const { | |||
198 | } | 243 | } |
199 | 244 | ||
200 | // does this client match this pattern? | 245 | // does this client match this pattern? |
201 | bool ClientPattern::match(const WinClient &win) const { | 246 | bool ClientPattern::match(const Focusable &win) const { |
202 | if (m_matchlimit != 0 && m_nummatches >= m_matchlimit || | 247 | if (m_matchlimit != 0 && m_nummatches >= m_matchlimit) |
203 | m_terms.empty()) | ||
204 | return false; // already matched out | 248 | return false; // already matched out |
205 | 249 | ||
206 | // regmatch everything | 250 | // regmatch everything |
@@ -209,7 +253,20 @@ bool ClientPattern::match(const WinClient &win) const { | |||
209 | Terms::const_iterator it = m_terms.begin(); | 253 | Terms::const_iterator it = m_terms.begin(); |
210 | Terms::const_iterator it_end = m_terms.end(); | 254 | Terms::const_iterator it_end = m_terms.end(); |
211 | for (; it != it_end; ++it) { | 255 | for (; it != it_end; ++it) { |
212 | if (!(*it)->regexp.match(getProperty((*it)->prop, win))) | 256 | if ((*it)->orig == "[current]") { |
257 | // workspaces don't necessarily have unique names, so we want to | ||
258 | // compare numbers instead of strings | ||
259 | if ((*it)->prop == WORKSPACE && (!win.fbwindow() || | ||
260 | win.fbwindow()->workspaceNumber() != | ||
261 | win.screen().currentWorkspaceID())) | ||
262 | return false; | ||
263 | else { | ||
264 | WinClient *focused = FocusControl::focusedWindow(); | ||
265 | if (!focused || getProperty((*it)->prop, win) != | ||
266 | getProperty((*it)->prop, *focused)) | ||
267 | return false; | ||
268 | } | ||
269 | } else if (!(*it)->regexp.match(getProperty((*it)->prop, win))) | ||
213 | return false; | 270 | return false; |
214 | } | 271 | } |
215 | return true; | 272 | return true; |
@@ -232,7 +289,11 @@ bool ClientPattern::addTerm(const string &str, WinProperty prop) { | |||
232 | return true; | 289 | return true; |
233 | } | 290 | } |
234 | 291 | ||
235 | string ClientPattern::getProperty(WinProperty prop, const WinClient &client) const { | 292 | string ClientPattern::getProperty(WinProperty prop, |
293 | const Focusable &client) const { | ||
294 | // we need this for some of the window properties | ||
295 | const FluxboxWindow *fbwin = client.fbwindow(); | ||
296 | |||
236 | switch (prop) { | 297 | switch (prop) { |
237 | case TITLE: | 298 | case TITLE: |
238 | return client.title(); | 299 | return client.title(); |
@@ -244,8 +305,44 @@ string ClientPattern::getProperty(WinProperty prop, const WinClient &client) con | |||
244 | return client.getWMClassName(); | 305 | return client.getWMClassName(); |
245 | break; | 306 | break; |
246 | case ROLE: | 307 | case ROLE: |
247 | Atom wm_role = XInternAtom(FbTk::App::instance()->display(), "WM_WINDOW_ROLE", False); | 308 | return client.getWMRole(); |
248 | return client.textProperty(wm_role); | 309 | break; |
310 | case MAXIMIZED: | ||
311 | return (fbwin && fbwin->isMaximized()) ? "yes" : "no"; | ||
312 | break; | ||
313 | case MINIMIZED: | ||
314 | return (fbwin && fbwin->isIconic()) ? "yes" : "no"; | ||
315 | break; | ||
316 | case SHADED: | ||
317 | return (fbwin && fbwin->isShaded()) ? "yes" : "no"; | ||
318 | break; | ||
319 | case STUCK: | ||
320 | return (fbwin && fbwin->isStuck()) ? "yes" : "no"; | ||
321 | break; | ||
322 | case FOCUSHIDDEN: | ||
323 | return (fbwin && fbwin->isFocusHidden()) ? "yes" : "no"; | ||
324 | break; | ||
325 | case ICONHIDDEN: | ||
326 | return (fbwin && fbwin->isIconHidden()) ? "yes" : "no"; | ||
327 | break; | ||
328 | case WORKSPACE: { | ||
329 | if (!fbwin) | ||
330 | return ""; | ||
331 | const Workspace *w = client.screen().getWorkspace(fbwin->workspaceNumber()); | ||
332 | return w ? w->name() : ""; | ||
333 | break; | ||
334 | } | ||
335 | case HEAD: { | ||
336 | if (!fbwin) | ||
337 | return ""; | ||
338 | int head = client.screen().getHead(fbwin->fbWindow()); | ||
339 | char tmpstr[128]; | ||
340 | sprintf(tmpstr, "%d", head); | ||
341 | return std::string(tmpstr); | ||
342 | break; | ||
343 | } | ||
344 | case LAYER: | ||
345 | return fbwin ? ::Layer::getString(fbwin->layerNum()) : ""; | ||
249 | break; | 346 | break; |
250 | } | 347 | } |
251 | return client.getWMClassName(); | 348 | return client.getWMClassName(); |