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:
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;