all repos — fluxbox @ ad10a3543e278aea0dd8e1fb83fa79b93025d14b

custom fork of the fluxbox windowmanager

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)
mathias mathias
commit

ad10a3543e278aea0dd8e1fb83fa79b93025d14b

parent

a88d3b39ad76182bf120b8c69b80104f7b61cba8

4 files changed, 196 insertions(+), 49 deletions(-)

jump to
M src/Ewmh.ccsrc/Ewmh.cc

@@ -60,10 +60,28 @@

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

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 @@ m_net_wm_state,

// 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 @@ * the list of types whilst providing default behavior for Window

* 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 @@ delete[] coords;

} 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 @@

// 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 @@ } else if (ce.data.l[0] == STATE_TOGGLE) {

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)

@@ -676,7 +727,7 @@ cerr<<"_NET_WM_STRUT"<<endl;

#endif // DEBUG updateStrut(winclient); return true; - } + } return false; }

@@ -725,6 +776,18 @@ m_net_wm_state_skip_taskbar = XInternAtom(disp, "_NET_WM_STATE_SKIP_TASKBAR", 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); + // 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::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 @@ if (!saved_state) { // not already fullscreen

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 @@ if ((value && !win.isMaximized()) ||

(!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());
M src/Ewmh.hhsrc/Ewmh.hh

@@ -36,7 +36,7 @@ ~Ewmh();

void initForScreen(BScreen &screen); void setupFrame(FluxboxWindow &win); void setupClient(WinClient &winclient); - + void updateFocusedWindow(BScreen &screen, Window win); void updateClientList(BScreen &screen); void updateWorkspaceNames(BScreen &screen);

@@ -51,7 +51,7 @@ void updateLayer(FluxboxWindow &win);

void updateHints(FluxboxWindow &win); void updateWorkspace(FluxboxWindow &win); - bool checkClientMessage(const XClientMessageEvent &ce, + bool checkClientMessage(const XClientMessageEvent &ce, BScreen * screen, WinClient * const winclient); bool propertyNotify(WinClient &winclient, Atom the_property);

@@ -63,9 +63,10 @@

void setFullscreen(FluxboxWindow &win, bool value); 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;

@@ -88,7 +89,7 @@ // root window messages

Atom m_net_close_window, m_net_wm_moveresize; // application window properties - Atom m_net_properties, m_net_wm_name, m_net_wm_desktop, + Atom m_net_properties, m_net_wm_name, m_net_wm_desktop, // types m_net_wm_window_type, m_net_wm_window_type_dock,

@@ -96,16 +97,28 @@ m_net_wm_window_type_desktop,

// 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; - + // application protocols Atom m_net_wm_ping;
M src/Window.ccsrc/Window.cc

@@ -280,7 +280,7 @@ m_titlesig(*this),

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 @@ m_last_resize_h(1), m_last_resize_w(1),

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 @@ m_last_button_x(0), m_last_button_y(0),

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 @@ /// apply shape to this window

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

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();
M src/Window.hhsrc/Window.hh

@@ -71,12 +71,12 @@ enum {

MwmHintsFunctions = (1l << 0), ///< use motif wm functions MwmHintsDecorations = (1l << 1) ///< use motif wm decorations }; - + /// Motif wm functions enum MwmFunc{ MwmFuncAll = (1l << 0), ///< all motif wm functions - MwmFuncResize = (1l << 1), ///< resize - MwmFuncMove = (1l << 2), ///< move + MwmFuncResize = (1l << 1), ///< resize + MwmFuncMove = (1l << 2), ///< move MwmFuncIconify = (1l << 3), ///< iconify MwmFuncMaximize = (1l << 4), ///< maximize MwmFuncClose = (1l << 5) ///< close

@@ -100,10 +100,10 @@ ATTRIB_MAXHORIZ = 0x02,

ATTRIB_MAXVERT = 0x04, ATTRIB_OMNIPRESENT = 0x08, ATTRIB_WORKSPACE = 0x10, - ATTRIB_STACK = 0x20, + ATTRIB_STACK = 0x20, ATTRIB_DECORATION = 0x40, ATTRIB_HIDDEN = 0x80, - }; + }; /** * Types of maximization

@@ -114,8 +114,8 @@ MAX_HORZ = 1, ///< maximize horizontal

MAX_VERT = 2, ///< maximize vertical MAX_FULL = 3 ///< maximize full }; - /** - This enumeration represents individual decoration + /** + This enumeration represents individual decoration attributes, they can be OR-d together to get a mask. Useful for saving. */

@@ -165,7 +165,7 @@ virtual ~FluxboxWindow();

/// attach client to our client list and remove it from old window void attachClient(WinClient &client, int x=-1, int y=-1); - /// detach client (remove it from list) and create a new window for it + /// detach client (remove it from list) and create a new window for it bool detachClient(WinClient &client); /// detach current working client if we have more than one void detachCurrentClient();

@@ -199,6 +199,8 @@ /// kill current client

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

@@ -210,7 +212,7 @@ void maximizeFull();

/// toggles shade void shade(); /// toggles sticky - void stick(); + void stick(); void raise(); void lower(); void tempRaise();

@@ -269,10 +271,13 @@ unsigned int decorationMask() const;

void setDecorationMask(unsigned int mask); /** - @name accessors + @name accessors */ //@{ - // whether this window can be tabbed with other windows, + + // @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; } inline bool isTabable() { return functions.tabable; }

@@ -280,12 +285,13 @@ inline void setMovable(bool movable) { functions.move = movable; }

inline void setResizable(bool resizable) { functions.resize = resizable; } inline bool isFocusHidden() const { return (m_blackbox_attrib.flags & ATTRIB_HIDDEN); } - inline bool isIconHidden() const { return m_icon_hidden; } + inline bool isIconHidden() const { return m_icon_hidden; } inline bool isManaged() const { return m_managed; } inline bool isFocused() const { return focused; } 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; }

@@ -318,8 +324,8 @@ FbTk::Menu &menu() { return *m_windowmenu.get(); }

const FbTk::Menu &menu() const { return *m_windowmenu.get(); } - // for extras to add menus. - // These menus will be marked internal, + // for extras to add menus. + // These menus will be marked internal, // and deleted when the window dies (as opposed to Screen void addExtraMenu(const char *label, FbTk::Menu *menu); void removeExtraMenu(FbTk::Menu *menu);

@@ -341,7 +347,7 @@ unsigned int workspaceNumber() const { return m_workspace_number; }

int layerNum() const { return m_layernum; } void setLayerNum(int layernum); - + unsigned int titlebarHeight() const;

@@ -453,7 +459,7 @@ ThemeListener m_themelistener;

// Window states bool moving, resizing, shaded, iconic, - focused, stuck, m_managed; + focused, stuck, m_managed, fullscreen; int maximized;

@@ -474,9 +480,10 @@ 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" 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

@@ -491,14 +498,14 @@ bool titlebar, handle, border, iconify,

maximize, close, menu, sticky, shade, tab, enabled; } decorations; - bool m_toggled_decos; + bool m_toggled_decos; struct _functions { bool resize, move, iconify, maximize, close, tabable; } functions; bool m_shaped; ///< if the window is shaped with a mask - bool m_icon_hidden; ///< if the window is in the iconbar + bool m_icon_hidden; ///< if the window is in the iconbar int m_old_pos_x, m_old_pos_y; ///< old position so we can restore from maximized 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

@@ -507,6 +514,7 @@ FbWinFrame m_frame;

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