From 7ffb91c2a7504b29bf001c599999000fa3264f73 Mon Sep 17 00:00:00 2001 From: Dave Foster Date: Wed, 27 Jan 2016 22:38:32 -0500 Subject: [PATCH 01/11] WIP LXDE support --- src/SetBG.cc | 1 + src/SetBG.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/SetBG.cc b/src/SetBG.cc index b231c27..223cf71 100644 --- a/src/SetBG.cc +++ b/src/SetBG.cc @@ -199,6 +199,7 @@ SetBG::RootWindowType SetBG::get_rootwindowtype(Glib::RefPtr displ if (strclass == std::string("Xfdesktop")) retval = SetBG::XFCE; else if (strclass == std::string("Nautilus")) retval = SetBG::NAUTILUS; else if (strclass == std::string("Nemo")) retval = SetBG::NEMO; else + if (strclass == std::string("Pcmanfm")) retval = SetBG::PCMANFM; else { std::cerr << _("UNKNOWN ROOT WINDOW TYPE DETECTED, will attempt to set via normal X procedure") << "\n"; retval = SetBG::UNKNOWN; diff --git a/src/SetBG.h b/src/SetBG.h index e0ce085..3f51dd9 100644 --- a/src/SetBG.h +++ b/src/SetBG.h @@ -57,6 +57,7 @@ class SetBG { UNKNOWN, XINERAMA, NEMO, + PCMANFM, }; virtual bool set_bg(Glib::ustring &disp, From 07f42254dac72b7fabee93376aadc4a36fa00f75 Mon Sep 17 00:00:00 2001 From: Dave Foster Date: Thu, 28 Jan 2016 13:05:44 -0500 Subject: [PATCH 02/11] WIP pcmanfm setter --- src/SetBG.cc | 38 ++++++++++++++++++++++++++++++++++++++ src/SetBG.h | 10 ++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/SetBG.cc b/src/SetBG.cc index 223cf71..45629c5 100644 --- a/src/SetBG.cc +++ b/src/SetBG.cc @@ -1235,3 +1235,41 @@ void SetBGNemo::set_show_desktop() Glib::RefPtr settings = Gio::Settings::create(Glib::ustring("org.nemo.desktop")); settings->set_boolean("draw-background", true); } + +/* + * ************************************************************************** + * SetBGPcmanfm + * ************************************************************************** + */ + +bool SetBGPcmanfm::set_bg(Glib::ustring &disp, Glib::ustring file, SetMode mode, Gdk::Color bgcolor) +{ + Glib::ustring strmode; + switch(mode) { + case SetBG::SET_SCALE: strmode = "stretch"; break; + case SetBG::SET_TILE: strmode = "tile"; break; + case SetBG::SET_CENTER: strmode = "center"; break; + case SetBG::SET_ZOOM: strmode = "screen"; break; + case SetBG::SET_ZOOM_FILL: strmode = "crop"; break; + default: strmode = "fit"; break; + }; + + std::vector vecCmdLine; + + vecCmdLine.push_back(std::string("pcmanfm")); + vecCmdLine.push_back(std::string("--set-wallpaper")); + vecCmdLine.push_back(file); + vecCmdLine.push_back(std::string("--wallpaper-mode")); + vecCmdLine.push_back(strmode); + + + return true; +} + +std::map SetBGPcmanfm::get_active_displays() +{ + std::map map_displays; + map_displays["dummy"] = "Pcmanfm"; + return map_displays; +} + diff --git a/src/SetBG.h b/src/SetBG.h index 3f51dd9..8ee96bd 100644 --- a/src/SetBG.h +++ b/src/SetBG.h @@ -167,4 +167,14 @@ class SetBGNemo : public SetBGGnome { virtual void set_show_desktop(); }; +class SetBGPcmanfm : public SetBGGnome { + public: + virtual bool set_bg(Glib::ustring &disp, + Glib::ustring file, + SetMode mode, + Gdk::Color bgcolor); + + virtual std::map get_active_displays(); +}; + #endif From 42a2b94c329bdf4531c24cb32f84f808e8b0ee36 Mon Sep 17 00:00:00 2001 From: Dave Foster Date: Wed, 19 Oct 2016 22:32:59 -0400 Subject: [PATCH 03/11] Hook up LXDE/Pcmanfm background setter --- src/SetBG.cc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/SetBG.cc b/src/SetBG.cc index 45629c5..f403398 100644 --- a/src/SetBG.cc +++ b/src/SetBG.cc @@ -61,6 +61,9 @@ SetBG* SetBG::get_bg_setter() ((SetBGXinerama*)setter)->set_xinerama_info(xinerama_info, xinerama_num_screens); break; #endif + case SetBG::PCMANFM: + setter = new SetBGPcmanfm(); + break; case SetBG::DEFAULT: default: setter = new SetBGXWindows(); @@ -1262,6 +1265,20 @@ bool SetBGPcmanfm::set_bg(Glib::ustring &disp, Glib::ustring file, SetMode mode, vecCmdLine.push_back(std::string("--wallpaper-mode")); vecCmdLine.push_back(strmode); + try { + Glib::spawn_async("", vecCmdLine, Glib::SPAWN_SEARCH_PATH); + } + catch (Glib::SpawnError e) + { + std::cerr << _("ERROR") << "\n" << e.what() << "\n"; + + for (std::vector::const_iterator i = vecCmdLine.begin(); i != vecCmdLine.end(); i++) + std::cerr << *i << " "; + + std::cerr << "\n"; + + return false; + } return true; } From 2c666ba490cd88a8cf82a3f2d6e7a2b7c8430f31 Mon Sep 17 00:00:00 2001 From: Dave Foster Date: Wed, 19 Oct 2016 22:39:03 -0400 Subject: [PATCH 04/11] Add force setter option for LXDE/pcmanfm --- src/Util.cc | 2 +- src/main.cc | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Util.cc b/src/Util.cc index 99e8d91..8f375e1 100644 --- a/src/Util.cc +++ b/src/Util.cc @@ -97,7 +97,7 @@ ArgParser* create_arg_parser() { parser->register_option("sort", _("How to sort the backgrounds. Valid options are:\n\t\t\t* alpha, for alphanumeric sort\n\t\t\t* ralpha, for reverse alphanumeric sort\n\t\t\t* time, for last modified time sort (oldest first)\n\t\t\t* rtime, for reverse last modified time sort (newest first)"), true); parser->register_option("set-color", _("background color in hex, #000000 by default"), true); parser->register_option("head", _("Select xinerama/multihead display in GUI, 0..n, -1 for full"), true); - parser->register_option("force-setter", _("Force setter engine: xwindows, xinerama, gnome"), true); + parser->register_option("force-setter", _("Force setter engine: xwindows, xinerama, gnome, pcmanfm"), true); parser->register_option("random", _("Choose random background from config or given directory")); // command line set modes diff --git a/src/main.cc b/src/main.cc index 496c620..64917ae 100644 --- a/src/main.cc +++ b/src/main.cc @@ -156,6 +156,8 @@ int main (int argc, char ** argv) { } else if (setter_str == "gnome") setter = new SetBGGnome(); + else if (setter_str == "pcmanfm") + setter = new SetBGPcmanfm(); else setter = SetBG::get_bg_setter(); From f5787b90cfaf6b60b9c1244cf8c761e1134485a7 Mon Sep 17 00:00:00 2001 From: Dave Foster Date: Sat, 22 Oct 2016 12:55:12 -0400 Subject: [PATCH 05/11] Extract get_root_window utility function --- src/SetBG.cc | 56 ++++++++++++++++++++++++++++++++++------------------ src/SetBG.h | 1 + 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/src/SetBG.cc b/src/SetBG.cc index f403398..7699fa7 100644 --- a/src/SetBG.cc +++ b/src/SetBG.cc @@ -139,33 +139,30 @@ int SetBG::find_desktop_window(Display *xdisp, Window curwindow) { } /** - * Determines if Nautilus is being used to draw the root desktop. + * Finds any false desktop/root window, either via root window hint or recursively. * - * @returns True if nautilus is drawing the desktop. + * @returns The Window's ID, or 0. */ -SetBG::RootWindowType SetBG::get_rootwindowtype(Glib::RefPtr display) -{ +guint SetBG::get_root_window(Glib::RefPtr display) { GdkAtom type; gint format; gint length; guchar *data; - SetBG::RootWindowType retval = SetBG::DEFAULT; gboolean ret = FALSE; - Glib::RefPtr rootwin; - guint wid = 0; - - rootwin = display->get_default_screen()->get_root_window(); + Glib::RefPtr rootwin = display->get_default_screen()->get_root_window(); Display *xdisp = GDK_DISPLAY_XDISPLAY(rootwin->get_display()->gobj()); + guint wid = 0; - ret = gdk_property_get(rootwin->gobj(), - gdk_atom_intern("NAUTILUS_DESKTOP_WINDOW_ID", FALSE), - gdk_atom_intern("WINDOW", FALSE), - 0L, - 4L, /* length of a window is 32bits*/ - FALSE, &type, &format, &length, &data); + ret = gdk_property_get(rootwin->gobj(), + gdk_atom_intern("NAUTILUS_DESKTOP_WINDOW_ID", FALSE), + gdk_atom_intern("WINDOW", FALSE), + 0L, + 4L, /* length of a window is 32bits*/ + FALSE, &type, &format, &length, &data); if (ret) { wid = *(guint*)data; + g_free(data); } else { // newer nautilus and nemo don't leave a hint on the root window (whyyyy) // now we have to search for it! @@ -176,6 +173,30 @@ SetBG::RootWindowType SetBG::get_rootwindowtype(Glib::RefPtr displ wid = (guint)wwid; } + return wid; +} + +/** + * Determines if Nautilus is being used to draw the root desktop. + * + * @returns True if nautilus is drawing the desktop. + */ +SetBG::RootWindowType SetBG::get_rootwindowtype(Glib::RefPtr display) +{ + GdkAtom type; + gint format; + gint length; + guchar *data; + SetBG::RootWindowType retval = SetBG::DEFAULT; + gboolean ret = FALSE; + Glib::RefPtr rootwin; + guint wid = 0; + + rootwin = display->get_default_screen()->get_root_window(); + Display *xdisp = GDK_DISPLAY_XDISPLAY(rootwin->get_display()->gobj()); + + wid = get_root_window(display); + if (wid > 0) { Atom propatom = XInternAtom(xdisp, "WM_CLASS", FALSE); @@ -215,10 +236,6 @@ SetBG::RootWindowType SetBG::get_rootwindowtype(Glib::RefPtr displ XFree(tprop.value); } - // need to free what we got from property get - if (ret) - g_free(data); - return retval; } @@ -231,6 +248,7 @@ SetBG::RootWindowType SetBG::get_rootwindowtype(Glib::RefPtr displ FALSE, &type, &format, &length, &data); if (ret) { + g_free(data); return SetBG::NAUTILUS; // mutter uses same keys } diff --git a/src/SetBG.h b/src/SetBG.h index 8ee96bd..9073561 100644 --- a/src/SetBG.h +++ b/src/SetBG.h @@ -98,6 +98,7 @@ class SetBG { static int handle_x_errors(Display *display, XErrorEvent *error); static int find_desktop_window(Display *display, Window curwindow); + static guint get_root_window(Glib::RefPtr display); Glib::RefPtr make_resized_pixbuf(Glib::RefPtr pixbuf, SetBG::SetMode mode, Gdk::Color bgcolor, gint tarw, gint tarh); virtual Glib::RefPtr get_display(const Glib::ustring& disp); From 027e09c0d1f63316eac4c86941a701a0946bcf0c Mon Sep 17 00:00:00 2001 From: Dave Foster Date: Sat, 22 Oct 2016 22:47:47 -0400 Subject: [PATCH 06/11] Add ArgParser ability to parse vector of strings --- src/ArgParser.cc | 15 ++++++++++++--- src/ArgParser.h | 2 ++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/ArgParser.cc b/src/ArgParser.cc index ded0e9e..062bff0 100644 --- a/src/ArgParser.cc +++ b/src/ArgParser.cc @@ -24,11 +24,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. bool ArgParser::parse (int argc, char ** argv) { - int count = 1; + std::vector argVec; + for (int i = 0; i < argc; i++) { + argVec.push_back(Glib::ustring(argv[i])); + } + + return this->parse(argVec); +} + +bool ArgParser::parse + (std::vector argVec) { bool retval = true; - while (count < argc) { - std::string arg (argv[count++]); + for (std::vector::const_iterator i = argVec.begin() + 1; i != argVec.end(); i++) { + std::string arg(*i); std::string key = arg; std::string value; diff --git a/src/ArgParser.h b/src/ArgParser.h index c6739ef..277f4c3 100644 --- a/src/ArgParser.h +++ b/src/ArgParser.h @@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #include #include +#include class Arg { public: @@ -120,6 +121,7 @@ class ArgParser { // parses away. bool parse (int argc, char ** argv); + bool parse (std::vector argVec); // returns the help text (--help) std::string help_text (void) const; From f25024b504eb6f2f70d447f807e1583d1f6f4dfb Mon Sep 17 00:00:00 2001 From: Dave Foster Date: Sat, 22 Oct 2016 22:48:13 -0400 Subject: [PATCH 07/11] Move color_to_string from Config to Util --- src/Config.cc | 23 ++--------------------- src/Config.h | 2 -- src/Util.cc | 20 ++++++++++++++++++++ src/Util.h | 2 ++ 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/Config.cc b/src/Config.cc index 018ddc5..b93690b 100644 --- a/src/Config.cc +++ b/src/Config.cc @@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "Config.h" #include #include "gcs-i18n.h" +#include "Util.h" /** * Constructor, initializes default settings. @@ -250,7 +251,7 @@ bool Config::set_bg(const Glib::ustring disp, const Glib::ustring file, const Se // set data g_key_file_set_string(kf, realdisp.c_str(), "file", file.c_str()); g_key_file_set_integer(kf, realdisp.c_str(), "mode", (gint)mode); - g_key_file_set_string(kf, realdisp.c_str(), "bgcolor", color_to_string(bgcolor).c_str()); + g_key_file_set_string(kf, realdisp.c_str(), "bgcolor", Util::color_to_string(bgcolor).c_str()); // output it Glib::ustring outp = g_key_file_to_data(kf, NULL, NULL); @@ -316,26 +317,6 @@ bool Config::check_dir() { return true; } -/** - * Converts a Gdk::Color to a string representation with a #. - * - * @param color The color to convert - * @return A hex string - */ -Glib::ustring Config::color_to_string(Gdk::Color color) { - guchar red = guchar(color.get_red_p() * 255); - guchar green = guchar(color.get_green_p() * 255); - guchar blue = guchar(color.get_blue_p() * 255); - - char * c_str = new char[7]; - - snprintf(c_str, 7, "%.2x%.2x%.2x", red, green, blue); - Glib::ustring string = '#' + Glib::ustring(c_str); - - delete[] c_str; - return string; -} - /** * Gets the last saved position. */ diff --git a/src/Config.h b/src/Config.h index a948ed0..b5b6e69 100644 --- a/src/Config.h +++ b/src/Config.h @@ -46,8 +46,6 @@ class Config { VecStrs m_vec_dirs; Thumbview::SortMode m_sort_mode; - Glib::ustring color_to_string(Gdk::Color color); - std::string get_bg_config_file() const { return get_file("bg-saved.cfg"); } std::string get_config_file() const { return get_file("nitrogen.cfg"); } std::string get_file(const Glib::ustring filename) const; diff --git a/src/Util.cc b/src/Util.cc index 8f375e1..9d289de 100644 --- a/src/Util.cc +++ b/src/Util.cc @@ -297,4 +297,24 @@ Glib::ustring make_current_set_string(Gtk::Window* window, Glib::ustring filenam return ostr.str(); } +/** + * Converts a Gdk::Color to a string representation with a #. + * + * @param color The color to convert + * @return A hex string + */ +Glib::ustring color_to_string(Gdk::Color color) { + guchar red = guchar(color.get_red_p() * 255); + guchar green = guchar(color.get_green_p() * 255); + guchar blue = guchar(color.get_blue_p() * 255); + + char * c_str = new char[7]; + + snprintf(c_str, 7, "%.2x%.2x%.2x", red, green, blue); + Glib::ustring string = '#' + Glib::ustring(c_str); + + delete[] c_str; + return string; +} + } diff --git a/src/Util.h b/src/Util.h index b45ecaa..a8165da 100644 --- a/src/Util.h +++ b/src/Util.h @@ -40,6 +40,8 @@ namespace Util { bool is_display_relevant(Gtk::Window* window, Glib::ustring display); Glib::ustring make_current_set_string(Gtk::Window* window, Glib::ustring filename, Glib::ustring display); + + Glib::ustring color_to_string(Gdk::Color color); } #endif From ff93fcd2070442dfb14597260f5d008c0d498cba Mon Sep 17 00:00:00 2001 From: Dave Foster Date: Sat, 22 Oct 2016 22:49:04 -0400 Subject: [PATCH 08/11] Functional Pcmanfm backend setter directly changing config and restarting pcmanfm desktop process --- src/SetBG.cc | 184 ++++++++++++++++++++++++++++++++++++++++++++++----- src/SetBG.h | 3 + 2 files changed, 169 insertions(+), 18 deletions(-) diff --git a/src/SetBG.cc b/src/SetBG.cc index 7699fa7..fbb0253 100644 --- a/src/SetBG.cc +++ b/src/SetBG.cc @@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "Config.h" #include #include +#include using namespace Util; @@ -1265,37 +1266,152 @@ void SetBGNemo::set_show_desktop() bool SetBGPcmanfm::set_bg(Glib::ustring &disp, Glib::ustring file, SetMode mode, Gdk::Color bgcolor) { + Atom ret_type; + int ret_format; + gulong ret_items; + gulong ret_bytesleft; + guchar *data; Glib::ustring strmode; switch(mode) { case SetBG::SET_SCALE: strmode = "stretch"; break; case SetBG::SET_TILE: strmode = "tile"; break; case SetBG::SET_CENTER: strmode = "center"; break; - case SetBG::SET_ZOOM: strmode = "screen"; break; + case SetBG::SET_ZOOM: strmode = "fit"; break; case SetBG::SET_ZOOM_FILL: strmode = "crop"; break; default: strmode = "fit"; break; }; - std::vector vecCmdLine; + // default to "LXDE" for profile name + Glib::ustring profileName = Glib::ustring("LXDE"); - vecCmdLine.push_back(std::string("pcmanfm")); - vecCmdLine.push_back(std::string("--set-wallpaper")); - vecCmdLine.push_back(file); - vecCmdLine.push_back(std::string("--wallpaper-mode")); - vecCmdLine.push_back(strmode); + // find pcmanfm process (pull off root window) + Glib::RefPtr display = Gdk::DisplayManager::get()->get_default_display(); + Display* xdisp = GDK_DISPLAY_XDISPLAY(display->gobj()); - try { - Glib::spawn_async("", vecCmdLine, Glib::SPAWN_SEARCH_PATH); - } - catch (Glib::SpawnError e) - { - std::cerr << _("ERROR") << "\n" << e.what() << "\n"; + guint wid = get_root_window(display); - for (std::vector::const_iterator i = vecCmdLine.begin(); i != vecCmdLine.end(); i++) - std::cerr << *i << " "; + if (wid > 0) { + // pull PID atom from pcman desktop window + Window curwindow = (Window)wid; - std::cerr << "\n"; + Atom propatom = XInternAtom(xdisp, "_NET_WM_PID", False); - return false; + int result = XGetWindowProperty(xdisp, + curwindow, + propatom, + 0, G_MAXLONG, + False, XA_CARDINAL, &ret_type, &ret_format, &ret_items, &ret_bytesleft, &data); + + if (result != Success) { + // throw? + throw false; + return false; + } + + long pid = 0; + + if (ret_type == XA_CARDINAL && ret_format == 32 && ret_items == 1) { + pid = ((long* )data)[0]; + XFree(data); + } + + if (pid > 0) { + + // attempt to pull profile name from pcmanfm process command line + std::ostringstream ss; + ss << pid; + + std::string filename = Glib::build_filename("/", "proc", ss.str(), "cmdline"); + if (Glib::file_test(filename, Glib::FILE_TEST_EXISTS)) { + std::string contents = Glib::file_get_contents(filename); + + // contents is a string with null characters. glib doesn't seem to like splitting on the null character, + // so we have to do it manually. + std::vector splits; + + std::string::const_iterator i = contents.begin(); + while (i != contents.end()) { + std::string::const_iterator next = std::find(i, (std::string::const_iterator)contents.end(), '\0'); + splits.push_back(std::string(i, next)); + i = next + 1; + } + + // use our own ArgParse + ArgParser* parser = new ArgParser(); + parser->register_option("profile", "", true); + parser->register_option("desktop"); + + if (parser->parse(splits)) { + if (parser->has_argument("profile")) + profileName = parser->get_value("profile"); + else + // found pcmanfm exe, but no profile arg? use 'default' instead of LXDE + profileName = std::string("default"); + } + + // cleanup + delete parser; + } + + // find configuration file in profile directory (do a minimal create if needed) + // mimics logic in pcmanfm_get_profile_dir + std::string configdir = Glib::build_filename(Glib::get_user_config_dir(), "pcmanfm", profileName); + if (!Glib::file_test(configdir, Glib::FILE_TEST_EXISTS)) { + Glib::RefPtr giof = Gio::File::create_for_path(configdir); + giof->make_directory_with_parents(); + } + + // SPECIAL HANDLING: for "full screen", all configs must be set to the same bg and stretch across mode + if (disp == this->get_fullscreen_key()) { + + // iterate all screens + std::map map_displays = this->get_active_displays(); + for (std::map::const_iterator i = map_displays.begin(); i != map_displays.end(); i++) { + + // skip fullscreen key, there's no config file for that + if (i->first == disp) + continue; + + // read config file, set, save + std::string configfile = Glib::build_filename(Glib::get_user_config_dir(), "pcmanfm", profileName, Glib::ustring::compose("desktop-items-%1.conf", i->first)); + + Glib::KeyFile kf; + kf.load_from_file(configfile); + + kf.set_string("*", "wallpaper_mode", "screen"); + kf.set_string("*", "wallpaper_common", "1"); + kf.set_string("*", "wallpaper", file); + kf.set_string("*", "desktop_bg", Util::color_to_string(bgcolor)); + + if (kf.has_key("*", "wallpapers_configured")) + kf.remove_key("*", "wallpapers_configured"); + if (kf.has_key("*", "wallpaper0")) + kf.remove_key("*", "wallpaper0"); + + kf.save_to_file(configfile); + } + + } else { + // read config file, set, save + std::string configfile = Glib::build_filename(Glib::get_user_config_dir(), "pcmanfm", profileName, Glib::ustring::compose("desktop-items-%1.conf", disp)); + + Glib::KeyFile kf; + kf.load_from_file(configfile); + + kf.set_string("*", "wallpaper_mode", strmode); + kf.set_string("*", "wallpaper_common", "0"); + kf.set_string("*", "wallpapers_configured", "1"); + kf.set_string("*", "wallpaper0", file); + kf.set_string("*", "desktop_bg", Util::color_to_string(bgcolor)); + + kf.save_to_file(configfile); + } + + // send USR1 to pcmanfm + kill(pid, SIGUSR1); + } else { + throw "failboat"; + } } return true; @@ -1303,8 +1419,40 @@ bool SetBGPcmanfm::set_bg(Glib::ustring &disp, Glib::ustring file, SetMode mode, std::map SetBGPcmanfm::get_active_displays() { + Glib::RefPtr disp = Gdk::DisplayManager::get()->get_default_display(); std::map map_displays; - map_displays["dummy"] = "Pcmanfm"; + + map_displays[this->get_fullscreen_key()] = _("Full Screen"); + + for (int i=0; i < disp->get_n_screens(); i++) { + Glib::RefPtr screen = disp->get_screen(i); + + for (int j=0; j < screen->get_n_monitors(); j++) { + std::ostringstream ostr; + ostr << _("Screen") << " " << j; + + map_displays[this->make_display_key(j)] = ostr.str(); + } + } + return map_displays; } +/** + * Gets the full key for "full screen" for this setter. + * + * For Pcmanfm, simply "-1". + */ +Glib::ustring SetBGPcmanfm::get_fullscreen_key() { + return this->make_display_key(-1); +} + +/* + * Make a usable display key to pass to set_bg with a given head number. + * + * For Pcmanfm, return simply the head number. + */ +Glib::ustring SetBGPcmanfm::make_display_key(gint head) { + return Glib::ustring::compose("%1", head); +} + diff --git a/src/SetBG.h b/src/SetBG.h index 9073561..df312f0 100644 --- a/src/SetBG.h +++ b/src/SetBG.h @@ -170,12 +170,15 @@ class SetBGNemo : public SetBGGnome { class SetBGPcmanfm : public SetBGGnome { public: + virtual Glib::ustring get_fullscreen_key(); virtual bool set_bg(Glib::ustring &disp, Glib::ustring file, SetMode mode, Gdk::Color bgcolor); virtual std::map get_active_displays(); + protected: + virtual Glib::ustring make_display_key(gint head); }; #endif From 298430969fa680f02bce0381c49f30ec68e179cc Mon Sep 17 00:00:00 2001 From: Dave Foster Date: Sat, 22 Oct 2016 23:05:30 -0400 Subject: [PATCH 09/11] Pcmanfm needs to clean up after itself when changing from full to nonfull --- src/SetBG.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/SetBG.cc b/src/SetBG.cc index fbb0253..0ef3c17 100644 --- a/src/SetBG.cc +++ b/src/SetBG.cc @@ -1404,6 +1404,9 @@ bool SetBGPcmanfm::set_bg(Glib::ustring &disp, Glib::ustring file, SetMode mode, kf.set_string("*", "wallpaper0", file); kf.set_string("*", "desktop_bg", Util::color_to_string(bgcolor)); + if (kf.has_key("*", "wallpaper")) + kf.remove_key("*", "wallpaper"); + kf.save_to_file(configfile); } From adc1e406cc909ccc8755254042924a4a1389c966 Mon Sep 17 00:00:00 2001 From: Dave Foster Date: Wed, 26 Oct 2016 20:30:21 -0400 Subject: [PATCH 10/11] Error messages for LXDE setter exception paths --- src/SetBG.cc | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/SetBG.cc b/src/SetBG.cc index 0ef3c17..a3b38b1 100644 --- a/src/SetBG.cc +++ b/src/SetBG.cc @@ -1303,8 +1303,7 @@ bool SetBGPcmanfm::set_bg(Glib::ustring &disp, Glib::ustring file, SetMode mode, False, XA_CARDINAL, &ret_type, &ret_format, &ret_items, &ret_bytesleft, &data); if (result != Success) { - // throw? - throw false; + std::cerr << "ERROR: Could not determine pid of Pcmanfm desktop window, is _NET_WM_PID set on X root window?\n"; return false; } @@ -1413,13 +1412,21 @@ bool SetBGPcmanfm::set_bg(Glib::ustring &disp, Glib::ustring file, SetMode mode, // send USR1 to pcmanfm kill(pid, SIGUSR1); } else { - throw "failboat"; + std::cerr << "ERROR: _NET_WM_PID set on X root window, but pid not readable.\n"; + return false; } } return true; } +/** + * Gets all active screens on this display. + * This is used by the main window to determine what to show in the dropdown, + * if anything. + * + * Returns a map of display string to human-readable representation. + */ std::map SetBGPcmanfm::get_active_displays() { Glib::RefPtr disp = Gdk::DisplayManager::get()->get_default_display(); From dc27d9c52f18e781dc0993c1f6484dc9ac1d68a6 Mon Sep 17 00:00:00 2001 From: Dave Foster Date: Wed, 26 Oct 2016 20:51:57 -0400 Subject: [PATCH 11/11] Setters can indicate if they need to have config saved In Nitrogen config only. Now, external setters like GNOME, Pcmanfm, etc don't save to nitrogen's config files. --- src/NWindow.cc | 16 ++++++++++------ src/NWindow.h | 2 +- src/SetBG.cc | 40 ++++++++++++++++++++++++++++++++++++++++ src/SetBG.h | 6 ++++++ src/main.cc | 6 ++++-- 5 files changed, 61 insertions(+), 9 deletions(-) diff --git a/src/NWindow.cc b/src/NWindow.cc index 89b7f08..b7470c4 100644 --- a/src/NWindow.cc +++ b/src/NWindow.cc @@ -163,10 +163,9 @@ void NWindow::sighandle_dblclick_item (const Gtk::TreeModel::Path& path) { // find out which image was double clicked Gtk::TreeModel::iterator iter = (view.store)->get_iter(path); Gtk::TreeModel::Row row = *iter; - this->set_bg(row[view.record.Filename]); - // preview - set dirty flag - m_dirty = true; + // preview - set dirty flag, if setter says we should + m_dirty = this->set_bg(row[view.record.Filename]); } /** @@ -188,7 +187,7 @@ void NWindow::apply_bg () { Gtk::TreeModel::iterator iter = view.get_selected (); Gtk::TreeModel::Row row = *iter; Glib::ustring file = row[view.record.Filename]; - this->set_bg(file); + bool saveToConfig = this->set_bg(file); // apply - remove dirty flag m_dirty = false; @@ -198,7 +197,8 @@ void NWindow::apply_bg () { Gdk::Color bgcolor = this->button_bgcolor.get_color(); // save - Config::get_instance()->set_bg(thedisp, file, mode, bgcolor); + if (saveToConfig) + Config::get_instance()->set_bg(thedisp, file, mode, bgcolor); // tell the bg setter to forget about the first pixmap bg_setter->clear_first_pixmaps(); @@ -282,8 +282,10 @@ bool NWindow::on_delete_event(GdkEventAny *event) /** * Queries the necessary widgets to get the data needed to set a bg. * * @param file The file to set the bg to + * + * @returns If the dirty flag should be set or not */ -void NWindow::set_bg(const Glib::ustring file) { +bool NWindow::set_bg(const Glib::ustring file) { // get the data from the active items SetBG::SetMode mode = SetBG::string_to_mode(this->select_mode.get_active_data()); @@ -292,6 +294,8 @@ void NWindow::set_bg(const Glib::ustring file) { // set it bg_setter->set_bg(thedisp, file, mode, bgcolor); + + return bg_setter->save_to_config(); } // leethax destructor diff --git a/src/NWindow.h b/src/NWindow.h index 169f681..cfad9fb 100644 --- a/src/NWindow.h +++ b/src/NWindow.h @@ -43,7 +43,7 @@ class NWindow : public Gtk::Window { std::map map_displays; // a map of current displays on the running instance to their display names void set_default_display(int display); - void set_bg(Glib::ustring file); + bool set_bg(Glib::ustring file); protected: Glib::RefPtr m_action_group; diff --git a/src/SetBG.cc b/src/SetBG.cc index a3b38b1..fa8929d 100644 --- a/src/SetBG.cc +++ b/src/SetBG.cc @@ -937,6 +937,16 @@ void SetBG::disable_pixmap_save() has_set_once = true; } +/** + * Returns if this background setter should be setting the Nitrogen configuration. + * + * Override this in alternate setters that may directly touch external configurations. + */ +bool SetBG::save_to_config() +{ + return true; +} + /* * ************************************************************************** * SetBGXwindows @@ -1231,6 +1241,16 @@ void SetBGGnome::set_show_desktop() settings->set_boolean("draw-background", true); } +/** + * Returns if this background setter should be setting the Nitrogen configuration. + * + * The Gnome mode is completely external. + */ +bool SetBGGnome::save_to_config() +{ + return false; +} + /* * ************************************************************************** * SetBGNemo @@ -1258,6 +1278,16 @@ void SetBGNemo::set_show_desktop() settings->set_boolean("draw-background", true); } +/** + * Returns if this background setter should be setting the Nitrogen configuration. + * + * The Nemo mode is completely external. + */ +bool SetBGNemo::save_to_config() +{ + return false; +} + /* * ************************************************************************** * SetBGPcmanfm @@ -1466,3 +1496,13 @@ Glib::ustring SetBGPcmanfm::make_display_key(gint head) { return Glib::ustring::compose("%1", head); } +/** + * Returns if this background setter should be setting the Nitrogen configuration. + * + * The Pcmanfm mode is completely external. + */ +bool SetBGPcmanfm::save_to_config() +{ + return false; +} + diff --git a/src/SetBG.h b/src/SetBG.h index df312f0..8c55788 100644 --- a/src/SetBG.h +++ b/src/SetBG.h @@ -83,6 +83,8 @@ class SetBG { void reset_first_pixmaps(); void disable_pixmap_save(); + virtual bool save_to_config(); + protected: virtual Glib::ustring get_prefix() = 0; @@ -155,6 +157,7 @@ class SetBGGnome : public SetBG { virtual std::map get_active_displays(); virtual Glib::ustring get_fullscreen_key(); + virtual bool save_to_config(); protected: virtual Glib::ustring get_prefix(); virtual Glib::ustring make_display_key(gint head); @@ -163,6 +166,8 @@ class SetBGGnome : public SetBG { }; class SetBGNemo : public SetBGGnome { + public: + virtual bool save_to_config(); protected: virtual Glib::ustring get_gsettings_key(); virtual void set_show_desktop(); @@ -177,6 +182,7 @@ class SetBGPcmanfm : public SetBGGnome { Gdk::Color bgcolor); virtual std::map get_active_displays(); + virtual bool save_to_config(); protected: virtual Glib::ustring make_display_key(gint head); }; diff --git a/src/main.cc b/src/main.cc index 64917ae..32cc618 100644 --- a/src/main.cc +++ b/src/main.cc @@ -72,9 +72,11 @@ int set_bg_once(Config *cfg, SetBG* bg_setter, Glib::ustring path, int head, Set bg_setter->disable_pixmap_save(); disp = bg_setter->make_display_key(head); - bg_setter->set_bg(disp, file, mode, col); + bool shouldSave = bg_setter->set_bg(disp, file, mode, col); + + if (save && shouldSave) + Config::get_instance()->set_bg(disp, file, mode, col); - if (save) Config::get_instance()->set_bg(disp, file, mode, col); while (Gtk::Main::events_pending()) Gtk::Main::iteration();