aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMathias Gumz <akira at fluxbox dot org>2013-01-31 08:13:45 (GMT)
committerMathias Gumz <akira at fluxbox dot org>2013-01-31 08:14:06 (GMT)
commitdc47491533e0ca7cf5a5386a10e68fbaf873e9db (patch)
tree4ee0c68722207189912a106d3f77e9cab52e65a8 /src
parent716532dd47d718cb548da5f65b53a8b744ce235f (diff)
downloadfluxbox_pavel-dc47491533e0ca7cf5a5386a10e68fbaf873e9db.zip
fluxbox_pavel-dc47491533e0ca7cf5a5386a10e68fbaf873e9db.tar.bz2
Adds 'ClientPatternTest' command
ClientPatterns might be tricky to get right. Instead of fiddling around in either the keys-file or the apps-file and restarting fluxbox to see if the changes had any effect / matched the right windows, 'ClientPatternTest' and the fluxbox-remote should make this easier: $> fluxbox-remote "clientpatterntest (title=.*vim*)" This causes fluxbox to store the list of matched windows in the _FLUXBOX_ACTION_RESULT property onto the rootwindow. This property might then be read by: $> xprop -root _FLUXBOX_ACTION_RESULT or $> fluxbox-remote result The format of the list is: win_id \t title_of_window \n win_id is '-1' when fluxbox wasn't able to parse the given ClientPattern. win_id is '0' when there are no windows matching the given ClientPattern.
Diffstat (limited to 'src')
-rw-r--r--src/ClientPattern.hh1
-rw-r--r--src/FbCommands.cc82
-rw-r--r--src/FbCommands.hh10
-rw-r--r--src/FbTk/StringUtil.cc9
-rw-r--r--src/FbTk/StringUtil.hh1
-rw-r--r--src/Screen.cc66
6 files changed, 133 insertions, 36 deletions
diff --git a/src/ClientPattern.hh b/src/ClientPattern.hh
index a5b7206..358977a 100644
--- a/src/ClientPattern.hh
+++ b/src/ClientPattern.hh
@@ -89,6 +89,7 @@ public:
89 * the column of the error is stored in m_matchlimit 89 * the column of the error is stored in m_matchlimit
90 */ 90 */
91 int error() const { return m_terms.empty() ? 1 : 0; } 91 int error() const { return m_terms.empty() ? 1 : 0; }
92 int error_col() const { return m_matchlimit; }
92 93
93 static FbTk::FbString getProperty(WinProperty prop, const Focusable &client); 94 static FbTk::FbString getProperty(WinProperty prop, const Focusable &client);
94 95
diff --git a/src/FbCommands.cc b/src/FbCommands.cc
index b0289b8..eb7fbfd 100644
--- a/src/FbCommands.cc
+++ b/src/FbCommands.cc
@@ -445,13 +445,12 @@ REGISTER_UNTRUSTED_COMMAND_WITH_ARGS(bindkey, FbCommands::BindKeyCmd, void);
445BindKeyCmd::BindKeyCmd(const string &keybind):m_keybind(keybind) { } 445BindKeyCmd::BindKeyCmd(const string &keybind):m_keybind(keybind) { }
446 446
447void BindKeyCmd::execute() { 447void BindKeyCmd::execute() {
448 if (Fluxbox::instance()->keys() != 0) { 448 Keys* keys = Fluxbox::instance()->keys();
449 if (Fluxbox::instance()->keys()->addBinding(m_keybind)) { 449 if (keys && keys->addBinding(m_keybind)) {
450 ofstream ofile(Fluxbox::instance()->keys()->filename().c_str(), ios::app); 450 ofstream ofile(keys->filename().c_str(), ios::app);
451 if (!ofile) 451 if (!ofile)
452 return; 452 return;
453 ofile<<m_keybind<<endl; 453 ofile<<m_keybind<<endl;
454 }
455 } 454 }
456} 455}
457 456
@@ -542,4 +541,73 @@ void DeiconifyCmd::execute() {
542 }; 541 };
543} 542}
544 543
544
545REGISTER_COMMAND_WITH_ARGS(clientpatterntest, FbCommands::ClientPatternTestCmd, void);
546
547void ClientPatternTestCmd::execute() {
548
549 std::vector< const FluxboxWindow* > matches;
550 std::string result;
551 std::string pat;
552 int opts;
553 ClientPattern* cp;
554 Display* dpy;
555 Atom atom_utf8;
556 Atom atom_fbcmd_result;
557 Fluxbox::ScreenList::const_iterator screen;
558 const Fluxbox::ScreenList screens(Fluxbox::instance()->screenList());
559
560 dpy = Fluxbox::instance()->display();
561 atom_utf8 = XInternAtom(dpy, "UTF8_STRING", False);
562 atom_fbcmd_result = XInternAtom(dpy, "_FLUXBOX_ACTION_RESULT", False);
563
564 FocusableList::parseArgs(m_args, opts, pat);
565 cp = new ClientPattern(pat.c_str());
566
567 if (!cp->error()) {
568
569 const FocusableList* windows;
570 FocusControl::Focusables::const_iterator wit;
571 FocusControl::Focusables::const_iterator wit_end;
572
573 for (screen = screens.begin(); screen != screens.end(); screen++) {
574
575 windows = FocusableList::getListFromOptions(**screen, opts|FocusableList::LIST_GROUPS);
576 wit = windows->clientList().begin();
577 wit_end = windows->clientList().end();
578
579 for ( ; wit != wit_end; wit++) {
580 if (typeid(**wit) == typeid(FluxboxWindow) && cp->match(**wit)) {
581 matches.push_back(static_cast<const FluxboxWindow*>(*wit));
582 }
583 }
584 }
585
586 if (!matches.empty()) {
587 std::vector< const FluxboxWindow* >::const_iterator win;
588 for (win = matches.begin(); win != matches.end(); win++) {
589 result += "0x";
590 result += FbTk::StringUtil::number2HexString((*win)->clientWindow());
591 result += "\t";
592 result += (*win)->title().logical();
593 result += "\n";
594 }
595 } else {
596 result += "0\n";
597 }
598 } else {
599 result = "-1\t";
600 result += FbTk::StringUtil::number2String(cp->error_col());
601 result += "\n";
602 }
603
604
605 // write result to _FLUXBOX_ACTION_RESULT property
606 for (screen = screens.begin(); screen != screens.end(); screen++) {
607 (*screen)->rootWindow().changeProperty(atom_fbcmd_result, atom_utf8, 8,
608 PropModeReplace, (unsigned char*)result.c_str(), result.size());
609 }
610}
611
612
545} // end namespace FbCommands 613} // end namespace FbCommands
diff --git a/src/FbCommands.hh b/src/FbCommands.hh
index b6b1f7f..d9639ad 100644
--- a/src/FbCommands.hh
+++ b/src/FbCommands.hh
@@ -218,6 +218,16 @@ private:
218 Destination m_dest; 218 Destination m_dest;
219}; 219};
220 220
221
222/// test client pattern
223class ClientPatternTestCmd: public FbTk::Command<void> {
224public:
225 ClientPatternTestCmd(const std::string& args) : m_args(args) { };
226 void execute();
227private:
228 std::string m_args;
229};
230
221} // end namespace FbCommands 231} // end namespace FbCommands
222 232
223#endif // FBCOMMANDS_HH 233#endif // FBCOMMANDS_HH
diff --git a/src/FbTk/StringUtil.cc b/src/FbTk/StringUtil.cc
index 0dcd989..fa809be 100644
--- a/src/FbTk/StringUtil.cc
+++ b/src/FbTk/StringUtil.cc
@@ -145,10 +145,17 @@ int extractNumber(const std::string& in, unsigned long long& out) {
145 145
146std::string number2String(long long num) { 146std::string number2String(long long num) {
147 char s[128]; 147 char s[128];
148 sprintf(s, "%lld", num); 148 snprintf(s, sizeof(s), "%lld", num);
149 return std::string(s); 149 return std::string(s);
150} 150}
151 151
152std::string number2HexString(long long num) {
153 char s[17];
154 snprintf(s, sizeof(s), "%lx", num);
155 return std::string(s);
156}
157
158
152/** 159/**
153 Tries to find a string in another and 160 Tries to find a string in another and
154 ignoring the case of the characters 161 ignoring the case of the characters
diff --git a/src/FbTk/StringUtil.hh b/src/FbTk/StringUtil.hh
index 538828b..930e0b5 100644
--- a/src/FbTk/StringUtil.hh
+++ b/src/FbTk/StringUtil.hh
@@ -44,6 +44,7 @@ int extractNumber(const std::string& in, unsigned long long& out);
44 44
45/// creates a number to a string 45/// creates a number to a string
46std::string number2String(long long num); 46std::string number2String(long long num);
47std::string number2HexString(long long num);
47 48
48/// Similar to `strstr' but this function ignores the case of both strings 49/// Similar to `strstr' but this function ignores the case of both strings
49const char *strcasestr(const char *str, const char *ptn); 50const char *strcasestr(const char *str, const char *ptn);
diff --git a/src/Screen.cc b/src/Screen.cc
index 637bd82..725d4b5 100644
--- a/src/Screen.cc
+++ b/src/Screen.cc
@@ -231,6 +231,22 @@ const TabPlacementString placement_strings[] = {
231 { FbWinFrame::RIGHTTOP, "RightTop" } 231 { FbWinFrame::RIGHTTOP, "RightTop" }
232}; 232};
233 233
234Atom atom_fbcmd = 0;
235Atom atom_wm_check = 0;
236Atom atom_net_desktop = 0;
237Atom atom_utf8_string = 0;
238Atom atom_kde_systray = 0;
239Atom atom_kwm1 = 0;
240
241void initAtoms(Display* dpy) {
242 atom_wm_check = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
243 atom_net_desktop = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False);
244 atom_fbcmd = XInternAtom(dpy, "_FLUXBOX_ACTION", False);
245 atom_utf8_string = XInternAtom(dpy, "UTF8_STRING", False);
246 atom_kde_systray = XInternAtom(dpy, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False);
247 atom_kwm1 = XInternAtom(dpy, "KWM_DOCKWINDOW", False);
248}
249
234 250
235} // end anonymous namespace 251} // end anonymous namespace
236 252
@@ -317,8 +333,7 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
317 m_geom_window(new OSDWindow(m_root_window, *this, *m_focused_windowtheme)), 333 m_geom_window(new OSDWindow(m_root_window, *this, *m_focused_windowtheme)),
318 m_pos_window(new OSDWindow(m_root_window, *this, *m_focused_windowtheme)), 334 m_pos_window(new OSDWindow(m_root_window, *this, *m_focused_windowtheme)),
319 m_tooltip_window(new TooltipWindow(m_root_window, *this, *m_focused_windowtheme)), 335 m_tooltip_window(new TooltipWindow(m_root_window, *this, *m_focused_windowtheme)),
320 m_dummy_window(scrn, -1, -1, 1, 1, 0, true, false, CopyFromParent, 336 m_dummy_window(scrn, -1, -1, 1, 1, 0, true, false, CopyFromParent, InputOnly),
321 InputOnly),
322 resource(rm, screenname, altscreenname), 337 resource(rm, screenname, altscreenname),
323 m_resource_manager(rm), 338 m_resource_manager(rm),
324 m_name(screenname), 339 m_name(screenname),
@@ -331,8 +346,11 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
331 m_shutdown(false) { 346 m_shutdown(false) {
332 347
333 348
334 Display *disp = m_root_window.display();
335 Fluxbox *fluxbox = Fluxbox::instance(); 349 Fluxbox *fluxbox = Fluxbox::instance();
350 Display *disp = fluxbox->display();
351
352 initAtoms(disp);
353
336 354
337 // TODO fluxgen: check if this is the right place (it was not -lis) 355 // TODO fluxgen: check if this is the right place (it was not -lis)
338 // 356 //
@@ -349,7 +367,7 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
349 SubstructureRedirectMask | KeyPressMask | KeyReleaseMask | 367 SubstructureRedirectMask | KeyPressMask | KeyReleaseMask |
350 ButtonPressMask | ButtonReleaseMask| SubstructureNotifyMask); 368 ButtonPressMask | ButtonReleaseMask| SubstructureNotifyMask);
351 369
352 FbTk::App::instance()->sync(false); 370 fluxbox->sync(false);
353 371
354 XSetErrorHandler((XErrorHandler) old); 372 XSetErrorHandler((XErrorHandler) old);
355 373
@@ -370,12 +388,11 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
370#endif // HAVE_GETPID 388#endif // HAVE_GETPID
371 389
372 // check if we're the first EWMH compliant window manager on this screen 390 // check if we're the first EWMH compliant window manager on this screen
373 Atom wm_check = XInternAtom(disp, "_NET_SUPPORTING_WM_CHECK", False);
374 Atom xa_ret_type; 391 Atom xa_ret_type;
375 int ret_format; 392 int ret_format;
376 unsigned long ret_nitems, ret_bytes_after; 393 unsigned long ret_nitems, ret_bytes_after;
377 unsigned char *ret_prop; 394 unsigned char *ret_prop;
378 if (rootWindow().property(wm_check, 0l, 1l, 395 if (rootWindow().property(atom_wm_check, 0l, 1l,
379 False, XA_WINDOW, &xa_ret_type, &ret_format, &ret_nitems, 396 False, XA_WINDOW, &xa_ret_type, &ret_format, &ret_nitems,
380 &ret_bytes_after, &ret_prop) ) { 397 &ret_bytes_after, &ret_prop) ) {
381 m_restart = (ret_prop != NULL); 398 m_restart = (ret_prop != NULL);
@@ -415,7 +432,7 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
415 432
416 FbTk::EventManager *evm = FbTk::EventManager::instance(); 433 FbTk::EventManager *evm = FbTk::EventManager::instance();
417 evm->add(*this, rootWindow()); 434 evm->add(*this, rootWindow());
418 Keys *keys = Fluxbox::instance()->keys(); 435 Keys *keys = fluxbox->keys();
419 if (keys) 436 if (keys)
420 keys->registerWindow(rootWindow().window(), *this, 437 keys->registerWindow(rootWindow().window(), *this,
421 Keys::GLOBAL|Keys::ON_DESKTOP); 438 Keys::GLOBAL|Keys::ON_DESKTOP);
@@ -476,9 +493,8 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
476 // check which desktop we should start on 493 // check which desktop we should start on
477 unsigned int first_desktop = 0; 494 unsigned int first_desktop = 0;
478 if (m_restart) { 495 if (m_restart) {
479 Atom net_desktop = XInternAtom(disp, "_NET_CURRENT_DESKTOP", False);
480 bool exists; 496 bool exists;
481 unsigned int ret=static_cast<unsigned int>(rootWindow().cardinalProperty(net_desktop, &exists)); 497 unsigned int ret=static_cast<unsigned int>(rootWindow().cardinalProperty(atom_net_desktop, &exists));
482 if (exists) { 498 if (exists) {
483 if (ret < static_cast<unsigned int>(nr_ws)) 499 if (ret < static_cast<unsigned int>(nr_ws))
484 first_desktop = ret; 500 first_desktop = ret;
@@ -764,29 +780,29 @@ void BScreen::focusedWinFrameThemeReconfigured() {
764} 780}
765 781
766void BScreen::propertyNotify(Atom atom) { 782void BScreen::propertyNotify(Atom atom) {
767 static Atom fbcmd_atom = XInternAtom(FbTk::App::instance()->display(), 783
768 "_FLUXBOX_ACTION", False); 784 if (allowRemoteActions() && atom == atom_fbcmd) {
769 if (allowRemoteActions() && atom == fbcmd_atom) {
770 Atom xa_ret_type; 785 Atom xa_ret_type;
771 int ret_format; 786 int ret_format;
772 unsigned long ret_nitems, ret_bytes_after; 787 unsigned long ret_nitems, ret_bytes_after;
773 char *str; 788 char *str;
774 if (rootWindow().property(fbcmd_atom, 0l, 64l, 789 if (rootWindow().property(atom_fbcmd, 0l, 64l,
775 True, XA_STRING, &xa_ret_type, &ret_format, &ret_nitems, 790 True, XA_STRING, &xa_ret_type, &ret_format, &ret_nitems,
776 &ret_bytes_after, (unsigned char **)&str) && str) { 791 &ret_bytes_after, (unsigned char **)&str) && str) {
777 792
778 if (ret_bytes_after) { 793 if (ret_bytes_after) {
779 XFree(str); 794 XFree(str);
780 long len = 64 + (ret_bytes_after + 3)/4; 795 long len = 64 + (ret_bytes_after + 3)/4;
781 rootWindow().property(fbcmd_atom, 0l, len, 796 rootWindow().property(atom_fbcmd, 0l, len,
782 True, XA_STRING, &xa_ret_type, &ret_format, &ret_nitems, 797 True, XA_STRING, &xa_ret_type, &ret_format, &ret_nitems,
783 &ret_bytes_after, (unsigned char **)&str); 798 &ret_bytes_after, (unsigned char **)&str);
784 } 799 }
785 800
786 static std::auto_ptr<FbTk::Command<void> > cmd(0); 801 static std::auto_ptr<FbTk::Command<void> > cmd(0);
787 cmd.reset(FbTk::CommandParser<void>::instance().parse(str, false)); 802 cmd.reset(FbTk::CommandParser<void>::instance().parse(str, false));
788 if (cmd.get()) 803 if (cmd.get()) {
789 cmd->execute(); 804 cmd->execute();
805 }
790 XFree(str); 806 XFree(str);
791 807
792 } 808 }
@@ -852,9 +868,8 @@ void BScreen::cycleFocus(int options, const ClientPattern *pat, bool reverse) {
852} 868}
853 869
854FbMenu *BScreen::createMenu(const string &label) { 870FbMenu *BScreen::createMenu(const string &label) {
855 FbMenu *menu = new FbMenu(menuTheme(), 871 FbTk::Layer* layer = layerManager().getLayer(ResourceLayer::MENU);
856 imageControl(), 872 FbMenu *menu = new FbMenu(menuTheme(), imageControl(), *layer);
857 *layerManager().getLayer(ResourceLayer::MENU));
858 if (!label.empty()) 873 if (!label.empty())
859 menu->setLabel(label); 874 menu->setLabel(label);
860 875
@@ -862,9 +877,8 @@ FbMenu *BScreen::createMenu(const string &label) {
862} 877}
863 878
864FbMenu *BScreen::createToggleMenu(const string &label) { 879FbMenu *BScreen::createToggleMenu(const string &label) {
865 FbMenu *menu = new ToggleMenu(menuTheme(), 880 FbTk::Layer* layer = layerManager().getLayer(ResourceLayer::MENU);
866 imageControl(), 881 FbMenu *menu = new ToggleMenu(menuTheme(), imageControl(), *layer);
867 *layerManager().getLayer(ResourceLayer::MENU));
868 if (!label.empty()) 882 if (!label.empty())
869 menu->setLabel(label); 883 menu->setLabel(label);
870 884
@@ -1177,9 +1191,7 @@ bool BScreen::isKdeDockapp(Window client) const {
1177 unsigned long *data = 0, uljunk; 1191 unsigned long *data = 0, uljunk;
1178 Display *disp = FbTk::App::instance()->display(); 1192 Display *disp = FbTk::App::instance()->display();
1179 // Check if KDE v2.x dock applet 1193 // Check if KDE v2.x dock applet
1180 if (XGetWindowProperty(disp, client, 1194 if (XGetWindowProperty(disp, client, atom_kde_systray,
1181 XInternAtom(FbTk::App::instance()->display(),
1182 "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False),
1183 0l, 1l, False, 1195 0l, 1l, False,
1184 XA_WINDOW, &ajunk, &ijunk, &uljunk, 1196 XA_WINDOW, &ajunk, &ijunk, &uljunk,
1185 &uljunk, (unsigned char **) &data) == Success) { 1197 &uljunk, (unsigned char **) &data) == Success) {
@@ -1192,11 +1204,9 @@ bool BScreen::isKdeDockapp(Window client) const {
1192 1204
1193 // Check if KDE v1.x dock applet 1205 // Check if KDE v1.x dock applet
1194 if (!iskdedockapp) { 1206 if (!iskdedockapp) {
1195 Atom kwm1 = XInternAtom(FbTk::App::instance()->display(),
1196 "KWM_DOCKWINDOW", False);
1197 if (XGetWindowProperty(disp, client, 1207 if (XGetWindowProperty(disp, client,
1198 kwm1, 0l, 1l, False, 1208 atom_kwm1, 0l, 1l, False,
1199 kwm1, &ajunk, &ijunk, &uljunk, 1209 atom_kwm1, &ajunk, &ijunk, &uljunk,
1200 &uljunk, (unsigned char **) &data) == Success && data) { 1210 &uljunk, (unsigned char **) &data) == Success && data) {
1201 iskdedockapp = (data && data[0] != 0); 1211 iskdedockapp = (data && data[0] != 0);
1202 XFree((void *) data); 1212 XFree((void *) data);