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) {
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
@ -72,10 +90,10 @@ void Ewmh::initForScreen(BScreen &screen) {
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,
PropModeReplace, (unsigned char *) &wincheck, 1);
PropModeReplace, (unsigned char *) &wincheck, 1);
XChangeProperty(disp, wincheck, m_net_wm_name, XA_STRING, 8,
PropModeReplace, (unsigned char *) "Fluxbox", strlen("Fluxbox"));
PropModeReplace, (unsigned char *) "Fluxbox", strlen("Fluxbox"));
}
//set supported atoms
@ -86,9 +104,9 @@ void Ewmh::initForScreen(BScreen &screen) {
// states that we support:
m_net_wm_state_sticky,
m_net_wm_state_shaded,
m_net_wm_state_maximized_horz,
m_net_wm_state_maximized_vert,
m_net_wm_state_fullscreen,
m_net_wm_state_maximized_horz,
m_net_wm_state_maximized_vert,
m_net_wm_state_fullscreen,
m_net_wm_state_hidden,
m_net_wm_state_skip_taskbar,
@ -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());

View file

@ -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;
@ -96,13 +97,25 @@ private:
// states
m_net_wm_state, m_net_wm_state_sticky, m_net_wm_state_shaded,
m_net_wm_state_maximized_horz, m_net_wm_state_maximized_vert,
m_net_wm_state_maximized_horz, m_net_wm_state_maximized_vert,
m_net_wm_state_fullscreen,
m_net_wm_state_hidden,
m_net_wm_state_skip_taskbar,
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;

View file

@ -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();

View file

@ -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")