external tabs
This commit is contained in:
parent
eba0040373
commit
f2d3fff4d4
20 changed files with 550 additions and 148 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,4 +1,17 @@
|
|||
(Format: Year/Month/Day)
|
||||
Changes for 0.9.16:
|
||||
*06/03/20:
|
||||
* External tabs (Simon)
|
||||
- option in Configure menu to enable
|
||||
- restart require at present when toggling this option
|
||||
- New apps pnemonic for "Deco" option: TAB, which is like NONE,
|
||||
but with an external tab
|
||||
Notes:
|
||||
- tab width currently hardcoded
|
||||
- only alignment is topleft
|
||||
fluxbox.cc Screen.hh/cc Window.hh/cc FbWinFrame.hh/cc Remember.cc
|
||||
Container.hh/cc FbTk/XLayer.hh/cc XLayerItem.cc fluxbox-nls.hh
|
||||
RowSmart/ColSmart/UnderMousePlacement.cc WinButton.cc
|
||||
Changes for 0.9.15:
|
||||
*06/03/19:
|
||||
* Fixed some wrong fbsetroot nls (Thanks Semushin Slava )
|
||||
|
|
|
@ -72,6 +72,7 @@ enum {
|
|||
ConfigmenuTransparency = 18,
|
||||
ConfigmenuFocusedAlpha = 19,
|
||||
ConfigmenuUnfocusedAlpha = 20,
|
||||
ConfigmenuExternalTabs = 21,
|
||||
|
||||
EwmhSet = 5,
|
||||
EwmhOutOfMemoryClientList = 1,
|
||||
|
|
|
@ -48,8 +48,11 @@ bool ColSmartPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowli
|
|||
|
||||
int test_x;
|
||||
|
||||
int win_w = win.width() + win.fbWindow().borderWidth()*2;
|
||||
int win_h = win.height() + win.fbWindow().borderWidth()*2;
|
||||
int win_w = win.width() + win.fbWindow().borderWidth()*2 + win.widthOffset();
|
||||
int win_h = win.height() + win.fbWindow().borderWidth()*2 + win.heightOffset();
|
||||
|
||||
int x_off = win.xOffset();
|
||||
int y_off = win.yOffset();
|
||||
|
||||
if (left_right)
|
||||
test_x = head_left;
|
||||
|
@ -87,10 +90,10 @@ bool ColSmartPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowli
|
|||
std::vector<FluxboxWindow *>::const_iterator it_end =
|
||||
windowlist.end();
|
||||
for (; it != it_end && placed; ++it) {
|
||||
int curr_x = (*it)->x();
|
||||
int curr_y = (*it)->y();
|
||||
int curr_w = (*it)->width() + (*it)->fbWindow().borderWidth()*2;
|
||||
int curr_h = (*it)->height() + (*it)->fbWindow().borderWidth()*2;
|
||||
int curr_x = (*it)->x() + (*it)->xOffset();
|
||||
int curr_y = (*it)->y() + (*it)->yOffset();
|
||||
int curr_w = (*it)->width() + (*it)->fbWindow().borderWidth()*2 + (*it)->widthOffset();
|
||||
int curr_h = (*it)->height() + (*it)->fbWindow().borderWidth()*2 + (*it)->heightOffset();
|
||||
|
||||
if (curr_x < test_x + win_w &&
|
||||
curr_x + curr_w > test_x &&
|
||||
|
@ -122,8 +125,8 @@ bool ColSmartPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowli
|
|||
}
|
||||
|
||||
if (placed) {
|
||||
place_x = test_x;
|
||||
place_y = test_y;
|
||||
place_x = test_x + x_off;
|
||||
place_y = test_y + y_off;
|
||||
}
|
||||
|
||||
test_y = next_y;
|
||||
|
|
|
@ -34,6 +34,7 @@ Container::Container(const FbTk::FbWindow &parent):
|
|||
FbTk::FbWindow(parent, 0, 0, 1, 1, ExposureMask),
|
||||
m_align(RELATIVE),
|
||||
m_max_size_per_client(60),
|
||||
m_max_total_size(0),
|
||||
m_selected(0),
|
||||
m_update_lock(false) {
|
||||
FbTk::EventManager::instance()->add(*this, *this);
|
||||
|
@ -59,6 +60,13 @@ void Container::moveResize(int x, int y,
|
|||
repositionItems();
|
||||
}
|
||||
|
||||
/*
|
||||
void Container::move(int x, int y) {
|
||||
FbTk::FbWindow::move(x, y);
|
||||
// no need to reposition
|
||||
}
|
||||
*/
|
||||
|
||||
void Container::insertItems(ItemList &item_list, int pos) {
|
||||
|
||||
// make sure all items have parent == this
|
||||
|
@ -255,6 +263,33 @@ void Container::setMaxSizePerClient(unsigned int size) {
|
|||
m_max_size_per_client = size;
|
||||
}
|
||||
|
||||
void Container::setMaxTotalSize(unsigned int size) {
|
||||
m_max_total_size = size;
|
||||
|
||||
if (m_max_total_size && width() > m_max_total_size) {
|
||||
resize(m_max_total_size, height());
|
||||
} else {
|
||||
// this is a bit of duplication from repositionItems
|
||||
// for when we are allowed to grow ourself
|
||||
Alignment align = alignment();
|
||||
unsigned int num_items = m_item_list.size();
|
||||
if (m_max_total_size && (align == RIGHT || align == LEFT) &&
|
||||
num_items) {
|
||||
unsigned int max_width_per_client = maxWidthPerClient();
|
||||
unsigned int borderW = m_item_list.front()->borderWidth();
|
||||
|
||||
unsigned int preferred_width = (max_width_per_client + borderW) * num_items - borderW;
|
||||
|
||||
if (preferred_width > m_max_total_size)
|
||||
preferred_width = m_max_total_size;
|
||||
|
||||
if (preferred_width != width())
|
||||
repositionItems();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Container::setAlignment(Container::Alignment a) {
|
||||
m_align = a;
|
||||
}
|
||||
|
@ -325,25 +360,48 @@ void Container::repositionItems() {
|
|||
|
||||
//!! TODO vertical position
|
||||
|
||||
const int max_width_per_client = maxWidthPerClient();
|
||||
unsigned int max_width_per_client = maxWidthPerClient();
|
||||
unsigned int borderW = m_item_list.front()->borderWidth();
|
||||
unsigned int num_items = m_item_list.size();
|
||||
|
||||
unsigned int total_width = width();
|
||||
|
||||
// if we have a max total size, then we must also resize ourself
|
||||
// within that bound
|
||||
Alignment align = alignment();
|
||||
if (m_max_total_size && (align == RIGHT || align == LEFT)) {
|
||||
total_width = (max_width_per_client + borderW) * num_items - borderW;
|
||||
if (total_width > m_max_total_size) {
|
||||
total_width = m_max_total_size;
|
||||
if (m_max_total_size > ((num_items - 1)*borderW)) { // don't go negative with unsigned nums
|
||||
max_width_per_client = ( m_max_total_size - (num_items - 1)*borderW ) / num_items;
|
||||
total_width = (max_width_per_client + borderW) * num_items - borderW;
|
||||
} else
|
||||
max_width_per_client = 1;
|
||||
}
|
||||
if (total_width != width()) {
|
||||
// calling Container::resize here risks infinite loops
|
||||
FbTk::FbWindow::resize(total_width, height());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ItemList::iterator it = m_item_list.begin();
|
||||
const ItemList::iterator it_end = m_item_list.end();
|
||||
int borderW = m_item_list.front()->borderWidth();
|
||||
|
||||
int rounding_error = width() - ((maxWidthPerClient() + borderW)* m_item_list.size() - borderW);
|
||||
int rounding_error = total_width - ((max_width_per_client + borderW)* num_items - borderW);
|
||||
|
||||
int next_x = -borderW; // zero so the border of the first shows
|
||||
int extra = 0;
|
||||
int direction = 1;
|
||||
if (alignment() == RIGHT) {
|
||||
if (align == RIGHT) {
|
||||
direction = -1;
|
||||
next_x = 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)) {
|
||||
// we only need to do error stuff with alignment RELATIVE
|
||||
if (rounding_error != 0 && alignment() == RELATIVE) {
|
||||
if (rounding_error != 0 && align == RELATIVE) {
|
||||
--rounding_error;
|
||||
extra = 1;
|
||||
} else {
|
||||
|
@ -374,7 +432,11 @@ unsigned int Container::maxWidthPerClient() const {
|
|||
int borderW = m_item_list.front()->borderWidth();
|
||||
// there're count-1 borders to fit in with the windows
|
||||
// -> 1 per window plus end
|
||||
return (width() - (count - 1) * borderW) / count;
|
||||
unsigned int w = width();
|
||||
if (w < (count-1)*borderW)
|
||||
return 1;
|
||||
else
|
||||
return (w - (count - 1) * borderW) / count;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -25,15 +25,21 @@
|
|||
#ifndef CONTAINER_HH
|
||||
#define CONTAINER_HH
|
||||
|
||||
#include "FbTk/Button.hh"
|
||||
#include "FbTk/FbWindow.hh"
|
||||
#include "FbTk/EventHandler.hh"
|
||||
#include "FbTk/NotCopyable.hh"
|
||||
|
||||
namespace FbTk {
|
||||
class Button;
|
||||
}
|
||||
|
||||
#include <list>
|
||||
#include <functional>
|
||||
|
||||
class Container:public FbTk::FbWindow, public FbTk::EventHandler, private FbTk::NotCopyable {
|
||||
public:
|
||||
// LEFT, RIGHT => fixed total width, fixed icon size
|
||||
// RELATIVE => fixed total width, relative/variable icon size
|
||||
enum Alignment { LEFT, RELATIVE, RIGHT };
|
||||
typedef FbTk::Button * Item;
|
||||
typedef const FbTk::Button * ConstItem;
|
||||
|
@ -58,6 +64,7 @@ public:
|
|||
int find(ConstItem item);
|
||||
void setSelected(int index);
|
||||
void setMaxSizePerClient(unsigned int size);
|
||||
void setMaxTotalSize(unsigned int size);
|
||||
void setAlignment(Alignment a);
|
||||
|
||||
Item back() { return m_item_list.back(); }
|
||||
|
@ -81,6 +88,7 @@ public:
|
|||
inline const Item& selected() const { return m_selected; }
|
||||
inline Item selected() { return m_selected; }
|
||||
unsigned int maxWidthPerClient() const;
|
||||
unsigned int maxTotalSize() const { return m_max_total_size; }
|
||||
inline unsigned int maxHeightPerClient() const { return (empty() ? height() : height()/size()); }
|
||||
inline bool updateLock() const { return m_update_lock; }
|
||||
|
||||
|
@ -97,6 +105,7 @@ private:
|
|||
|
||||
Alignment m_align;
|
||||
unsigned int m_max_size_per_client;
|
||||
unsigned int m_max_total_size;
|
||||
ItemList m_item_list;
|
||||
Item m_selected;
|
||||
bool m_update_lock;
|
||||
|
|
|
@ -131,6 +131,26 @@ void XLayer::stackBelowItem(XLayerItem *item, XLayerItem *above) {
|
|||
|
||||
}
|
||||
|
||||
void XLayer::alignItem(XLayerItem &item) {
|
||||
// Note: some other things effectively assume that the window list is
|
||||
// sorted from highest to lowest
|
||||
size_t winnum = 0,
|
||||
num = item.numWindows();
|
||||
Window *winlist = new Window[num];
|
||||
|
||||
// fill the rest of the array
|
||||
XLayerItem::Windows::iterator it = item.getWindows().begin();
|
||||
XLayerItem::Windows::iterator it_end = item.getWindows().end();
|
||||
for (; it != it_end; ++it) {
|
||||
if ((*it)->window()) {
|
||||
winlist[winnum++] = (*it)->window();
|
||||
}
|
||||
}
|
||||
|
||||
XRestackWindows(FbTk::App::instance()->display(), winlist, winnum);
|
||||
delete [] winlist;
|
||||
}
|
||||
|
||||
XLayer::iterator XLayer::insert(XLayerItem &item, unsigned int pos) {
|
||||
#ifdef DEBUG
|
||||
// at this point we don't support insertions into a layer other than at the top
|
||||
|
|
|
@ -48,6 +48,8 @@ public:
|
|||
void setLayerNum(int layernum) { m_layernum = layernum; };
|
||||
int getLayerNum() { return m_layernum; };
|
||||
void restack();
|
||||
// Put all items on the same layer (called when layer item added to)
|
||||
void alignItem(XLayerItem &item);
|
||||
int countWindows();
|
||||
void stackBelowItem(XLayerItem *item, XLayerItem *above);
|
||||
XLayerItem *getLowestItem();
|
||||
|
|
|
@ -81,9 +81,10 @@ void XLayerItem::moveToLayer(int layernum) {
|
|||
}
|
||||
|
||||
void XLayerItem::addWindow(FbWindow &win) {
|
||||
// I'd like to think we can trust ourselves that it won't be added twice...
|
||||
// Otherwise we're always scanning through the list.
|
||||
m_windows.push_back(&win);
|
||||
// I'd like to think we can trust ourselves that it won't be added twice...
|
||||
// Otherwise we're always scanning through the list.
|
||||
m_windows.push_back(&win);
|
||||
m_layer->alignItem(*this);
|
||||
}
|
||||
|
||||
void XLayerItem::removeWindow(FbWindow &win) {
|
||||
|
@ -91,7 +92,8 @@ void XLayerItem::removeWindow(FbWindow &win) {
|
|||
// Otherwise we're always scanning through the list.
|
||||
|
||||
XLayerItem::Windows::iterator it = std::find(m_windows.begin(), m_windows.end(), &win);
|
||||
m_windows.erase(it);
|
||||
if (it != m_windows.end())
|
||||
m_windows.erase(it);
|
||||
}
|
||||
|
||||
void XLayerItem::bringToTop(FbWindow &win) {
|
||||
|
|
|
@ -25,13 +25,13 @@
|
|||
|
||||
#include "FbTk/ImageControl.hh"
|
||||
#include "FbTk/EventManager.hh"
|
||||
#include "FbTk/TextButton.hh"
|
||||
#include "FbTk/App.hh"
|
||||
#include "FbTk/SimpleCommand.hh"
|
||||
#include "FbTk/Compose.hh"
|
||||
#include "FbTk/Transparent.hh"
|
||||
#include "CompareWindow.hh"
|
||||
#include "FbWinFrameTheme.hh"
|
||||
#include "Screen.hh"
|
||||
|
||||
#include "Container.hh"
|
||||
|
||||
|
@ -46,24 +46,22 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
FbWinFrame::FbWinFrame(FbWinFrameTheme &theme, FbTk::ImageControl &imgctrl,
|
||||
FbWinFrame::FbWinFrame(BScreen &screen, FbWinFrameTheme &theme, FbTk::ImageControl &imgctrl,
|
||||
FbTk::XLayer &layer,
|
||||
int x, int y,
|
||||
unsigned int width, unsigned int height):
|
||||
m_screen(screen),
|
||||
m_theme(theme),
|
||||
m_imagectrl(imgctrl),
|
||||
m_window(theme.screenNum(), x, y, width, height, ButtonPressMask | ButtonReleaseMask |
|
||||
ButtonMotionMask | EnterWindowMask, true),
|
||||
m_layeritem(window(), layer),
|
||||
m_titlebar(m_window, 0, 0, 100, 16,
|
||||
ButtonPressMask | ButtonReleaseMask |
|
||||
ButtonMotionMask | ExposureMask |
|
||||
EnterWindowMask | LeaveWindowMask),
|
||||
m_tab_container(m_titlebar),
|
||||
/*
|
||||
m_label(m_titlebar, 0, 0, 100, 16,
|
||||
ButtonPressMask | ButtonReleaseMask |
|
||||
ButtonMotionMask | ExposureMask |
|
||||
EnterWindowMask | LeaveWindowMask),
|
||||
*/
|
||||
m_label(m_titlebar, m_theme.font(), ""),
|
||||
m_handle(m_window, 0, 0, 100, 5,
|
||||
ButtonPressMask | ButtonReleaseMask |
|
||||
ButtonMotionMask | ExposureMask |
|
||||
|
@ -82,11 +80,12 @@ FbWinFrame::FbWinFrame(FbWinFrameTheme &theme, FbTk::ImageControl &imgctrl,
|
|||
EnterWindowMask | LeaveWindowMask),
|
||||
m_bevel(1),
|
||||
m_use_titlebar(true),
|
||||
m_use_tabs(true),
|
||||
m_use_handle(true),
|
||||
m_focused(false),
|
||||
m_visible(false),
|
||||
m_button_pm(0),
|
||||
m_tabmode(INTERNAL), // TODO: configurable default (on compile, for backwards compat)
|
||||
m_tabmode(NOTSET),
|
||||
m_need_render(true),
|
||||
m_themelistener(*this),
|
||||
m_shape(new Shape(m_window, theme.shapePlace())) {
|
||||
|
@ -116,8 +115,78 @@ bool FbWinFrame::setOnClickTitlebar(FbTk::RefCount<FbTk::Command> &ref, int mous
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FbWinFrame::setTabMode(TabMode tabmode) {
|
||||
if (m_tabmode == tabmode)
|
||||
return false;
|
||||
|
||||
bool ret = true;
|
||||
|
||||
// setting tabmode to notset forces it through when
|
||||
// something is likely to change
|
||||
if (tabmode == NOTSET)
|
||||
tabmode = m_tabmode;
|
||||
|
||||
// reparent tab container
|
||||
if (tabmode == EXTERNAL) {
|
||||
|
||||
m_tab_container.setBorderWidth(m_window.borderWidth());
|
||||
m_tab_container.setBorderColor(theme().border().color());
|
||||
m_tab_container.setEventMask(
|
||||
ButtonPressMask | ButtonReleaseMask |
|
||||
ButtonMotionMask | ExposureMask |
|
||||
EnterWindowMask | LeaveWindowMask);
|
||||
|
||||
XGrabButton(m_tab_container.display(), Button1, AnyModifier,
|
||||
m_tab_container.window(), True, ButtonPressMask,
|
||||
GrabModeSync, GrabModeSync, None, None);
|
||||
XUngrabButton(m_tab_container.display(), Button1, Mod1Mask|Mod2Mask|Mod3Mask, m_tab_container.window());
|
||||
|
||||
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());
|
||||
|
||||
// TODO: tab position
|
||||
if (m_use_tabs && m_visible)
|
||||
m_tab_container.show();
|
||||
else {
|
||||
ret = false;
|
||||
m_tab_container.hide();
|
||||
}
|
||||
|
||||
} else {
|
||||
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.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;
|
||||
// reconfigure();
|
||||
}
|
||||
|
||||
m_tabmode = tabmode;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FbWinFrame::hide() {
|
||||
m_window.hide();
|
||||
if (m_tabmode == EXTERNAL && m_use_tabs)
|
||||
m_tab_container.hide();
|
||||
|
||||
m_visible = false;
|
||||
}
|
||||
|
||||
|
@ -130,6 +199,9 @@ void FbWinFrame::show() {
|
|||
clearAll();
|
||||
}
|
||||
|
||||
if (m_tabmode == EXTERNAL && m_use_tabs)
|
||||
m_tab_container.show();
|
||||
|
||||
m_window.showSubwindows();
|
||||
m_window.show();
|
||||
}
|
||||
|
@ -214,8 +286,28 @@ void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int heigh
|
|||
m_window.resize(width, height);
|
||||
}
|
||||
|
||||
if (resize)
|
||||
if (move)
|
||||
alignTabs();
|
||||
|
||||
if (resize) {
|
||||
if (m_tabmode == EXTERNAL)
|
||||
m_tab_container.setMaxTotalSize(width);
|
||||
reconfigure();
|
||||
}
|
||||
}
|
||||
|
||||
void FbWinFrame::quietMoveResize(int x, int y,
|
||||
unsigned int width, unsigned int height) {
|
||||
m_window.moveResize(x, y, width, height);
|
||||
if (m_tabmode == EXTERNAL) {
|
||||
m_tab_container.setMaxTotalSize(width);
|
||||
alignTabs();
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
void FbWinFrame::notifyMoved(bool clear) {
|
||||
|
@ -224,10 +316,16 @@ void FbWinFrame::notifyMoved(bool clear) {
|
|||
if (alpha == 255)
|
||||
return;
|
||||
|
||||
if (m_use_titlebar) {
|
||||
m_titlebar.parentMoved();
|
||||
//m_label.parentMoved();
|
||||
if (m_tabmode == EXTERNAL && m_use_tabs || m_use_titlebar) {
|
||||
m_tab_container.parentMoved();
|
||||
m_tab_container.for_each(mem_fun(&FbTk::Button::parentMoved));
|
||||
}
|
||||
|
||||
if (m_use_titlebar) {
|
||||
if (m_tabmode == INTERNAL)
|
||||
m_label.parentMoved();
|
||||
|
||||
m_titlebar.parentMoved();
|
||||
|
||||
for_each(m_buttons_left.begin(),
|
||||
m_buttons_left.end(),
|
||||
|
@ -235,7 +333,6 @@ void FbWinFrame::notifyMoved(bool clear) {
|
|||
for_each(m_buttons_right.begin(),
|
||||
m_buttons_right.end(),
|
||||
mem_fun(&FbTk::Button::parentMoved));
|
||||
m_tab_container.for_each(mem_fun(&FbTk::Button::parentMoved));
|
||||
}
|
||||
|
||||
if (m_use_handle) {
|
||||
|
@ -246,7 +343,8 @@ void FbWinFrame::notifyMoved(bool clear) {
|
|||
|
||||
if (clear && (m_use_handle || m_use_titlebar)) {
|
||||
clearAll();
|
||||
}
|
||||
} else if (clear && m_tabmode == EXTERNAL && m_use_tabs)
|
||||
m_tab_container.clear();
|
||||
}
|
||||
|
||||
void FbWinFrame::clearAll() {
|
||||
|
@ -260,7 +358,8 @@ void FbWinFrame::clearAll() {
|
|||
for_each(m_buttons_right.begin(),
|
||||
m_buttons_right.end(),
|
||||
mem_fun(&FbTk::Button::clear));
|
||||
}
|
||||
} else if (m_tabmode == EXTERNAL && m_use_tabs)
|
||||
m_tab_container.clear();
|
||||
|
||||
if (m_use_handle) {
|
||||
m_handle.clear();
|
||||
|
@ -293,6 +392,7 @@ void FbWinFrame::setFocus(bool newvalue) {
|
|||
|
||||
applyTitlebar();
|
||||
applyHandles();
|
||||
applyTabContainer();
|
||||
clearAll();
|
||||
}
|
||||
|
||||
|
@ -416,6 +516,7 @@ void FbWinFrame::setLabelButtonFocus(FbTk::TextButton &btn) {
|
|||
applyUnfocusLabel(*m_current_label);
|
||||
|
||||
m_current_label = &btn; // current focused button
|
||||
m_label.setText(btn.text());
|
||||
|
||||
if (m_focused)
|
||||
applyFocusLabel(*m_current_label);
|
||||
|
@ -451,11 +552,35 @@ void FbWinFrame::setClientWindow(FbTk::FbWindow &win) {
|
|||
XChangeWindowAttributes(win.display(), win.window(), CWEventMask|CWDontPropagate, &attrib_set);
|
||||
|
||||
m_clientarea.raise();
|
||||
win.show();
|
||||
win.raise();
|
||||
m_window.showSubwindows();
|
||||
|
||||
}
|
||||
|
||||
bool FbWinFrame::hideTabs() {
|
||||
if (m_tabmode == INTERNAL || !m_use_tabs) {
|
||||
m_use_tabs = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_use_tabs = false;
|
||||
m_tab_container.hide();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FbWinFrame::showTabs() {
|
||||
if (m_tabmode == INTERNAL || m_use_tabs) {
|
||||
m_use_tabs = true;
|
||||
return false; // nothing changed
|
||||
}
|
||||
|
||||
m_use_tabs = true;
|
||||
if (m_visible)
|
||||
m_tab_container.show();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FbWinFrame::hideTitlebar() {
|
||||
if (!m_use_titlebar)
|
||||
return false;
|
||||
|
@ -484,6 +609,7 @@ bool FbWinFrame::showTitlebar() {
|
|||
// only add one borderwidth (as the other border is still the "top" border)
|
||||
m_window.resize(m_window.width(), m_window.height() + m_titlebar.height() +
|
||||
m_titlebar.borderWidth());
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
@ -555,6 +681,7 @@ void FbWinFrame::setEventHandler(FbTk::EventHandler &evh) {
|
|||
|
||||
FbTk::EventManager &evm = *FbTk::EventManager::instance();
|
||||
evm.add(evh, m_tab_container);
|
||||
evm.add(evh, m_label);
|
||||
evm.add(evh, m_titlebar);
|
||||
evm.add(evh, m_handle);
|
||||
evm.add(evh, m_grip_right);
|
||||
|
@ -569,6 +696,7 @@ void FbWinFrame::setEventHandler(FbTk::EventHandler &evh) {
|
|||
void FbWinFrame::removeEventHandler() {
|
||||
FbTk::EventManager &evm = *FbTk::EventManager::instance();
|
||||
evm.remove(m_tab_container);
|
||||
evm.remove(m_label);
|
||||
evm.remove(m_titlebar);
|
||||
evm.remove(m_handle);
|
||||
evm.remove(m_grip_right);
|
||||
|
@ -579,6 +707,9 @@ void FbWinFrame::removeEventHandler() {
|
|||
|
||||
void FbWinFrame::buttonPressEvent(XButtonEvent &event) {
|
||||
// we can ignore which window the event was generated for
|
||||
if (event.window == m_label.window() && m_current_label)
|
||||
event.window = m_current_label->window();
|
||||
|
||||
m_tab_container.tryButtonPressEvent(event);
|
||||
if (event.window == m_grip_right.window() ||
|
||||
event.window == m_grip_left.window() ||
|
||||
|
@ -595,6 +726,8 @@ void FbWinFrame::buttonPressEvent(XButtonEvent &event) {
|
|||
|
||||
void FbWinFrame::buttonReleaseEvent(XButtonEvent &event) {
|
||||
// we can ignore which window the event was generated for
|
||||
if (event.window == m_label.window() && m_current_label)
|
||||
event.window = m_current_label->window();
|
||||
|
||||
// we continue even if a button got the event
|
||||
m_tab_container.tryButtonReleaseEvent(event);
|
||||
|
@ -626,6 +759,8 @@ void FbWinFrame::exposeEvent(XExposeEvent &event) {
|
|||
m_titlebar.clearArea(event.x, event.y, event.width, event.height);
|
||||
} else if (m_tab_container == event.window) {
|
||||
m_tab_container.clearArea(event.x, event.y, event.width, event.height);
|
||||
} else if (m_label == event.window) {
|
||||
m_label.clearArea(event.x, event.y, event.width, event.height);
|
||||
} else if (m_handle == event.window) {
|
||||
m_handle.clearArea(event.x, event.y, event.width, event.height);
|
||||
} else if (m_grip_left == event.window) {
|
||||
|
@ -696,6 +831,8 @@ void FbWinFrame::reconfigure() {
|
|||
} else
|
||||
m_titlebar.lower();
|
||||
|
||||
if (m_tabmode == EXTERNAL)
|
||||
m_tab_container.resize(m_tab_container.width(), buttonHeight());
|
||||
|
||||
// leave client+grips alone if we're shaded (it'll get fixed when we unshade)
|
||||
if (!m_shaded) {
|
||||
|
@ -788,7 +925,7 @@ void FbWinFrame::redrawTitlebar() {
|
|||
|
||||
if (isVisible()) {
|
||||
m_tab_container.clear();
|
||||
//m_label.clear();
|
||||
m_label.clear();
|
||||
m_titlebar.clear();
|
||||
}
|
||||
}
|
||||
|
@ -825,16 +962,23 @@ void FbWinFrame::reconfigureTitlebar() {
|
|||
next_x += m_bevel;
|
||||
|
||||
// space left on titlebar between left and right buttons
|
||||
unsigned int space_left = m_titlebar.width() - next_x;
|
||||
int space_left = m_titlebar.width() - next_x;
|
||||
|
||||
if (!m_buttons_right.empty())
|
||||
space_left -= m_buttons_right.size() * (button_size + m_bevel);
|
||||
|
||||
space_left -= m_bevel;
|
||||
|
||||
m_tab_container.moveResize(next_x, m_bevel,
|
||||
space_left, button_size);
|
||||
|
||||
next_x += m_tab_container.width() + m_bevel;;
|
||||
if (space_left <= 0)
|
||||
space_left = 1;
|
||||
|
||||
m_label.moveResize(next_x, m_bevel, space_left, button_size);
|
||||
|
||||
if (m_tabmode == INTERNAL)
|
||||
m_tab_container.moveResize(next_x, m_bevel,
|
||||
space_left, button_size);
|
||||
|
||||
next_x += m_label.width() + m_bevel;
|
||||
|
||||
// finaly set new buttons to the right
|
||||
for (size_t i=0; i < m_buttons_right.size();
|
||||
|
@ -851,13 +995,13 @@ void FbWinFrame::renderAll() {
|
|||
|
||||
renderTitlebar();
|
||||
renderHandles();
|
||||
renderLabelButtons();
|
||||
renderTabContainer();
|
||||
}
|
||||
|
||||
void FbWinFrame::applyAll() {
|
||||
applyTitlebar();
|
||||
applyHandles();
|
||||
applyLabelButtons();
|
||||
applyTabContainer();
|
||||
}
|
||||
|
||||
void FbWinFrame::renderTitlebar() {
|
||||
|
@ -878,18 +1022,47 @@ void FbWinFrame::renderTitlebar() {
|
|||
m_title_unfocused_pm,
|
||||
m_titlebar.width(), m_titlebar.height());
|
||||
|
||||
//!! TODO: don't render label if internal tabs
|
||||
|
||||
render(m_theme.labelFocusTexture(), m_label_focused_color,
|
||||
m_label_focused_pm,
|
||||
m_tab_container.width(), m_tab_container.height());
|
||||
|
||||
m_label.width(), m_label.height());
|
||||
|
||||
render(m_theme.labelUnfocusTexture(), m_label_unfocused_color,
|
||||
m_label_unfocused_pm,
|
||||
m_tab_container.width(), m_tab_container.height());
|
||||
m_label.width(), m_label.height());
|
||||
|
||||
renderButtons();
|
||||
}
|
||||
|
||||
void FbWinFrame::renderTabContainer() {
|
||||
if (!isVisible()) {
|
||||
m_need_render = true;
|
||||
return;
|
||||
}
|
||||
|
||||
render(m_theme.labelFocusTexture(), m_tabcontainer_focused_color,
|
||||
m_tabcontainer_focused_pm,
|
||||
m_tab_container.width(), m_tab_container.height());
|
||||
|
||||
render(m_theme.labelUnfocusTexture(), m_tabcontainer_unfocused_color,
|
||||
m_tabcontainer_unfocused_pm,
|
||||
m_tab_container.width(), m_tab_container.height());
|
||||
|
||||
render(m_theme.labelFocusTexture(), m_labelbutton_focused_color,
|
||||
m_labelbutton_focused_pm,
|
||||
m_tab_container.width(), m_tab_container.height());
|
||||
|
||||
render(m_theme.labelUnfocusTexture(), m_labelbutton_unfocused_color,
|
||||
m_labelbutton_unfocused_pm,
|
||||
m_tab_container.width(), m_tab_container.height());
|
||||
|
||||
render(m_theme.labelActiveTexture(), m_labelbutton_active_color,
|
||||
m_labelbutton_active_pm,
|
||||
m_tab_container.width(), m_tab_container.height());
|
||||
|
||||
}
|
||||
|
||||
void FbWinFrame::applyTitlebar() {
|
||||
|
||||
// set up pixmaps for titlebar windows
|
||||
|
@ -902,13 +1075,13 @@ void FbWinFrame::applyTitlebar() {
|
|||
|
||||
unsigned char alpha = (m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
|
||||
m_titlebar.setAlpha(alpha);
|
||||
m_tab_container.setAlpha(alpha);
|
||||
m_label.setAlpha(alpha);
|
||||
|
||||
if (label_pm != 0)
|
||||
m_tab_container.setBackgroundPixmap(label_pm);
|
||||
else
|
||||
m_tab_container.setBackgroundColor(label_color);
|
||||
|
||||
m_label.setBackgroundPixmap(label_pm);
|
||||
else
|
||||
m_label.setBackgroundColor(label_color);
|
||||
|
||||
if (title_pm != 0)
|
||||
m_titlebar.setBackgroundPixmap(title_pm);
|
||||
else
|
||||
|
@ -1036,6 +1209,7 @@ void FbWinFrame::init() {
|
|||
// clear pixmaps
|
||||
m_title_focused_pm = m_title_unfocused_pm = 0;
|
||||
m_label_focused_pm = m_label_unfocused_pm = 0;
|
||||
m_tabcontainer_focused_pm = m_tabcontainer_unfocused_pm = 0;
|
||||
m_labelbutton_focused_pm = m_labelbutton_unfocused_pm = m_labelbutton_active_pm = 0;
|
||||
m_handle_focused_pm = m_handle_unfocused_pm = 0;
|
||||
m_button_pm = m_button_unfocused_pm = m_button_pressed_pm = 0;
|
||||
|
@ -1045,8 +1219,20 @@ void FbWinFrame::init() {
|
|||
m_button_size = 26;
|
||||
|
||||
m_clientarea.setBorderWidth(0);
|
||||
m_label.setBorderWidth(0);
|
||||
m_shaded = false;
|
||||
|
||||
// TODO: configurable default (on compile, for backwards compat)
|
||||
// setTabMode(EXTERNAL);
|
||||
setTabMode(INTERNAL);
|
||||
|
||||
m_label.setEventMask(ExposureMask | ButtonPressMask |
|
||||
ButtonReleaseMask | ButtonMotionMask |
|
||||
EnterWindowMask);
|
||||
m_label.show();
|
||||
|
||||
m_tab_container.show();
|
||||
m_tab_container.raise();
|
||||
|
||||
showHandle();
|
||||
showTitlebar();
|
||||
|
@ -1104,62 +1290,52 @@ void FbWinFrame::render(const FbTk::Texture &tex, FbTk::Color &col, Pixmap &pm,
|
|||
void FbWinFrame::getCurrentFocusPixmap(Pixmap &label_pm, Pixmap &title_pm,
|
||||
FbTk::Color &label_color, FbTk::Color &title_color) {
|
||||
if (m_focused) {
|
||||
if (m_labelbutton_focused_pm != 0)
|
||||
label_pm = m_labelbutton_focused_pm;
|
||||
if (m_label_focused_pm != 0)
|
||||
label_pm = m_label_focused_pm;
|
||||
else
|
||||
label_color = m_labelbutton_focused_color;
|
||||
label_color = m_label_focused_color;
|
||||
|
||||
if (m_title_focused_pm != 0)
|
||||
title_pm = m_title_focused_pm;
|
||||
else
|
||||
title_color = m_title_focused_color;
|
||||
|
||||
} else {
|
||||
getActiveLabelPixmap(label_pm, title_pm,
|
||||
label_color, title_color);
|
||||
if (m_label_unfocused_pm != 0)
|
||||
label_pm = m_label_unfocused_pm;
|
||||
else
|
||||
label_color = m_label_unfocused_color;
|
||||
|
||||
if (m_title_unfocused_pm != 0)
|
||||
title_pm = m_title_unfocused_pm;
|
||||
else
|
||||
title_color = m_title_unfocused_color;
|
||||
}
|
||||
}
|
||||
|
||||
void FbWinFrame::applyTabContainer() {
|
||||
m_tab_container.setAlpha(m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
|
||||
|
||||
// do the parent container
|
||||
Pixmap tabcontainer_pm = None;
|
||||
FbTk::Color *tabcontainer_color = NULL;
|
||||
if (m_focused) {
|
||||
if (m_tabcontainer_focused_pm != 0)
|
||||
tabcontainer_pm = m_tabcontainer_focused_pm;
|
||||
else
|
||||
tabcontainer_color = &m_tabcontainer_focused_color;
|
||||
} else {
|
||||
if (m_tabcontainer_unfocused_pm != 0)
|
||||
tabcontainer_pm = m_tabcontainer_unfocused_pm;
|
||||
else
|
||||
tabcontainer_color = &m_tabcontainer_unfocused_color;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// only called if not focused
|
||||
void FbWinFrame::getActiveLabelPixmap(Pixmap &label_pm, Pixmap &title_pm,
|
||||
FbTk::Color &label_color,
|
||||
FbTk::Color &title_color) {
|
||||
|
||||
if (m_labelbutton_active_pm != 0)
|
||||
label_pm = m_labelbutton_active_pm;
|
||||
if (tabcontainer_pm != 0)
|
||||
m_tab_container.setBackgroundPixmap(tabcontainer_pm);
|
||||
else
|
||||
label_color = m_labelbutton_active_color;
|
||||
|
||||
if (m_title_unfocused_pm != 0)
|
||||
title_pm = m_title_unfocused_pm;
|
||||
else
|
||||
title_color = m_title_unfocused_color;
|
||||
}
|
||||
|
||||
void FbWinFrame::renderLabelButtons() {
|
||||
if (!isVisible()) {
|
||||
m_need_render = true;
|
||||
return;
|
||||
}
|
||||
|
||||
render(m_theme.labelFocusTexture(), m_labelbutton_focused_color,
|
||||
m_labelbutton_focused_pm,
|
||||
m_tab_container.width(), m_tab_container.height());
|
||||
|
||||
|
||||
render(m_theme.labelUnfocusTexture(), m_labelbutton_unfocused_color,
|
||||
m_labelbutton_unfocused_pm,
|
||||
m_tab_container.width(), m_tab_container.height());
|
||||
|
||||
render(m_theme.labelActiveTexture(), m_labelbutton_active_color,
|
||||
m_labelbutton_active_pm,
|
||||
m_tab_container.width(), m_tab_container.height());
|
||||
|
||||
}
|
||||
|
||||
void FbWinFrame::applyLabelButtons() {
|
||||
m_tab_container.setBackgroundColor(*tabcontainer_color);
|
||||
|
||||
// and the labelbuttons in it
|
||||
Container::ItemList::iterator btn_it = m_tab_container.begin();
|
||||
Container::ItemList::iterator btn_it_end = m_tab_container.end();
|
||||
for (; btn_it != btn_it_end; ++btn_it) {
|
||||
|
@ -1186,6 +1362,8 @@ void FbWinFrame::setBorderWidth(unsigned int border_width) {
|
|||
window().setBorderWidth(border_width);
|
||||
window().setBorderColor(theme().border().color());
|
||||
|
||||
setTabMode(NOTSET);
|
||||
|
||||
titlebar().setBorderWidth(border_width);
|
||||
titlebar().setBorderColor(theme().border().color());
|
||||
|
||||
|
@ -1200,13 +1378,16 @@ void FbWinFrame::setBorderWidth(unsigned int border_width) {
|
|||
|
||||
if (bw_changes != 0)
|
||||
resize(width(), height() + bw_changes);
|
||||
|
||||
if (m_tabmode == EXTERNAL)
|
||||
alignTabs();
|
||||
}
|
||||
|
||||
void FbWinFrame::applyFocusLabel(FbTk::TextButton &button) {
|
||||
|
||||
button.setBorderWidth(1);
|
||||
button.setGC(theme().labelTextFocusGC());
|
||||
button.setJustify(theme().justify());
|
||||
button.setBorderWidth(1);
|
||||
button.setAlpha(m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
|
||||
|
||||
if (m_labelbutton_focused_pm != 0) {
|
||||
|
@ -1217,10 +1398,9 @@ void FbWinFrame::applyFocusLabel(FbTk::TextButton &button) {
|
|||
}
|
||||
|
||||
void FbWinFrame::applyActiveLabel(FbTk::TextButton &button) {
|
||||
|
||||
button.setBorderWidth(1);
|
||||
button.setGC(theme().labelTextActiveGC());
|
||||
button.setJustify(theme().justify());
|
||||
button.setBorderWidth(1);
|
||||
button.setAlpha(m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
|
||||
|
||||
if (m_labelbutton_active_pm != 0) {
|
||||
|
@ -1362,3 +1542,18 @@ void FbWinFrame::gravityTranslate(int &x, int &y, unsigned int width, unsigned i
|
|||
move(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
int FbWinFrame::heightOffset() const {
|
||||
if (m_tabmode == EXTERNAL && m_use_tabs)
|
||||
return m_tab_container.height() + m_window.borderWidth();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FbWinFrame::yOffset() const {
|
||||
if (m_tabmode == EXTERNAL && m_use_tabs)
|
||||
return m_tab_container.height() + m_window.borderWidth();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#include "FbTk/Observer.hh"
|
||||
#include "FbTk/Color.hh"
|
||||
#include "FbTk/FbPixmap.hh"
|
||||
#include "FbTk/XLayerItem.hh"
|
||||
#include "FbTk/TextButton.hh"
|
||||
#include "Container.hh"
|
||||
|
||||
#include <vector>
|
||||
|
@ -39,6 +41,7 @@
|
|||
|
||||
class Shape;
|
||||
class FbWinFrameTheme;
|
||||
class BScreen;
|
||||
|
||||
namespace FbTk {
|
||||
class TextButton;
|
||||
|
@ -46,27 +49,30 @@ class ImageControl;
|
|||
class Command;
|
||||
class Button;
|
||||
class Texture;
|
||||
class XLayer;
|
||||
}
|
||||
|
||||
/// holds a window frame with a client window
|
||||
/// (see: <a href="fluxbox_fbwinframe.png">image</a>)
|
||||
class FbWinFrame:public FbTk::EventHandler {
|
||||
public:
|
||||
enum TabMode { INTERNAL = 1, EXTERNAL };
|
||||
// STRICTINTERNAL means it doesn't go external automatically when no titlebar
|
||||
enum TabMode { NOTSET = 0, INTERNAL = 1, EXTERNAL };
|
||||
|
||||
typedef FbTk::TextButton *ButtonId; ///< defines a button id
|
||||
|
||||
/// create a top level window
|
||||
FbWinFrame(FbWinFrameTheme &theme, FbTk::ImageControl &imgctrl,
|
||||
FbWinFrame(BScreen &screen, FbWinFrameTheme &theme, FbTk::ImageControl &imgctrl,
|
||||
FbTk::XLayer &layer,
|
||||
int x, int y,
|
||||
unsigned int width, unsigned int height);
|
||||
|
||||
/// create a frame window inside another FbWindow, NOT IMPLEMENTED!
|
||||
FbWinFrame(FbWinFrameTheme &theme, FbTk::ImageControl &imgctrl,
|
||||
/* /// create a frame window inside another FbWindow, NOT IMPLEMENTED!
|
||||
FbWinFrame(BScreen &screen, FbWinFrameTheme &theme, FbTk::ImageControl &imgctrl,
|
||||
const FbTk::FbWindow &parent,
|
||||
int x, int y,
|
||||
unsigned int width, unsigned int height);
|
||||
|
||||
*/
|
||||
/// destroy frame
|
||||
~FbWinFrame();
|
||||
|
||||
|
@ -94,6 +100,10 @@ public:
|
|||
unsigned int width, unsigned int height,
|
||||
bool move = true, bool resize = true, int win_gravity=ForgetGravity);
|
||||
|
||||
// move without transparency or special effects (generally when dragging)
|
||||
void quietMoveResize(int x, int y,
|
||||
unsigned int width, unsigned int height);
|
||||
|
||||
/// some outside move/resize happened, and we need to notify all of our windows
|
||||
/// in case of transparency
|
||||
void notifyMoved(bool clear);
|
||||
|
@ -101,7 +111,9 @@ public:
|
|||
|
||||
/// set focus/unfocus style
|
||||
void setFocus(bool newvalue);
|
||||
inline void setFocusTitle(const std::string &str) { m_label.setText(str); }
|
||||
void setDoubleClickTime(unsigned int time);
|
||||
bool setTabMode(TabMode tabmode);
|
||||
|
||||
/// add a button to the left of the label
|
||||
void addLeftButton(FbTk::Button *btn);
|
||||
|
@ -138,6 +150,8 @@ public:
|
|||
// these return true/false for if something changed
|
||||
bool hideTitlebar();
|
||||
bool showTitlebar();
|
||||
bool hideTabs();
|
||||
bool showTabs();
|
||||
bool hideHandle();
|
||||
bool showHandle();
|
||||
bool hideAllDecorations();
|
||||
|
@ -172,6 +186,13 @@ public:
|
|||
inline int y() const { return m_window.y(); }
|
||||
inline unsigned int width() const { return m_window.width(); }
|
||||
inline unsigned int height() const { return m_window.height(); }
|
||||
|
||||
// extra bits for tabs
|
||||
inline int xOffset() const { return 0; }
|
||||
int yOffset() const;
|
||||
inline int widthOffset() const { return 0; }
|
||||
int heightOffset() const;
|
||||
|
||||
inline const FbTk::FbWindow &window() const { return m_window; }
|
||||
inline FbTk::FbWindow &window() { return m_window; }
|
||||
/// @return titlebar window
|
||||
|
@ -201,6 +222,10 @@ public:
|
|||
unsigned int titlebarHeight() const { return m_titlebar.height(); }
|
||||
/// @return size of button
|
||||
unsigned int buttonHeight() const;
|
||||
bool externalTabMode() const { return m_tabmode == EXTERNAL; }
|
||||
|
||||
inline const FbTk::XLayerItem &layerItem() const { return m_layeritem; }
|
||||
inline FbTk::XLayerItem &layerItem() { return m_layeritem; }
|
||||
|
||||
//@}
|
||||
|
||||
|
@ -216,7 +241,7 @@ private:
|
|||
void renderAll();
|
||||
void renderTitlebar();
|
||||
void renderHandles();
|
||||
void renderLabelButtons();
|
||||
void renderTabContainer(); // and labelbuttons
|
||||
|
||||
void renderButtons(); // subset of renderTitlebar - don't call directly
|
||||
|
||||
|
@ -233,7 +258,7 @@ private:
|
|||
void applyAll();
|
||||
void applyTitlebar();
|
||||
void applyHandles();
|
||||
void applyLabelButtons();
|
||||
void applyTabContainer(); // and label buttons
|
||||
void applyFocusLabel(FbTk::TextButton &button);
|
||||
void applyUnfocusLabel(FbTk::TextButton &button);
|
||||
void applyActiveLabel(FbTk::TextButton &button);
|
||||
|
@ -246,11 +271,15 @@ private:
|
|||
|
||||
/// initiate inserted button for current theme
|
||||
void applyButton(FbTk::Button &btn);
|
||||
|
||||
void alignTabs();
|
||||
//@}
|
||||
|
||||
/// initiate some commont variables
|
||||
void init();
|
||||
|
||||
BScreen &m_screen;
|
||||
|
||||
FbWinFrameTheme &m_theme; ///< theme to be used
|
||||
FbTk::ImageControl &m_imagectrl; ///< Image control for rendering
|
||||
/**
|
||||
|
@ -258,9 +287,12 @@ private:
|
|||
*/
|
||||
//@{
|
||||
FbTk::FbWindow m_window; ///< base window that holds each decorations (ie titlebar, handles)
|
||||
// want this deleted before the windows in it
|
||||
FbTk::XLayerItem m_layeritem;
|
||||
|
||||
FbTk::FbWindow m_titlebar; ///< titlebar window
|
||||
Container m_tab_container; ///< Holds tabs
|
||||
FbTk::FbWindow m_label; ///< holds title
|
||||
FbTk::TextButton m_label; ///< holds title
|
||||
FbTk::FbWindow m_handle; ///< handle between grips
|
||||
FbTk::FbWindow m_grip_right, ///< rightgrip
|
||||
m_grip_left; ///< left grip
|
||||
|
@ -274,6 +306,7 @@ private:
|
|||
std::string m_titletext; ///< text to be displayed int m_label
|
||||
int m_bevel; ///< bevel between titlebar items and titlebar
|
||||
bool m_use_titlebar; ///< if we should use titlebar
|
||||
bool m_use_tabs; ///< if we should use tabs (turns them off in external mode only)
|
||||
bool m_use_handle; ///< if we should use handle
|
||||
bool m_focused; ///< focused/unfocused mode
|
||||
bool m_visible; ///< if we are currently showing
|
||||
|
@ -285,17 +318,22 @@ private:
|
|||
Pixmap m_title_focused_pm; ///< pixmap for focused title
|
||||
FbTk::Color m_title_focused_color; ///< color for focused title
|
||||
Pixmap m_title_unfocused_pm; ///< pixmap for unfocused title
|
||||
FbTk::Color m_title_unfocused_color; ///< color for unfocued title
|
||||
FbTk::Color m_title_unfocused_color; ///< color for unfocused title
|
||||
|
||||
Pixmap m_label_focused_pm; ///< pixmap for focused label
|
||||
Pixmap m_label_focused_pm; ///< pixmap for focused label (only visible with external tabs)
|
||||
FbTk::Color m_label_focused_color; ///< color for focused label
|
||||
Pixmap m_label_unfocused_pm; ///< pixmap for unfocused label
|
||||
FbTk::Color m_label_unfocused_color; ///< color for unfocued label
|
||||
FbTk::Color m_label_unfocused_color; ///< color for unfocused label
|
||||
|
||||
Pixmap m_tabcontainer_focused_pm; ///< pixmap for focused tab container
|
||||
FbTk::Color m_tabcontainer_focused_color; ///< color for focused tab container
|
||||
Pixmap m_tabcontainer_unfocused_pm; ///< pixmap for unfocused tab container
|
||||
FbTk::Color m_tabcontainer_unfocused_color; ///< color for unfocused tab container
|
||||
|
||||
Pixmap m_labelbutton_focused_pm; ///< pixmap for focused label
|
||||
FbTk::Color m_labelbutton_focused_color; ///< color for focused label
|
||||
Pixmap m_labelbutton_unfocused_pm; ///< pixmap for unfocused label
|
||||
FbTk::Color m_labelbutton_unfocused_color; ///< color for unfocued label
|
||||
FbTk::Color m_labelbutton_unfocused_color; ///< color for unfocused label
|
||||
Pixmap m_labelbutton_active_pm; ///< pixmap for active label
|
||||
FbTk::Color m_labelbutton_active_color; ///< color for active label
|
||||
|
||||
|
|
|
@ -416,6 +416,7 @@ int Remember::parseApp(ifstream &file, Application &app, string *first_line) {
|
|||
FluxboxWindow::DECORM_TITLEBAR
|
||||
| FluxboxWindow::DECORM_ICONIFY
|
||||
| FluxboxWindow::DECORM_MENU
|
||||
| FluxboxWindow::DECORM_TAB
|
||||
);
|
||||
} else if (str_label == "TOOL") {
|
||||
app.rememberDecostate((unsigned int)
|
||||
|
@ -427,6 +428,12 @@ int Remember::parseApp(ifstream &file, Application &app, string *first_line) {
|
|||
FluxboxWindow::DECORM_BORDER
|
||||
| FluxboxWindow::DECORM_MENU
|
||||
);
|
||||
} else if (str_label == "TAB") {
|
||||
app.rememberDecostate((unsigned int)
|
||||
FluxboxWindow::DECORM_BORDER
|
||||
| FluxboxWindow::DECORM_MENU
|
||||
| FluxboxWindow::DECORM_TAB
|
||||
);
|
||||
} else {
|
||||
unsigned int mask;
|
||||
const char * str = str_label.c_str();
|
||||
|
|
|
@ -57,11 +57,12 @@ bool RowSmartPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowli
|
|||
if (screen_placement.rowDirection() == ScreenPlacement::RIGHTLEFT)
|
||||
change_x = -1;
|
||||
|
||||
int win_w = win.width() + win.fbWindow().borderWidth()*2 + win.widthOffset();
|
||||
int win_h = win.height() + win.fbWindow().borderWidth()*2 + win.heightOffset();
|
||||
|
||||
int x_off = win.xOffset();
|
||||
int y_off = win.yOffset();
|
||||
|
||||
|
||||
int win_h = win.height() + win.fbWindow().borderWidth()*2;
|
||||
int win_w = win.width() + win.fbWindow().borderWidth()*2;
|
||||
int test_y;
|
||||
if (top_bot)
|
||||
test_y = head_top;
|
||||
|
@ -102,10 +103,10 @@ bool RowSmartPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowli
|
|||
for (; win_it != win_it_end && placed; ++win_it) {
|
||||
FluxboxWindow &window = **win_it;
|
||||
|
||||
int curr_x = window.x();
|
||||
int curr_y = window.y();
|
||||
int curr_w = window.width() + window.fbWindow().borderWidth()*2;
|
||||
int curr_h = window.height() + window.fbWindow().borderWidth()*2;
|
||||
int curr_x = window.x() + window.xOffset();
|
||||
int curr_y = window.y() + window.yOffset();
|
||||
int curr_w = window.width() + window.fbWindow().borderWidth()*2 + window.widthOffset();
|
||||
int curr_h = window.height() + window.fbWindow().borderWidth()*2 + window.heightOffset();
|
||||
|
||||
if (curr_x < test_x + win_w &&
|
||||
curr_x + curr_w > test_x &&
|
||||
|
@ -138,8 +139,8 @@ bool RowSmartPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowli
|
|||
|
||||
|
||||
if (placed) {
|
||||
place_x = test_x;
|
||||
place_y = test_y;
|
||||
place_x = test_x + x_off;
|
||||
place_y = test_y + y_off;
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -201,7 +201,8 @@ BScreen::ScreenResource::ScreenResource(FbTk::ResourceManager &rm,
|
|||
scrname+".overlay.capStyle",
|
||||
altscrname+".overlay.CapStyle"),
|
||||
scroll_action(rm, "", scrname+".windowScrollAction", altscrname+".WindowScrollAction"),
|
||||
scroll_reverse(rm, false, scrname+".windowScrollReverse", altscrname+".WindowScrollReverse") {
|
||||
scroll_reverse(rm, false, scrname+".windowScrollReverse", altscrname+".WindowScrollReverse"),
|
||||
default_external_tabs(rm, false /* TODO: autoconf option? */ , scrname+".externalTabs", altscrname+".ExternalTabs") {
|
||||
|
||||
|
||||
}
|
||||
|
@ -1549,6 +1550,9 @@ void BScreen::setupConfigmenu(FbTk::Menu &menu) {
|
|||
_BOOLITEM(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,
|
||||
"Click Raises", "Click Raises",
|
||||
*resource.click_raises, saverc_cmd);
|
||||
|
|
|
@ -138,6 +138,7 @@ public:
|
|||
|
||||
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 Slit *slit() { return m_slit.get(); }
|
||||
inline const Slit *slit() const { return m_slit.get(); }
|
||||
|
@ -446,6 +447,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;
|
||||
|
||||
} resource;
|
||||
|
||||
|
|
|
@ -113,15 +113,14 @@ bool ScreenPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowlist
|
|||
|
||||
|
||||
|
||||
int win_w = win.width() + win.fbWindow().borderWidth()*2,
|
||||
win_h = win.height() + win.fbWindow().borderWidth()*2;
|
||||
|
||||
int win_w = win.width() + win.fbWindow().borderWidth()*2 + win.widthOffset(),
|
||||
win_h = win.height() + win.fbWindow().borderWidth()*2 + win.heightOffset();
|
||||
|
||||
// make sure the window is inside our screen(head) area
|
||||
if (place_x + win_w > head_right)
|
||||
place_x = (head_right - win_w) / 2;
|
||||
place_x = (head_right - win_w) / 2 + win.xOffset();
|
||||
if (place_y + win_h > head_bot)
|
||||
place_y = (head_bot - win_h) / 2;
|
||||
place_y = (head_bot - win_h) / 2 + win.yOffset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ bool UnderMousePlacement::placeWindow(const std::vector<FluxboxWindow *> &list,
|
|||
&ignore_i, &ignore_i, &ignore_ui);
|
||||
|
||||
// 2*border = border on each side of the screen
|
||||
// not using offset ones because we won't let tabs influence the "centre"
|
||||
int win_w = win.width() + win.fbWindow().borderWidth()*2,
|
||||
win_h = win.height() + win.fbWindow().borderWidth()*2;
|
||||
|
||||
|
|
|
@ -298,7 +298,7 @@ void WinButton::drawType() {
|
|||
if (m_icon_mask.drawable())
|
||||
XSetClipMask(m_listen_to.fbWindow().display(), gc(), None);
|
||||
} else {
|
||||
for (int y = height()/3; y <= height() - height()/3; y+=3) {
|
||||
for (unsigned int y = height()/3; y <= height() - height()/3; y+=3) {
|
||||
drawLine(gc(), width()/4, y, width() - width()/4 - oddW - 1, y);
|
||||
}
|
||||
drawRectangle(gc(),
|
||||
|
|
|
@ -311,8 +311,7 @@ FluxboxWindow::FluxboxWindow(WinClient &client, FbWinFrameTheme &tm,
|
|||
m_old_pos_x(0), m_old_pos_y(0),
|
||||
m_old_width(1), m_old_height(1),
|
||||
m_last_button_x(0), m_last_button_y(0),
|
||||
m_frame(tm, client.screen().imageControl(), 0, 0, 100, 100),
|
||||
m_layeritem(m_frame.window(), layer),
|
||||
m_frame(client.screen(), tm, client.screen().imageControl(), layer, 0, 0, 100, 100),
|
||||
m_layernum(layer.getLayerNum()),
|
||||
m_old_layernum(0),
|
||||
m_parent(client.screen().rootWindow()),
|
||||
|
@ -344,6 +343,7 @@ FluxboxWindow::~FluxboxWindow() {
|
|||
|
||||
// no longer a valid window to do stuff with
|
||||
Fluxbox::instance()->removeWindowSearchGroup(frame().window().window());
|
||||
Fluxbox::instance()->removeWindowSearchGroup(frame().tabcontainer().window());
|
||||
|
||||
Client2ButtonMap::iterator it = m_labelbuttons.begin();
|
||||
Client2ButtonMap::iterator it_end = m_labelbuttons.end();
|
||||
|
@ -394,6 +394,12 @@ void FluxboxWindow::init() {
|
|||
|
||||
frame().setUseShape(!m_shaped);
|
||||
|
||||
if (screen().getDefaultExternalTabs()) {
|
||||
frame().setTabMode(FbWinFrame::EXTERNAL);
|
||||
} else {
|
||||
frame().setTabMode(FbWinFrame::INTERNAL);
|
||||
}
|
||||
|
||||
//!! TODO init of client should be better
|
||||
// we don't want to duplicate code here and in attachClient
|
||||
m_clientlist.push_back(m_client);
|
||||
|
@ -467,6 +473,7 @@ void FluxboxWindow::init() {
|
|||
m_timer.fireOnce(true);
|
||||
|
||||
Fluxbox::instance()->saveWindowSearchGroup(frame().window().window(), this);
|
||||
Fluxbox::instance()->saveWindowSearchGroup(frame().tabcontainer().window(), this);
|
||||
|
||||
/**************************************************/
|
||||
/* Read state above here, apply state below here. */
|
||||
|
@ -1146,8 +1153,11 @@ void FluxboxWindow::updateTitleFromClient(WinClient &client) {
|
|||
client.updateTitle();
|
||||
// compare old title with new and see if we need to update
|
||||
// graphics
|
||||
if (m_labelbuttons[&client]->text() != client.title())
|
||||
if (m_labelbuttons[&client]->text() != client.title()) {
|
||||
m_labelbuttons[&client]->setText(client.title());
|
||||
if (&client == m_client)
|
||||
frame().setFocusTitle(client.title());
|
||||
}
|
||||
}
|
||||
|
||||
/// update icon title from client
|
||||
|
@ -2648,7 +2658,7 @@ void FluxboxWindow::buttonPressEvent(XButtonEvent &be) {
|
|||
setInputFocus();
|
||||
}
|
||||
|
||||
if (frame().window().window() == be.window) {
|
||||
if (frame().window().window() == be.window || frame().tabcontainer().window() == be.window) {
|
||||
if (screen().clickRaises())
|
||||
raise();
|
||||
#ifdef DEBUG
|
||||
|
@ -2694,17 +2704,28 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) {
|
|||
if (isMoving() && me.window == parent()) {
|
||||
me.window = frame().window().window();
|
||||
}
|
||||
bool inside_titlebar = (frame().titlebar() == me.window || frame().label() == me.window ||
|
||||
frame().handle() == me.window || frame().window() == me.window);
|
||||
|
||||
bool inside_titlebar = (frame().titlebar() == me.window
|
||||
|| frame().label() == me.window
|
||||
|| frame().tabcontainer() == me.window
|
||||
|| frame().handle() == me.window
|
||||
|| frame().window() == me.window);
|
||||
|
||||
if (Fluxbox::instance()->getIgnoreBorder()
|
||||
&& !(me.state & Mod1Mask) // really should check for exact matches
|
||||
&& !(isMoving() || isResizing() || m_attaching_tab != 0)) {
|
||||
int borderw = frame().window().borderWidth();
|
||||
if (me.x_root < (frame().x() + borderw) ||
|
||||
//!! TODO(tabs): the below test ought to be in FbWinFrame
|
||||
if ((me.x_root < (frame().x() + borderw) ||
|
||||
me.y_root < (frame().y() + borderw) ||
|
||||
me.x_root > (frame().x() + (int)frame().width() + borderw) ||
|
||||
me.y_root > (frame().y() + (int)frame().height() + borderw))
|
||||
me.y_root > (frame().y() + (int)frame().height() + borderw)) &&
|
||||
( !frame().externalTabMode() ||
|
||||
(me.x_root < (frame().tabcontainer().x() + borderw) ||
|
||||
me.y_root < (frame().tabcontainer().y() + borderw) ||
|
||||
me.x_root > (frame().tabcontainer().x() + (int)frame().tabcontainer().width() + borderw) ||
|
||||
me.y_root > (frame().tabcontainer().y() + (int)frame().tabcontainer().height() + borderw)
|
||||
)))
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2794,7 +2815,7 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) {
|
|||
} else {
|
||||
//moveResize(dx, dy, frame().width(), frame().height());
|
||||
// need to move the base window without interfering with transparency
|
||||
frame().window().moveResize(dx, dy, frame().width(), frame().height());
|
||||
frame().quietMoveResize(dx, dy, frame().width(), frame().height());
|
||||
}
|
||||
|
||||
screen().showPosition(dx, dy);
|
||||
|
@ -3077,11 +3098,26 @@ void FluxboxWindow::applyDecorations(bool initial) {
|
|||
frame().setBorderWidth(border_width);
|
||||
}
|
||||
|
||||
// we rely on frame not doing anything if it is already shown/hidden
|
||||
if (decorations.titlebar)
|
||||
client_move |= frame().showTitlebar();
|
||||
// tab deocration only affects if we're external
|
||||
// must do before the setTabMode in case it goes
|
||||
// to external and is meant to be hidden
|
||||
if (decorations.tab)
|
||||
client_move |= frame().showTabs();
|
||||
else
|
||||
client_move |= frame().hideTabs();
|
||||
|
||||
// we rely on frame not doing anything if it is already shown/hidden
|
||||
if (decorations.titlebar) {
|
||||
bool change = frame().showTitlebar();
|
||||
client_move |= change;
|
||||
if (change && !screen().getDefaultExternalTabs()) {
|
||||
client_move |= frame().setTabMode(FbWinFrame::INTERNAL);
|
||||
}
|
||||
} else {
|
||||
client_move |= frame().hideTitlebar();
|
||||
if (decorations.tab)
|
||||
client_move |= frame().setTabMode(FbWinFrame::EXTERNAL);
|
||||
}
|
||||
|
||||
if (decorations.handle) {
|
||||
client_move |= frame().showHandle();
|
||||
|
@ -4048,6 +4084,7 @@ void FluxboxWindow::associateClient(WinClient &client) {
|
|||
Fluxbox::instance()->getTabsPadding());
|
||||
|
||||
m_labelbuttons[&client] = btn;
|
||||
|
||||
|
||||
|
||||
FbTk::EventManager &evm = *FbTk::EventManager::instance();
|
||||
|
|
|
@ -316,8 +316,8 @@ public:
|
|||
inline const BScreen &screen() const { return m_screen; }
|
||||
inline BScreen &screen() { return m_screen; }
|
||||
|
||||
inline const FbTk::XLayerItem &layerItem() const { return m_layeritem; }
|
||||
inline FbTk::XLayerItem &layerItem() { return m_layeritem; }
|
||||
inline const FbTk::XLayerItem &layerItem() const { return m_frame.layerItem(); }
|
||||
inline FbTk::XLayerItem &layerItem() { return m_frame.layerItem(); }
|
||||
|
||||
Window clientWindow() const;
|
||||
|
||||
|
@ -337,6 +337,11 @@ public:
|
|||
inline unsigned int width() const { return frame().width(); }
|
||||
inline unsigned int height() const { return frame().height(); }
|
||||
|
||||
inline int xOffset() const { return frame().xOffset(); }
|
||||
inline int yOffset() const { return frame().yOffset(); }
|
||||
inline int widthOffset() const { return frame().widthOffset(); }
|
||||
inline int heightOffset() const { return frame().heightOffset(); }
|
||||
|
||||
unsigned int workspaceNumber() const { return m_workspace_number; }
|
||||
|
||||
int layerNum() const { return m_layernum; }
|
||||
|
@ -504,7 +509,6 @@ private:
|
|||
m_last_button_y; ///< last known y position of the mouse button
|
||||
FbWinFrame m_frame;
|
||||
|
||||
FbTk::XLayerItem m_layeritem;
|
||||
int m_layernum;
|
||||
int m_old_layernum;
|
||||
|
||||
|
|
|
@ -175,6 +175,8 @@ int handleXErrors(Display *d, XErrorEvent *e) {
|
|||
XGetErrorText(d, e->error_code, errtxt, 128);
|
||||
cerr<<"Fluxbox: X Error: "<<errtxt<<"("<<(int)e->error_code<<") opcodes "<<
|
||||
(int)e->request_code<<"/"<<(int)e->minor_code<<" resource 0x"<<hex<<(int)e->resourceid<<dec<<endl;
|
||||
// if (e->error_code != 9 && e->error_code != 183)
|
||||
// kill(0, 2);
|
||||
}
|
||||
#endif // !DEBUG
|
||||
|
||||
|
@ -193,15 +195,15 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile
|
|||
// TODO: shouldn't need a separate one for screen
|
||||
m_screen_rm(m_resourcemanager),
|
||||
m_rc_tabs(m_resourcemanager, true, "session.tabs", "Session.Tabs"),
|
||||
m_rc_tabs_padding(m_resourcemanager, 0, "session.tabPadding", "Session.TabPadding"),
|
||||
m_rc_focused_tab_min_width(m_resourcemanager, 0, "session.focusTabMinWidth",
|
||||
"Session.FocusTabMinWidth"),
|
||||
m_rc_ignoreborder(m_resourcemanager, false, "session.ignoreBorder", "Session.IgnoreBorder"),
|
||||
m_rc_pseudotrans(m_resourcemanager, false, "session.forcePseudoTransparency", "Session.forcePseudoTransparency"),
|
||||
m_rc_colors_per_channel(m_resourcemanager, 4,
|
||||
"session.colorsPerChannel", "Session.ColorsPerChannel"),
|
||||
m_rc_numlayers(m_resourcemanager, 13, "session.numLayers", "Session.NumLayers"),
|
||||
m_rc_double_click_interval(m_resourcemanager, 250, "session.doubleClickInterval", "Session.DoubleClickInterval"),
|
||||
m_rc_tabs_padding(m_resourcemanager, 0, "session.tabPadding", "Session.TabPadding"),
|
||||
m_rc_focused_tab_min_width(m_resourcemanager, 0, "session.focusTabMinWidth",
|
||||
"Session.FocusTabMinWidth"),
|
||||
m_rc_stylefile(m_resourcemanager, DEFAULTSTYLE, "session.styleFile", "Session.StyleFile"),
|
||||
m_rc_styleoverlayfile(m_resourcemanager, "~/.fluxbox/overlay", "session.styleOverlay", "Session.StyleOverlay"),
|
||||
m_rc_menufile(m_resourcemanager, DEFAULTMENU, "session.menuFile", "Session.MenuFile"),
|
||||
|
@ -358,8 +360,8 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile
|
|||
}
|
||||
|
||||
// init all "screens"
|
||||
for(i = 0; i < screens.size(); i++)
|
||||
initScreen(screens[i]);
|
||||
for(unsigned int s = 0; s < screens.size(); s++)
|
||||
initScreen(screens[s]);
|
||||
|
||||
XAllowEvents(disp, ReplayPointer, CurrentTime);
|
||||
|
||||
|
|
Loading…
Reference in a new issue