merged changes from pre-devel

This commit is contained in:
markt 2007-10-13 21:51:37 +00:00
parent 41b5c6dadb
commit a59428d67a
92 changed files with 3066 additions and 3160 deletions

131
ChangeLog
View file

@ -1,9 +1,136 @@
(Format: Year/Month/Day)
Changes for 1.0.0:
Changes for 1.0.1:
*07/10/13:
* Merged pre-devel branch; see all Changes since 1.0.0 (Mark)
* Updated ru_RU (Thanks Konstantin Shashkin)
* Deiconify windows via :Deiconify in reverse order (Mathias)
* deiconify windows via :Deiconify in reverse order (Mathias)
FbCommands.cc
*07/05/23:
* Added key command :Attach <pattern> which groups all windows matching the
given pattern (Mark)
FbCommandFactory.cc WorkspaceCmd.cc/hh
*07/05/20:
* Added resources session.screen<N>.maxDisable{Move,Resize}: <boolean>, which
prevent maximized windows from being moved/resized (Mark)
Window.cc Screen.cc/hh nls/fluxbox-nls.hh
*07/05/19:
* Changed behavior of resource session.screen<N>.followModel (Mark)
- now only options are Ignore and Follow, the latter using the setting in
session.screen<N>.userFollowModel
Window.cc/hh Ewmh.cc Screen.cc/hh
*07/05/16:
* Added new resource session.screen<N>.noFocusWhileTypingDelay: <int> (Mark)
- specifies a time in milliseconds that new windows should not gain focus
while the user is typing in the focused window
Window.cc/hh Screen.cc/hh
*07/05/13:
* Added new placement policies {Row,Col}MinOverlapPlacement. They behave the
same as {Row,Col}SmartPlacement when the window fits but fall back on
minimizing overlap with other windows instead of CascadePlacement (Mark)
MinOverlapPlacement.cc/hh ScreenPlacement.cc/hh
*07/04/23:
* Set IconicState on all unmapped clients and unmap clients with frames, as
per ICCCM 4.1.4 (Mark)
Screen.cc Window.cc FocusControl.cc
* Added ClientMenu key command, which pops up a menu of open windows, based
on a pattern match
- e.g. :ClientMenu (workspace=[current]) (minimized=no)
ClientMenu.cc FbCommands.cc/hh FbCommandFactory.cc
*07/04/11:
* Added resource session.screen<N>.maxIgnoreIncrement: <boolean>, to
disable size checking when maximizing a window (e.g. terminals) (Mark)
- Also added a new configuration submenu for maximize options, to be filled
at a later date
Screen.cc/hh Window.cc
*07/04/08:
* Added OnToolbar modifier to keys file (Mark)
Keys.cc/hh Toolbar.cc/hh Screen.cc/hh IconbarTool.cc fluxbox.cc
*07/04/06:
* More changes to theme handling (Mark)
- introduced window.label.(un)focused.{justify,border{Color,Width}},
which fallback to window.label.{justify,border{Color,Width}} before
window.{justify,border{Color,Width}}
- this has the backwards-incompatible effect that
toolbar.iconbar.(un)focused.* fallback first to toolbar.iconbar.* and
then to window.label.*
FbWinFrame.cc/hh IconbarTool.cc/hh IconButton.cc/hh IconbarTheme.cc
FbWinFrameTheme.cc/hh
*07/04/03:
* Added window.label.(un)focused.font to styles (Mark)
FbWinFrame.cc
*07/03/31:
* [group] tag in apps file may now have a pattern appended to it, and a new
window will only be automatically attached to the group if the group
matches that pattern -- e.g. [group] (workspace) (shaded=no) will only
automatically group with windows on the current workspace that are not
shaded (Mark)
Remember.cc/hh
* Lots of window commands now take a client pattern as an additional
argument, and the command will then be applied to all matching windows
(Mark)
- For example: `SendToWorkspace 2 (xterm)' will send all xterm windows to
workspace 2
- Here is the full list of affected commands (which is not to imply they
all necessarily make sense to do): Fullscreen, Minimize, Maximize,
MaximizeVertical, MaximizeHorizontal, SetAlpha, Resize, ResizeTo,
ResizeHorizontal, ResizeVertical, MoveTo, Move, MoveRight, MoveLeft,
MoveUp, MoveDown, Raise, RaiseLayer, Lower, LowerLayer, Close, Kill,
Shade, Stick, ToggleDecor, SetHead, Tab, SendToNextWorkspace,
SendToPrevWorkspace, TakeToNextWorkspace, TakeToPrevWorkspace,
SendToWorkspace, TakeToWorkspace, NextTab, PrevTab, MoveTabLeft,
MoveTabRight, DetachClient
WorkspaceCmd.cc/hh CurrentWindowCmd.cc/hh FbCommandFactory.cc
*07/03/30:
* Changed syntax for window cycling (Mark)
- Instead of a bitmask, the window cycling functions NextWindow,
PrevWindow, TypeAheadFocus, and GoToWindow now take a list of options
enclosed in {} followed by a pattern similar to those used in the apps
file.
- Examples:
* NextWindow {static groups} (shaded=yes) (name=xterm)
- cycles through all shaded xterms in creation order, only focusing
the active tab in the group
* GoToWindow 3 (title=[current])
- focuses the third client in last-focused order with the same title
as the currently focused window
- The options are: name, class, title, role, maximized, minimized, shaded,
stuck, focushidden (can't be disabled), iconhidden, workspace (matches
workspace names, not numbers), head (numbers), and layer (names)
- Parsing is a pain, so you'll have to update your keys file yourself for
now.
*07/03/29:
* Removed groups file; entries will be added to the apps file automatically
(Mark)
* Fixed a problem with programs starting in IconicState (Mark)
*07/03/27:
* Added new resource session.screen<N>.clientMenu.usePixmap that puts the
window's icon in the workspace and icons menus: default true. (Mark)
- For some reason, it doesn't work with un-shaped icons yet, but I've spent
way too many hours already trying to figure out why
* Use IconTitle in iconbar for minimized windows (Mark)
*07/03/25:
* Added new resource session.screen<N>.tabs.usePixmap that puts the window's
icon in the tab, if available. This is on by default. (Mark)
Window.cc FbWinFrame.cc/hh WinClient.cc Screen.cc/hh
*07/03/24:
* Added new key command GoToWindow (Mark)
- Syntax is GoToWindow <int> [<bitmask>], where the int gives the position
of the desired window with respect to a list of windows, and the bitmask
is the same as for NextWindow. A negative number for <int> will count
back from the end of the list.
- Particularly useful examples are GoToWindow <int> 9 and
GoToWindow <int> 25, which will focus the window at position <int> in the
iconbar modes Workspace and WorkspaceNoIcons, respectively.
* Fixed creation order window cycling with tabbed windows (Mark)
*07/03/21:
* Added new command TypeAheadFocus (Mark)
- syntax is the same as for NextWindow; when you run the command, you can
start typing the title of the window, and it will gain focus; pressing
tab will cycle through all matching entries using the options specified;
when you've found the window you want, just press return or escape
WinClient.hh Screen.cc/hh FbCommandFactory.cc WorkspaceCmd.cc/hh
--------------------------------
Changes for 1.0.0:
*07/10/08:
* Changed default style to bloe
*07/10/07:

View file

@ -77,6 +77,10 @@ enum {
ConfigmenuExternalTabWidth = 23,
ConfigmenuMouseTabFocus = 24,
ConfigmenuClickTabFocus = 25,
ConfigmenuMaxMenu = 26,
ConfigmenuMaxIgnoreInc = 27,
ConfigmenuMaxDisableMove = 28,
ConfigmenuMaxDisableResize = 29,
EwmhSet = 5,
EwmhOutOfMemoryClientList = 1,

View file

@ -62,7 +62,6 @@ $set 4 #Configmenu
10 Полная максимизация
11 Сглаживать изображение
12 Перемещение заполненных окон
13 Размытый фокус
14 Фокус по перемещению
15 Перемещение окон между рабочими столами
16 Использовать псевдо-прозрачность
@ -82,15 +81,49 @@ $set 5 #Ewmh
$set 6 #FbTkError
1 Внимание! Высота > 3200, установлена Высота = 3200
2 Внимание! Ширина > 3200, установлена Ширина = 3200
3 Внимание: не удалось загрузить резервный шрифт
4 Ошибка выделения памяти.
5 Ошибка при создании pixmap
6 Невозможно создать XImage
7 Ошибка чтения
8 Внимание: Неверное значение alpha.
9 Внимание: Не удалось создать alpha picture.
10 Внимание: Не удалось создать alpha pixmap.
11 Не удалось найти формат экрана(%d)
12 Нехватка памяти
13 Нехватка памяти при выделении буфера синего.
14 Нехватка памяти при выделении буфера зеленого.
15 Нехватка памяти при выделении буфера красного.
16 Ошибка чтения элемента стиля
17 Неподдерживаемый visual
18 Установлено значение по умолчанию
$set 7 #Fluxbox
1 Неправильное имя файла ресурсов
2 Невозможно загрузить файл групп
3 Невозможно загрузить базу
4 Повторная попытка с
5 Внимание! Не найден экран для отображения окна!
6 Невозможно создать директорию %s
7 Не удалось найти экран.\nУбедитесь, что не запущен другой WM.
8 Ошибка при разборе регулярного выражения
9 Фатальная ошибка! Экземпляр класса fluxbox может быть только один.
10 Невозможно соединиться с X сервером.\nУбедитесь, что X сервер запущен перед запуском Fluxbox.
11 Внимание: X сервер не поддерживает локаль
12 Внимание: невозможно установить модификаторы локали
$set 8 #Gnome
1 Фатальная ошибка: не удалось выделить память для списка клиентов GNOME
$set 9 #Keys
1 Keys: Ошибка в строке
2 Keys: Не удалось создать дерево ключей
3 Keys: Неверная клавиша/модификатор в строке
$set 10 #Menu
@ -103,6 +136,7 @@ $set 10 #Menu
7 Расположение
8 Перечитать настройки
9 Перезапуск
10 Внимание: не закрыты тэги [encoding]
$set 11 #Remember
@ -121,6 +155,11 @@ $set 11 #Remember
$set 12 #Screen
1 BScreen::BScreen: произошла ошибка во время опроса X сервера.\n запущен другой менеджер окон
2 W: %4d x H: %4d
3 BScreen::BScreen: управляем экраном %d используя visual 0x%lx, depth %d\n
4 W: %04d x H: %04d
$set 13 #Slit
1 Клиенты
2 Обычный порядок
@ -165,6 +204,7 @@ $set 16 #Windowmenu
8 Свернуть в заголовок
9 Приклеить
10 Убить
11 Использовать установки по умолчанию
$set 17 #Workspace
@ -176,6 +216,7 @@ $set 17 #Workspace
$set 18 #fbsetroot
1 Ошибка: необходимо задать один из следующих ключей: -solid, -mod, -gradient\n
2 Не удалось создать атомы pixmap, бросаем это гиблое дело!
3 -display <string> соединение с дисплеем\n\
-mod <x> <y> макет клетки\n\
-foreground, -fg <color> цвет переднего плана клетки\n\
@ -196,8 +237,8 @@ $set 19 #main
6 Стандартное исключение
7 Неизвестная ошибка
8 ошибка: '-log' требует наличие аргумента
9 Записывается в
10 Имя журнала
9 Имя файла журнала
10 Записывается в
11 ошибка: '-rc' требует наличие аргумента
12 ошибка: '-screen' требует наличие аргумента
13 Fluxbox %s: (c) %s Henrik Kinnunen\n\

View file

@ -62,7 +62,6 @@ $set 4 #Configmenu
10 Полная максимизация
11 Сглаживать изображение
12 Перемещение заполненных окон
13 Размытый фокус
14 Фокус по перемещению
15 Перемещение окон между рабочими столами
16 Использовать псевдо-прозрачность
@ -82,15 +81,49 @@ $set 5 #Ewmh
$set 6 #FbTkError
1 Внимание! Высота > 3200, установлена Высота = 3200
2 Внимание! Ширина > 3200, установлена Ширина = 3200
3 Внимание: не удалось загрузить резервный шрифт
4 Ошибка выделения памяти.
5 Ошибка при создании pixmap
6 Невозможно создать XImage
7 Ошибка чтения
8 Внимание: Неверное значение alpha.
9 Внимание: Не удалось создать alpha picture.
10 Внимание: Не удалось создать alpha pixmap.
11 Не удалось найти формат экрана(%d)
12 Нехватка памяти
13 Нехватка памяти при выделении буфера синего.
14 Нехватка памяти при выделении буфера зеленого.
15 Нехватка памяти при выделении буфера красного.
16 Ошибка чтения элемента стиля
17 Неподдерживаемый visual
18 Установлено значение по умолчанию
$set 7 #Fluxbox
1 Неправильное имя файла ресурсов
2 Невозможно загрузить файл групп
3 Невозможно загрузить базу
4 Повторная попытка с
5 Внимание! Не найден экран для отображения окна!
6 Невозможно создать директорию %s
7 Не удалось найти экран.\nУбедитесь, что не запущен другой WM.
8 Ошибка при разборе регулярного выражения
9 Фатальная ошибка! Экземпляр класса fluxbox может быть только один.
10 Невозможно соединиться с X сервером.\nУбедитесь, что X сервер запущен перед запуском Fluxbox.
11 Внимание: X сервер не поддерживает локаль
12 Внимание: невозможно установить модификаторы локали
$set 8 #Gnome
1 Фатальная ошибка: не удалось выделить память для списка клиентов GNOME
$set 9 #Keys
1 Keys: Ошибка в строке
2 Keys: Не удалось создать дерево ключей
3 Keys: Неверная клавиша/модификатор в строке
$set 10 #Menu
@ -103,6 +136,7 @@ $set 10 #Menu
7 Расположение
8 Перечитать настройки
9 Перезапуск
10 Внимание: не закрыты тэги [encoding]
$set 11 #Remember
@ -121,6 +155,11 @@ $set 11 #Remember
$set 12 #Screen
1 BScreen::BScreen: произошла ошибка во время опроса X сервера.\n запущен другой менеджер окон
2 W: %4d x H: %4d
3 BScreen::BScreen: управляем экраном %d используя visual 0x%lx, depth %d\n
4 W: %04d x H: %04d
$set 13 #Slit
1 Клиенты
2 Обычный порядок
@ -165,6 +204,7 @@ $set 16 #Windowmenu
8 Свернуть в заголовок
9 Приклеить
10 Убить
11 Использовать установки по умолчанию
$set 17 #Workspace
@ -176,6 +216,7 @@ $set 17 #Workspace
$set 18 #fbsetroot
1 Ошибка: необходимо задать один из следующих ключей: -solid, -mod, -gradient\n
2 Не удалось создать атомы pixmap, бросаем это гиблое дело!
3 -display <string> соединение с дисплеем\n\
-mod <x> <y> макет клетки\n\
-foreground, -fg <color> цвет переднего плана клетки\n\
@ -196,8 +237,8 @@ $set 19 #main
6 Стандартное исключение
7 Неизвестная ошибка
8 ошибка: '-log' требует наличие аргумента
9 Записывается в
10 Имя журнала
9 Имя файла журнала
10 Записывается в
11 ошибка: '-rc' требует наличие аргумента
12 ошибка: '-screen' требует наличие аргумента
13 Fluxbox %s: (c) %s Henrik Kinnunen\n\

View file

@ -23,7 +23,7 @@
#include "AttentionNoticeHandler.hh"
#include "WinClient.hh"
#include "Window.hh"
#include "Screen.hh"
#include "STLUtil.hh"
@ -34,16 +34,15 @@
namespace {
class ToggleFrameFocusCmd: public FbTk::Command {
public:
ToggleFrameFocusCmd(WinClient &client):
ToggleFrameFocusCmd(Focusable &client):
m_client(client),
m_state(false) {}
void execute() {
m_state ^= true;
m_client.fbwindow()->setLabelButtonFocus(m_client, m_state);
m_client.fbwindow()->setAttentionState(m_state);
m_client.setAttentionState(m_state);
}
private:
WinClient& m_client;
Focusable &m_client;
bool m_state;
};
@ -54,9 +53,9 @@ AttentionNoticeHandler::~AttentionNoticeHandler() {
STLUtil::destroyAndClearSecond(m_attentions);
}
void AttentionNoticeHandler::addAttention(WinClient &client) {
void AttentionNoticeHandler::addAttention(Focusable &client) {
// no need to add already active client
if (client.fbwindow()->isFocused() && &client.fbwindow()->winClient() == &client)
if (client.isFocused())
return;
// Already have a notice for it?
@ -104,22 +103,24 @@ void AttentionNoticeHandler::addAttention(WinClient &client) {
void AttentionNoticeHandler::update(FbTk::Subject *subj) {
// we need to be able to get the window
if (typeid(*subj) != typeid(WinClient::WinClientSubj))
if (!subj || typeid(*subj) != typeid(Focusable::FocusSubject))
return;
// all signals results in destruction of the notice
WinClient::WinClientSubj *winsubj =
static_cast<WinClient::WinClientSubj *>(subj);
delete m_attentions[&winsubj->winClient()];
m_attentions.erase(&winsubj->winClient());
Focusable::FocusSubject *winsubj =
static_cast<Focusable::FocusSubject *>(subj);
delete m_attentions[&winsubj->win()];
m_attentions.erase(&winsubj->win());
winsubj->win().setAttentionState(false);
// update _NET_WM_STATE atom
FluxboxWindow *fbwin = winsubj->winClient().fbwindow();
if (fbwin && winsubj != &winsubj->winClient().dieSig())
FluxboxWindow *fbwin = winsubj->win().fbwindow();
if (fbwin && winsubj != &winsubj->win().dieSig())
fbwin->stateSig().notify();
}
bool AttentionNoticeHandler::isDemandingAttention(WinClient &client) {
bool AttentionNoticeHandler::isDemandingAttention(Focusable &client) {
return m_attentions.find(&client) != m_attentions.end();
}

View file

@ -27,7 +27,7 @@
#include <map>
class WinClient;
class Focusable;
namespace FbTk {
class Timer;
@ -41,14 +41,14 @@ class AttentionNoticeHandler: public FbTk::Observer {
public:
~AttentionNoticeHandler();
typedef std::map<WinClient*, FbTk::Timer*> NoticeMap;
typedef std::map<Focusable*, FbTk::Timer*> NoticeMap;
/// Adds a client that requires attention,
/// will fail if the client is already active
void addAttention(WinClient &client);
void addAttention(Focusable &client);
/// removes the client from the attention map
void update(FbTk::Subject *subj);
bool isDemandingAttention(WinClient &client);
bool isDemandingAttention(Focusable &client);
private:
NoticeMap m_attentions;

View file

@ -42,7 +42,7 @@ CascadePlacement::~CascadePlacement() {
delete [] m_cascade_y;
}
bool CascadePlacement::placeWindow(const std::vector<FluxboxWindow *> &windowlist,
bool CascadePlacement::placeWindow(const std::list<FluxboxWindow *> &windowlist,
const FluxboxWindow &win,
int &place_x, int &place_y) {

View file

@ -34,7 +34,7 @@ class CascadePlacement: public PlacementStrategy,
public:
explicit CascadePlacement(const BScreen &screen);
~CascadePlacement();
bool placeWindow(const std::vector<FluxboxWindow *> &windowlist,
bool placeWindow(const std::list<FluxboxWindow *> &windowlist,
const FluxboxWindow &window,
int &place_x, int &place_y);
private:

146
src/ClientMenu.cc Normal file
View file

@ -0,0 +1,146 @@
// ClientMenu.hh
// Copyright (c) 2007 Fluxbox Team (fluxgen at fluxbox dot org)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id$
#include "ClientMenu.hh"
#include "Layer.hh"
#include "Screen.hh"
#include "Window.hh"
#include "WindowCmd.hh"
#include "FbTk/MenuItem.hh"
namespace { // anonymous
class ClientMenuItem: public FbTk::MenuItem {
public:
ClientMenuItem(Focusable &client, ClientMenu &menu):
FbTk::MenuItem(client.title().c_str(), menu),
m_client(client) {
client.titleSig().attach(&menu);
client.dieSig().attach(&menu);
}
~ClientMenuItem() { m_client.titleSig().detach(menu()); }
void click(int button, int time) {
FluxboxWindow *fbwin = m_client.fbwindow();
if (fbwin == 0)
return;
// this MenuItem object can get destroyed as a result of focus(), so we
// must get a local copy of the parent menu
FbTk::Menu *parent = menu();
m_client.focus();
fbwin->raise();
parent->hide();
}
const std::string &label() const { return m_client.title(); }
const FbTk::PixmapWithMask *icon() const {
return m_client.screen().clientMenuUsePixmap() ? &m_client.icon() : 0;
}
bool isSelected() const {
if (m_client.fbwindow() == 0)
return false;
if (m_client.fbwindow()->isFocused() == false)
return false;
return (&(m_client.fbwindow()->winClient()) == &m_client);
}
// for updating menu when receiving a signal from client
Focusable *client() { return &m_client; }
private:
Focusable &m_client;
};
}; // end anonymous namespace
ClientMenu::ClientMenu(BScreen &screen, Focusables &clients,
FbTk::Subject *refresh):
FbMenu(screen.menuTheme(), screen.imageControl(),
*screen.layerManager().getLayer(Layer::MENU)),
m_list(clients),
m_refresh_sig(refresh) {
if (refresh)
refresh->attach(this);
refreshMenu();
}
void ClientMenu::refreshMenu() {
// remove all items and then add them again
removeAll();
// for each fluxboxwindow add every client in them to our clientlist
Focusables::iterator win_it = m_list.begin();
Focusables::iterator win_it_end = m_list.end();
for (; win_it != win_it_end; ++win_it) {
// add every client in this fluxboxwindow to menu
if (typeid(*win_it) == typeid(FluxboxWindow *)) {
FluxboxWindow *win = static_cast<FluxboxWindow *>(*win_it);
FluxboxWindow::ClientList::iterator client_it =
win->clientList().begin();
FluxboxWindow::ClientList::iterator client_it_end =
win->clientList().end();
for (; client_it != client_it_end; ++client_it)
insert(new ClientMenuItem(**client_it, *this));
} else
insert(new ClientMenuItem(**win_it, *this));
}
updateMenu();
}
void ClientMenu::update(FbTk::Subject *subj) {
if (subj == m_refresh_sig)
refreshMenu();
else if (subj && typeid(*subj) == typeid(Focusable::FocusSubject)) {
Focusable::FocusSubject *fsubj = static_cast<Focusable::FocusSubject *>(subj);
Focusable &win = fsubj->win();
// find the corresponding menuitem
ClientMenuItem *cl_item = 0;
for (size_t i = 0; i < numberOfItems(); i++) {
FbTk::MenuItem *item = find(i);
if (item && typeid(*item) == typeid(ClientMenuItem)) {
cl_item = static_cast<ClientMenuItem *>(item);
if (cl_item->client() == &win)
break;
}
}
// update accordingly
if (cl_item && fsubj == &win.dieSig())
remove(cl_item->getIndex());
else if (cl_item && fsubj == &win.titleSig())
// this could change the size of the menu, so do a full update
FbTk::Menu::update(subj);
} else
FbTk::Menu::update(subj);
}

View file

@ -1,8 +1,5 @@
// Netizen.hh for Fluxbox
// Copyright (c) 2002-2003 Henrik Kinnunen (fluxgen at fluxbox dot org)
//
// Netizen.hh for Blackbox - An X11 Window Manager
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
// ClientMenu.hh
// Copyright (c) 2007 Fluxbox Team (fluxgen at fluxbox dot org)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
@ -22,37 +19,42 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#ifndef NETIZEN_HH
#define NETIZEN_HH
// $Id$
#include <X11/Xlib.h>
#ifndef CLIENTMENU_HH
#define CLIENTMENU_HH
#include <list>
#include "FbMenu.hh"
class BScreen;
class Netizen {
class FluxboxWindow;
/**
* A menu holding a set of client menus.
* @see WorkspaceMenu
*/
class ClientMenu: public FbMenu {
public:
Netizen(const BScreen &scr, Window w);
inline Window window() const { return m_window; }
typedef std::list<FluxboxWindow *> Focusables;
void sendWorkspaceCount();
void sendCurrentWorkspace();
/**
* @param screen the screen to show this menu on
* @param client a list of clients to show in this menu
* @param refresh the refresh subject to listen to
*/
ClientMenu(BScreen &screen,
Focusables &clients, FbTk::Subject *refresh);
void sendWindowFocus(Window w);
void sendWindowAdd(Window w, unsigned long wkspc);
void sendWindowDel(Window w);
void sendWindowRaise(Window w);
void sendWindowLower(Window w);
void sendConfigNotify(XEvent &xe);
private:
const BScreen &m_screen;
Display *m_display; ///< display connection
Window m_window;
XEvent event;
/// refresh the entire menu
void refreshMenu();
/// called when receiving a subject signal
void update(FbTk::Subject *subj);
Focusables &m_list; ///< clients in the menu
FbTk::Subject *m_refresh_sig; ///< signal to listen to
};
#endif // _NETIZEN_HH_
#endif // CLIENTMENU_HH

View file

@ -24,7 +24,12 @@
#include "ClientPattern.hh"
#include "RegExp.hh"
#include "FocusControl.hh"
#include "Layer.hh"
#include "Screen.hh"
#include "WinClient.hh"
#include "Workspace.hh"
#include "FbTk/StringUtil.hh"
#include "FbTk/App.hh"
@ -73,54 +78,67 @@ ClientPattern::ClientPattern(const char *str):
If no limit is specified, no limit is applied (i.e. limit = infinity)
*/
int had_error = 0;
bool had_error = false;
int pos = 0;
string match;
int err = 1; // for starting first loop
while (had_error == 0 && err > 0) {
while (!had_error && err > 0) {
err = FbTk::StringUtil::getStringBetween(match,
str + pos,
'(', ')', " \t\n", true);
if (err > 0) {
size_t eq = match.find_first_of('=');
// need to determine the property used
string memstr, expr;
WinProperty prop;
string::size_type eq = match.find_first_of('=');
if (eq == match.npos) {
if (!addTerm(match, NAME)) {
had_error = pos + match.find_first_of('(') + 1;
break;
}
memstr = match;
expr = "[current]";
} else {
// need to determine the property used
string memstr, expr;
WinProperty prop;
memstr.assign(match, 0, eq); // memstr = our identifier
expr.assign(match, eq+1, match.length());
if (strcasecmp(memstr.c_str(), "name") == 0) {
prop = NAME;
} else if (strcasecmp(memstr.c_str(), "class") == 0) {
prop = CLASS;
} else if (strcasecmp(memstr.c_str(), "title") == 0) {
prop = TITLE;
} else if (strcasecmp(memstr.c_str(), "role") == 0) {
prop = ROLE;
} else {
had_error = pos + match.find_first_of('(') + 1;
break;
}
if (!addTerm(expr, prop)) {
had_error = pos + ((str+pos) - index(str+pos, '=')) + 1;
break;
}
}
if (strcasecmp(memstr.c_str(), "name") == 0) {
prop = NAME;
} else if (strcasecmp(memstr.c_str(), "class") == 0) {
prop = CLASS;
} else if (strcasecmp(memstr.c_str(), "title") == 0) {
prop = TITLE;
} else if (strcasecmp(memstr.c_str(), "role") == 0) {
prop = ROLE;
} else if (strcasecmp(memstr.c_str(), "maximized") == 0) {
prop = MAXIMIZED;
} else if (strcasecmp(memstr.c_str(), "minimized") == 0) {
prop = MINIMIZED;
} else if (strcasecmp(memstr.c_str(), "shaded") == 0) {
prop = SHADED;
} else if (strcasecmp(memstr.c_str(), "stuck") == 0) {
prop = STUCK;
} else if (strcasecmp(memstr.c_str(), "focushidden") == 0) {
prop = FOCUSHIDDEN;
} else if (strcasecmp(memstr.c_str(), "iconhidden") == 0) {
prop = ICONHIDDEN;
} else if (strcasecmp(memstr.c_str(), "workspace") == 0) {
prop = WORKSPACE;
} else if (strcasecmp(memstr.c_str(), "head") == 0) {
prop = HEAD;
} else if (strcasecmp(memstr.c_str(), "layer") == 0) {
prop = LAYER;
} else {
prop = NAME;
expr = match;
}
had_error = !addTerm(expr, prop);
pos += err;
}
}
if (pos == 0 && had_error == 0) {
if (pos == 0 && !had_error) {
// no match terms given, this is not allowed
had_error = 1;
had_error = true;
}
if (had_error == 0) {
if (!had_error) {
// otherwise, we check for a number
string number;
err = FbTk::StringUtil::getStringBetween(number,
@ -139,12 +157,11 @@ ClientPattern::ClientPattern(const char *str):
uerr = match.find_first_not_of(" \t\n", pos);
if (uerr != match.npos) {
// found something, not good
had_error++;
had_error = true;
}
}
if (had_error > 0) {
m_matchlimit = had_error;
if (had_error) {
// delete all the terms
while (!m_terms.empty()) {
Term * term = m_terms.back();
@ -183,6 +200,34 @@ string ClientPattern::toString() const {
break;
case ROLE:
pat.append("role=");
break;
case MAXIMIZED:
pat.append("maximized=");
break;
case MINIMIZED:
pat.append("minimized=");
break;
case SHADED:
pat.append("shaded=");
break;
case STUCK:
pat.append("stuck=");
break;
case FOCUSHIDDEN:
pat.append("focushidden=");
break;
case ICONHIDDEN:
pat.append("iconhidden=");
break;
case WORKSPACE:
pat.append("workspace=");
break;
case HEAD:
pat.append("head=");
break;
case LAYER:
pat.append("layer=");
break;
}
pat.append((*it)->orig);
@ -198,9 +243,8 @@ string ClientPattern::toString() const {
}
// does this client match this pattern?
bool ClientPattern::match(const WinClient &win) const {
if (m_matchlimit != 0 && m_nummatches >= m_matchlimit ||
m_terms.empty())
bool ClientPattern::match(const Focusable &win) const {
if (m_matchlimit != 0 && m_nummatches >= m_matchlimit)
return false; // already matched out
// regmatch everything
@ -209,7 +253,20 @@ bool ClientPattern::match(const WinClient &win) const {
Terms::const_iterator it = m_terms.begin();
Terms::const_iterator it_end = m_terms.end();
for (; it != it_end; ++it) {
if (!(*it)->regexp.match(getProperty((*it)->prop, win)))
if ((*it)->orig == "[current]") {
// workspaces don't necessarily have unique names, so we want to
// compare numbers instead of strings
if ((*it)->prop == WORKSPACE && (!win.fbwindow() ||
win.fbwindow()->workspaceNumber() !=
win.screen().currentWorkspaceID()))
return false;
else {
WinClient *focused = FocusControl::focusedWindow();
if (!focused || getProperty((*it)->prop, win) !=
getProperty((*it)->prop, *focused))
return false;
}
} else if (!(*it)->regexp.match(getProperty((*it)->prop, win)))
return false;
}
return true;
@ -232,7 +289,11 @@ bool ClientPattern::addTerm(const string &str, WinProperty prop) {
return true;
}
string ClientPattern::getProperty(WinProperty prop, const WinClient &client) const {
string ClientPattern::getProperty(WinProperty prop,
const Focusable &client) const {
// we need this for some of the window properties
const FluxboxWindow *fbwin = client.fbwindow();
switch (prop) {
case TITLE:
return client.title();
@ -244,8 +305,44 @@ string ClientPattern::getProperty(WinProperty prop, const WinClient &client) con
return client.getWMClassName();
break;
case ROLE:
Atom wm_role = XInternAtom(FbTk::App::instance()->display(), "WM_WINDOW_ROLE", False);
return client.textProperty(wm_role);
return client.getWMRole();
break;
case MAXIMIZED:
return (fbwin && fbwin->isMaximized()) ? "yes" : "no";
break;
case MINIMIZED:
return (fbwin && fbwin->isIconic()) ? "yes" : "no";
break;
case SHADED:
return (fbwin && fbwin->isShaded()) ? "yes" : "no";
break;
case STUCK:
return (fbwin && fbwin->isStuck()) ? "yes" : "no";
break;
case FOCUSHIDDEN:
return (fbwin && fbwin->isFocusHidden()) ? "yes" : "no";
break;
case ICONHIDDEN:
return (fbwin && fbwin->isIconHidden()) ? "yes" : "no";
break;
case WORKSPACE: {
if (!fbwin)
return "";
const Workspace *w = client.screen().getWorkspace(fbwin->workspaceNumber());
return w ? w->name() : "";
break;
}
case HEAD: {
if (!fbwin)
return "";
int head = client.screen().getHead(fbwin->fbWindow());
char tmpstr[128];
sprintf(tmpstr, "%d", head);
return std::string(tmpstr);
break;
}
case LAYER:
return fbwin ? ::Layer::getString(fbwin->layerNum()) : "";
break;
}
return client.getWMClassName();

View file

@ -32,7 +32,7 @@
#include <string>
#include <list>
class WinClient;
class Focusable;
/**
* This class represents a "pattern" that we can match against a
@ -53,10 +53,14 @@ public:
/// @return a string representation of this pattern
std::string toString() const;
enum WinProperty { TITLE, CLASS, NAME, ROLE };
enum WinProperty {
TITLE, CLASS, NAME, ROLE,
MAXIMIZED, MINIMIZED, SHADED, STUCK, FOCUSHIDDEN, ICONHIDDEN,
WORKSPACE, HEAD, LAYER
};
/// Does this client match this pattern?
bool match(const WinClient &win) const;
bool match(const Focusable &win) const;
/**
* Add an expression to match against
@ -68,7 +72,7 @@ public:
inline void addMatch() { ++m_nummatches; }
inline bool operator == (const WinClient &win) const {
inline bool operator == (const Focusable &win) const {
return match(win);
}
@ -79,9 +83,9 @@ public:
* If there are no terms, then there is assumed to be an error
* the column of the error is stored in m_matchlimit
*/
inline int error() const { return m_terms.empty() ? m_matchlimit : 0; }
inline int error() const { return m_terms.empty() ? 1 : 0; }
std::string getProperty(WinProperty prop, const WinClient &winclient) const;
std::string getProperty(WinProperty prop, const Focusable &winclient) const;
private:
/**

View file

@ -220,12 +220,12 @@ void ClockTool::update(FbTk::Subject *subj) {
updateTime();
// + 2 to make the entire text fit inside
// we only replace numbers with zeros because everything else should be
// we only replace numbers with zeros because everything else should be
// relatively static. If we replace all text with zeros then widths of
// proportional fonts with some strftime formats will be considerably off.
std::string text(m_button.text());
int textlen = text.size();
int textlen = text.size();
for (int i=0; i < textlen; ++i) {
if (isdigit(text[i])) // don't bother replacing zeros
text[i] = '0';

View file

@ -27,7 +27,7 @@
#include "ScreenPlacement.hh"
#include "Window.hh"
bool ColSmartPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowlist,
bool ColSmartPlacement::placeWindow(const std::list<FluxboxWindow *> &windowlist,
const FluxboxWindow &win,
int &place_x, int &place_y) {
@ -85,9 +85,9 @@ bool ColSmartPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowli
next_y = test_y + change_y;
std::vector<FluxboxWindow *>::const_iterator it =
std::list<FluxboxWindow *>::const_iterator it =
windowlist.begin();
std::vector<FluxboxWindow *>::const_iterator it_end =
std::list<FluxboxWindow *>::const_iterator it_end =
windowlist.end();
for (; it != it_end && placed; ++it) {
int curr_x = (*it)->x() - (*it)->xOffset();

View file

@ -28,7 +28,7 @@
class ColSmartPlacement: public PlacementStrategy {
public:
bool placeWindow(const std::vector<FluxboxWindow *> &windowlist,
bool placeWindow(const std::list<FluxboxWindow *> &windowlist,
const FluxboxWindow &win,
int &place_x, int &place_y);
};

View file

@ -98,7 +98,7 @@ void CommandDialog::hide() {
// return focus to fluxbox window
if (FocusControl::focusedFbWindow())
FocusControl::focusedFbWindow()->setInputFocus();
FocusControl::focusedFbWindow()->focus();
}
@ -193,12 +193,12 @@ void CommandDialog::tabComplete() {
void CommandDialog::render() {
Pixmap tmp = m_pixmap;
if (!m_screen.winFrameTheme().labelFocusTexture().usePixmap()) {
m_label.setBackgroundColor(m_screen.winFrameTheme().labelFocusTexture().color());
if (!m_screen.winFrameTheme().iconbarTheme().focusedTexture().usePixmap()) {
m_label.setBackgroundColor(m_screen.winFrameTheme().iconbarTheme().focusedTexture().color());
m_pixmap = 0;
} else {
m_pixmap = m_screen.imageControl().renderImage(m_label.width(), m_label.height(),
m_screen.winFrameTheme().labelFocusTexture());
m_screen.winFrameTheme().iconbarTheme().focusedTexture());
m_label.setBackgroundPixmap(m_pixmap);
}
@ -213,7 +213,7 @@ void CommandDialog::init() {
// setup label
// we listen to motion notify too
m_label.setEventMask(m_label.eventMask() | ButtonPressMask | ButtonMotionMask);
m_label.setGC(m_screen.winFrameTheme().labelTextFocusGC());
m_label.setGC(m_screen.winFrameTheme().iconbarTheme().focusedText().textGC());
m_label.show();
// setup text box

View file

@ -34,14 +34,25 @@
class BScreen;
/**
* Displays a fluxbox command dialog which executes fluxbox
* action commands.
*/
class CommandDialog: public FbTk::FbWindow, public FbTk::EventHandler {
public:
CommandDialog(BScreen &screen, const std::string &title,
const std::string pre_command = "");
virtual ~CommandDialog();
/// Sets the entry text.
void setText(const std::string &text);
void setPostCommand(FbTk::RefCount<FbTk::Command> &postcommand) { m_postcommand = postcommand; }
/**
* Sets the command to be execute after the command is done.
* @param postcommand the command.
*/
void setPostCommand(FbTk::RefCount<FbTk::Command> &postcommand) {
m_postcommand = postcommand;
}
void show();
void hide();
@ -52,6 +63,7 @@ public:
void keyPressEvent(XKeyEvent &event);
protected:
/// expand the current word, using the history as a references
virtual void tabComplete();
private:
@ -59,8 +71,8 @@ private:
void render();
void updateSizes();
FbTk::TextBox m_textbox;
FbTk::TextButton m_label;
FbTk::TextBox m_textbox; //< entry field
FbTk::TextButton m_label; //< text in the titlebar
FbTk::GContext m_gc;
FbTk::RefCount<FbTk::Command> m_postcommand; ///< command to do after the first command was issued (like reconfigure)
BScreen &m_screen;

View file

@ -36,7 +36,6 @@ Container::Container(const FbTk::FbWindow &parent):
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);
}
@ -215,9 +214,6 @@ bool Container::removeItem(int index) {
for (; index != 0; ++it, --index)
continue;
if (*it == selected())
m_selected = 0;
m_item_list.erase(it);
repositionItems();
@ -225,7 +221,6 @@ bool Container::removeItem(int index) {
}
void Container::removeAll() {
m_selected = 0;
m_item_list.clear();
if (!m_update_lock) {
clear();
@ -248,19 +243,6 @@ int Container::find(ConstItem item) {
return index;
}
void Container::setSelected(int pos) {
if (pos < 0 || pos >= size())
m_selected = 0;
else {
ItemList::iterator it = m_item_list.begin();
for (; pos != 0; --pos, ++it)
continue;
m_selected = *it;
// caller does any graphics stuff if appropriate
}
}
void Container::setMaxSizePerClient(unsigned int size) {
if (size != m_max_size_per_client) {
m_max_size_per_client = size;

View file

@ -65,7 +65,6 @@ public:
void moveItem(Item item, int movement); // wraps around
bool moveItemTo(Item item, int x, int y);
int find(ConstItem item);
void setSelected(int index);
void setMaxSizePerClient(unsigned int size);
void setMaxTotalSize(unsigned int size);
void setAlignment(Alignment a);
@ -93,8 +92,6 @@ public:
inline FbTk::Orientation orientation() const { return m_orientation; }
inline int size() const { return m_item_list.size(); }
inline bool empty() const { return m_item_list.empty(); }
inline const Item& selected() const { return m_selected; }
inline Item selected() { return m_selected; }
unsigned int maxWidthPerClient() const;
inline bool updateLock() const { return m_update_lock; }
@ -115,7 +112,6 @@ private:
unsigned int m_max_size_per_client;
unsigned int m_max_total_size;
ItemList m_item_list;
Item m_selected;
bool m_update_lock;
};

View file

@ -31,17 +31,24 @@
#include "FocusControl.hh"
CurrentWindowCmd::CurrentWindowCmd(Action act):m_action(act) { }
void CurrentWindowCmd::execute() {
FluxboxWindow *win = FocusControl::focusedFbWindow();
if (win)
(win->*m_action)();
void WindowHelperCmd::execute() {
m_win = 0;
if (FocusControl::focusedFbWindow()) // guarantee that fbwindow() exists too
real_execute();
}
void WindowHelperCmd::execute(FluxboxWindow &win) {
m_win = &win;
real_execute();
}
void KillWindowCmd::real_execute() {
winclient().sendClose(true);
FluxboxWindow &WindowHelperCmd::fbwindow() {
// will exist from execute above
return (m_win ? *m_win : *FocusControl::focusedFbWindow());
}
void CurrentWindowCmd::real_execute() {
(fbwindow().*m_action)();
}
void SetHeadCmd::real_execute() {
@ -54,13 +61,14 @@ void SendToWorkspaceCmd::real_execute() {
void SendToNextWorkspaceCmd::real_execute() {
const int ws_nr =
( fbwindow().screen().currentWorkspaceID() + m_workspace_num ) %
( fbwindow().workspaceNumber() + m_workspace_num ) %
fbwindow().screen().numberOfWorkspaces();
fbwindow().screen().sendToWorkspace(ws_nr, &fbwindow(), false);
}
void SendToPrevWorkspaceCmd::real_execute() {
int ws_nr = fbwindow().screen().currentWorkspaceID() - m_workspace_num;
int ws_nr = (fbwindow().workspaceNumber() - m_workspace_num) %
fbwindow().screen().numberOfWorkspaces();
if ( ws_nr < 0 )
ws_nr += fbwindow().screen().numberOfWorkspaces();
fbwindow().screen().sendToWorkspace(ws_nr, &fbwindow(), false);
@ -72,13 +80,14 @@ void TakeToWorkspaceCmd::real_execute() {
void TakeToNextWorkspaceCmd::real_execute() {
unsigned int workspace_num=
( fbwindow().screen().currentWorkspaceID() + m_workspace_num ) %
( fbwindow().workspaceNumber() + m_workspace_num ) %
fbwindow().screen().numberOfWorkspaces();
fbwindow().screen().sendToWorkspace(workspace_num, &fbwindow());
}
void TakeToPrevWorkspaceCmd::real_execute() {
int workspace_num= fbwindow().screen().currentWorkspaceID() - m_workspace_num;
int workspace_num = (fbwindow().workspaceNumber() - m_workspace_num) %
fbwindow().screen().numberOfWorkspaces();
if ( workspace_num < 0 )
workspace_num += fbwindow().screen().numberOfWorkspaces();
fbwindow().screen().sendToWorkspace(workspace_num, &fbwindow());
@ -97,21 +106,6 @@ void GoToTabCmd::real_execute() {
(*it)->focus();
}
void WindowHelperCmd::execute() {
if (FocusControl::focusedFbWindow()) // guarantee that fbwindow() exists too
real_execute();
}
WinClient &WindowHelperCmd::winclient() {
// will exist from execute above
return *FocusControl::focusedWindow();
}
FluxboxWindow &WindowHelperCmd::fbwindow() {
// will exist from execute above
return *FocusControl::focusedFbWindow();
}
MoveCmd::MoveCmd(const int step_size_x, const int step_size_y) :
m_step_size_x(step_size_x), m_step_size_y(step_size_y) { }

View file

@ -28,36 +28,33 @@
#include "Command.hh"
class FluxboxWindow;
class WinClient;
/// command that calls FluxboxWindow::<the function> on execute()
/// similar to FbTk::SimpleCommand<T>
class CurrentWindowCmd: public FbTk::Command {
public:
typedef void (FluxboxWindow::* Action)();
explicit CurrentWindowCmd(Action action);
void execute();
private:
Action m_action;
};
/// helper class for window commands
/// calls real_execute if there's a focused window or a window in button press/release window
class WindowHelperCmd: public FbTk::Command {
public:
explicit WindowHelperCmd(FluxboxWindow *win = 0): m_win(win) { }
void execute();
void execute(FluxboxWindow &fbwin);
protected:
WinClient &winclient();
FluxboxWindow &fbwindow();
virtual void real_execute() = 0;
private:
FluxboxWindow *m_win;
};
class KillWindowCmd: public WindowHelperCmd {
protected:
/// command that calls FluxboxWindow::<the function> on execute()
/// similar to FbTk::SimpleCommand<T>
class CurrentWindowCmd: public WindowHelperCmd {
public:
typedef void (FluxboxWindow::* Action)();
explicit CurrentWindowCmd(Action action): m_action(action) { }
void real_execute();
private:
Action m_action;
};
class SetHeadCmd : public WindowHelperCmd {

View file

@ -28,7 +28,6 @@
#include "WinClient.hh"
#include "Workspace.hh"
#include "Layer.hh"
#include "WinClientUtil.hh"
#include "fluxbox.hh"
#include "FbWinFrameTheme.hh"
#include "FocusControl.hh"
@ -79,13 +78,6 @@ Ewmh::Ewmh() {
createAtoms();
}
Ewmh::~Ewmh() {
while (!m_windows.empty()) {
XDestroyWindow(FbTk::App::instance()->display(), m_windows.back());
m_windows.pop_back();
}
}
void Ewmh::initForScreen(BScreen &screen) {
Display *disp = FbTk::App::instance()->display();
@ -108,14 +100,9 @@ void Ewmh::initForScreen(BScreen &screen) {
* Window Manager is present.
*/
Window wincheck = XCreateSimpleWindow(disp,
screen.rootWindow().window(),
-10, -10, 5, 5, 0, 0, 0);
Window wincheck = screen.dummyWindow().window();
if (wincheck != None) {
// store the window so we can delete it later
m_windows.push_back(wincheck);
screen.rootWindow().changeProperty(m_net_supporting_wm_check, XA_WINDOW, 32,
PropModeReplace, (unsigned char *) &wincheck, 1);
XChangeProperty(disp, wincheck, m_net_supporting_wm_check, XA_WINDOW, 32,
@ -278,7 +265,7 @@ void Ewmh::setupFrame(FluxboxWindow &win) {
// we also assume it shouldn't be visible in any toolbar
win.setFocusHidden(true);
win.setIconHidden(true);
win.setDecoration(FluxboxWindow::DECOR_NONE);
win.setDecorationMask(FluxboxWindow::DECOR_NONE);
win.moveToLayer(Layer::DOCK);
} else if (atoms[l] == m_net_wm_window_type_desktop) {
/*
@ -291,7 +278,7 @@ void Ewmh::setupFrame(FluxboxWindow &win) {
win.setFocusHidden(true);
win.setIconHidden(true);
win.moveToLayer(Layer::DESKTOP);
win.setDecorationMask(0);
win.setDecorationMask(FluxboxWindow::DECOR_NONE);
win.setTabable(false);
win.setMovable(false);
win.setResizable(false);
@ -303,7 +290,7 @@ void Ewmh::setupFrame(FluxboxWindow &win) {
* window is a splash screen displayed as an application
* is starting up.
*/
win.setDecoration(FluxboxWindow::DECOR_NONE);
win.setDecorationMask(FluxboxWindow::DECOR_NONE);
win.setFocusHidden(true);
win.setIconHidden(true);
win.setMovable(false);
@ -320,11 +307,11 @@ void Ewmh::setupFrame(FluxboxWindow &win) {
* application). Windows of this type may set the
* WM_TRANSIENT_FOR hint indicating the main application window.
*/
win.setDecoration(FluxboxWindow::DECOR_TOOL);
win.setDecorationMask(FluxboxWindow::DECOR_TOOL);
win.setIconHidden(true);
win.moveToLayer(Layer::ABOVE_DOCK);
} else if (atoms[l] == m_net_wm_window_type_toolbar) {
win.setDecoration(FluxboxWindow::DECOR_NONE);
win.setDecorationMask(FluxboxWindow::DECOR_NONE);
win.setIconHidden(true);
win.moveToLayer(Layer::ABOVE_DOCK);
}
@ -402,7 +389,10 @@ void Ewmh::updateClientClose(WinClient &winclient){
void Ewmh::updateClientList(BScreen &screen) {
list<WinClient *> creation_order_list = screen.focusControl().creationOrderList();
if (screen.isShuttingdown())
return;
list<Focusable *> creation_order_list = screen.focusControl().creationOrderList();
size_t num = creation_order_list.size();
Window *wl = FB_new_nothrow Window[num];
@ -414,10 +404,13 @@ void Ewmh::updateClientList(BScreen &screen) {
}
int win=0;
list<WinClient *>::iterator client_it = creation_order_list.begin();
list<WinClient *>::iterator client_it_end = creation_order_list.end();
for (; client_it != client_it_end; ++client_it)
wl[win++] = (*client_it)->window();
list<Focusable *>::iterator client_it = creation_order_list.begin();
list<Focusable *>::iterator client_it_end = creation_order_list.end();
for (; client_it != client_it_end; ++client_it) {
WinClient *client = dynamic_cast<WinClient *>(*client_it);
if (client)
wl[win++] = client->window();
}
/* From Extended Window Manager Hints, draft 1.3:
*
@ -800,32 +793,12 @@ bool Ewmh::checkClientMessage(const XClientMessageEvent &ce,
return true;
// ce.window = window to focus
if (winclient->fbwindow()) {
FluxboxWindow* fbwin = winclient->fbwindow();
// if the raised window is on a different workspace
// we do what the user wish:
// either ignore|go to that workspace|get the window
if (fbwin->screen().currentWorkspaceID() != fbwin->workspaceNumber()
&& !fbwin->isStuck()) {
BScreen::FollowModel model = (ce.data.l[0] == 2) ?
fbwin->screen().getUserFollowModel() :
fbwin->screen().getFollowModel();
if (model == BScreen::FOLLOW_ACTIVE_WINDOW) {
fbwin->screen().changeWorkspaceID(fbwin->workspaceNumber());
} else if (model == BScreen::FETCH_ACTIVE_WINDOW) {
fbwin->screen().sendToWorkspace(fbwin->screen().currentWorkspaceID(), fbwin);
} else if (model == BScreen::SEMIFOLLOW_ACTIVE_WINDOW) {
if (fbwin->isIconic())
fbwin->screen().sendToWorkspace(fbwin->screen().currentWorkspaceID(), fbwin);
else
fbwin->screen().changeWorkspaceID(fbwin->workspaceNumber());
} // else we ignore it. my favourite mode :)
}
fbwin->raise();
// ce.data.l[0] == 2 means the request came from a pager
if (winclient->fbwindow() && (ce.data.l[0] == 2 ||
winclient->fbwindow()->allowsFocusFromClient())) {
winclient->focus();
winclient->fbwindow()->raise();
}
winclient->focus();
return true;
} else if (ce.message_type == m_net_close_window) {
if (winclient == 0)
@ -1203,7 +1176,7 @@ void Ewmh::updateActions(FluxboxWindow &win) {
actions.push_back(m_net_wm_action_minimize);
unsigned int max_width, max_height;
WinClientUtil::maxSize(win.clientList(), max_width, max_height);
win.maxSize(max_width, max_height);
// if unlimited max width we can maximize horizontal
if (max_width == 0) {

View file

@ -34,7 +34,6 @@ class Ewmh:public AtomHandler {
public:
Ewmh();
~Ewmh();
void initForScreen(BScreen &screen);
void setupFrame(FluxboxWindow &win);
void setupClient(WinClient &winclient);
@ -145,7 +144,5 @@ private:
Atom utf8_string;
std::vector<Window> m_windows;
FbTk::FbString getUTF8Property(Atom property);
};

View file

@ -60,35 +60,6 @@ void FbAtoms::initAtoms() {
xa_wm_take_focus = XInternAtom(display, "WM_TAKE_FOCUS", False);
motif_wm_hints = XInternAtom(display, "_MOTIF_WM_HINTS", False);
blackbox_hints = XInternAtom(display, "_BLACKBOX_HINTS", False);
blackbox_attributes = XInternAtom(display, "_BLACKBOX_ATTRIBUTES", False);
blackbox_change_attributes =
XInternAtom(display, "_BLACKBOX_CHANGE_ATTRIBUTES", False);
blackbox_structure_messages =
XInternAtom(display, "_BLACKBOX_STRUCTURE_MESSAGES", False);
blackbox_notify_startup =
XInternAtom(display, "_BLACKBOX_NOTIFY_STARTUP", False);
blackbox_notify_window_add =
XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_ADD", False);
blackbox_notify_window_del =
XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_DEL", False);
blackbox_notify_current_workspace =
XInternAtom(display, "_BLACKBOX_NOTIFY_CURRENT_WORKSPACE", False);
blackbox_notify_workspace_count =
XInternAtom(display, "_BLACKBOX_NOTIFY_WORKSPACE_COUNT", False);
blackbox_notify_window_focus =
XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_FOCUS", False);
blackbox_notify_window_raise =
XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_RAISE", False);
blackbox_notify_window_lower =
XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_LOWER", False);
blackbox_change_workspace =
XInternAtom(display, "_BLACKBOX_CHANGE_WORKSPACE", False);
blackbox_change_window_focus =
XInternAtom(display, "_BLACKBOX_CHANGE_WINDOW_FOCUS", False);
blackbox_cycle_window_focus =
XInternAtom(display, "_BLACKBOX_CYCLE_WINDOW_FOCUS", False);
}

View file

@ -40,57 +40,18 @@ public:
inline Atom getWMProtocolsAtom() const { return xa_wm_protocols; }
inline Atom getWMTakeFocusAtom() const { return xa_wm_take_focus; }
// this atom is for normal app->WM hints about decorations, stacking,
// starting workspace etc...
inline Atom getFluxboxHintsAtom() const { return blackbox_hints;}
inline Atom getMWMHintsAtom() const { return motif_wm_hints; }
// these atoms are for normal app->WM interaction beyond the scope of the
// ICCCM...
inline Atom getFluxboxAttributesAtom() const { return blackbox_attributes; }
inline Atom getFluxboxChangeAttributesAtom() const { return blackbox_change_attributes; }
// these atoms are for window->WM interaction, with more control and
// information on window "structure"... common examples are
// notifying apps when windows are raised/lowered... when the user changes
// workspaces... i.e. "pager talk"
inline Atom getFluxboxStructureMessagesAtom() const{ return blackbox_structure_messages; }
// *Notify* portions of the NETStructureMessages protocol
inline Atom getFluxboxNotifyStartupAtom() const { return blackbox_notify_startup; }
inline Atom getFluxboxNotifyWindowAddAtom() const { return blackbox_notify_window_add; }
inline Atom getFluxboxNotifyWindowDelAtom() const { return blackbox_notify_window_del; }
inline Atom getFluxboxNotifyWindowFocusAtom() const { return blackbox_notify_window_focus; }
inline Atom getFluxboxNotifyCurrentWorkspaceAtom() const { return blackbox_notify_current_workspace; }
inline Atom getFluxboxNotifyWorkspaceCountAtom() const { return blackbox_notify_workspace_count; }
inline Atom getFluxboxNotifyWindowRaiseAtom() const { return blackbox_notify_window_raise; }
inline Atom getFluxboxNotifyWindowLowerAtom() const { return blackbox_notify_window_lower; }
// atoms to change that request changes to the desktop environment during
// runtime... these messages can be sent by any client... as the sending
// client window id is not included in the ClientMessage event...
inline Atom getFluxboxChangeWorkspaceAtom() const { return blackbox_change_workspace; }
inline Atom getFluxboxChangeWindowFocusAtom() const { return blackbox_change_window_focus; }
inline Atom getFluxboxCycleWindowFocusAtom() const { return blackbox_cycle_window_focus; }
private:
void initAtoms();
// NETAttributes
Atom blackbox_attributes, blackbox_change_attributes, blackbox_hints;
Atom blackbox_attributes;
Atom motif_wm_hints;
// NETStructureMessages
Atom blackbox_structure_messages, blackbox_notify_startup,
blackbox_notify_window_add, blackbox_notify_window_del,
blackbox_notify_window_focus, blackbox_notify_current_workspace,
blackbox_notify_workspace_count, blackbox_notify_window_raise,
blackbox_notify_window_lower;
// message_types for client -> wm messages
Atom blackbox_change_workspace, blackbox_change_window_focus,
blackbox_cycle_window_focus;
Atom xa_wm_protocols, xa_wm_state,
xa_wm_delete_window, xa_wm_take_focus, xa_wm_change_state;

View file

@ -52,17 +52,43 @@ using std::endl;
// autoregister this module to command parser
FbCommandFactory FbCommandFactory::s_autoreg;
namespace {
static int getint(const char *str, int defaultvalue) {
sscanf(str, "%d", &defaultvalue);
return defaultvalue;
}
void parseNextWindowArgs(const string &in, int &opts, string &pat) {
string options;
int err = FbTk::StringUtil::getStringBetween(options, in.c_str(), '{', '}');
// the rest of the string is a ClientPattern
pat = in.c_str() + err;
// now parse the options
vector<string> args;
FbTk::StringUtil::stringtok(args, options);
vector<string>::iterator it = args.begin(), it_end = args.end();
opts = 0;
for (; it != it_end; ++it) {
if (strcasecmp((*it).c_str(), "static") == 0)
opts |= FocusControl::CYCLELINEAR;
else if (strcasecmp((*it).c_str(), "groups") == 0)
opts |= FocusControl::CYCLEGROUPS;
}
}
}; // end anonymous namespace
FbCommandFactory::FbCommandFactory() {
// setup commands that we can handle
const char* commands[] = {
"addworkspace",
"addworkspace",
"arrangewindows",
"attach",
"bindkey",
"clientmenu",
"close",
"closeallwindows",
"commanddialog",
@ -79,6 +105,7 @@ FbCommandFactory::FbCommandFactory() {
"focusleft",
"focusright",
"fullscreen",
"gotowindow",
"hidemenus",
"iconify",
"keymode",
@ -116,7 +143,7 @@ FbCommandFactory::FbCommandFactory() {
"reconfig",
"reconfigure",
"reloadstyle",
"removelastworkspace",
"removelastworkspace",
"resizeto",
"resize",
"resizehorizontal",
@ -148,6 +175,7 @@ FbCommandFactory::FbCommandFactory() {
"taketoprevworkspace",
"togglecmd",
"toggledecor",
"typeaheadfocus",
"windowmenu",
"workspace",
/* NOTE: The following are DEPRECATED and subject to removal */
@ -243,21 +271,15 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command,
// Current focused window commands
//
else if (command == "fullscreen")
return new FullscreenCmd();
else if (command == "minimizewindow" || command == "minimize" || command == "iconify") {
string cmd;
if (FbTk::StringUtil::getStringBetween(cmd, arguments.c_str() +
0, '(', ')', " \t\n", true)
&& cmd == "layer")
return new MinimizeLayerCmd();
else
return new CurrentWindowCmd(&FluxboxWindow::iconify);
} else if (command == "maximizewindow" || command == "maximize")
return new CurrentWindowCmd(&FluxboxWindow::maximizeFull);
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new FullscreenCmd()), arguments);
else if (command == "minimizewindow" || command == "minimize" || command == "iconify")
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new CurrentWindowCmd(&FluxboxWindow::iconify)), arguments);
else if (command == "maximizewindow" || command == "maximize")
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new CurrentWindowCmd(&FluxboxWindow::maximizeFull)), arguments);
else if (command == "maximizevertical")
return new CurrentWindowCmd(&FluxboxWindow::maximizeVertical);
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new CurrentWindowCmd(&FluxboxWindow::maximizeVertical)), arguments);
else if (command == "maximizehorizontal")
return new CurrentWindowCmd(&FluxboxWindow::maximizeHorizontal);
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new CurrentWindowCmd(&FluxboxWindow::maximizeHorizontal)), arguments);
else if (command == "setalpha") {
typedef vector<string> StringTokens;
StringTokens tokens;
@ -279,24 +301,37 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command,
unfocused = atoi(tokens[1].c_str());
}
return new SetAlphaCmd(focused, relative, unfocused, un_rel);
} else if (command == "resize") {
string pat;
string::size_type pos = arguments.find('(');
if (pos != string::npos && pos != arguments.size())
pat = arguments.c_str() + pos;
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new SetAlphaCmd(focused, relative, unfocused, un_rel)), pat);
} else if (command == "resize" || command == "resizeto" ||
command == "resizehorizontal" || command == "resizevertical") {
FbTk_istringstream is(arguments.c_str());
int dx = 0, dy = 0;
is >> dx >> dy;
return new ResizeCmd(dx, dy);
}
else if (command == "resizeto") {
FbTk_istringstream is(arguments.c_str());
int dx = 0, dy = 0;
is >> dx >> dy;
return new ResizeToCmd(dx, dy);
}
else if (command == "resizehorizontal")
return new ResizeCmd(atoi(arguments.c_str()),0);
else if (command == "resizevertical")
return new ResizeCmd(0,atoi(arguments.c_str()));
else if (command == "moveto") {
if (command == "resizehorizontal")
dy = 0;
else if (command == "resizevertical") {
dy = dx;
dx = 0;
}
string pat;
string::size_type pos = arguments.find('(');
if (pos != string::npos && pos != arguments.size())
pat = arguments.c_str() + pos;
FbTk::RefCount<WindowHelperCmd> cmd;
if (command == "resizeto")
cmd = new ResizeToCmd(dx, dy);
else
cmd = new ResizeCmd(dx, dy);
return new WindowListCmd(cmd, pat);
} else if (command == "moveto") {
typedef vector<string> StringTokens;
StringTokens tokens;
FbTk::StringUtil::stringtok<StringTokens>(tokens, arguments);
@ -339,70 +374,107 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command,
}
}
return new MoveToCmd(dx, dy, refc);
}
else if (command == "move") {
string pat;
string::size_type pos = arguments.find('(');
if (pos != string::npos && pos != arguments.size())
pat = arguments.c_str() + pos;
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new MoveToCmd(dx, dy, refc)), pat);
} else if (command == "move" || command == "moveright" ||
command == "moveleft" || command == "moveup" ||
command == "movedown") {
FbTk_istringstream is(arguments.c_str());
int dx = 0, dy = 0;
is >> dx >> dy;
return new MoveCmd(dx, dy);
}
else if (command == "moveright")
return new MoveCmd(atoi(arguments.c_str()),0);
else if (command == "moveleft")
return new MoveCmd(-atoi(arguments.c_str()),0);
else if (command == "moveup")
return new MoveCmd(0,-atoi(arguments.c_str()));
else if (command == "movedown")
return new MoveCmd(0,atoi(arguments.c_str()));
else if (command == "raise")
return new CurrentWindowCmd(&FluxboxWindow::raise);
if (command == "moveright")
dy = 0;
else if (command == "moveleft") {
dy = 0;
dx = -dx;
} else if (command == "movedown") {
dy = dx;
dx = 0;
} else if (command == "moveup") {
dy = -dx;
dx = 0;
}
string pat;
string::size_type pos = arguments.find('(');
if (pos != string::npos && pos != arguments.size())
pat = arguments.c_str() + pos;
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new MoveCmd(dx, dy)), pat);
} else if (command == "raise")
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new CurrentWindowCmd(&FluxboxWindow::raise)), arguments);
else if (command == "raiselayer")
return new CurrentWindowCmd(&FluxboxWindow::raiseLayer);
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new CurrentWindowCmd(&FluxboxWindow::raiseLayer)), arguments);
else if (command == "lower")
return new CurrentWindowCmd(&FluxboxWindow::lower);
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new CurrentWindowCmd(&FluxboxWindow::lower)), arguments);
else if (command == "lowerlayer")
return new CurrentWindowCmd(&FluxboxWindow::lowerLayer);
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new CurrentWindowCmd(&FluxboxWindow::lowerLayer)), arguments);
else if (command == "close")
return new CurrentWindowCmd(&FluxboxWindow::close);
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new CurrentWindowCmd(&FluxboxWindow::close)), arguments);
else if (command == "closeallwindows")
return new CloseAllWindowsCmd();
else if (command == "shade" || command == "shadewindow")
return new CurrentWindowCmd(&FluxboxWindow::shade);
else if (command == "stick" || command == "stickwindow")
return new CurrentWindowCmd(&FluxboxWindow::stick);
else if (command == "toggledecor")
return new CurrentWindowCmd(&FluxboxWindow::toggleDecoration);
else if (command == "sethead")
return new SetHeadCmd(atoi(arguments.c_str()));
else if (command == "sendtoworkspace")
// workspaces appear 1-indexed to the user, hence the minus 1
return new SendToWorkspaceCmd(getint(arguments.c_str(), 1) - 1);
else if (command == "sendtonextworkspace")
return new SendToNextWorkspaceCmd(getint(arguments.c_str(), 1));
else if (command == "sendtoprevworkspace")
return new SendToPrevWorkspaceCmd(getint(arguments.c_str(), 1));
else if (command == "taketoworkspace")
// workspaces appear 1-indexed to the user, hence the minus 1
return new TakeToWorkspaceCmd(getint(arguments.c_str(), 1) - 1);
else if (command == "taketonextworkspace")
return new TakeToNextWorkspaceCmd(getint(arguments.c_str(), 1));
else if (command == "taketoprevworkspace")
return new TakeToPrevWorkspaceCmd(getint(arguments.c_str(), 1));
else if (command == "killwindow" || command == "kill")
return new KillWindowCmd();
else if (command == "tab")
return new GoToTabCmd(getint(arguments.c_str(), 1));
else if (command == "nexttab")
return new CurrentWindowCmd(&FluxboxWindow::nextClient);
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new CurrentWindowCmd(&FluxboxWindow::kill)), arguments);
else if (command == "shade" || command == "shadewindow")
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new CurrentWindowCmd(&FluxboxWindow::shade)), arguments);
else if (command == "stick" || command == "stickwindow")
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new CurrentWindowCmd(&FluxboxWindow::stick)), arguments);
else if (command == "toggledecor")
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new CurrentWindowCmd(&FluxboxWindow::toggleDecoration)), arguments);
else if (command == "sethead") {
int num = 0;
string pat;
FbTk_istringstream iss(arguments.c_str());
iss >> num;
string::size_type pos = arguments.find('(');
if (pos != string::npos && pos != arguments.size())
pat = arguments.c_str() + pos;
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new SetHeadCmd(num)), pat);
} else if (command == "tab" || command == "sendtonextworkspace" ||
command == "sendtoprevworkspace" ||
command == "taketonextworkspace" ||
command == "taketoprevworkspace" ||
command == "sendtoworkspace" || command == "taketoworkspace") {
// workspaces appear 1-indexed to the user, hence the minus 1
int num = 1;
string pat;
FbTk_istringstream iss(arguments.c_str());
iss >> num;
string::size_type pos = arguments.find('(');
if (pos != string::npos && pos != arguments.size())
pat = arguments.c_str() + pos;
FbTk::RefCount<WindowHelperCmd> cmd;
if (command == "tab")
cmd = new GoToTabCmd(num);
else if (command == "sendtonextworkspace")
cmd = new SendToNextWorkspaceCmd(num);
else if (command == "sendtoprevworkspace")
cmd = new SendToPrevWorkspaceCmd(num);
else if (command == "taketonextworkspace")
cmd = new TakeToNextWorkspaceCmd(num);
else if (command == "taketoprevworkspace")
cmd = new TakeToPrevWorkspaceCmd(num);
else if (command == "sendtoworkspace")
cmd = new SendToWorkspaceCmd(num-1);
else
cmd = new TakeToWorkspaceCmd(num-1);
return new WindowListCmd(cmd, pat);
} else if (command == "nexttab")
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new CurrentWindowCmd(&FluxboxWindow::nextClient)), arguments);
else if (command == "prevtab")
return new CurrentWindowCmd(&FluxboxWindow::prevClient);
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new CurrentWindowCmd(&FluxboxWindow::prevClient)), arguments);
else if (command == "movetableft")
return new CurrentWindowCmd(&FluxboxWindow::moveClientLeft);
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new CurrentWindowCmd(&FluxboxWindow::moveClientLeft)), arguments);
else if (command == "movetabright")
return new CurrentWindowCmd(&FluxboxWindow::moveClientRight);
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new CurrentWindowCmd(&FluxboxWindow::moveClientRight)), arguments);
else if (command == "detachclient")
return new CurrentWindowCmd(&FluxboxWindow::detachCurrentClient);
return new WindowListCmd(FbTk::RefCount<WindowHelperCmd>(new CurrentWindowCmd(&FluxboxWindow::detachCurrentClient)), arguments);
else if (command == "windowmenu")
return new CurrentWindowCmd(&FluxboxWindow::popupMenu);
//
@ -423,11 +495,54 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command,
cerr<<"*** WARNING: 'Workspace<n>' actions are deprecated! Use 'Workspace <n>' instead"<<endl;
return new JumpToWorkspaceCmd(getint(command.substr(9).c_str(), 1) - 1);
} else if (command == "nextwindow")
return new NextWindowCmd(atoi(arguments.c_str()));
else if (command == "prevwindow")
return new PrevWindowCmd(atoi(arguments.c_str()));
else if (command == "focusup")
} else if (command == "attach") {
int opts; // not used
string pat;
parseNextWindowArgs(arguments, opts, pat);
return new AttachCmd(pat);
} else if (command == "nextwindow") {
int opts;
string pat;
parseNextWindowArgs(arguments, opts, pat);
return new NextWindowCmd(opts, pat);
} else if (command == "nextgroup") {
int opts;
string pat;
parseNextWindowArgs(arguments, opts, pat);
opts |= FocusControl::CYCLEGROUPS;
return new NextWindowCmd(opts, pat);
} else if (command == "prevwindow") {
int opts;
string pat;
parseNextWindowArgs(arguments, opts, pat);
return new PrevWindowCmd(opts, pat);
} else if (command == "prevgroup") {
int opts;
string pat;
parseNextWindowArgs(arguments, opts, pat);
opts |= FocusControl::CYCLEGROUPS;
return new PrevWindowCmd(opts, pat);
} else if (command == "typeaheadfocus") {
int opts;
string pat;
parseNextWindowArgs(arguments, opts, pat);
return new TypeAheadFocusCmd(opts, pat);
} else if (command == "gotowindow") {
int num, opts;
string args, pat;
FbTk_istringstream iss(arguments.c_str());
iss >> num;
string::size_type pos = arguments.find_first_of("({");
if (pos != string::npos && pos != arguments.size())
args = arguments.c_str() + pos;
parseNextWindowArgs(args, opts, pat);
return new GoToWindowCmd(num, opts, pat);
} else if (command == "clientmenu") {
int opts;
string pat;
parseNextWindowArgs(arguments, opts, pat);
return new ShowClientMenuCmd(opts, pat);
} else if (command == "focusup")
return new DirFocusCmd(FocusControl::FOCUSUP);
else if (command == "focusdown")
return new DirFocusCmd(FocusControl::FOCUSDOWN);
@ -435,10 +550,6 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command,
return new DirFocusCmd(FocusControl::FOCUSLEFT);
else if (command == "focusright")
return new DirFocusCmd(FocusControl::FOCUSRIGHT);
else if (command == "nextgroup")
return new NextWindowCmd(atoi(arguments.c_str()) ^ FocusControl::CYCLEGROUPS);
else if (command == "prevgroup")
return new PrevWindowCmd(atoi(arguments.c_str()) ^ FocusControl::CYCLEGROUPS);
else if (command == "arrangewindows")
return new ArrangeWindowsCmd();
else if (command == "showdesktop")

View file

@ -25,6 +25,7 @@
#include "fluxbox.hh"
#include "Screen.hh"
#include "CommandDialog.hh"
#include "FocusControl.hh"
#include "Workspace.hh"
#include "Window.hh"
#include "Keys.hh"
@ -279,6 +280,35 @@ void HideMenuCmd::execute() {
FbTk::Menu::shownMenu()->hide();
}
void ShowClientMenuCmd::execute() {
BScreen *screen = Fluxbox::instance()->mouseScreen();
if (screen == 0)
return;
// TODO: ClientMenu only accepts lists of FluxboxWindows for now
FocusControl::Focusables *win_list = 0;
// if (m_option & FocusControl::CYCLEGROUPS) {
win_list = (m_option & FocusControl::CYCLELINEAR) ?
&screen->focusControl().creationOrderWinList() :
&screen->focusControl().focusedOrderWinList();
/* } else {
win_list = (m_option & FocusControl::CYCLELINEAR) ?
&screen->focusControl().creationOrderList() :
&screen->focusControl().focusedOrderList();
} */
m_list.clear();
FocusControl::Focusables::iterator it = win_list->begin(),
it_end = win_list->end();
for (; it != it_end; ++it) {
if (typeid(**it) == typeid(FluxboxWindow) && m_pat.match(**it))
m_list.push_back(static_cast<FluxboxWindow *>(*it));
}
m_menu = new ClientMenu(*screen, m_list, 0);
::showMenu(*screen, **m_menu);
}
ShowCustomMenuCmd::ShowCustomMenuCmd(const string &arguments) : custom_menu_file(arguments) {}
void ShowCustomMenuCmd::execute() {

View file

@ -29,8 +29,10 @@
#include "Command.hh"
#include "FbTk/RefCount.hh"
#include "FbTk/Menu.hh"
#include "ClientMenu.hh"
#include "ClientPattern.hh"
#include <list>
#include <string>
namespace FbCommands {
@ -121,6 +123,18 @@ public:
void execute();
};
class ShowClientMenuCmd: public FbTk::Command {
public:
ShowClientMenuCmd(int option, std::string &pat):
m_option(option), m_pat(pat.c_str()) { }
void execute();
private:
const int m_option;
const ClientPattern m_pat;
std::list<FluxboxWindow *> m_list;
FbTk::RefCount<ClientMenu> m_menu;
};
class ShowCustomMenuCmd: public FbTk::Command {
public:
explicit ShowCustomMenuCmd(const std::string &arguments);

View file

@ -19,6 +19,8 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id$
#ifndef FBTK_ITYPEAHEADABLE_HH
#define FBTK_ITYPEAHEADABLE_HH

View file

@ -49,7 +49,6 @@ libFbTk_a_SOURCES = App.hh App.cc Color.cc Color.hh Command.hh \
GContext.hh GContext.cc \
KeyUtil.hh KeyUtil.cc \
MenuSeparator.hh MenuSeparator.cc \
MenuIcon.hh MenuIcon.cc \
stringstream.hh \
TypeAhead.hh SearchResult.hh SearchResult.cc ITypeAheadable.hh \
Select2nd.hh \

View file

@ -357,10 +357,6 @@ void Menu::enterSubmenu() {
submenu->cycleItems(false);
}
void Menu::enterParent() {
internal_hide();
}
void Menu::disableTitle() {
setTitleVisibility(false);
}
@ -1033,7 +1029,7 @@ void Menu::keyPressEvent(XKeyEvent &event) {
break;
case XK_Left: // enter parent if we have one
resetTypeAhead();
enterParent();
internal_hide();
break;
case XK_Right: // enter submenu if we have one
resetTypeAhead();
@ -1046,7 +1042,7 @@ void Menu::keyPressEvent(XKeyEvent &event) {
break;
case XK_BackSpace:
if (m_type_ahead.stringSize() == 0) {
enterParent();
internal_hide();
break;
}

View file

@ -49,7 +49,8 @@ class MenuItem;
class ImageControl;
/// Base class for menus
class Menu: public FbTk::EventHandler, FbTk::FbWindowRenderer, protected FbTk::Observer {
class Menu: public FbTk::EventHandler, FbTk::FbWindowRenderer,
public FbTk::Observer {
public:
enum Alignment{ ALIGNDONTCARE = 1, ALIGNTOP, ALIGNBOTTOM };
enum { RIGHT = 1, LEFT };
@ -91,7 +92,6 @@ public:
/// cycle through menuitems
void cycleItems(bool reverse);
void enterSubmenu();
void enterParent();
void disableTitle();
void enableTitle();
@ -193,7 +193,7 @@ protected:
virtual void internal_hide(bool first = true);
void update(FbTk::Subject *);
virtual void update(FbTk::Subject *);
private:

View file

@ -1,96 +0,0 @@
// MenuIcon.cc for FbTk - Fluxbox ToolKit
// Copyright (c) 2004 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org)
// and Simon Bowden (rathnor at users.sourceforge.net)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id$
#include "MenuIcon.hh"
#include "MenuTheme.hh"
#include "Image.hh"
#include "App.hh"
namespace FbTk {
MenuIcon::MenuIcon(const std::string &filename, FbString &label, int screen_num):
MenuItem(label),
m_filename(filename) {
FbTk::PixmapWithMask *pm = Image::load(filename.c_str(), screen_num);
if (pm != 0) {
m_pixmap = pm->pixmap().release();
m_mask = pm->mask().release();
delete pm;
}
}
void MenuIcon::updateTheme(const MenuTheme &theme) {
FbTk::PixmapWithMask *pm = Image::load(m_filename.c_str(), theme.screenNum());
if (pm != 0) {
m_pixmap = pm->pixmap().release();
m_mask = pm->mask().release();
delete pm;
}
}
void MenuIcon::draw(FbDrawable &drawable,
const MenuTheme &theme,
bool highlight, bool draw_foreground, bool draw_background,
int x, int y,
unsigned int width, unsigned int height) const {
// all background
if (draw_background) {
Display *disp = FbTk::App::instance()->display();
if (height - 2*theme.bevelWidth() != m_pixmap.height() &&
!m_filename.empty()) {
unsigned int scale_size = height - 2*theme.bevelWidth();
m_pixmap.scale(scale_size, scale_size);
m_mask.scale(scale_size, scale_size);
}
if (m_pixmap.drawable() != 0) {
GC gc = theme.frameTextGC().gc();
// enable clip mask
XSetClipMask(disp, gc, m_mask.drawable());
XSetClipOrigin(disp, gc, x + theme.bevelWidth(), y + theme.bevelWidth());
drawable.copyArea(m_pixmap.drawable(),
gc,
0, 0,
x + theme.bevelWidth(), y + theme.bevelWidth(),
m_pixmap.width(), m_pixmap.height());
// restore clip mask
XSetClipMask(disp, gc, None);
}
}
FbTk::MenuItem::draw(drawable, theme, highlight,
draw_background, draw_foreground, x, y, width, height);
}
unsigned int MenuIcon::width(const MenuTheme &theme) const {
return MenuItem::width(theme) + 2 * (theme.bevelWidth() + height(theme));
}
} // end namespace FbTk

View file

@ -1,54 +0,0 @@
// MenuIcon.hh for FbTk - Fluxbox ToolKit
// Copyright (c) 2004 Henrik Kinnunen (fluxgen at fluxbox dot org)
// and Simon Bowden (rathnor at users.sourceforge.net)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id$
#ifndef MENUICON_HH
#define MENUICON_HH
#include "MenuItem.hh"
#include "FbPixmap.hh"
#include <string>
namespace FbTk {
class MenuIcon: public MenuItem {
public:
MenuIcon(const std::string &filename, FbString &label, int screen_num);
void draw(FbDrawable &drawable,
const MenuTheme &theme,
bool highlight,
bool draw_foreground, bool draw_background,
int x, int y,
unsigned int width, unsigned int height) const;
unsigned int width(const MenuTheme &item) const;
void updateTheme(const MenuTheme &theme);
private:
mutable FbPixmap m_pixmap, m_mask;
const std::string m_filename;
};
} // end namespace FbTk
#endif // MENUICON_HH

View file

@ -93,27 +93,32 @@ void MenuItem::draw(FbDrawable &draw,
// Icon
//
if (draw_background) {
if (m_icon.get() != 0 && m_icon->pixmap.get() != 0) {
if (icon() != 0) {
// copy pixmap, so we don't resize the original
FbPixmap tmp_pixmap, tmp_mask;
tmp_pixmap.copy(icon()->pixmap());
tmp_mask.copy(icon()->mask());
// scale pixmap to right size
if (height - 2*theme.bevelWidth() != m_icon->pixmap->height() &&
!m_icon->filename.empty()) {
if (height - 2*theme.bevelWidth() != tmp_pixmap.height()) {
unsigned int scale_size = height - 2*theme.bevelWidth();
m_icon->pixmap->scale(scale_size, scale_size);
tmp_pixmap.scale(scale_size, scale_size);
tmp_mask.scale(scale_size, scale_size);
}
if (m_icon->pixmap->pixmap().drawable() != 0) {
if (tmp_pixmap.drawable() != 0) {
GC gc = theme.frameTextGC().gc();
int icon_x = x + theme.bevelWidth();
int icon_y = y + theme.bevelWidth();
// enable clip mask
XSetClipMask(disp, gc, m_icon->pixmap->mask().drawable());
XSetClipMask(disp, gc, tmp_mask.drawable());
XSetClipOrigin(disp, gc, icon_x, icon_y);
draw.copyArea(m_icon->pixmap->pixmap().drawable(),
draw.copyArea(tmp_pixmap.drawable(),
gc,
0, 0,
icon_x, icon_y,
m_icon->pixmap->width(), m_icon->pixmap->height());
tmp_pixmap.width(), tmp_pixmap.height());
// restore clip mask
XSetClipMask(disp, gc, None);

View file

@ -101,6 +101,9 @@ public:
*/
//@{
virtual const std::string &label() const { return m_label; }
virtual const PixmapWithMask *icon() const {
return m_icon.get() ? m_icon->pixmap.get() : 0;
}
virtual const Menu *submenu() const { return m_submenu; }
virtual bool isEnabled() const { return m_enabled; }
virtual bool isSelected() const { return m_selected; }

View file

@ -103,6 +103,8 @@ public:
if (!m_search_results.empty())
fillValues(m_search_results.back().result(), last_matched);
else
return *m_ref;
return last_matched;
}

View file

@ -33,6 +33,7 @@
#include "FbWinFrameTheme.hh"
#include "Screen.hh"
#include "IconButton.hh"
#include "Container.hh"
#ifdef SHAPE
@ -52,7 +53,8 @@ FbWinFrame::FbWinFrame(BScreen &screen, FbWinFrameTheme &theme, FbTk::ImageContr
m_screen(screen),
m_theme(theme),
m_imagectrl(imgctrl),
m_window(theme.screenNum(), x, y, width, height, ButtonPressMask | ButtonReleaseMask |
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,
@ -512,13 +514,6 @@ void FbWinFrame::setFocus(bool newvalue) {
}
}
if (currentLabel()) {
if (newvalue) // focused
applyFocusLabel(*m_current_label);
else // unfocused
applyUnfocusLabel(*m_current_label);
}
applyAll();
clearAll();
}
@ -610,11 +605,9 @@ void FbWinFrame::removeAllButtons() {
}
}
FbWinFrame::ButtonId FbWinFrame::createTab(const string &title, FbTk::Command *command,
int tabs_padding) {
FbTk::TextButton *button = new FbTk::TextButton(m_tab_container,
theme().font(),
title);
IconButton *FbWinFrame::createTab(Focusable &client) {
IconButton *button = new IconButton(m_tab_container, theme().iconbarTheme(),
client);
button->show();
button->setEventMask(ExposureMask | ButtonPressMask |
@ -622,29 +615,14 @@ FbWinFrame::ButtonId FbWinFrame::createTab(const string &title, FbTk::Command *c
EnterWindowMask);
FbTk::EventManager::instance()->add(*button, button->window());
FbTk::RefCount<FbTk::Command> refcmd(command);
button->setOnClick(refcmd);
button->setTextPadding(tabs_padding);
button->setJustify(theme().justify());
button->setBorderColor(theme().border().color());
button->setBorderWidth(m_window.borderWidth());
m_tab_container.insertItem(button);
if (currentLabel() == 0)
setLabelButtonFocus(*button);
return button;
}
void FbWinFrame::removeTab(ButtonId btn) {
if (btn == m_current_label)
m_current_label = 0;
void FbWinFrame::removeTab(IconButton *btn) {
if (m_tab_container.removeItem(btn))
delete btn;
}
@ -688,33 +666,10 @@ void FbWinFrame::moveLabelButtonRightOf(FbTk::TextButton &btn, const FbTk::TextB
m_tab_container.moveItem(&btn, movement);
}
void FbWinFrame::setLabelButtonFocus(FbTk::TextButton &btn) {
if (&btn == currentLabel() || btn.parent() != &m_tab_container)
return;
// render label buttons
if (currentLabel() != 0)
applyUnfocusLabel(*m_current_label);
m_current_label = &btn; // current focused button
m_label.setText(btn.text());
if (m_focused)
applyFocusLabel(*m_current_label);
else
applyUnfocusLabel(*m_current_label);
}
void FbWinFrame::setLabelButtonFocus(FbTk::TextButton &btn, bool value) {
void FbWinFrame::setLabelButtonFocus(IconButton &btn) {
if (btn.parent() != &m_tab_container)
return;
if (value)
applyFocusLabel(btn);
else
applyUnfocusLabel(btn);
btn.clear();
m_label.setText(btn.text());
}
void FbWinFrame::setClientWindow(FbTk::FbWindow &win) {
@ -745,7 +700,8 @@ void FbWinFrame::setClientWindow(FbTk::FbWindow &win) {
XChangeWindowAttributes(win.display(), win.window(), CWEventMask|CWDontPropagate, &attrib_set);
m_clientarea.raise();
win.show();
if (isVisible())
win.show();
win.raise();
m_window.showSubwindows();
@ -900,10 +856,6 @@ 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() ||
@ -919,10 +871,6 @@ 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);
@ -1274,11 +1222,11 @@ void FbWinFrame::renderTitlebar() {
//!! TODO: don't render label if internal tabs
render(m_theme.labelFocusTexture(), m_label_focused_color,
render(m_theme.iconbarTheme().focusedTexture(), m_label_focused_color,
m_label_focused_pm,
m_label.width(), m_label.height());
render(m_theme.labelUnfocusTexture(), m_label_unfocused_color,
render(m_theme.iconbarTheme().unfocusedTexture(), m_label_unfocused_color,
m_label_unfocused_pm,
m_label.width(), m_label.height());
@ -1290,8 +1238,8 @@ void FbWinFrame::renderTabContainer() {
return;
}
const FbTk::Texture *tc_focused = &m_theme.labelFocusTexture();
const FbTk::Texture *tc_unfocused = &m_theme.labelUnfocusTexture();
const FbTk::Texture *tc_focused = &m_theme.iconbarTheme().focusedTexture();
const FbTk::Texture *tc_unfocused = &m_theme.iconbarTheme().unfocusedTexture();
if (m_tabmode == EXTERNAL && tc_focused->type() & FbTk::Texture::PARENTRELATIVE)
tc_focused = &m_theme.titleFocusTexture();
@ -1306,14 +1254,6 @@ void FbWinFrame::renderTabContainer() {
m_tabcontainer_unfocused_pm,
m_tab_container.width(), m_tab_container.height(), m_tab_container.orientation());
render(m_theme.labelFocusTexture(), m_labelbutton_focused_color,
m_labelbutton_focused_pm,
m_tab_container.width(), m_tab_container.height(), m_tab_container.orientation());
render(m_theme.labelUnfocusTexture(), m_labelbutton_unfocused_color,
m_labelbutton_unfocused_pm,
m_tab_container.width(), m_tab_container.height(), m_tab_container.orientation());
renderButtons();
}
@ -1333,8 +1273,12 @@ void FbWinFrame::applyTitlebar() {
m_label.setAlpha(alpha);
if (m_tabmode != INTERNAL) {
m_label.setGC(m_focused?theme().labelTextFocusGC():theme().labelTextUnfocusGC());
m_label.setJustify(theme().justify());
m_label.setGC(m_focused ?
theme().iconbarTheme().focusedText().textGC() :
theme().iconbarTheme().unfocusedText().textGC());
m_label.setJustify(m_focused ?
theme().iconbarTheme().focusedText().justify() :
theme().iconbarTheme().unfocusedText().justify());
if (label_pm != 0)
m_label.setBackgroundPixmap(label_pm);
@ -1455,15 +1399,12 @@ void FbWinFrame::init() {
m_disable_themeshape = false;
m_current_label = 0; // no focused button at first
m_handle.showSubwindows();
// 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 = 0;
m_handle_focused_pm = m_handle_unfocused_pm = 0;
m_button_pm = m_button_unfocused_pm = m_button_pressed_pm = 0;
m_grip_unfocused_pm = m_grip_focused_pm = 0;
@ -1586,11 +1527,8 @@ void FbWinFrame::applyTabContainer() {
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) {
FbTk::TextButton *btn = static_cast<FbTk::TextButton *>(*btn_it);
if (btn == m_current_label && m_focused)
applyFocusLabel(*btn);
else
applyUnfocusLabel(*btn);
IconButton *btn = static_cast<IconButton *>(*btn_it);
btn->reconfigTheme();
}
}
@ -1626,15 +1564,6 @@ void FbWinFrame::setBorderWidth(unsigned int border_width) {
gripRight().setBorderWidth(border_width);
gripRight().setBorderColor(theme().border().color());
// and the labelbuttons
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) {
(*btn_it)->setBorderWidth(border_width);
(*btn_it)->setBorderColor(theme().border().color());
}
m_tab_container.update();
if (bw_changes != 0)
resize(width(), height() + bw_changes);
@ -1648,32 +1577,6 @@ void FbWinFrame::setBorderWidth(unsigned int border_width) {
}
void FbWinFrame::applyFocusLabel(FbTk::TextButton &button) {
button.setGC(theme().labelTextFocusGC());
button.setJustify(theme().justify());
button.setAlpha(getAlpha(m_focused));
if (m_labelbutton_focused_pm != 0) {
button.setBackgroundPixmap(m_labelbutton_focused_pm);
} else
button.setBackgroundColor(m_labelbutton_focused_color);
}
void FbWinFrame::applyUnfocusLabel(FbTk::TextButton &button) {
button.setGC(theme().labelTextUnfocusGC());
button.setJustify(theme().justify());
button.setAlpha(getAlpha(m_focused));
if (m_labelbutton_unfocused_pm != 0) {
button.setBackgroundPixmap(m_labelbutton_unfocused_pm);
} else
button.setBackgroundColor(m_labelbutton_unfocused_color);
}
// this function translates its arguments according to win_gravity
// if win_gravity is negative, it does an inverse translation
// This function should be used when a window is mapped/unmapped/pos configured

View file

@ -43,6 +43,8 @@
class Shape;
class FbWinFrameTheme;
class BScreen;
class IconButton;
class Focusable;
namespace FbTk {
class TextButton;
@ -71,8 +73,6 @@ public:
};
typedef FbTk::TextButton *ButtonId; ///< defines a button id
/// create a top level window
FbWinFrame(BScreen &screen, FbWinFrameTheme &theme, FbTk::ImageControl &imgctrl,
FbTk::XLayer &layer,
@ -142,10 +142,9 @@ public:
/// remove all buttons from titlebar
void removeAllButtons();
/// adds a button to label window with specified title and command
ButtonId createTab(const std::string &title, FbTk::Command *cmd, int tab_padding);
// void addLabelButton(FbTk::TextButton &btn);
IconButton *createTab(Focusable &client);
/// removes a specific button from label window
void removeTab(ButtonId id);
void removeTab(IconButton *id);
/// move label button to the left
void moveLabelButtonLeft(FbTk::TextButton &btn);
/// move label button to the right
@ -157,9 +156,7 @@ public:
//move the first label button to the right of the second
void moveLabelButtonRightOf(FbTk::TextButton &btn, const FbTk::TextButton &dest);
/// which button is to be rendered focused
void setLabelButtonFocus(FbTk::TextButton &btn);
/// specify focus state of button
void setLabelButtonFocus(FbTk::TextButton &btn, bool value);
void setLabelButtonFocus(IconButton &btn);
/// attach a client window for client area
void setClientWindow(FbTk::FbWindow &win);
/// remove attached client window
@ -238,7 +235,7 @@ public:
inline FbTk::FbWindow &gripLeft() { return m_grip_left; }
inline const FbTk::FbWindow &gripRight() const { return m_grip_right; }
inline FbTk::FbWindow &gripRight() { return m_grip_right; }
inline const FbTk::TextButton *currentLabel() const { return m_current_label; }
inline const IconButton *currentLabel() const { return m_current_label; }
inline bool focused() const { return m_focused; }
inline bool isShaded() const { return m_shaded; }
inline FbWinFrameTheme &theme() const { return m_theme; }
@ -284,8 +281,6 @@ private:
void applyTitlebar();
void applyHandles();
void applyTabContainer(); // and label buttons
void applyFocusLabel(FbTk::TextButton &button);
void applyUnfocusLabel(FbTk::TextButton &button);
void applyButtons(); // only called within applyTitlebar
void getCurrentFocusPixmap(Pixmap &label_pm, Pixmap &title_pm,
@ -324,8 +319,7 @@ private:
ButtonList m_buttons_left, ///< buttons to the left
m_buttons_right; ///< buttons to the right
typedef std::list<FbTk::TextButton *> LabelList;
FbTk::TextButton *m_current_label; ///< which client button is focused at the moment
std::string m_titletext; ///< text to be displayed int m_label
IconButton *m_current_label; ///< which client button is focused at the moment
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)
@ -354,11 +348,6 @@ private:
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 unfocused label
FbTk::Color m_handle_focused_color, m_handle_unfocused_color;
Pixmap m_handle_focused_pm, m_handle_unfocused_pm;

View file

@ -24,13 +24,12 @@
#include "FbWinFrameTheme.hh"
#include "App.hh"
#include "IconbarTheme.hh"
#include <X11/cursorfont.h>
FbWinFrameTheme::FbWinFrameTheme(int screen_num):
FbTk::Theme(screen_num),
m_label_focus(*this, "window.label.focus", "Window.Label.Focus"),
m_label_unfocus(*this, "window.label.unfocus", "Window.Label.Unfocus"),
m_title_focus(*this, "window.title.focus", "Window.Title.Focus"),
m_title_unfocus(*this, "window.title.unfocus", "Window.Title.Unfocus"),
@ -44,25 +43,20 @@ FbWinFrameTheme::FbWinFrameTheme(int screen_num):
m_grip_focus(*this, "window.grip.focus", "Window.Grip.Focus"),
m_grip_unfocus(*this, "window.grip.unfocus", "Window.Grip.Unfocus"),
m_label_focus_color(*this, "window.label.focus.textColor", "Window.Label.Focus.TextColor"),
m_label_unfocus_color(*this, "window.label.unfocus.textColor", "Window.Label.Unfocus.TextColor"),
m_button_focus_color(*this, "window.button.focus.picColor", "Window.Button.Focus.PicColor"),
m_button_unfocus_color(*this, "window.button.unfocus.picColor", "Window.Button.Unfocus.PicColor"),
m_font(*this, "window.font", "Window.Font"),
m_textjustify(*this, "window.justify", "Window.Justify"),
m_shape_place(*this, "window.roundCorners", "Window.RoundCorners"),
m_title_height(*this, "window.title.height", "Window.Title.Height"),
m_bevel_width(*this, "window.bevelWidth", "Window.BevelWidth"),
m_handle_width(*this, "window.handleWidth", "Window.handleWidth"),
m_border(*this, "window", "Window"), // for window.border*
m_label_text_focus_gc(RootWindow(FbTk::App::instance()->display(), screen_num)),
m_label_text_unfocus_gc(RootWindow(FbTk::App::instance()->display(), screen_num)),
m_button_pic_focus_gc(RootWindow(FbTk::App::instance()->display(), screen_num)),
m_button_pic_unfocus_gc(RootWindow(FbTk::App::instance()->display(), screen_num)),
m_focused_alpha(255),
m_unfocused_alpha(255) {
m_unfocused_alpha(255),
m_iconbar_theme(screen_num, "window.label", "Window.Label") {
*m_title_height = 0;
// set defaults
@ -107,9 +101,9 @@ void FbWinFrameTheme::reconfigTheme() {
else if (*m_handle_width < 0)
*m_handle_width = 1;
m_label_text_focus_gc.setForeground(*m_label_focus_color);
m_label_text_unfocus_gc.setForeground(*m_label_unfocus_color);
m_button_pic_focus_gc.setForeground(*m_button_focus_color);
m_button_pic_unfocus_gc.setForeground(*m_button_unfocus_color);
m_iconbar_theme.reconfigTheme();
}

View file

@ -33,6 +33,7 @@
#include "FbTk/GContext.hh"
#include "BorderTheme.hh"
#include "IconbarTheme.hh"
#include "Shape.hh"
class FbWinFrameTheme: public FbTk::Theme {
@ -43,9 +44,6 @@ public:
@name textures
*/
//@{
const FbTk::Texture &labelFocusTexture() const { return *m_label_focus; }
const FbTk::Texture &labelUnfocusTexture() const { return *m_label_unfocus; }
const FbTk::ThemeItem<FbTk::Texture> &label() const { return m_label_unfocus; }
const FbTk::Texture &titleFocusTexture() const { return *m_title_focus; }
const FbTk::Texture &titleUnfocusTexture() const { return *m_title_unfocus; }
@ -64,18 +62,11 @@ public:
@name colors
*/
//@{
const FbTk::Color &labelFocusColor() const { return *m_label_focus_color; }
const FbTk::Color &labelUnfocusColor() const { return *m_label_unfocus_color; }
const FbTk::Color &buttonFocuscolor() const { return *m_button_focus_color; }
const FbTk::Color &buttonUnfocuscolor() const { return *m_button_unfocus_color; }
//@}
FbTk::Font &font() { return *m_font; }
FbTk::Justify justify() const { return *m_textjustify; }
GC labelTextFocusGC() const { return m_label_text_focus_gc.gc(); }
GC labelTextUnfocusGC() const { return m_label_text_unfocus_gc.gc(); }
GC buttonPicFocusGC() const { return m_button_pic_focus_gc.gc(); }
GC buttonPicUnfocusGC() const { return m_button_pic_unfocus_gc.gc(); }
@ -100,24 +91,22 @@ public:
void setFocusedAlpha(unsigned char alpha) { m_focused_alpha = alpha; }
void setUnfocusedAlpha(unsigned char alpha) { m_unfocused_alpha = alpha; }
IconbarTheme &iconbarTheme() { return m_iconbar_theme; }
private:
FbTk::ThemeItem<FbTk::Texture> m_label_focus, m_label_unfocus;
FbTk::ThemeItem<FbTk::Texture> m_title_focus, m_title_unfocus;
FbTk::ThemeItem<FbTk::Texture> m_handle_focus, m_handle_unfocus;
FbTk::ThemeItem<FbTk::Texture> m_button_focus, m_button_unfocus, m_button_pressed;
FbTk::ThemeItem<FbTk::Texture> m_grip_focus, m_grip_unfocus;
FbTk::ThemeItem<FbTk::Color> m_label_focus_color, m_label_unfocus_color;
FbTk::ThemeItem<FbTk::Color> m_button_focus_color, m_button_unfocus_color;
FbTk::ThemeItem<FbTk::Font> m_font;
FbTk::ThemeItem<FbTk::Justify> m_textjustify;
FbTk::ThemeItem<Shape::ShapePlace> m_shape_place;
FbTk::ThemeItem<int> m_title_height, m_bevel_width, m_handle_width;
BorderTheme m_border;
FbTk::GContext m_label_text_focus_gc, m_label_text_unfocus_gc;
FbTk::GContext m_button_pic_focus_gc, m_button_pic_unfocus_gc;
Cursor m_cursor_move;
@ -127,6 +116,8 @@ private:
Cursor m_cursor_upper_right_angle;
unsigned char m_focused_alpha;
unsigned char m_unfocused_alpha;
IconbarTheme m_iconbar_theme;
};
#endif // FBWINFRAMETHEME_HH

View file

@ -23,6 +23,7 @@
#include "FocusControl.hh"
#include "ClientPattern.hh"
#include "Screen.hh"
#include "Window.hh"
#include "WinClient.hh"
@ -48,6 +49,22 @@ WinClient *FocusControl::s_focused_window = 0;
FluxboxWindow *FocusControl::s_focused_fbwindow = 0;
bool FocusControl::s_reverting = false;
namespace {
bool doSkipWindow(const Focusable &win, const ClientPattern *pat) {
const FluxboxWindow *fbwin = win.fbwindow();
if (!fbwin || fbwin->isFocusHidden())
return true; // skip if no fbwindow or if focushidden
if (pat && !pat->match(win))
return true; // skip if it doesn't match the pattern
if (fbwin->workspaceNumber() != win.screen().currentWorkspaceID() &&
!fbwin->isStuck())
return true; // for now, we only cycle through the current workspace
return false; // else don't skip
}
}; // end anonymous namespace
FocusControl::FocusControl(BScreen &screen):
m_screen(screen),
m_focus_model(screen.resourceManager(),
@ -65,28 +82,12 @@ FocusControl::FocusControl(BScreen &screen):
m_was_iconic(false),
m_cycling_last(0) {
m_cycling_window = m_focused_list.end();
m_cycling_window = m_focused_win_list.end();
}
// true if the windows should be skiped else false
bool doSkipWindow(const WinClient &winclient, int opts) {
const FluxboxWindow *win = winclient.fbwindow();
return (!win ||
// skip if stuck
(opts & FocusControl::CYCLESKIPSTUCK) != 0 && win->isStuck() ||
// skip if not active client (i.e. only visit each fbwin once)
(opts & FocusControl::CYCLEGROUPS) != 0 && win->winClient().window() != winclient.window() ||
// skip if shaded
(opts & FocusControl::CYCLESKIPSHADED) != 0 && win->isShaded() ||
// skip if iconic
(opts & FocusControl::CYCLESKIPICONIC) != 0 && win->isIconic() ||
// skip if hidden
win->isFocusHidden()
);
}
void FocusControl::cycleFocus(FocusedWindows &window_list, int opts, bool cycle_reverse) {
void FocusControl::cycleFocus(Focusables &window_list, const ClientPattern *pat,
bool cycle_reverse) {
if (!m_cycling_list) {
if (&m_screen == FbTk::EventManager::instance()->grabbingKeyboard())
@ -97,13 +98,15 @@ void FocusControl::cycleFocus(FocusedWindows &window_list, int opts, bool cycle_
} else if (m_cycling_list != &window_list)
m_cycling_list = &window_list;
FocusedWindows::iterator it_begin = window_list.begin();
FocusedWindows::iterator it_end = window_list.end();
Focusables::iterator it_begin = window_list.begin();
Focusables::iterator it_end = window_list.end();
// too many things can go wrong with remembering this
m_cycling_window = find(it_begin, it_end, s_focused_window);
if (m_cycling_window == it_end)
m_cycling_window = find(it_begin, it_end, s_focused_fbwindow);
FocusedWindows::iterator it = m_cycling_window;
Focusables::iterator it = m_cycling_window;
FluxboxWindow *fbwin = 0;
WinClient *last_client = 0;
WinClient *was_iconic = 0;
@ -123,11 +126,7 @@ void FocusControl::cycleFocus(FocusedWindows &window_list, int opts, bool cycle_
continue;
fbwin = (*it)->fbwindow();
// make sure the window is on the same workspace,
// unless its sticky, which is ok
if (!fbwin ||
( fbwin->workspaceNumber() != m_screen.currentWorkspaceID() &&
! fbwin->isStuck()))
if (!fbwin)
continue;
// keep track of the originally selected window in a group
@ -135,7 +134,7 @@ void FocusControl::cycleFocus(FocusedWindows &window_list, int opts, bool cycle_
was_iconic = (fbwin->isIconic() ? last_client : 0);
// now we actually try to focus the window
if (!doSkipWindow(**it, opts) && (*it)->focus())
if (!doSkipWindow(**it, pat) && (*it)->focus())
break;
}
@ -168,6 +167,33 @@ void FocusControl::cycleFocus(FocusedWindows &window_list, int opts, bool cycle_
}
void FocusControl::goToWindowNumber(Focusables &winlist, int num,
const ClientPattern *pat) {
Focusable *last_matched = 0;
if (num > 0) {
Focusables::iterator it = winlist.begin();
Focusables::iterator it_end = winlist.end();
for (; it != it_end; ++it) {
if (!doSkipWindow(**it, pat) && (*it)->acceptsFocus()) {
--num;
last_matched = *it;
if (!num) break;
}
}
} else if (num < 0) {
Focusables::reverse_iterator it = winlist.rbegin();
Focusables::reverse_iterator it_end = winlist.rend();
for (; it != it_end; ++it) {
if (!doSkipWindow(**it, pat) && (*it)->acceptsFocus()) {
++num;
last_matched = *it;
if (!num) break;
}
}
}
if (last_matched) last_matched->focus();
}
void FocusControl::addFocusBack(WinClient &client) {
m_focused_list.push_back(&client);
m_creation_order_list.push_back(&client);
@ -178,6 +204,16 @@ void FocusControl::addFocusFront(WinClient &client) {
m_creation_order_list.push_back(&client);
}
void FocusControl::addFocusWinBack(Focusable &win) {
m_focused_win_list.push_back(&win);
m_creation_order_win_list.push_back(&win);
}
void FocusControl::addFocusWinFront(Focusable &win) {
m_focused_win_list.push_front(&win);
m_creation_order_win_list.push_back(&win);
}
// move all clients in given window to back of focused list
void FocusControl::setFocusBack(FluxboxWindow *fbwin) {
// do nothing if there are no windows open
@ -185,9 +221,19 @@ void FocusControl::setFocusBack(FluxboxWindow *fbwin) {
if (m_focused_list.empty() || s_reverting)
return;
FocusedWindows::iterator it = m_focused_list.begin();
// if the window isn't already in this list, we could accidentally add it
Focusables::iterator win_begin = m_focused_win_list.begin(),
win_end = m_focused_win_list.end();
Focusables::iterator win_it = find(win_begin, win_end, fbwin);
if (win_it == win_end)
return;
m_focused_win_list.erase(win_it);
m_focused_win_list.push_back(fbwin);
Focusables::iterator it = m_focused_list.begin();
// use back to avoid an infinite loop
FocusedWindows::iterator it_back = --m_focused_list.end();
Focusables::iterator it_back = --m_focused_list.end();
while (it != it_back) {
if ((*it)->fbwindow() == fbwin) {
@ -201,6 +247,7 @@ void FocusControl::setFocusBack(FluxboxWindow *fbwin) {
m_focused_list.push_back(*it);
m_focused_list.erase(it);
}
}
void FocusControl::stopCyclingFocus() {
@ -208,7 +255,7 @@ void FocusControl::stopCyclingFocus() {
if (m_cycling_list == 0)
return;
FocusedWindows::iterator it_end = m_cycling_list->end();
Focusables::iterator it_end = m_cycling_list->end();
m_cycling_last = 0;
m_cycling_list = 0;
@ -217,10 +264,9 @@ void FocusControl::stopCyclingFocus() {
// in which case we'll do a proper revert focus
if (m_cycling_window != it_end && (*m_cycling_window)->fbwindow() &&
(*m_cycling_window)->fbwindow()->isVisible()) {
WinClient *client = *m_cycling_window;
m_focused_list.remove(client);
m_focused_list.push_front(client);
client->fbwindow()->raise();
(*m_cycling_window)->fbwindow()->raise();
if (s_focused_window)
setScreenFocusedWindow(*s_focused_window);
} else
revertFocus(m_screen);
}
@ -230,13 +276,13 @@ void FocusControl::stopCyclingFocus() {
* If workspace is outside the ID range, then the absolute last focused window
* is given.
*/
WinClient *FocusControl::lastFocusedWindow(int workspace) {
if (m_focused_list.empty()) return 0;
Focusable *FocusControl::lastFocusedWindow(int workspace) {
if (m_focused_list.empty() || m_screen.isShuttingdown()) return 0;
if (workspace < 0 || workspace >= (int) m_screen.numberOfWorkspaces())
return m_focused_list.front();
FocusedWindows::iterator it = m_focused_list.begin();
FocusedWindows::iterator it_end = m_focused_list.end();
Focusables::iterator it = m_focused_list.begin();
Focusables::iterator it_end = m_focused_list.end();
for (; it != it_end; ++it) {
if ((*it)->fbwindow() &&
((((int)(*it)->fbwindow()->workspaceNumber()) == workspace ||
@ -253,14 +299,15 @@ WinClient *FocusControl::lastFocusedWindow(int workspace) {
* Stuck, iconic etc don't matter within a group
*/
WinClient *FocusControl::lastFocusedWindow(FluxboxWindow &group, WinClient *ignore_client) {
if (m_focused_list.empty()) return 0;
if (m_focused_list.empty() || m_screen.isShuttingdown())
return 0;
FocusedWindows::iterator it = m_focused_list.begin();
FocusedWindows::iterator it_end = m_focused_list.end();
Focusables::iterator it = m_focused_list.begin();
Focusables::iterator it_end = m_focused_list.end();
for (; it != it_end; ++it) {
if (((*it)->fbwindow() == &group) &&
(*it) != ignore_client)
return *it;
return dynamic_cast<WinClient *>(*it);
}
return 0;
}
@ -269,11 +316,28 @@ void FocusControl::setScreenFocusedWindow(WinClient &win_client) {
// raise newly focused window to the top of the focused list
// don't change the order if we're cycling or shutting down
// don't change on startup, as it may add windows that aren't listed yet
if (!isCycling() && !m_screen.isShuttingdown() && !s_reverting &&
!Fluxbox::instance()->isStartup()) {
m_focused_list.remove(&win_client);
if (!isCycling() && !m_screen.isShuttingdown() && !s_reverting) {
// make sure client is in our list, or else we could end up adding it
Focusables::iterator it_begin = m_focused_list.begin(),
it_end = m_focused_list.end();
Focusables::iterator it = find(it_begin, it_end, &win_client);
if (it == it_end)
return;
m_focused_list.erase(it);
m_focused_list.push_front(&win_client);
// also check the fbwindow
it_begin = m_focused_win_list.begin();
it_end = m_focused_win_list.end();
it = find(it_begin, it_end, win_client.fbwindow());
if (it != it_end) {
m_focused_win_list.erase(it);
m_focused_win_list.push_front(win_client.fbwindow());
}
}
}
@ -380,7 +444,7 @@ void FocusControl::dirFocus(FluxboxWindow &win, FocusDir dir) {
}
if (foundwin)
foundwin->setInputFocus();
foundwin->focus();
}
@ -388,7 +452,7 @@ void FocusControl::removeClient(WinClient &client) {
if (client.screen().isShuttingdown())
return;
WinClient *cyc = 0;
Focusable *cyc = 0;
if (m_cycling_list && m_cycling_window != m_cycling_list->end())
cyc = *m_cycling_window;
@ -401,27 +465,30 @@ void FocusControl::removeClient(WinClient &client) {
}
}
void FocusControl::removeWindow(Focusable &win) {
m_focused_win_list.remove(&win);
m_creation_order_win_list.remove(&win);
}
void FocusControl::shutdown() {
// restore windows backwards so they get put back correctly on restart
FocusedWindows::reverse_iterator it = m_focused_list.rbegin();
Focusables::reverse_iterator it = m_focused_list.rbegin();
for (; it != m_focused_list.rend(); ++it) {
if (*it && (*it)->fbwindow())
(*it)->fbwindow()->restore(*it, true);
WinClient *client = dynamic_cast<WinClient *>(*it);
if (client && client->fbwindow())
client->fbwindow()->restore(client, true);
}
}
/**
* This function is called whenever we aren't quite sure what
* focus is meant to be, it'll make things right ;-)
* last_focused is set to something if we want to make use of the
* previously focused window (it must NOT be set focused now, it
* is probably dying).
*/
void FocusControl::revertFocus(BScreen &screen) {
if (s_reverting)
if (s_reverting || screen.isShuttingdown())
return;
WinClient *next_focus =
Focusable *next_focus =
screen.focusControl().lastFocusedWindow(screen.currentWorkspaceID());
if (next_focus && next_focus->fbwindow() &&
@ -430,6 +497,7 @@ void FocusControl::revertFocus(BScreen &screen) {
// if setting focus fails, or isn't possible, fallback correctly
if (!(next_focus && next_focus->focus())) {
setFocusedWindow(0); // so we don't get dangling m_focused_window pointer
// if there's a menu open, focus it
if (FbTk::Menu::shownMenu())
@ -458,9 +526,8 @@ void FocusControl::revertFocus(BScreen &screen) {
* If unfocus_frame is true, we won't focus anything in the same frame
* as the client.
*
* So, we first prefer to choose a transient parent, then the last
* client in this window, and if no luck (or unfocus_frame), then
* we just use the normal revertFocus on the screen.
* So, we first prefer to choose the last client in this window, and if no luck
* (or unfocus_frame), then we just use the normal revertFocus on the screen.
*
* assumption: client has focus
*/

View file

@ -28,8 +28,10 @@
#include "FbTk/Resource.hh"
class ClientPattern;
class WinClient;
class FluxboxWindow;
class Focusable;
class BScreen;
/**
@ -38,13 +40,12 @@ class BScreen;
*/
class FocusControl {
public:
typedef std::list<WinClient *> FocusedWindows;
typedef std::list<Focusable *> Focusables;
/// main focus model
enum FocusModel {
MOUSEFOCUS = 0, ///< focus follows mouse
CLICKFOCUS ///< focus on click
};
/// focus model for tabs
enum TabFocusModel {
MOUSETABFOCUS = 0, ///< tab focus follows mouse
@ -60,18 +61,12 @@ public:
};
/// prevFocus/nextFocus option bits
enum FocusOption {
CYCLEGROUPS = 0x01, ///< cycle groups
CYCLESKIPSTUCK = 0x02, ///< skip stuck windows
CYCLESKIPSHADED = 0x04, ///< skip shaded windows
CYCLELINEAR = 0x08, ///< linear cycle
CYCLESKIPICONIC = 0x10, ///< skip iconified windows
CYCLEDEFAULT = 0x00 ///< default
enum {
CYCLEGROUPS = 0x01, //< cycle through groups
CYCLELINEAR = 0x08, ///< linear cycle
};
/// @param screen the screen to control focus for
explicit FocusControl(BScreen &screen);
/// cycle previous focuable
void prevFocus() { cycleFocus(m_focused_list, 0, true); }
/// cycle next focusable
@ -79,17 +74,20 @@ public:
/**
* Cycle focus for a set of windows.
* @param winlist the windowlist to cycle through
* @param options cycle options @see FocusOption
* @param pat pattern for matching focusables
* @param reverse reverse the cycle order
*/
void cycleFocus(FocusedWindows &winlist, int options, bool reverse = false);
void cycleFocus(Focusables &winlist, const ClientPattern *pat = 0,
bool reverse = false);
void goToWindowNumber(Focusables &winlist, int num,
const ClientPattern *pat = 0);
/// sets the focused window on a screen
void setScreenFocusedWindow(WinClient &win_client);
/// sets the main focus model
void setFocusModel(FocusModel model);
/// sets tab focus model
void setTabFocusModel(TabFocusModel model);
void setTabFocusModel(TabFocusModel model);
/// stop cycling mode
void stopCyclingFocus();
/**
@ -104,10 +102,12 @@ public:
bool isMouseTabFocus() const { return tabFocusModel() == MOUSETABFOCUS; }
/// @return true if cycling is in progress
bool isCycling() const { return m_cycling_list != 0; }
/// Appends a client to the back of the focus list
/// Appends a client to the front of the focus list
void addFocusBack(WinClient &client);
/// Appends a client to the front of the focus list
void addFocusFront(WinClient &client);
void addFocusWinBack(Focusable &win);
void addFocusWinFront(Focusable &win);
void setFocusBack(FluxboxWindow *fbwin);
/// @return main focus model
FocusModel focusModel() const { return *m_focus_model; }
@ -115,19 +115,26 @@ public:
TabFocusModel tabFocusModel() const { return *m_tab_focus_model; }
/// @return true if newly created windows are focused
bool focusNew() const { return *m_focus_new; }
/// @return last focused client in a specific workspace, or NULL.
WinClient *lastFocusedWindow(int workspace);
WinClient *lastFocusedWindow(FluxboxWindow &group, WinClient *ignore_client);
Focusable *lastFocusedWindow(int workspace);
WinClient *lastFocusedWindow(FluxboxWindow &group, WinClient *ignore_client = 0);
/// @return focus list in creation order
FocusedWindows &creationOrderList() { return m_creation_order_list; }
/// @return the focus list
FocusedWindows &focusedOrderList() { return m_focused_list; }
/// removes a client from the focus list
Focusables &creationOrderList() { return m_creation_order_list; }
/// @return the focus list in focused order
Focusables &focusedOrderList() { return m_focused_list; }
Focusables &creationOrderWinList() { return m_creation_order_win_list; }
Focusables &focusedOrderWinList() { return m_focused_win_list; }
/// remove client from focus list
void removeClient(WinClient &client);
/// remove window from focus list
void removeWindow(Focusable &win);
/// starts terminating this control
void shutdown();
/// do fallback focus for screen if normal focus control failed.
static void revertFocus(BScreen &screen);
// like revertFocus, but specifically related to this window (transients etc)
@ -146,12 +153,14 @@ private:
// This list keeps the order of window focusing for this screen
// Screen global so it works for sticky windows too.
FocusedWindows m_focused_list;
FocusedWindows m_creation_order_list;
Focusables m_focused_list;
Focusables m_creation_order_list;
Focusables m_focused_win_list;
Focusables m_creation_order_win_list;
FocusedWindows::iterator m_cycling_window;
FocusedWindows *m_cycling_list;
WinClient *m_was_iconic;
Focusables::iterator m_cycling_window;
Focusables *m_cycling_list;
Focusable *m_was_iconic;
WinClient *m_cycling_last;
static WinClient *s_focused_window;

140
src/Focusable.hh Normal file
View file

@ -0,0 +1,140 @@
// Focusable.hh
// Copyright (c) 2007 Fluxbox Team (fluxgen at fluxbox dot org)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id$
#ifndef FOCUSABLE_HH
#define FOCUSABLE_HH
#include "FbTk/PixmapWithMask.hh"
#include "FbTk/ITypeAheadable.hh"
#include "FbTk/Subject.hh"
#include <string>
class BScreen;
class FluxboxWindow;
/**
* A Base class for any object that might be "focused".
* Such as FluxboxWindow, Menu etc
*/
class Focusable: public FbTk::ITypeAheadable {
public:
Focusable(BScreen &scr, FluxboxWindow *fbwin = 0):
m_screen(scr), m_fbwin(fbwin),
m_instance_name("fluxbox"), m_class_name("fluxbox"),
m_focused(false), m_attention_state(false),
m_titlesig(*this), m_focussig(*this), m_diesig(*this),
m_attentionsig(*this) { }
virtual ~Focusable() { }
/**
* Take focus.
* @return true if the focuable took focus
*/
virtual bool focus() { return false; }
/// @return true if the focusable has input focus
virtual bool isFocused() const { return m_focused; }
/// @return return true if it can be focused
virtual bool acceptsFocus() const { return true; }
/// @return true if icon button should appear focused
inline bool getAttentionState() const { return m_attention_state; }
/// @set the attention state
virtual void setAttentionState(bool value) {
m_attention_state = value; attentionSig().notify();
}
/// @return the screen in which this object resides
inline BScreen &screen() { return m_screen; }
/// @return the screen in which this object resides
inline const BScreen &screen() const { return m_screen; }
/**
* For accessing window properties, like shaded, minimized, etc.
* @return window context
*/
inline const FluxboxWindow *fbwindow() const { return m_fbwin; }
/**
* For accessing window properties, like shaded, minimized, etc.
* @return window context
*/
inline FluxboxWindow *fbwindow() { return m_fbwin; }
/// @return WM_CLASS class string (for pattern matching)
virtual const std::string &getWMClassClass() const { return m_class_name; }
/// @return WM_CLASS name string (for pattern matching)
virtual const std::string &getWMClassName() const { return m_instance_name; }
/// @return wm role string ( for pattern matching)
virtual std::string getWMRole() const { return "Focusable"; }
// so we can make nice buttons, menu entries, etc.
/// @return icon pixmap of the focusable
virtual const FbTk::PixmapWithMask &icon() const { return m_icon; }
/// @return title string
virtual const std::string &title() const { return m_title; }
/// @return type ahead string
const std::string &iTypeString() const { return title(); }
/**
* Signaling object to attatch observers to.
*/
class FocusSubject: public FbTk::Subject {
public:
explicit FocusSubject(Focusable &w):m_win(w) { }
/// @return context focusable for this signal
Focusable &win() { return m_win; }
/// @return context focusable for this signal
const Focusable &win() const { return m_win; }
private:
Focusable &m_win; //< the context
};
/**
@name signals
@{
*/
// Used for both title and icon changes.
FbTk::Subject &titleSig() { return m_titlesig; }
// Used for both title and icon changes.
const FbTk::Subject &titleSig() const { return m_titlesig; }
FbTk::Subject &focusSig() { return m_focussig; }
const FbTk::Subject &focusSig() const { return m_focussig; }
FbTk::Subject &dieSig() { return m_diesig; }
const FbTk::Subject &dieSig() const { return m_diesig; }
FbTk::Subject &attentionSig() { return m_attentionsig; }
const FbTk::Subject &attentionSig() const { return m_attentionsig; }
/** @} */ // end group signals
protected:
BScreen &m_screen; //< the screen in which it works
FluxboxWindow *m_fbwin; //< the working fluxbox window
std::string m_title, m_instance_name, m_class_name;
bool m_focused; //< whether or not it has focus
bool m_attention_state; //< state of icon button while demanding attention
FbTk::PixmapWithMask m_icon; //< icon pixmap with mask
// state and hint signals
FocusSubject m_titlesig, m_focussig, m_diesig, m_attentionsig;
};
#endif // FOCUSABLE_HH

View file

@ -24,21 +24,19 @@
#include "IconButton.hh"
#include "IconbarTool.hh"
#include "IconbarTheme.hh"
#include "fluxbox.hh"
#include "Screen.hh"
#include "Window.hh"
#include "WinClient.hh"
#include "CommandParser.hh"
#include "WindowCmd.hh"
#include "Focusable.hh"
#include "FbTk/App.hh"
#include "FbTk/SimpleCommand.hh"
#include "FbTk/EventManager.hh"
#include "FbTk/MacroCommand.hh"
#include "FbTk/Command.hh"
#include "FbTk/RefCount.hh"
#include "FbTk/EventManager.hh"
#include "FbTk/ImageControl.hh"
#include "FbTk/MacroCommand.hh"
#include "FbTk/Menu.hh"
#include "FbTk/RefCount.hh"
#include "FbTk/SimpleCommand.hh"
#ifdef HAVE_CONFIG_H
#include "config.h"
@ -49,127 +47,25 @@
#include <X11/extensions/shape.h>
#endif // SHAPE
typedef FbTk::RefCount<FbTk::Command> RefCmd;
namespace {
class ShowMenu: public FbTk::Command {
public:
explicit ShowMenu(FluxboxWindow &win):m_win(win) { }
void execute() {
// hide the menu if it's already showing for this FluxboxWindow
if (m_win.menu().isVisible() && WindowCmd<void>::window() == &m_win) {
m_win.screen().hideMenus();
return;
}
m_win.screen().hideMenus();
// get last button pos
const XEvent &event = Fluxbox::instance()->lastEvent();
int x = event.xbutton.x_root - (m_win.menu().width() / 2);
int y = event.xbutton.y_root - (m_win.menu().height() / 2);
m_win.showMenu(x, y);
}
private:
FluxboxWindow &m_win;
};
class FocusCommand: public FbTk::Command {
public:
explicit FocusCommand(const IconbarTool& tool, FluxboxWindow &win) :
m_win(win), m_tool(tool) { }
void execute() {
// this needs to be a local variable, as this object could be destroyed
// if the workspace is changed.
FluxboxWindow &win = m_win;
if(win.isIconic() || !win.isFocused()) {
switch(win.screen().getUserFollowModel()) {
case BScreen::SEMIFOLLOW_ACTIVE_WINDOW:
if (win.isIconic()) {
win.screen().sendToWorkspace(win.screen().currentWorkspaceID(), &win);
} else {
win.screen().changeWorkspaceID(win.workspaceNumber());
}
break;
case BScreen::FETCH_ACTIVE_WINDOW:
win.screen().sendToWorkspace(win.screen().currentWorkspaceID(), &win);
break;
case BScreen::FOLLOW_ACTIVE_WINDOW:
if (!win.isStuck())
win.screen().changeWorkspaceID(win.workspaceNumber());
default:
break;
};
win.raiseAndFocus();
} else
win.iconify();
}
private:
FluxboxWindow &m_win;
const IconbarTool& m_tool;
};
// simple forwarding of wheeling, but only
// if desktopwheeling is enabled
class WheelWorkspaceCmd : public FbTk::Command {
public:
explicit WheelWorkspaceCmd(const IconbarTool& tool, FluxboxWindow &win, const char* cmd) :
m_win(win), m_cmd(CommandParser::instance().parseLine(cmd)), m_tool(tool) { }
void execute() {
switch(m_tool.wheelMode()) {
case IconbarTool::ON:
m_cmd->execute();
break;
case IconbarTool::SCREEN:
if(m_win.screen().isDesktopWheeling())
m_cmd->execute();
break;
case IconbarTool::OFF:
default:
break;
};
}
private:
FluxboxWindow &m_win;
RefCmd m_cmd;
const IconbarTool& m_tool;
};
} // end anonymous namespace
IconButton::IconButton(const IconbarTool& tool, const FbTk::FbWindow &parent,
FbTk::Font &font, FluxboxWindow &win):
FbTk::TextButton(parent, font, win.winClient().title()),
IconButton::IconButton(const FbTk::FbWindow &parent, IconbarTheme &theme,
Focusable &win):
FbTk::TextButton(parent, theme.focusedText().font(), win.title()),
m_win(win),
m_icon_window(*this, 1, 1, 1, 1,
ExposureMask | ButtonPressMask | ButtonReleaseMask),
m_use_pixmap(true) {
m_use_pixmap(true),
m_theme(theme),
m_focused_pm(win.screen().imageControl()),
m_unfocused_pm(win.screen().imageControl()) {
RefCmd next_workspace(new ::WheelWorkspaceCmd(tool, m_win, "nextworkspace"));
RefCmd prev_workspace(new ::WheelWorkspaceCmd(tool, m_win, "prevworkspace"));
RefCmd focus_cmd(new ::FocusCommand(tool, m_win));
RefCmd menu_cmd(new ::ShowMenu(m_win));
setOnClick(focus_cmd, 1);
setOnClick(menu_cmd, 3);
if(win.screen().isReverseWheeling()) {
setOnClick(next_workspace, 5);
setOnClick(prev_workspace, 4);
} else {
setOnClick(next_workspace, 4);
setOnClick(prev_workspace, 5);
}
m_win.hintSig().attach(this);
m_win.titleSig().attach(this);
m_win.focusSig().attach(this);
m_win.attentionSig().attach(this);
FbTk::EventManager::instance()->add(*this, m_icon_window);
reconfigTheme();
update(0);
}
@ -222,20 +118,68 @@ void IconButton::setPixmap(bool use) {
}
}
void IconButton::reconfigTheme() {
if (m_theme.focusedTexture().usePixmap())
m_focused_pm.reset(m_win.screen().imageControl().renderImage(
width(), height(), m_theme.focusedTexture(),
orientation()));
else
m_focused_pm.reset(0);
if (m_theme.unfocusedTexture().usePixmap())
m_unfocused_pm.reset(m_win.screen().imageControl().renderImage(
width(), height(), m_theme.unfocusedTexture(),
orientation()));
else
m_unfocused_pm.reset(0);
setAlpha(parent()->alpha());
if (m_win.isFocused() || m_win.getAttentionState()) {
if (m_focused_pm != 0)
setBackgroundPixmap(m_focused_pm);
else
setBackgroundColor(m_theme.focusedTexture().color());
setGC(m_theme.focusedText().textGC());
setFont(m_theme.focusedText().font());
setJustify(m_theme.focusedText().justify());
setBorderWidth(m_theme.focusedBorder().width());
setBorderColor(m_theme.focusedBorder().color());
} else {
if (m_unfocused_pm != 0)
setBackgroundPixmap(m_unfocused_pm);
else
setBackgroundColor(m_theme.unfocusedTexture().color());
setGC(m_theme.unfocusedText().textGC());
setFont(m_theme.unfocusedText().font());
setJustify(m_theme.unfocusedText().justify());
setBorderWidth(m_theme.unfocusedBorder().width());
setBorderColor(m_theme.unfocusedBorder().color());
}
}
void IconButton::update(FbTk::Subject *subj) {
// if the window's focus state changed, we need to update the background
if (subj == &m_win.focusSig() || subj == &m_win.attentionSig()) {
reconfigTheme();
clear();
return;
}
// we got signal that either title or
// icon pixmap was updated,
// so we refresh everything
// we need to check our client first
if (m_win.clientList().empty())
return;
Display *display = FbTk::App::instance()->display();
int screen = m_win.screen().screenNumber();
if (m_use_pixmap && m_win.usePixmap()) {
if (m_use_pixmap && m_win.icon().pixmap().drawable() != None) {
// setup icon window
m_icon_window.show();
unsigned int w = width();
@ -254,7 +198,8 @@ void IconButton::update(FbTk::Subject *subj) {
m_icon_window.moveResize(iconx, icony, neww, newh);
m_icon_pixmap.copy(m_win.iconPixmap().drawable(), DefaultDepth(display, screen), screen);
m_icon_pixmap.copy(m_win.icon().pixmap().drawable(),
DefaultDepth(display, screen), screen);
m_icon_pixmap.scale(m_icon_window.width(), m_icon_window.height());
// rotate the icon or not?? lets go not for now, and see what they say...
@ -269,8 +214,8 @@ void IconButton::update(FbTk::Subject *subj) {
m_icon_pixmap = 0;
}
if(m_use_pixmap && m_win.useMask()) {
m_icon_mask.copy(m_win.iconMask().drawable(), 0, 0);
if(m_icon_pixmap.drawable() && m_win.icon().mask().drawable() != None) {
m_icon_mask.copy(m_win.icon().mask().drawable(), 0, 0);
m_icon_mask.scale(m_icon_pixmap.width(), m_icon_pixmap.height());
m_icon_mask.rotate(orientation());
} else
@ -287,9 +232,6 @@ void IconButton::update(FbTk::Subject *subj) {
#endif // SHAPE
if (subj == &(m_win.titleSig()))
setText(m_win.title());
if (subj != 0) {
setupWindow();
} else {
@ -298,13 +240,8 @@ void IconButton::update(FbTk::Subject *subj) {
}
void IconButton::setupWindow() {
m_icon_window.clear();
if (!m_win.clientList().empty()) {
setText(m_win.winClient().title());
// draw with x offset and y offset
}
setText(m_win.title());
FbTk::TextButton::clear();
}

View file

@ -25,17 +25,18 @@
#ifndef ICONBUTTON_HH
#define ICONBUTTON_HH
#include "FbTk/CachedPixmap.hh"
#include "FbTk/FbPixmap.hh"
#include "FbTk/Observer.hh"
#include "FbTk/TextButton.hh"
class FluxboxWindow;
class IconbarTool;
class Focusable;
class IconbarTheme;
class IconButton: public FbTk::TextButton, public FbTk::Observer {
public:
IconButton(const IconbarTool& tool, const FbTk::FbWindow &parent,
FbTk::Font &font, FluxboxWindow &window);
IconButton(const FbTk::FbWindow &parent, IconbarTheme &theme,
Focusable &window);
virtual ~IconButton();
void exposeEvent(XExposeEvent &event);
@ -47,11 +48,13 @@ public:
unsigned int width, unsigned int height);
void resize(unsigned int width, unsigned int height);
void reconfigTheme();
void update(FbTk::Subject *subj);
void setPixmap(bool use);
FluxboxWindow &win() { return m_win; }
const FluxboxWindow &win() const { return m_win; }
Focusable &win() { return m_win; }
const Focusable &win() const { return m_win; }
bool setOrientation(FbTk::Orientation orient);
@ -60,11 +63,15 @@ protected:
private:
void setupWindow();
FluxboxWindow &m_win;
Focusable &m_win;
FbTk::FbWindow m_icon_window;
FbTk::FbPixmap m_icon_pixmap;
FbTk::FbPixmap m_icon_mask;
bool m_use_pixmap;
IconbarTheme &m_theme;
// cached pixmaps
FbTk::CachedPixmap m_focused_pm, m_unfocused_pm;
};
#endif // ICONBUTTON_HH

View file

@ -1,66 +0,0 @@
// IconMenu.cc for Fluxbox
// Copyright (c) 2004 Henrik Kinnunen (fluxgen at fluxbox dot org)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id$
#include "IconMenu.hh"
#include "Screen.hh"
#include "IconMenuItem.hh"
#include "Layer.hh"
#include "FbTk/I18n.hh"
#include <typeinfo>
static void updateItems(FbTk::Menu &menu, BScreen &screen) {
menu.removeAll();
BScreen::Icons::iterator it = screen.iconList().begin();
BScreen::Icons::iterator it_end = screen.iconList().end();
for (; it != it_end; ++it) {
FluxboxWindow::ClientList::iterator client_it = (*it)->clientList().begin();
FluxboxWindow::ClientList::iterator client_it_end = (*it)->clientList().end();
for (; client_it != client_it_end; ++client_it)
menu.insert(new IconMenuItem(**client_it));
}
menu.updateMenu();
}
IconMenu::IconMenu(BScreen &screen):
FbMenu(screen.menuTheme(),
screen.imageControl(),
*screen.layerManager().
getLayer(Layer::MENU)) {
_FB_USES_NLS;
setLabel(_FB_XTEXT(Menu, Icons, "Icons", "Iconic windows menu title"));
screen.iconListSig().attach(this);
updateItems(*this, screen);
}
void IconMenu::update(FbTk::Subject *subj) {
if (subj == 0)
FbTk::Menu::update(subj);
else if (typeid(*subj) == typeid(BScreen::ScreenSubject)) {
BScreen &screen = static_cast<BScreen::ScreenSubject *>(subj)->screen();
updateItems(*this, screen);
} else
FbTk::Menu::update(subj);
}

View file

@ -1,38 +0,0 @@
// IconMenu.hh for Fluxbox
// Copyright (c) 2004 Henrik Kinnunen (fluxgen at fluxbox dot org)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id$
#ifndef ICONMENU_HH
#define ICONMENU_HH
#include "FbMenu.hh"
class BScreen;
class IconMenu: public FbMenu {
public:
explicit IconMenu(BScreen &screen);
virtual ~IconMenu() { }
void update(FbTk::Subject *subj);
};
#endif // ICONMENU_HH

View file

@ -1,44 +0,0 @@
// IconMenuItem.hh for Fluxbox Window Manager
// Copyright (c) 2003 Henrik Kinnunen (fluxgen at fluxbox dot org)
// and Simon Bowden (rathnor at users.sourceforge.net)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id$
#ifndef ICONMENUITEM_HH
#define ICONMENUITEM_HH
#include "FbTk/MenuItem.hh"
#include "WinClient.hh"
#include "Window.hh"
class IconMenuItem: public FbTk::MenuItem {
public:
explicit IconMenuItem(WinClient &client):FbTk::MenuItem(client.iconTitle().c_str()), m_client(client) { }
const std::string &label() const { return m_client.iconTitle(); }
void click(int button, int time) {
if (m_client.fbwindow() != 0)
m_client.fbwindow()->deiconify();
}
private:
WinClient &m_client;
};
#endif // ICONMENUITEM_HH

View file

@ -37,8 +37,7 @@ IconbarTheme::IconbarTheme(int screen_num,
m_border(*this, name, altname),
m_focused_text(*this, name + ".focused", altname + ".Focused"),
m_unfocused_text(*this, name + ".unfocused", altname + ".Unfocused"),
m_name(name),
m_alpha(*this, name+".alpha", altname+".Alpha") {
m_name(name), m_altname(altname) {
FbTk::ThemeManager::instance().loadTheme(*this);
@ -58,27 +57,36 @@ bool IconbarTheme::fallback(FbTk::ThemeItem_base &item) {
using namespace FbTk;
ThemeManager &tm = ThemeManager::instance();
// TODO: fix fallbacks for "focused" vs. "focus"
if (&m_focused_texture == &item) {
return (tm.loadItem(item, "window.label.focus", "Window.Label.Focus") ||
tm.loadItem(item, "toolbar.windowLabel", "toolbar.windowLabel"));
} else if (&m_unfocused_texture == &item) {
return (tm.loadItem(item, "window.label.unfocus", "Window.Label.Unfocus") ||
tm.loadItem(item, "toolbar.windowLabel", "toolbar.windowLabel"));
return (tm.loadItem(item, "window.label.unfocus",
"Window.Label.Unfocus") ||
tm.loadItem(item, "toolbar.windowLabel",
"toolbar.windowLabel"));
} else if (&m_empty_texture == &item) {
return (tm.loadItem(item, m_focused_texture.name(), m_focused_texture.altName()) ||
tm.loadItem(item, "toolbar.windowLabel", "toolbar.windowLabel") ||
tm.loadItem(item, "toolbar", "toolbar")
);
return (tm.loadItem(item, m_focused_texture.name(),
m_focused_texture.altName()) ||
tm.loadItem(item, "toolbar.windowLabel", "toolbar.windowLabel")
|| tm.loadItem(item, "toolbar", "toolbar"));
} else if (item.name() == m_name + ".focused.borderWidth" ||
item.name() == m_name + ".unfocused.borderWidth")
// don't fallback for base border, for theme backwards compatibility
return tm.loadItem(item, "borderWidth", "BorderWidth");
return (tm.loadItem(item, m_name + ".borderWidth",
m_altname + ".BorderWidth") ||
tm.loadItem(item, "window.borderWidth", "Window.BorderWidth") ||
tm.loadItem(item, "borderWidth", "BorderWidth"));
else if (item.name() == m_name + ".focused.borderColor" ||
item.name() == m_name + ".unfocused.borderColor")
return tm.loadItem(item, "borderColor", "BorderColor");
return (tm.loadItem(item, m_name + ".borderColor",
m_altname + ".BorderColor") ||
tm.loadItem(item, "window.borderColor", "Window.BorderColor") ||
tm.loadItem(item, "borderColor", "BorderColor"));
else if (item.name() == m_name + ".focused.font" ||
item.name() == m_name + ".unfocused.font")
@ -91,11 +99,10 @@ bool IconbarTheme::fallback(FbTk::ThemeItem_base &item) {
} else if (item.name() == m_name + ".unfocused.textColor") {
return tm.loadItem(item, "window.label.unfocus.textColor", "Window.Label.Unfocus.TextColor");
} else if (item.name() == m_name + ".alpha") {
if (!tm.loadItem(item, "toolbar.alpha", "Toolbar.Alpha")) {
*m_alpha = 255;
}
return true;
} else if (item.name() == m_name + ".focused.justify" ||
item.name() == m_name + ".unfocused.justify") {
return (tm.loadItem(item, m_name + ".justify", m_altname + ".Justify")
|| tm.loadItem(item, "window.justify", "Window.Justify"));
}
return false;

View file

@ -49,14 +49,12 @@ public:
const FbTk::Texture &focusedTexture() const { return *m_focused_texture; }
const FbTk::Texture &unfocusedTexture() const { return *m_unfocused_texture; }
const FbTk::Texture &emptyTexture() const { return *m_empty_texture; }
inline unsigned char alpha() const { return *m_alpha; }
private:
FbTk::ThemeItem<FbTk::Texture> m_focused_texture, m_unfocused_texture, m_empty_texture;
BorderTheme m_focused_border, m_unfocused_border, m_border;
TextTheme m_focused_text, m_unfocused_text;
std::string m_name;
FbTk::ThemeItem<int> m_alpha;
std::string m_name, m_altname;
};
#endif // ICONBARTHEME_HH

View file

@ -24,6 +24,8 @@
#include "IconbarTool.hh"
#include "fluxbox.hh"
#include "WindowCmd.hh"
#include "Screen.hh"
#include "IconbarTheme.hh"
#include "Window.hh"
@ -85,40 +87,6 @@ void FbTk::Resource<IconbarTool::Mode>::setFromString(const char *strval) {
setDefaultValue();
}
template<>
void FbTk::Resource<IconbarTool::WheelMode>::setDefaultValue() {
m_value = IconbarTool::SCREEN;
}
template<>
void FbTk::Resource<IconbarTool::WheelMode>::setFromString(const char* strval) {
if (strncasecmp(strval, "off", strlen("off")) == 0)
m_value = IconbarTool::OFF;
else if (strncasecmp(strval, "on", strlen("on")) == 0)
m_value = IconbarTool::ON;
else if (strncasecmp(strval, "screen", strlen("screen")) == 0)
m_value = IconbarTool::SCREEN;
else
setDefaultValue();
}
template<>
string FbTk::Resource<IconbarTool::WheelMode>::getString() const {
switch(m_value) {
case IconbarTool::ON:
return string("On");
break;
case IconbarTool::SCREEN:
return string("Screen");
break;
case IconbarTool::OFF:
default:
return string("Off");
};
}
template<>
void FbTk::Resource<Container::Alignment>::setDefaultValue() {
m_value = Container::RELATIVE;
@ -290,52 +258,67 @@ void setupModeMenu(FbTk::Menu &menu, IconbarTool &handler) {
}
inline bool checkAddWindow(IconbarTool::Mode mode, const FluxboxWindow &win) {
bool ret_val = false;
// just add the icons that are on the this workspace
switch (mode) {
case IconbarTool::NONE:
break;
case IconbarTool::ICONS:
if (win.isIconic())
ret_val = true;
break;
case IconbarTool::NOICONS:
if (!win.isIconic())
ret_val = true;
break;
case IconbarTool::WORKSPACEICONS:
if(win.workspaceNumber() == win.screen().currentWorkspaceID() &&
win.isIconic())
ret_val = true;
break;
case IconbarTool::WORKSPACENOICONS:
if (win.isIconic())
break;
case IconbarTool::WORKSPACE:
if (win.workspaceNumber() == win.screen().currentWorkspaceID())
ret_val = true;
break;
case IconbarTool::ALLWINDOWS:
ret_val = true;
break;
if (win.isIconHidden() || mode == IconbarTool::NONE)
return false;
if ((mode == IconbarTool::ICONS || mode == IconbarTool::WORKSPACEICONS) &&
!win.isIconic())
return false;
if ((mode == IconbarTool::NOICONS || mode == IconbarTool::WORKSPACENOICONS)
&& win.isIconic())
return false;
if ((mode == IconbarTool::WORKSPACE || mode == IconbarTool::WORKSPACEICONS
|| mode == IconbarTool::WORKSPACENOICONS) &&
win.workspaceNumber() != win.screen().currentWorkspaceID())
return false;
return true;
}
typedef FbTk::RefCount<FbTk::Command> RefCmd;
class ShowMenu: public FbTk::Command {
public:
explicit ShowMenu(FluxboxWindow &win):m_win(win) { }
void execute() {
// hide the menu if it's already showing for this FluxboxWindow
if (m_win.menu().isVisible() && WindowCmd<void>::window() == &m_win) {
m_win.screen().hideMenus();
return;
}
m_win.screen().hideMenus();
// get last button pos
const XEvent &event = Fluxbox::instance()->lastEvent();
int x = event.xbutton.x_root - (m_win.menu().width() / 2);
int y = event.xbutton.y_root - (m_win.menu().height() / 2);
m_win.showMenu(x, y);
}
private:
FluxboxWindow &m_win;
};
class FocusCommand: public FbTk::Command {
public:
explicit FocusCommand(Focusable &win): m_win(win) { }
void execute() {
// this needs to be a local variable, as this object could be destroyed
// if the workspace is changed.
FluxboxWindow *fbwin = m_win.fbwindow();
if (!fbwin)
return;
if (m_win.isFocused())
fbwin->iconify();
else {
m_win.focus();
fbwin->raise();
}
}
if (win.isIconHidden())
ret_val = false;
return ret_val;
}
void removeDuplicate(const IconbarTool::IconList &iconlist, list<FluxboxWindow *> &windowlist) {
IconbarTool::IconList::const_iterator icon_it = iconlist.begin();
IconbarTool::IconList::const_iterator icon_it_end = iconlist.end();
list<FluxboxWindow *>::iterator remove_it = windowlist.end();
for (; icon_it != icon_it_end; ++icon_it)
remove_it = remove(windowlist.begin(), remove_it, &(*icon_it)->win());
// remove already existing windows
windowlist.erase(remove_it, windowlist.end());
}
private:
Focusable &m_win;
};
}; // end anonymous namespace
@ -345,16 +328,9 @@ IconbarTool::IconbarTool(const FbTk::FbWindow &parent, IconbarTheme &theme, BScr
m_screen(screen),
m_icon_container(parent),
m_theme(theme),
m_focused_pm( screen.imageControl() ),
m_unfocused_pm( screen.imageControl() ),
m_focused_err_pm( screen.imageControl() ),
m_unfocused_err_pm( screen.imageControl() ),
m_empty_pm( screen.imageControl() ),
m_rc_mode(screen.resourceManager(), WORKSPACE,
screen.name() + ".iconbar.mode", screen.altName() + ".Iconbar.Mode"),
m_wheel_mode(screen.resourceManager(), OFF,
screen.name() + ".iconbar.wheelMode",
screen.name() + ".iconbar.WheelMode"),
m_rc_alignment(screen.resourceManager(), Container::LEFT,
screen.name() + ".iconbar.alignment", screen.altName() + ".Iconbar.Alignment"),
m_rc_client_width(screen.resourceManager(), 70,
@ -392,15 +368,6 @@ IconbarTool::IconbarTool(const FbTk::FbWindow &parent, IconbarTheme &theme, BScr
screen.clientListSig().attach(this);
screen.iconListSig().attach(this);
screen.currentWorkspaceSig().attach(this);
// setup focus timer
FbTk::RefCount<FbTk::Command> timer_cmd(new FbTk::SimpleCommand<IconbarTool>(*this, &IconbarTool::timedRender));
timeval to;
to.tv_sec = 0;
to.tv_usec = 1; // so it updates next event round
m_focus_timer.setCommand(timer_cmd);
m_focus_timer.setTimeout(to);
m_focus_timer.fireOnce(true);
}
@ -506,18 +473,10 @@ void IconbarTool::update(FbTk::Subject *subj) {
if (subj != 0 && typeid(*subj) == typeid(FluxboxWindow::WinSubject)) {
// we handle everything except die signal here
FluxboxWindow::WinSubject *winsubj = static_cast<FluxboxWindow::WinSubject *>(subj);
if (subj == &(winsubj->win().focusSig())) {
// start focus timer, so we can update without flicker
m_focus_timer.start();
return;
} else if (subj == &(winsubj->win().workspaceSig())) {
if (subj == &(winsubj->win().workspaceSig())) {
// we can ignore this signal if we're in ALLWINDOWS mode
// unless the window was focused and has nothing to revert to
if (mode() == ALLWINDOWS || mode() == ICONS || mode() == NOICONS) {
m_focus_timer.start();
if (mode() == ALLWINDOWS || mode() == ICONS || mode() == NOICONS)
return;
}
// workspace changed for this window, and if it's not on current workspace we remove it
if (m_screen.currentWorkspaceID() != winsubj->win().workspaceNumber()) {
@ -525,30 +484,24 @@ void IconbarTool::update(FbTk::Subject *subj) {
renderTheme();
}
return;
} else if (subj == &(winsubj->win().dieSig())) { // die sig
removeWindow(winsubj->win());
renderTheme();
return; // we don't need to update the entire list
} else if (subj == &(winsubj->win().stateSig())) {
if (!checkAddWindow(mode(), winsubj->win())) {
removeWindow(winsubj->win());
renderTheme();
}
return;
} else if (subj == &(winsubj->win().attentionSig())) {
// render with titlebar focus, on attention
IconButton *button = findButton(winsubj->win());
if (button) {
renderButton(*button, true,
winsubj->win().getAttentionState());
}
return;
} else {
// signal not handled
return;
}
} else if (subj != 0 && typeid(*subj) == typeid(Focusable::FocusSubject)) {
Focusable::FocusSubject *winsubj = static_cast<Focusable::FocusSubject *>(subj);
if (subj == &(winsubj->win().dieSig())) { // die sig
removeWindow(winsubj->win());
renderTheme();
return; // we don't need to update the entire list
}
}
bool remove_all = false; // if we should readd all windows
@ -587,7 +540,7 @@ void IconbarTool::update(FbTk::Subject *subj) {
renderTheme();
}
IconButton *IconbarTool::findButton(FluxboxWindow &win) {
IconButton *IconbarTool::findButton(Focusable &win) {
IconList::iterator icon_it = m_icon_list.begin();
IconList::iterator icon_it_end = m_icon_list.end();
@ -598,25 +551,14 @@ IconButton *IconbarTool::findButton(FluxboxWindow &win) {
return 0;
}
/*
void IconbarTool::renderWindow(FluxboxWindow &win) {
IconButton *button = findButton(win);
if (button == 0)
return;
renderButton(*button);
}
*/
void IconbarTool::updateSizing() {
m_icon_container.setBorderWidth(m_theme.border().width());
IconList::iterator icon_it = m_icon_list.begin();
const IconList::iterator icon_it_end = m_icon_list.end();
for (; icon_it != icon_it_end; ++icon_it) {
if ((*icon_it)->win().isFocused())
(*icon_it)->setBorderWidth(m_theme.focusedBorder().width());
else // unfocused
(*icon_it)->setBorderWidth(m_theme.unfocusedBorder().width());
}
for (; icon_it != icon_it_end; ++icon_it)
(*icon_it)->reconfigTheme();
}
@ -631,127 +573,33 @@ void IconbarTool::renderTheme() {
// update button sizes before we get max width per client!
updateSizing();
unsigned int icon_width = 0, icon_height = 0;
unsigned int icon_width_off=0, icon_height_off=0;
if (orientation() == FbTk::ROT0 || orientation() == FbTk::ROT180) {
icon_width = m_icon_container.maxWidthPerClient();
icon_height = m_icon_container.height();
icon_width_off = 1;
} else {
icon_width = m_icon_container.width();
icon_height = m_icon_container.maxWidthPerClient();
icon_height_off = 1;
}
if (!m_theme.focusedTexture().usePixmap()) {
m_focused_pm.reset( 0 );
m_focused_err_pm.reset( 0 );
} else {
m_focused_pm.reset( m_screen.imageControl().
renderImage(icon_width, icon_height,
m_theme.focusedTexture(), orientation()) );
m_focused_err_pm.reset( m_screen.imageControl().
renderImage(icon_width + icon_width_off,
icon_height + icon_height_off,
m_theme.focusedTexture(), orientation()) );
}
if (!m_theme.unfocusedTexture().usePixmap()) {
m_unfocused_pm.reset( 0 );
m_unfocused_err_pm.reset( 0 );
} else {
m_unfocused_pm.reset( m_screen.imageControl().
renderImage(icon_width, icon_height,
m_theme.unfocusedTexture(), orientation()) );
m_unfocused_err_pm.reset( m_screen.imageControl().
renderImage(icon_width+icon_width_off,
icon_height+icon_height_off,
m_theme.unfocusedTexture(), orientation()) );
}
// if we dont have any icons then we should render empty texture
if (!m_theme.emptyTexture().usePixmap()) {
m_empty_pm.reset( 0 );
m_icon_container.setBackgroundColor(m_theme.emptyTexture().color());
} else {
m_empty_pm.reset( m_screen.imageControl().
renderImage(m_icon_container.width(), m_icon_container.height(),
m_theme.emptyTexture(), orientation()) );
m_empty_pm.reset(m_screen.imageControl().
renderImage(m_icon_container.width(),
m_icon_container.height(),
m_theme.emptyTexture(), orientation()));
m_icon_container.setBackgroundPixmap(m_empty_pm);
}
// set to zero so its consistent and not ugly
m_icon_container.setBorderWidth(m_theme.border().width());
m_icon_container.setBorderColor(m_theme.border().color());
m_icon_container.setAlpha(m_alpha);
// update buttons
IconList::iterator icon_it = m_icon_list.begin();
const IconList::iterator icon_it_end = m_icon_list.end();
for (; icon_it != icon_it_end; ++icon_it) {
for (; icon_it != icon_it_end; ++icon_it)
renderButton(*(*icon_it));
}
}
void IconbarTool::renderButton(IconButton &button, bool clear,
int focusOption) {
void IconbarTool::renderButton(IconButton &button, bool clear) {
button.setPixmap(*m_rc_use_pixmap);
button.setAlpha(m_alpha);
button.setTextPadding(*m_rc_client_padding);
// The last button is always the regular width
bool wider_button = false;
if (!m_icon_container.empty()) {
if (button.orientation() == FbTk::ROT0 || button.orientation() == FbTk::ROT180)
wider_button = button.width() != m_icon_container.back()->width();
else
wider_button = button.height() != m_icon_container.back()->height();
// wider_button = (button.width() != m_icon_container.maxWidthPerClient() || // height to cover both orients
// button.height() != m_icon_container.back()->height());
}
if (focusOption == 1 ||
(focusOption == -1 &&
button.win().isFocused())) {
// focused texture
if (button.win().isFocused())
m_icon_container.setSelected(m_icon_container.find(&button));
button.setGC(m_theme.focusedText().textGC());
button.setFont(m_theme.focusedText().font());
button.setJustify(m_theme.focusedText().justify());
button.setBorderWidth(m_theme.focusedBorder().width());
button.setBorderColor(m_theme.focusedBorder().color());
if (!wider_button && m_focused_pm != 0)
button.setBackgroundPixmap(m_focused_pm);
else if (wider_button && m_focused_err_pm != 0)
button.setBackgroundPixmap(m_focused_err_pm);
else
button.setBackgroundColor(m_theme.focusedTexture().color());
} else { // unfocused
if (m_icon_container.selected() == &button)
m_icon_container.setSelected(-1);
button.setGC(m_theme.unfocusedText().textGC());
button.setFont(m_theme.unfocusedText().font());
button.setJustify(m_theme.unfocusedText().justify());
button.setBorderWidth(m_theme.unfocusedBorder().width());
button.setBorderColor(m_theme.unfocusedBorder().color());
if (!wider_button && m_unfocused_pm != 0)
button.setBackgroundPixmap(m_unfocused_pm);
else if (wider_button && m_unfocused_err_pm != 0)
button.setBackgroundPixmap(m_unfocused_err_pm);
else
button.setBackgroundColor(m_theme.unfocusedTexture().color());
}
button.reconfigTheme();
if (clear)
button.clear(); // the clear also updates transparent
}
@ -764,7 +612,7 @@ void IconbarTool::deleteIcons() {
}
}
void IconbarTool::removeWindow(FluxboxWindow &win) {
void IconbarTool::removeWindow(Focusable &win) {
// got window die signal, lets find and remove the window
IconList::iterator it = m_icon_list.begin();
IconList::iterator it_end = m_icon_list.end();
@ -780,12 +628,11 @@ void IconbarTool::removeWindow(FluxboxWindow &win) {
cerr<<"IconbarTool::"<<__FUNCTION__<<"( 0x"<<&win<<" title = "<<win.title()<<") found!"<<endl;
#endif // DEBUG
// detach from all signals
win.focusSig().detach(this);
win.dieSig().detach(this);
win.workspaceSig().detach(this);
win.stateSig().detach(this);
win.titleSig().detach(this);
if (win.fbwindow()) {
win.fbwindow()->workspaceSig().detach(this);
win.fbwindow()->stateSig().detach(this);
}
// remove from list and render theme again
IconButton *button = *it;
@ -797,46 +644,46 @@ void IconbarTool::removeWindow(FluxboxWindow &win) {
}
void IconbarTool::addWindow(FluxboxWindow &win) {
// we just want windows that has clients
if (win.clientList().empty() || win.isIconHidden() )
void IconbarTool::addWindow(Focusable &win) {
// we just want windows that have clients
FluxboxWindow *fbwin = win.fbwindow();
if (!fbwin || fbwin->clientList().empty() || fbwin->isIconHidden())
return;
#ifdef DEBUG
cerr<<"IconbarTool::addWindow(0x"<<&win<<" title = "<<win.title()<<")"<<endl;
#endif // DEBUG
IconButton *button = new IconButton(*this,
m_icon_container,
m_theme.focusedText().font(),
win);
IconButton *button = new IconButton(m_icon_container, m_theme, win);
RefCmd focus_cmd(new ::FocusCommand(win));
RefCmd menu_cmd(new ::ShowMenu(*fbwin));
button->setOnClick(focus_cmd, 1);
button->setOnClick(menu_cmd, 3);
renderButton(*button, false); // update the attributes, but don't clear it
m_icon_container.insertItem(button);
m_icon_list.push_back(button);
// dont forget to detach signal in removeWindow
win.focusSig().attach(this);
win.dieSig().attach(this);
win.workspaceSig().attach(this);
win.stateSig().attach(this);
win.attentionSig().attach(this);
fbwin->workspaceSig().attach(this);
fbwin->stateSig().attach(this);
}
void IconbarTool::updateList() {
list<WinClient *> ordered_list =
m_screen.focusControl().creationOrderList();
list<WinClient *>::iterator it = ordered_list.begin();
list<WinClient *>::iterator it_end = ordered_list.end();
list<Focusable *> ordered_list =
m_screen.focusControl().creationOrderWinList();
list<Focusable *>::iterator it = ordered_list.begin();
list<Focusable *>::iterator it_end = ordered_list.end();
for (; it != it_end; ++it) {
if ((*it)->fbwindow() && checkAddWindow(mode(), *(*it)->fbwindow()) &&
!checkDuplicate(*(*it)->fbwindow()))
addWindow(*(*it)->fbwindow());
!checkDuplicate(**it))
addWindow(**it);
}
renderTheme();
}
bool IconbarTool::checkDuplicate(FluxboxWindow &win) {
bool IconbarTool::checkDuplicate(Focusable &win) {
IconList::iterator it = m_icon_list.begin();
IconList::iterator it_end = m_icon_list.end();
for (; it != it_end; ++it) {
@ -846,27 +693,6 @@ bool IconbarTool::checkDuplicate(FluxboxWindow &win) {
return false;
}
void IconbarTool::timedRender() {
WinClient *client = FocusControl::focusedWindow();
IconButton *current_button = static_cast<IconButton *>(m_icon_container.selected());
if (client == 0 || client->fbwindow() == 0) {
if (current_button != 0)
renderButton(*current_button);
return;
}
IconButton *button = findButton(*client->fbwindow());
// if old window is the same as the new focused window then ignore this render
// else render old client and new client
if (button == current_button)
return;
if (button != 0)
renderButton(*button);
if (current_button != 0)
renderButton(*current_button);
}
void IconbarTool::setOrientation(FbTk::Orientation orient) {
m_icon_container.setOrientation(orient);
ToolbarItem::setOrientation(orient);

View file

@ -41,7 +41,7 @@
class IconbarTheme;
class BScreen;
class IconButton;
class FluxboxWindow;
class Focusable;
class IconbarTool: public ToolbarItem, public FbTk::Observer {
public:
@ -57,13 +57,6 @@ public:
ALLWINDOWS ///< all windows and all icons from all workspaces
};
/// wheeling on iconbutton
enum WheelMode {
OFF, ///< no wheeling, default mode
ON, ///< enabled wheeling
SCREEN ///< in perfect harmony with desktopwheeling-value
};
IconbarTool(const FbTk::FbWindow &parent, IconbarTheme &theme,
BScreen &screen, FbTk::Menu &menu);
~IconbarTool();
@ -85,60 +78,48 @@ public:
unsigned int borderWidth() const;
Mode mode() const { return *m_rc_mode; }
WheelMode wheelMode() const { return *m_wheel_mode; }
void setOrientation(FbTk::Orientation orient);
Container::Alignment alignment() const { return m_icon_container.alignment(); }
const BScreen &screen() const { return m_screen; }
private:
/// @return button associated with window
IconButton *findButton(FluxboxWindow &win);
IconButton *findButton(Focusable &win);
void updateSizing();
/// render single button that holds win
// void renderWindow(FluxboxWindow &win);
/// render single button, and probably apply changes (clear)
/// @param button the button to render
/// @param clear if the window should be cleared first
/// @param focusOption -1 = use window focus, 0 = render no focus, 1 = render focus
void renderButton(IconButton &button, bool clear = true,
int focusOption = -1);
void renderButton(IconButton &button, bool clear = true);
/// render all buttons
void renderTheme();
void renderTheme(unsigned char alpha);
/// destroy all icons
void deleteIcons();
/// remove a single window
void removeWindow(FluxboxWindow &win);
void removeWindow(Focusable &win);
/// add a single window
void addWindow(FluxboxWindow &win);
void addWindow(Focusable &win);
/// add icons to the list
void updateList();
/// check if window is already in the list
bool checkDuplicate(FluxboxWindow &win);
/// so we can update current window without flicker
void timedRender();
bool checkDuplicate(Focusable &win);
BScreen &m_screen;
Container m_icon_container;
IconbarTheme &m_theme;
// cached pixmaps
FbTk::CachedPixmap m_focused_pm, m_unfocused_pm;
// some are a fraction bigger due to rounding
FbTk::CachedPixmap m_focused_err_pm, m_unfocused_err_pm;
FbTk::CachedPixmap m_empty_pm; ///< pixmap for empty container
IconList m_icon_list;
FbTk::Resource<Mode> m_rc_mode;
FbTk::Resource<WheelMode> m_wheel_mode;
FbTk::Resource<Container::Alignment> m_rc_alignment; ///< alignment of buttons
FbTk::Resource<int> m_rc_client_width; ///< size of client button in LEFT/RIGHT mode
FbTk::Resource<unsigned int> m_rc_client_padding; ///< padding of the text
FbTk::Resource<bool> m_rc_use_pixmap; ///< if iconbar should use win pixmap or not
FbTk::Timer m_focus_timer; ///< so we can update current window without flicker while changing attached clients
FbMenu m_menu;
unsigned char m_alpha;
};

View file

@ -101,18 +101,7 @@ using std::vector;
using std::ifstream;
using std::pair;
Keys::Keys():
m_display(FbTk::App::instance()->display())
{
typedef std::list<BScreen *> ScreenList;
ScreenList screen_list = Fluxbox::instance()->screenList();
ScreenList::iterator it = screen_list.begin();
ScreenList::iterator it_end = screen_list.end();
for (; it != it_end; ++it)
m_window_list.push_back(RootWindow(m_display,(*it)->screenNumber()));
}
Keys::Keys(): m_display(FbTk::App::instance()->display()) { }
Keys::~Keys() {
ungrabKeys();
@ -127,37 +116,69 @@ void Keys::deleteTree() {
m_map.clear();
}
// keys are only grabbed in global context
void Keys::grabKey(unsigned int key, unsigned int mod) {
std::list<Window>::iterator it = m_window_list.begin();
std::list<Window>::iterator it_end = m_window_list.end();
WindowMap::iterator it = m_window_map.begin();
WindowMap::iterator it_end = m_window_map.end();
for (; it != it_end; ++it)
FbTk::KeyUtil::grabKey(key, mod, *it);
for (; it != it_end; ++it) {
if ((it->second & Keys::GLOBAL) > 0)
FbTk::KeyUtil::grabKey(key, mod, it->first);
}
}
// keys are only grabbed in global context
void Keys::ungrabKeys() {
std::list<Window>::iterator it = m_window_list.begin();
std::list<Window>::iterator it_end = m_window_list.end();
WindowMap::iterator it = m_window_map.begin();
WindowMap::iterator it_end = m_window_map.end();
for (; it != it_end; ++it)
FbTk::KeyUtil::ungrabKeys(*it);
for (; it != it_end; ++it) {
if ((it->second & Keys::GLOBAL) > 0)
FbTk::KeyUtil::ungrabKeys(it->first);
}
}
void Keys::grabButton(unsigned int button, unsigned int mod) {
std::list<Window>::iterator it = m_window_list.begin();
std::list<Window>::iterator it_end = m_window_list.end();
// ON_DESKTOP context doesn't need to be grabbed
void Keys::grabButton(unsigned int button, unsigned int mod, int context) {
WindowMap::iterator it = m_window_map.begin();
WindowMap::iterator it_end = m_window_map.end();
for (; it != it_end; ++it)
FbTk::KeyUtil::grabButton(button, mod, *it,
ButtonPressMask|ButtonReleaseMask);
for (; it != it_end; ++it) {
if ((context & it->second & ~Keys::ON_DESKTOP) > 0)
FbTk::KeyUtil::grabButton(button, mod, it->first,
ButtonPressMask|ButtonReleaseMask);
}
}
void Keys::ungrabButtons() {
std::list<Window>::iterator it = m_window_list.begin();
std::list<Window>::iterator it_end = m_window_list.end();
WindowMap::iterator it = m_window_map.begin();
WindowMap::iterator it_end = m_window_map.end();
for (; it != it_end; ++it)
FbTk::KeyUtil::ungrabButtons(*it);
FbTk::KeyUtil::ungrabButtons(it->first);
}
void Keys::grabWindow(Window win) {
if (!m_keylist)
return;
// make sure the window is in our list
WindowMap::iterator win_it = m_window_map.find(win);
if (win_it == m_window_map.end())
return;
keylist_t::iterator it = m_keylist->keylist.begin();
keylist_t::iterator it_end = m_keylist->keylist.end();
for (; it != it_end; ++it) {
// keys are only grabbed in global context
if ((win_it->second & Keys::GLOBAL) > 0 && (*it)->type == KeyPress)
FbTk::KeyUtil::grabKey((*it)->key, (*it)->mod, win);
// ON_DESKTOP buttons don't need to be grabbed
else if ((win_it->second & (*it)->context & ~Keys::ON_DESKTOP) > 0 &&
(*it)->type == ButtonPress)
FbTk::KeyUtil::grabButton((*it)->key, (*it)->mod, win,
ButtonPressMask|ButtonReleaseMask);
}
}
/**
@ -278,6 +299,8 @@ bool Keys::addBinding(const string &linebuffer) {
mod |= tmpmod; //If it's a modifier
else if (strcasecmp("ondesktop", val[argc].c_str()) == 0)
context |= ON_DESKTOP;
else if (strcasecmp("ontoolbar", val[argc].c_str()) == 0)
context |= ON_TOOLBAR;
else if (strcasecmp("NONE",val[argc].c_str())) {
// check if it's a mouse button
if (!strcasecmp(val[argc].substr(0,5).c_str(), "mouse") &&
@ -349,16 +372,15 @@ bool Keys::addBinding(const string &linebuffer) {
}
// return true if bound to a command, else false
bool Keys::doAction(int type, unsigned int mods, unsigned int key) {
bool Keys::doAction(int type, unsigned int mods, unsigned int key,
int context) {
static t_key* next_key = m_keylist;
if (!next_key)
next_key = m_keylist;
mods = FbTk::KeyUtil::instance().cleanMods(mods);
// at the moment, any key/button that gets here is on root window
// context will need to be added as an argument to doAction, though
t_key *temp_key = next_key->find(type, mods, key, ON_DESKTOP|GLOBAL);
t_key *temp_key = next_key->find(type, mods, key, context);
// need to save this for emacs-style keybindings
static t_key *saved_keymode = 0;
@ -396,6 +418,19 @@ bool Keys::doAction(int type, unsigned int mods, unsigned int key) {
return true;
}
/// adds the window to m_window_map, so we know to grab buttons on it
void Keys::registerWindow(Window win, int context) {
m_window_map[win] = context;
grabWindow(win);
}
/// remove the window from the window map, probably being deleted
void Keys::unregisterWindow(Window win) {
FbTk::KeyUtil::ungrabKeys(win);
FbTk::KeyUtil::ungrabButtons(win);
m_window_map.erase(win);
}
/**
deletes the tree and load configuration
returns true on success else false
@ -419,14 +454,13 @@ void Keys::setKeyMode(t_key *keyMode) {
keylist_t::iterator it_end = keyMode->keylist.end();
for (; it != it_end; ++it) {
if ((*it)->type == KeyPress)
grabKey((*it)->key,(*it)->mod);
else if ((*it)->context == GLOBAL)
grabButton((*it)->key,(*it)->mod);
// we must use root window's event mask to get ON_DESKTOP events
grabKey((*it)->key, (*it)->mod);
else
grabButton((*it)->key, (*it)->mod, (*it)->context);
}
m_keylist = keyMode;
}
Keys::t_key::t_key(int type_, unsigned int mod_, unsigned int key_,
int context_, FbTk::RefCount<FbTk::Command> command) {
key = key_;

View file

@ -25,7 +25,6 @@
#define KEYS_HH
#include <string>
#include <vector>
#include <list>
#include <map>
#include <X11/Xlib.h>
@ -53,11 +52,7 @@ public:
// and so on...
};
/**
Constructor
@param display display connection
@param filename file to load, default none
*/
/// constructor
explicit Keys();
/// destructor
~Keys();
@ -80,7 +75,12 @@ public:
/**
do action from XKeyEvent; return false if not bound to anything
*/
bool doAction(int type, unsigned int mods, unsigned int key);
bool doAction(int type, unsigned int mods, unsigned int key, int context);
/// register a window so that proper keys/buttons get grabbed on it
void registerWindow(Window win, int context);
/// unregister window
void unregisterWindow(Window win);
/**
Reload configuration from filename
@ -94,8 +94,9 @@ private:
void grabKey(unsigned int key, unsigned int mod);
void ungrabKeys();
void grabButton(unsigned int button, unsigned int mod);
void grabButton(unsigned int button, unsigned int mod, int context);
void ungrabButtons();
void grabWindow(Window win);
// Load default keybindings for when there are errors loading the initial one
void loadDefaults();
@ -103,7 +104,7 @@ private:
std::string m_filename;
class t_key;
typedef std::vector<t_key*> keylist_t;
typedef std::list<t_key*> keylist_t;
class t_key {
public:
@ -116,11 +117,12 @@ private:
int context_) {
// t_key ctor sets context_ of 0 to GLOBAL, so we must here too
context_ = context_ ? context_ : GLOBAL;
for (size_t i = 0; i < keylist.size(); i++) {
if (keylist[i]->type == type_ && keylist[i]->key == key_ &&
(keylist[i]->context & context_) > 0 && keylist[i]->mod ==
keylist_t::iterator it = keylist.begin(), it_end = keylist.end();
for (; it != it_end; it++) {
if ((*it)->type == type_ && (*it)->key == key_ &&
((*it)->context & context_) > 0 && (*it)->mod ==
FbTk::KeyUtil::instance().isolateModifierMask(mod_))
return keylist[i];
return *it;
}
return 0;
}
@ -141,7 +143,9 @@ private:
keyspace_t m_map;
Display *m_display; ///< display connection
std::list<Window> m_window_list;
typedef std::map<Window, int> WindowMap;
WindowMap m_window_map;
};
#endif // KEYS_HH

View file

@ -22,6 +22,9 @@
#ifndef LAYER_HH
#define LAYER_HH
#include <string>
using std::string;
/**
* (This is not the layer->raise/lower handling stuff, @see FbTk::Layer)
* Class to store layer numbers (special Resource type)
@ -42,7 +45,53 @@ public:
};
explicit Layer(int i) : m_num(i) {};
static int getNumFromString(string &str) {
int tempnum = 0;
if (sscanf(str.c_str(), "%d", &tempnum) == 1)
return tempnum;
if (strcasecmp(str.c_str(), "Menu") == 0)
return ::Layer::MENU;
if (strcasecmp(str.c_str(), "AboveDock") == 0)
return ::Layer::ABOVE_DOCK;
if (strcasecmp(str.c_str(), "Dock") == 0)
return ::Layer::DOCK;
if (strcasecmp(str.c_str(), "Top") == 0)
return ::Layer::TOP;
if (strcasecmp(str.c_str(), "Normal") == 0)
return ::Layer::NORMAL;
if (strcasecmp(str.c_str(), "Bottom") == 0)
return ::Layer::BOTTOM;
if (strcasecmp(str.c_str(), "Desktop") == 0)
return ::Layer::DESKTOP;
return -1;
}
static string getString(int num) {
switch (num) {
case ::Layer::MENU:
return string("Menu");
case ::Layer::ABOVE_DOCK:
return string("AboveDock");
case ::Layer::DOCK:
return string("Dock");
case ::Layer::TOP:
return string("Top");
case ::Layer::NORMAL:
return string("Normal");
case ::Layer::BOTTOM:
return string("Bottom");
case ::Layer::DESKTOP:
return string("Desktop");
default:
char tmpstr[128];
sprintf(tmpstr, "%d", num);
return string(tmpstr);
}
}
int getNum() const { return m_num; }
string getString() const { return getString(m_num); }
Layer &operator=(int num) { m_num = num; return *this; }

View file

@ -87,9 +87,8 @@ TOOLBAR_SOURCE = Toolbar.hh Toolbar.cc \
ToolbarTheme.hh ToolbarTheme.cc ToolbarItem.hh ToolbarItem.cc \
ClockTool.hh ClockTool.cc \
WorkspaceNameTool.hh WorkspaceNameTool.cc WorkspaceNameTheme.hh \
IconbarTool.hh IconbarTool.cc IconbarTheme.hh IconbarTheme.cc \
IconbarTool.hh IconbarTool.cc \
ToolTheme.hh ToolTheme.cc \
IconButton.hh IconButton.cc \
SystemTray.hh SystemTray.cc \
GenericTool.hh GenericTool.cc \
ButtonTool.hh ButtonTool.cc ButtonTheme.hh ButtonTheme.cc \
@ -102,7 +101,6 @@ fluxbox_SOURCES = AtomHandler.hh ArrowButton.hh ArrowButton.cc \
FbWinFrameTheme.hh FbWinFrameTheme.cc \
fluxbox.cc fluxbox.hh \
Keys.cc Keys.hh main.cc \
Netizen.cc Netizen.hh \
RootTheme.hh RootTheme.cc \
FbRootWindow.hh FbRootWindow.cc \
Screen.cc Screen.hh ScreenResources.cc \
@ -117,7 +115,6 @@ fluxbox_SOURCES = AtomHandler.hh ArrowButton.hh ArrowButton.cc \
WinClient.hh WinClient.cc \
Strut.hh \
Xinerama.hh \
IconMenuItem.hh \
Xutil.hh Xutil.cc \
CurrentWindowCmd.hh CurrentWindowCmd.cc \
WorkspaceCmd.hh WorkspaceCmd.cc \
@ -135,7 +132,7 @@ fluxbox_SOURCES = AtomHandler.hh ArrowButton.hh ArrowButton.cc \
StyleMenuItem.hh StyleMenuItem.cc \
RootCmdMenuItem.hh RootCmdMenuItem.cc\
MenuCreator.hh MenuCreator.cc \
IconMenu.hh IconMenu.cc \
ClientMenu.hh ClientMenu.cc \
WorkspaceMenu.hh WorkspaceMenu.cc \
FocusModelMenuItem.hh \
ToggleMenu.hh \
@ -146,11 +143,13 @@ fluxbox_SOURCES = AtomHandler.hh ArrowButton.hh ArrowButton.cc \
PlacementStrategy.hh \
CascadePlacement.hh CascadePlacement.cc \
ColSmartPlacement.hh ColSmartPlacement.cc \
MinOverlapPlacement.hh MinOverlapPlacement.cc \
RowSmartPlacement.hh RowSmartPlacement.cc \
ScreenPlacement.hh ScreenPlacement.cc \
UnderMousePlacement.hh UnderMousePlacement.cc \
WinClientUtil.hh WinClientUtil.cc \
AttentionNoticeHandler.hh AttentionNoticeHandler.cc \
IconButton.hh IconButton.cc \
IconbarTheme.hh IconbarTheme.cc \
STLUtil.hh \
${newwmspec_SOURCE} ${gnome_SOURCE} \
${REMEMBER_SOURCE} ${TOOLBAR_SOURCE}

View file

@ -31,8 +31,7 @@
#include "Window.hh"
#include "WindowCmd.hh"
#include "FbMenu.hh"
#include "IconMenu.hh"
#include "ClientMenu.hh"
#include "WorkspaceMenu.hh"
#include "LayerMenu.hh"
#include "SendToMenu.hh"
@ -52,7 +51,6 @@
#include "FbTk/StringUtil.hh"
#include "FbTk/FileUtil.hh"
#include "FbTk/MenuSeparator.hh"
#include "FbTk/MenuIcon.hh"
#include "FbTk/Transparent.hh"
#include <iostream>
@ -470,8 +468,8 @@ FbTk::Menu *MenuCreator::createFromFile(const string &filename, int screen_numbe
bool MenuCreator::createFromFile(const string &filename,
FbTk::Menu &inject_into, bool require_begin) {
string real_filename = FbTk::StringUtil::expandFilename(filename);
FbMenuParser parser(real_filename);
if (!parser.isLoaded())
return false;
@ -521,7 +519,8 @@ FbTk::Menu *MenuCreator::createMenuType(const string &type, int screen_num) {
if (screen == 0)
return 0;
if (type == "iconmenu") {
return new IconMenu(*screen);
return new ClientMenu(*screen, screen->iconList(),
&screen->iconListSig());
} else if (type == "workspacemenu") {
return new WorkspaceMenu(*screen);
} else if (type == "windowmenu") {

186
src/MinOverlapPlacement.cc Normal file
View file

@ -0,0 +1,186 @@
// MinOverlapPlacement.cc
// Copyright (c) 2007 Fluxbox Team (fluxgen at fluxbox dot org)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR (*it)
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR (*it)WISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR (*it)
// DEALINGS IN THE SOFTWARE.
// $Id$
#include "MinOverlapPlacement.hh"
#include "Window.hh"
#include "Screen.hh"
ScreenPlacement::PlacementPolicy MinOverlapPlacement::s_policy = ScreenPlacement::ROWMINOVERLAPPLACEMENT;
ScreenPlacement::RowDirection MinOverlapPlacement::s_row_dir = ScreenPlacement::LEFTRIGHT;
ScreenPlacement::ColumnDirection MinOverlapPlacement::s_col_dir = ScreenPlacement::TOPBOTTOM;
MinOverlapPlacement::MinOverlapPlacement(ScreenPlacement::PlacementPolicy policy) {
s_policy = policy;
}
bool MinOverlapPlacement::placeWindow(
const std::list<FluxboxWindow *> &windowlist,
const FluxboxWindow &win, int &place_x, int &place_y) {
// view (screen + head) constraints
int head = (signed) win.screen().getCurrHead();
int head_left = (signed) win.screen().maxLeft(head);
int head_right = (signed) win.screen().maxRight(head);
int head_top = (signed) win.screen().maxTop(head);
int head_bot = (signed) win.screen().maxBottom(head);
const ScreenPlacement &screen_placement =
dynamic_cast<const ScreenPlacement &>(win.screen().placementStrategy());
s_row_dir = screen_placement.rowDirection();
s_col_dir = screen_placement.colDirection();
int win_w = win.width() + win.fbWindow().borderWidth()*2 + win.widthOffset();
int win_h = win.height() + win.fbWindow().borderWidth()*2 + win.heightOffset();
// we keep a set of open spaces on the desktop, sorted by size/location
std::set<Region> region_set;
// initialize the set of regions to contain the entire head
region_set.insert(Region(Region::TOPLEFT, head_left, head_top));
region_set.insert(Region(Region::TOPRIGHT, head_right - win_w, head_top));
region_set.insert(Region(Region::BOTTOMLEFT, head_left, head_bot - win_h));
region_set.insert(Region(Region::BOTTOMRIGHT, head_right - win_w,
head_bot - win_h));
// go through the list of windows, creating other reasonable placements
// at the end, we'll find the one with minimum overlap
// the size of this set is at most 2(n+2)(n+1) (n = number of windows)
// finding overlaps is therefore O(n^3), but it can probably be improved
std::list<FluxboxWindow *>::const_reverse_iterator it = windowlist.rbegin(),
it_end = windowlist.rend();
for (; it != it_end; ++it) {
// get the dimensions of the window
int left = (*it)->x() - (*it)->xOffset();
int top = (*it)->y() - (*it)->yOffset();
int right = left + (*it)->width() +
2*(*it)->frame().window().borderWidth() +
(*it)->widthOffset();
int bottom = top + (*it)->height() +
2*(*it)->frame().window().borderWidth() +
(*it)->heightOffset();
// go through the list of regions
// if this window overlaps that region and the new window still fits,
// it will create new regions to test
std::set<Region>::iterator reg_it = region_set.begin();
for (; reg_it != region_set.end(); ++reg_it) {
switch (reg_it->corner) {
case Region::TOPLEFT:
if (right > reg_it->x && bottom > reg_it->y) {
if (bottom + win_h <= head_bot)
region_set.insert(Region(Region::TOPLEFT,
reg_it->x, bottom));
if (right + win_w <= head_right)
region_set.insert(Region(Region::TOPLEFT,
right, reg_it->y));
}
break;
case Region::TOPRIGHT:
if (left < reg_it->x + win_w && bottom > reg_it->y) {
if (bottom + win_h <= head_bot)
region_set.insert(Region(Region::TOPRIGHT,
reg_it->x, bottom));
if (left - win_w >= head_left)
region_set.insert(Region(Region::TOPRIGHT,
left - win_w, reg_it->y));
}
break;
case Region::BOTTOMRIGHT:
if (left < reg_it->x + win_w && top < reg_it->y + win_h) {
if (top - win_h >= head_top)
region_set.insert(Region(Region::BOTTOMRIGHT,
reg_it->x, top - win_h));
if (left - win_w >= head_left)
region_set.insert(Region(Region::BOTTOMRIGHT,
left - win_w, reg_it->y));
}
break;
case Region::BOTTOMLEFT:
if (right > reg_it->x && top < reg_it->y + win_h) {
if (top - win_h >= head_top)
region_set.insert(Region(Region::BOTTOMLEFT,
reg_it->x, top - win_h));
if (right + win_w <= head_right)
region_set.insert(Region(Region::BOTTOMLEFT,
right, reg_it->y));
}
break;
}
}
}
// choose the region with minimum overlap
int min_so_far = win_w * win_h * windowlist.size() + 1;
std::set<Region>::iterator min_reg = region_set.end();
std::set<Region>::iterator reg_it = region_set.begin();
for (; reg_it != region_set.end(); ++reg_it) {
int overlap = 0;
it = windowlist.rbegin();
for (; it != windowlist.rend(); ++it) {
// get the dimensions of the window
int left = (*it)->x() - (*it)->xOffset();
int top = (*it)->y() - (*it)->yOffset();
int right = left + (*it)->width() +
2*(*it)->frame().window().borderWidth() +
(*it)->widthOffset();
int bottom = top + (*it)->height() +
2*(*it)->frame().window().borderWidth() +
(*it)->heightOffset();
// get the coordinates of the overlap region
int min_right = (right > reg_it->x + win_w) ?
reg_it->x + win_w : right;
int min_bottom = (bottom > reg_it->y + win_h) ?
reg_it->y + win_h : bottom;
int max_left = (left > reg_it->x) ? left : reg_it->x;
int max_top = (top > reg_it->y) ? top : reg_it->y;
// now compute the overlap and add to running total
if (min_right > max_left && min_bottom > max_top)
overlap += (min_right - max_left) * (min_bottom - max_top);
}
// if this placement is better, use it
if (overlap < min_so_far) {
min_reg = reg_it;
min_so_far = overlap;
if (overlap == 0) // can't do better than this
break;
}
}
// place window
place_x = min_reg->x + win.xOffset();
place_y = min_reg->y + win.yOffset();
return true;
}

View file

@ -0,0 +1,83 @@
// MinOverlapPlacement.hh
// Copyright (c) 2007 Fluxbox Team (fluxgen at fluxbox dot org)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id$
#ifndef MINOVERLAPPLACEMENT_HH
#define MINOVERLAPPLACEMENT_HH
#include "ScreenPlacement.hh"
class MinOverlapPlacement: public PlacementStrategy {
public:
MinOverlapPlacement(ScreenPlacement::PlacementPolicy policy);
bool placeWindow(const std::list<FluxboxWindow *> &windowlist,
const FluxboxWindow &win,
int &place_x, int &place_y);
private:
class Region {
public:
enum Corner {
TOPLEFT,
TOPRIGHT,
BOTTOMLEFT,
BOTTOMRIGHT
} corner; // indicates the corner of the window that will be placed
Region(Corner _corner, int _x, int _y):
corner(_corner), x(_x), y(_y) { };
// do all STL set implementations use this for sorting?
bool operator <(const Region &o) const {
// for now, I'm assuming RowSmartPlacement, so y is more important
switch (MinOverlapPlacement::s_policy) {
case ScreenPlacement::ROWMINOVERLAPPLACEMENT:
// if we're making rows, y-value is most important
if (y != o.y)
return ((y < o.y) ^ (s_col_dir == ScreenPlacement::BOTTOMTOP));
if (x != o.x)
return ((x < o.x) ^ (s_row_dir == ScreenPlacement::RIGHTLEFT));
return (corner < o.corner);
case ScreenPlacement::COLMINOVERLAPPLACEMENT:
// if we're making columns, x-value is most important
if (x != o.x)
return ((x < o.x) ^ (s_row_dir == ScreenPlacement::RIGHTLEFT));
if (y != o.y)
return ((y < o.y) ^ (s_col_dir == ScreenPlacement::BOTTOMTOP));
return (corner < o.corner);
default:
return false;
}
}
// position where the top left corner of the window will be placed
int x, y;
};
static ScreenPlacement::PlacementPolicy s_policy;
static ScreenPlacement::RowDirection s_row_dir;
static ScreenPlacement::ColumnDirection s_col_dir;
};
#endif // MINOVERLAPPLACEMENT_HH

View file

@ -1,112 +0,0 @@
// Netizen.cc for Fluxbox
// Copyright (c) 2001 - 2003 Henrik Kinnunen (fluxgen at fluxbox dot org)
//
// Netizen.cc for Blackbox - An X11 Window Manager
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#include "Netizen.hh"
#include "Screen.hh"
#include "FbAtoms.hh"
#include "FbTk/App.hh"
Netizen::Netizen(const BScreen &scr, Window win):
m_screen(scr),
m_display(FbTk::App::instance()->display()),
m_window(win) {
event.type = ClientMessage;
event.xclient.message_type = FbAtoms::instance()->getFluxboxStructureMessagesAtom();
event.xclient.display = m_display;
event.xclient.window = window();
event.xclient.format = 32;
event.xclient.data.l[0] = FbAtoms::instance()->getFluxboxNotifyStartupAtom();
event.xclient.data.l[1] = event.xclient.data.l[2] =
event.xclient.data.l[3] = event.xclient.data.l[4] = 0l;
XSendEvent(m_display, window(), False, NoEventMask, &event);
}
void Netizen::sendWorkspaceCount() {
event.xclient.data.l[0] = FbAtoms::instance()->getFluxboxNotifyWorkspaceCountAtom();
event.xclient.data.l[1] = m_screen.numberOfWorkspaces();
XSendEvent(m_display, window(), False, NoEventMask, &event);
}
void Netizen::sendCurrentWorkspace() {
event.xclient.data.l[0] = FbAtoms::instance()->getFluxboxNotifyCurrentWorkspaceAtom();
event.xclient.data.l[1] = m_screen.currentWorkspaceID();
XSendEvent(m_display, window(), False, NoEventMask, &event);
}
void Netizen::sendWindowFocus(Window w) {
event.xclient.data.l[0] = FbAtoms::instance()->getFluxboxNotifyWindowFocusAtom();
event.xclient.data.l[1] = w;
XSendEvent(m_display, window(), False, NoEventMask, &event);
}
void Netizen::sendWindowAdd(Window w, unsigned long wkspc) {
event.xclient.data.l[0] = FbAtoms::instance()->getFluxboxNotifyWindowAddAtom();
event.xclient.data.l[1] = w;
event.xclient.data.l[2] = wkspc;
XSendEvent(m_display, window(), False, NoEventMask, &event);
event.xclient.data.l[2] = 0l;
}
void Netizen::sendWindowDel(Window w) {
event.xclient.data.l[0] = FbAtoms::instance()->getFluxboxNotifyWindowDelAtom();
event.xclient.data.l[1] = w;
XSendEvent(m_display, window(), False, NoEventMask, &event);
}
void Netizen::sendWindowRaise(Window w) {
event.xclient.data.l[0] = FbAtoms::instance()->getFluxboxNotifyWindowRaiseAtom();
event.xclient.data.l[1] = w;
XSendEvent(m_display, window(), False, NoEventMask, &event);
}
void Netizen::sendWindowLower(Window w) {
event.xclient.data.l[0] = FbAtoms::instance()->getFluxboxNotifyWindowLowerAtom();
event.xclient.data.l[1] = w;
XSendEvent(m_display, window(), False, NoEventMask, &event);
}
void Netizen::sendConfigNotify(XEvent &ev) {
XSendEvent(m_display, window(), False, StructureNotifyMask, &ev);
}

View file

@ -24,7 +24,7 @@
#ifndef PLACEMENTSTRATEGY_HH
#define PLACEMENTSTRATEGY_HH
#include <vector>
#include <list>
class FluxboxWindow;
@ -37,7 +37,7 @@ struct PlacementStrategy {
* @param place_y y placement of specific strategy
* @return true if the strategy found a placement for the window
*/
virtual bool placeWindow(const std::vector<FluxboxWindow *> &windowlist,
virtual bool placeWindow(const std::list<FluxboxWindow *> &windowlist,
const FluxboxWindow &win,
int &place_x, int &place_y) = 0;
virtual ~PlacementStrategy() { }

View file

@ -247,8 +247,8 @@ bool handleStartupItem(const string &line, int offset) {
}; // end anonymous namespace
Application::Application(int grouped)
: is_grouped(grouped)
Application::Application(bool grouped, ClientPattern *pat)
: is_grouped(grouped), group_pattern(pat)
{
decostate_remember =
dimensions_remember =
@ -328,7 +328,7 @@ Application* Remember::find(WinClient &winclient) {
Application * Remember::add(WinClient &winclient) {
ClientPattern *p = new ClientPattern();
Application *app = new Application(0);
Application *app = new Application(false);
// by default, we match against the WMClass of a window (instance and class strings)
string win_name = ::escapeRememberChars(p->getProperty(ClientPattern::NAME, winclient));
@ -520,11 +520,13 @@ int Remember::parseApp(ifstream &file, Application &app, string *first_line) {
effectively moved into the new
*/
Application *Remember::findMatchingPatterns(ClientPattern *pat, Patterns *patlist, int is_group) {
Application *Remember::findMatchingPatterns(ClientPattern *pat, Patterns *patlist, bool is_group, ClientPattern *match_pat) {
Patterns::iterator it = patlist->begin();
Patterns::iterator it_end = patlist->end();
for (; it != it_end; ++it) {
if (it->first->equals(*pat) && is_group == it->second->is_grouped) {
if (it->first->equals(*pat) && is_group == it->second->is_grouped &&
((match_pat == 0 && *it->second->group_pattern == 0) ||
(match_pat && match_pat->equals(**it->second->group_pattern)))) {
Application *ret = it->second;
// find any previous or subsequent matching ones and delete
@ -576,7 +578,8 @@ void Remember::reconfigure() {
if (!apps_file.eof()) {
string line;
int row = 0;
int in_group = 0;
bool in_group = false;
ClientPattern *pat = 0;
list<ClientPattern *> grouped_pats;
while (getline(apps_file, line) && ! apps_file.eof()) {
row++;
@ -592,11 +595,11 @@ void Remember::reconfigure() {
if (pos > 0 && strcasecmp(key.c_str(), "app") == 0) {
ClientPattern *pat = new ClientPattern(line.c_str() + pos);
if (in_group == 0) {
if (!in_group) {
if ((err = pat->error()) == 0) {
Application *app = findMatchingPatterns(pat, old_pats, 0);
Application *app = findMatchingPatterns(pat, old_pats, false);
if (!app)
app = new Application(0);
app = new Application(false);
m_pats->push_back(make_pair(pat, app));
row += parseApp(apps_file, *app);
@ -615,12 +618,9 @@ void Remember::reconfigure() {
// save the item even if it was bad (aren't we nice)
m_startups.push_back(line.substr(pos));
} else if (pos > 0 && strcasecmp(key.c_str(), "group") == 0) {
in_group = Application::IS_GROUPED;
pos = FbTk::StringUtil::getStringBetween(key,
line.c_str() + pos,
'(', ')');
if (pos > 0 && strcasecmp(key.c_str(), "workspace") == 0)
in_group |= Application::MATCH_WORKSPACE;
in_group = true;
if (line.find('(') != string::npos)
pat = new ClientPattern(line.c_str() + pos);
} else if (in_group) {
// otherwise assume that it is the start of the attributes
Application *app = 0;
@ -628,12 +628,12 @@ void Remember::reconfigure() {
list<ClientPattern *>::iterator it = grouped_pats.begin();
list<ClientPattern *>::iterator it_end = grouped_pats.end();
while (!app && it != it_end) {
app = findMatchingPatterns(*it, old_pats, in_group);
app = findMatchingPatterns(*it, old_pats, in_group, pat);
++it;
}
if (!app)
app = new Application(in_group);
app = new Application(in_group, pat);
while (!grouped_pats.empty()) {
// associate all the patterns with this app
@ -647,7 +647,7 @@ void Remember::reconfigure() {
if (!(pos>0 && strcasecmp(key.c_str(), "end") == 0)) {
row += parseApp(apps_file, *app, &line);
}
in_group = 0;
in_group = false;
} else
cerr<<"Error in apps file on line "<<row<<"."<<endl;
@ -725,8 +725,8 @@ void Remember::save() {
grouped_apps.insert(&a);
// otherwise output this whole group
apps_file << "[group]";
if (a.is_grouped & Application::MATCH_WORKSPACE)
apps_file << " (workspace)";
if (*a.group_pattern)
apps_file << " " << a.group_pattern->toString();
apps_file << endl;
Patterns::iterator git = m_pats->begin();
@ -1151,10 +1151,7 @@ FluxboxWindow *Remember::findGroup(Application *app, BScreen &screen) {
for (; it != it_end; ++it) {
if (it->second == app && it->first->fbwindow() &&
&screen == &it->first->screen() &&
(!(app->is_grouped & Application::MATCH_WORKSPACE) ||
it->first->fbwindow()->workspaceNumber() ==
screen.currentWorkspaceID()))
(!*app->group_pattern || app->group_pattern->match(*it->first)))
return it->first->fbwindow();
}

View file

@ -29,6 +29,9 @@
#define REMEMBER_HH
#include "AtomHandler.hh"
#include "ClientPattern.hh"
#include "FbTk/RefCount.hh"
#include <fstream>
#include <map>
@ -40,11 +43,10 @@
class FluxboxWindow;
class BScreen;
class WinClient;
class ClientPattern;
class Application {
public:
Application(int grouped);
Application(bool grouped, ClientPattern *pat = 0);
inline void forgetWorkspace() { workspace_remember = false; }
inline void forgetHead() { head_remember = false; }
inline void forgetDimensions() { dimensions_remember = false; }
@ -137,14 +139,8 @@ public:
bool save_on_close_remember;
bool save_on_close;
enum {
IS_GROUPED = 0x01,
MATCH_WORKSPACE = 0x02
// MATCH_HEAD, STUCK, ICONIFIED, etc.?
// this will probably evolve into a ClientPattern as soon as they
// match things like currentworkspace
};
int is_grouped;
bool is_grouped;
FbTk::RefCount<ClientPattern> group_pattern;
};
@ -254,7 +250,8 @@ private:
// optionally can give a line to read before the first (lookahead line)
int parseApp(std::ifstream &file, Application &app, std::string *first_line = 0);
Application *findMatchingPatterns(ClientPattern *pat, Patterns *patlist, int is_group);
Application *findMatchingPatterns(ClientPattern *pat, Patterns *patlist,
bool is_group, ClientPattern *match_pat = 0);
std::auto_ptr<Patterns> m_pats;
Clients m_clients;

View file

@ -202,23 +202,10 @@ getString() const {
template<>
void FbTk::Resource<Layer>::
setFromString(const char *strval) {
int tempnum = 0;
if (sscanf(strval, "%d", &tempnum) == 1)
string str(strval);
int tempnum = ::Layer::getNumFromString(str);
if (tempnum >= 0 && tempnum < ::Layer::NUM_LAYERS)
m_value = tempnum;
else if (strcasecmp(strval, "Menu") == 0)
m_value = ::Layer::MENU;
else if (strcasecmp(strval, "AboveDock") == 0)
m_value = ::Layer::ABOVE_DOCK;
else if (strcasecmp(strval, "Dock") == 0)
m_value = ::Layer::DOCK;
else if (strcasecmp(strval, "Top") == 0)
m_value = ::Layer::TOP;
else if (strcasecmp(strval, "Normal") == 0)
m_value = ::Layer::NORMAL;
else if (strcasecmp(strval, "Bottom") == 0)
m_value = ::Layer::BOTTOM;
else if (strcasecmp(strval, "Desktop") == 0)
m_value = ::Layer::DESKTOP;
else
setDefaultValue();
}
@ -227,26 +214,7 @@ setFromString(const char *strval) {
template<>
string FbTk::Resource<Layer>::
getString() const {
switch (m_value.getNum()) {
case Layer::MENU:
return string("Menu");
case Layer::ABOVE_DOCK:
return string("AboveDock");
case Layer::DOCK:
return string("Dock");
case Layer::TOP:
return string("Top");
case Layer::NORMAL:
return string("Normal");
case Layer::BOTTOM:
return string("Bottom");
case Layer::DESKTOP:
return string("Desktop");
default:
char tmpstr[128];
sprintf(tmpstr, "%d", m_value.getNum());
return string(tmpstr);
}
return ::Layer::getString(m_value.getNum());
}
template<>

View file

@ -27,7 +27,7 @@
#include "Screen.hh"
#include "ScreenPlacement.hh"
bool RowSmartPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowlist,
bool RowSmartPlacement::placeWindow(const std::list<FluxboxWindow *> &windowlist,
const FluxboxWindow &win,
int &place_x, int &place_y) {
@ -95,9 +95,9 @@ bool RowSmartPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowli
next_x = test_x + change_x;
std::vector<FluxboxWindow *>::const_iterator win_it =
std::list<FluxboxWindow *>::const_iterator win_it =
windowlist.begin();
std::vector<FluxboxWindow *>::const_iterator win_it_end =
std::list<FluxboxWindow *>::const_iterator win_it_end =
windowlist.end();
for (; win_it != win_it_end && placed; ++win_it) {

View file

@ -28,7 +28,7 @@
class RowSmartPlacement: public PlacementStrategy {
public:
bool placeWindow(const std::vector<FluxboxWindow *> &windowlist,
bool placeWindow(const std::list<FluxboxWindow *> &windowlist,
const FluxboxWindow &win,
int &place_x, int &place_y);
};

View file

@ -31,7 +31,6 @@
#include "Keys.hh"
#include "Window.hh"
#include "Workspace.hh"
#include "Netizen.hh"
#include "Layer.hh"
#include "FocusControl.hh"
@ -287,9 +286,10 @@ BScreen::ScreenResource::ScreenResource(FbTk::ResourceManager &rm,
image_dither(rm, false, scrname+".imageDither", altscrname+".ImageDither"),
opaque_move(rm, false, scrname + ".opaqueMove", altscrname+".OpaqueMove"),
full_max(rm, false, scrname+".fullMaximization", altscrname+".FullMaximization"),
max_ignore_inc(rm, true, scrname+".maxIgnoreIncrement", altscrname+".MaxIgnoreIncrement"),
max_disable_move(rm, false, scrname+".maxDisableMove", altscrname+".MaxDisableMove"),
max_disable_resize(rm, false, scrname+".maxDisableResize", altscrname+".MaxDisableResize"),
workspace_warping(rm, true, scrname+".workspacewarping", altscrname+".WorkspaceWarping"),
desktop_wheeling(rm, true, scrname+".desktopwheeling", altscrname+".DesktopWheeling"),
reverse_wheeling(rm, false, scrname+".reversewheeling", altscrname+".ReverseWheeling"),
show_window_pos(rm, true, scrname+".showwindowposition", altscrname+".ShowWindowPosition"),
auto_raise(rm, true, scrname+".autoRaise", altscrname+".AutoRaise"),
click_raises(rm, true, scrname+".clickRaises", altscrname+".ClickRaises"),
@ -299,6 +299,7 @@ BScreen::ScreenResource::ScreenResource(FbTk::ResourceManager &rm,
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"),
typing_delay(rm, 0, scrname+".noFocusWhileTypingDelay", altscrname+".NoFocusWhileTypingDelay"),
follow_model(rm, IGNORE_OTHER_WORKSPACES, scrname+".followModel", altscrname+".followModel"),
user_follow_model(rm, FOLLOW_ACTIVE_WINDOW, scrname+".userFollowModel", altscrname+".UserFollowModel"),
workspaces(rm, 1, scrname+".workspaces", altscrname+".Workspaces"),
@ -327,6 +328,8 @@ BScreen::ScreenResource::ScreenResource(FbTk::ResourceManager &rm,
scroll_action(rm, "", scrname+".windowScrollAction", altscrname+".WindowScrollAction"),
scroll_reverse(rm, false, scrname+".windowScrollReverse", altscrname+".WindowScrollReverse"),
allow_remote_actions(rm, false, scrname+".allowRemoteActions", altscrname+".AllowRemoteActions"),
clientmenu_use_pixmap(rm, true, scrname+".clientMenu.usePixmap", altscrname+".ClientMenu.UsePixmap"),
tabs_use_pixmap(rm, true, scrname+".tabs.usePixmap", altscrname+".Tabs.UsePixmap"),
max_over_tabs(rm, false, scrname+".tabs.maxOver", altscrname+".Tabs.MaxOver"),
default_internal_tabs(rm, true /* TODO: autoconf option? */ , scrname+".tabs.intitlebar", altscrname+".Tabs.InTitlebar") {
@ -362,13 +365,15 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
0, 0, 10, 10,
false, // override redirect
true), // save under
m_dummy_window(scrn, -1, -1, 1, 1, 0, true, false, CopyFromParent,
InputOnly),
resource(rm, screenname, altscreenname),
m_resource_manager(rm),
m_name(screenname),
m_altname(altscreenname),
m_focus_control(new FocusControl(*this)),
m_placement_strategy(new ScreenPlacement(*this)),
m_cycling(false),
m_cycling(false), m_typing_ahead(false), m_cycle_opts(0),
m_xinerama_headinfo(0),
m_restart(false),
m_shutdown(false) {
@ -423,6 +428,10 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
FbTk::EventManager *evm = FbTk::EventManager::instance();
evm->add(*this, rootWindow());
Keys *keys = Fluxbox::instance()->keys();
if (keys)
keys->registerWindow(rootWindow().window(),
Keys::GLOBAL|Keys::ON_DESKTOP);
rootWindow().setCursor(XCreateFontCursor(disp, XC_left_ptr));
// load this screens resources
@ -510,7 +519,6 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
}
changeWorkspaceID(first_desktop);
updateNetizenWorkspaceCount();
// we need to load win frame theme before we create any fluxbox window
// and after we've load the resources
@ -547,6 +555,9 @@ BScreen::~BScreen() {
FbTk::EventManager *evm = FbTk::EventManager::instance();
evm->remove(rootWindow());
Keys *keys = Fluxbox::instance()->keys();
if (keys)
keys->unregisterWindow(rootWindow().window());
if (m_rootmenu.get() != 0)
m_rootmenu->removeAll();
@ -582,7 +593,6 @@ BScreen::~BScreen() {
removeWorkspaceNames();
using namespace STLUtil;
destroyAndClear(m_workspaces_list);
destroyAndClear(m_netizen_list);
destroyAndClear(m_managed_resources);
//why not destroyAndClear(m_icon_list); ?
@ -816,7 +826,44 @@ void BScreen::propertyNotify(Atom atom) {
}
void BScreen::keyPressEvent(XKeyEvent &ke) {
Fluxbox::instance()->keys()->doAction(ke.type, ke.state, ke.keycode);
if (!m_typing_ahead) {
Fluxbox::instance()->keys()->doAction(ke.type, ke.state, ke.keycode,
Keys::GLOBAL|Keys::ON_DESKTOP);
return;
}
KeySym ks;
char keychar[1];
XLookupString(&ke, keychar, 1, &ks, 0);
// a modifier key by itself doesn't do anything
if (IsModifierKey(ks))
return;
switch (ks) {
case XK_Escape:
case XK_KP_Enter:
case XK_Return:
m_type_ahead.reset();
FbTk::EventManager::instance()->ungrabKeyboard();
break;
case XK_BackSpace:
m_type_ahead.putBackSpace();
m_matches = m_type_ahead.matched();
break;
case XK_Tab:
case XK_ISO_Left_Tab:
m_type_ahead.seek();
focusControl().cycleFocus(m_matches, m_cycle_opts, (bool)(ke.state & ShiftMask));
break;
default:
m_matches = m_type_ahead.putCharacter(keychar[0]);
// if focused win doesn't match new search string, find the next one
if (!m_matches.empty() &&
std::find(m_matches.begin(), m_matches.end(),
FocusControl::focusedWindow()) == m_matches.end())
focusControl().cycleFocus(m_matches, m_cycle_opts);
break;
}
}
void BScreen::keyReleaseEvent(XKeyEvent &ke) {
@ -835,15 +882,28 @@ void BScreen::buttonPressEvent(XButtonEvent &be) {
imageControl().installRootColormap();
Keys *keys = Fluxbox::instance()->keys();
keys->doAction(be.type, be.state, be.button);
keys->doAction(be.type, be.state, be.button, Keys::GLOBAL|Keys::ON_DESKTOP);
}
void BScreen::notifyUngrabKeyboard() {
m_cycling = false;
m_typing_ahead = false;
m_type_ahead.reset();
focusControl().stopCyclingFocus();
}
void BScreen::cycleFocus(int options, bool reverse) {
void BScreen::startTypeAheadFocus(std::list<Focusable *> &winlist,
const ClientPattern *pat) {
m_type_ahead.init(winlist);
m_matches = winlist;
FbTk::EventManager *evm = FbTk::EventManager::instance();
if (!m_typing_ahead && !m_cycling)
evm->grabKeyboard(*this, rootWindow().window());
m_cycle_opts = pat;
m_typing_ahead = true;
}
void BScreen::cycleFocus(int options, const ClientPattern *pat, bool reverse) {
// get modifiers from event that causes this for focus order cycling
XEvent ev = Fluxbox::instance()->lastEvent();
unsigned int mods = 0;
@ -852,7 +912,7 @@ void BScreen::cycleFocus(int options, bool reverse) {
else if (ev.type == ButtonPress)
mods = FbTk::KeyUtil::instance().cleanMods(ev.xbutton.state);
if (!m_cycling && mods) {
if (!m_cycling && !m_typing_ahead && mods) {
m_cycling = true;
FbTk::EventManager::instance()->grabKeyboard(*this, rootWindow().window());
}
@ -860,12 +920,19 @@ void BScreen::cycleFocus(int options, bool reverse) {
if (mods == 0) // can't stacked cycle unless there is a mod to grab
options |= FocusControl::CYCLELINEAR;
FocusControl::FocusedWindows *win_list =
(options & FocusControl::CYCLELINEAR) ?
FocusControl::Focusables *win_list = 0;
if (options & FocusControl::CYCLEGROUPS) {
win_list = (options & FocusControl::CYCLELINEAR) ?
&focusControl().creationOrderWinList() :
&focusControl().focusedOrderWinList();
} else {
win_list = (options & FocusControl::CYCLELINEAR) ?
&focusControl().creationOrderList() :
&focusControl().focusedOrderList();
}
focusControl().cycleFocus(*win_list, pat, reverse);
focusControl().cycleFocus(*win_list, options, reverse);
}
FbTk::Menu *BScreen::createMenu(const string &label) {
@ -1101,8 +1168,8 @@ void BScreen::removeClient(WinClient &client) {
focusControl().removeClient(client);
for_each(getWorkspacesList().begin(), getWorkspacesList().end(),
mem_fun(&Workspace::updateClientmenu));
if (client.fbwindow() && client.fbwindow()->isIconic())
iconListSig().notify();
using namespace FbTk;
@ -1124,7 +1191,7 @@ void BScreen::removeClient(WinClient &client) {
int BScreen::addWorkspace() {
bool save_name = getNameOfWorkspace(m_workspaces_list.size()) != "" ? false : true;
Workspace *wkspc = new Workspace(*this, m_layermanager,
Workspace *wkspc = new Workspace(*this,
getNameOfWorkspace(m_workspaces_list.size()),
m_workspaces_list.size());
m_workspaces_list.push_back(wkspc);
@ -1134,8 +1201,6 @@ int BScreen::addWorkspace() {
saveWorkspaces(m_workspaces_list.size());
updateNetizenWorkspaceCount();
return m_workspaces_list.size();
}
@ -1163,7 +1228,6 @@ int BScreen::removeLastWorkspace() {
//remove last workspace
m_workspaces_list.pop_back();
updateNetizenWorkspaceCount();
saveWorkspaces(m_workspaces_list.size());
// must be deleted after we send notify!!
// so we dont get bad pointers somewhere
@ -1225,14 +1289,15 @@ void BScreen::changeWorkspaceID(unsigned int id) {
currentWorkspace()->showAll();
if (focused && focused->isMoving()) {
focused->setInputFocus();
focused->focus();
focused->resumeMoving();
} else
FocusControl::revertFocus(*this);
updateNetizenCurrentWorkspace();
FbTk::App::instance()->sync(false);
m_currentworkspace_sig.notify();
}
@ -1243,31 +1308,24 @@ void BScreen::sendToWorkspace(unsigned int id, FluxboxWindow *win, bool changeWS
if (!win)
win = FocusControl::focusedFbWindow();
FbTk::App::instance()->sync(false);
if (!win || &win->screen() != this || win->isStuck())
if (!win || &win->screen() != this)
return;
// if iconified, deiconify it before we send it somewhere
if (win->isIconic())
win->deiconify();
// if the window isn't on current workspace, hide it
if (id != currentWorkspace()->workspaceID())
win->withdraw(true);
FbTk::App::instance()->sync(false);
windowMenu().hide();
reassociateWindow(win, id, true);
// if the window is on current workspace, show it.
if (id == currentWorkspace()->workspaceID())
win->deiconify(false, false);
// change workspace ?
if (changeWS && id != currentWorkspace()->workspaceID()) {
if (changeWS)
changeWorkspaceID(id);
win->setInputFocus();
// if the window is on current workspace, show it; else hide it.
if (id == currentWorkspace()->workspaceID() && !win->isIconic())
win->deiconify(false, false);
else {
win->hide(true);
FocusControl::revertFocus(*this);
}
// send all the transients too
@ -1285,113 +1343,6 @@ void BScreen::sendToWorkspace(unsigned int id, FluxboxWindow *win, bool changeWS
}
void BScreen::addNetizen(Window win) {
Netizen *net = new Netizen(*this, win);
m_netizen_list.push_back(net);
net->sendWorkspaceCount();
net->sendCurrentWorkspace();
// send all windows to netizen
Workspaces::iterator it = m_workspaces_list.begin();
Workspaces::iterator it_end = m_workspaces_list.end();
for (; it != it_end; ++it) {
Workspace::Windows::iterator win_it = (*it)->windowList().begin();
Workspace::Windows::iterator win_it_end = (*it)->windowList().end();
for (; win_it != win_it_end; ++win_it) {
net->sendWindowAdd((*win_it)->clientWindow(),
(*it)->workspaceID());
}
}
Window f = ((FocusControl::focusedWindow()) ?
FocusControl::focusedWindow()->window() : None);
net->sendWindowFocus(f);
}
void BScreen::removeNetizen(Window w) {
Netizens::iterator it = m_netizen_list.begin();
Netizens::iterator it_end = m_netizen_list.end();
for (; it != it_end; ++it) {
if ((*it)->window() == w) {
Netizen *n = *it;
delete n;
m_netizen_list.erase(it);
break;
}
}
}
void BScreen::updateNetizenCurrentWorkspace() {
m_currentworkspace_sig.notify();
for_each(m_netizen_list.begin(),
m_netizen_list.end(),
mem_fun(&Netizen::sendCurrentWorkspace));
}
void BScreen::updateNetizenWorkspaceCount() {
for_each(m_netizen_list.begin(),
m_netizen_list.end(),
mem_fun(&Netizen::sendWorkspaceCount));
m_workspacecount_sig.notify();
}
void BScreen::updateNetizenWindowFocus() {
Window f = ((FocusControl::focusedWindow()) ?
FocusControl::focusedWindow()->window() : None);
for_each(m_netizen_list.begin(),
m_netizen_list.end(),
bind2nd(mem_fun(&Netizen::sendWindowFocus), f));
}
void BScreen::updateNetizenWindowAdd(Window w, unsigned long p) {
// update the list of clients
m_clientlist_sig.notify();
// and then send the signal to listeners
Netizens::iterator it = m_netizen_list.begin();
Netizens::iterator it_end = m_netizen_list.end();
for (; it != it_end; ++it) {
(*it)->sendWindowAdd(w, p);
}
}
void BScreen::updateNetizenWindowDel(Window w) {
for_each(m_netizen_list.begin(),
m_netizen_list.end(),
bind2nd(mem_fun(&Netizen::sendWindowDel), w));
m_clientlist_sig.notify();
}
void BScreen::updateNetizenWindowRaise(Window w) {
for_each(m_netizen_list.begin(),
m_netizen_list.end(),
bind2nd(mem_fun(&Netizen::sendWindowRaise), w));
}
void BScreen::updateNetizenWindowLower(Window w) {
for_each(m_netizen_list.begin(),
m_netizen_list.end(),
bind2nd(mem_fun(&Netizen::sendWindowLower), w));
}
void BScreen::updateNetizenConfigNotify(XEvent &e) {
Netizens::iterator it = m_netizen_list.begin();
Netizens::iterator it_end = m_netizen_list.end();
for (; it != it_end; ++it)
(*it)->sendConfigNotify(e);
}
bool BScreen::isKdeDockapp(Window client) const {
//Check and see if client is KDE dock applet.
bool iskdedockapp = false;
@ -1505,10 +1456,6 @@ FluxboxWindow *BScreen::createWindow(Window client) {
delete win;
return 0;
}
Workspace *workspace = getWorkspace(win->workspaceNumber());
if (workspace && !Fluxbox::instance()->isStartup())
workspace->checkGrouping(*win);
}
}
@ -1559,7 +1506,7 @@ FluxboxWindow *BScreen::createWindow(WinClient &client) {
// don't ask me why, but client doesn't seem to keep focus in new window
// and we don't seem to get a FocusIn event from setInputFocus
if ((focusControl().focusNew() || FocusControl::focusedWindow() == &client)
&& win->setInputFocus())
&& win->focus())
FocusControl::setFocusedWindow(&client);
m_clientlist_sig.notify();
@ -1640,20 +1587,12 @@ void BScreen::reassociateWindow(FluxboxWindow *w, unsigned int wkspc_id,
if (w->isIconic()) {
removeIcon(w);
getWorkspace(wkspc_id)->addWindow(*w);
// client list need to notify now even though
// we didn't remove/add any window,
// so listeners that uses the client list to
// show whats on current/other workspace
// gets updated
m_clientlist_sig.notify();
} else if (ignore_sticky || ! w->isStuck()) {
// fresh windows have workspaceNumber == -1, which leads to
// an invalid workspace (unsigned int)
if (getWorkspace(w->workspaceNumber()))
getWorkspace(w->workspaceNumber())->removeWindow(w, true);
getWorkspace(wkspc_id)->addWindow(*w);
// see comment above
m_clientlist_sig.notify();
}
}
@ -1775,6 +1714,15 @@ void BScreen::setupConfigmenu(FbTk::Menu &menu) {
MouseTabFocus, "MouseTabFocus", "Hover over tab to focus windows"),
focusControl(), FocusControl::MOUSETABFOCUS, save_and_reconfigure));
try {
focus_menu->insert(new BoolMenuItem(_FB_XTEXT(Configmenu, FocusNew,
"Focus New Windows", "Focus newly created windows"),
*m_resource_manager.getResource<bool>(name() + ".focusNewWindows"),
saverc_cmd));
} catch (FbTk::ResourceException e) {
cerr<<e.what()<<endl;
}
focus_menu->insert(new BoolMenuItem(_FB_XTEXT(Configmenu,
AutoRaise,
"Auto Raise",
@ -1788,6 +1736,31 @@ void BScreen::setupConfigmenu(FbTk::Menu &menu) {
// END focus menu
// BEGIN maximize menu
FbTk::FbString maxmenu_label = _FB_XTEXT(Configmenu, MaxMenu,
"Maximize Options", "heading for maximization options");
FbTk::Menu *maxmenu = createMenu(maxmenu_label);
_BOOLITEM(*maxmenu, Configmenu, FullMax,
"Full Maximization", "Maximise over slit, toolbar, etc",
*resource.full_max, saverc_cmd);
_BOOLITEM(*maxmenu, Configmenu, MaxIgnoreInc,
"Ignore Resize Increment",
"Maximizing Ignores Resize Increment (e.g. xterm)",
*resource.max_ignore_inc, saverc_cmd);
_BOOLITEM(*maxmenu, Configmenu, MaxDisableMove,
"Disable Moving", "Don't Allow Moving While Maximized",
*resource.max_disable_move, saverc_cmd);
_BOOLITEM(*maxmenu, Configmenu, MaxDisableResize,
"Disable Resizing", "Don't Allow Resizing While Maximized",
*resource.max_disable_resize, saverc_cmd);
maxmenu->updateMenu();
menu.insert(maxmenu_label, maxmenu);
// END maximize menu
// BEGIN tab menu
FbTk::FbString tabmenu_label = _FB_XTEXT(Configmenu, TabMenu,
@ -1805,6 +1778,9 @@ void BScreen::setupConfigmenu(FbTk::Menu &menu) {
tab_menu->insert(new BoolMenuItem(_FB_XTEXT(Common, MaximizeOver,
"Maximize Over", "Maximize over this thing when maximizing"),
*resource.max_over_tabs, save_and_reconfigure));
tab_menu->insert(new BoolMenuItem(_FB_XTEXT(Toolbar, ShowIcons,
"Show Pictures", "chooses if little icons are shown next to title in the iconbar"),
*resource.tabs_use_pixmap, save_and_reconfigure));
FbTk::MenuItem *tab_width_item =
new IntResMenuItem< FbTk::Resource<int> >(_FB_XTEXT(Configmenu, ExternalTabWidth,
@ -1908,18 +1884,6 @@ void BScreen::setupConfigmenu(FbTk::Menu &menu) {
"Opaque Window Moving",
"Window Moving with whole window visible (as opposed to outline moving)",
*resource.opaque_move, saverc_cmd);
_BOOLITEM(menu, Configmenu, FullMax,
"Full Maximization", "Maximise over slit, toolbar, etc",
*resource.full_max, saverc_cmd);
try {
_BOOLITEM(menu, Configmenu, FocusNew,
"Focus New Windows", "Focus newly created windows",
*m_resource_manager.getResource<bool>(name() + ".focusNewWindows"),
saverc_cmd);
} catch (FbTk::ResourceException e) {
cerr<<e.what()<<endl;
}
_BOOLITEM(menu, Configmenu, WorkspaceWarping,
"Workspace Warping",
"Workspace Warping - dragging windows to the edge and onto the next workspace",
@ -1978,7 +1942,7 @@ void BScreen::showPosition(int x, int y) {
winFrameTheme().font().drawText(m_pos_window,
screenNumber(),
winFrameTheme().labelTextFocusGC(),
winFrameTheme().iconbarTheme().focusedText().textGC(),
label, strlen(label),
winFrameTheme().bevelWidth(),
winFrameTheme().bevelWidth() +
@ -2030,7 +1994,7 @@ void BScreen::showGeometry(int gx, int gy) {
//!! TODO: geom window again?! repeated
winFrameTheme().font().drawText(m_geom_window,
screenNumber(),
winFrameTheme().labelTextFocusGC(),
winFrameTheme().iconbarTheme().focusedText().textGC(),
label, strlen(label),
winFrameTheme().bevelWidth(),
winFrameTheme().bevelWidth() +
@ -2101,7 +2065,7 @@ void BScreen::renderGeomWindow() {
Pixmap tmp = geom_pixmap;
if (winFrameTheme().labelFocusTexture().type() & FbTk::Texture::PARENTRELATIVE) {
if (winFrameTheme().iconbarTheme().focusedTexture().type() & FbTk::Texture::PARENTRELATIVE) {
if (!winFrameTheme().titleFocusTexture().usePixmap()) {
geom_pixmap = None;
m_geom_window.setBackgroundColor(winFrameTheme().titleFocusTexture().color());
@ -2111,12 +2075,12 @@ void BScreen::renderGeomWindow() {
m_geom_window.setBackgroundPixmap(geom_pixmap);
}
} else {
if (!winFrameTheme().labelFocusTexture().usePixmap()) {
if (!winFrameTheme().iconbarTheme().focusedTexture().usePixmap()) {
geom_pixmap = None;
m_geom_window.setBackgroundColor(winFrameTheme().labelFocusTexture().color());
m_geom_window.setBackgroundColor(winFrameTheme().iconbarTheme().focusedTexture().color());
} else {
geom_pixmap = imageControl().renderImage(m_geom_window.width(), m_geom_window.height(),
winFrameTheme().labelFocusTexture());
winFrameTheme().iconbarTheme().focusedTexture());
m_geom_window.setBackgroundPixmap(geom_pixmap);
}
}
@ -2139,7 +2103,7 @@ void BScreen::renderPosWindow() {
Pixmap tmp = pos_pixmap;
if (winFrameTheme().labelFocusTexture().type() & FbTk::Texture::PARENTRELATIVE) {
if (winFrameTheme().iconbarTheme().focusedTexture().type() & FbTk::Texture::PARENTRELATIVE) {
if (!winFrameTheme().titleFocusTexture().usePixmap()) {
pos_pixmap = None;
m_pos_window.setBackgroundColor(winFrameTheme().titleFocusTexture().color());
@ -2149,12 +2113,12 @@ void BScreen::renderPosWindow() {
m_pos_window.setBackgroundPixmap(pos_pixmap);
}
} else {
if (!winFrameTheme().labelFocusTexture().usePixmap()) {
if (!winFrameTheme().iconbarTheme().focusedTexture().usePixmap()) {
pos_pixmap = None;
m_pos_window.setBackgroundColor(winFrameTheme().labelFocusTexture().color());
m_pos_window.setBackgroundColor(winFrameTheme().iconbarTheme().focusedTexture().color());
} else {
pos_pixmap = imageControl().renderImage(m_pos_window.width(), m_pos_window.height(),
winFrameTheme().labelFocusTexture());
winFrameTheme().iconbarTheme().focusedTexture());
m_pos_window.setBackgroundPixmap(pos_pixmap);
}
}

View file

@ -58,7 +58,6 @@
class ClientPattern;
class Focusable;
class FluxboxWindow;
class Netizen;
class FbWinFrameTheme;
class RootTheme;
class WinButtonTheme;
@ -88,17 +87,17 @@ public:
/// a window becomes active / focussed on a different workspace
enum FollowModel {
IGNORE_OTHER_WORKSPACES = 0, ///< who cares?
FOLLOW_ACTIVE_WINDOW, ///< go to that workspace
FOLLOW_ACTIVE_WINDOW, ///< go to that workspace
SEMIFOLLOW_ACTIVE_WINDOW, ///< fetch iconified windows, else follow
FETCH_ACTIVE_WINDOW ///< put that window to the current workspace
FETCH_ACTIVE_WINDOW ///< put that window to the current workspace
};
/// Different resize modes when resizing a window
enum ResizeModel {
BOTTOMRESIZE = 0, //< resizes from the bottom right corner
QUADRANTRESIZE, //< resizes from one quadrant
CENTERRESIZE, //< resizes from center
DEFAULTRESIZE = BOTTOMRESIZE //< default resize mode is bottom
BOTTOMRESIZE = 0, ///< resizes from the bottom right corner
QUADRANTRESIZE, ///< resizes from one quadrant
CENTERRESIZE, ///< resizes from center
DEFAULTRESIZE = BOTTOMRESIZE ///< default resize mode is bottom
};
@ -119,12 +118,13 @@ public:
bool isRootColormapInstalled() const { return root_colormap_installed; }
bool isScreenManaged() const { return managed; }
bool isWorkspaceWarping() const { return *resource.workspace_warping; }
bool isDesktopWheeling() const { return *resource.desktop_wheeling; }
bool isReverseWheeling() const { return *resource.reverse_wheeling; }
bool doAutoRaise() const { return *resource.auto_raise; }
bool clickRaises() const { return *resource.click_raises; }
bool doOpaqueMove() const { return *resource.opaque_move; }
bool doFullMax() const { return *resource.full_max; }
bool getMaxIgnoreIncrement() const { return *resource.max_ignore_inc; }
bool getMaxDisableMove() const { return *resource.max_disable_move; }
bool getMaxDisableResize() const { return *resource.max_disable_resize; }
bool doShowWindowPos() const { return *resource.show_window_pos; }
bool decorateTransient() const { return *resource.decorate_transient; }
const std::string &defaultDeco() const { return *resource.default_deco; }
@ -144,13 +144,16 @@ public:
ResizeModel getResizeModel() const { return *resource.resize_model; }
inline unsigned int noFocusWhileTypingDelay() const { return *resource.typing_delay; }
inline FollowModel getFollowModel() const { return *resource.follow_model; }
inline FollowModel getUserFollowModel() const { return *resource.user_follow_model; }
inline const std::string &getScrollAction() const { return *resource.scroll_action; }
inline const bool getScrollReverse() const { return *resource.scroll_reverse; }
inline const bool allowRemoteActions() const { return *resource.allow_remote_actions; }
inline const bool clientMenuUsePixmap() const { return *resource.clientmenu_use_pixmap; }
inline const bool getDefaultInternalTabs() const { return *resource.default_internal_tabs; }
inline const bool getTabsUsePixmap() const { return *resource.tabs_use_pixmap; }
inline const bool getMaxOverTabs() const { return *resource.max_over_tabs; }
inline unsigned int getTabWidth() const { return *resource.tab_width; }
@ -256,9 +259,10 @@ public:
/**
* Cycles focus of windows
* @param opts focus options
* @param pat specific pattern to match windows with
* @param reverse the order of cycling
*/
void cycleFocus(int opts = 0, bool reverse = false);
void cycleFocus(int opts = 0, const ClientPattern *pat = 0, bool reverse = false);
/**
* Creates an empty menu with specified label
@ -307,6 +311,9 @@ public:
FbRootWindow &rootWindow() { return m_root_window; }
const FbRootWindow &rootWindow() const { return m_root_window; }
FbTk::FbWindow &dummyWindow() { return m_dummy_window; }
const FbTk::FbWindow &dummyWindow() const { return m_dummy_window; }
FbTk::MultLayers &layerManager() { return m_layermanager; }
const FbTk::MultLayers &layerManager() const { return m_layermanager; }
FbTk::ResourceManager &resourceManager() { return m_resource_manager; }
@ -355,10 +362,6 @@ public:
void updateWorkspaceNamesAtom();
/// add a workspace name to the end of the workspace name list
void addWorkspaceName(const char *name);
/// add a Netizen window
void addNetizen(Window win);
/// remove a netizen
void removeNetizen(Window win);
/// add a window to the icon list
void addIcon(FluxboxWindow *win);
/// remove a window from the icon list
@ -457,16 +460,6 @@ public:
WinClient *findGroupLeft(WinClient &winclient);
WinClient *findGroupRight(WinClient &winclient);
// notify netizens
void updateNetizenCurrentWorkspace();
void updateNetizenWorkspaceCount();
void updateNetizenWindowFocus();
void updateNetizenWindowAdd(Window, unsigned long);
void updateNetizenWindowDel(Window);
void updateNetizenConfigNotify(XEvent &ev);
void updateNetizenWindowRaise(Window);
void updateNetizenWindowLower(Window);
/// create window frame for client window and attach it
FluxboxWindow *createWindow(Window clientwin);
/// creates a window frame for a winclient. The client is attached to the window
@ -536,12 +529,10 @@ private:
ExtraMenus m_extramenus;
typedef std::list<FbTk::Menu *> Rootmenus;
typedef std::list<Netizen *> Netizens;
typedef std::list<std::pair<FbTk::FbString, FbTk::Menu *> > Configmenus;
Rootmenus m_rootmenu_list;
Netizens m_netizen_list;
Configmenus m_configmenu_list;
Icons m_icon_list;
@ -558,21 +549,22 @@ private:
std::auto_ptr<RootTheme> m_root_theme;
FbRootWindow m_root_window;
FbTk::FbWindow m_geom_window, m_pos_window;
FbTk::FbWindow m_geom_window, m_pos_window, m_dummy_window;
struct ScreenResource {
ScreenResource(FbTk::ResourceManager &rm, const std::string &scrname,
const std::string &altscrname);
FbTk::Resource<bool> image_dither, opaque_move, full_max,
workspace_warping,
desktop_wheeling, reverse_wheeling, show_window_pos,
auto_raise, click_raises, decorate_transient;
max_ignore_inc, max_disable_move, max_disable_resize,
workspace_warping, show_window_pos, auto_raise, click_raises,
decorate_transient;
FbTk::Resource<std::string> default_deco;
FbTk::Resource<std::string> rootcommand;
FbTk::Resource<ResizeModel> resize_model;
FbTk::Resource<FbWinFrame::TabPlacement> tab_placement;
FbTk::Resource<std::string> windowmenufile;
FbTk::Resource<unsigned int> typing_delay;
FbTk::Resource<FollowModel> follow_model, user_follow_model;
bool ordered_dither;
FbTk::Resource<int> workspaces, edge_snap_threshold, focused_alpha,
@ -586,6 +578,8 @@ private:
FbTk::Resource<std::string> scroll_action;
FbTk::Resource<bool> scroll_reverse;
FbTk::Resource<bool> allow_remote_actions;
FbTk::Resource<bool> clientmenu_use_pixmap;
FbTk::Resource<bool> tabs_use_pixmap;
FbTk::Resource<bool> max_over_tabs;
FbTk::Resource<bool> default_internal_tabs;

View file

@ -25,6 +25,7 @@
#include "RowSmartPlacement.hh"
#include "MinOverlapPlacement.hh"
#include "UnderMousePlacement.hh"
#include "ColSmartPlacement.hh"
#include "CascadePlacement.hh"
@ -57,7 +58,7 @@ ScreenPlacement::ScreenPlacement(BScreen &screen):
{
}
bool ScreenPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowlist,
bool ScreenPlacement::placeWindow(const std::list<FluxboxWindow *> &windowlist,
const FluxboxWindow &win,
int &place_x, int &place_y) {
@ -73,6 +74,10 @@ bool ScreenPlacement::placeWindow(const std::vector<FluxboxWindow *> &windowlist
case COLSMARTPLACEMENT:
m_strategy.reset(new ColSmartPlacement());
break;
case ROWMINOVERLAPPLACEMENT:
case COLMINOVERLAPPLACEMENT:
m_strategy.reset(new MinOverlapPlacement(*m_placement_policy));
break;
case CASCADEPLACEMENT:
m_strategy.reset(new CascadePlacement(win.screen()));
break;
@ -143,6 +148,10 @@ void FbTk::Resource<ScreenPlacement::PlacementPolicy>::setFromString(const char
*(*this) = ScreenPlacement::ROWSMARTPLACEMENT;
else if (strcasecmp("ColSmartPlacement", str) == 0)
*(*this) = ScreenPlacement::COLSMARTPLACEMENT;
else if (strcasecmp("RowMinOverlapPlacement", str) == 0)
*(*this) = ScreenPlacement::ROWMINOVERLAPPLACEMENT;
else if (strcasecmp("ColMinOverlapPlacement", str) == 0)
*(*this) = ScreenPlacement::COLMINOVERLAPPLACEMENT;
else if (strcasecmp("UnderMousePlacement", str) == 0)
*(*this) = ScreenPlacement::UNDERMOUSEPLACEMENT;
else if (strcasecmp("CascadePlacement", str) == 0)
@ -158,6 +167,10 @@ std::string FbTk::Resource<ScreenPlacement::PlacementPolicy>::getString() const
return "RowSmartPlacement";
case ScreenPlacement::COLSMARTPLACEMENT:
return "ColSmartPlacement";
case ScreenPlacement::ROWMINOVERLAPPLACEMENT:
return "RowMinOverlapPlacement";
case ScreenPlacement::COLMINOVERLAPPLACEMENT:
return "ColMinOverlapPlacement";
case ScreenPlacement::UNDERMOUSEPLACEMENT:
return "UnderMousePlacement";
case ScreenPlacement::CASCADEPLACEMENT:

View file

@ -43,8 +43,10 @@ class ScreenPlacement: public PlacementStrategy {
public:
enum PlacementPolicy {
ROWSMARTPLACEMENT,
COLSMARTPLACEMENT,
CASCADEPLACEMENT,
COLSMARTPLACEMENT,
COLMINOVERLAPPLACEMENT,
ROWMINOVERLAPPLACEMENT,
CASCADEPLACEMENT,
UNDERMOUSEPLACEMENT
};
@ -62,7 +64,7 @@ public:
virtual ~ScreenPlacement() {}
/// placeWindow is guaranteed to succeed, ignore return value
/// @return true
bool placeWindow(const std::vector<FluxboxWindow *> &windowlist,
bool placeWindow(const std::list<FluxboxWindow *> &windowlist,
const FluxboxWindow &window,
int &place_x, int &place_y);

View file

@ -59,7 +59,6 @@
#include "SlitTheme.hh"
#include "SlitClient.hh"
#include "Xutil.hh"
#include "FbAtoms.hh"
#include "FbTk/App.hh"
#include "FbTk/MenuSeparator.hh"
#include "FbTk/StringUtil.hh"
@ -497,15 +496,9 @@ void Slit::addClient(Window w) {
Atom *proto = 0;
int num_return = 0;
FbAtoms *fbatoms = FbAtoms::instance();
if (XGetWMProtocols(disp, w, &proto, &num_return)) {
for (int i = 0; i < num_return; ++i) {
if (proto[i] == fbatoms->getFluxboxStructureMessagesAtom())
screen().addNetizen(w);
}
XFree((void *) proto);
#ifdef DEBUG
} else {
@ -588,8 +581,6 @@ void Slit::removeClient(SlitClient *client, bool remap, bool destroy) {
else // Clear the window info, but keep around to help future sorting?
client->initialize();
screen().removeNetizen(client->window());
if (remap && client->window() != 0) {
Display *disp = FbTk::App::instance()->display();

View file

@ -33,6 +33,7 @@
#include "ToolbarTheme.hh"
#include "fluxbox.hh"
#include "Keys.hh"
#include "Screen.hh"
#include "IntResMenuItem.hh"
#include "BoolMenuItem.hh"
@ -279,6 +280,8 @@ Toolbar::Toolbar(BScreen &scrn, FbTk::XLayer &layer, size_t width):
scrn.resourceManager().unlock();
// setup to listen to child events
FbTk::EventManager::instance()->addParent(*this, window());
Fluxbox::instance()->keys()->registerWindow(window().window(),
Keys::ON_TOOLBAR);
// get everything together
reconfigure();
// this gets done by the screen later as it loads
@ -286,6 +289,7 @@ Toolbar::Toolbar(BScreen &scrn, FbTk::XLayer &layer, size_t width):
}
Toolbar::~Toolbar() {
Fluxbox::instance()->keys()->unregisterWindow(window().window());
FbTk::EventManager::instance()->remove(window());
// remove menu items before we delete tools so we dont end up
// with dangling pointers to old submenu items (internal menus)
@ -520,6 +524,11 @@ void Toolbar::reconfigure() {
void Toolbar::buttonPressEvent(XButtonEvent &be) {
if (Fluxbox::instance()->keys()->doAction(be.type, be.state, be.button,
Keys::ON_TOOLBAR))
return;
if (be.button == 1)
raise();
if (be.button != 3)
return;
@ -547,25 +556,6 @@ void Toolbar::buttonPressEvent(XButtonEvent &be) {
}
void Toolbar::buttonReleaseEvent(XButtonEvent &re) {
if (re.button == 1) {
raise();
} else if (re.button == 4) { //mousewheel scroll up
if(screen().isReverseWheeling()) {
screen().prevWorkspace(1);
} else {
screen().nextWorkspace(1);
}
} else if (re.button == 5) { //mousewheel scroll down
if(screen().isReverseWheeling()) {
screen().nextWorkspace(1);
} else {
screen().prevWorkspace(1);
}
}
}
void Toolbar::enterNotifyEvent(XCrossingEvent &not_used) {
if (! doAutoHide()) {
if (isHidden())

View file

@ -88,7 +88,6 @@ public:
*/
//@{
void buttonPressEvent(XButtonEvent &be);
void buttonReleaseEvent(XButtonEvent &be);
void enterNotifyEvent(XCrossingEvent &ce);
void leaveNotifyEvent(XCrossingEvent &ce);
void exposeEvent(XExposeEvent &ee);

View file

@ -27,7 +27,7 @@
#include "Screen.hh"
#include "Window.hh"
bool UnderMousePlacement::placeWindow(const std::vector<FluxboxWindow *> &list,
bool UnderMousePlacement::placeWindow(const std::list<FluxboxWindow *> &list,
const FluxboxWindow &win,
int &place_x, int &place_y) {

View file

@ -28,7 +28,7 @@
class UnderMousePlacement: public PlacementStrategy {
public:
bool placeWindow(const std::vector<FluxboxWindow *> &windowlist,
bool placeWindow(const std::list<FluxboxWindow *> &windowlist,
const FluxboxWindow &win,
int &place_x, int &place_y);
};

View file

@ -321,15 +321,15 @@ void WinButton::update(FbTk::Subject *subj) {
Display* display = m_listen_to.fbWindow().display();
int screen = m_listen_to.screen().screenNumber();
if (m_listen_to.usePixmap()) {
m_icon_pixmap.copy(m_listen_to.iconPixmap().drawable(),
if (m_listen_to.icon().pixmap().drawable() != None) {
m_icon_pixmap.copy(m_listen_to.icon().pixmap().drawable(),
DefaultDepth(display, screen), screen);
m_icon_pixmap.scale(width() - 4, height() - 4);
} else
m_icon_pixmap.release();
if (m_listen_to.useMask()) {
m_icon_mask.copy(m_listen_to.iconMask().drawable(), 0, 0);
if (m_listen_to.icon().mask().drawable() != None) {
m_icon_mask.copy(m_listen_to.icon().mask().drawable(), 0, 0);
m_icon_mask.scale(width() - 4, height() - 4);
} else
m_icon_mask.release();

View file

@ -25,6 +25,7 @@
#include "Window.hh"
#include "fluxbox.hh"
#include "FocusControl.hh"
#include "Screen.hh"
#include "FbAtoms.hh"
@ -62,7 +63,8 @@ using std::dec;
WinClient::TransientWaitMap WinClient::s_transient_wait;
WinClient::WinClient(Window win, BScreen &screen, FluxboxWindow *fbwin):FbTk::FbWindow(win),
WinClient::WinClient(Window win, BScreen &screen, FluxboxWindow *fbwin):
Focusable(screen, fbwin), FbTk::FbWindow(win),
transient_for(0),
window_group(0),
x(0), y(0), old_bw(0),
@ -75,24 +77,17 @@ WinClient::WinClient(Window win, BScreen &screen, FluxboxWindow *fbwin):FbTk::Fb
initial_state(0),
normal_hint_flags(0),
wm_hint_flags(0),
m_win(fbwin),
m_modal_count(0),
m_modal(false),
send_focus_message(false),
send_close_message(false),
m_win_gravity(0),
m_title(""), m_icon_title(""),
m_class_name(""), m_instance_name(""),
m_title_override(false),
m_icon_title_override(false),
m_blackbox_hint(0),
m_mwm_hint(0),
m_focus_mode(F_PASSIVE),
m_diesig(*this), m_focussig(*this),
m_screen(screen),
m_strut(0) {
updateWMProtocols();
updateBlackboxHints();
updateMWMHints();
updateWMHints();
updateWMNormalHints();
@ -145,8 +140,8 @@ WinClient::~WinClient() {
transients.pop_back();
}
if (m_win != 0)
m_win->removeClient(*this);
if (fbwindow() != 0)
fbwindow()->removeClient(*this);
// this takes care of any focus issues
m_diesig.notify();
@ -159,8 +154,6 @@ WinClient::~WinClient() {
s_transient_wait.erase(window());
screen().removeNetizen(window());
if (window_group != 0) {
fluxbox->removeGroupSearch(window_group);
window_group = 0;
@ -169,13 +162,8 @@ WinClient::~WinClient() {
if (m_mwm_hint != 0)
XFree(m_mwm_hint);
if (m_blackbox_hint != 0)
XFree(m_blackbox_hint);
if (window())
fluxbox->removeWindowSearch(window());
m_win = 0;
}
bool WinClient::acceptsFocus() const {
@ -243,12 +231,16 @@ bool WinClient::getWMIconName(XTextProperty &textprop) const {
return XGetWMIconName(display(), window(), &textprop);
}
const string &WinClient::getWMClassName() const {
return m_instance_name;
string WinClient::getWMRole() const {
Atom wm_role = XInternAtom(FbTk::App::instance()->display(),
"WM_WINDOW_ROLE", False);
return textProperty(wm_role);
}
const string &WinClient::getWMClassClass() const {
return m_class_name;
const string &WinClient::title() const {
if (!fbwindow() || !fbwindow()->isIconic() || m_icon_title.empty())
return m_title;
return m_icon_title;
}
void WinClient::updateWMClassHint() {
@ -257,6 +249,7 @@ void WinClient::updateWMClassHint() {
#ifdef DEBUG
cerr<<"WinClient: Failed to read class hint!"<<endl;
#endif //DEBUG
m_instance_name = m_class_name = "";
} else {
if (ch.res_name != 0) {
@ -364,18 +357,24 @@ void WinClient::updateTitle() {
return;
m_title = string(Xutil::getWMName(window()), 0, 512);
titleSig().notify();
if (fbwindow())
fbwindow()->updateTitleFromClient(*this);
}
void WinClient::setTitle(FbTk::FbString &title) {
m_title = title;
m_title_override = true;
if (m_win)
m_win->updateTitleFromClient(*this);
titleSig().notify();
if (fbwindow())
fbwindow()->updateTitleFromClient(*this);
}
void WinClient::setIconTitle(FbTk::FbString &icon_title) {
m_icon_title = icon_title;
m_icon_title_override = true;
if (fbwindow() && fbwindow()->isIconic())
fbwindow()->updateTitleFromClient(*this);
}
void WinClient::updateIconTitle() {
@ -390,24 +389,27 @@ void WinClient::updateIconTitle() {
if (text_prop.value && text_prop.nitems > 0) {
if (text_prop.encoding != XA_STRING) {
text_prop.nitems = strlen((char *) text_prop.value);
XmbTextPropertyToTextList(display(), &text_prop, &list, &num);
if (XmbTextPropertyToTextList(display(), &text_prop,
&list, &num) == Success &&
num > 0 && *list) {
if (num > 0 && list)
m_icon_title = (char *)*list;
XFreeStringList(list);
} else
else
m_icon_title = text_prop.value ? (char *)text_prop.value : "";
if (list)
XFreeStringList(list);
} else
m_icon_title = text_prop.value ? (char *)text_prop.value : "";
if (text_prop.value)
XFree((char *) text_prop.value);
} else
m_icon_title = title();
m_icon_title = "";
} else
m_icon_title = title();
m_icon_title = "";
if (fbwindow() && fbwindow()->isIconic())
fbwindow()->updateTitleFromClient(*this);
}
void WinClient::saveBlackboxAttribs(FluxboxWindow::BlackboxAttributes &blackbox_attribs) {
@ -419,32 +421,7 @@ void WinClient::saveBlackboxAttribs(FluxboxWindow::BlackboxAttributes &blackbox_
}
void WinClient::setFluxboxWindow(FluxboxWindow *win) {
m_win = win;
}
void WinClient::updateBlackboxHints() {
int format;
Atom atom_return;
unsigned long num, len;
FbAtoms *atoms = FbAtoms::instance();
if (m_blackbox_hint) {
XFree(m_blackbox_hint);
m_blackbox_hint = 0;
}
if (property(atoms->getFluxboxHintsAtom(), 0,
PropBlackboxHintsElements, False,
atoms->getFluxboxHintsAtom(), &atom_return,
&format, &num, &len,
(unsigned char **) &m_blackbox_hint) &&
m_blackbox_hint) {
if (num != (unsigned)PropBlackboxHintsElements) {
XFree(m_blackbox_hint);
m_blackbox_hint = 0;
}
}
m_fbwin = win;
}
void WinClient::updateMWMHints() {
@ -521,16 +498,16 @@ void WinClient::updateWMHints() {
window_group = None;
if ((bool)(wmhint->flags & IconPixmapHint) && wmhint->icon_pixmap != 0)
m_icon_pixmap.copy(wmhint->icon_pixmap, 0, 0);
m_icon.pixmap().copy(wmhint->icon_pixmap, 0, 0);
else
m_icon_pixmap = 0;
m_icon.pixmap().release();
if ((bool)(wmhint->flags & IconMaskHint) && wmhint->icon_mask != 0)
m_icon_mask.copy(wmhint->icon_mask, 0, 0);
m_icon.mask().copy(wmhint->icon_mask, 0, 0);
else
m_icon_mask = 0;
m_icon.mask().release();
if (m_win) {
if (fbwindow()) {
if (wmhint->flags & XUrgencyHint) {
Fluxbox::instance()->attentionHandler().addAttention(*this);
} else {
@ -715,10 +692,22 @@ void WinClient::clearStrut() {
}
bool WinClient::focus() {
if (m_win == 0)
if (fbwindow() == 0)
return false;
else
return m_win->setCurrentClient(*this, true);
return fbwindow()->setCurrentClient(*this, true);
}
bool WinClient::isFocused() const {
return (fbwindow() ?
fbwindow()->isFocused() && &fbwindow()->winClient() == this :
false);
}
void WinClient::setAttentionState(bool value) {
Focusable::setAttentionState(value);
if (fbwindow() && !fbwindow()->isFocused())
fbwindow()->setAttentionState(value);
}
void WinClient::updateWMProtocols() {
@ -731,19 +720,16 @@ void WinClient::updateWMProtocols() {
// defaults
send_focus_message = false;
send_close_message = false;
// could be added to netizens twice...
for (int i = 0; i < num_return; ++i) {
if (proto[i] == fbatoms->getWMDeleteAtom())
send_close_message = true;
else if (proto[i] == fbatoms->getWMTakeFocusAtom())
send_focus_message = true;
else if (proto[i] == fbatoms->getFluxboxStructureMessagesAtom())
screen().addNetizen(window());
}
XFree(proto);
if (m_win)
m_win->updateFunctions();
if (fbwindow())
fbwindow()->updateFunctions();
#ifdef DEBUG
} else {
cerr<<"Warning: Failed to read WM Protocols. "<<endl;

View file

@ -24,6 +24,7 @@
#ifndef WINCLIENT_HH
#define WINCLIENT_HH
#include "Focusable.hh"
#include "Window.hh"
#include "Subject.hh"
#include "FbWindow.hh"
@ -35,7 +36,7 @@ class BScreen;
class Strut;
/// Holds client window info
class WinClient:public FbTk::FbWindow {
class WinClient: public Focusable, public FbTk::FbWindow {
public:
typedef std::list<WinClient *> TransientList;
// this structure only contains 3 elements... the Motif 2.0 structure contains
@ -69,7 +70,6 @@ public:
/// updates transient window information
void updateTransientInfo();
void updateBlackboxHints();
void updateMWMHints();
void updateWMHints();
void updateWMNormalHints();
@ -78,6 +78,9 @@ public:
void clearStrut();
bool focus(); // calls Window->setCurrentClient to give focus to this client
bool isFocused() const;
void setAttentionState(bool value);
const std::string &title() const;
/**
* Changes width and height to the nearest (lower) value
@ -106,17 +109,7 @@ public:
bool getAttrib(XWindowAttributes &attr) const;
bool getWMName(XTextProperty &textprop) const;
bool getWMIconName(XTextProperty &textprop) const;
/// @return name member of class structure
const std::string &getWMClassName() const;
/// @return class member of class structure
const std::string &getWMClassClass() const;
BScreen &screen() { return m_screen; }
const BScreen &screen() const { return m_screen; }
/// notifies when this client dies
FbTk::Subject &dieSig() { return m_diesig; }
/// notifies when this client becomes focused
FbTk::Subject &focusSig() { return m_focussig; }
std::string getWMRole() const;
inline WinClient *transientFor() { return transient_for; }
inline const WinClient *transientFor() const { return transient_for; }
@ -128,15 +121,6 @@ public:
inline bool isStateModal() const { return m_modal; }
void setStateModal(bool state);
const FbTk::FbPixmap &iconPixmap() const { return m_icon_pixmap; }
const FbTk::FbPixmap &iconMask() const { return m_icon_mask; }
const bool usePixmap() const { return m_icon_pixmap.drawable() != None; }
const bool useMask() const { return m_icon_mask.drawable() != None; }
inline const std::string &title() const { return m_title; }
inline const std::string &iconTitle() const { return m_icon_title; }
inline const FluxboxWindow *fbwindow() const { return m_win; }
inline FluxboxWindow *fbwindow() { return m_win; }
inline int gravity() const { return m_win_gravity; }
bool hasGroupLeftWindow() const;
@ -144,14 +128,11 @@ public:
Window getGroupLeftWindow() const;
inline int getFocusMode() const { return m_focus_mode; }
inline const FluxboxWindow::BlackboxHints *getBlackboxHint() const { return m_blackbox_hint; }
inline const MwmHints *getMwmHint() const { return m_mwm_hint; }
inline unsigned int maxWidth() const { return max_width; }
inline unsigned int maxHeight() const { return max_height; }
static const int PropBlackboxHintsElements = 5;
static const int PropMwmHintsElements = 3;
/**
@ -172,15 +153,6 @@ public:
unsigned long initial_state, normal_hint_flags, wm_hint_flags;
class WinClientSubj: public FbTk::Subject {
public:
explicit WinClientSubj(WinClient &client):m_winclient(client) { }
WinClient &winClient() { return m_winclient; }
private:
WinClient &m_winclient;
};
enum FocusMode { F_NOINPUT = 0, F_PASSIVE, F_LOCALLYACTIVE, F_GLOBALLYACTIVE };
private:
@ -192,8 +164,6 @@ private:
// some transient (or us) is no longer modal
void removeModal() { --m_modal_count; }
FluxboxWindow *m_win;
// number of transients which we are modal for
int m_modal_count;
bool m_modal;
@ -201,22 +171,13 @@ private:
int m_win_gravity;
std::string m_title, m_icon_title;
std::string m_class_name, m_instance_name;
std::string m_icon_title;
bool m_title_override, m_icon_title_override;
FbTk::FbPixmap m_icon_pixmap;
FbTk::FbPixmap m_icon_mask;
FluxboxWindow::BlackboxHints *m_blackbox_hint;
MwmHints *m_mwm_hint;
int m_focus_mode;
WinClientSubj m_diesig;
WinClientSubj m_focussig;
BScreen &m_screen;
Strut *m_strut;
// map transient_for X window to winclient transient
// (used if transient_for FbWindow was created after transient)

View file

@ -1,32 +0,0 @@
#include "WinClientUtil.hh"
#include "WinClient.hh"
#include <algorithm>
namespace WinClientUtil {
void maxSize(const FluxboxWindow::ClientList &clients,
unsigned int &max_width, unsigned int &max_height) {
FluxboxWindow::ClientList::const_iterator it = clients.begin();
FluxboxWindow::ClientList::const_iterator it_end = clients.end();
max_width = (unsigned int) ~0; // unlimited
max_height = (unsigned int) ~0; // unlimited
for (; it != it_end; ++it) {
// special case for max height/width == 0
// 0 indicates unlimited size, so we skip them
// and set max size to 0 if max size == ~0 after the loop
if ((*it)->maxHeight() != 0)
max_height = std::min( (*it)->maxHeight(), max_height );
if ((*it)->maxWidth() != 0)
max_width = std::min( (*it)->maxWidth(), max_width );
}
if (max_width == (unsigned int) ~0)
max_width = 0;
if (max_height == (unsigned int) ~0)
max_height = 0;
}
}

View file

@ -1,19 +0,0 @@
#ifndef WINCLIENTUTIL_H
#define WINCLIENTUTIL_H
#include "Window.hh"
/// window client utilities
namespace WinClientUtil {
/**
* Calculates the min of all maximum width/heights of all clients
* @param clients the client list
* @param width the return value of minimum of all max width of all clients
* @param height the return value of mimimum of all max heights of all clients
*/
void maxSize(const FluxboxWindow::ClientList &clients,
unsigned int &width, unsigned int &height);
}
#endif // WINCLIENTUTIL_H

File diff suppressed because it is too large Load diff

View file

@ -32,11 +32,13 @@
#include "FbTk/EventHandler.hh"
#include "FbTk/XLayerItem.hh"
#include "FbWinFrame.hh"
#include "Focusable.hh"
#include "WinButton.hh"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <sys/time.h>
#include <vector>
#include <string>
#include <memory>
@ -56,17 +58,8 @@ class Menu;
}
/// Creates the window frame and handles any window event for it
class FluxboxWindow: public FbTk::EventHandler {
class FluxboxWindow: public Focusable, public FbTk::EventHandler {
public:
/// Represents certain "preset" sets of decorations.
enum Decoration {
DECOR_NONE=0, ///< no decor at all
DECOR_NORMAL, ///< normal normal
DECOR_TINY, ///< tiny decoration
DECOR_TOOL, ///< decor tool
DECOR_TAB ///< decor tab (border + tab)
};
/// Motif wm Hints
enum {
MwmHintsFunctions = (1l << 0), ///< use motif wm functions
@ -96,14 +89,14 @@ public:
/// attributes for BlackboxHints
enum Attrib {
ATTRIB_SHADED = 0x01,
ATTRIB_MAXHORIZ = 0x02,
ATTRIB_MAXVERT = 0x04,
ATTRIB_OMNIPRESENT = 0x08,
ATTRIB_WORKSPACE = 0x10,
ATTRIB_STACK = 0x20,
ATTRIB_DECORATION = 0x40,
ATTRIB_HIDDEN = 0x80,
ATTRIB_SHADED = 0x01, ///< shaded
ATTRIB_MAXHORIZ = 0x02, ///< maximized horizontal
ATTRIB_MAXVERT = 0x04, ///< maximized vertical
ATTRIB_OMNIPRESENT = 0x08, ///< omnipresent (sticky)
ATTRIB_WORKSPACE = 0x10, ///< workspace
ATTRIB_STACK = 0x20, ///< stack
ATTRIB_DECORATION = 0x40, ///< decorations
ATTRIB_HIDDEN = 0x80, ///< hidden
};
/**
@ -135,7 +128,18 @@ public:
DECORM_LAST = (1<<11) // useful for getting "All"
};
enum Decoration {
DECOR_NONE = 0,
DECOR_NORMAL = DECORM_LAST - 1,
DECOR_TINY = DECORM_TITLEBAR|DECORM_ICONIFY|DECORM_MENU|DECORM_TAB,
DECOR_TOOL = DECORM_TITLEBAR|DECORM_MENU,
DECOR_BORDER = DECORM_BORDER|DECORM_MENU,
DECOR_TAB = DECORM_BORDER|DECORM_MENU|DECORM_TAB
};
/**
* Resize direction while resizing
*/
enum ResizeDirection {
NOCORNER = -1,
LEFTTOP = 0,
@ -149,11 +153,7 @@ public:
ALLCORNERS = 8
};
typedef struct _blackbox_hints {
unsigned long flags, attrib, workspace, stack;
long decoration;
} BlackboxHints;
/// holds old blackbox attributes
typedef struct _blackbox_attributes {
unsigned long flags, attrib, workspace, stack;
long premax_x, premax_y;
@ -179,33 +179,76 @@ public:
bool removeClient(WinClient &client);
/// set new current client and raise it
bool setCurrentClient(WinClient &client, bool setinput = true);
void setLabelButtonFocus(WinClient &client, bool value = true);
void setAttentionState(bool value);
bool getAttentionState() { return m_attention_state; }
/**
* Searches for a client
* @param win the client X window
* @return pointer to client matching the window or NULL
*/
WinClient *findClient(Window win);
/// select next client
void nextClient();
/// select previous client
void prevClient();
/// move the current client to the left
void moveClientLeft();
/// move the current client to the right
void moveClientRight();
/**
* Move a client to the right of dest.
* @param win the client to move
* @param dest the left-of-client
*/
void moveClientRightOf(WinClient &win, WinClient &dest);
/**
* Move a client to the right of dest.
* @param win the client to move
* @param dest the left-of-client
*/
void moveClientLeftOf(WinClient &win, WinClient &dest);
/**
* Move client to place specified by pixel position
* @param win the client to move
* @param x position
* @param y position
*/
void moveClientTo(WinClient &win, int x, int y);
/**
* Calculates insertition position in the list by
* using pixel position x and y.
* @param x position
* @param y position
* @return iterator position for insertion
*/
ClientList::iterator getClientInsertPosition(int x, int y);
/**
* Take focus.
* @see Focusable
* @return true if it took focus.
*/
bool focus();
bool allowsFocusFromClient();
bool setInputFocus();
void raiseAndFocus() { raise(); setInputFocus(); }
/// Raises the window and takes focus (if possible).
void raiseAndFocus() { raise(); focus(); }
/// sets the internal focus flag
void setFocusFlag(bool flag);
// map this window
/// make this window visible
void show();
// unmap this window
/// hide window
void hide(bool interrupt_moving = true);
/// iconify window
void iconify();
/**
* Deiconify window
* @param reassoc reassociate the window to the current workspace
* @param do_raise raise the window when its been deiconfied
*/
void deiconify(bool reassoc = true, bool do_raise = true);
// ------------------
// Per window transparency addons
unsigned char getFocusedAlpha() const { return frame().getAlpha(true); }
unsigned char getUnfocusedAlpha() const { return frame().getAlpha(false); }
unsigned char getFocusedAlpha() const { return frame().getAlpha(true); }
unsigned char getUnfocusedAlpha() const { return frame().getAlpha(false); }
void setFocusedAlpha(unsigned char alpha) { frame().setAlpha(true, alpha); }
void setUnfocusedAlpha(unsigned char alpha) { frame().setAlpha(false, alpha); }
void updateAlpha(bool focused, unsigned char alpha) { frame().setAlpha(focused, alpha); }
@ -218,8 +261,6 @@ public:
void close();
/// kill current client
void kill();
/// set the window in withdrawn state
void withdraw(bool interrupt_moving);
/// set fullscreen
void setFullscreen(bool flag);
/// toggle maximize
@ -245,8 +286,11 @@ public:
void tempRaise();
void raiseLayer();
void lowerLayer();
/// moves the window to a new layer
void moveToLayer(int layernum, bool force = false);
/// sets the window focus hidden state
void setFocusHidden(bool value);
/// sets the window icon hidden state
void setIconHidden(bool value);
void reconfigure();
@ -262,11 +306,21 @@ public:
void moveResize(int x, int y, unsigned int width, unsigned int height, bool send_event = false);
/// move to pos x,y and resize client window to size width, height
void moveResizeForClient(int x, int y, unsigned int width, unsigned int height, int gravity = ForgetGravity, unsigned int client_bw = 0);
/**
* Determines maximum size using all clients that this window can have.
* @param width will be filled in with maximum width
* @param height will be filled in with maximum height
*/
void maxSize(unsigned int &width, unsigned int &height);
void setWorkspace(int n);
void changeBlackboxHints(const BlackboxHints &bh);
void updateFunctions();
void restoreAttributes();
void showMenu(int mx, int my, WinClient *client = 0);
/**
* Show window meny at at given position
* @param mx position
* @param my position
*/
void showMenu(int mx, int my);
// popup menu on last button press position
void popupMenu();
@ -277,6 +331,7 @@ public:
*/
//@{
void handleEvent(XEvent &event);
void keyPressEvent(XKeyEvent &ke);
void buttonPressEvent(XButtonEvent &be);
void buttonReleaseEvent(XButtonEvent &be);
void motionNotifyEvent(XMotionEvent &me);
@ -291,7 +346,6 @@ public:
void leaveNotifyEvent(XCrossingEvent &ev);
//@}
void setDecoration(Decoration decoration, bool apply = true);
void applyDecorations(bool initial = false);
void toggleDecoration();
@ -333,7 +387,6 @@ public:
inline bool isFocusHidden() const { return m_focus_hidden; }
inline bool isIconHidden() const { return m_icon_hidden; }
inline bool isManaged() const { return m_initialized; }
inline bool isFocused() const { return focused; }
bool isVisible() const;
inline bool isIconic() { return iconic; }
inline bool isIconic() const { return iconic; }
@ -360,8 +413,7 @@ public:
inline WinClient &winClient() { return *m_client; }
inline const WinClient &winClient() const { return *m_client; }
inline const BScreen &screen() const { return m_screen; }
inline BScreen &screen() { return m_screen; }
bool isTyping();
inline const FbTk::XLayerItem &layerItem() const { return m_frame.layerItem(); }
inline FbTk::XLayerItem &layerItem() { return m_frame.layerItem(); }
@ -377,13 +429,13 @@ public:
const FbTk::FbWindow &parent() const { return m_parent; }
FbTk::FbWindow &parent() { return m_parent; }
const FbTk::FbPixmap &iconPixmap() const;
const FbTk::FbPixmap &iconMask() const;
const bool usePixmap() const;
const bool useMask() const;
bool acceptsFocus() const;
const FbTk::PixmapWithMask &icon() const;
const std::string &title() const;
const std::string &iconTitle() const;
const std::string &getWMClassName() const;
const std::string &getWMClassClass() const;
std::string getWMRole() const;
inline int x() const { return frame().x(); }
inline int y() const { return frame().y(); }
inline unsigned int width() const { return frame().width(); }
@ -425,11 +477,6 @@ public:
const FbTk::Subject &hintSig() const { return m_hintsig; }
FbTk::Subject &workspaceSig() { return m_workspacesig; }
const FbTk::Subject &workspaceSig() const { return m_workspacesig; }
FbTk::Subject &dieSig() { return m_diesig; }
const FbTk::Subject &dieSig() const { return m_diesig; }
FbTk::Subject &focusSig() { return m_focussig; }
FbTk::Subject &titleSig() { return m_titlesig; }
FbTk::Subject &attentionSig() { return m_attentionsig; }
/** @} */ // end group signals
void reconfigTheme();
@ -464,9 +511,7 @@ private:
/// gets title string from client window and updates frame's title
void updateTitleFromClient(WinClient &client);
/// gets icon name from client window
void updateIconNameFromClient(WinClient &client);
void updateMWMHintsFromClient(WinClient &client);
void updateBlackboxHintsFromClient(const WinClient &client);
void updateRememberStateFromClient(WinClient &client);
void saveBlackboxAttribs();
void associateClientWindow(bool use_attrs = false, int x = 0, int y = 0, unsigned int width = 1, unsigned int height = 1, int gravity = ForgetGravity, unsigned int client_bw = 0);
@ -479,7 +524,7 @@ private:
void fixsize(int *user_w = 0, int *user_h = 0, bool maximizing = false);
void moveResizeClient(WinClient &client, int x, int y, unsigned int width, unsigned int height);
/// sends configurenotify to all clients
void sendConfigureNotify(bool send_to_netizens = true);
void sendConfigureNotify();
static void grabPointer(Window grab_window,
Bool owner_events,
@ -496,10 +541,7 @@ private:
WinSubject m_hintsig,
m_statesig,
m_layersig,
m_workspacesig,
m_diesig, m_focussig,
m_titlesig,
m_attentionsig;
m_workspacesig;
class ThemeListener: public FbTk::Observer {
public:
@ -516,14 +558,12 @@ private:
// Window states
bool moving, resizing, shaded, iconic,
focused, stuck, m_initialized, fullscreen;
stuck, m_initialized, fullscreen;
int maximized;
WinClient *m_attaching_tab;
bool m_attention_state;
BScreen &m_screen; /// screen on which this window exist
FbTk::Timer m_timer;
Display *display; /// display connection
BlackboxAttributes m_blackbox_attrib;
@ -533,6 +573,8 @@ private:
int m_last_move_x, m_last_move_y; // handles last pos for non opaque moving
unsigned int m_last_resize_h, m_last_resize_w; // handles height/width for resize "window"
timeval m_last_keypress_time;
unsigned int m_workspace_number;
unsigned long m_current_state; // NormalState | IconicState | Withdrawn
@ -540,7 +582,7 @@ private:
ClientList m_clientlist;
WinClient *m_client; ///< current client
typedef std::map<WinClient *, FbTk::TextButton *> Client2ButtonMap;
typedef std::map<WinClient *, IconButton *> Client2ButtonMap;
Client2ButtonMap m_labelbuttons;
// just temporary solution
@ -564,14 +606,14 @@ private:
unsigned int m_old_width, m_old_height; ///< old size so we can restore from maximized state
int m_last_button_x, ///< last known x position of the mouse button
m_last_button_y; ///< last known y position of the mouse button
FbWinFrame m_frame;
FbWinFrame m_frame; ///< the actuall window frame
int m_layernum;
int m_old_layernum;
FbTk::FbWindow &m_parent; ///< window on which we draw move/resize rectangle (the "root window")
ResizeDirection m_resize_corner;
ResizeDirection m_resize_corner; //< the current resize corner used while resizing
static int s_num_grabs; ///< number of XGrabPointer's
};

View file

@ -30,13 +30,10 @@
#include "Window.hh"
#include "WinClient.hh"
#include "FbWinFrame.hh"
#include "WindowCmd.hh"
#include "FocusControl.hh"
#include "PlacementStrategy.hh"
#include "Layer.hh"
#include "FbTk/I18n.hh"
#include "FbTk/MenuItem.hh"
#include "FbTk/StringUtil.hh"
#include "FbTk/FbString.hh"
@ -64,95 +61,18 @@
#endif
#include <algorithm>
#include <iostream>
#include <iterator>
using std::string;
using std::vector;
using std::ifstream;
#ifdef DEBUG
#include <iostream>
using std::cerr;
using std::endl;
#endif // DEBUG
namespace { // anonymous
int countTransients(const WinClient &client) {
if (client.transientList().empty())
return 0;
// now go throu the entire tree and count transients
size_t ret = client.transientList().size();
WinClient::TransientList::const_iterator it = client.transientList().begin();
WinClient::TransientList::const_iterator it_end = client.transientList().end();
for (; it != it_end; ++it)
ret += countTransients(*(*it));
return ret;
}
class ClientMenuItem:public FbTk::MenuItem {
public:
ClientMenuItem(WinClient &client):
FbTk::MenuItem(client.title().c_str(), &client.screen().windowMenu()),
m_client(client) {
}
FbTk::Menu *submenu() { return &m_client.screen().windowMenu(); }
const FbTk::Menu *submenu() const { return &m_client.screen().windowMenu(); }
void showSubmenu() {
WindowCmd<void>::setClient(&m_client);
FbTk::MenuItem::showSubmenu();
}
void click(int button, int time) {
if (m_client.fbwindow() == 0)
return;
FluxboxWindow &win = *m_client.fbwindow();
if (win.screen().currentWorkspaceID() != win.workspaceNumber() &&
!win.isStuck()) {
win.menu().hide();
BScreen::FollowModel model = win.screen().getUserFollowModel();
if (model == BScreen::IGNORE_OTHER_WORKSPACES)
return;
// fetch the window to the current workspace
else if ((button == 3) ^ (model == BScreen::FETCH_ACTIVE_WINDOW ||
win.isIconic() && model == BScreen::SEMIFOLLOW_ACTIVE_WINDOW)) {
win.screen().sendToWorkspace(win.screen().currentWorkspaceID(), &win, true);
return;
}
// warp to the workspace of the window
win.screen().changeWorkspaceID(win.workspaceNumber());
}
win.setCurrentClient(m_client);
win.raiseAndFocus();
}
const string &label() const { return m_client.title(); }
bool isSelected() const {
if (m_client.fbwindow() == 0)
return false;
if (m_client.fbwindow()->isFocused() == false)
return false;
return (&(m_client.fbwindow()->winClient()) == &m_client);
}
private:
WinClient &m_client;
};
};
Workspace::GroupList Workspace::m_groups;
Workspace::Workspace(BScreen &scrn, FbTk::MultLayers &layermanager,
const string &name, unsigned int id):
Workspace::Workspace(BScreen &scrn, const string &name, unsigned int id):
m_screen(scrn),
m_clientmenu(scrn.menuTheme(), scrn.imageControl(),
*scrn.layerManager().getLayer(Layer::MENU)),
m_layermanager(layermanager),
m_clientmenu(scrn, m_windowlist, &m_clientlist_sig),
m_name(name),
m_id(id) {
@ -171,23 +91,12 @@ void Workspace::addWindow(FluxboxWindow &w, bool place) {
return;
w.setWorkspace(m_id);
// attach signals
w.titleSig().attach(this);
if (place)
placeWindow(w);
m_windowlist.push_back(&w);
updateClientmenu();
if (!w.isStuck()) {
FluxboxWindow::ClientList::iterator client_it =
w.clientList().begin();
FluxboxWindow::ClientList::iterator client_it_end =
w.clientList().end();
for (; client_it != client_it_end; ++client_it)
screen().updateNetizenWindowAdd((*client_it)->window(), m_id);
}
m_clientlist_sig.notify();
}
@ -200,28 +109,11 @@ int Workspace::removeWindow(FluxboxWindow *w, bool still_alive) {
if (w == 0)
return -1;
// detach from signals
w->titleSig().detach(this);
if (w->isFocused() && still_alive)
FocusControl::unfocusWindow(w->winClient(), true, true);
// we don't remove it from the layermanager, as it may be being moved
Windows::iterator erase_it = remove(m_windowlist.begin(),
m_windowlist.end(), w);
if (erase_it != m_windowlist.end())
m_windowlist.erase(erase_it);
updateClientmenu();
if (!w->isStuck()) {
FluxboxWindow::ClientList::iterator client_it =
w->clientList().begin();
FluxboxWindow::ClientList::iterator client_it_end =
w->clientList().end();
for (; client_it != client_it_end; ++client_it)
screen().updateNetizenWindowDel((*client_it)->window());
}
m_windowlist.remove(w);
m_clientlist_sig.notify();
return m_windowlist.size();
}
@ -239,7 +131,7 @@ void Workspace::hideAll(bool interrupt_moving) {
Windows::reverse_iterator it_end = m_windowlist.rend();
for (; it != it_end; ++it) {
if (! (*it)->isStuck())
(*it)->withdraw(interrupt_moving);
(*it)->hide(interrupt_moving);
}
}
@ -268,107 +160,6 @@ size_t Workspace::numberOfWindows() const {
return m_windowlist.size();
}
namespace {
// helper class for checkGrouping
class FindInGroup {
public:
FindInGroup(const FluxboxWindow &w):m_w(w) { }
bool operator ()(const string &name) const {
return (name == m_w.winClient().getWMClassName());
}
private:
const FluxboxWindow &m_w;
};
};
//Note: this function doesn't check if the window is groupable
bool Workspace::checkGrouping(FluxboxWindow &win) {
if (win.numClients() == 0)
return false;
#ifdef DEBUG
cerr<<__FILE__<<"("<<__LINE__<<"): Checking grouping. ("<<win.title()<<")"<<endl;
#endif // DEBUG
if (!win.isGroupable()) { // make sure this window can hold a tab
#ifdef DEBUG
cerr<<__FILE__<<"("<<__LINE__<<"): window can't use a tab"<<endl;
#endif // DEBUG
return false;
}
string instance_name = win.winClient().getWMClassName();
// go through every group and search for matching win instancename
GroupList::iterator g(m_groups.begin());
GroupList::iterator g_end(m_groups.end());
for (; g != g_end; ++g) {
Group::iterator name((*g).begin());
Group::iterator name_end((*g).end());
for (; name != name_end; ++name) {
if ((*name) != instance_name)
continue;
// find a window with the specific name
Windows::iterator wit(m_windowlist.begin());
Windows::iterator wit_end(m_windowlist.end());
for (; wit != wit_end; ++wit) {
#ifdef DEBUG
cerr<<__FILE__<<" check group with : "<<(*wit)->winClient().getWMClassName()<<endl;
#endif // DEBUG
if (find_if((*g).begin(),
(*g).end(),
FindInGroup(*(*wit))) != (*g).end()) {
// make sure the window is groupable
// and don't group with ourself
if ( !(*wit)->isGroupable() || (*wit)->winClient().fbwindow() == &win)
break; // try next name
#ifdef DEBUG
cerr<<__FILE__<<"("<<__FUNCTION__<<"): window ("<<*wit<<") attaching window ("<<&win<<")"<<endl;
#endif // DEBUG
WinClient &client = win.winClient();
(*wit)->attachClient(client);
if (client.screen().focusControl().focusNew())
(*wit)->setCurrentClient(client);
return true; // grouping done
}
}
}
}
return false;
}
bool Workspace::loadGroups(const string &filename) {
string real_filename = FbTk::StringUtil::expandFilename(filename);
FbTk::StringUtil::removeTrailingWhitespace(real_filename);
ifstream infile(real_filename.c_str());
if (!infile)
return false;
m_groups.clear(); // erase old groups
// load new groups
while (!infile.eof()) {
string line;
vector<string> names;
getline(infile, line);
FbTk::StringUtil::stringtok(names, line);
m_groups.push_back(names);
}
return true;
}
void Workspace::update(FbTk::Subject *subj) {
updateClientmenu();
}
void Workspace::setName(const string &name) {
if (!name.empty() && name != "") {
if (name == m_name)
@ -404,22 +195,7 @@ void Workspace::shutdown() {
}
void Workspace::updateClientmenu() {
// remove all items and then add them again
menu().removeAll();
// for each fluxboxwindow add every client in them to our clientlist
Windows::iterator win_it = m_windowlist.begin();
Windows::iterator win_it_end = m_windowlist.end();
for (; win_it != win_it_end; ++win_it) {
// add every client in this fluxboxwindow to menu
FluxboxWindow::ClientList::iterator client_it =
(*win_it)->clientList().begin();
FluxboxWindow::ClientList::iterator client_it_end =
(*win_it)->clientList().end();
for (; client_it != client_it_end; ++client_it)
menu().insert(new ClientMenuItem(*(*client_it)));
}
menu().updateMenu();
m_clientlist_sig.notify();
}
void Workspace::placeWindow(FluxboxWindow &win) {

View file

@ -25,30 +25,24 @@
#ifndef WORKSPACE_HH
#define WORKSPACE_HH
#include "ClientMenu.hh"
#include "FbMenu.hh"
#include "FbTk/MultLayers.hh"
#include "FbTk/Observer.hh"
#include "FbTk/NotCopyable.hh"
#include <string>
#include <vector>
#include <list>
class BScreen;
class FluxboxWindow;
class WinClient;
/**
* Handles a single workspace
*/
class Workspace:private FbTk::NotCopyable, private FbTk::Observer {
class Workspace: private FbTk::NotCopyable {
public:
typedef std::vector<FluxboxWindow *> Windows;
typedef std::list<FluxboxWindow *> Windows;
Workspace(BScreen &screen, FbTk::MultLayers &layermanager, const std::string &name,
Workspace(BScreen &screen, const std::string &name,
unsigned int workspaceid = 0);
~Workspace();
@ -83,24 +77,15 @@ public:
Windows &windowList() { return m_windowlist; }
size_t numberOfWindows() const;
bool checkGrouping(FluxboxWindow &win);
static bool loadGroups(const std::string &filename);
private:
void update(FbTk::Subject *subj);
void placeWindow(FluxboxWindow &win);
BScreen &m_screen;
FbMenu m_clientmenu;
typedef std::vector<std::string> Group;
typedef std::vector<Group> GroupList;
static GroupList m_groups; ///< handle auto groupings
FbTk::MultLayers &m_layermanager;
Windows m_windowlist;
FbTk::Subject m_clientlist_sig;
ClientMenu m_clientmenu;
std::string m_name; ///< name of this workspace
unsigned int m_id; ///< id, obsolete, this should be in BScreen

View file

@ -41,16 +41,90 @@
#include <algorithm>
#include <functional>
void WindowListCmd::execute() {
if (m_pat.error()) {
m_cmd->execute();
return;
}
BScreen *screen = Fluxbox::instance()->keyScreen();
if (screen != 0) {
FocusControl::Focusables win_list(screen->focusControl().creationOrderWinList());
FocusControl::Focusables::iterator it = win_list.begin(),
it_end = win_list.end();
for (; it != it_end; ++it) {
if (m_pat.match(**it) && (*it)->fbwindow())
m_cmd->execute(*(*it)->fbwindow());
}
}
}
void AttachCmd::execute() {
BScreen *screen = Fluxbox::instance()->keyScreen();
if (screen != 0) {
FocusControl::Focusables win_list(screen->focusControl().focusedOrderWinList());
FocusControl::Focusables::iterator it = win_list.begin(),
it_end = win_list.end();
FluxboxWindow *first = 0;
for (; it != it_end; ++it) {
if (m_pat.match(**it) && (*it)->fbwindow()) {
if (first == 0)
first = (*it)->fbwindow();
else
first->attachClient((*it)->fbwindow()->winClient());
}
}
}
}
void NextWindowCmd::execute() {
BScreen *screen = Fluxbox::instance()->keyScreen();
if (screen != 0)
screen->cycleFocus(m_option, false);
screen->cycleFocus(m_option, &m_pat, false);
}
void PrevWindowCmd::execute() {
BScreen *screen = Fluxbox::instance()->keyScreen();
if (screen != 0)
screen->cycleFocus(m_option, true);
screen->cycleFocus(m_option, &m_pat, true);
}
void TypeAheadFocusCmd::execute() {
BScreen *screen = Fluxbox::instance()->keyScreen();
if (screen != 0) {
FocusControl::Focusables *win_list = 0;
if (m_option & FocusControl::CYCLEGROUPS) {
win_list = (m_option & FocusControl::CYCLELINEAR) ?
&screen->focusControl().creationOrderWinList() :
&screen->focusControl().focusedOrderWinList();
} else {
win_list = (m_option & FocusControl::CYCLELINEAR) ?
&screen->focusControl().creationOrderList() :
&screen->focusControl().focusedOrderList();
}
screen->startTypeAheadFocus(*win_list, &m_pat);
}
}
void GoToWindowCmd::execute() {
BScreen *screen = Fluxbox::instance()->keyScreen();
if (screen != 0) {
FocusControl::Focusables *win_list = 0;
if (m_option & FocusControl::CYCLEGROUPS) {
win_list = (m_option & FocusControl::CYCLELINEAR) ?
&screen->focusControl().creationOrderWinList() :
&screen->focusControl().focusedOrderWinList();
} else {
win_list = (m_option & FocusControl::CYCLELINEAR) ?
&screen->focusControl().creationOrderList() :
&screen->focusControl().focusedOrderList();
}
screen->focusControl().goToWindowNumber(*win_list, m_num, &m_pat);
}
}
void DirFocusCmd::execute() {
@ -250,19 +324,6 @@ void ShowDesktopCmd::execute() {
std::mem_fun(&FluxboxWindow::iconify));
}
void MinimizeLayerCmd::execute() {
FluxboxWindow *win = FocusControl::focusedFbWindow();
if (!win)
return;
Workspace::Windows windows(win->screen().currentWorkspace()->windowList());
Workspace::Windows::iterator it = windows.begin(), it_end = windows.end();
for (; it != it_end; ++it) {
if (win->layerNum() == (*it)->layerNum())
(*it)->iconify();
}
}
void CloseAllWindowsCmd::execute() {
BScreen *screen = Fluxbox::instance()->mouseScreen();
if (screen == 0)

View file

@ -26,23 +26,73 @@
#define WORKSPACECMD_HH
#include "Command.hh"
#include "ClientPattern.hh"
#include "CurrentWindowCmd.hh"
#include "FocusControl.hh"
#include "FbTk/RefCount.hh"
class WindowHelperCmd;
class WindowListCmd: public FbTk::Command {
public:
WindowListCmd(FbTk::RefCount<WindowHelperCmd> cmd, const std::string &pat):
m_cmd(cmd), m_pat(pat.c_str()) { }
void execute();
private:
FbTk::RefCount<WindowHelperCmd> m_cmd;
ClientPattern m_pat;
};
class AttachCmd: public FbTk::Command {
public:
explicit AttachCmd(const std::string &pat): m_pat(pat.c_str()) { }
void execute();
private:
const ClientPattern m_pat;
};
class NextWindowCmd: public FbTk::Command {
public:
explicit NextWindowCmd(int option):m_option(option) { }
explicit NextWindowCmd(int option, std::string &pat):
m_option(option), m_pat(pat.c_str()) { }
void execute();
private:
const int m_option;
const ClientPattern m_pat;
};
class PrevWindowCmd: public FbTk::Command {
public:
explicit PrevWindowCmd(int option):m_option(option) { }
explicit PrevWindowCmd(int option, std::string &pat):
m_option(option), m_pat(pat.c_str()) { }
void execute();
private:
const int m_option;
const ClientPattern m_pat;
};
class TypeAheadFocusCmd: public FbTk::Command {
public:
explicit TypeAheadFocusCmd(int option, std::string &pat):
m_option(option), m_pat(pat.c_str()) { }
void execute();
private:
const int m_option;
const ClientPattern m_pat;
};
class GoToWindowCmd: public FbTk::Command {
public:
GoToWindowCmd(int num, int option, std::string &pat):
m_num(num), m_option(option), m_pat(pat.c_str()) { }
void execute();
private:
const int m_num;
const int m_option;
const ClientPattern m_pat;
};
class DirFocusCmd: public FbTk::Command {
@ -114,11 +164,6 @@ public:
void execute();
};
class MinimizeLayerCmd: public FbTk::Command {
public:
void execute();
};
class CloseAllWindowsCmd: public FbTk::Command {
public:
void execute();

View file

@ -28,12 +28,21 @@
class BScreen;
/**
* A menu specific for workspace.
* Contains some simple workspace commands
* such as new/delete workspace and edit
* workspace name.
* It also contains client menus for all clients.
*/
class WorkspaceMenu: public FbMenu {
public:
explicit WorkspaceMenu(BScreen &screen);
virtual ~WorkspaceMenu() { }
/// called when a subject is sending a signal
void update(FbTk::Subject *subj);
private:
/// initialize menu for the screen
void init(BScreen &screen);
};

View file

@ -56,8 +56,8 @@ FbTk::FbString getWMName(Window window) {
XTextProperty text_prop;
text_prop.value = 0;
char **list;
int num;
char **list = 0;
int num = 0;
_FB_USES_NLS;
string name;
@ -66,15 +66,16 @@ FbTk::FbString getWMName(Window window) {
if (text_prop.encoding != XA_STRING) {
text_prop.nitems = strlen((char *) text_prop.value);
XmbTextPropertyToTextList(display, &text_prop, &list, &num);
if ((XmbTextPropertyToTextList(display, &text_prop,
&list, &num) == Success) &&
(num > 0) && *list) {
if (num > 0 && list != 0)
name = FbTk::FbStringUtil::LocaleStrToFb(static_cast<char *>(*list));
XFreeStringList(list);
} else
else
name = text_prop.value ? FbTk::FbStringUtil::XStrToFb((char *)text_prop.value) : "";
if (list)
XFreeStringList(list);
} else
name = text_prop.value ? FbTk::FbStringUtil::XStrToFb((char *)text_prop.value) : "";

View file

@ -206,7 +206,6 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile
m_rc_menufile(m_resourcemanager, DEFAULTMENU, "session.menuFile", "Session.MenuFile"),
m_rc_keyfile(m_resourcemanager, DEFAULTKEYSFILE, "session.keyFile", "Session.KeyFile"),
m_rc_slitlistfile(m_resourcemanager, "~/." + realProgramName("fluxbox") + "/slitlist", "session.slitlistFile", "Session.SlitlistFile"),
m_rc_groupfile(m_resourcemanager, "~/." + realProgramName("fluxbox") + "/groups", "session.groupFile", "Session.GroupFile"),
m_rc_appsfile(m_resourcemanager, "~/." + realProgramName("fluxbox") + "/apps", "session.appsFile", "Session.AppsFile"),
m_rc_tabs_attach_area(m_resourcemanager, ATTACH_AREA_WINDOW, "session.tabsAttachArea", "Session.TabsAttachArea"),
m_rc_cache_life(m_resourcemanager, 5, "session.cacheLife", "Session.CacheLife"),
@ -320,6 +319,11 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile
#endif // HAVE_GETPID
// Create keybindings handler and load keys file
// Note: this needs to be done before creating screens
m_key.reset(new Keys);
m_key->load(StringUtil::expandFilename(*m_rc_keyfile).c_str());
vector<int> screens;
int i;
@ -415,10 +419,6 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile
m_reconfigure_wait = m_reread_menu_wait = false;
// Create keybindings handler and load keys file
m_key.reset(new Keys);
m_key->load(StringUtil::expandFilename(*m_rc_keyfile).c_str());
m_resourcemanager.unlock();
ungrab();
@ -545,8 +545,11 @@ void Fluxbox::eventLoop() {
if (last_bad_window != None && e.xany.window == last_bad_window &&
e.type != DestroyNotify) { // we must let the actual destroys through
if (e.type == FocusOut)
m_revert_timer.start();
#ifdef DEBUG
cerr<<"Fluxbox::eventLoop(): removing bad window from event queue"<<endl;
else
cerr<<"Fluxbox::eventLoop(): removing bad window from event queue"<<endl;
#endif // DEBUG
} else {
last_bad_window = None;
@ -640,7 +643,7 @@ void Fluxbox::setupConfigFiles() {
if (create_init)
FbTk::FileUtil::copyFile(DEFAULT_INITFILE, init_file.c_str());
#define CONFIG_VERSION 1
#define CONFIG_VERSION 3
FbTk::Resource<int> config_version(m_resourcemanager, 0,
"session.configVersion", "Session.ConfigVersion");
if (*config_version < CONFIG_VERSION) {
@ -1019,41 +1022,6 @@ void Fluxbox::handleClientMessage(XClientMessageEvent &ce) {
winclient->fbwindow()->iconify();
if (ce.data.l[0] == NormalState)
winclient->fbwindow()->deiconify();
} else if (ce.message_type == m_fbatoms->getFluxboxChangeWorkspaceAtom()) {
BScreen *screen = searchScreen(ce.window);
if (screen && ce.data.l[0] >= 0 &&
ce.data.l[0] < (signed)screen->numberOfWorkspaces())
screen->changeWorkspaceID(ce.data.l[0]);
} else if (ce.message_type == m_fbatoms->getFluxboxChangeWindowFocusAtom()) {
WinClient *winclient = searchWindow(ce.window);
if (winclient) {
FluxboxWindow *win = winclient->fbwindow();
if (win && win->isVisible())
win->setCurrentClient(*winclient, true);
}
} else if (ce.message_type == m_fbatoms->getFluxboxCycleWindowFocusAtom()) {
BScreen *screen = searchScreen(ce.window);
if (screen) {
if (! ce.data.l[0])
screen->focusControl().prevFocus();
else
screen->focusControl().nextFocus();
}
} else if (ce.message_type == m_fbatoms->getFluxboxChangeAttributesAtom()) {
WinClient *winclient = searchWindow(ce.window);
FluxboxWindow *win = 0;
if (winclient && (win = winclient->fbwindow()) && winclient->validateClient()) {
FluxboxWindow::BlackboxHints net;
net.flags = ce.data.l[0];
net.attrib = ce.data.l[1];
net.workspace = ce.data.l[2];
net.stack = ce.data.l[3];
net.decoration = static_cast<int>(ce.data.l[4]);
win->changeBlackboxHints(net);
}
} else {
WinClient *winclient = searchWindow(ce.window);
BScreen *screen = searchScreen(ce.window);
@ -1117,73 +1085,92 @@ void Fluxbox::handleSignal(int signum) {
void Fluxbox::update(FbTk::Subject *changedsub) {
//TODO: fix signaling, this does not look good
FluxboxWindow *fbwin = 0;
WinClient *client = 0;
if (typeid(*changedsub) == typeid(FluxboxWindow::WinSubject)) {
FluxboxWindow::WinSubject *winsub = dynamic_cast<FluxboxWindow::WinSubject *>(changedsub);
FluxboxWindow &win = winsub->win();
if ((&(win.hintSig())) == changedsub) { // hint signal
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ( (*it).first->update())
(*it).first->updateHints(win);
}
} else if ((&(win.stateSig())) == changedsub) { // state signal
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateState(win);
}
// if window changed to iconic state
// add to icon list
if (win.isIconic()) {
win.screen().addIcon(&win);
Workspace *space = win.screen().getWorkspace(win.workspaceNumber());
if (space != 0)
space->removeWindow(&win, true);
}
fbwin = &winsub->win();
} else if (typeid(*changedsub) == typeid(Focusable::FocusSubject)) {
Focusable::FocusSubject *winsub = dynamic_cast<Focusable::FocusSubject *>(changedsub);
fbwin = winsub->win().fbwindow();
if (typeid(winsub->win()) == typeid(WinClient))
client = dynamic_cast<WinClient *>(&winsub->win());
}
if (win.isStuck()) {
// if we're sticky then reassociate window
// to all workspaces
BScreen &scr = win.screen();
if (scr.currentWorkspaceID() != win.workspaceNumber()) {
scr.reassociateWindow(&win,
scr.currentWorkspaceID(),
true);
}
}
} else if ((&(win.layerSig())) == changedsub) { // layer signal
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateLayer(win);
}
} else if ((&(win.dieSig())) == changedsub) { // window death signal
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateFrameClose(win);
}
// make sure each workspace get this
BScreen &scr = win.screen();
scr.removeWindow(&win);
if (FocusControl::focusedFbWindow() == &win)
FocusControl::setFocusedFbWindow(0);
} else if ((&(win.workspaceSig())) == changedsub) { // workspace signal
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateWorkspace(win);
}
} else {
#ifdef DEBUG
cerr<<__FILE__<<"("<<__LINE__<<"): WINDOW uncought signal from "<<&win<<endl;
#endif // DEBUG
if (fbwin && &fbwin->stateSig() == changedsub) { // state signal
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateState(*fbwin);
}
// if window changed to iconic state
// add to icon list
if (fbwin->isIconic()) {
fbwin->screen().addIcon(fbwin);
Workspace *space = fbwin->screen().getWorkspace(fbwin->workspaceNumber());
if (space != 0)
space->removeWindow(fbwin, true);
}
if (fbwin->isStuck()) {
// if we're sticky then reassociate window
// to all workspaces
BScreen &scr = fbwin->screen();
if (scr.currentWorkspaceID() != fbwin->workspaceNumber()) {
scr.reassociateWindow(fbwin,
scr.currentWorkspaceID(),
true);
}
}
} else if (fbwin && &fbwin->layerSig() == changedsub) { // layer signal
AtomHandlerContainerIt it= m_atomhandler.begin();
for (; it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateLayer(*fbwin);
}
} else if (fbwin && &fbwin->dieSig() == changedsub) { // window death signal
AtomHandlerContainerIt it= m_atomhandler.begin();
for (; it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateFrameClose(*fbwin);
}
// make sure each workspace get this
BScreen &scr = fbwin->screen();
scr.removeWindow(fbwin);
if (FocusControl::focusedFbWindow() == fbwin)
FocusControl::setFocusedFbWindow(0);
} else if (fbwin && &fbwin->workspaceSig() == changedsub) { // workspace signal
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateWorkspace(*fbwin);
}
} else if (client && &client->dieSig() == changedsub) { // client death
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateClientClose(*client);
}
BScreen &screen = client->screen();
screen.removeClient(*client);
// At this point, we trust that this client is no longer in the
// client list of its frame (but it still has reference to the frame)
// We also assume that any remaining active one is the last focused one
// This is where we revert focus on window close
// NOWHERE ELSE!!!
if (FocusControl::focusedWindow() == client) {
FocusControl::unfocusWindow(*client);
// make sure nothing else uses this window before focus reverts
FocusControl::setFocusedWindow(0);
m_revert_screen = &screen;
m_revert_timer.start();
}
} else if (typeid(*changedsub) == typeid(BScreen::ScreenSubject)) {
BScreen::ScreenSubject *subj = dynamic_cast<BScreen::ScreenSubject *>(changedsub);
BScreen &screen = subj->screen();
@ -1218,37 +1205,6 @@ void Fluxbox::update(FbTk::Subject *changedsub) {
(*it).first->updateClientList(screen);
}
}
} else if (typeid(*changedsub) == typeid(WinClient::WinClientSubj)) {
WinClient::WinClientSubj *subj = dynamic_cast<WinClient::WinClientSubj *>(changedsub);
WinClient &client = subj->winClient();
// TODO: don't assume it is diesig (need to fix as soon as another signal appears)
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateClientClose(client);
}
BScreen &screen = client.screen();
screen.removeClient(client);
// finaly send notify signal
screen.updateNetizenWindowDel(client.window());
// At this point, we trust that this client is no longer in the
// client list of its frame (but it still has reference to the frame)
// We also assume that any remaining active one is the last focused one
// This is where we revert focus on window close
// NOWHERE ELSE!!!
if (FocusControl::focusedWindow() == &client) {
FocusControl::unfocusWindow(client);
// make sure nothing else uses this window before focus reverts
FocusControl::setFocusedWindow(0);
m_revert_screen = &screen;
m_revert_timer.start();
}
}
}
@ -1450,7 +1406,7 @@ string Fluxbox::getRcFilename() {
}
/// Provides default filename of data file
void Fluxbox::getDefaultDataFilename(const char *name, string &filename) {
void Fluxbox::getDefaultDataFilename(const char *name, string &filename) const {
filename = string(getenv("HOME") + string("/.") + m_RC_PATH + string("/") + name);
}
@ -1492,12 +1448,6 @@ void Fluxbox::load_rc() {
if (m_rc_stylefile->empty())
*m_rc_stylefile = DEFAULTSTYLE;
if (!Workspace::loadGroups(*m_rc_groupfile)) {
#ifdef DEBUG
cerr<<_FB_CONSOLETEXT(Fluxbox, CantLoadGroupFile, "Failed to load groupfile", "Couldn't load the groupfile")<<": "<<*m_rc_groupfile<<endl;
#endif // DEBUG
}
}
void Fluxbox::load_rc(BScreen &screen) {
@ -1735,7 +1685,6 @@ bool Fluxbox::validateClient(const WinClient *client) const {
void Fluxbox::updateFocusedWindow(BScreen *screen, BScreen *old_screen) {
if (screen != 0) {
screen->updateNetizenWindowFocus();
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); it++) {
(*it).first->updateFocusedWindow(*screen, (FocusControl::focusedWindow() ?
@ -1745,7 +1694,6 @@ void Fluxbox::updateFocusedWindow(BScreen *screen, BScreen *old_screen) {
}
if (old_screen && old_screen != screen) {
old_screen->updateNetizenWindowFocus();
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); it++)
(*it).first->updateFocusedWindow(*old_screen, 0);

View file

@ -196,7 +196,7 @@ public:
bool menuTimestampsChanged() const;
bool haveShape() const { return m_have_shape; }
int shapeEventbase() const { return m_shape_eventbase; }
void getDefaultDataFilename(const char *name, std::string &);
void getDefaultDataFilename(const char *name, std::string &) const;
// screen mouse was in at last key event
BScreen *mouseScreen() { return m_mousescreen; }
// screen of window that last key event (i.e. focused window) went to
@ -240,7 +240,7 @@ private:
FbTk::Resource<std::string> m_rc_stylefile,
m_rc_styleoverlayfile,
m_rc_menufile, m_rc_keyfile, m_rc_slitlistfile,
m_rc_groupfile, m_rc_appsfile;
m_rc_appsfile;
FbTk::Resource<TabsAttachArea> m_rc_tabs_attach_area;

View file

@ -38,23 +38,17 @@
#define _GNU_SOURCE
#endif // _GNU_SOURCE
#ifdef HAVE_CSTDIO
#include <cstdio>
#else
#include <stdio.h>
#endif
#ifdef HAVE_CSTDLIB
#include <cstdlib>
#else
#include <stdlib.h>
#endif
#ifdef HAVE_CSTRING
#include <cstring>
#else
#include <string.h>
#endif
#include <iostream>
#include <fstream>
#include <set>
#include <map>
#include <list>
using std::cout;
using std::cerr;
@ -62,39 +56,34 @@ using std::endl;
using std::string;
using std::ifstream;
using std::ofstream;
using std::set;
using std::map;
using std::list;
#define VERSION 1
string read_file(string filename);
void write_file(string filename, string &contents);
void save_all_files();
int run_updates(int old_version, FbTk::ResourceManager rm) {
int new_version = old_version;
FbTk::Resource<string> rc_keyfile(rm, "~/.fluxbox/keys",
"session.keyFile", "Session.KeyFile");
FbTk::Resource<string> rc_appsfile(rm, "~/.fluxbox/apps",
"session.appsFile", "Session.AppsFile");
string appsfilename = FbTk::StringUtil::expandFilename(*rc_appsfile);
string keyfilename = FbTk::StringUtil::expandFilename(*rc_keyfile);
if (old_version < 1) { // add mouse events to keys file
FbTk::Resource<string> rc_keyfile(rm, DEFAULTKEYSFILE,
"session.keyFile", "Session.KeyFile");
string keyfilename = FbTk::StringUtil::expandFilename(*rc_keyfile);
// ok, I don't know anything about file handling in c++
// what's it to you?!?!
// I assume there should be some error handling in here, but I sure
// don't know how, and I don't have documentation
ifstream in_keyfile(keyfilename.c_str());
string whole_keyfile = "";
while (!in_keyfile.eof()) {
string linebuffer;
getline(in_keyfile, linebuffer);
whole_keyfile += linebuffer + "\n";
}
in_keyfile.close();
ofstream out_keyfile(keyfilename.c_str());
string whole_keyfile = read_file(keyfilename);
string new_keyfile = "";
// let's put our new keybindings first, so they're easy to find
out_keyfile << "!mouse actions added by fluxbox-update_configs" << endl
<< "OnDesktop Mouse1 :hideMenus" << endl
<< "OnDesktop Mouse2 :workspaceMenu" << endl
<< "OnDesktop Mouse3 :rootMenu" << endl;
new_keyfile += "!mouse actions added by fluxbox-update_configs\n";
new_keyfile += "OnDesktop Mouse1 :hideMenus\n";
new_keyfile += "OnDesktop Mouse2 :workspaceMenu\n";
new_keyfile += "OnDesktop Mouse3 :rootMenu\n";
// scrolling on desktop needs to match user's desktop wheeling settings
// hmmm, what are the odds that somebody wants this to be different on
@ -108,25 +97,97 @@ int run_updates(int old_version, FbTk::ResourceManager rm) {
"Session.Screen0.ReverseWheeling");
if (*rc_wheeling) {
if (*rc_reverse) { // if you ask me, this should have been default
out_keyfile << "OnDesktop Mouse4 :prevWorkspace" << endl
<< "OnDesktop Mouse5 :nextWorkspace" << endl;
new_keyfile += "OnDesktop Mouse4 :prevWorkspace\n";
new_keyfile += "OnDesktop Mouse5 :nextWorkspace\n";
} else {
out_keyfile << "OnDesktop Mouse4 :nextWorkspace" << endl
<< "OnDesktop Mouse5 :prevWorkspace" << endl;
new_keyfile += "OnDesktop Mouse4 :nextWorkspace\n";
new_keyfile += "OnDesktop Mouse5 :prevWorkspace\n";
}
}
out_keyfile << endl; // just for good looks
new_keyfile += "\n"; // just for good looks
new_keyfile += whole_keyfile; // don't forget user's old keybindings
// now, restore user's old keybindings
out_keyfile << whole_keyfile;
write_file(keyfilename, new_keyfile);
new_version = 1;
}
if (old_version < 2) { // move groups entries to apps file
FbTk::Resource<string> rc_groupfile(rm, "~/.fluxbox/groups",
"session.groupFile", "Session.GroupFile");
string groupfilename = FbTk::StringUtil::expandFilename(*rc_groupfile);
string whole_groupfile = read_file(groupfilename);
string whole_appsfile = read_file(appsfilename);
string new_appsfile = "";
list<string> lines;
FbTk::StringUtil::stringtok(lines, whole_groupfile, "\n");
list<string>::iterator line_it = lines.begin();
list<string>::iterator line_it_end = lines.end();
for (; line_it != line_it_end; ++line_it) {
new_appsfile += "[group] (workspace=[current])\n";
list<string> apps;
FbTk::StringUtil::stringtok(apps, *line_it);
list<string>::iterator it = apps.begin();
list<string>::iterator it_end = apps.end();
for (; it != it_end; ++it) {
new_appsfile += " [app] (name=";
new_appsfile += *it;
new_appsfile += ")\n";
}
new_appsfile += "[end]\n";
}
new_appsfile += whole_appsfile;
write_file(appsfilename, new_appsfile);
new_version = 2;
}
if (old_version < 3) { // move toolbar wheeling to keys file
string whole_keyfile = read_file(keyfilename);
string new_keyfile = "";
// let's put our new keybindings first, so they're easy to find
new_keyfile += "!mouse actions added by fluxbox-update_configs\n";
bool keep_changes = false;
// scrolling on toolbar needs to match user's toolbar wheeling settings
FbTk::Resource<string> rc_wheeling(rm, "Off",
"session.screen0.iconbar.wheelMode",
"Session.Screen0.Iconbar.WheelMode");
FbTk::Resource<bool> rc_screen(rm, true,
"session.screen0.desktopwheeling",
"Session.Screen0.DesktopWheeling");
FbTk::Resource<bool> rc_reverse(rm, false,
"session.screen0.reversewheeling",
"Session.Screen0.ReverseWheeling");
if (strcasecmp((*rc_wheeling).c_str(), "On") == 0 ||
(strcasecmp((*rc_wheeling).c_str(), "Screen") && *rc_screen)) {
keep_changes = true;
if (*rc_reverse) { // if you ask me, this should have been default
new_keyfile += "OnToolbar Mouse4 :prevWorkspace\n";
new_keyfile += "OnToolbar Mouse5 :nextWorkspace\n";
} else {
new_keyfile += "OnToolbar Mouse4 :nextWorkspace\n";
new_keyfile += "OnToolbar Mouse5 :prevWorkspace\n";
}
}
new_keyfile += "\n"; // just for good looks
new_keyfile += whole_keyfile; // don't forget user's old keybindings
if (keep_changes)
write_file(keyfilename, new_keyfile);
new_version = 3;
}
return new_version;
}
int main(int argc, char **argv) {
string rc_filename;
set<string> style_filenames;
int i = 1;
pid_t fb_pid = 0;
@ -184,8 +245,10 @@ int main(int argc, char **argv) {
int old_version = *config_version;
int new_version = run_updates(old_version, resource_manager);
if (new_version > old_version) {
// configs were updated -- let's save our changes
config_version = new_version;
resource_manager.save(rc_filename.c_str(), rc_filename.c_str());
save_all_files();
#ifdef HAVE_SIGNAL_H
// if we were given a fluxbox pid, send it a reconfigure signal
@ -197,3 +260,75 @@ int main(int argc, char **argv) {
return 0;
}
static set<string> modified_files;
// we may want to put a size limit on this cache, so it doesn't grow too big
static map<string,string> file_cache;
// returns the contents of the file given, either from the cache or by reading
// the file from disk
string read_file(string filename) {
// check if we already have the file in memory
map<string,string>::iterator it = file_cache.find(filename);
if (it != file_cache.end())
return it->second;
// nope, we'll have to read the file
ifstream infile(filename.c_str());
string whole_file = "";
if (!infile) // failed to open file
return whole_file;
while (!infile.eof()) {
string linebuffer;
getline(infile, linebuffer);
whole_file += linebuffer + "\n";
}
infile.close();
file_cache[filename] = whole_file;
return whole_file;
}
#ifdef NOT_USED
// remove the file from the cache, writing to disk if it's been changed
void forget_file(string filename) {
map<string,string>::iterator cache_it = file_cache.find(filename);
// check if we knew about the file to begin with
if (cache_it == file_cache.end())
return;
// check if we've actually modified it
set<string>::iterator mod_it = modified_files.find(filename);
if (mod_it == modified_files.end()) {
file_cache.erase(cache_it);
return;
}
// flush our changes to disk and remove all traces
ofstream outfile(filename.c_str());
outfile << cache_it->second;
file_cache.erase(cache_it);
modified_files.erase(mod_it);
}
#endif // NOT_USED
// updates the file contents in the cache and marks the file as modified so it
// gets saved later
void write_file(string filename, string &contents) {
modified_files.insert(filename);
file_cache[filename] = contents;
}
// actually save all the files we've modified
void save_all_files() {
set<string>::iterator it = modified_files.begin();
set<string>::iterator it_end = modified_files.end();
for (; it != it_end; ++it) {
ofstream outfile(it->c_str());
outfile << file_cache[it->c_str()];
}
modified_files.clear();
}