all repos — fluxbox @ 5373f6d840abaa49685c15fee2f411e77472a7da

custom fork of the fluxbox windowmanager

moved window menu from FluxboxWindow to BScreen
fluxgen fluxgen
commit

5373f6d840abaa49685c15fee2f411e77472a7da

parent

18cf5862495aa6f37110c90286bb6c315a145526

M src/LayerMenu.hhsrc/LayerMenu.hh

@@ -25,91 +25,46 @@

#ifndef LAYERMENU_HH #define LAYERMENU_HH -#include "MenuItem.hh" + #include "ToggleMenu.hh" -#include "RefCount.hh" -#include "SimpleCommand.hh" -#include "I18n.hh" -#include "fluxbox.hh" +#include "FbTk/MenuItem.hh" + +class LayerObject { +public: + virtual void moveToLayer(int layer_number) = 0; + virtual int layerNumber() const = 0; +}; -// provides a generic way for giving an object a layer menu /// this class holds the layermenu items -template <typename ItemType> class LayerMenuItem : public FbTk::MenuItem { public: - LayerMenuItem(const char *label, ItemType *object, int layernum, + LayerMenuItem(const char *label, LayerObject *object, int layernum, FbTk::RefCount<FbTk::Command> &cmd): - FbTk::MenuItem(label,cmd), m_object(object), m_layernum(layernum) {} - LayerMenuItem(const char *label, ItemType *object, int layernum): + FbTk::MenuItem(label, cmd), m_object(object), m_layernum(layernum) {} + + LayerMenuItem(const char *label, LayerObject *object, int layernum): FbTk::MenuItem(label), m_object(object), m_layernum(layernum) {} - bool isEnabled() const { return m_object->layerItem().getLayerNum() != m_layernum; } + bool isEnabled() const { return m_object->layerNumber() != m_layernum; } void click(int button, int time) { m_object->moveToLayer(m_layernum); FbTk::MenuItem::click(button, time); } private: - ItemType *m_object; + LayerObject *m_object; int m_layernum; }; /// Create a layer menu inside from the given menu -template <typename ItemType> class LayerMenu : public ToggleMenu { public: LayerMenu(MenuTheme &tm, FbTk::ImageControl &imgctrl, - FbTk::XLayer &layer, ItemType *item, bool save_rc); + FbTk::XLayer &layer, LayerObject *item, bool save_rc); - -private: - ItemType *m_object; }; - - -template <typename ItemType> -LayerMenu<ItemType>::LayerMenu(MenuTheme &tm, FbTk::ImageControl &imgctrl, - FbTk::XLayer &layer, ItemType *item, bool save_rc): - ToggleMenu(tm, imgctrl, layer), - m_object(item) -{ - _FB_USES_NLS; - - Fluxbox *fluxbox = Fluxbox::instance(); - - struct { - int set; - int base; - const char *default_str; - int layernum; - } layer_menuitems[] = { - //TODO: nls - {0, 0, _FBTEXT(Layer, AboveDock, "Above Dock", "Layer above dock"), fluxbox->getAboveDockLayer()}, - {0, 0, _FBTEXT(Layer, Dock, "Dock", "Layer dock"), fluxbox->getDockLayer()}, - {0, 0, _FBTEXT(Layer, Top, "Top", "Layer top"), fluxbox->getTopLayer()}, - {0, 0, _FBTEXT(Layer, Normal, "Normal", "Layer normal"), fluxbox->getNormalLayer()}, - {0, 0, _FBTEXT(Layer, Bottom, "Bottom", "Layer bottom"), fluxbox->getBottomLayer()}, - {0, 0, _FBTEXT(Layer, Desktop, "Desktop", "Layer desktop"), fluxbox->getDesktopLayer()}, - }; - - FbTk::RefCount<FbTk::Command> saverc_cmd(new FbTk::SimpleCommand<Fluxbox>( - *Fluxbox::instance(), - &Fluxbox::save_rc)); - - for (size_t i=0; i < 6; ++i) { - // TODO: fetch nls string - if (save_rc) { - insert(new LayerMenuItem<ItemType>(layer_menuitems[i].default_str, - m_object, layer_menuitems[i].layernum, saverc_cmd)); - } else { - insert(new LayerMenuItem<ItemType>(layer_menuitems[i].default_str, - m_object, layer_menuitems[i].layernum)); - } - } - updateMenu(); -} #endif // LAYERMENU_HH
M src/MenuCreator.ccsrc/MenuCreator.cc

@@ -29,6 +29,7 @@ #include "CommandParser.hh"

#include "fluxbox.hh" #include "CommandParser.hh" #include "Window.hh" +#include "WindowCmd.hh" #include "FbMenu.hh" #include "IconMenu.hh"

@@ -53,13 +54,8 @@

#include <iostream> using namespace std; -template <> -void LayerMenuItem<FluxboxWindow>::click(int button, int time) { - m_object->moveToLayer(m_layernum); -} - static void createStyleMenu(FbTk::Menu &parent, const std::string &label, - const std::string &directory) { + const std::string &directory) { // perform shell style ~ home directory expansion string stylesdir(FbTk::StringUtil::expandFilename(directory));

@@ -326,19 +322,19 @@ }

} -static void parseWindowMenu(Parser &parse, FbTk::Menu &menu, FluxboxWindow &win) { +static void parseWindowMenu(Parser &parse, FbTk::Menu &menu) { ParseItem pitem(&menu); while (!parse.eof()) { pitem.load(parse); - if (MenuCreator::createWindowMenuItem(pitem.key(), pitem.label(), menu, win)) + if (MenuCreator::createWindowMenuItem(pitem.key(), pitem.label(), menu)) continue; if (pitem.key() == "end") { return; } else if (pitem.key() == "submenu") { FbTk::Menu *submenu = MenuCreator::createMenu(pitem.label(), menu.screenNumber()); - parseWindowMenu(parse, *submenu, win); + parseWindowMenu(parse, *submenu); submenu->updateMenu(); menu.insert(pitem.label().c_str(), submenu);

@@ -416,9 +412,9 @@ return true;

} -bool MenuCreator::createFromFile(const std::string &filename, - FbTk::Menu &inject_into, - FluxboxWindow &win, bool require_begin) { +bool MenuCreator::createWindowMenuFromFile(const std::string &filename, + FbTk::Menu &inject_into, + bool require_begin) { std::string real_filename = FbTk::StringUtil::expandFilename(filename); FbMenuParser parser(real_filename); if (!parser.isLoaded())

@@ -429,7 +425,7 @@

if (require_begin && !getStart(parser, label)) return false; - parseWindowMenu(parser, inject_into, win); + parseWindowMenu(parser, inject_into); return true; }

@@ -442,26 +438,56 @@ if (type == "iconmenu") {

return new IconMenu(*screen); } else if (type == "workspacemenu") { return new WorkspaceMenu(*screen); + } else if (type == "windowmenu") { + FbTk::Menu *menu = screen->createMenu(""); + + menu->removeAll(); // clear old items + menu->disableTitle(); // not titlebar + if (screen->windowMenuFilename().empty() || + ! createWindowMenuFromFile(screen->windowMenuFilename(), *menu, true)) { + char default_menu[][11] = { + "shade", + "stick", + "maximize", + "iconify", + "raise", + "lower", + "sendto", + "layer", + "extramenus", + "separator", + "close", + 0 + }; + for (int i=0; i < sizeof(default_menu); ++i) + createWindowMenuItem(default_menu[i], "", *menu); + } + menu->reconfigure(); // update graphics + return menu; } + return 0; } bool MenuCreator::createWindowMenuItem(const std::string &type, const std::string &label, - FbTk::Menu &menu, - FluxboxWindow &win) { + FbTk::Menu &menu) { typedef FbTk::RefCount<FbTk::Command> RefCmd; - typedef FbTk::SimpleCommand<FluxboxWindow> WindowCmd; _FB_USES_NLS; if (type == "shade") { - RefCmd shade_cmd(new WindowCmd(win, &FluxboxWindow::shade)); + RefCmd shade_cmd(new WindowCmd<void>(&FluxboxWindow::shade)); menu.insert(label.empty()?_FBTEXT(Windowmenu, Shade, "Shade", "Shade the window"):label.c_str(), shade_cmd); } else if (type == "maximize") { - RefCmd maximize_cmd(new WindowCmd(win, &FluxboxWindow::maximizeFull)); - RefCmd maximize_vert_cmd(new WindowCmd(win, &FluxboxWindow::maximizeVertical)); - RefCmd maximize_horiz_cmd(new WindowCmd(win, &FluxboxWindow::maximizeHorizontal)); - FbTk::MultiButtonMenuItem *maximize_item = new FbTk::MultiButtonMenuItem(3, label.empty()?_FBTEXT(Windowmenu, Maximize, "Maximize", "Maximize the window"):label.c_str()); + RefCmd maximize_cmd(new WindowCmd<void>(&FluxboxWindow::maximizeFull)); + RefCmd maximize_vert_cmd(new WindowCmd<void>(&FluxboxWindow::maximizeVertical)); + RefCmd maximize_horiz_cmd(new WindowCmd<void>(&FluxboxWindow::maximizeHorizontal)); + FbTk::MultiButtonMenuItem *maximize_item = + new FbTk::MultiButtonMenuItem(3, + label.empty()? + _FBTEXT(Windowmenu, Maximize, + "Maximize", "Maximize the window"): + label.c_str()); // create maximize item with: // button1: Maximize normal // button2: Maximize Vertical

@@ -471,43 +497,61 @@ maximize_item->setCommand(2, maximize_vert_cmd);

maximize_item->setCommand(3, maximize_horiz_cmd); menu.insert(maximize_item); } else if (type == "iconify") { - RefCmd iconify_cmd(new WindowCmd(win, &FluxboxWindow::iconify)); + RefCmd iconify_cmd(new WindowCmd<void>(&FluxboxWindow::iconify)); menu.insert(label.empty()?_FBTEXT(Windowmenu, Iconify, "Iconify", "Iconify the window"):label.c_str(), iconify_cmd); } else if (type == "close") { - RefCmd close_cmd(new WindowCmd(win, &FluxboxWindow::close)); + RefCmd close_cmd(new WindowCmd<void>(&FluxboxWindow::close)); menu.insert(label.empty()?_FBTEXT(Windowmenu, Close, "Close", "Close the window"):label.c_str(), close_cmd); } else if (type == "kill" || type == "killwindow") { - RefCmd kill_cmd(new WindowCmd(win, &FluxboxWindow::kill)); + RefCmd kill_cmd(new WindowCmd<void>(&FluxboxWindow::kill)); menu.insert(label.empty()?_FBTEXT(Windowmenu, Kill, "Kill", "Kill the window"):label.c_str(), kill_cmd); } else if (type == "lower") { - RefCmd lower_cmd(new WindowCmd(win, &FluxboxWindow::lower)); + RefCmd lower_cmd(new WindowCmd<void>(&FluxboxWindow::lower)); menu.insert(label.empty()?_FBTEXT(Windowmenu, Lower, "Lower", "Lower the window"):label.c_str(), lower_cmd); } else if (type == "raise") { - RefCmd raise_cmd(new WindowCmd(win, &FluxboxWindow::raise)); + RefCmd raise_cmd(new WindowCmd<void>(&FluxboxWindow::raise)); menu.insert(label.empty()?_FBTEXT(Windowmenu, Raise, "Raise", "Raise the window"):label.c_str(), raise_cmd); } else if (type == "stick") { - RefCmd stick_cmd(new WindowCmd(win, &FluxboxWindow::stick)); + RefCmd stick_cmd(new WindowCmd<void>(&FluxboxWindow::stick)); menu.insert(label.empty()?_FBTEXT(Windowmenu, Stick, "Stick", "Stick the window"):label.c_str(), stick_cmd); - } else if (type == "extramenus") { - FluxboxWindow::ExtraMenus::iterator it = win.extraMenus().begin(); - FluxboxWindow::ExtraMenus::iterator it_end = win.extraMenus().end(); + } + else if (type == "extramenus") { + BScreen *screen = Fluxbox::instance()->findScreen(menu.screenNumber()); + BScreen::ExtraMenus::iterator it = screen->extraWindowMenus().begin(); + BScreen::ExtraMenus::iterator it_end = screen->extraWindowMenus().end(); for (; it != it_end; ++it) { it->second->disableTitle(); menu.insert(it->first, it->second); } - + } else if (type == "sendto") { - menu.insert(label.empty()?_FBTEXT(Windowmenu, SendTo, "Send To...", "Send to menu item name"):label.c_str(), new SendToMenu(win)); - } else if (type == "layer") { + menu.insert(label.empty() ? _FBTEXT(Windowmenu, SendTo, "Send To...", "Send to menu item name"): + label.c_str(), new SendToMenu(*Fluxbox::instance()->findScreen(menu.screenNumber()))); + }else if (type == "layer") { BScreen *screen = Fluxbox::instance()->findScreen(menu.screenNumber()); if (screen == 0) return false; - FbTk::Menu *submenu = new LayerMenu<FluxboxWindow>(screen->menuTheme(), - screen->imageControl(), - *screen->layerManager(). - getLayer(Fluxbox::instance()->getMenuLayer()), - &win, - false); + + class MenuContext: public LayerObject { + public: + void moveToLayer(int layer_number) { + if (WindowCmd<void>::window() == 0) + return; + WindowCmd<void>::window()->moveToLayer(layer_number); + } + int layerNumber() const { + if (WindowCmd<void>::window() == 0) + return -1; + return WindowCmd<void>::window()->layerItem().getLayerNum(); + } + } static context; + + FbTk::Menu *submenu = new LayerMenu(screen->menuTheme(), + screen->imageControl(), + *screen->layerManager(). + getLayer(Fluxbox::instance()->getMenuLayer()), + &context, + false); submenu->disableTitle(); menu.insert(label.empty()?_FBTEXT(Windowmenu, Layer, "Layer ...", "Layer menu"):label.c_str(), submenu);
M src/MenuCreator.hhsrc/MenuCreator.hh

@@ -39,10 +39,11 @@ bool require_begin);

static FbTk::Menu *createMenuType(const std::string &label, int screen_num); static bool createFromFile(const std::string &filename, FbTk::Menu &inject_into, bool require_begin); - static bool createFromFile(const std::string &filename, FbTk::Menu &inject_into, - FluxboxWindow &win, bool require_begin); + static bool createWindowMenuFromFile(const std::string &filename, FbTk::Menu &inject_into, + bool require_begin); static bool createWindowMenuItem(const std::string &type, const std::string &label, - FbTk::Menu &inject_into, FluxboxWindow &win); + FbTk::Menu &inject_into); + }; #endif // MENUCREATOR_HH
M src/Remember.ccsrc/Remember.cc

@@ -31,6 +31,7 @@ #include "WinClient.hh"

#include "FbMenu.hh" #include "FbCommands.hh" #include "fluxbox.hh" +#include "WindowCmd.hh" #include "FbTk/I18n.hh" #include "FbTk/StringUtil.hh"

@@ -60,53 +61,58 @@ namespace {

class RememberMenuItem : public FbTk::MenuItem { public: - RememberMenuItem(const char *label, Remember &remember, - FluxboxWindow &fbwin, + RememberMenuItem(const char *label, Remember::Attribute attrib) : - FbTk::MenuItem(label), m_remember(remember), - m_win(fbwin), m_attrib(attrib) { + FbTk::MenuItem(label), + m_attrib(attrib) { setToggleItem(true); } bool isSelected() const { - if (m_win.numClients()) // ensure it HAS clients - return m_remember.isRemembered(m_win.winClient(), m_attrib); + if (WindowCmd<void>::window() == 0) + return false; + + if (WindowCmd<void>::window()->numClients()) // ensure it HAS clients + return Remember::instance().isRemembered(WindowCmd<void>::window()->winClient(), m_attrib); else return false; } bool isEnabled() const { + if (WindowCmd<void>::window() == 0) + return false; + if (m_attrib != Remember::REM_JUMPWORKSPACE) return true; - else if (m_win.numClients()) - return (m_remember.isRemembered(m_win.winClient(), Remember::REM_WORKSPACE)); + else if (WindowCmd<void>::window()->numClients()) + return (Remember::instance().isRemembered(WindowCmd<void>::window()->winClient(), Remember::REM_WORKSPACE)); else return false; } void click(int button, int time) { - if (isSelected()) { - m_remember.forgetAttrib(m_win.winClient(), m_attrib); - } else { - m_remember.rememberAttrib(m_win.winClient(), m_attrib); + if (WindowCmd<void>::window() != 0) { + if (isSelected()) { + Remember::instance().forgetAttrib(WindowCmd<void>::window()->winClient(), m_attrib); + } else { + Remember::instance().rememberAttrib(WindowCmd<void>::window()->winClient(), m_attrib); + } } - m_remember.save(); + Remember::instance().save(); FbTk::MenuItem::click(button, time); } private: - // my remember manager - Remember &m_remember; - FluxboxWindow &m_win; Remember::Attribute m_attrib; }; -FbTk::Menu *createRememberMenu(Remember &remember, FluxboxWindow &win, bool enabled) { +FbTk::Menu *createRememberMenu(BScreen &screen) { // each fluxboxwindow has its own windowmenu // so we also create a remember menu just for it... - FbTk::Menu *menu = win.screen().createMenu(""); + FbTk::Menu *menu = screen.createMenu(""); // if enabled, then we want this to be a unavailable menu + /* if (!enabled) { FbTk::MenuItem *item = new FbTk::MenuItem("unavailable"); item->setEnabled(false);

@@ -114,28 +120,28 @@ menu->insert(item);

menu->updateMenu(); return menu; } - + */ _FB_USES_NLS; menu->insert(new RememberMenuItem(_FBTEXT(Remember, Workspace, "Workspace", "Remember Workspace"), - remember, win, Remember::REM_WORKSPACE)); + Remember::REM_WORKSPACE)); menu->insert(new RememberMenuItem(_FBTEXT(Remember, JumpToWorkspace, "Jump to workspace", "Change active workspace to remembered one on open"), - remember, win, Remember::REM_JUMPWORKSPACE)); + Remember::REM_JUMPWORKSPACE)); menu->insert(new RememberMenuItem(_FBTEXT(Remember, Head, "Head", "Remember Head"), - remember, win, Remember::REM_HEAD)); + Remember::REM_HEAD)); menu->insert(new RememberMenuItem(_FBTEXT(Remember, Dimensions, "Dimensions", "Remember Dimensions - with width and height"), - remember, win, Remember::REM_DIMENSIONS)); + Remember::REM_DIMENSIONS)); menu->insert(new RememberMenuItem(_FBTEXT(Remember, Position, "Position", "Remember position - window co-ordinates"), - remember, win, Remember::REM_POSITION)); + Remember::REM_POSITION)); menu->insert(new RememberMenuItem(_FBTEXT(Remember, Sticky, "Sticky", "Remember Sticky"), - remember, win, Remember::REM_STUCKSTATE)); + Remember::REM_STUCKSTATE)); menu->insert(new RememberMenuItem(_FBTEXT(Remember, Decorations, "Decorations", "Remember window decorations"), - remember, win, Remember::REM_DECOSTATE)); + Remember::REM_DECOSTATE)); menu->insert(new RememberMenuItem(_FBTEXT(Remember, Shaded, "Shaded", "Remember shaded"), - remember, win, Remember::REM_SHADEDSTATE)); + Remember::REM_SHADEDSTATE)); menu->insert(new RememberMenuItem(_FBTEXT(Remember, Layer, "Layer", "Remember Layer"), - remember, win, Remember::REM_LAYER)); + Remember::REM_LAYER)); menu->insert(new RememberMenuItem(_FBTEXT(Remember, SaveOnClose, "Save on close", "Save remembered attributes on close"), - remember, win, Remember::REM_SAVEONCLOSE)); + Remember::REM_SAVEONCLOSE)); menu->updateMenu(); return menu;

@@ -217,16 +223,23 @@ head_remember =

save_on_close_remember = false; } -/******************************************************** +/************ * Remember * ************/ +Remember *Remember::s_instance = 0; + Remember::Remember() { + if (s_instance != 0) + throw string("Can not create more than one instance of Remember"); + + s_instance = this; enableUpdate(); load(); } Remember::~Remember() { + // free our resources // the patterns free the "Application"s

@@ -245,6 +258,8 @@ while (ait != all_apps.end()) {

delete (*ait); ++ait; } + + s_instance = 0; } Application* Remember::find(WinClient &winclient) {

@@ -811,9 +826,6 @@ _FB_USES_NLS;

// we don't touch the window if it is a transient // of something else - // All windows get the remember menu. - win.addExtraMenu(_FBTEXT(Remember, MenuItemName, "Remember...", "Remember item in menu"), - createRememberMenu(*this, win, (winclient.transientFor() == 0))); if (winclient.transientFor()) return;

@@ -933,6 +945,13 @@

if (wc_it != m_clients.end()) { m_clients.erase(wc_it); } + +} + +void Remember::initForScreen(BScreen &screen) { + // All windows get the remember menu. + screen.addExtraWindowMenu(_FBTEXT(Remember, MenuItemName, "Remember...", "Remember item in menu"), + createRememberMenu(screen)); }
M src/Screen.ccsrc/Screen.cc

@@ -367,7 +367,7 @@ fluxbox->getSlitlistFilename().c_str()));

#endif // SLIT rm.unlock(); - + XFlush(disp); }

@@ -384,6 +384,7 @@ }

BScreen::~BScreen() { + if (! managed) return;

@@ -394,6 +395,24 @@ // Since workspacemenu holds client list menus (from workspace)

// we need to destroy it before we destroy workspaces m_workspacemenu.reset(0); + ExtraMenus::iterator mit = m_extramenus.begin(); + ExtraMenus::iterator mit_end = m_extramenus.end(); + for (; mit != mit_end; ++mit) { + // we set them to NOT internal so that they will be deleted when the + // menu is cleaned up. We can't delete them here because they are + // still in the menu + // (They need to be internal for most of the time so that if we + // rebuild the menu, then they won't be removed. + if (mit->second->parent() == 0) { + // not attached to our windowmenu + // so we clean it up + delete mit->second; + } else { + // let the parent clean it up + mit->second->setInternalMenu(false); + } + } + if (geom_pixmap != None) imageControl().removeImage(geom_pixmap);

@@ -601,6 +620,25 @@

return menu; } +void BScreen::addExtraWindowMenu(const char *label, FbTk::Menu *menu) { + menu->setInternalMenu(); + menu->disableTitle(); + m_extramenus.push_back(std::make_pair(label, menu)); + // recreate window menu + m_windowmenu.reset(MenuCreator::createMenuType("windowmenu", screenNumber())); +} + +void BScreen::removeExtraWindowMenu(FbTk::Menu *menu) { + ExtraMenus::iterator it = find_if(m_extramenus.begin(), + m_extramenus.end(), + FbTk::Compose(bind2nd(equal_to<FbTk::Menu *>(), menu), + FbTk::Select2nd<ExtraMenus::value_type>())); + if (it != m_extramenus.end()) + m_extramenus.erase(it); + // recreate window menu + m_windowmenu.reset(MenuCreator::createMenuType("windowmenu", screenNumber())); +} + void BScreen::hideMenus() { // hide extra menus Fluxbox::instance()->hideExtraMenus(*this);

@@ -684,6 +722,8 @@

//reconfigure menus m_workspacemenu->reconfigure(); m_configmenu->reconfigure(); + // recreate window menu + m_windowmenu.reset(MenuCreator::createMenuType("windowmenu", screenNumber())); // We need to check to see if the timestamps // changed before we actually can restore the menus

@@ -963,8 +1003,10 @@ if (win->isIconic())

win->deiconify(); // if the window isn't on current workspace, hide it - if (id != currentWorkspace()->workspaceID()) + if (id != currentWorkspace()->workspaceID()) win->withdraw(true); + + windowMenu().hide(); reassociateWindow(win, id, true);

@@ -1649,8 +1691,10 @@ foundwin->setInputFocus();

} void BScreen::initMenus() { m_workspacemenu.reset(MenuCreator::createMenuType("workspacemenu", screenNumber())); + m_windowmenu.reset(MenuCreator::createMenuType("windowmenu", screenNumber())); initMenu(); } + void BScreen::initMenu() {
M src/Screen.hhsrc/Screen.hh

@@ -97,6 +97,7 @@ typedef std::vector<FluxboxWindow *> Icons;

typedef std::list<WinClient *> FocusedWindows; typedef std::vector<Workspace *> Workspaces; typedef std::vector<std::string> WorkspaceNames; + typedef std::list<std::pair<const char *, FbTk::Menu *> > ExtraMenus; BScreen(FbTk::ResourceManager &rm, const std::string &screenname, const std::string &altscreenname,

@@ -123,10 +124,16 @@ inline bool antialias() const { return *resource.antialias; }

inline bool decorateTransient() const { return *resource.decorate_transient; } inline const std::string &windowMenuFilename() const { return *resource.windowmenufile; } inline FbTk::ImageControl &imageControl() { return *m_image_control.get(); } + // menus const FbTk::Menu &getRootmenu() const { return *m_rootmenu.get(); } FbTk::Menu &getRootmenu() { return *m_rootmenu.get(); } const FbTk::Menu &configMenu() const { return *m_configmenu.get(); } FbTk::Menu &configMenu() { return *m_configmenu.get(); } + const FbTk::Menu &windowMenu() const { return *m_windowmenu.get(); } + FbTk::Menu &windowMenu() { return *m_windowmenu.get(); } + + ExtraMenus &extraWindowMenus() { return m_extramenus; } + const ExtraMenus &extraWindowMenus() const { return m_extramenus; } inline const std::string &getRootCommand() const { return *resource.rootcommand; } inline ResizeModel getResizeModel() const { return *resource.resize_model; }

@@ -199,6 +206,11 @@ void update(FbTk::Subject *subj);

FbTk::Menu *createMenu(const std::string &label); void hideMenus(); + // for extras to add menus. + // These menus will be marked internal, + // and deleted when the window dies (as opposed to Screen + void addExtraWindowMenu(const char *label, FbTk::Menu *menu); + void removeExtraWindowMenu(FbTk::Menu *menu); /// hide all windowmenus except the given one (if given) void hideWindowMenus(const FluxboxWindow* except= 0);

@@ -393,7 +405,9 @@

std::auto_ptr<FbTk::ImageControl> m_image_control; - std::auto_ptr<FbTk::Menu> m_configmenu, m_rootmenu, m_workspacemenu; + std::auto_ptr<FbTk::Menu> m_configmenu, m_rootmenu, m_workspacemenu, m_windowmenu; + + ExtraMenus m_extramenus; typedef std::list<FbTk::Menu *> Rootmenus; typedef std::list<Netizen *> Netizens;
M src/SendToMenu.ccsrc/SendToMenu.cc

@@ -28,39 +28,36 @@ #include "Window.hh"

#include "Screen.hh" #include "fluxbox.hh" #include "Workspace.hh" +#include "WindowCmd.hh" #include "FbTk/MultiButtonMenuItem.hh" #include "FbTk/Command.hh" class SendToCmd: public FbTk::Command { public: - SendToCmd(FluxboxWindow &win, int workspace, bool follow): - m_win(win), + SendToCmd(int workspace, bool follow): m_workspace(workspace), m_follow(follow) { } void execute() { - m_win.screen().sendToWorkspace(m_workspace, &m_win, m_follow); + if (WindowCmd<void>::window() != 0) + WindowCmd<void>::window()->screen().sendToWorkspace(m_workspace, WindowCmd<void>::window(), m_follow); } private: - FluxboxWindow &m_win; const int m_workspace; const bool m_follow; }; -SendToMenu::SendToMenu(FluxboxWindow &win): - FbMenu(win.screen().menuTheme(), - win.screen().imageControl(), - *win.screen().layerManager().getLayer(Fluxbox::instance()->getMenuLayer())), - m_win(win) { +SendToMenu::SendToMenu(BScreen &screen): + FbMenu(screen.menuTheme(), + screen.imageControl(), + *screen.layerManager().getLayer(Fluxbox::instance()->getMenuLayer())) { // listen to: // workspace count signal // workspace names signal // current workspace signal - // and window's workspace sig - win.screen().workspaceCountSig().attach(this); - win.screen().workspaceNamesSig().attach(this); - win.screen().currentWorkspaceSig().attach(this); - win.workspaceSig().attach(this); + screen.workspaceCountSig().attach(this); + screen.workspaceNamesSig().attach(this); + screen.currentWorkspaceSig().attach(this); disableTitle(); // build menu

@@ -69,19 +66,7 @@ }

void SendToMenu::update(FbTk::Subject *subj) { if (subj != 0) { - // if workspace changed we enable all workspaces except the current one - if (subj == &(m_win.screen().currentWorkspaceSig()) || - subj == &(m_win.workspaceSig())) { - // enabled all workspaces - const BScreen::Workspaces &wlist = m_win.screen().getWorkspacesList(); - for (size_t i = 0; i < wlist.size(); ++i) - setItemEnabled(i, true); - // disable send to on the workspace which the window exist - setItemEnabled(m_win.workspaceNumber(), false); - updateMenu(); - // we're done - return; - } else if (subj == &(theme().reconfigSig())) { + if (subj == &(theme().reconfigSig())) { // we got reconfig Theme signal, let base menu handle it FbTk::Menu::update(subj); return;

@@ -91,11 +76,11 @@ }

// rebuild menu removeAll(); - - const BScreen::Workspaces &wlist = m_win.screen().getWorkspacesList(); + BScreen *screen = Fluxbox::instance()->findScreen(screenNumber()); + const BScreen::Workspaces &wlist = screen->getWorkspacesList(); for (size_t i = 0; i < wlist.size(); ++i) { - FbTk::RefCount<FbTk::Command> sendto_cmd(new SendToCmd(m_win, i, false)); - FbTk::RefCount<FbTk::Command> sendto_follow_cmd(new SendToCmd(m_win, i, true)); + FbTk::RefCount<FbTk::Command> sendto_cmd(new SendToCmd(i, false)); + FbTk::RefCount<FbTk::Command> sendto_follow_cmd(new SendToCmd(i, true)); FbTk::MultiButtonMenuItem* item = new FbTk::MultiButtonMenuItem(3, wlist[i]->name().c_str()); item->setCommand(1, sendto_cmd);

@@ -104,7 +89,16 @@ item->setCommand(3, sendto_cmd);

insert(item); } - setItemEnabled(m_win.workspaceNumber(), false); + updateMenu(); +} - updateMenu(); +void SendToMenu::show() { + if (WindowCmd<void>::window() != 0) { + for (unsigned int i=0; i < numberOfItems(); ++i) + setItemEnabled(i, true); + setItemEnabled(WindowCmd<void>::window()->workspaceNumber(), false); + updateMenu(); + } + FbTk::Menu::show(); } +
M src/SendToMenu.hhsrc/SendToMenu.hh

@@ -29,16 +29,15 @@ #include "FbMenu.hh"

#include "FbTk/Observer.hh" -class FluxboxWindow; +class BScreen; class SendToMenu:public FbMenu { public: - explicit SendToMenu(FluxboxWindow &win); + explicit SendToMenu(BScreen &win); virtual ~SendToMenu() { } + void show(); protected: void update(FbTk::Subject *subj); -private: - FluxboxWindow &m_win; }; #endif // SENDTOMENU_HH
M src/Slit.ccsrc/Slit.cc

@@ -313,16 +313,18 @@ frame.window.setAlpha(*m_rc_alpha);

} m_layeritem.reset(new FbTk::XLayerItem(frame.window, layer)); - m_layermenu.reset(new LayerMenu<Slit>(scr.menuTheme(), - scr.imageControl(), - *scr.layerManager(). - getLayer(Fluxbox::instance()->getMenuLayer()), - this, - true)); + + m_layermenu.reset(new LayerMenu(scr.menuTheme(), + scr.imageControl(), + *scr.layerManager(). + getLayer(Fluxbox::instance()->getMenuLayer()), + this, + true)); + m_layermenu->setLabel(_FBTEXT(Slit, Layer, "Slit Layer", "Title of Slit Layer Menu")); + moveToLayer((*m_rc_layernum).getNum()); - if (m_layermenu.get()) - m_layermenu->setLabel(_FBTEXT(Slit, Layer, "Slit Layer", "Title of Slit Layer Menu")); + // Get client list for sorting purposes loadClientList(filename);
M src/Slit.hhsrc/Slit.hh

@@ -27,11 +27,15 @@

#ifndef SLIT_HH #define SLIT_HH -#include "Menu.hh" -#include "FbWindow.hh" -#include "Timer.hh" -#include "XLayerItem.hh" + #include "LayerMenu.hh" +#include "fluxbox.hh" + +#include "FbTk/Menu.hh" +#include "FbTk/FbWindow.hh" +#include "FbTk/Timer.hh" +#include "FbTk/Resource.hh" +#include "FbTk/XLayerItem.hh" #include <X11/Xlib.h> #include <X11/Xutil.h>

@@ -47,7 +51,7 @@ class FbMenu;

class Strut; /// Handles dock apps -class Slit: public FbTk::EventHandler, public FbTk::Observer { +class Slit: public FbTk::EventHandler, public FbTk::Observer, public LayerObject { public: typedef std::list<SlitClient *> SlitClients; /**

@@ -105,7 +109,8 @@ const BScreen &screen() const { return m_screen; }

SlitTheme &theme() { return *m_slit_theme.get(); } const SlitTheme &theme() const { return *m_slit_theme.get(); } - FbTk::XLayerItem &layerItem() { return *m_layeritem; } + int layerNumber() const { return m_layeritem->getLayerNum(); } + inline bool isHidden() const { return m_hidden; } inline bool doAutoHide() const { return *m_rc_auto_hide; } inline Direction direction() const { return *m_rc_direction; }

@@ -141,7 +146,7 @@ FbTk::Timer m_timer;

SlitClients m_client_list; FbMenu m_slitmenu, m_placement_menu, m_clientlist_menu; - std::auto_ptr<LayerMenu<Slit> > m_layermenu; + std::auto_ptr<LayerMenu> m_layermenu; std::string m_filename; struct frame {
M src/ToggleMenu.hhsrc/ToggleMenu.hh

@@ -51,7 +51,7 @@ if (ev.window == frameWindow()) {

// force full foreground update frameWindow().updateBackground(false); } - + clearWindow(); } };
M src/Toolbar.ccsrc/Toolbar.cc

@@ -826,7 +826,7 @@

menu().insert(new BoolMenuItem(_FBTEXT(Common, MaximizeOver,"Maximize Over", "Maximize over this thing when maximizing"), *m_rc_maximize_over, reconfig_toolbar_and_save_resource)); - menu().insert(_FBTEXT(Menu, Layer, "Layer...", "Title of Layer menu"), &layermenu()); + menu().insert(_FBTEXT(Menu, Layer, "Layer...", "Title of Layer menu"), &layerMenu());
M src/Toolbar.hhsrc/Toolbar.hh

@@ -31,6 +31,7 @@ #include "ToolbarTheme.hh"

#include "LayerMenu.hh" #include "ToolFactory.hh" #include "ToolTheme.hh" +#include "fluxbox.hh" #include "FbTk/Timer.hh" #include "FbTk/Resource.hh"

@@ -54,7 +55,7 @@ }

/// The toolbar. /// Handles iconbar, workspace name view and clock view -class Toolbar: public FbTk::EventHandler, public FbTk::Observer { +class Toolbar: public FbTk::EventHandler, public FbTk::Observer, public LayerObject { public: /// Toolbar placement on the screen

@@ -101,15 +102,15 @@ void setPlacement(Placement where);

void update(FbTk::Subject *subj); - FbTk::XLayerItem &layerItem() { return m_layeritem; } + int layerNumber() const { return const_cast<FbTk::XLayerItem &>(m_layeritem).getLayerNum(); } inline const FbTk::Menu &menu() const { return m_toolbarmenu; } inline FbTk::Menu &menu() { return m_toolbarmenu; } inline FbTk::Menu &placementMenu() { return m_placementmenu; } inline const FbTk::Menu &placementMenu() const { return m_placementmenu; } - inline FbTk::Menu &layermenu() { return m_layermenu; } - inline const FbTk::Menu &layermenu() const { return m_layermenu; } + inline FbTk::Menu &layerMenu() { return m_layermenu; } + inline const FbTk::Menu &layerMenu() const { return m_layermenu; } /// are we hidden? inline bool isHidden() const { return m_hidden; }

@@ -163,8 +164,8 @@

FbTk::Timer m_hide_timer; ///< timer to for auto hide toolbar FbTk::XLayerItem m_layeritem; ///< layer item, must be declared before layermenu - LayerMenu<Toolbar> m_layermenu; - FbMenu m_placementmenu, m_toolbarmenu; + LayerMenu m_layermenu; + FbMenu m_placementmenu, m_toolbarmenu; // themes
M src/Window.ccsrc/Window.cc

@@ -36,6 +36,7 @@ #include "Workspace.hh"

#include "FbWinFrame.hh" #include "WinButton.hh" #include "WinButtonTheme.hh" +#include "WindowCmd.hh" #include "Remember.hh" #include "MenuCreator.hh"

@@ -294,7 +295,6 @@ maximized(MAX_NONE),

m_attaching_tab(0), m_screen(client.screen()), display(FbTk::App::instance()->display()), - m_windowmenu(MenuCreator::createMenu("", client.screenNumber())), m_button_grab_x(0), m_button_grab_y(0), m_last_move_x(0), m_last_move_y(0), m_last_resize_h(1), m_last_resize_w(1),

@@ -323,6 +323,9 @@ }

FluxboxWindow::~FluxboxWindow() { + if (WindowCmd<void>::window() == this) + WindowCmd<void>::setWindow(0); + #ifdef DEBUG cerr<<__FILE__<<"("<<__LINE__<<"): starting ~FluxboxWindow("<<this<<", "<<title()<<")"<<endl; cerr<<__FILE__<<"("<<__LINE__<<"): num clients = "<<numClients()<<endl;

@@ -364,24 +367,6 @@ }

} // deal with extra menus - ExtraMenus::iterator mit = m_extramenus.begin(); - ExtraMenus::iterator mit_end = m_extramenus.end(); - for (; mit != mit_end; ++mit) { - // we set them to NOT internal so that they will be deleted when the - // menu is cleaned up. We can't delete them here because they are - // still in the menu - // (They need to be internal for most of the time so that if we - // rebuild the menu, then they won't be removed. - if (mit->second->parent() == 0) { - // not attached to our windowmenu - // so we clean it up - delete mit->second; - } else { - // let the parent clean it up - mit->second->setInternalMenu(false); - } - } - #ifdef DEBUG cerr<<__FILE__<<"("<<__LINE__<<"): ~FluxboxWindow("<<this<<")"<<endl; #endif // DEBUG

@@ -2263,7 +2248,7 @@ menu_x = screen().maxLeft(head);

else if (menu_x + static_cast<signed>(menu().width()) >= static_cast<signed>(screen().maxRight(head))) menu_x = screen().maxRight(head) - menu().width() - 1; - + WindowCmd<void>::setWindow(this); menu().move(menu_x, menu_y); menu().show(); menu().raise();

@@ -2275,6 +2260,8 @@ Moves the menu to last button press position and shows it,

if it's already visible it'll be hidden */ void FluxboxWindow::popupMenu() { + WindowCmd<void>::setWindow(this); + if (menu().isVisible()) { menu().hide(); return;

@@ -3553,6 +3540,14 @@ const FbTk::FbWindow &FluxboxWindow::fbWindow() const {

return frame().window(); } +FbTk::Menu &FluxboxWindow::menu() { + return screen().windowMenu(); +} + +const FbTk::Menu &FluxboxWindow::menu() const { + return screen().windowMenu(); +} + unsigned int FluxboxWindow::titlebarHeight() const { return frame().titlebarHeight(); }

@@ -3736,24 +3731,6 @@ }

} // end for } -void FluxboxWindow::addExtraMenu(const char *label, FbTk::Menu *menu) { - menu->setInternalMenu(); - menu->disableTitle(); - m_extramenus.push_back(std::make_pair(label, menu)); - - setupMenu(); -} - -void FluxboxWindow::removeExtraMenu(FbTk::Menu *menu) { - ExtraMenus::iterator it = find_if(m_extramenus.begin(), - m_extramenus.end(), - Compose(bind2nd(equal_to<Menu *>(), menu), - Select2nd<ExtraMenus::value_type>())); - if (it != m_extramenus.end()) - m_extramenus.erase(it); - - setupMenu(); -} void FluxboxWindow::close() { if (m_client)

@@ -3870,33 +3847,6 @@ frame().setDoubleClickTime(Fluxbox::instance()->getDoubleClickInterval());

// end setup frame - setupMenu(); -} - -void FluxboxWindow::setupMenu() { - // setup menu - - menu().removeAll(); // clear old items - menu().disableTitle(); // not titlebar - - if (screen().windowMenuFilename().empty() || - ! MenuCreator::createFromFile(screen().windowMenuFilename(), menu(), *this, true)) - - { - MenuCreator::createWindowMenuItem("shade", "", menu(), *this); - MenuCreator::createWindowMenuItem("stick", "", menu(), *this); - MenuCreator::createWindowMenuItem("maximize", "", menu(), *this); - MenuCreator::createWindowMenuItem("iconify", "", menu(), *this); - MenuCreator::createWindowMenuItem("raise", "", menu(), *this); - MenuCreator::createWindowMenuItem("lower", "", menu(), *this); - MenuCreator::createWindowMenuItem("sendto", "", menu(), *this); - MenuCreator::createWindowMenuItem("layer", "", menu(), *this); - MenuCreator::createWindowMenuItem("extramenus", "", menu(), *this); - MenuCreator::createWindowMenuItem("separator", "", menu(), *this); - MenuCreator::createWindowMenuItem("close", "", menu(), *this); - } - - menu().reconfigure(); // update graphics }
M src/Window.hhsrc/Window.hh

@@ -31,7 +31,6 @@ #include "FbTk/Timer.hh"

#include "FbTk/Subject.hh" #include "FbTk/EventHandler.hh" #include "FbTk/XLayerItem.hh" - #include "FbWinFrame.hh" #include <X11/Xlib.h>

@@ -153,8 +152,6 @@ unsigned long premax_w, premax_h;

} BlackboxAttributes; typedef std::list<WinClient *> ClientList; - // this should perhaps be a refcount?? - typedef std::list<std::pair<const char *, FbTk::Menu *> > ExtraMenus; /// create a window from a client FluxboxWindow(WinClient &client,

@@ -322,18 +319,8 @@

FbTk::FbWindow &fbWindow(); const FbTk::FbWindow &fbWindow() const; - FbTk::Menu &menu() { return *m_windowmenu.get(); } - const FbTk::Menu &menu() const { return *m_windowmenu.get(); } - - - // for extras to add menus. - // These menus will be marked internal, - // and deleted when the window dies (as opposed to Screen - void addExtraMenu(const char *label, FbTk::Menu *menu); - void removeExtraMenu(FbTk::Menu *menu); - - ExtraMenus &extraMenus() { return m_extramenus; } - const ExtraMenus &extraMenus() const { return m_extramenus; } + FbTk::Menu &menu(); + const FbTk::Menu &menu() const; const FbTk::FbWindow &parent() const { return m_parent; } FbTk::FbWindow &parent() { return m_parent; }

@@ -398,7 +385,6 @@ private:

static const int PropBlackboxAttributesElements = 8; void setupWindow(); - void setupMenu(); void init(); /// applies a shape mask to the window if it has one

@@ -474,8 +460,6 @@ FbTk::Timer m_timer;

Display *display; /// display connection BlackboxAttributes m_blackbox_attrib; - std::auto_ptr<FbTk::Menu> m_windowmenu; - timeval m_last_focus_time; int m_button_grab_x, m_button_grab_y; // handles last button press event for move

@@ -524,7 +508,6 @@ FbTk::FbWindow &m_parent; ///< window on which we draw move/resize rectangle (the "root window")

ResizeCorner m_resize_corner; - ExtraMenus m_extramenus; static int s_num_grabs; ///< number of XGrabPointer's };
M src/Workspace.ccsrc/Workspace.cc

@@ -31,6 +31,7 @@ #include "Screen.hh"

#include "Window.hh" #include "WinClient.hh" #include "FbWinFrame.hh" +#include "WindowCmd.hh" #include "FbTk/I18n.hh" #include "FbTk/MenuItem.hh"

@@ -83,10 +84,18 @@

class ClientMenuItem:public FbTk::MenuItem { public: ClientMenuItem(WinClient &client): - FbTk::MenuItem(client.title().c_str(), client.fbwindow() ? &client.fbwindow()->menu() : 0), + FbTk::MenuItem(client.title().c_str(), &client.screen().windowMenu()), m_client(client) { } + FbTk::Menu *submenu() { return &m_client.screen().windowMenu(); } + const FbTk::Menu *submenu() const { return &m_client.screen().windowMenu(); } + + void showSubmenu() { + WindowCmd<void>::setWindow(m_client.fbwindow()); + FbTk::MenuItem::showSubmenu(); + } + void click(int button, int time) { if (m_client.fbwindow() == 0) return;