kranewm

An ICCCM & EWMH compliant X11 reparenting, dynamic window manager, written in C++
git clone git clone git://git.deurzen.net/kranewm.git
Log | Files | Refs | LICENSE

commit 8a0056464b8cf801a46a046a6e58c7f85ed624e1
parent c6f2664843a68bde1367e5b6a3b45aafaf32cd21
Author: deurzen <m.deurzen@tum.de>
Date:   Wed,  4 Aug 2021 12:35:17 +0200

fixes unmanaged window mapping bug

Diffstat:
Msrc/core/client.cc | 2--
Msrc/core/client.hh | 2--
Msrc/core/model.cc | 44++++++++++++++++++++++++--------------------
Msrc/core/model.hh | 2+-
Msrc/winsys/connection.hh | 13++++++-------
Msrc/winsys/screen.cc | 16++++++----------
Msrc/winsys/xdata/xconnection.cc | 60+++++++++---------------------------------------------------
Msrc/winsys/xdata/xconnection.hh | 6++----
8 files changed, 48 insertions(+), 97 deletions(-)

diff --git a/src/core/client.cc b/src/core/client.cc @@ -10,7 +10,6 @@ Client::Client( Index partition, Index context, Index workspace, - winsys::WindowType window_type, std::optional<winsys::Pid> pid, std::optional<winsys::Pid> ppid ) @@ -22,7 +21,6 @@ Client::Client( partition(partition), context(context), workspace(workspace), - window_type(window_type), free_region({}), tile_region({}), active_region({}), diff --git a/src/core/client.hh b/src/core/client.hh @@ -46,7 +46,6 @@ typedef struct Client final Index partition, Index context, Index workspace, - winsys::WindowType window_type, std::optional<winsys::Pid> pid, std::optional<winsys::Pid> ppid ); @@ -87,7 +86,6 @@ typedef struct Client final Index partition; Index context; Index workspace; - winsys::WindowType window_type; winsys::Region free_region; winsys::Region tile_region; winsys::Region active_region; diff --git a/src/core/model.cc b/src/core/model.cc @@ -741,7 +741,7 @@ Model::Model(Connection& conn) m_conn.grab_bindings(key_inputs, mouse_inputs); for (auto& window : m_conn.top_level_windows()) - manage(window, !m_conn.must_manage_window(window)); + manage(window, !m_conn.must_manage_window(window), true); { // user configurations std::stringstream configdir_ss; @@ -1615,12 +1615,12 @@ Model::retrieve_rules(Client_ptr client) const void -Model::manage(const Window window, const bool ignore) +Model::manage(const Window window, const bool ignore, const bool may_map) { std::optional<Region> window_geometry = m_conn.get_window_geometry(window); if (ignore || !window_geometry) { - if (m_conn.window_is_mappable(window)) + if (may_map && m_conn.window_is_mappable(window)) m_conn.map_window(window); m_conn.init_unmanaged(window); @@ -1648,8 +1648,8 @@ Model::manage(const Window window, const bool ignore) std::string class_ = m_conn.get_icccm_window_class(window); std::string instance = m_conn.get_icccm_window_instance(window); - WindowType preferred_type = m_conn.get_window_preferred_type(window); - std::optional<WindowState> preferred_state = m_conn.get_window_preferred_state(window); + std::unordered_set<WindowType> types = m_conn.get_window_types(window); + std::unordered_set<WindowState> states = m_conn.get_window_states(window); Region geometry = *window_geometry; @@ -1693,7 +1693,6 @@ Model::manage(const Window window, const bool ignore) mp_partition->index(), context, workspace, - preferred_type, pid, ppid ); @@ -1795,10 +1794,10 @@ Model::manage(const Window window, const bool ignore) focus_client(client); } - if (preferred_state && *preferred_state == WindowState::DemandsAttention) + if (Util::contains(states, WindowState::DemandsAttention)) handle_state_request({ window, - *preferred_state, + WindowState::DemandsAttention, Toggle::On, false }); @@ -3470,6 +3469,8 @@ void Model::handle_map_request(MapRequestEvent event) { bool must_restack = false; + bool may_map = true; + std::optional<std::vector<std::optional<Strut>>> struts = m_conn.get_window_strut(event.window); @@ -3486,25 +3487,25 @@ Model::handle_map_request(MapRequestEvent event) apply_layout(mp_workspace); must_restack = true; } else - m_conn.unmap_window(event.window); + may_map = false; } - WindowType type - = m_conn.get_window_preferred_type(event.window); + std::unordered_set<WindowType> types + = m_conn.get_window_types(event.window); - std::optional<WindowState> state - = m_conn.get_window_preferred_state(event.window); + std::unordered_set<WindowState> states + = m_conn.get_window_states(event.window); std::optional<Region> region = m_conn.get_window_geometry(event.window); std::optional<StackHandler::StackLayer> layer = std::nullopt; - if (state == WindowState::Below_) + if (Util::contains(states, WindowState::Below_)) layer = StackHandler::StackLayer::Below_; - else if (type == WindowType::Desktop) + else if (Util::contains(types, WindowType::Desktop)) layer = StackHandler::StackLayer::Desktop; - else if (type == WindowType::Dock) { + else if (Util::contains(types, WindowType::Dock)) { Screen& screen = mp_partition->screen(); if (region && !screen.contains_strut(event.window)) { @@ -3547,14 +3548,14 @@ Model::handle_map_request(MapRequestEvent event) apply_layout(mp_workspace); } else - m_conn.unmap_window(strut->window); + may_map = false; } } layer = StackHandler::StackLayer::Dock; - } else if (type == WindowType::Notification) + } else if (Util::contains(types, WindowType::Notification)) layer = StackHandler::StackLayer::Notification; - else if (state == WindowState::Above_) + else if (Util::contains(states, WindowState::Above_)) layer = StackHandler::StackLayer::Above_; if (layer) { @@ -3565,8 +3566,11 @@ Model::handle_map_request(MapRequestEvent event) if (must_restack) apply_stack(mp_workspace); + if (!may_map) + m_conn.unmap_window(event.window); + if (!(m_client_map.count(event.window) > 0)) - manage(event.window, event.ignore); + manage(event.window, event.ignore, may_map); } void diff --git a/src/core/model.hh b/src/core/model.hh @@ -104,7 +104,7 @@ private: Rules retrieve_rules(Client_ptr) const; - void manage(const winsys::Window, const bool); + void manage(const winsys::Window, const bool, const bool); void unmanage(Client_ptr); void start_moving(Client_ptr); diff --git a/src/winsys/connection.hh b/src/winsys/connection.hh @@ -1,16 +1,17 @@ #ifndef __WINSYS_CONNECTION_H_GUARD__ #define __WINSYS_CONNECTION_H_GUARD__ -#include <vector> #include <optional> -#include <tuple> #include <string> +#include <tuple> +#include <unordered_set> +#include <vector> #include "common.hh" #include "event.hh" +#include "hints.hh" #include "screen.hh" #include "window.hh" -#include "hints.hh" namespace winsys { @@ -98,10 +99,8 @@ namespace winsys virtual std::optional<std::vector<std::optional<Strut>>> get_window_strut(Window) = 0; virtual std::optional<std::vector<std::optional<Strut>>> get_window_strut_partial(Window) = 0; virtual std::optional<Index> get_window_desktop(Window) = 0; - virtual WindowType get_window_preferred_type(Window) = 0; - virtual std::vector<WindowType> get_window_types(Window) = 0; - virtual std::optional<WindowState> get_window_preferred_state(Window) = 0; - virtual std::vector<WindowState> get_window_states(Window) = 0; + virtual std::unordered_set<WindowType> get_window_types(Window) = 0; + virtual std::unordered_set<WindowState> get_window_states(Window) = 0; virtual bool window_is_fullscreen(Window) = 0; virtual bool window_is_above(Window) = 0; virtual bool window_is_below(Window) = 0; diff --git a/src/winsys/screen.cc b/src/winsys/screen.cc @@ -27,21 +27,17 @@ Screen::show_and_get_struts(bool show) void Screen::add_struts(std::vector<std::optional<Strut>> struts) { - if (struts[0]) { + if (struts.size() > 0 && struts[0]) add_strut(Edge::Left, *struts[0]); - } - if (struts[1]) { - add_strut(Edge::Top, *struts[1]); - } + if (struts.size() > 1 && struts[1]) + add_strut(Edge::Right, *struts[1]); - if (struts[2]) { - add_strut(Edge::Right, *struts[2]); - } + if (struts.size() > 2 && struts[2]) + add_strut(Edge::Top, *struts[2]); - if (struts[3]) { + if (struts.size() > 3 && struts[3]) add_strut(Edge::Bottom, *struts[3]); - } } void diff --git a/src/winsys/xdata/xconnection.cc b/src/winsys/xdata/xconnection.cc @@ -863,18 +863,10 @@ XConnection::must_free_window(winsys::Window window) bool XConnection::window_is_mappable(winsys::Window window) { - static const std::vector<winsys::WindowState> unmappable_states = { - winsys::WindowState::Hidden - }; - XWindowAttributes wa; XGetWindowAttributes(mp_dpy, window, &wa); - std::optional<winsys::Hints> hints = get_icccm_window_hints(window); - - return (wa.c_class != InputOnly) - && (hints && hints->initial_state && *hints->initial_state == winsys::IcccmWindowState::Normal) - && !window_is_any_of_states(window, unmappable_states); + return wa.c_class != InputOnly; } // ICCCM @@ -1386,18 +1378,7 @@ XConnection::get_window_desktop(winsys::Window window) return index; } -winsys::WindowType -XConnection::get_window_preferred_type(winsys::Window window) -{ - std::vector<winsys::WindowType> window_types = get_window_types(window); - - if (window_types.size() > 0) - return window_types[0]; - - return winsys::WindowType::Normal; -} - -std::vector<winsys::WindowType> +std::unordered_set<winsys::WindowType> XConnection::get_window_types(winsys::Window window) { std::vector<Atom> window_type_atoms = get_atomlist_property(window, "_NET_WM_WINDOW_TYPE"); @@ -1405,32 +1386,15 @@ XConnection::get_window_types(winsys::Window window) if (!property_status_ok()) return {}; - std::vector<winsys::WindowType> window_types = {}; + std::unordered_set<winsys::WindowType> window_types = {}; - std::transform( - window_type_atoms.begin(), - window_type_atoms.end(), - std::back_inserter(window_types), - [=, this](Atom atom) -> winsys::WindowType { - return get_window_type_from_atom(atom); - } - ); + for (Atom atom : window_type_atoms) + window_types.insert(get_window_type_from_atom(atom)); return window_types; } -std::optional<winsys::WindowState> -XConnection::get_window_preferred_state(winsys::Window window) -{ - std::vector<winsys::WindowState> window_states = get_window_states(window); - - if (window_states.size() > 0) - return window_states[0]; - - return std::nullopt; -} - -std::vector<winsys::WindowState> +std::unordered_set<winsys::WindowState> XConnection::get_window_states(winsys::Window window) { std::vector<Atom> window_state_atoms = get_atomlist_property(window, "_NET_WM_STATE"); @@ -1438,16 +1402,10 @@ XConnection::get_window_states(winsys::Window window) if (!property_status_ok()) return {}; - std::vector<winsys::WindowState> window_states = {}; + std::unordered_set<winsys::WindowState> window_states = {}; - std::transform( - window_state_atoms.begin(), - window_state_atoms.end(), - std::back_inserter(window_states), - [=, this](Atom atom) -> winsys::WindowState { - return get_window_state_from_atom(atom); - } - ); + for (Atom atom : window_state_atoms) + window_states.insert(get_window_state_from_atom(atom)); return window_states; } diff --git a/src/winsys/xdata/xconnection.hh b/src/winsys/xdata/xconnection.hh @@ -102,10 +102,8 @@ public: virtual std::optional<std::vector<std::optional<winsys::Strut>>> get_window_strut(winsys::Window) override; virtual std::optional<std::vector<std::optional<winsys::Strut>>> get_window_strut_partial(winsys::Window) override; virtual std::optional<Index> get_window_desktop(winsys::Window) override; - virtual winsys::WindowType get_window_preferred_type(winsys::Window) override; - virtual std::vector<winsys::WindowType> get_window_types(winsys::Window) override; - virtual std::optional<winsys::WindowState> get_window_preferred_state(winsys::Window) override; - virtual std::vector<winsys::WindowState> get_window_states(winsys::Window) override; + virtual std::unordered_set<winsys::WindowType> get_window_types(winsys::Window) override; + virtual std::unordered_set<winsys::WindowState> get_window_states(winsys::Window) override; virtual bool window_is_fullscreen(winsys::Window) override; virtual bool window_is_above(winsys::Window) override; virtual bool window_is_below(winsys::Window) override;