xconnection.hh (14608B)
1 #ifndef __WINSYS_XDATA_XCONNECTION_H_GUARD__ 2 #define __WINSYS_XDATA_XCONNECTION_H_GUARD__ 3 4 #include "../connection.hh" 5 #include "../event.hh" 6 #include "../input.hh" 7 8 #include <cstddef> 9 #include <functional> 10 #include <iostream> 11 #include <string> 12 #include <unordered_map> 13 #include <variant> 14 15 extern "C" { 16 #include <X11/Xatom.h> 17 #include <X11/Xlib.h> 18 #include <X11/Xmd.h> 19 #include <X11/cursorfont.h> 20 #include <sys/un.h> 21 } 22 23 class XConnection final: public winsys::Connection 24 { 25 public: 26 XConnection(const std::string_view); 27 ~XConnection(); 28 29 virtual void init_wm_ipc() override; 30 virtual bool flush() override; 31 virtual winsys::Event step() override; 32 virtual bool check_progress() override; 33 virtual void process_events(std::function<void(winsys::Event)>) override; 34 virtual void process_messages(std::function<void(winsys::Message)>) override; 35 virtual std::vector<winsys::Screen> connected_outputs() override; 36 virtual std::vector<winsys::Window> top_level_windows() override; 37 virtual winsys::Pos get_pointer_position() override; 38 virtual void warp_pointer_center_of_window_or_root(std::optional<winsys::Window>, winsys::Screen&) override; 39 virtual void warp_pointer(winsys::Pos) override; 40 virtual void warp_pointer_rpos(winsys::Window, winsys::Pos) override; 41 virtual void confine_pointer(winsys::Window) override; 42 virtual bool release_pointer() override; 43 virtual void call_external_command(std::string&) override; 44 virtual void cleanup() override; 45 46 // window manipulation 47 virtual winsys::Window create_frame(winsys::Region) override; 48 virtual void init_window(winsys::Window) override; 49 virtual void init_frame(winsys::Window, bool) override; 50 virtual void init_unmanaged(winsys::Window) override; 51 virtual void init_move(winsys::Window) override; 52 virtual void init_resize(winsys::Window) override; 53 virtual void cleanup_window(winsys::Window) override; 54 virtual void map_window(winsys::Window) override; 55 virtual void unmap_window(winsys::Window) override; 56 virtual void reparent_window(winsys::Window, winsys::Window, winsys::Pos) override; 57 virtual void unparent_window(winsys::Window, winsys::Pos) override; 58 virtual void destroy_window(winsys::Window) override; 59 virtual bool close_window(winsys::Window) override; 60 virtual bool kill_window(winsys::Window) override; 61 virtual void place_window(winsys::Window, winsys::Region&) override; 62 virtual void move_window(winsys::Window, winsys::Pos) override; 63 virtual void resize_window(winsys::Window, winsys::Dim) override; 64 virtual void focus_window(winsys::Window) override; 65 virtual void stack_window_above(winsys::Window, std::optional<winsys::Window>) override; 66 virtual void stack_window_below(winsys::Window, std::optional<winsys::Window>) override; 67 virtual void insert_window_in_save_set(winsys::Window) override; 68 virtual void grab_bindings(std::vector<winsys::KeyInput>&, std::vector<winsys::MouseInput>&) override; 69 virtual void regrab_buttons(winsys::Window) override; 70 virtual void ungrab_buttons(winsys::Window) override; 71 virtual void unfocus() override; 72 virtual void set_window_border_width(winsys::Window, unsigned) override; 73 virtual void set_window_border_color(winsys::Window, unsigned) override; 74 virtual void set_window_background_color(winsys::Window, unsigned) override; 75 virtual void set_window_notify_enter(Window, bool) override; 76 virtual void update_window_offset(winsys::Window, winsys::Window) override; 77 virtual winsys::Window get_focused_window() override; 78 virtual std::optional<winsys::Region> get_window_geometry(winsys::Window) override; 79 virtual std::optional<winsys::Pid> get_window_pid(winsys::Window) override; 80 virtual std::optional<winsys::Pid> get_ppid(std::optional<winsys::Pid>) override; 81 virtual bool must_manage_window(winsys::Window) override; 82 virtual bool must_free_window(winsys::Window) override; 83 virtual bool window_is_mappable(winsys::Window) override; 84 85 // ICCCM 86 virtual void set_icccm_window_state(winsys::Window, winsys::IcccmWindowState) override; 87 virtual void set_icccm_window_hints(winsys::Window, winsys::Hints) override; 88 virtual std::string get_icccm_window_name(winsys::Window) override; 89 virtual std::string get_icccm_window_class(winsys::Window) override; 90 virtual std::string get_icccm_window_instance(winsys::Window) override; 91 virtual std::optional<winsys::Window> get_icccm_window_transient_for(winsys::Window) override; 92 virtual std::optional<winsys::Window> get_icccm_window_client_leader(winsys::Window) override; 93 virtual std::optional<winsys::Hints> get_icccm_window_hints(winsys::Window) override; 94 virtual std::optional<winsys::SizeHints> get_icccm_window_size_hints(winsys::Window, std::optional<winsys::Dim>) override; 95 96 // EWMH 97 virtual void init_for_wm(std::vector<std::string> const&) override; 98 virtual void set_current_desktop(Index) override; 99 virtual void set_root_window_name(std::string const&) override; 100 virtual void set_window_desktop(winsys::Window, Index) override; 101 virtual void set_window_state(winsys::Window, winsys::WindowState, bool) override; 102 virtual void set_window_frame_extents(winsys::Window, winsys::Extents) override; 103 virtual void set_desktop_geometry(std::vector<winsys::Region> const&) override; 104 virtual void set_desktop_viewport(std::vector<winsys::Region> const&) override; 105 virtual void set_workarea(std::vector<winsys::Region> const&) override; 106 virtual void update_desktops(std::vector<std::string> const&) override; 107 virtual void update_client_list(std::vector<winsys::Window> const&) override; 108 virtual void update_client_list_stacking(std::vector<winsys::Window> const&) override; 109 virtual std::optional<std::vector<std::optional<winsys::Strut>>> get_window_strut(winsys::Window) override; 110 virtual std::optional<std::vector<std::optional<winsys::Strut>>> get_window_strut_partial(winsys::Window) override; 111 virtual std::optional<Index> get_window_desktop(winsys::Window) override; 112 virtual std::unordered_set<winsys::WindowType> get_window_types(winsys::Window) override; 113 virtual std::unordered_set<winsys::WindowState> get_window_states(winsys::Window) override; 114 virtual bool window_is_fullscreen(winsys::Window) override; 115 virtual bool window_is_above(winsys::Window) override; 116 virtual bool window_is_below(winsys::Window) override; 117 virtual bool window_is_sticky(winsys::Window) override; 118 119 // IPC client 120 virtual void init_for_client() override; 121 122 private: 123 static int s_otherwm_error_handler(Display*, XErrorEvent*); 124 static int s_passthrough_error_handler(Display*, XErrorEvent*); 125 static int s_default_error_handler(Display*, XErrorEvent*); 126 127 enum NetWMID : int 128 { // NetWM atom identifiers 129 NetSupported = 0, NetFirst = NetSupported, 130 NetClientList, 131 NetNumberOfDesktops, 132 NetCurrentDesktop, 133 NetDesktopNames, 134 NetDesktopGeometry, 135 NetDesktopViewport, 136 NetWorkarea, 137 NetActiveWindow, 138 NetWMName, 139 NetWMDesktop, 140 NetWMStrut, 141 NetWMStrutPartial, 142 NetWMFrameExtents, 143 NetSupportingWMCheck, 144 NetWMState, 145 NetWMWindowType, 146 // root messages 147 NetWMCloseWindow, NetWMRootFirst = NetWMCloseWindow, 148 NetWMMoveResize, 149 NetRequestFrameExtents, 150 NetMoveResizeWindow, NetWMRootLast = NetMoveResizeWindow, 151 // window states 152 NetWMStateFullscreen, NetWMStateFirst = NetWMStateFullscreen, 153 NetWMStateAbove, 154 NetWMStateBelow, 155 NetWMStateDemandsAttention, 156 NetWMStateHidden, NetWMStateLast = NetWMStateHidden, 157 // window types 158 NetWMWindowTypeDesktop, NetWMWindowTypeFirst = NetWMWindowTypeDesktop, 159 NetWMWindowTypeDock, 160 NetWMWindowTypeToolbar, 161 NetWMWindowTypeMenu, 162 NetWMWindowTypeUtility, 163 NetWMWindowTypeSplash, 164 NetWMWindowTypeDialog, 165 NetWMWindowTypeDropdownMenu, 166 NetWMWindowTypePopupMenu, 167 NetWMWindowTypeTooltip, 168 NetWMWindowTypeNotification, 169 NetWMWindowTypeNormal, NetWMwindowtypelast = NetWMWindowTypeNormal, 170 NetLast 171 }; 172 173 enum class NetWMAction 174 { 175 NetRemove = 0, 176 NetAdd = 1, 177 NetToggle = 2, 178 NetNoAction 179 }; 180 181 friend inline XConnection::NetWMID& 182 operator++(XConnection::NetWMID& id) 183 { 184 return id = static_cast<XConnection::NetWMID>(static_cast<int>(id) + 1); 185 } 186 187 Display* mp_dpy; 188 winsys::Window m_root; 189 winsys::Window m_check_window; 190 191 int m_dpy_fd; 192 int m_sock_fd; 193 int m_client_fd; 194 int m_max_fd; 195 196 fd_set m_descr; 197 char m_sock_path[256]; 198 char m_state_path[256] = {}; 199 struct sockaddr_un m_sock_addr; 200 201 std::string m_wm_name; 202 203 XEvent m_current_event; 204 205 int m_substructure_level = 0; 206 long m_prev_root_mask = 0; 207 208 Status m_property_status = 0; 209 210 std::optional<winsys::Window> m_confined_to; 211 212 std::unordered_map<std::string, Atom> m_interned_atoms; 213 std::unordered_map<Atom, std::string> m_atom_names; 214 215 std::unordered_map<std::size_t, winsys::Key> m_keys; 216 std::unordered_map<winsys::Key, std::size_t> m_keycodes; 217 218 std::unordered_map<NetWMID, Atom> m_netwm_atoms; 219 220 int (*m_checkwm_error_handler)(Display*, XErrorEvent*); 221 222 template <class T> 223 XEvent 224 create_event(winsys::Window window, Atom type, T data) 225 { 226 XEvent event; 227 event.type = ClientMessage; 228 event.xclient.window = window; 229 event.xclient.message_type = type; 230 event.xclient.format = 32; 231 event.xclient.data.l[0] = data; 232 event.xclient.data.l[1] = CurrentTime; 233 return event; 234 } 235 236 void enable_substructure_events(); 237 void disable_substructure_events(); 238 239 void next_event(XEvent&); 240 bool typed_event(XEvent&, int); 241 void last_typed_event(XEvent&, int); 242 243 void sync(bool); 244 int pending(); 245 246 winsys::Window create_handle(); 247 248 Atom get_atom(std::string const&); 249 Atom get_netwm_atom(NetWMID const&); 250 void intern_atom(std::string const&, Atom); 251 252 winsys::Key get_key(const std::size_t); 253 std::size_t get_keycode(const winsys::Key); 254 void intern_key(const unsigned, const winsys::Key); 255 winsys::Button get_button(const unsigned) const; 256 unsigned get_buttoncode(const winsys::Button) const; 257 258 winsys::WindowState get_window_state_from_atom(Atom); 259 winsys::WindowType get_window_type_from_atom(Atom); 260 Atom get_atom_from_window_state(winsys::WindowState); 261 Atom get_atom_from_window_type(winsys::WindowType); 262 263 bool property_status_ok(); 264 265 bool has_atom_property(winsys::Window, Atom); 266 bool has_atomlist_property(winsys::Window, Atom); 267 bool has_window_property(winsys::Window, Atom); 268 bool has_windowlist_property(winsys::Window, Atom); 269 bool has_string_property(winsys::Window, Atom); 270 bool has_stringlist_property(winsys::Window, Atom); 271 bool has_card_property(winsys::Window, Atom); 272 bool has_cardlist_property(winsys::Window, Atom); 273 274 Atom get_atom_property(winsys::Window, std::string const&); 275 std::vector<Atom> get_atomlist_property(winsys::Window, std::string const&); 276 winsys::Window get_window_property(winsys::Window, std::string const&); 277 std::vector<winsys::Window> get_windowlist_property(winsys::Window, std::string const&); 278 std::string get_string_property(winsys::Window, std::string const&); 279 std::vector<std::string> get_stringlist_property(winsys::Window, std::string const&); 280 unsigned long get_card_property(winsys::Window, std::string const&); 281 std::vector<unsigned long> get_cardlist_property(winsys::Window, std::string const&); 282 283 bool get_text_property(winsys::Window, Atom, char*, unsigned); 284 285 void replace_atom_property(winsys::Window, std::string const&, Atom); 286 void replace_atomlist_property(winsys::Window, std::string const&, std::vector<Atom> const&); 287 void replace_window_property(winsys::Window, std::string const&, winsys::Window); 288 void replace_windowlist_property(winsys::Window, std::string const&, std::vector<winsys::Window> const&); 289 void replace_string_property(winsys::Window, std::string const&, std::string const&); 290 void replace_stringlist_property(winsys::Window, std::string const&, std::vector<std::string> const&); 291 void replace_card_property(winsys::Window, std::string const&, const unsigned long); 292 void replace_cardlist_property(winsys::Window, std::string const&, std::vector<unsigned long> const&); 293 294 void append_atomlist_property(winsys::Window, std::string const&, Atom); 295 void append_windowlist_property(winsys::Window, std::string const&, winsys::Window); 296 void append_stringlist_property(winsys::Window, std::string const&, std::string const&); 297 void append_cardlist_property(winsys::Window, std::string const&, const unsigned long); 298 299 void unset_atom_property(winsys::Window, std::string const&); 300 void unset_atomlist_property(winsys::Window, std::string const&); 301 void unset_window_property(winsys::Window, std::string const&); 302 void unset_windowlist_property(winsys::Window, std::string const&); 303 void unset_string_property(winsys::Window, std::string const&); 304 void unset_stringlist_property(winsys::Window, std::string const&); 305 void unset_card_property(winsys::Window, std::string const&); 306 void unset_cardlist_property(winsys::Window, std::string const&); 307 308 bool window_is_any_of_states(winsys::Window, std::vector<winsys::WindowState> const&); 309 bool window_is_any_of_types(winsys::Window, std::vector<winsys::WindowType> const&); 310 311 void check_otherwm(); 312 313 // event dispatching logic 314 winsys::Event (XConnection::*m_event_dispatcher[LASTEvent])(); 315 316 winsys::Event on_button_press(); 317 winsys::Event on_button_release(); 318 winsys::Event on_circulate_request(); 319 winsys::Event on_client_message(); 320 winsys::Event on_configure_notify(); 321 winsys::Event on_configure_request(); 322 winsys::Event on_destroy_notify(); 323 winsys::Event on_expose(); 324 winsys::Event on_focus_in(); 325 winsys::Event on_enter_notify(); 326 winsys::Event on_key_press(); 327 winsys::Event on_map_notify(); 328 winsys::Event on_map_request(); 329 winsys::Event on_mapping_notify(); 330 winsys::Event on_motion_notify(); 331 winsys::Event on_property_notify(); 332 winsys::Event on_screen_change(); 333 winsys::Event on_unmap_notify(); 334 335 winsys::Event on_unimplemented(); 336 }; 337 338 #endif//__WINSYS_XDATA_XCONNECTION_H_GUARD__