| 1 |
@@ -1,3 +1,10 @@ |
| 1 |
//
|
| 2 |
// MenuHandler.cc for pekwm
|
| 3 |
// Copyright © 2009 Claes Nästén <me@pekdon.net>
|
| 4 |
//
|
| 5 |
// This program is licensed under the GNU GPL.
|
| 6 |
// See the LICENSE file for more information.
|
| 7 |
//
|
| 8 |
|
| 9 |
#ifdef HAVE_CONFIG_H
|
| 10 |
#include "config.h"
|
| ... |
|
| 36 |
@@ -29,18 +36,18 @@ |
| 36 |
* List of reserved names of built-in menus.
|
| 37 |
*/
|
| 38 |
const char *MenuHandler::MENU_NAMES_RESERVED[] = {
|
| 32 |
"AttachClientInFrame",
|
| 33 |
"AttachClient",
|
| 34 |
"AttachFrameInFrame",
|
| 35 |
"AttachFrame",
|
| 36 |
"DecorMenu",
|
| 37 |
"GotoClient",
|
| 38 |
"Goto",
|
| 39 |
"Icon",
|
| 40 |
"RootMenu",
|
| 41 |
"Root", // To avoid name conflict, ROOTMENU -> ROOT
|
| 42 |
"WindowMenu",
|
| 43 |
"Window" // To avoid name conflict, WINDOWMENU -> WINDOW
|
| 51 |
"ATTACHCLIENTINFRAME",
|
| 52 |
"ATTACHCLIENT",
|
| 53 |
"ATTACHFRAMEINFRAME",
|
| 54 |
"ATTACHFRAME",
|
| 55 |
"DECORMENU",
|
| 56 |
"GOTOCLIENT",
|
| 57 |
"GOTO",
|
| 58 |
"ICON",
|
| 59 |
"ROOTMENU",
|
| 60 |
"ROOT", // To avoid name conflict, ROOTMENU -> ROOT
|
| 61 |
"WINDOWMENU",
|
| 62 |
"WINDOW" // To avoid name conflict, WINDOWMENU -> WINDOW
|
| 63 |
};
|
| 64 |
|
| 65 |
const unsigned int MenuHandler::MENU_NAMES_RESERVED_COUNT =
|
| ... |
|
| 86 |
@@ -79,6 +86,8 @@ |
| 86 |
|
| 87 |
/**
|
| 88 |
* Menu handler constructor, create menus.
|
| 89 |
*
|
| 90 |
* Requires Config, PScreen and ActionHandler to be constructed.
|
| 91 |
*/
|
| 92 |
MenuHandler::MenuHandler(Theme *theme)
|
| 93 |
: _theme(theme)
|
| ... |
|
| 109 |
@@ -100,19 +109,10 @@ |
| 109 |
void
|
| 110 |
MenuHandler::hideAllMenus(void)
|
| 111 |
{
|
| 103 |
// bool do_focus = PWinObj::isFocusedPWinObj(PWinObj::WO_MENU);
|
| 104 |
|
| 114 |
map<std::string, PMenu*>::iterator it(_menu_map.begin());
|
| 115 |
for (; it != _menu_map.end(); ++it) {
|
| 116 |
it->second->unmapAll();
|
| 117 |
}
|
| 109 |
|
| 110 |
/**
|
| 111 |
* FIXME: Handled in window manager?
|
| 112 |
* if (do_focus) {
|
| 113 |
* findWOAndFocus(0);
|
| 114 |
* }
|
| 115 |
*/
|
| 125 |
}
|
| 126 |
|
| 127 |
/**
|
| ... |
|
| 121 |
@@ -121,54 +121,63 @@ |
| 121 |
void
|
| 122 |
MenuHandler::createMenus(void)
|
| 123 |
{
|
| 124 |
Config *config = Config::instance();
|
| 125 |
PScreen *screen = PScreen::instance();
|
| 126 |
ActionHandler *action_handler = ActionHandler::instance();
|
| 127 |
PMenu *menu = 0;
|
| 128 |
|
| 129 |
menu = new FrameListMenu(screen, _theme, ATTACH_CLIENT_IN_FRAME_TYPE,
|
| 130 |
L"Attach Client In Frame",
|
| 131 |
"ATTACHCLIENTINFRAME");
|
| 132 |
"AttachClientInFrame");
|
| 133 |
_menu_map["ATTACHCLIENTINFRAME"] = menu;
|
| 134 |
menu = new FrameListMenu(screen, _theme, ATTACH_CLIENT_TYPE,
|
| 135 |
L"Attach Client", "ATTACHCLIENT");
|
| 136 |
L"Attach Client", "AttachClient");
|
| 137 |
_menu_map["ATTACHCLIENT"] = menu;
|
| 138 |
menu = new FrameListMenu(screen, _theme, ATTACH_FRAME_IN_FRAME_TYPE,
|
| 139 |
L"Attach Frame In Frame",
|
| 140 |
"ATTACHFRAMEINFRAME");
|
| 141 |
"AttachFrameInFrame");
|
| 142 |
_menu_map["ATTACHFRAMEINFRAME"] = menu;
|
| 143 |
menu = new FrameListMenu(screen, _theme, ATTACH_FRAME_TYPE,
|
| 144 |
L"Attach Frame", "ATTACHFRAME");
|
| 145 |
L"Attach Frame", "AttachFrame");
|
| 146 |
_menu_map["ATTACHFRAME"] = menu;
|
| 147 |
menu = new FrameListMenu(screen, _theme, GOTOCLIENTMENU_TYPE,
|
| 148 |
L"Focus Client", "GOTOCLIENT");
|
| 149 |
L"Focus Client", "GotoClient");
|
| 150 |
_menu_map["GOTOCLIENT"] = menu;
|
| 151 |
menu = new FrameListMenu(screen, _theme, GOTOMENU_TYPE,
|
| 152 |
L"Focus Frame", "GOTO");
|
| 153 |
L"Focus Frame", "Goto");
|
| 154 |
_menu_map["GOTO"] = menu;
|
| 155 |
menu = new FrameListMenu(screen, _theme, ICONMENU_TYPE,
|
| 156 |
L"Focus Iconified Frame", "ICON");
|
| 157 |
L"Focus Iconified Frame", "Icon");
|
| 158 |
_menu_map["ICON"] = menu;
|
| 159 |
menu = new DecorMenu(screen, _theme, action_handler, "DECORMENU");
|
| 160 |
menu = new DecorMenu(screen, _theme, action_handler, "DecorMenu");
|
| 161 |
_menu_map["DECORMENU"] = menu;
|
| 162 |
menu = new ActionMenu(ROOTMENU_TYPE, L"", "ROOTMENU");
|
| 163 |
menu = new ActionMenu(ROOTMENU_TYPE, L"", "RootMenu");
|
| 164 |
_menu_map["ROOT"] = menu;
|
| 165 |
menu = new ActionMenu(WINDOWMENU_TYPE, L"", "WINDOWMENU");
|
| 166 |
menu = new ActionMenu(WINDOWMENU_TYPE, L"", "WindowMenu");
|
| 167 |
_menu_map["WINDOW"] = menu;
|
| 168 |
|
| 169 |
// As the previous step is done manually, make sure it's done correct.
|
| 170 |
assert(_menu_map.size() == (MENU_NAMES_RESERVED_COUNT - 2));
|
| 171 |
|
| 172 |
createMenusLoadConfiguration();
|
| 173 |
}
|
| 174 |
|
| 175 |
/**
|
| 176 |
* Initial load of menu configuration.
|
| 177 |
*/
|
| 178 |
void
|
| 179 |
MenuHandler::createMenusLoadConfiguration(void)
|
| 180 |
{
|
| 181 |
// Load configuration, pass specific section to loading
|
| 182 |
CfgParser menu_cfg;
|
| 183 |
if (menu_cfg.parse(config->getMenuFile())
|
| 184 |
if (menu_cfg.parse(Config::instance()->getMenuFile())
|
| 185 |
|| menu_cfg.parse (string(SYSCONFDIR "/menu"))) {
|
| 186 |
_menu_state = menu_cfg.get_file_list();
|
| 187 |
CfgParser::Entry *root_entry = menu_cfg.get_entry_root();
|
| 188 |
|
| 189 |
// Load standard menus
|
| 190 |
map<string, PMenu*>::iterator it = _menu_map.begin();
|
| 191 |
for (; it != _menu_map.end(); ++it) {
|
| 192 |
it->second->reload(menu_cfg.get_entry_root()->find_section(it->second->getName()));
|
| 193 |
it->second->reload(root_entry->find_section(it->second->getName()));
|
| 194 |
}
|
| 195 |
|
| 196 |
// Load standalone menus
|
| ... |
|
| 197 |
@@ -188,9 +197,34 @@ |
| 197 |
return;
|
| 198 |
}
|
| 199 |
|
| 191 |
// Load configuration, pass specific section to loading
|
| 201 |
CfgParser cfg;
|
| 202 |
bool cfg_ok = loadMenuConfig(menu_file, cfg);
|
| 203 |
CfgParser::Entry *root = cfg.get_entry_root();
|
| 204 |
|
| 205 |
// Update, delete standalone root menus, load decors on others
|
| 206 |
map<string, PMenu*>::iterator it(_menu_map.begin());
|
| 207 |
for (; it != _menu_map.end(); ++it) {
|
| 208 |
if (it->second->getMenuType() == ROOTMENU_STANDALONE_TYPE) {
|
| 209 |
delete it->second;
|
| 210 |
_menu_map.erase(it);
|
| 211 |
} else if (cfg_ok) {
|
| 212 |
// Only reload the menu if we got a ok configuration
|
| 213 |
it->second->reload(root->find_section(it->second->getName()));
|
| 214 |
}
|
| 215 |
}
|
| 216 |
|
| 217 |
// Update standalone root menus (name != ROOTMENU)
|
| 218 |
reloadStandaloneMenus(root);
|
| 219 |
}
|
| 220 |
|
| 221 |
/**
|
| 222 |
* Load menu configuration from menu_file resetting menu state.
|
| 223 |
*/
|
| 224 |
bool
|
| 225 |
MenuHandler::loadMenuConfig(const std::string &menu_file, CfgParser &menu_cfg)
|
| 226 |
{
|
| 227 |
bool cfg_ok = true;
|
| 219 |
CfgParser menu_cfg;
|
| 229 |
|
| 230 |
if (! menu_cfg.parse(menu_file)) {
|
| 231 |
if (! menu_cfg.parse(string(SYSCONFDIR "/menu"))) {
|
| 232 |
cfg_ok = false;
|
| ... |
|
| 239 |
@@ -205,22 +239,7 @@ |
| 239 |
_menu_state = menu_cfg.get_file_list();
|
| 240 |
}
|
| 241 |
|
| 208 |
// Update, delete standalone root menus, load decors on others
|
| 209 |
map<string, PMenu*>::iterator it(_menu_map.begin());
|
| 210 |
for (; it != _menu_map.end(); ++it) {
|
| 211 |
if (it->second->getMenuType() == ROOTMENU_STANDALONE_TYPE) {
|
| 212 |
delete it->second;
|
| 213 |
_menu_map.erase(it);
|
| 214 |
} else {
|
| 215 |
// Only reload the menu if we got a ok configuration
|
| 216 |
if (cfg_ok) {
|
| 217 |
it->second->reload(menu_cfg.get_entry_root()->find_section(it->second->getName()));
|
| 218 |
}
|
| 219 |
}
|
| 220 |
}
|
| 221 |
|
| 222 |
// Update standalone root menus (name != ROOTMENU)
|
| 223 |
reloadStandaloneMenus(menu_cfg.get_entry_root());
|
| 258 |
return cfg_ok;
|
| 259 |
}
|
| 260 |
|
| 261 |
/**
|
| ... |
|
| 249 |
@@ -230,24 +249,23 @@ |
| 249 |
MenuHandler::reloadStandaloneMenus(CfgParser::Entry *section)
|
| 250 |
{
|
| 251 |
// Temporary name, as names are stored uppercase
|
| 233 |
string menu_name;
|
| 253 |
string menu_name, menu_name_upper;
|
| 254 |
|
| 255 |
// Go through all but reserved section names and create menus
|
| 256 |
CfgParser::iterator it(section->begin());
|
| 257 |
for (; it != section->end(); ++it) {
|
| 258 |
// Uppercase name
|
| 259 |
menu_name = (*it)->get_name();
|
| 241 |
Util::to_upper(menu_name);
|
| 261 |
menu_name_upper = menu_name;
|
| 262 |
Util::to_upper(menu_name_upper);
|
| 263 |
|
| 264 |
// Create new menus, if the name is not reserved and not used
|
| 246 |
if (! binary_search(MENU_NAMES_RESERVED,
|
| 247 |
MENU_NAMES_RESERVED + MENU_NAMES_RESERVED_COUNT,
|
| 248 |
menu_name, str_comparator)
|
| 249 |
&& ! getMenu(menu_name)) {
|
| 269 |
if (! isReservedName(menu_name_upper) && ! getMenu(menu_name_upper)) {
|
| 270 |
// Create, parse and add to map
|
| 252 |
PMenu *menu = new ActionMenu(ROOTMENU_STANDALONE_TYPE, L"", menu_name);
|
| 272 |
PMenu *menu = new ActionMenu(ROOTMENU_STANDALONE_TYPE,
|
| 273 |
L"", menu_name);
|
| 274 |
menu->reload((*it)->get_section());
|
| 256 |
_menu_map[menu->getName()] = menu;
|
| 276 |
_menu_map[menu_name_upper] = menu;
|
| 277 |
}
|
| 278 |
}
|
| 279 |
}
|
| ... |
|
| 283 |
@@ -265,4 +283,15 @@ |
| 283 |
_menu_map.clear();
|
| 284 |
}
|
| 285 |
|
| 286 |
/**
|
| 287 |
* Check if name is reserved, return true if it is.
|
| 288 |
*/
|
| 289 |
bool
|
| 290 |
MenuHandler::isReservedName(const std::string &name)
|
| 291 |
{
|
| 292 |
return binary_search(MENU_NAMES_RESERVED,
|
| 293 |
MENU_NAMES_RESERVED + MENU_NAMES_RESERVED_COUNT,
|
| 294 |
name, str_comparator);
|
| 295 |
}
|
| 296 |
|
| 297 |
#endif // MENUS
|
| ... |
|