external tabs features and bugfixes
This commit is contained in:
parent
da365bb4c9
commit
fe4a7db228
9 changed files with 418 additions and 73 deletions
|
@ -1,5 +1,14 @@
|
|||
(Format: Year/Month/Day)
|
||||
Changes for 0.9.16:
|
||||
*06/03/22:
|
||||
* More external tabs work (Simon)
|
||||
- Can now be placed TopLeft/TopRight/BottomLeft/BottomRight
|
||||
- New "Tab Options" config menu, with (efficient) runtime updating
|
||||
- edge snapping includes tabs
|
||||
- decoration fixes where some missed the tab option
|
||||
- label text color was not updated
|
||||
Screen.hh/cc Window.hh/cc FbWinFrame.hh/cc Container.cc
|
||||
fluxbox-nls.hh
|
||||
*06/03/20:
|
||||
* Fix placement config (some compilers resulted in ignoring of
|
||||
placement policy setting), and a minor ext. tabs placement bug
|
||||
|
|
|
@ -72,7 +72,8 @@ enum {
|
|||
ConfigmenuTransparency = 18,
|
||||
ConfigmenuFocusedAlpha = 19,
|
||||
ConfigmenuUnfocusedAlpha = 20,
|
||||
ConfigmenuExternalTabs = 21,
|
||||
ConfigmenuTabMenu = 21,
|
||||
ConfigmenuTabsInTitlebar = 22,
|
||||
|
||||
EwmhSet = 5,
|
||||
EwmhOutOfMemoryClientList = 1,
|
||||
|
|
|
@ -264,10 +264,16 @@ void Container::setMaxSizePerClient(unsigned int size) {
|
|||
}
|
||||
|
||||
void Container::setMaxTotalSize(unsigned int size) {
|
||||
if (m_max_total_size == size)
|
||||
return;
|
||||
|
||||
unsigned int old = m_max_total_size;
|
||||
m_max_total_size = size;
|
||||
|
||||
if (m_max_total_size && width() > m_max_total_size) {
|
||||
resize(m_max_total_size, height());
|
||||
} else if (!m_max_total_size && old) { // going from restricted to unrestricted
|
||||
repositionItems();
|
||||
} else {
|
||||
// this is a bit of duplication from repositionItems
|
||||
// for when we are allowed to grow ourself
|
||||
|
@ -286,7 +292,6 @@ void Container::setMaxTotalSize(unsigned int size) {
|
|||
if (preferred_width != width())
|
||||
repositionItems();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -381,7 +386,10 @@ void Container::repositionItems() {
|
|||
}
|
||||
if (total_width != width()) {
|
||||
// calling Container::resize here risks infinite loops
|
||||
FbTk::FbWindow::resize(total_width, height());
|
||||
if (align == RIGHT)
|
||||
FbTk::FbWindow::moveResize(x() - (total_width - width()), y(), total_width, height());
|
||||
else
|
||||
FbTk::FbWindow::resize(total_width, height());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -396,7 +404,7 @@ void Container::repositionItems() {
|
|||
int direction = 1;
|
||||
if (align == RIGHT) {
|
||||
direction = -1;
|
||||
next_x = total_width - max_width_per_client + borderW;
|
||||
next_x = total_width - max_width_per_client - borderW;
|
||||
}
|
||||
|
||||
for (; it != it_end; ++it, next_x += direction*(max_width_per_client + borderW + extra)) {
|
||||
|
|
|
@ -80,6 +80,7 @@ FbWinFrame::FbWinFrame(BScreen &screen, FbWinFrameTheme &theme, FbTk::ImageContr
|
|||
EnterWindowMask | LeaveWindowMask),
|
||||
m_bevel(1),
|
||||
m_use_titlebar(true),
|
||||
m_tabplacement(BOTTOMRIGHT),
|
||||
m_use_tabs(true),
|
||||
m_use_handle(true),
|
||||
m_focused(false),
|
||||
|
@ -126,9 +127,11 @@ bool FbWinFrame::setTabMode(TabMode tabmode) {
|
|||
if (tabmode == NOTSET)
|
||||
tabmode = m_tabmode;
|
||||
|
||||
m_tabmode = tabmode;
|
||||
|
||||
// reparent tab container
|
||||
if (tabmode == EXTERNAL) {
|
||||
|
||||
m_label.show();
|
||||
m_tab_container.setBorderWidth(m_window.borderWidth());
|
||||
m_tab_container.setBorderColor(theme().border().color());
|
||||
m_tab_container.setEventMask(
|
||||
|
@ -141,15 +144,35 @@ bool FbWinFrame::setTabMode(TabMode tabmode) {
|
|||
GrabModeSync, GrabModeSync, None, None);
|
||||
XUngrabButton(m_tab_container.display(), Button1, Mod1Mask|Mod2Mask|Mod3Mask, m_tab_container.window());
|
||||
|
||||
int tabx, taby;
|
||||
switch (m_tabplacement) {
|
||||
case TOPLEFT:
|
||||
m_tab_container.setAlignment(Container::LEFT);
|
||||
tabx = x();
|
||||
taby = y() - yOffset();
|
||||
break;
|
||||
case TOPRIGHT:
|
||||
m_tab_container.setAlignment(Container::RIGHT);
|
||||
tabx = x() + width() - m_tab_container.width();
|
||||
taby = y() - yOffset();
|
||||
break;
|
||||
case BOTTOMLEFT:
|
||||
m_tab_container.setAlignment(Container::LEFT);
|
||||
tabx = x();
|
||||
taby = y() + height() + m_window.borderWidth();
|
||||
break;
|
||||
case BOTTOMRIGHT:
|
||||
m_tab_container.setAlignment(Container::RIGHT);
|
||||
tabx = x() + width() - m_tab_container.width();
|
||||
taby = y() + height() + m_window.borderWidth();
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_tab_container.parent()->window() != m_screen.rootWindow().window()) {
|
||||
int tabx = x();
|
||||
// one borderwidth only, so the adjacent borders overlab
|
||||
int taby = y() - m_tab_container.height() - m_tab_container.borderWidth();
|
||||
m_tab_container.reparent(m_screen.rootWindow(), tabx, taby);
|
||||
m_layeritem.addWindow(m_tab_container);
|
||||
}
|
||||
|
||||
m_tab_container.setAlignment(Container::LEFT);
|
||||
m_tab_container.setMaxSizePerClient(64); //!!TODO make this a setting
|
||||
m_tab_container.setMaxTotalSize(window().width());
|
||||
|
||||
|
@ -162,23 +185,24 @@ bool FbWinFrame::setTabMode(TabMode tabmode) {
|
|||
}
|
||||
|
||||
} else {
|
||||
m_tab_container.setAlignment(Container::RELATIVE);
|
||||
if (m_tab_container.parent()->window() == m_screen.rootWindow().window()) {
|
||||
m_layeritem.removeWindow(m_tab_container);
|
||||
m_tab_container.reparent(m_titlebar, m_label.x(), m_label.y());
|
||||
m_tab_container.resize(m_label.width(), m_label.height());
|
||||
m_tab_container.raise();
|
||||
}
|
||||
m_tab_container.setBorderWidth(0);
|
||||
m_tab_container.setMaxTotalSize(0);
|
||||
m_tab_container.setMaxSizePerClient(0);
|
||||
m_tab_container.setAlignment(Container::RELATIVE);
|
||||
if (!m_use_tabs)
|
||||
m_tab_container.show();
|
||||
else
|
||||
ret = false;
|
||||
m_label.hide();
|
||||
// reconfigure();
|
||||
}
|
||||
|
||||
m_tabmode = tabmode;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -286,7 +310,7 @@ void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int heigh
|
|||
m_window.resize(width, height);
|
||||
}
|
||||
|
||||
if (move)
|
||||
if (move || resize && m_tabplacement != TOPLEFT)
|
||||
alignTabs();
|
||||
|
||||
if (resize) {
|
||||
|
@ -306,8 +330,30 @@ void FbWinFrame::quietMoveResize(int x, int y,
|
|||
}
|
||||
|
||||
void FbWinFrame::alignTabs() {
|
||||
if (m_tabmode == EXTERNAL)
|
||||
m_tab_container.move(m_window.x(), m_window.y() - m_tab_container.height() - m_tab_container.borderWidth());
|
||||
if (m_tabmode != EXTERNAL)
|
||||
return;
|
||||
|
||||
int tabx = 0, taby = 0;
|
||||
switch (m_tabplacement) {
|
||||
case TOPLEFT:
|
||||
tabx = x();
|
||||
taby = y() - yOffset();
|
||||
break;
|
||||
case TOPRIGHT:
|
||||
tabx = x() + width() - m_tab_container.width();
|
||||
taby = y() - yOffset();
|
||||
break;
|
||||
case BOTTOMLEFT:
|
||||
tabx = x();
|
||||
taby = y() + height() + m_window.borderWidth();
|
||||
break;
|
||||
case BOTTOMRIGHT:
|
||||
tabx = x() + width() - m_tab_container.width();
|
||||
taby = y() + height() + m_window.borderWidth();
|
||||
break;
|
||||
}
|
||||
|
||||
m_tab_container.move(tabx, taby);
|
||||
}
|
||||
|
||||
void FbWinFrame::notifyMoved(bool clear) {
|
||||
|
@ -1077,6 +1123,9 @@ void FbWinFrame::applyTitlebar() {
|
|||
m_titlebar.setAlpha(alpha);
|
||||
m_label.setAlpha(alpha);
|
||||
|
||||
if (externalTabMode())
|
||||
m_label.setGC(m_focused?theme().labelTextFocusGC():theme().labelTextUnfocusGC());
|
||||
|
||||
if (label_pm != 0)
|
||||
m_label.setBackgroundPixmap(label_pm);
|
||||
else
|
||||
|
@ -1398,6 +1447,7 @@ void FbWinFrame::applyFocusLabel(FbTk::TextButton &button) {
|
|||
}
|
||||
|
||||
void FbWinFrame::applyActiveLabel(FbTk::TextButton &button) {
|
||||
|
||||
button.setBorderWidth(1);
|
||||
button.setGC(theme().labelTextActiveGC());
|
||||
button.setJustify(theme().justify());
|
||||
|
@ -1544,16 +1594,26 @@ void FbWinFrame::gravityTranslate(int &x, int &y, unsigned int width, unsigned i
|
|||
}
|
||||
|
||||
int FbWinFrame::heightOffset() const {
|
||||
if (m_tabmode == EXTERNAL && m_use_tabs)
|
||||
return m_tab_container.height() + m_window.borderWidth();
|
||||
else
|
||||
if (m_tabmode != EXTERNAL || !m_use_tabs)
|
||||
return 0;
|
||||
|
||||
// same height offset for top and bottom tabs
|
||||
return m_tab_container.height() + m_window.borderWidth();
|
||||
}
|
||||
|
||||
int FbWinFrame::yOffset() const {
|
||||
if (m_tabmode == EXTERNAL && m_use_tabs)
|
||||
return m_tab_container.height() + m_window.borderWidth();
|
||||
else
|
||||
if (m_tabmode != EXTERNAL || !m_use_tabs)
|
||||
return 0;
|
||||
|
||||
switch (m_tabplacement) {
|
||||
case TOPLEFT:
|
||||
case TOPRIGHT:
|
||||
return m_tab_container.height() + m_window.borderWidth();
|
||||
break;
|
||||
case BOTTOMLEFT:
|
||||
case BOTTOMRIGHT:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,17 @@ public:
|
|||
// STRICTINTERNAL means it doesn't go external automatically when no titlebar
|
||||
enum TabMode { NOTSET = 0, INTERNAL = 1, EXTERNAL };
|
||||
|
||||
/// Toolbar placement on the screen
|
||||
enum TabPlacement{
|
||||
// top and bottom placement
|
||||
TOPLEFT = 1, BOTTOMLEFT,
|
||||
TOPRIGHT, BOTTOMRIGHT
|
||||
// left and right placement
|
||||
// LEFTBOTTOM, LEFTTOP,
|
||||
// RIGHTBOTTOM, RIGHTTOP
|
||||
};
|
||||
|
||||
|
||||
typedef FbTk::TextButton *ButtonId; ///< defines a button id
|
||||
|
||||
/// create a top level window
|
||||
|
@ -114,6 +125,7 @@ public:
|
|||
inline void setFocusTitle(const std::string &str) { m_label.setText(str); }
|
||||
void setDoubleClickTime(unsigned int time);
|
||||
bool setTabMode(TabMode tabmode);
|
||||
inline void setTabPlacement(TabPlacement tabplacement) { m_tabplacement = tabplacement; alignTabs(); }
|
||||
|
||||
/// add a button to the left of the label
|
||||
void addLeftButton(FbTk::Button *btn);
|
||||
|
@ -222,7 +234,7 @@ public:
|
|||
unsigned int titlebarHeight() const { return m_titlebar.height(); }
|
||||
/// @return size of button
|
||||
unsigned int buttonHeight() const;
|
||||
bool externalTabMode() const { return m_tabmode == EXTERNAL; }
|
||||
bool externalTabMode() const { return m_tabmode == EXTERNAL && m_use_tabs; }
|
||||
|
||||
inline const FbTk::XLayerItem &layerItem() const { return m_layeritem; }
|
||||
inline FbTk::XLayerItem &layerItem() { return m_layeritem; }
|
||||
|
@ -355,6 +367,7 @@ private:
|
|||
//@}
|
||||
|
||||
TabMode m_tabmode;
|
||||
TabPlacement m_tabplacement;
|
||||
|
||||
bool m_need_render;
|
||||
int m_button_size; ///< size for all titlebar buttons
|
||||
|
|
235
src/Screen.cc
235
src/Screen.cc
|
@ -156,9 +156,93 @@ int anotherWMRunning(Display *display, XErrorEvent *) {
|
|||
}
|
||||
|
||||
|
||||
class TabPlacementMenuItem: public FbTk::MenuItem {
|
||||
public:
|
||||
TabPlacementMenuItem(const char * label, BScreen &screen, FbWinFrame::TabPlacement place, FbTk::RefCount<FbTk::Command> &cmd):
|
||||
FbTk::MenuItem(label, cmd),
|
||||
m_screen(screen),
|
||||
m_place(place) { }
|
||||
|
||||
bool isEnabled() const { return m_screen.getTabPlacement() != m_place; }
|
||||
void click(int button, int time) {
|
||||
m_screen.saveTabPlacement(m_place);
|
||||
FbTk::MenuItem::click(button, time);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
BScreen &m_screen;
|
||||
FbWinFrame::TabPlacement m_place;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
|
||||
|
||||
namespace FbTk {
|
||||
|
||||
template<>
|
||||
void FbTk::Resource<FbWinFrame::TabPlacement>::
|
||||
setFromString(const char *strval) {
|
||||
if (strcasecmp(strval, "TopLeft")==0)
|
||||
m_value = FbWinFrame::TOPLEFT;
|
||||
else if (strcasecmp(strval, "BottomLeft")==0)
|
||||
m_value = FbWinFrame::BOTTOMLEFT;
|
||||
else if (strcasecmp(strval, "TopRight")==0)
|
||||
m_value = FbWinFrame::TOPRIGHT;
|
||||
else if (strcasecmp(strval, "BottomRight")==0)
|
||||
m_value = FbWinFrame::BOTTOMRIGHT;
|
||||
/*
|
||||
else if (strcasecmp(strval, "LeftTop") == 0)
|
||||
m_value = FbWinFrame::LEFTTOP;
|
||||
else if (strcasecmp(strval, "LeftBottom") == 0)
|
||||
m_value = FbWinFrame::LEFTBOTTOM;
|
||||
else if (strcasecmp(strval, "RightTop") == 0)
|
||||
m_value = FbWinFrame::RIGHTTOP;
|
||||
else if (strcasecmp(strval, "RightBottom") == 0)
|
||||
m_value = FbWinFrame::RIGHTBOTTOM;
|
||||
*/
|
||||
else
|
||||
setDefaultValue();
|
||||
}
|
||||
|
||||
template<>
|
||||
string FbTk::Resource<FbWinFrame::TabPlacement>::
|
||||
getString() const {
|
||||
switch (m_value) {
|
||||
case FbWinFrame::TOPLEFT:
|
||||
return string("TopLeft");
|
||||
break;
|
||||
case FbWinFrame::BOTTOMLEFT:
|
||||
return string("BottomLeft");
|
||||
break;
|
||||
case FbWinFrame::TOPRIGHT:
|
||||
return string("TopRight");
|
||||
break;
|
||||
case FbWinFrame::BOTTOMRIGHT:
|
||||
return string("BottomRight");
|
||||
break;
|
||||
/*
|
||||
case FbWinFrame::LEFTTOP:
|
||||
return string("LeftTop");
|
||||
break;
|
||||
case FbWinFrame::LEFTBOTTOM:
|
||||
return string("LeftBottom");
|
||||
break;
|
||||
case FbWinFrame::RIGHTTOP:
|
||||
return string("RightTop");
|
||||
break;
|
||||
case FbWinFrame::RIGHTBOTTOM:
|
||||
return string("RightBottom");
|
||||
break;
|
||||
*/
|
||||
}
|
||||
//default string
|
||||
return string("TopLeft");
|
||||
}
|
||||
} // end namespace FbTk
|
||||
|
||||
|
||||
BScreen::ScreenResource::ScreenResource(FbTk::ResourceManager &rm,
|
||||
const std::string &scrname,
|
||||
const std::string &altscrname):
|
||||
|
@ -176,6 +260,7 @@ BScreen::ScreenResource::ScreenResource(FbTk::ResourceManager &rm,
|
|||
decorate_transient(rm, false, scrname+".decorateTransient", altscrname+".DecorateTransient"),
|
||||
rootcommand(rm, "", scrname+".rootCommand", altscrname+".RootCommand"),
|
||||
resize_model(rm, BOTTOMRESIZE, scrname+".resizeMode", altscrname+".ResizeMode"),
|
||||
tab_placement(rm, FbWinFrame::TOPLEFT, scrname+".tab.placement", altscrname+".Tab.Placement"),
|
||||
windowmenufile(rm, "", scrname+".windowMenu", altscrname+".WindowMenu"),
|
||||
follow_model(rm, IGNORE_OTHER_WORKSPACES, scrname+".followModel", altscrname+".followModel"),
|
||||
workspaces(rm, 1, scrname+".workspaces", altscrname+".Workspaces"),
|
||||
|
@ -202,7 +287,7 @@ BScreen::ScreenResource::ScreenResource(FbTk::ResourceManager &rm,
|
|||
altscrname+".overlay.CapStyle"),
|
||||
scroll_action(rm, "", scrname+".windowScrollAction", altscrname+".WindowScrollAction"),
|
||||
scroll_reverse(rm, false, scrname+".windowScrollReverse", altscrname+".WindowScrollReverse"),
|
||||
default_external_tabs(rm, false /* TODO: autoconf option? */ , scrname+".externalTabs", altscrname+".ExternalTabs") {
|
||||
default_internal_tabs(rm, false /* TODO: autoconf option? */ , scrname+".tabs.intitlebar", altscrname+".Tabs.InTitlebar") {
|
||||
|
||||
|
||||
}
|
||||
|
@ -330,7 +415,7 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
|
|||
}
|
||||
|
||||
m_current_workspace = m_workspaces_list.front();
|
||||
|
||||
|
||||
|
||||
//!! TODO: we shouldn't do this more than once, but since slit handles their
|
||||
// own resources we must do this.
|
||||
|
@ -626,6 +711,15 @@ FbTk::Menu *BScreen::createMenu(const std::string &label) {
|
|||
|
||||
return menu;
|
||||
}
|
||||
FbTk::Menu *BScreen::createToggleMenu(const std::string &label) {
|
||||
FbTk::Menu *menu = new ToggleMenu(menuTheme(),
|
||||
imageControl(),
|
||||
*layerManager().getLayer(Layer::MENU));
|
||||
if (!label.empty())
|
||||
menu->setLabel(label.c_str());
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
void BScreen::addExtraWindowMenu(const char *label, FbTk::Menu *menu) {
|
||||
menu->setInternalMenu();
|
||||
|
@ -794,6 +888,26 @@ void BScreen::reconfigure() {
|
|||
FbTk::ThemeManager::instance().load(fluxbox->getStyleFilename(),
|
||||
fluxbox->getStyleOverlayFilename(),
|
||||
m_root_theme->screenNum());
|
||||
|
||||
reconfigureTabs();
|
||||
}
|
||||
|
||||
void BScreen::reconfigureTabs() {
|
||||
Workspaces::iterator w_it = getWorkspacesList().begin();
|
||||
const Workspaces::iterator w_it_end = getWorkspacesList().end();
|
||||
for (; w_it != w_it_end; ++w_it) {
|
||||
if ((*w_it)->windowList().size()) {
|
||||
Workspace::Windows::iterator win_it = (*w_it)->windowList().begin();
|
||||
const Workspace::Windows::iterator win_it_end = (*w_it)->windowList().end();
|
||||
for (; win_it != win_it_end; ++win_it) {
|
||||
(*win_it)->frame().setTabPlacement(*resource.tab_placement);
|
||||
if (*resource.default_internal_tabs)
|
||||
(*win_it)->frame().setTabMode(FbWinFrame::INTERNAL);
|
||||
else
|
||||
(*win_it)->frame().setTabMode(FbWinFrame::EXTERNAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1454,12 +1568,21 @@ void BScreen::setupConfigmenu(FbTk::Menu &menu) {
|
|||
menu.removeAll();
|
||||
|
||||
FbTk::MacroCommand *s_a_reconf_macro = new FbTk::MacroCommand();
|
||||
FbTk::RefCount<FbTk::Command> saverc_cmd(new FbTk::SimpleCommand<Fluxbox>(*Fluxbox::instance(),
|
||||
&Fluxbox::save_rc));
|
||||
FbTk::MacroCommand *s_a_reconftabs_macro = new FbTk::MacroCommand();
|
||||
FbTk::RefCount<FbTk::Command> saverc_cmd(new FbTk::SimpleCommand<Fluxbox>(
|
||||
*Fluxbox::instance(),
|
||||
&Fluxbox::save_rc));
|
||||
FbTk::RefCount<FbTk::Command> reconf_cmd(CommandParser::instance().parseLine("reconfigure"));
|
||||
|
||||
FbTk::RefCount<FbTk::Command> reconftabs_cmd(new FbTk::SimpleCommand<BScreen>(
|
||||
*this,
|
||||
&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);
|
||||
FbTk::RefCount<FbTk::Command> save_and_reconfigure(s_a_reconf_macro);
|
||||
FbTk::RefCount<FbTk::Command> save_and_reconftabs(s_a_reconftabs_macro);
|
||||
// create focus menu
|
||||
// we don't set this to internal menu so will
|
||||
// be deleted toghether with the parent
|
||||
|
@ -1468,6 +1591,9 @@ void BScreen::setupConfigmenu(FbTk::Menu &menu) {
|
|||
"Method used to give focus to windows");
|
||||
FbTk::Menu *focus_menu = createMenu(focusmenu_label ? focusmenu_label : "");
|
||||
|
||||
#define _BOOLITEM(m,a, b, c, d, e, f) (m).insert(new BoolMenuItem(_FBTEXT(a, b, c, d), e, f))
|
||||
|
||||
|
||||
#define _FOCUSITEM(a, b, c, d, e) \
|
||||
focus_menu->insert(new FocusModelMenuItem(_FBTEXT(a, b, c, d), focusControl(), \
|
||||
e, save_and_reconfigure))
|
||||
|
@ -1498,6 +1624,84 @@ void BScreen::setupConfigmenu(FbTk::Menu &menu) {
|
|||
focus_menu->updateMenu();
|
||||
|
||||
menu.insert(focusmenu_label, focus_menu);
|
||||
|
||||
// END focus menu
|
||||
|
||||
// BEGIN tab menu
|
||||
|
||||
const char *tabmenu_label = _FBTEXT(Configmenu, TabMenu,
|
||||
"Tab Options",
|
||||
"heading for tab-related options");
|
||||
FbTk::Menu *tab_menu = createMenu(tabmenu_label ? tabmenu_label : "");
|
||||
const char *tabplacement_label = _FBTEXT(Menu, Placement, "Placement", "Title of Placement menu");
|
||||
FbTk::Menu *tabplacement_menu = createToggleMenu(tabplacement_label);
|
||||
|
||||
tab_menu->insert(tabplacement_label, tabplacement_menu);
|
||||
|
||||
_BOOLITEM(*tab_menu,Configmenu, TabsInTitlebar,
|
||||
"Tabs in Titlebar", "Tabs in Titlebar",
|
||||
*resource.default_internal_tabs, save_and_reconftabs);
|
||||
|
||||
typedef pair<const char*, FbWinFrame::TabPlacement> PlacementP;
|
||||
typedef list<PlacementP> Placements;
|
||||
Placements place_menu;
|
||||
|
||||
// menu is 3 wide, 5 down
|
||||
place_menu.push_back(PlacementP(_FBTEXT(Align, TopLeft, "Top Left", "Top Left"), FbWinFrame::TOPLEFT));
|
||||
place_menu.push_back(PlacementP(_FBTEXT(Align, BottomLeft, "Bottom Left", "Bottom Left"), FbWinFrame::BOTTOMLEFT));
|
||||
place_menu.push_back(PlacementP(_FBTEXT(Align, TopRight, "Top Right", "Top Right"), FbWinFrame::TOPRIGHT));
|
||||
place_menu.push_back(PlacementP(_FBTEXT(Align, BottomRight, "Bottom Right", "Bottom Right"), FbWinFrame::BOTTOMRIGHT));
|
||||
|
||||
/*
|
||||
place_menu.push_back(PlacementP(_FBTEXT(Align, LeftTop, "Left Top", "Left Top"), FbWinFrame::LEFTTOP));
|
||||
place_menu.push_back(PlacementP(_FBTEXT(Align, LeftBottom, "Left Bottom", "Left Bottom"), FbWinFrame::LEFTBOTTOM));
|
||||
place_menu.push_back(PlacementP(_FBTEXT(Align, RightTop, "Right Top", "Right Top"), FbWinFrame::RIGHTTOP));
|
||||
place_menu.push_back(PlacementP(_FBTEXT(Align, RightBottom, "Right Bottom", "Right Bottom"), FbWinFrame::RIGHTBOTTOM));
|
||||
*/
|
||||
|
||||
tabplacement_menu->setMinimumSublevels(2);
|
||||
// create items in sub menu
|
||||
size_t i=0;
|
||||
while (!place_menu.empty()) {
|
||||
i++;
|
||||
const char *str = place_menu.front().first;
|
||||
FbWinFrame::TabPlacement placement = place_menu.front().second;
|
||||
|
||||
if (str == 0) {
|
||||
tabplacement_menu->insert("");
|
||||
tabplacement_menu->setItemEnabled(i, false);
|
||||
} else {
|
||||
tabplacement_menu->insert(new TabPlacementMenuItem(str, *this, placement, save_and_reconftabs));
|
||||
}
|
||||
place_menu.pop_front();
|
||||
}
|
||||
tabplacement_menu->updateMenu();
|
||||
|
||||
menu.insert(tabmenu_label, tab_menu);
|
||||
|
||||
#undef _FOCUSITEM
|
||||
|
||||
focus_menu->insert(new TabFocusModelMenuItem("ClickTabFocus", focusControl(),
|
||||
FocusControl::CLICKTABFOCUS,
|
||||
save_and_reconfigure));
|
||||
focus_menu->insert(new TabFocusModelMenuItem("MouseTabFocus", focusControl(),
|
||||
FocusControl::MOUSETABFOCUS,
|
||||
save_and_reconfigure));
|
||||
|
||||
|
||||
focus_menu->insert(new BoolMenuItem(_FBTEXT(Configmenu,
|
||||
AutoRaise,
|
||||
"Auto Raise",
|
||||
"Auto Raise windows on sloppy"),
|
||||
*resource.auto_raise,
|
||||
save_and_reconfigure));
|
||||
|
||||
focus_menu->updateMenu();
|
||||
|
||||
menu.insert(focusmenu_label, focus_menu);
|
||||
|
||||
// end tab menu
|
||||
|
||||
#ifdef SLIT
|
||||
if (slit() != 0) {
|
||||
slit()->menu().setInternalMenu();
|
||||
|
@ -1510,20 +1714,18 @@ void BScreen::setupConfigmenu(FbTk::Menu &menu) {
|
|||
for (; it != it_end; ++it)
|
||||
menu.insert(it->first, it->second);
|
||||
|
||||
#define _BOOLITEM(a, b, c, d, e, f) menu.insert(new BoolMenuItem(_FBTEXT(a, b, c, d), e, f))
|
||||
|
||||
_BOOLITEM(Configmenu, ImageDithering,
|
||||
_BOOLITEM(menu, Configmenu, ImageDithering,
|
||||
"Image Dithering", "Image Dithering",
|
||||
*resource.image_dither, save_and_reconfigure);
|
||||
_BOOLITEM(Configmenu, OpaqueMove,
|
||||
_BOOLITEM(menu, Configmenu, OpaqueMove,
|
||||
"Opaque Window Moving",
|
||||
"Window Moving with whole window visible (as opposed to outline moving)",
|
||||
*resource.opaque_move, saverc_cmd);
|
||||
_BOOLITEM(Configmenu, FullMax,
|
||||
_BOOLITEM(menu, Configmenu, FullMax,
|
||||
"Full Maximization", "Maximise over slit, toolbar, etc",
|
||||
*resource.full_max, saverc_cmd);
|
||||
try {
|
||||
_BOOLITEM(Configmenu, FocusNew,
|
||||
_BOOLITEM(menu, Configmenu, FocusNew,
|
||||
"Focus New Windows", "Focus newly created windows",
|
||||
*m_resource_manager.getResource<bool>(name() + ".focusNewWindows"),
|
||||
saverc_cmd);
|
||||
|
@ -1532,7 +1734,7 @@ void BScreen::setupConfigmenu(FbTk::Menu &menu) {
|
|||
}
|
||||
|
||||
try {
|
||||
_BOOLITEM(Configmenu, FocusLast,
|
||||
_BOOLITEM(menu, Configmenu, FocusLast,
|
||||
"Focus Last Window on Workspace", "Focus Last Window on Workspace",
|
||||
*resourceManager().getResource<bool>(name() + ".focusLastWindow"),
|
||||
saverc_cmd);
|
||||
|
@ -1540,20 +1742,17 @@ void BScreen::setupConfigmenu(FbTk::Menu &menu) {
|
|||
cerr<<e.what()<<endl;
|
||||
}
|
||||
|
||||
_BOOLITEM(Configmenu, WorkspaceWarping,
|
||||
_BOOLITEM(menu, Configmenu, WorkspaceWarping,
|
||||
"Workspace Warping",
|
||||
"Workspace Warping - dragging windows to the edge and onto the next workspace",
|
||||
*resource.workspace_warping, saverc_cmd);
|
||||
_BOOLITEM(Configmenu, DesktopWheeling,
|
||||
_BOOLITEM(menu, Configmenu, DesktopWheeling,
|
||||
"Desktop MouseWheel Switching", "Workspace switching using mouse wheel",
|
||||
*resource.desktop_wheeling, saverc_cmd);
|
||||
_BOOLITEM(Configmenu, DecorateTransient,
|
||||
_BOOLITEM(menu, Configmenu, DecorateTransient,
|
||||
"Decorate Transient Windows", "Decorate Transient Windows",
|
||||
*resource.decorate_transient, saverc_cmd);
|
||||
_BOOLITEM(Configmenu, ExternalTabs,
|
||||
"Use External Tabs (experimental)", "Use External Tabs (experimental)",
|
||||
*resource.default_external_tabs, saverc_cmd);
|
||||
_BOOLITEM(Configmenu, ClickRaises,
|
||||
_BOOLITEM(menu, Configmenu, ClickRaises,
|
||||
"Click Raises", "Click Raises",
|
||||
*resource.click_raises, saverc_cmd);
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#ifndef SCREEN_HH
|
||||
#define SCREEN_HH
|
||||
|
||||
|
||||
#include "FbWinFrame.hh"
|
||||
#include "FbRootWindow.hh"
|
||||
#include "MenuTheme.hh"
|
||||
#include "PlacementStrategy.hh"
|
||||
|
@ -132,13 +132,15 @@ public:
|
|||
ExtraMenus &extraWindowMenus() { return m_extramenus; }
|
||||
const ExtraMenus &extraWindowMenus() const { return m_extramenus; }
|
||||
|
||||
FbWinFrame::TabPlacement getTabPlacement() const { return *resource.tab_placement; }
|
||||
|
||||
ResizeModel getResizeModel() const { return *resource.resize_model; }
|
||||
|
||||
inline FollowModel getFollowModel() const { return *resource.follow_model; }
|
||||
|
||||
inline const std::string &getScrollAction() const { return *resource.scroll_action; }
|
||||
inline const bool getScrollReverse() const { return *resource.scroll_reverse; }
|
||||
inline const bool getDefaultExternalTabs() const { return *resource.default_external_tabs; }
|
||||
inline const bool getDefaultInternalTabs() const { return *resource.default_internal_tabs; }
|
||||
|
||||
inline Slit *slit() { return m_slit.get(); }
|
||||
inline const Slit *slit() const { return m_slit.get(); }
|
||||
|
@ -203,6 +205,7 @@ public:
|
|||
void update(FbTk::Subject *subj);
|
||||
|
||||
FbTk::Menu *createMenu(const std::string &label);
|
||||
FbTk::Menu *createToggleMenu(const std::string &label);
|
||||
void hideMenus();
|
||||
// for extras to add menus.
|
||||
// These menus will be marked internal,
|
||||
|
@ -218,6 +221,8 @@ public:
|
|||
void setRootColormapInstalled(bool r) { root_colormap_installed = r; }
|
||||
void saveRootCommand(std::string rootcmd) { *resource.rootcommand = rootcmd; }
|
||||
|
||||
void saveTabPlacement(FbWinFrame::TabPlacement place) { *resource.tab_placement = place; }
|
||||
|
||||
void saveWorkspaces(int w) { *resource.workspaces = w; }
|
||||
|
||||
void saveMenu(FbTk::Menu &menu) { m_rootmenu_list.push_back(&menu); }
|
||||
|
@ -275,6 +280,7 @@ public:
|
|||
|
||||
|
||||
void reconfigure();
|
||||
void reconfigureTabs();
|
||||
void rereadMenu();
|
||||
void shutdown();
|
||||
/// show position window centered on the screen with "X x Y" text
|
||||
|
@ -434,6 +440,7 @@ private:
|
|||
antialias, auto_raise, click_raises, decorate_transient;
|
||||
FbTk::Resource<std::string> rootcommand;
|
||||
FbTk::Resource<ResizeModel> resize_model;
|
||||
FbTk::Resource<FbWinFrame::TabPlacement> tab_placement;
|
||||
FbTk::Resource<std::string> windowmenufile;
|
||||
FbTk::Resource<FollowModel> follow_model;
|
||||
bool ordered_dither;
|
||||
|
@ -447,7 +454,7 @@ private:
|
|||
FbTk::Resource<FbTk::GContext::CapStyle> gc_cap_style;
|
||||
FbTk::Resource<std::string> scroll_action;
|
||||
FbTk::Resource<bool> scroll_reverse;
|
||||
FbTk::Resource<bool> default_external_tabs;
|
||||
FbTk::Resource<bool> default_internal_tabs;
|
||||
|
||||
} resource;
|
||||
|
||||
|
|
107
src/Window.cc
107
src/Window.cc
|
@ -394,10 +394,11 @@ void FluxboxWindow::init() {
|
|||
|
||||
frame().setUseShape(!m_shaped);
|
||||
|
||||
if (screen().getDefaultExternalTabs()) {
|
||||
frame().setTabMode(FbWinFrame::EXTERNAL);
|
||||
} else {
|
||||
frame().setTabPlacement(screen().getTabPlacement());
|
||||
if (screen().getDefaultInternalTabs()) {
|
||||
frame().setTabMode(FbWinFrame::INTERNAL);
|
||||
} else {
|
||||
frame().setTabMode(FbWinFrame::EXTERNAL);
|
||||
}
|
||||
|
||||
//!! TODO init of client should be better
|
||||
|
@ -3049,20 +3050,28 @@ void FluxboxWindow::setDecoration(Decoration decoration, bool apply) {
|
|||
case DECOR_NORMAL:
|
||||
decorations.titlebar = decorations.border = decorations.handle =
|
||||
decorations.iconify = decorations.maximize =
|
||||
decorations.menu = true;
|
||||
decorations.menu = decorations.tab = true;
|
||||
functions.resize = functions.move = functions.iconify =
|
||||
functions.maximize = true;
|
||||
break;
|
||||
|
||||
case DECOR_TAB:
|
||||
decorations.border = decorations.iconify = decorations.maximize =
|
||||
decorations.menu = decorations.tab = true;
|
||||
decorations.titlebar = decorations.handle = false;
|
||||
functions.resize = functions.move = functions.iconify =
|
||||
functions.maximize = true;
|
||||
break;
|
||||
|
||||
case DECOR_TINY:
|
||||
decorations.titlebar = decorations.iconify = decorations.menu =
|
||||
functions.move = functions.iconify = true;
|
||||
functions.move = functions.iconify = decorations.tab = true;
|
||||
decorations.border = decorations.handle = decorations.maximize =
|
||||
functions.resize = functions.maximize = false;
|
||||
break;
|
||||
|
||||
case DECOR_TOOL:
|
||||
decorations.titlebar = decorations.menu = functions.move = true;
|
||||
decorations.titlebar = decorations.tab = decorations.menu = functions.move = true;
|
||||
decorations.iconify = decorations.border = decorations.handle =
|
||||
decorations.maximize = functions.resize = functions.maximize =
|
||||
functions.iconify = false;
|
||||
|
@ -3110,7 +3119,7 @@ void FluxboxWindow::applyDecorations(bool initial) {
|
|||
if (decorations.titlebar) {
|
||||
bool change = frame().showTitlebar();
|
||||
client_move |= change;
|
||||
if (change && !screen().getDefaultExternalTabs()) {
|
||||
if (change && screen().getDefaultInternalTabs()) {
|
||||
client_move |= frame().setTabMode(FbWinFrame::INTERNAL);
|
||||
}
|
||||
} else {
|
||||
|
@ -3357,42 +3366,56 @@ void FluxboxWindow::doSnapping(int &orig_left, int &orig_top) {
|
|||
int right = orig_left + width() + 2 * borderW;
|
||||
int bottom = orig_top + height() + 2 * borderW;
|
||||
|
||||
// test against tabs too
|
||||
bool i_have_tabs = frame().externalTabMode();
|
||||
int xoff,yoff,woff,hoff;
|
||||
if (i_have_tabs) {
|
||||
xoff = xOffset();
|
||||
yoff = yOffset();
|
||||
woff = widthOffset();
|
||||
hoff = heightOffset();
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////
|
||||
// begin by checking the screen (or Xinerama head) edges
|
||||
|
||||
int h;
|
||||
if (screen().numHeads() > 0) {
|
||||
// head "0" == whole screen width + height, which we skip since the
|
||||
// sum of all the heads covers those edges
|
||||
for (h = 1; h <= screen().numHeads(); h++) {
|
||||
snapToWindow(dx, dy, left, right, top, bottom,
|
||||
int starth = 0;
|
||||
|
||||
// head "0" == whole screen width + height, which we skip since the
|
||||
// sum of all the heads covers those edges, if >1 head
|
||||
if (screen().numHeads() > 0)
|
||||
starth=1;
|
||||
|
||||
for (int h=starth; h <= screen().numHeads(); h++) {
|
||||
snapToWindow(dx, dy, left, right, top, bottom,
|
||||
screen().maxLeft(h),
|
||||
screen().maxRight(h),
|
||||
screen().maxTop(h),
|
||||
screen().maxBottom(h));
|
||||
|
||||
if (i_have_tabs)
|
||||
snapToWindow(dx, dy, left - xoff, right - xoff + woff, top - yoff, bottom - yoff + hoff,
|
||||
screen().maxLeft(h),
|
||||
screen().maxRight(h),
|
||||
screen().maxTop(h),
|
||||
screen().maxBottom(h));
|
||||
}
|
||||
for (h = 1; h <= screen().numHeads(); h++) {
|
||||
snapToWindow(dx, dy, left, right, top, bottom,
|
||||
}
|
||||
for (int h=starth; h <= screen().numHeads(); h++) {
|
||||
snapToWindow(dx, dy, left, right, top, bottom,
|
||||
screen().getHeadX(h),
|
||||
screen().getHeadX(h) + screen().getHeadWidth(h),
|
||||
screen().getHeadY(h),
|
||||
screen().getHeadY(h) + screen().getHeadHeight(h));
|
||||
|
||||
if (i_have_tabs)
|
||||
snapToWindow(dx, dy, left - xoff, right - xoff + woff, top - yoff, bottom - yoff + hoff,
|
||||
screen().getHeadX(h),
|
||||
screen().getHeadX(h) + screen().getHeadWidth(h),
|
||||
screen().getHeadY(h),
|
||||
screen().getHeadY(h) + screen().getHeadHeight(h));
|
||||
}
|
||||
} else {
|
||||
snapToWindow(dx, dy, left, right, top, bottom,
|
||||
screen().maxLeft(0),
|
||||
screen().maxRight(0),
|
||||
screen().maxTop(0),
|
||||
screen().maxBottom(0));
|
||||
|
||||
snapToWindow(dx, dy, left, right, top, bottom,
|
||||
screen().getHeadX(0),
|
||||
screen().getHeadX(0) + screen().getHeadWidth(0),
|
||||
screen().getHeadY(0),
|
||||
screen().getHeadY(0) + screen().getHeadHeight(0));
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////
|
||||
// now check window edges
|
||||
|
||||
|
@ -3415,6 +3438,30 @@ void FluxboxWindow::doSnapping(int &orig_left, int &orig_top) {
|
|||
(*it)->x() + (*it)->width() + 2 * bw,
|
||||
(*it)->y(),
|
||||
(*it)->y() + (*it)->height() + 2 * bw);
|
||||
|
||||
if (i_have_tabs)
|
||||
snapToWindow(dx, dy, left - xoff, right - xoff + woff, top - yoff, bottom - yoff + hoff,
|
||||
(*it)->x(),
|
||||
(*it)->x() + (*it)->width() + 2 * bw,
|
||||
(*it)->y(),
|
||||
(*it)->y() + (*it)->height() + 2 * bw);
|
||||
|
||||
// also snap to the box containing the tabs (don't bother with actual
|
||||
// tab edges, since they're dynamic
|
||||
if ((*it)->frame().externalTabMode())
|
||||
snapToWindow(dx, dy, left, right, top, bottom,
|
||||
(*it)->x() - (*it)->xOffset(),
|
||||
(*it)->x() - (*it)->xOffset() + (*it)->width() + 2 * bw + (*it)->widthOffset(),
|
||||
(*it)->y() - (*it)->yOffset(),
|
||||
(*it)->y() - (*it)->yOffset() + (*it)->height() + 2 * bw + (*it)->heightOffset());
|
||||
|
||||
if (i_have_tabs)
|
||||
snapToWindow(dx, dy, left - xoff, right - xoff + woff, top - yoff, bottom - yoff + hoff,
|
||||
(*it)->x() - (*it)->xOffset(),
|
||||
(*it)->x() - (*it)->xOffset() + (*it)->width() + 2 * bw + (*it)->widthOffset(),
|
||||
(*it)->y() - (*it)->yOffset(),
|
||||
(*it)->y() - (*it)->yOffset() + (*it)->height() + 2 * bw + (*it)->heightOffset());
|
||||
|
||||
}
|
||||
|
||||
// commit
|
||||
|
|
|
@ -62,7 +62,8 @@ public:
|
|||
DECOR_NONE=0, ///< no decor at all
|
||||
DECOR_NORMAL, ///< normal normal
|
||||
DECOR_TINY, ///< tiny decoration
|
||||
DECOR_TOOL ///< decor tool
|
||||
DECOR_TOOL, ///< decor tool
|
||||
DECOR_TAB ///< decor tab (border + tab)
|
||||
};
|
||||
|
||||
/// Motif wm Hints
|
||||
|
|
Loading…
Reference in a new issue