added support for _NET_WM_ALLOWED_ACTIONS and all the _NET_WM_ACTION_*. Added _NET_WM_STATE_MODAL and _NET_WM_WINDOW_TYPE_SPLASH
This commit is contained in:
parent
b0d7010f8b
commit
75d289be65
6 changed files with 178 additions and 28 deletions
149
src/Ewmh.cc
149
src/Ewmh.cc
|
@ -28,6 +28,8 @@
|
|||
#include "WinClient.hh"
|
||||
#include "Workspace.hh"
|
||||
#include "Layer.hh"
|
||||
#include "WinClientUtil.hh"
|
||||
|
||||
#include "FbTk/App.hh"
|
||||
#include "FbTk/FbWindow.hh"
|
||||
#include "FbTk/I18n.hh"
|
||||
|
@ -109,11 +111,28 @@ void Ewmh::initForScreen(BScreen &screen) {
|
|||
m_net_wm_state_fullscreen,
|
||||
m_net_wm_state_hidden,
|
||||
m_net_wm_state_skip_taskbar,
|
||||
|
||||
m_net_wm_state_modal,
|
||||
m_net_wm_state_below,
|
||||
m_net_wm_state_above,
|
||||
|
||||
// window type
|
||||
m_net_wm_window_type,
|
||||
m_net_wm_window_type_dock,
|
||||
m_net_wm_window_type_desktop,
|
||||
m_net_wm_window_type_splash,
|
||||
|
||||
// window actions
|
||||
m_net_wm_allowed_actions,
|
||||
m_net_wm_action_move,
|
||||
m_net_wm_action_resize,
|
||||
m_net_wm_action_minimize,
|
||||
m_net_wm_action_shade,
|
||||
m_net_wm_action_stick,
|
||||
m_net_wm_action_maximize_horz,
|
||||
m_net_wm_action_maximize_vert,
|
||||
m_net_wm_action_fullscreen,
|
||||
m_net_wm_action_change_desktop,
|
||||
m_net_wm_action_close,
|
||||
|
||||
// root properties
|
||||
m_net_client_list,
|
||||
|
@ -223,6 +242,15 @@ void Ewmh::setupFrame(FluxboxWindow &win) {
|
|||
win.setMovable(false);
|
||||
win.setResizable(false);
|
||||
win.stick();
|
||||
|
||||
} else if (atoms[l] == m_net_wm_window_type_splash) {
|
||||
/*
|
||||
* _NET_WM_WINDOW_TYPE_SPLASH indicates that the
|
||||
* window is a splash screen displayed as an application
|
||||
* is starting up.
|
||||
*/
|
||||
win.setDecoration(FluxboxWindow::DECOR_NONE);
|
||||
win.setMovable(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -297,7 +325,8 @@ void Ewmh::updateClientList(BScreen &screen) {
|
|||
Window *wl = FB_new_nothrow Window[num];
|
||||
if (wl == 0) {
|
||||
_FB_USES_NLS;
|
||||
cerr<<_FBTEXT(Ewmh, OutOfMemoryClientList, "Fatal: Out of memory, can't allocate for EWMH client list", "")<<endl;
|
||||
cerr<<_FBTEXT(Ewmh, OutOfMemoryClientList,
|
||||
"Fatal: Out of memory, can't allocate for EWMH client list", "")<<endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -523,8 +552,8 @@ void Ewmh::updateWorkarea(BScreen &screen) {
|
|||
|
||||
void Ewmh::updateState(FluxboxWindow &win) {
|
||||
|
||||
// TODO: should we update the _NET_WM_ALLOWED_ACTIONS
|
||||
// here too?
|
||||
|
||||
updateActions(win);
|
||||
|
||||
typedef std::vector<unsigned int> StateVec;
|
||||
|
||||
|
@ -542,14 +571,13 @@ void Ewmh::updateState(FluxboxWindow &win) {
|
|||
state.push_back(m_net_wm_state_hidden);
|
||||
if (win.isIconHidden())
|
||||
state.push_back(m_net_wm_state_skip_taskbar);
|
||||
if (win.isFullscreen()) {
|
||||
if (win.isFullscreen())
|
||||
state.push_back(m_net_wm_state_fullscreen);
|
||||
}
|
||||
if (win.winClient().isModal())
|
||||
state.push_back(m_net_wm_state_modal);
|
||||
|
||||
FluxboxWindow::ClientList::iterator it = win.clientList().begin();
|
||||
FluxboxWindow::ClientList::iterator it_end = win.clientList().end();
|
||||
|
||||
it = win.clientList().begin();
|
||||
for (; it != it_end; ++it) {
|
||||
|
||||
// search the old states for _NET_WM_STATE_SKIP_PAGER and append it
|
||||
|
@ -565,18 +593,19 @@ void Ewmh::updateState(FluxboxWindow &win) {
|
|||
&data);
|
||||
if (data) {
|
||||
Atom *old_states = (Atom *)data;
|
||||
for (unsigned long i=0; i < nitems; ++i)
|
||||
for (unsigned long i=0; i < nitems; ++i) {
|
||||
if (old_states[i] == m_net_wm_state_skip_pager) {
|
||||
client_state.push_back(m_net_wm_state_skip_pager);
|
||||
}
|
||||
}
|
||||
XFree(data);
|
||||
}
|
||||
|
||||
if (!client_state.empty())
|
||||
if (!client_state.empty()) {
|
||||
(*it)->changeProperty(m_net_wm_state, XA_ATOM, 32, PropModeReplace,
|
||||
reinterpret_cast<unsigned char*>(&client_state.front()),
|
||||
client_state.size());
|
||||
else
|
||||
} else
|
||||
(*it)->deleteProperty(m_net_wm_state);
|
||||
}
|
||||
}
|
||||
|
@ -750,9 +779,6 @@ bool Ewmh::checkClientMessage(const XClientMessageEvent &ce,
|
|||
|
||||
bool Ewmh::propertyNotify(WinClient &winclient, Atom the_property) {
|
||||
if (the_property == m_net_wm_strut) {
|
||||
#ifdef DEBUG
|
||||
cerr<<"_NET_WM_STRUT"<<endl;
|
||||
#endif // DEBUG
|
||||
updateStrut(winclient);
|
||||
return true;
|
||||
}
|
||||
|
@ -791,6 +817,7 @@ void Ewmh::createAtoms() {
|
|||
m_net_wm_window_type = XInternAtom(disp, "_NET_WM_WINDOW_TYPE", False);
|
||||
m_net_wm_window_type_dock = XInternAtom(disp, "_NET_WM_WINDOW_TYPE_DOCK", False);
|
||||
m_net_wm_window_type_desktop = XInternAtom(disp, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
|
||||
m_net_wm_window_type_splash = XInternAtom(disp, "_NET_WM_WINDOW_TYPE_SPLASH", False);
|
||||
|
||||
// state atom and the supported state atoms
|
||||
m_net_wm_state = XInternAtom(disp, "_NET_WM_STATE", False);
|
||||
|
@ -804,19 +831,20 @@ void Ewmh::createAtoms() {
|
|||
m_net_wm_state_skip_pager = XInternAtom(disp, "_NET_WM_STATE_SKIP_PAGER", False);
|
||||
m_net_wm_state_above = XInternAtom(disp, "_NET_WM_STATE_ABOVE", False);
|
||||
m_net_wm_state_below = XInternAtom(disp, "_NET_WM_STATE_BELOW", False);
|
||||
m_net_wm_state_modal = XInternAtom(disp, "_NET_WM_STATE_MODAL", False);
|
||||
|
||||
// allowed actions
|
||||
m_net_wm_allowed_actions = XInternAtom(disp, "_NET_WM_ALLOWED_ACTIONS", False);
|
||||
m_net_wm_action_move = XInternAtom(disp, "_NET_WM_ACTIONS_MOVE", False);
|
||||
m_net_wm_action_resize = XInternAtom(disp, "_NET_WM_ACTIONS_RESIZE", False);
|
||||
m_net_wm_action_minimize = XInternAtom(disp, "_NET_WM_ACTIONS_MINIMIZE", False);
|
||||
m_net_wm_action_shade = XInternAtom(disp, "_NET_WM_ACTIONS_SHADE", False);
|
||||
m_net_wm_action_stick = XInternAtom(disp, "_NET_WM_ACTIONS_STICK", False);
|
||||
m_net_wm_action_maximize_horz = XInternAtom(disp, "_NET_WM_ACTIONS_MAXIMIZE_HORZ", False);
|
||||
m_net_wm_action_maximize_vert = XInternAtom(disp, "_NET_WM_ACTIONS_MAXIMIZE_VERT", False);
|
||||
m_net_wm_action_fullscreen = XInternAtom(disp, "_NET_WM_ACTIONS_FULLSCREEN", False);
|
||||
m_net_wm_action_change_desktop = XInternAtom(disp, "_NET_WM_ACTIONS_CHANGE_DESKTOP", False);
|
||||
m_net_wm_action_close = XInternAtom(disp, "_NET_WM_ACTIONS_CLOSE", False);
|
||||
m_net_wm_action_move = XInternAtom(disp, "_NET_WM_ACTION_MOVE", False);
|
||||
m_net_wm_action_resize = XInternAtom(disp, "_NET_WM_ACTION_RESIZE", False);
|
||||
m_net_wm_action_minimize = XInternAtom(disp, "_NET_WM_ACTION_MINIMIZE", False);
|
||||
m_net_wm_action_shade = XInternAtom(disp, "_NET_WM_ACTION_SHADE", False);
|
||||
m_net_wm_action_stick = XInternAtom(disp, "_NET_WM_ACTION_STICK", False);
|
||||
m_net_wm_action_maximize_horz = XInternAtom(disp, "_NET_WM_ACTION_MAXIMIZE_HORZ", False);
|
||||
m_net_wm_action_maximize_vert = XInternAtom(disp, "_NET_WM_ACTION_MAXIMIZE_VERT", False);
|
||||
m_net_wm_action_fullscreen = XInternAtom(disp, "_NET_WM_ACTION_FULLSCREEN", False);
|
||||
m_net_wm_action_change_desktop = XInternAtom(disp, "_NET_WM_ACTION_CHANGE_DESKTOP", False);
|
||||
m_net_wm_action_close = XInternAtom(disp, "_NET_WM_ACTION_CLOSE", False);
|
||||
|
||||
m_net_wm_strut = XInternAtom(disp, "_NET_WM_STRUT", False);
|
||||
m_net_wm_icon_geometry = XInternAtom(disp, "_NET_WM_ICON_GEOMETRY", False);
|
||||
|
@ -890,7 +918,7 @@ void Ewmh::setState(FluxboxWindow &win, Atom state, bool value) {
|
|||
win.iconify();
|
||||
else if (!value && win.isIconic())
|
||||
win.deiconify();
|
||||
} else if (state == m_net_wm_state_skip_taskbar) {
|
||||
} else if (state == m_net_wm_state_skip_taskbar) { // skip taskbar
|
||||
win.setIconHidden(value);
|
||||
} else if (state == m_net_wm_state_below) { // bottom layer
|
||||
if (value)
|
||||
|
@ -904,13 +932,14 @@ void Ewmh::setState(FluxboxWindow &win, Atom state, bool value) {
|
|||
else
|
||||
win.moveToLayer(Layer::NORMAL);
|
||||
}
|
||||
// Note: state == net_wm_state_modal, We should not change it
|
||||
}
|
||||
|
||||
// toggle window state
|
||||
void Ewmh::toggleState(FluxboxWindow &win, Atom state) {
|
||||
if (state == m_net_wm_state_sticky) {
|
||||
if (state == m_net_wm_state_sticky) { // sticky
|
||||
win.stick();
|
||||
} else if (state == m_net_wm_state_shaded){
|
||||
} else if (state == m_net_wm_state_shaded){ // shaded
|
||||
win.shade();
|
||||
} else if (state == m_net_wm_state_maximized_horz ) { // maximized Horizontal
|
||||
win.maximizeHorizontal();
|
||||
|
@ -923,7 +952,7 @@ void Ewmh::toggleState(FluxboxWindow &win, Atom state) {
|
|||
win.deiconify();
|
||||
else
|
||||
win.iconify();
|
||||
} else if (state == m_net_wm_state_skip_taskbar) {
|
||||
} else if (state == m_net_wm_state_skip_taskbar) { // taskbar
|
||||
win.setIconHidden(!win.isIconHidden());
|
||||
} else if (state == m_net_wm_state_below) { // bottom layer
|
||||
if (win.layerNum() == Layer::BOTTOM)
|
||||
|
@ -958,6 +987,70 @@ void Ewmh::updateStrut(WinClient &winclient) {
|
|||
}
|
||||
}
|
||||
|
||||
void Ewmh::updateActions(FluxboxWindow &win) {
|
||||
|
||||
/* From Extended Window Manager Hints, draft 1.3:
|
||||
*
|
||||
* _NET_WM_ALLOWED_ACTIONS, ATOM[]
|
||||
*
|
||||
* A list of atoms indicating user operations that the
|
||||
* Window Manager supports for this window. Atoms present in the
|
||||
* list indicate allowed actions, atoms not present in the list
|
||||
* indicate actions that are not supported for this window. The
|
||||
* Window Manager MUST keep this property updated to reflect the
|
||||
* actions which are currently "active" or "sensitive" for a window.
|
||||
* Taskbars, Pagers, and other tools use _NET_WM_ALLOWED_ACTIONS to
|
||||
* decide which actions should be made available to the user.
|
||||
*/
|
||||
|
||||
typedef std::vector<Atom> ActionsVector;
|
||||
ActionsVector actions;
|
||||
actions.reserve(10);
|
||||
// all windows can change desktop,
|
||||
// be shaded or be sticky
|
||||
actions.push_back(m_net_wm_action_change_desktop);
|
||||
actions.push_back(m_net_wm_action_shade);
|
||||
actions.push_back(m_net_wm_action_stick);
|
||||
|
||||
if (win.isResizable())
|
||||
actions.push_back(m_net_wm_action_resize);
|
||||
if (win.isMoveable())
|
||||
actions.push_back(m_net_wm_action_move);
|
||||
if (win.isClosable())
|
||||
actions.push_back(m_net_wm_action_close);
|
||||
if (win.isIconifiable())
|
||||
actions.push_back(m_net_wm_action_minimize);
|
||||
|
||||
unsigned int max_width, max_height;
|
||||
WinClientUtil::maxSize(win.clientList(), max_width, max_height);
|
||||
|
||||
// if unlimited max width we can maximize horizontal
|
||||
if (max_width == 0) {
|
||||
actions.push_back(m_net_wm_action_maximize_horz);
|
||||
}
|
||||
// if unlimited max height we can maxmize vert
|
||||
if (max_height == 0) {
|
||||
actions.push_back(m_net_wm_action_maximize_vert);
|
||||
}
|
||||
|
||||
// if we have unlimited size in all directions we can have this window
|
||||
// in fullscreen mode
|
||||
if (max_height == 0 && max_width == 0) {
|
||||
actions.push_back(m_net_wm_action_fullscreen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
FluxboxWindow::ClientList::iterator it = win.clientList().begin();
|
||||
FluxboxWindow::ClientList::iterator it_end = win.clientList().end();
|
||||
for (; it != it_end; ++it) {
|
||||
(*it)->changeProperty(m_net_wm_allowed_actions, XA_ATOM, 32, PropModeReplace,
|
||||
reinterpret_cast<unsigned char*>(&actions.front()),
|
||||
actions.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Ewmh::setupState(FluxboxWindow &win) {
|
||||
/* From Extended Window Manager Hints, draft 1.3:
|
||||
*
|
||||
|
|
|
@ -77,6 +77,8 @@ private:
|
|||
void toggleState(FluxboxWindow &win, Atom state);
|
||||
void createAtoms();
|
||||
void updateStrut(WinClient &winclient);
|
||||
void updateActions(FluxboxWindow &win);
|
||||
|
||||
void setupState(FluxboxWindow &win);
|
||||
|
||||
// root window properties
|
||||
|
@ -94,6 +96,7 @@ private:
|
|||
m_net_wm_window_type,
|
||||
m_net_wm_window_type_dock,
|
||||
m_net_wm_window_type_desktop,
|
||||
m_net_wm_window_type_splash,
|
||||
|
||||
// states
|
||||
m_net_wm_state, m_net_wm_state_sticky, m_net_wm_state_shaded,
|
||||
|
@ -104,6 +107,7 @@ private:
|
|||
m_net_wm_state_skip_pager,
|
||||
m_net_wm_state_below,
|
||||
m_net_wm_state_above,
|
||||
m_net_wm_state_modal,
|
||||
|
||||
// allowed actions
|
||||
m_net_wm_allowed_actions,
|
||||
|
|
|
@ -135,6 +135,7 @@ fluxbox_SOURCES = AtomHandler.hh ArrowButton.hh ArrowButton.cc \
|
|||
RowSmartPlacement.hh RowSmartPlacement.cc \
|
||||
ScreenPlacement.hh ScreenPlacement.cc \
|
||||
UnderMousePlacement.hh UnderMousePlacement.cc \
|
||||
WinClientUtil.hh WinClientUtil.cc \
|
||||
${newwmspec_SOURCE} ${gnome_SOURCE} \
|
||||
${REMEMBER_SOURCE} ${TOOLBAR_SOURCE}
|
||||
|
||||
|
|
32
src/WinClientUtil.cc
Normal file
32
src/WinClientUtil.cc
Normal file
|
@ -0,0 +1,32 @@
|
|||
#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 = ~0; // unlimited
|
||||
max_height = ~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 == ~0)
|
||||
max_width = 0;
|
||||
if (max_height == ~0)
|
||||
max_height = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
19
src/WinClientUtil.hh
Normal file
19
src/WinClientUtil.hh
Normal file
|
@ -0,0 +1,19 @@
|
|||
#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
|
|
@ -302,6 +302,7 @@ public:
|
|||
inline bool isMaximizable() const { return functions.maximize; }
|
||||
inline bool isResizable() const { return functions.resize; }
|
||||
inline bool isClosable() const { return functions.close; }
|
||||
inline bool isMoveable() const { return functions.move; }
|
||||
inline bool isStuck() const { return stuck; }
|
||||
inline bool hasTitlebar() const { return decorations.titlebar; }
|
||||
inline bool isMoving() const { return moving; }
|
||||
|
|
Loading…
Reference in a new issue