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:
mathias 2004-12-21 16:17:14 +00:00
parent a88d3b39ad
commit ad10a3543e
4 changed files with 196 additions and 49 deletions

View file

@ -60,10 +60,28 @@ Ewmh::~Ewmh() {
void Ewmh::initForScreen(BScreen &screen) { void Ewmh::initForScreen(BScreen &screen) {
Display *disp = FbTk::App::instance()->display(); 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, Window wincheck = XCreateSimpleWindow(disp,
screen.rootWindow().window(), screen.rootWindow().window(),
0, 0, 5, 5, 0, 0, 0); -10, -10, 5, 5, 0, 0, 0);
if (wincheck != None) { if (wincheck != None) {
// store the window so we can delete it later // 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. * Managers that do not recognize the extensions.
* *
*/ */
win.winClient().property(m_net_wm_window_type, 0, 0x7fffffff, False, XA_ATOM, win.winClient().property(m_net_wm_window_type, 0, 0x7fffffff, False, XA_ATOM,
&ret_type, &fmt, &nitems, &bytes_after, &ret_type, &fmt, &nitems, &bytes_after,
&data); &data);
@ -501,7 +520,39 @@ void Ewmh::updateWorkarea(BScreen &screen) {
} }
void Ewmh::updateState(FluxboxWindow &win) { 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) { void Ewmh::updateLayer(FluxboxWindow &win) {
@ -537,6 +588,7 @@ void Ewmh::updateWorkspace(FluxboxWindow &win) {
// return true if we did handle the atom here // return true if we did handle the atom here
bool Ewmh::checkClientMessage(const XClientMessageEvent &ce, bool Ewmh::checkClientMessage(const XClientMessageEvent &ce,
BScreen * screen, WinClient * const winclient) { BScreen * screen, WinClient * const winclient) {
if (ce.message_type == m_net_wm_desktop) { if (ce.message_type == m_net_wm_desktop) {
// ce.data.l[0] = workspace number // ce.data.l[0] = workspace number
// valid window // valid window
@ -581,7 +633,6 @@ bool Ewmh::checkClientMessage(const XClientMessageEvent &ce,
toggleState(win, ce.data.l[1]); toggleState(win, ce.data.l[1]);
toggleState(win, ce.data.l[2]); toggleState(win, ce.data.l[2]);
} }
return true; return true;
} else if (ce.message_type == m_net_number_of_desktops) { } else if (ce.message_type == m_net_number_of_desktops) {
if (screen == 0) 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_above = XInternAtom(disp, "_NET_WM_STATE_ABOVE", False);
m_net_wm_state_below = XInternAtom(disp, "_NET_WM_STATE_BELOW", 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_strut = XInternAtom(disp, "_NET_WM_STRUT", False);
m_net_wm_icon_geometry = XInternAtom(disp, "_NET_WM_ICON_GEOMETRY", 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) { void Ewmh::setFullscreen(FluxboxWindow &win, bool value) {
// fullscreen implies maximised, above dock layer, // fullscreen implies maximised, above dock layer,
// and no decorations (or decorations offscreen) // 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); WindowState *saved_state = getState(win);
if (value) { if (value) {
// fullscreen on // fullscreen on
@ -746,25 +815,17 @@ void Ewmh::setFullscreen(FluxboxWindow &win, bool value) {
saved_state = new WindowState(win.x(), win.y(), win.width(), saved_state = new WindowState(win.x(), win.y(), win.width(),
win.height(), win.layerNum(), win.decorationMask()); win.height(), win.layerNum(), win.decorationMask());
saveState(win, saved_state); saveState(win, saved_state);
win.setFullscreen(true);
// 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());
} }
} else { // turn off fullscreen } else { // turn off fullscreen
if (saved_state) { // no saved state, can't restore it if (saved_state) { // no saved state, can't restore it
win.setFullscreen(false);
/*
win.setDecorationMask(saved_state->decor); win.setDecorationMask(saved_state->decor);
win.moveResize(saved_state->x, saved_state->y, win.moveResize(saved_state->x, saved_state->y,
saved_state->width, saved_state->height); saved_state->width, saved_state->height);
win.moveToLayer(saved_state->layer); win.moveToLayer(saved_state->layer);
*/
clearState(win); clearState(win);
saved_state = 0; saved_state = 0;
} }
@ -791,11 +852,13 @@ void Ewmh::setState(FluxboxWindow &win, Atom state, bool value) {
(!value && win.isMaximized())) (!value && win.isMaximized()))
win.maximizeVertical(); win.maximizeVertical();
} else if (state == m_net_wm_state_fullscreen) { // fullscreen } else if (state == m_net_wm_state_fullscreen) { // fullscreen
if ((value && !win.isFullscreen()) ||
(!value && win.isFullscreen()))
setFullscreen(win, value); setFullscreen(win, value);
} else if (state == m_net_wm_state_hidden || } else if (state == m_net_wm_state_hidden ||
state == m_net_wm_state_skip_taskbar) { state == m_net_wm_state_skip_taskbar) {
win.setFocusHidden(value); win.setFocusHidden(value);
win.setIconHidden(win.isFocusHidden()); win.setIconHidden(value);
} else if (state == m_net_wm_state_below) { // bottom layer } else if (state == m_net_wm_state_below) { // bottom layer
if (value) if (value)
win.moveToLayer(Fluxbox::instance()->getBottomLayer()); win.moveToLayer(Fluxbox::instance()->getBottomLayer());

View file

@ -65,7 +65,8 @@ public:
private: private:
typedef struct WindowState { 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; int x, y, layer;
unsigned int width, height, decor; unsigned int width, height, decor;
} WindowState; } WindowState;
@ -103,6 +104,18 @@ private:
m_net_wm_state_below, m_net_wm_state_below,
m_net_wm_state_above, 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_strut, m_net_wm_icon_geometry, m_net_wm_icon, m_net_wm_pid,
m_net_wm_handled_icons; m_net_wm_handled_icons;

View file

@ -280,7 +280,7 @@ FluxboxWindow::FluxboxWindow(WinClient &client, FbWinFrameTheme &tm,
m_themelistener(*this), m_themelistener(*this),
moving(false), resizing(false), shaded(false), moving(false), resizing(false), shaded(false),
iconic(false), focused(false), iconic(false), focused(false),
stuck(false), m_managed(false), stuck(false), m_managed(false), fullscreen(false),
maximized(MAX_NONE), maximized(MAX_NONE),
m_attaching_tab(0), m_attaching_tab(0),
m_screen(client.screen()), m_screen(client.screen()),
@ -292,6 +292,7 @@ FluxboxWindow::FluxboxWindow(WinClient &client, FbWinFrameTheme &tm,
m_workspace_number(0), m_workspace_number(0),
m_current_state(0), m_current_state(0),
m_old_decoration(DECOR_NORMAL), m_old_decoration(DECOR_NORMAL),
m_old_decoration_mask(0),
m_client(&client), m_client(&client),
m_toggled_decos(false), m_toggled_decos(false),
m_shaped(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_frame(tm, client.screen().imageControl(), 0, 0, 100, 100),
m_layeritem(m_frame.window(), layer), m_layeritem(m_frame.window(), layer),
m_layernum(layer.getLayerNum()), m_layernum(layer.getLayerNum()),
m_old_layernum(0),
m_parent(client.screen().rootWindow()), m_parent(client.screen().rootWindow()),
m_resize_corner(RIGHTBOTTOM) { m_resize_corner(RIGHTBOTTOM) {
@ -603,6 +605,7 @@ void FluxboxWindow::init() {
void FluxboxWindow::shape() { void FluxboxWindow::shape() {
#ifdef SHAPE #ifdef SHAPE
if (m_shaped) { if (m_shaped) {
if (isFullscreen())
XShapeCombineShape(display, XShapeCombineShape(display,
frame().window().window(), ShapeBounding, frame().window().window(), ShapeBounding,
0, frame().clientArea().y(), // xOff, yOff 0, frame().clientArea().y(), // xOff, yOff
@ -1579,10 +1582,70 @@ void FluxboxWindow::withdraw(bool interrupt_moving) {
hide(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 Maximize window both horizontal and vertical
*/ */
void FluxboxWindow::maximize(int type) { void FluxboxWindow::maximize(int type) {
if (isFullscreen())
return;
if (isIconic()) if (isIconic())
deiconify(); deiconify();

View file

@ -199,6 +199,8 @@ public:
void kill(); void kill();
/// set the window in withdrawn state /// set the window in withdrawn state
void withdraw(bool interrupt_moving); void withdraw(bool interrupt_moving);
/// set fullscreen
void setFullscreen(bool flag);
/// toggle maximize /// toggle maximize
void maximize(int type = MAX_FULL); void maximize(int type = MAX_FULL);
/// maximizes the window horizontal /// maximizes the window horizontal
@ -272,6 +274,9 @@ public:
@name accessors @name accessors
*/ */
//@{ //@{
// @return NormalState | IconicState | WithdrawnState
unsigned int getWmState() const { return m_current_state; }
// whether this window can be tabbed with other windows, // whether this window can be tabbed with other windows,
// and others tabbed with it // and others tabbed with it
inline void setTabable(bool tabable) { functions.tabable = tabable; } inline void setTabable(bool tabable) { functions.tabable = tabable; }
@ -286,6 +291,7 @@ public:
bool isVisible() const; bool isVisible() const;
inline bool isIconic() const { return iconic; } inline bool isIconic() const { return iconic; }
inline bool isShaded() const { return shaded; } inline bool isShaded() const { return shaded; }
inline bool isFullscreen() const { return fullscreen; }
inline bool isMaximized() const { return maximized == MAX_FULL; } inline bool isMaximized() const { return maximized == MAX_FULL; }
inline bool isIconifiable() const { return functions.iconify; } inline bool isIconifiable() const { return functions.iconify; }
inline bool isMaximizable() const { return functions.maximize; } inline bool isMaximizable() const { return functions.maximize; }
@ -453,7 +459,7 @@ private:
// Window states // Window states
bool moving, resizing, shaded, iconic, bool moving, resizing, shaded, iconic,
focused, stuck, m_managed; focused, stuck, m_managed, fullscreen;
int maximized; 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_last_resize_h, m_last_resize_w; // handles height/width for resize "window"
unsigned int m_workspace_number; unsigned int m_workspace_number;
unsigned long m_current_state; unsigned long m_current_state; // NormalState | IconicState | Withdrawn
Decoration m_old_decoration; Decoration m_old_decoration;
unsigned int m_old_decoration_mask;
ClientList m_clientlist; ClientList m_clientlist;
WinClient *m_client; ///< current client WinClient *m_client; ///< current client
@ -507,6 +514,7 @@ private:
FbTk::XLayerItem m_layeritem; FbTk::XLayerItem m_layeritem;
int m_layernum; int m_layernum;
int m_old_layernum;
FbTk::FbWindow &m_parent; ///< window on which we draw move/resize rectangle (the "root window") FbTk::FbWindow &m_parent; ///< window on which we draw move/resize rectangle (the "root window")