fix a problem with enabling/disabling fullscreen-mode in gtk2-apps
* synchronize _NET_WM_STATE in Ewmh.cc * added FluxboxWindow::setFullscreen(bool) to Window.cc furthermore, if a window is in fullscreenmode any existing shape is disabled (looks pretty annoying in mplayer for example)
This commit is contained in:
parent
a88d3b39ad
commit
ad10a3543e
4 changed files with 196 additions and 49 deletions
95
src/Ewmh.cc
95
src/Ewmh.cc
|
@ -60,10 +60,28 @@ Ewmh::~Ewmh() {
|
|||
void Ewmh::initForScreen(BScreen &screen) {
|
||||
Display *disp = FbTk::App::instance()->display();
|
||||
|
||||
/* From Extended Window Manager Hints, draft 1.3:
|
||||
*
|
||||
* _NET_SUPPORTING_WM_CHECK
|
||||
*
|
||||
* The Window Manager MUST set this property on the root window
|
||||
* to be the ID of a child window created by himself, to indicate
|
||||
* that a compliant window manager is active. The child window
|
||||
* MUST also have the _NET_SUPPORTING_WM_CHECK property set to
|
||||
* the ID of the child window. The child window MUST also have
|
||||
* the _NET_WM_NAME property set to the name of the Window Manager.
|
||||
*
|
||||
* Rationale: The child window is used to distinguish an active
|
||||
* Window Manager from a stale _NET_SUPPORTING_WM_CHECK property
|
||||
* that happens to point to another window. If the
|
||||
* _NET_SUPPORTING_WM_CHECK window on the client window is missing
|
||||
* or not properly set, clients SHOULD assume that no conforming
|
||||
* Window Manager is present.
|
||||
*/
|
||||
|
||||
Window wincheck = XCreateSimpleWindow(disp,
|
||||
screen.rootWindow().window(),
|
||||
0, 0, 5, 5, 0, 0, 0);
|
||||
-10, -10, 5, 5, 0, 0, 0);
|
||||
|
||||
if (wincheck != None) {
|
||||
// store the window so we can delete it later
|
||||
|
@ -170,6 +188,7 @@ void Ewmh::setupFrame(FluxboxWindow &win) {
|
|||
* Managers that do not recognize the extensions.
|
||||
*
|
||||
*/
|
||||
|
||||
win.winClient().property(m_net_wm_window_type, 0, 0x7fffffff, False, XA_ATOM,
|
||||
&ret_type, &fmt, &nitems, &bytes_after,
|
||||
&data);
|
||||
|
@ -501,7 +520,39 @@ void Ewmh::updateWorkarea(BScreen &screen) {
|
|||
}
|
||||
|
||||
void Ewmh::updateState(FluxboxWindow &win) {
|
||||
//!! TODO
|
||||
|
||||
// TODO: should we update the _NET_WM_ALLOWED_ACTIONS
|
||||
// here too?
|
||||
|
||||
std::vector<unsigned int> state;
|
||||
|
||||
if (win.isStuck())
|
||||
state.push_back(m_net_wm_state_sticky);
|
||||
if (win.isShaded())
|
||||
state.push_back(m_net_wm_state_shaded);
|
||||
if (win.layerNum() == Fluxbox::instance()->getBottomLayer())
|
||||
state.push_back(m_net_wm_state_below);
|
||||
if (win.layerNum() == Fluxbox::instance()->getAboveDockLayer())
|
||||
state.push_back(m_net_wm_state_above);
|
||||
if (win.isFocusHidden()) {
|
||||
state.push_back(m_net_wm_state_hidden);
|
||||
state.push_back(m_net_wm_state_skip_taskbar);
|
||||
}
|
||||
if (win.isFullscreen()) {
|
||||
state.push_back(m_net_wm_state_fullscreen);
|
||||
}
|
||||
|
||||
FluxboxWindow::ClientList::iterator it = win.clientList().begin();
|
||||
FluxboxWindow::ClientList::iterator it_end = win.clientList().end();
|
||||
|
||||
it = win.clientList().begin();
|
||||
for (; it != it_end; ++it) {
|
||||
if (!state.empty())
|
||||
(*it)->changeProperty(m_net_wm_state, XA_ATOM, 32, PropModeReplace,
|
||||
reinterpret_cast<unsigned char*>(&state.front()), state.size());
|
||||
else
|
||||
(*it)->deleteProperty(m_net_wm_state);
|
||||
}
|
||||
}
|
||||
|
||||
void Ewmh::updateLayer(FluxboxWindow &win) {
|
||||
|
@ -537,6 +588,7 @@ void Ewmh::updateWorkspace(FluxboxWindow &win) {
|
|||
// return true if we did handle the atom here
|
||||
bool Ewmh::checkClientMessage(const XClientMessageEvent &ce,
|
||||
BScreen * screen, WinClient * const winclient) {
|
||||
|
||||
if (ce.message_type == m_net_wm_desktop) {
|
||||
// ce.data.l[0] = workspace number
|
||||
// valid window
|
||||
|
@ -581,7 +633,6 @@ bool Ewmh::checkClientMessage(const XClientMessageEvent &ce,
|
|||
toggleState(win, ce.data.l[1]);
|
||||
toggleState(win, ce.data.l[2]);
|
||||
}
|
||||
|
||||
return true;
|
||||
} else if (ce.message_type == m_net_number_of_desktops) {
|
||||
if (screen == 0)
|
||||
|
@ -725,6 +776,18 @@ void Ewmh::createAtoms() {
|
|||
m_net_wm_state_above = XInternAtom(disp, "_NET_WM_STATE_ABOVE", False);
|
||||
m_net_wm_state_below = XInternAtom(disp, "_NET_WM_STATE_BELOW", 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_strut = XInternAtom(disp, "_NET_WM_STRUT", False);
|
||||
m_net_wm_icon_geometry = XInternAtom(disp, "_NET_WM_ICON_GEOMETRY", False);
|
||||
|
@ -739,6 +802,12 @@ void Ewmh::createAtoms() {
|
|||
void Ewmh::setFullscreen(FluxboxWindow &win, bool value) {
|
||||
// fullscreen implies maximised, above dock layer,
|
||||
// and no decorations (or decorations offscreen)
|
||||
//
|
||||
// TODO: do we need the WindowState etc here anymore?
|
||||
// FluxboxWindow::setFullscreen() remembering old values
|
||||
// already and set them...
|
||||
// only reason i can see is that the user manually
|
||||
// moved the (fullscreened) window
|
||||
WindowState *saved_state = getState(win);
|
||||
if (value) {
|
||||
// fullscreen on
|
||||
|
@ -746,25 +815,17 @@ void Ewmh::setFullscreen(FluxboxWindow &win, bool value) {
|
|||
saved_state = new WindowState(win.x(), win.y(), win.width(),
|
||||
win.height(), win.layerNum(), win.decorationMask());
|
||||
saveState(win, saved_state);
|
||||
|
||||
// actually make it fullscreen
|
||||
|
||||
// clear decorations
|
||||
win.setDecorationMask(0);
|
||||
|
||||
// be xinerama aware
|
||||
BScreen &screen = win.screen();
|
||||
int head = screen.getHead(win.fbWindow());
|
||||
win.moveResize(screen.getHeadX(head), screen.getHeadY(head),
|
||||
screen.getHeadWidth(head), screen.getHeadHeight(head));
|
||||
win.moveToLayer(Fluxbox::instance()->getAboveDockLayer());
|
||||
win.setFullscreen(true);
|
||||
}
|
||||
} else { // turn off fullscreen
|
||||
if (saved_state) { // no saved state, can't restore it
|
||||
win.setFullscreen(false);
|
||||
/*
|
||||
win.setDecorationMask(saved_state->decor);
|
||||
win.moveResize(saved_state->x, saved_state->y,
|
||||
saved_state->width, saved_state->height);
|
||||
win.moveToLayer(saved_state->layer);
|
||||
*/
|
||||
clearState(win);
|
||||
saved_state = 0;
|
||||
}
|
||||
|
@ -791,11 +852,13 @@ void Ewmh::setState(FluxboxWindow &win, Atom state, bool value) {
|
|||
(!value && win.isMaximized()))
|
||||
win.maximizeVertical();
|
||||
} else if (state == m_net_wm_state_fullscreen) { // fullscreen
|
||||
if ((value && !win.isFullscreen()) ||
|
||||
(!value && win.isFullscreen()))
|
||||
setFullscreen(win, value);
|
||||
} else if (state == m_net_wm_state_hidden ||
|
||||
state == m_net_wm_state_skip_taskbar) {
|
||||
win.setFocusHidden(value);
|
||||
win.setIconHidden(win.isFocusHidden());
|
||||
win.setIconHidden(value);
|
||||
} else if (state == m_net_wm_state_below) { // bottom layer
|
||||
if (value)
|
||||
win.moveToLayer(Fluxbox::instance()->getBottomLayer());
|
||||
|
|
15
src/Ewmh.hh
15
src/Ewmh.hh
|
@ -65,7 +65,8 @@ public:
|
|||
private:
|
||||
|
||||
typedef struct WindowState {
|
||||
WindowState(int x, int y, unsigned int width, unsigned int height, int layer, unsigned int decor);
|
||||
WindowState(int x, int y, unsigned int width, unsigned int height,
|
||||
int layer, unsigned int decor);
|
||||
int x, y, layer;
|
||||
unsigned int width, height, decor;
|
||||
} WindowState;
|
||||
|
@ -103,6 +104,18 @@ private:
|
|||
m_net_wm_state_below,
|
||||
m_net_wm_state_above,
|
||||
|
||||
// allowed 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,
|
||||
|
||||
m_net_wm_strut, m_net_wm_icon_geometry, m_net_wm_icon, m_net_wm_pid,
|
||||
m_net_wm_handled_icons;
|
||||
|
||||
|
|
|
@ -280,7 +280,7 @@ FluxboxWindow::FluxboxWindow(WinClient &client, FbWinFrameTheme &tm,
|
|||
m_themelistener(*this),
|
||||
moving(false), resizing(false), shaded(false),
|
||||
iconic(false), focused(false),
|
||||
stuck(false), m_managed(false),
|
||||
stuck(false), m_managed(false), fullscreen(false),
|
||||
maximized(MAX_NONE),
|
||||
m_attaching_tab(0),
|
||||
m_screen(client.screen()),
|
||||
|
@ -292,6 +292,7 @@ FluxboxWindow::FluxboxWindow(WinClient &client, FbWinFrameTheme &tm,
|
|||
m_workspace_number(0),
|
||||
m_current_state(0),
|
||||
m_old_decoration(DECOR_NORMAL),
|
||||
m_old_decoration_mask(0),
|
||||
m_client(&client),
|
||||
m_toggled_decos(false),
|
||||
m_shaped(false),
|
||||
|
@ -302,6 +303,7 @@ FluxboxWindow::FluxboxWindow(WinClient &client, FbWinFrameTheme &tm,
|
|||
m_frame(tm, client.screen().imageControl(), 0, 0, 100, 100),
|
||||
m_layeritem(m_frame.window(), layer),
|
||||
m_layernum(layer.getLayerNum()),
|
||||
m_old_layernum(0),
|
||||
m_parent(client.screen().rootWindow()),
|
||||
m_resize_corner(RIGHTBOTTOM) {
|
||||
|
||||
|
@ -603,6 +605,7 @@ void FluxboxWindow::init() {
|
|||
void FluxboxWindow::shape() {
|
||||
#ifdef SHAPE
|
||||
if (m_shaped) {
|
||||
if (isFullscreen())
|
||||
XShapeCombineShape(display,
|
||||
frame().window().window(), ShapeBounding,
|
||||
0, frame().clientArea().y(), // xOff, yOff
|
||||
|
@ -1579,10 +1582,70 @@ void FluxboxWindow::withdraw(bool interrupt_moving) {
|
|||
hide(interrupt_moving);
|
||||
}
|
||||
|
||||
/** setFullscreen mode:
|
||||
|
||||
- maximize as big as the screen is, dont care about slit / toolbar
|
||||
- raise to toplayer
|
||||
*/
|
||||
void FluxboxWindow::setFullscreen(bool flag) {
|
||||
|
||||
const int head = screen().getHead(fbWindow());
|
||||
Fluxbox* fb = Fluxbox::instance();
|
||||
|
||||
if (flag && !isFullscreen()) {
|
||||
|
||||
if (isIconic())
|
||||
deiconify();
|
||||
|
||||
if (isShaded())
|
||||
shade();
|
||||
|
||||
frame().setUseShape(false);
|
||||
|
||||
m_old_decoration_mask = decorationMask();
|
||||
m_old_layernum =layerNum();
|
||||
m_old_pos_x = frame().x();
|
||||
m_old_pos_y = frame().y();
|
||||
m_old_width = frame().width();
|
||||
m_old_height = frame().height();
|
||||
|
||||
// clear decorations
|
||||
setDecorationMask(0);
|
||||
|
||||
// be xinerama aware
|
||||
moveResize(screen().getHeadX(head), screen().getHeadY(head),
|
||||
screen().getHeadWidth(head), screen().getHeadHeight(head));
|
||||
moveToLayer(Fluxbox::instance()->getAboveDockLayer());
|
||||
|
||||
fullscreen = true;
|
||||
|
||||
stateSig().notify();
|
||||
|
||||
} else if (!flag && isFullscreen()) {
|
||||
|
||||
fullscreen = false;
|
||||
|
||||
setDecorationMask(m_old_decoration_mask);
|
||||
frame().setUseShape(!m_shaped);
|
||||
|
||||
moveResize(m_old_pos_x, m_old_pos_y, m_old_width, m_old_height);
|
||||
moveToLayer(m_old_layernum);
|
||||
|
||||
m_old_decoration_mask = 0;
|
||||
m_old_layernum = Fluxbox::instance()->getNormalLayer();
|
||||
|
||||
stateSig().notify();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Maximize window both horizontal and vertical
|
||||
*/
|
||||
void FluxboxWindow::maximize(int type) {
|
||||
|
||||
if (isFullscreen())
|
||||
return;
|
||||
|
||||
if (isIconic())
|
||||
deiconify();
|
||||
|
||||
|
|
|
@ -199,6 +199,8 @@ public:
|
|||
void kill();
|
||||
/// set the window in withdrawn state
|
||||
void withdraw(bool interrupt_moving);
|
||||
/// set fullscreen
|
||||
void setFullscreen(bool flag);
|
||||
/// toggle maximize
|
||||
void maximize(int type = MAX_FULL);
|
||||
/// maximizes the window horizontal
|
||||
|
@ -272,6 +274,9 @@ public:
|
|||
@name accessors
|
||||
*/
|
||||
//@{
|
||||
|
||||
// @return NormalState | IconicState | WithdrawnState
|
||||
unsigned int getWmState() const { return m_current_state; }
|
||||
// whether this window can be tabbed with other windows,
|
||||
// and others tabbed with it
|
||||
inline void setTabable(bool tabable) { functions.tabable = tabable; }
|
||||
|
@ -286,6 +291,7 @@ public:
|
|||
bool isVisible() const;
|
||||
inline bool isIconic() const { return iconic; }
|
||||
inline bool isShaded() const { return shaded; }
|
||||
inline bool isFullscreen() const { return fullscreen; }
|
||||
inline bool isMaximized() const { return maximized == MAX_FULL; }
|
||||
inline bool isIconifiable() const { return functions.iconify; }
|
||||
inline bool isMaximizable() const { return functions.maximize; }
|
||||
|
@ -453,7 +459,7 @@ private:
|
|||
|
||||
// Window states
|
||||
bool moving, resizing, shaded, iconic,
|
||||
focused, stuck, m_managed;
|
||||
focused, stuck, m_managed, fullscreen;
|
||||
|
||||
int maximized;
|
||||
|
||||
|
@ -474,9 +480,10 @@ private:
|
|||
unsigned int m_last_resize_h, m_last_resize_w; // handles height/width for resize "window"
|
||||
|
||||
unsigned int m_workspace_number;
|
||||
unsigned long m_current_state;
|
||||
unsigned long m_current_state; // NormalState | IconicState | Withdrawn
|
||||
|
||||
Decoration m_old_decoration;
|
||||
unsigned int m_old_decoration_mask;
|
||||
|
||||
ClientList m_clientlist;
|
||||
WinClient *m_client; ///< current client
|
||||
|
@ -507,6 +514,7 @@ private:
|
|||
|
||||
FbTk::XLayerItem m_layeritem;
|
||||
int m_layernum;
|
||||
int m_old_layernum;
|
||||
|
||||
FbTk::FbWindow &m_parent; ///< window on which we draw move/resize rectangle (the "root window")
|
||||
|
||||
|
|
Loading…
Reference in a new issue