fluxbox/src/ConfigMenu.cc
2015-02-07 11:46:00 +01:00

347 lines
14 KiB
C++

// ConfigMenu.cc for Fluxbox Window Manager
// Copyright (c) 2015 - Mathias Gumz <akira@fluxbox.org>
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#include "ConfigMenu.hh"
#include "MenuCreator.hh"
#include "Screen.hh"
#include "fluxbox.hh"
#include "FocusModelMenuItem.hh"
#include "ScreenPlacement.hh"
#include "FbMenu.hh"
#include "ToggleMenu.hh"
#include "FbTk/Menu.hh"
#include "FbTk/BoolMenuItem.hh"
#include "FbTk/IntMenuItem.hh"
#include "FbTk/MenuSeparator.hh"
#include "FbTk/RadioMenuItem.hh"
#include "FbTk/MacroCommand.hh"
#include "FbTk/CommandParser.hh"
#include "FbTk/SimpleCommand.hh"
#include "FbTk/Transparent.hh"
#include "FbTk/Resource.hh"
#include "FbTk/I18n.hh"
namespace {
class TabPlacementMenuItem: public FbTk::RadioMenuItem {
public:
TabPlacementMenuItem(const FbTk::FbString & label, BScreen &screen,
FbWinFrame::TabPlacement place,
FbTk::RefCount<FbTk::Command<void> > &cmd):
FbTk::RadioMenuItem(label, cmd),
m_screen(screen),
m_place(place) {
setCloseOnClick(false);
}
bool isSelected() const { return m_screen.getTabPlacement() == m_place; }
void click(int button, int time, unsigned int mods) {
m_screen.saveTabPlacement(m_place);
FbTk::RadioMenuItem::click(button, time, mods);
}
private:
BScreen &m_screen;
FbWinFrame::TabPlacement m_place;
};
typedef FbTk::RefCount<FbTk::Command<void> > _Cmd;
// NOTE: might also be placed into MenuCreator; for now it ends up here
// because it's just used here
FbMenu *createToggleMenu(const std::string &label, BScreen& screen) {
FbTk::Layer* layer = screen.layerManager().getLayer(ResourceLayer::MENU);
FbMenu *menu = new ToggleMenu(screen.menuTheme(), screen.imageControl(), *layer);
if (!label.empty())
menu->setLabel(label);
return menu;
}
void setupAlphaMenu(FbTk::Menu& parent, ConfigMenu::SetupHelper& sh, _Cmd& save_reconf) {
#ifdef HAVE_XRENDER
_FB_USES_NLS;
enum {
L_ALPHA = 0,
L_PSEUDO_TRANS,
L_FOCUS_ALPHA,
L_UNFOCUS_ALPHA,
L_MENU_ALPHA,
};
static const FbTk::FbString _labels[] = {
_FB_XTEXT(Configmenu, Transparency, "Transparency", "Menu containing various transparency options"),
_FB_XTEXT(Configmenu, ForcePseudoTrans, "Force Pseudo-Transparency", "When composite is available, still use old pseudo-transparency"),
_FB_XTEXT(Configmenu, FocusedAlpha, "Focused Window Alpha", "Transparency level of the focused window"),
_FB_XTEXT(Configmenu, UnfocusedAlpha, "Unfocused Window Alpha", "Transparency level of unfocused windows"),
_FB_XTEXT(Configmenu, MenuAlpha, "Menu Alpha", "Transparency level of menu")
};
FbTk::FbString label = _labels[L_ALPHA];
FbTk::Menu* menu = MenuCreator::createMenu(label, sh.screen);
if (FbTk::Transparent::haveComposite(true)) {
static FbTk::SimpleAccessor<bool> s_pseudo = Fluxbox::instance()->getPseudoTrans();
menu->insertItem(new FbTk::BoolMenuItem(_labels[L_PSEUDO_TRANS], s_pseudo, save_reconf));
}
// in order to save system resources, don't save or reconfigure alpha
// settings until after the user is done changing them
_Cmd delayed_save_and_reconf(new FbTk::DelayedCmd(save_reconf));
FbTk::MenuItem *focused_alpha_item =
new FbTk::IntMenuItem(_labels[L_FOCUS_ALPHA], sh.resource.focused_alpha, 0, 255, *menu);
focused_alpha_item->setCommand(delayed_save_and_reconf);
menu->insertItem(focused_alpha_item);
FbTk::MenuItem *unfocused_alpha_item =
new FbTk::IntMenuItem(_labels[L_UNFOCUS_ALPHA], sh.resource.unfocused_alpha, 0, 255, *menu);
unfocused_alpha_item->setCommand(delayed_save_and_reconf);
menu->insertItem(unfocused_alpha_item);
FbTk::MenuItem *menu_alpha_item =
new FbTk::IntMenuItem(_labels[L_MENU_ALPHA], sh.resource.menu_alpha, 0, 255, *menu);
menu_alpha_item->setCommand(delayed_save_and_reconf);
menu->insertItem(menu_alpha_item);
menu->updateMenu();
parent.insertSubmenu(label, menu);
#endif
}
#define _BOOLITEM(m,a, b, c, d, e, f) (m).insertItem(new FbTk::BoolMenuItem(_FB_XTEXT(a, b, c, d), e, f))
void setupFocusMenu(FbTk::Menu& menu, ConfigMenu::SetupHelper& sh, _Cmd& save_rc, _Cmd& save_reconf) {
_FB_USES_NLS;
// we don't set this to internal menu so will
// be deleted toghether with the parent
FbTk::FbString label = _FB_XTEXT(Configmenu, FocusModel, "Focus Model", "Method used to give focus to windows");
FbMenu* fm = MenuCreator::createMenu(label, sh.screen);
#define _FOCUSITEM(a, b, c, d, e) \
fm->insertItem(new FocusModelMenuItem(_FB_XTEXT(a, b, c, d), sh.screen.focusControl(), \
e, save_reconf))
_FOCUSITEM(Configmenu, ClickFocus,
"Click To Focus", "Click to focus",
FocusControl::CLICKFOCUS);
_FOCUSITEM(Configmenu, MouseFocus,
"Mouse Focus (Keyboard Friendly)",
"Mouse Focus (Keyboard Friendly)",
FocusControl::MOUSEFOCUS);
_FOCUSITEM(Configmenu, StrictMouseFocus,
"Mouse Focus (Strict)",
"Mouse Focus (Strict)",
FocusControl::STRICTMOUSEFOCUS);
#undef _FOCUSITEM
fm->insertItem(new FbTk::MenuSeparator());
fm->insertItem(new TabFocusModelMenuItem(_FB_XTEXT(Configmenu,
ClickTabFocus, "ClickTabFocus", "Click tab to focus windows"),
sh.screen.focusControl(), FocusControl::CLICKTABFOCUS, save_reconf));
fm->insertItem(new TabFocusModelMenuItem(_FB_XTEXT(Configmenu,
MouseTabFocus, "MouseTabFocus", "Hover over tab to focus windows"),
sh.screen.focusControl(), FocusControl::MOUSETABFOCUS, save_reconf));
fm->insertItem(new FbTk::MenuSeparator());
try {
fm->insertItem(new FbTk::BoolMenuItem(_FB_XTEXT(Configmenu, FocusNew,
"Focus New Windows", "Focus newly created windows"),
sh.rm.getResource<bool>(sh.screen.name() + ".focusNewWindows"),
save_rc));
} catch (FbTk::ResourceException & e) {
std::cerr<<e.what()<<std::endl;
}
#ifdef XINERAMA
try {
fm->insertItem(new FbTk::BoolMenuItem(_FB_XTEXT(Configmenu, FocusSameHead,
"Keep Head", "Only revert focus on same head"),
sh.rm.getResource<bool>(sh.screen.name() + ".focusSameHead"),
save_rc));
} catch (FbTk::ResourceException e) {
std::cerr << e.what() << std::endl;
}
#endif // XINERAMA
_BOOLITEM(*fm, Configmenu, AutoRaise,
"Auto Raise", "Auto Raise windows on sloppy",
sh.resource.auto_raise, save_rc);
_BOOLITEM(*fm, Configmenu, ClickRaises,
"Click Raises", "Click Raises",
sh.resource.click_raises, save_rc);
fm->updateMenu();
menu.insertSubmenu(label, fm);
}
void setupMaximizeMenu(FbTk::Menu& menu, ConfigMenu::SetupHelper& sh, _Cmd& save_rc) {
_FB_USES_NLS;
FbTk::FbString label = _FB_XTEXT(Configmenu, MaxMenu,
"Maximize Options", "heading for maximization options");
FbTk::Menu* mm = MenuCreator::createMenu(label, sh.screen);
_BOOLITEM(*mm, Configmenu, FullMax,
"Full Maximization", "Maximise over slit, toolbar, etc",
sh.resource.full_max, save_rc);
_BOOLITEM(*mm, Configmenu, MaxIgnoreInc,
"Ignore Resize Increment",
"Maximizing Ignores Resize Increment (e.g. xterm)",
sh.resource.max_ignore_inc, save_rc);
_BOOLITEM(*mm, Configmenu, MaxDisableMove,
"Disable Moving", "Don't Allow Moving While Maximized",
sh.resource.max_disable_move, save_rc);
_BOOLITEM(*mm, Configmenu, MaxDisableResize,
"Disable Resizing", "Don't Allow Resizing While Maximized",
sh.resource.max_disable_resize, save_rc);
mm->updateMenu();
menu.insertSubmenu(label, mm);
}
void setupTabMenu(FbTk::Menu& parent, ConfigMenu::SetupHelper& sh, _Cmd& save_reconf, _Cmd& save_reconftabs) {
_FB_USES_NLS;
FbTk::FbString label = _FB_XTEXT(Configmenu, TabMenu, "Tab Options", "heading for tab-related options");
// TODO: main-category is 'Menu'?? should be 'ConfigMenu'???
FbTk::FbString p_label = _FB_XTEXT(Menu, Placement, "Placement", "Title of Placement menu");
FbTk::Menu* menu = MenuCreator::createMenu(label, sh.screen);
FbTk::Menu* p_menu = createToggleMenu(p_label, sh.screen);
menu->insertSubmenu(p_label, p_menu);
menu->insertItem(new FbTk::BoolMenuItem(_FB_XTEXT(Configmenu, TabsInTitlebar,
"Tabs in Titlebar", "Tabs in Titlebar"),
sh.resource.default_internal_tabs, save_reconftabs));
menu->insertItem(new FbTk::BoolMenuItem(_FB_XTEXT(Common, MaximizeOver,
"Maximize Over", "Maximize over this thing when maximizing"),
sh.resource.max_over_tabs, save_reconf));
menu->insertItem(new FbTk::BoolMenuItem(_FB_XTEXT(Toolbar, ShowIcons,
"Show Pictures", "chooses if little icons are shown next to title in the iconbar"),
sh.resource.tabs_use_pixmap, save_reconf));
FbTk::MenuItem *tab_width_item =
new FbTk::IntMenuItem(_FB_XTEXT(Configmenu, ExternalTabWidth,
"External Tab Width",
"Width of external-style tabs"),
sh.resource.tab_width, 10, 3000, /* silly number */
*menu);
tab_width_item->setCommand(save_reconftabs);
menu->insertItem(tab_width_item);
// menu is 3 wide, 5 down
struct PlacementP {
const FbTk::FbString label;
FbWinFrame::TabPlacement placement;
};
static const PlacementP place_menu[] = {
{ _FB_XTEXT(Align, TopLeft, "Top Left", "Top Left"), FbWinFrame::TOPLEFT},
{ _FB_XTEXT(Align, LeftTop, "Left Top", "Left Top"), FbWinFrame::LEFTTOP},
{ _FB_XTEXT(Align, LeftCenter, "Left Center", "Left Center"), FbWinFrame::LEFT},
{ _FB_XTEXT(Align, LeftBottom, "Left Bottom", "Left Bottom"), FbWinFrame::LEFTBOTTOM},
{ _FB_XTEXT(Align, BottomLeft, "Bottom Left", "Bottom Left"), FbWinFrame::BOTTOMLEFT},
{ _FB_XTEXT(Align, TopCenter, "Top Center", "Top Center"), FbWinFrame::TOP},
{ "", FbWinFrame::TOPLEFT},
{ "", FbWinFrame::TOPLEFT},
{ "", FbWinFrame::TOPLEFT},
{ _FB_XTEXT(Align, BottomCenter, "Bottom Center", "Bottom Center"), FbWinFrame::BOTTOM},
{ _FB_XTEXT(Align, TopRight, "Top Right", "Top Right"), FbWinFrame::TOPRIGHT},
{ _FB_XTEXT(Align, RightTop, "Right Top", "Right Top"), FbWinFrame::RIGHTTOP},
{ _FB_XTEXT(Align, RightCenter, "Right Center", "Right Center"), FbWinFrame::RIGHT},
{ _FB_XTEXT(Align, RightBottom, "Right Bottom", "Right Bottom"), FbWinFrame::RIGHTBOTTOM},
{ _FB_XTEXT(Align, BottomRight, "Bottom Right", "Bottom Right"), FbWinFrame::BOTTOMRIGHT}
};
p_menu->setMinimumColumns(3);
// create items in sub menu
for (size_t i=0; i< sizeof(place_menu)/sizeof(PlacementP); ++i) {
const PlacementP& p = place_menu[i];
if (p.label == "") {
p_menu->insert(p.label);
p_menu->setItemEnabled(i, false);
} else
p_menu->insertItem(new TabPlacementMenuItem(p.label,
sh.screen, p.placement, save_reconftabs));
}
p_menu->updateMenu();
menu->updateMenu();
parent.insertSubmenu(label, menu);
}
}
void ConfigMenu::setup(FbTk::Menu& menu, ConfigMenu::SetupHelper& sh) {
_FB_USES_NLS;
FbTk::MacroCommand *s_a_reconf_macro = new FbTk::MacroCommand();
FbTk::MacroCommand *s_a_reconftabs_macro = new FbTk::MacroCommand();
_Cmd saverc_cmd(new FbTk::SimpleCommand<Fluxbox>( *Fluxbox::instance(), &Fluxbox::save_rc));
_Cmd reconf_cmd(FbTk::CommandParser<void>::instance().parse("reconfigure"));
_Cmd reconftabs_cmd(new FbTk::SimpleCommand<BScreen>(sh.screen, &BScreen::reconfigureTabs));
s_a_reconf_macro->add(saverc_cmd);
s_a_reconf_macro->add(reconf_cmd);
s_a_reconftabs_macro->add(saverc_cmd);
s_a_reconftabs_macro->add(reconftabs_cmd);
_Cmd save_and_reconfigure(s_a_reconf_macro);
_Cmd save_and_reconftabs(s_a_reconftabs_macro);
setupFocusMenu(menu, sh, saverc_cmd, save_and_reconfigure);
setupMaximizeMenu(menu, sh, saverc_cmd);
setupTabMenu(menu, sh, save_and_reconfigure, save_and_reconftabs);
#ifdef HAVE_XRENDER
if (FbTk::Transparent::haveRender() ||
FbTk::Transparent::haveComposite()) {
setupAlphaMenu(menu, sh, save_and_reconfigure);
}
#endif // HAVE_XRENDER
_BOOLITEM(menu, Configmenu, OpaqueMove,
"Opaque Window Moving",
"Window Moving with whole window visible (as opposed to outline moving)",
sh.resource.opaque_move, saverc_cmd);
_BOOLITEM(menu, Configmenu, WorkspaceWarping,
"Workspace Warping",
"Workspace Warping - dragging windows to the edge and onto the next workspace",
sh.resource.workspace_warping, saverc_cmd);
#undef _BOOLITEM
menu.updateMenu();
}