merged changes from pre-devel
This commit is contained in:
parent
41b5c6dadb
commit
a59428d67a
92 changed files with 3066 additions and 3160 deletions
131
ChangeLog
131
ChangeLog
|
@ -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:
|
||||
|
|
|
@ -77,6 +77,10 @@ enum {
|
|||
ConfigmenuExternalTabWidth = 23,
|
||||
ConfigmenuMouseTabFocus = 24,
|
||||
ConfigmenuClickTabFocus = 25,
|
||||
ConfigmenuMaxMenu = 26,
|
||||
ConfigmenuMaxIgnoreInc = 27,
|
||||
ConfigmenuMaxDisableMove = 28,
|
||||
ConfigmenuMaxDisableResize = 29,
|
||||
|
||||
EwmhSet = 5,
|
||||
EwmhOutOfMemoryClientList = 1,
|
||||
|
|
|
@ -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\
|
||||
|
|
|
@ -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\
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
||||
|
|
|
@ -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
146
src/ClientMenu.cc
Normal 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);
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
|
|
|
@ -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:
|
||||
/**
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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) { }
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
73
src/Ewmh.cc
73
src/Ewmh.cc
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
140
src/Focusable.hh
Normal 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
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
110
src/Keys.cc
110
src/Keys.cc
|
@ -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_;
|
||||
|
|
32
src/Keys.hh
32
src/Keys.hh
|
@ -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
|
||||
|
|
49
src/Layer.hh
49
src/Layer.hh
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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
186
src/MinOverlapPlacement.cc
Normal 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;
|
||||
}
|
83
src/MinOverlapPlacement.hh
Normal file
83
src/MinOverlapPlacement.hh
Normal 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
|
112
src/Netizen.cc
112
src/Netizen.cc
|
@ -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);
|
||||
}
|
|
@ -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() { }
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<>
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
324
src/Screen.cc
324
src/Screen.cc
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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 ¬_used) {
|
||||
if (! doAutoHide()) {
|
||||
if (isHidden())
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
122
src/WinClient.cc
122
src/WinClient.cc
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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
|
850
src/Window.cc
850
src/Window.cc
File diff suppressed because it is too large
Load diff
170
src/Window.hh
170
src/Window.hh
|
@ -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
|
||||
};
|
||||
|
|
240
src/Workspace.cc
240
src/Workspace.cc
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
15
src/Xutil.cc
15
src/Xutil.cc
|
@ -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) : "";
|
||||
|
||||
|
|
236
src/fluxbox.cc
236
src/fluxbox.cc
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue