// // AutoProperties.cc for pekwm // Copyright © 2003-2009 Claes Nästén // // This program is licensed under the GNU GPL. // See the LICENSE file for more information. // #ifdef HAVE_CONFIG_H #include "config.h" #endif // HAVE_CONFIG_H #include #include #include #include "AutoProperties.hh" #include "Config.hh" #include "Util.hh" using std::cerr; using std::endl; using std::find; using std::list; using std::map; using std::string; using std::vector; using std::strtol; AutoProperties *AutoProperties::_instance = 0; //! @brief Constructor for AutoProperties class AutoProperties::AutoProperties(void) : _extended(false), _harbour_sort(false), _apply_on_start(true) { #ifdef DEBUG if (_instance) { cerr << __FILE__ << "@" << __LINE__ << ": " << "AutoProperties(" << this << ")::AutoProperties()" << endl << " *** _instance already set: " << _instance << endl; } #endif // DEBUG _instance = this; // fill parsing maps _apply_on_map[""] = APPLY_ON_NONE; _apply_on_map["START"] = APPLY_ON_START; _apply_on_map["NEW"] = APPLY_ON_NEW; _apply_on_map["RELOAD"] = APPLY_ON_RELOAD; _apply_on_map["WORKSPACE"] = APPLY_ON_WORKSPACE; _apply_on_map["TRANSIENT"] = APPLY_ON_TRANSIENT; _apply_on_map["TRANSIENTONLY"] = APPLY_ON_TRANSIENT_ONLY; // global properties _property_map[""] = AP_NO_PROPERTY; _property_map["WORKSPACE"] = AP_WORKSPACE; _property_map["PROPERTY"] = AP_PROPERTY; _property_map["STICKY"] = AP_STICKY; _property_map["SHADED"] = AP_SHADED; _property_map["MAXIMIZEDVERTICAL"] = AP_MAXIMIZED_VERTICAL; _property_map["MAXIMIZEDHORIZONTAL"] = AP_MAXIMIZED_HORIZONTAL; _property_map["ICONIFIED"] = AP_ICONIFIED; _property_map["BORDER"] = AP_BORDER; _property_map["TITLEBAR"] = AP_TITLEBAR; _property_map["FRAMEGEOMETRY"] = AP_FRAME_GEOMETRY; _property_map["CLIENTGEOMETRY"] = AP_CLIENT_GEOMETRY; _property_map["LAYER"] = AP_LAYER; _property_map["SKIP"] = AP_SKIP; _property_map["FULLSCREEN"] = AP_FULLSCREEN; _property_map["PLACENEW"] = AP_PLACE_NEW; _property_map["FOCUSNEW"] = AP_FOCUS_NEW; _property_map["FOCUSABLE"] = AP_FOCUSABLE; _property_map["CFGDENY"] = AP_CFG_DENY; _property_map["ALLOWEDACTIONS"] = AP_ALLOWED_ACTIONS; _property_map["DISALLOWEDACTIONS"] = AP_DISALLOWED_ACTIONS; #ifdef OPACITY _property_map["OPACITY"] = AP_OPACITY; #endif // OPACITY // group properties _group_property_map[""] = AP_NO_PROPERTY; _group_property_map["SIZE"] = AP_GROUP_SIZE; _group_property_map["BEHIND"] = AP_GROUP_BEHIND; _group_property_map["FOCUSEDFIRST"] = AP_GROUP_FOCUSED_FIRST; _group_property_map["GLOBAL"] = AP_GROUP_GLOBAL; _group_property_map["RAISE"] = AP_GROUP_RAISE; // window type map _window_type_map[""] = WINDOW_TYPE; _window_type_map["DESKTOP"] = WINDOW_TYPE_DESKTOP; _window_type_map["DOCK"] = WINDOW_TYPE_DOCK; _window_type_map["TOOLBAR"] = WINDOW_TYPE_TOOLBAR; _window_type_map["MENU"] = WINDOW_TYPE_MENU; _window_type_map["UTILITY"] = WINDOW_TYPE_UTILITY; _window_type_map["SPLASH"] = WINDOW_TYPE_SPLASH; _window_type_map["DIALOG"] = WINDOW_TYPE_DIALOG; _window_type_map["NORMAL"] = WINDOW_TYPE_NORMAL; } //! @brief Destructor for AutoProperties class AutoProperties::~AutoProperties(void) { unload(); _instance = 0; } //! @brief Loads the autoprop config file. bool AutoProperties::load(void) { string cfg_file(Config::instance()->getAutoPropsFile()); if (! Util::requireReload(_cfg_state, cfg_file)) { return false; } // dealloc memory unload(); CfgParser a_cfg; if (! a_cfg.parse(cfg_file, CfgParserSource::SOURCE_FILE, false)) { cfg_file = SYSCONFDIR "/autoproperties"; if (! a_cfg.parse (cfg_file, CfgParserSource::SOURCE_FILE, false)) { setDefaultTypeProperties(); return false; } } // Setup template parsing if requested loadRequire(a_cfg, cfg_file); if (a_cfg.is_dynamic_content()) { _cfg_state.clear(); } else { _cfg_state = a_cfg.get_file_list(); } // reset values _apply_on_start = true; vector tokens; vector::iterator token_it; list workspaces; CfgParser::iterator it(a_cfg.get_entry_root()->begin()); for (; it != a_cfg.get_entry_root()->end(); ++it) { if (*(*it) == "PROPERTY") { parseAutoProperty(*it, 0); } else if (*(*it) == "TITLERULES") { parseTitleProperty(*it); } else if (*(*it) == "DECORRULES") { parseDecorProperty(*it); } else if (*(*it) == "TYPERULES") { parseTypeProperty(*it); } else if (*(*it) == "HARBOUR") { parseDockAppProperty(*it); } else if (*(*it) == "WORKSPACE") { // Workspace section CfgParser::Entry *workspace = (*it)->get_section(); CfgParser::Entry *value = workspace->find_entry("WORKSPACE"); if (! value) { continue; // Need workspace numbers. } tokens.clear(); if (Util::splitString(value->get_value(), tokens, " \t")) { workspaces.clear(); for (token_it = tokens.begin(); token_it != tokens.end(); ++token_it) workspaces.push_back(strtol(token_it->c_str(), 0, 10) - 1); // Get all properties on for these workspaces. CfgParser::iterator workspace_it(workspace->begin()); for (; workspace_it != workspace->end(); ++workspace_it) { parseAutoProperty(*workspace_it, &workspaces); } } } } // Validate date setDefaultTypeProperties(); return true; } /** * Load autoproperties quirks. */ void AutoProperties::loadRequire(CfgParser &a_cfg, std::string &file) { CfgParser::Entry *section; // Look for requires section, section = a_cfg.get_entry_root()->find_section("REQUIRE"); if (section) { list key_list; key_list.push_back(new CfgParserKeyBool("TEMPLATES", _extended, false)); section->parse_key_values(key_list.begin(), key_list.end()); for_each(key_list.begin(), key_list.end(), Util::Free()); // Re-load configuration with templates enabled. if (_extended) { a_cfg.clear(true); a_cfg.parse(file, CfgParserSource::SOURCE_FILE, true); } } else { _extended = false; } } //! @brief Frees allocated memory void AutoProperties::unload(void) { list::iterator it; // remove auto properties for (it = _prop_list.begin(); it != _prop_list.end(); ++it) { delete *it; } _prop_list.clear(); // remove title properties for (it = _title_prop_list.begin(); it != _title_prop_list.end(); ++it) { delete *it; } _title_prop_list.clear(); // remove decor properties for (it = _decor_prop_list.begin(); it != _decor_prop_list.end(); ++it) { delete *it; } _decor_prop_list.clear(); // remove dock app properties for (it = _dock_app_prop_list.begin(); it != _dock_app_prop_list.end(); ++it) { delete *it; } _dock_app_prop_list.clear(); // remove type properties map::iterator m_it(_window_type_prop_map.begin()); for (; m_it != _window_type_prop_map.end(); ++m_it) { delete m_it->second; } _window_type_prop_map.clear(); } //! @brief Finds a property from the prop_list Property* AutoProperties::findProperty(const ClassHint* class_hint, std::list* prop_list, int ws, uint type) { // Allready remove apply on start if (! _apply_on_start && (type == APPLY_ON_START)) return 0; list::iterator it(prop_list->begin()); list::iterator w_it; // start searching for a suitable property for (; it != prop_list->end(); ++it) { // see if the type matches, if we have one if ((type != 0) && ! (*it)->isApplyOn(type)) continue; if (matchAutoClass(*class_hint, *it)) { // make sure it applies on the correct workspace if ((*it)->getWsList().size()) { w_it = find((*it)->getWsList().begin(), (*it)->getWsList().end(), unsigned(ws)); if (w_it != (*it)->getWsList().end()) { return *it; } } else { return *it; } } } return 0; } /** * Parse regex_str and set on regex, outputting warning with name if * it fails. */ bool AutoProperties::parseRegexpOrWarning(RegexString ®ex, const std::string regex_str, const std::string &name) { if (! regex_str.size() || regex.parse_match(Util::to_wide_str(regex_str))) { return true; } else { cerr << " *** WARNING: invalid regexp " << regex_str << " for autoproperty " << name << endl; return false; } } //! @brief Parses a property match rule //! @param str String to parse. //! @param prop Property to place result in. //! @param extended Extended syntax including role and title in the name, defaults to true. //! @return true on success, else false. bool AutoProperties::parsePropertyMatch(const std::string &str, Property *prop, bool extended) { bool status = false; // Format of property matches are regexp,regexp . Split up in class // and role regexps. vector tokens; Util::splitString(str, tokens, ",", extended ? 5 : 2, true); if (tokens.size() >= 2) { // Make sure one of the two regexps compiles status = parseRegexpOrWarning(prop->getHintName(), tokens[0], "name"); status = status && parseRegexpOrWarning(prop->getHintClass(), tokens[1], "class"); } // Parse extended part of regexp, role, title and apply on if (status && extended) { if (status && tokens.size() > 2) { status = parseRegexpOrWarning(prop->getRole(), tokens[2], "role"); } if (status && tokens.size() > 3) { status = parseRegexpOrWarning(prop->getTitle(), tokens[3], "title"); } if (status && tokens.size() > 4) { parsePropertyApplyOn(tokens[4], prop); } } return status; } //! @brief Parses a cs and sets up a basic property bool AutoProperties::parseProperty(CfgParser::Entry *section, Property *prop) { CfgParser::Entry *value; // Get extra matching info. value = section->find_entry ("TITLE"); if (value) { parseRegexpOrWarning(prop->getTitle(), value->get_value(), "title"); } value = section->find_entry ("ROLE"); if (value) { parseRegexpOrWarning(prop->getRole(), value->get_value(), "role"); } // Parse apply on mask. value = section->find_entry ("APPLYON"); if (value) { parsePropertyApplyOn(value->get_value(), prop); } return true; } /** * Parse property apply on. */ void AutoProperties::parsePropertyApplyOn(const std::string &apply_on, Property *prop) { vector tokens; if ((Util::splitString(apply_on, tokens, " \t", 5))) { vector::iterator it(tokens.begin()); for (; it != tokens.end(); ++it) { prop->applyAdd(static_cast(ParseUtil::getValue(*it, _apply_on_map))); } } } //! @brief Parses AutopProperty void AutoProperties::parseAutoProperty(CfgParser::Entry *section, std::list* ws) { // Get sub section section = section->get_section(); if (! section) { return; } AutoProperty* property = new AutoProperty(); parsePropertyMatch(section->get_value(), property, _extended); if (parseProperty(section, property)) { parseAutoPropertyValue(section, property, ws); _prop_list.push_back(property); } else { delete property; } } //! @brief Parses a Group section of the AutoProps void AutoProperties::parseAutoGroup(CfgParser::Entry *section, AutoProperty* property) { if (! section) { return; } if (section->get_value().size()) { property->group_name = Util::to_wide_str(section->get_value()); } PropertyType property_type; CfgParser::iterator it(section->begin()); for (; it != section->end(); ++it) { property_type = ParseUtil::getValue((*it)->get_name(), _group_property_map); switch (property_type) { case AP_GROUP_SIZE: property->group_size = strtol((*it)->get_value().c_str(), 0, 10); break; case AP_GROUP_BEHIND: property->group_behind = Util::isTrue((*it)->get_value()); break; case AP_GROUP_FOCUSED_FIRST: property->group_focused_first = Util::isTrue((*it)->get_value()); break; case AP_GROUP_GLOBAL: property->group_global = Util::isTrue((*it)->get_value()); break; case AP_GROUP_RAISE: property->group_raise = Util::isTrue((*it)->get_value()); break; default: // do nothing break; } } } /** * Parses a title property section. */ void AutoProperties::parseTitleProperty(CfgParser::Entry *section) { section = section->get_section(); TitleProperty *title_property; CfgParser::Entry *title_section; CfgParser::iterator it(section->begin()); for (; it != section->end(); ++it) { title_section = (*it)->get_section(); if (! title_section) { continue; } title_property = new TitleProperty(); parsePropertyMatch(title_section->get_value(), title_property, _extended); if (parseProperty(title_section, title_property)) { CfgParser::Entry *value = title_section->find_entry("RULE"); if (value && title_property->getTitleRule().parse_ed_s(Util::to_wide_str(value->get_value()))) { _title_prop_list.push_back(title_property); title_property = 0; } } if (title_property) { delete title_property; } } } /** * Parse decor property sections. */ void AutoProperties::parseDecorProperty(CfgParser::Entry *section) { section = section->get_section(); DecorProperty *decor_property; CfgParser::Entry *decor_section; CfgParser::iterator it(section->begin()); for (; it != section->end(); ++it) { decor_section = (*it)->get_section (); if (! decor_section) { continue; } decor_property = new DecorProperty(); parsePropertyMatch(decor_section->get_value (), decor_property, _extended); if (parseProperty(decor_section, decor_property)) { CfgParser::Entry *value = decor_section->find_entry("DECOR"); if (value) { decor_property->applyAdd(APPLY_ON_START); decor_property->setName(value->get_value()); _decor_prop_list.push_back(decor_property); decor_property = 0; } } if (decor_property) { delete decor_property; } } } /** * Parse dock app properties. */ void AutoProperties::parseDockAppProperty(CfgParser::Entry *section) { section = section->get_section(); // Reset harbour sort, set to true if POSITION property found. _harbour_sort = false; DockAppProperty *dock_property; CfgParser::Entry *dock_section; CfgParser::iterator it(section->begin()); for (; it != section->end(); ++it) { dock_section = (*it)->get_section(); if (! dock_section) { continue; } dock_property = new DockAppProperty(); parsePropertyMatch(dock_section->get_value(), dock_property, _extended); if (parseProperty(dock_section, dock_property)) { CfgParser::Entry *value = dock_section->find_entry("POSITION"); if (value) { _harbour_sort = true; int position = strtol(value->get_value().c_str(), 0, 10); dock_property->setPosition(position); _decor_prop_list.push_back(dock_property); dock_property = 0; } } if (dock_property) { delete dock_property; } } } //! @brief Parse type auto properties. //! @param section Section containing properties. void AutoProperties::parseTypeProperty(CfgParser::Entry *section) { // Get sub section section = section->get_section(); AtomName atom; AutoProperty *type_property; CfgParser::Entry *type_section; map::iterator atom_it; // Look for all type properties CfgParser::iterator it(section->begin()); for (; it != section->end(); ++it) { type_section = (*it)->get_section(); if (! type_section) { continue; } // Create new property and try to parse type_property = new AutoProperty(); atom = ParseUtil::getValue(type_section->get_value(), _window_type_map); if (atom == WINDOW_TYPE) { cerr << " *** WARNING: unknown type " << type_section->get_value() << " for autoproperty." << endl; } if (atom != WINDOW_TYPE && parseProperty(type_section, type_property)) { // Parse of match ok, parse values parseAutoPropertyValue(type_section, type_property, 0); // Add to list, make sure it does not exist already atom_it = _window_type_prop_map.find(atom); if (atom_it != _window_type_prop_map.end()) { cerr << " *** WARNING: multiple type autoproperties for type " << type_section->get_value() << endl; delete atom_it->second; } _window_type_prop_map[atom] = type_property; } else { delete type_property; } } } //! @brief Set default values for type auto properties not in configuration. void AutoProperties::setDefaultTypeProperties(void) { // DESKTOP if (! findWindowTypeProperty(WINDOW_TYPE_DESKTOP)) { AutoProperty *prop = new AutoProperty(); prop->maskAdd(AP_CLIENT_GEOMETRY); prop->client_gm_mask = XParseGeometry("0x0+0+0", &prop->client_gm.x, &prop->client_gm.y, &prop->client_gm.width, &prop->client_gm.height); prop->maskAdd(AP_STICKY); prop->sticky = true; prop->maskAdd(AP_TITLEBAR); prop->titlebar = false; prop->maskAdd(AP_BORDER); prop->border = false; prop->maskAdd(AP_SKIP); prop->skip = SKIP_MENUS|SKIP_FOCUS_TOGGLE|SKIP_SNAP|SKIP_PAGER|SKIP_TASKBAR; prop->maskAdd(AP_LAYER); prop->layer = LAYER_DESKTOP; prop->maskAdd(AP_FOCUSABLE); prop->focusable = false; prop->maskAdd(AP_DISALLOWED_ACTIONS); prop->disallowed_actions = ACTION_ACCESS_MOVE|ACTION_ACCESS_RESIZE; _window_type_prop_map[WINDOW_TYPE_DESKTOP] = prop; } // DOCK if (! findWindowTypeProperty(WINDOW_TYPE_DOCK)) { AutoProperty *prop = new AutoProperty(); prop->maskAdd(AP_STICKY); prop->sticky = true; prop->maskAdd(AP_TITLEBAR); prop->titlebar = false; prop->maskAdd(AP_BORDER); prop->border = false; prop->maskAdd(AP_SKIP); prop->skip = SKIP_MENUS|SKIP_FOCUS_TOGGLE|SKIP_PAGER|SKIP_TASKBAR; prop->maskAdd(AP_LAYER); prop->layer = LAYER_DOCK; prop->maskAdd(AP_FOCUSABLE); prop->focusable = false; prop->maskAdd(AP_DISALLOWED_ACTIONS); prop->disallowed_actions = ACTION_ACCESS_MOVE|ACTION_ACCESS_RESIZE; _window_type_prop_map[WINDOW_TYPE_DOCK] = prop; } // TOOLBAR if (! findWindowTypeProperty(WINDOW_TYPE_TOOLBAR)) { AutoProperty *prop = new AutoProperty(); prop->maskAdd(AP_TITLEBAR); prop->titlebar = true; prop->maskAdd(AP_BORDER); prop->border = true; prop->maskAdd(AP_SKIP); prop->skip = SKIP_MENUS|SKIP_FOCUS_TOGGLE|SKIP_PAGER|SKIP_TASKBAR; _window_type_prop_map[WINDOW_TYPE_TOOLBAR] = prop; } // MENU if (! findWindowTypeProperty(WINDOW_TYPE_MENU)) { AutoProperty *prop = new AutoProperty(); prop->maskAdd(AP_TITLEBAR); prop->titlebar = false; prop->maskAdd(AP_BORDER); prop->border = false; prop->maskAdd(AP_SKIP); prop->skip = SKIP_MENUS|SKIP_FOCUS_TOGGLE|SKIP_SNAP|SKIP_PAGER|SKIP_TASKBAR; _window_type_prop_map[WINDOW_TYPE_MENU] = prop; } // UTILITY if (! findWindowTypeProperty(WINDOW_TYPE_UTILITY)) { AutoProperty *prop = new AutoProperty(); prop->maskAdd(AP_TITLEBAR); prop->titlebar = true; prop->maskAdd(AP_BORDER); prop->border = true; prop->maskAdd(AP_SKIP); prop->skip = SKIP_MENUS|SKIP_FOCUS_TOGGLE|SKIP_SNAP; _window_type_prop_map[WINDOW_TYPE_UTILITY] = prop; } // SPLASH if (! findWindowTypeProperty(WINDOW_TYPE_SPLASH)) { AutoProperty *prop = new AutoProperty(); prop->maskAdd(AP_TITLEBAR); prop->titlebar = false; prop->maskAdd(AP_BORDER); prop->border = false; _window_type_prop_map[WINDOW_TYPE_SPLASH] = prop; } } //! @brief Parse AutoProperty value attributes. //! @param section Config section to parse. //! @param prop Property to store result in. //! @param ws List of workspaces to apply property on. void AutoProperties::parseAutoPropertyValue(CfgParser::Entry *section, AutoProperty *prop, std::list *ws) { // Copy workspaces, if any if (ws) { prop->getWsList().assign(ws->begin(), ws->end()); } // See if we have a group section CfgParser::Entry *group_section(section->find_section ("GROUP")); if (group_section) { parseAutoGroup(group_section, prop); } // start parsing of values string name, value; vector tokens; vector::iterator token_it; PropertyType property_type; CfgParser::iterator it(section->begin()); for (; it != section->end(); ++it) { property_type = ParseUtil::getValue((*it)->get_name(), _property_map); switch (property_type) { case AP_STICKY: prop->maskAdd(AP_STICKY); prop->sticky = Util::isTrue((*it)->get_value()); break; case AP_SHADED: prop->maskAdd(AP_SHADED); prop->shaded = Util::isTrue((*it)->get_value()); break; case AP_MAXIMIZED_VERTICAL: prop->maskAdd(AP_MAXIMIZED_VERTICAL); prop->maximized_vertical = Util::isTrue((*it)->get_value()); break; case AP_MAXIMIZED_HORIZONTAL: prop->maskAdd(AP_MAXIMIZED_HORIZONTAL); prop->maximized_horizontal = Util::isTrue((*it)->get_value()); break; case AP_ICONIFIED: prop->maskAdd(AP_ICONIFIED); prop->iconified = Util::isTrue((*it)->get_value()); break; case AP_BORDER: prop->maskAdd(AP_BORDER); prop->border = Util::isTrue((*it)->get_value()); break; case AP_TITLEBAR: prop->maskAdd(AP_TITLEBAR); prop->titlebar = Util::isTrue((*it)->get_value()); break; case AP_FRAME_GEOMETRY: prop->maskAdd(AP_FRAME_GEOMETRY); prop->frame_gm_mask = XParseGeometry((char*) (*it)->get_value().c_str(), &prop->frame_gm.x, &prop->frame_gm.y, &prop->frame_gm.width, &prop->frame_gm.height); break; case AP_CLIENT_GEOMETRY: prop->maskAdd(AP_CLIENT_GEOMETRY); prop->client_gm_mask = XParseGeometry((char*) (*it)->get_value().c_str(), &prop->client_gm.x, &prop->client_gm.y, &prop->client_gm.width, &prop->client_gm.height); break; case AP_LAYER: prop->layer = Config::instance()->getLayer((*it)->get_value()); if (prop->layer != LAYER_NONE) { prop->maskAdd(AP_LAYER); } break; case AP_WORKSPACE: prop->maskAdd(AP_WORKSPACE); prop->workspace = unsigned(strtol((*it)->get_value().c_str(), 0, 10) - 1); break; case AP_SKIP: prop->maskAdd(AP_SKIP); tokens.clear(); if ((Util::splitString((*it)->get_value(), tokens, " \t"))) { for (token_it = tokens.begin(); token_it != tokens.end(); ++token_it) { prop->skip |= Config::instance()->getSkip(*token_it); } } break; case AP_FULLSCREEN: prop->maskAdd(AP_FULLSCREEN); prop->fullscreen = Util::isTrue((*it)->get_value()); break; case AP_PLACE_NEW: prop->maskAdd(AP_PLACE_NEW); prop->place_new = Util::isTrue((*it)->get_value()); break; case AP_FOCUS_NEW: prop->maskAdd(AP_FOCUS_NEW); prop->focus_new = Util::isTrue((*it)->get_value()); break; case AP_FOCUSABLE: prop->maskAdd(AP_FOCUSABLE); prop->focusable = Util::isTrue((*it)->get_value()); break; case AP_CFG_DENY: prop->maskAdd(AP_CFG_DENY); tokens.clear(); if ((Util::splitString((*it)->get_value(), tokens, " \t"))) { for (token_it = tokens.begin(); token_it != tokens.end(); ++token_it) { prop->cfg_deny |= Config::instance()->getCfgDeny(*token_it); } } break; case AP_ALLOWED_ACTIONS: prop->maskAdd(AP_ALLOWED_ACTIONS); Config::instance()->parseActionAccessMask((*it)->get_value(), prop->allowed_actions); break; case AP_DISALLOWED_ACTIONS: prop->maskAdd(AP_DISALLOWED_ACTIONS); Config::instance()->parseActionAccessMask((*it)->get_value(), prop->disallowed_actions); break; #ifdef OPACITY case AP_OPACITY: prop->maskAdd(AP_OPACITY); Config::parseOpacity((*it)->get_value(), prop->focus_opacity, prop->unfocus_opacity); break; #endif // OPACITY default: // do nothing break; } } } //! @brief Searches the _prop_list for a property AutoProperty* AutoProperties::findAutoProperty(const ClassHint* class_hint, int ws, uint type) { return static_cast(findProperty(class_hint, &_prop_list, ws, type)); } //! @brief Searches the _title_prop_list for a property TitleProperty* AutoProperties::findTitleProperty(const ClassHint* class_hint) { return static_cast(findProperty(class_hint, &_title_prop_list, -1, 0)); } //! @brief DecorProperty* AutoProperties::findDecorProperty(const ClassHint* class_hint) { return static_cast(findProperty(class_hint, &_decor_prop_list, -1, 0)); } DockAppProperty* AutoProperties::findDockAppProperty(const ClassHint *class_hint) { return static_cast(findProperty(class_hint, &_dock_app_prop_list, -1, 0)); } //! @brief Get AutoProperty for window of type type //! @param atom Atom to get property for. //! @return AutoProperty on success, else 0. AutoProperty* AutoProperties::findWindowTypeProperty(AtomName atom) { AutoProperty *prop = 0; map::iterator it(_window_type_prop_map.find(atom)); if (it != _window_type_prop_map.end()) { prop = it->second; } return prop; } //! @brief Removes all ApplyOnStart actions as they consume memory void AutoProperties::removeApplyOnStart(void) { list::iterator it(_prop_list.begin()); for (; it != _prop_list.end(); ++it) { if ((*it)->isApplyOn(APPLY_ON_START)) { (*it)->applyRemove(APPLY_ON_START); if (! (*it)->getApplyOn()) { delete *it; it = _prop_list.erase(it); --it; // compensate for the ++ in the loop } } } _apply_on_start = false; } //! @brief Tries to match a class hint against an autoproperty data entry bool AutoProperties::matchAutoClass(const ClassHint &hint, Property *prop) { bool ok = false; if ((prop->getHintName() == hint.h_name) && (prop->getHintClass() == hint.h_class)) { ok = true; if (prop->getTitle ().is_match_ok ()) { ok = (prop->getTitle () == hint.title); } if (ok && prop->getRole ().is_match_ok ()) { ok = (prop->getRole () == hint.h_role); } } return ok; }