From fe4a7db228d69bc9a66ed948f218ef489b2cedaf Mon Sep 17 00:00:00 2001 From: simonb Date: Wed, 22 Mar 2006 12:23:17 +0000 Subject: external tabs features and bugfixes --- ChangeLog | 9 ++ nls/fluxbox-nls.hh | 3 +- src/Container.cc | 14 +++- src/FbWinFrame.cc | 90 ++++++++++++++++---- src/FbWinFrame.hh | 15 +++- src/Screen.cc | 235 +++++++++++++++++++++++++++++++++++++++++++++++++---- src/Screen.hh | 13 ++- src/Window.cc | 107 +++++++++++++++++------- src/Window.hh | 3 +- 9 files changed, 417 insertions(+), 72 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6a5919e..1073ad7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 diff --git a/nls/fluxbox-nls.hh b/nls/fluxbox-nls.hh index 21fbd88..fe70b64 100644 --- a/nls/fluxbox-nls.hh +++ b/nls/fluxbox-nls.hh @@ -72,7 +72,8 @@ enum { ConfigmenuTransparency = 18, ConfigmenuFocusedAlpha = 19, ConfigmenuUnfocusedAlpha = 20, - ConfigmenuExternalTabs = 21, + ConfigmenuTabMenu = 21, + ConfigmenuTabsInTitlebar = 22, EwmhSet = 5, EwmhOutOfMemoryClientList = 1, diff --git a/src/Container.cc b/src/Container.cc index 9cef92c..76d8d52 100644 --- a/src/Container.cc +++ b/src/Container.cc @@ -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)) { diff --git a/src/FbWinFrame.cc b/src/FbWinFrame.cc index ec74f4b..5ccfe12 100644 --- a/src/FbWinFrame.cc +++ b/src/FbWinFrame.cc @@ -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) + if (m_tabmode != EXTERNAL || !m_use_tabs) + return 0; + + switch (m_tabplacement) { + case TOPLEFT: + case TOPRIGHT: return m_tab_container.height() + m_window.borderWidth(); - else + break; + case BOTTOMLEFT: + case BOTTOMRIGHT: return 0; + break; + } } diff --git a/src/FbWinFrame.hh b/src/FbWinFrame.hh index 5b6b287..10cd98f 100644 --- a/src/FbWinFrame.hh +++ b/src/FbWinFrame.hh @@ -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 diff --git a/src/Screen.cc b/src/Screen.cc index 464b41f..851e407 100644 --- a/src/Screen.cc +++ b/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 &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:: +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:: +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 saverc_cmd(new FbTk::SimpleCommand(*Fluxbox::instance(), - &Fluxbox::save_rc)); + FbTk::MacroCommand *s_a_reconftabs_macro = new FbTk::MacroCommand(); + FbTk::RefCount saverc_cmd(new FbTk::SimpleCommand( + *Fluxbox::instance(), + &Fluxbox::save_rc)); FbTk::RefCount reconf_cmd(CommandParser::instance().parseLine("reconfigure")); + + FbTk::RefCount reconftabs_cmd(new FbTk::SimpleCommand( + *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 save_and_reconfigure(s_a_reconf_macro); + FbTk::RefCount 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 PlacementP; + typedef list 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(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(name() + ".focusLastWindow"), saverc_cmd); @@ -1540,20 +1742,17 @@ void BScreen::setupConfigmenu(FbTk::Menu &menu) { cerr< rootcommand; FbTk::Resource resize_model; + FbTk::Resource tab_placement; FbTk::Resource windowmenufile; FbTk::Resource follow_model; bool ordered_dither; @@ -447,7 +454,7 @@ private: FbTk::Resource gc_cap_style; FbTk::Resource scroll_action; FbTk::Resource scroll_reverse; - FbTk::Resource default_external_tabs; + FbTk::Resource default_internal_tabs; } resource; diff --git a/src/Window.cc b/src/Window.cc index f28f6ab..e1cf224 100644 --- a/src/Window.cc +++ b/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 diff --git a/src/Window.hh b/src/Window.hh index 9ad9594..44214c7 100644 --- a/src/Window.hh +++ b/src/Window.hh @@ -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 -- cgit v0.11.2