From 456c27b114fbd5d4e40bb9fb958d9335a2d3b5e4 Mon Sep 17 00:00:00 2001 From: Sergey Naumov Date: Wed, 20 Apr 2016 21:01:20 +0300 Subject: [PATCH 01/16] Implementation of GET_TREE --- include/i3ipc++/ipc.hpp | 57 +++++++++++++++++++++++++++++++ src/ipc.cpp | 74 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) diff --git a/include/i3ipc++/ipc.hpp b/include/i3ipc++/ipc.hpp index 38ed4a2..ad6287a 100644 --- a/include/i3ipc++/ipc.hpp +++ b/include/i3ipc++/ipc.hpp @@ -67,6 +67,7 @@ struct version_t { uint32_t patch; /**< Patch number of i3 */ }; + /** * Types of the events of i3 */ @@ -102,6 +103,56 @@ enum class WindowEventType : char { URGENT = 'u', /**< Window became urgent */ }; + +/** + * A style of a container's border + */ +enum class BorderStyle : char { + UNKNOWN = '?', //< If got an unknown border style in reply + NONE = 'N', + NORMAL = 'n', + ONE_PIXEL = '1', +}; + + +/** + * A type of a container's layout + */ +enum class ContainerLayout : char { + UNKNOWN = '?', //< If got an unknown border style in reply + SPLIT_H = 'h', + SPLIT_V = 'v', + STACKED = 's', + TABBED = 't', + DOCKAREA = 'd', + OUTPUT = 'o', +}; + + +/** + * A node of tree of windows + */ +struct container_t { + uint64_t id; ///< The internal ID (actually a C pointer value) of this container. Do not make any assumptions about it. You can use it to (re-)identify and address containers when talking to i3 + uint64_t xwindow_id; ///< The X11 window ID of the actual client window inside this container. This field is set to null for split containers or otherwise empty containers. This ID corresponds to what xwininfo(1) and other X11-related tools display (usually in hex) + std::string name; ///< The internal name of this container. For all containers which are part of the tree structure down to the workspace contents, this is set to a nice human-readable name of the container. For containers that have an X11 window, the content is the title (_NET_WM_NAME property) of that window. For all other containers, the content is not defined (yet) + std::string type; ///< Type of this container + BorderStyle border; ///< A style of the container's border + std::string border_raw; ///< A "border" field of TREE reply. NOT empty only if border equals BorderStyle::UNKNOWN + uint32_t current_border_width; ///< Number of pixels of the border width + ContainerLayout layout; ///< A type of the container's layout + std::string layout_raw; ///< A "layout" field of TREE reply. NOT empty only if layout equals ContainerLayout::UNKNOWN + float percent; ///< The percentage which this container takes in its parent. A value of < 0 means that the percent property does not make sense for this container, for example for the root container. + rect_t rect; ///< The absolute display coordinates for this container + rect_t window_rect; ///< The coordinates of the actual client window inside its container. These coordinates are relative to the container and do not include the window decoration (which is actually rendered on the parent container) + rect_t deco_rect; ///< The coordinates of the window decoration inside its container. These coordinates are relative to the container and do not include the actual client window + rect_t geometry; ///< The original geometry the window specified when i3 mapped it. Used when switching a window to floating mode, for example + bool urgent; + bool focused; + + std::list< std::shared_ptr > nodes; +}; + struct buf_t; /** * Connection to the i3 @@ -140,6 +191,12 @@ public: */ version_t get_version() const; + /** + * Request a tree of windows + * @return A root container + */ + std::shared_ptr get_tree() const; + /** * Subscribe on an events of i3 * diff --git a/src/ipc.cpp b/src/ipc.cpp index 9974e62..739e6de 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -224,6 +224,80 @@ version_t I3Connection::get_version() const { } +static std::shared_ptr parse_container_from_json(const Json::Value& o) { +#define i3IPC_TYPE_STR "GET_TREE" + std::shared_ptr container (new container_t()); + IPC_JSON_ASSERT_TYPE_OBJECT(o, "o") + + container->id = o["id"].asUInt64(); + container->xwindow_id= o["window"].asUInt64(); + container->name = o["name"].asString(); + container->type = o["type"].asString(); + container->current_border_width = o["current_border_width"].asInt(); + container->percent = o["percent"].asFloat(); + container->rect = parse_rect_from_json(o["rect"]); + container->window_rect = parse_rect_from_json(o["window_rect"]); + container->deco_rect = parse_rect_from_json(o["deco_rect"]); + container->geometry = parse_rect_from_json(o["geometry"]); + container->urgent = o["urgent"].asBool(); + container->focused = o["focused"].asBool(); + + container->border = BorderStyle::UNKNOWN; + std::string border = o["border"].asString(); + if (border == "normal") { + container->border = BorderStyle::NORMAL; + } else if (border == "none") { + container->border = BorderStyle::NONE; + } else if (border == "1pixel") { + container->border = BorderStyle::ONE_PIXEL; + } else { + container->border_raw = border; + I3IPC_WARN("Got a unknown \"border\" property: \"" << border << "\". Perhaps its neccessary to update i3ipc++. If you are using latest, note maintainer about this") + } + + container->layout = ContainerLayout::UNKNOWN; + std::string layout = o["layout"].asString(); + + if (layout == "splith") { + container->layout = ContainerLayout::SPLIT_H; + } else if (layout == "splitv") { + container->layout = ContainerLayout::SPLIT_V; + } else if (layout == "stacked") { + container->layout = ContainerLayout::STACKED; + } else if (layout == "tabbed") { + container->layout = ContainerLayout::TABBED; + } else if (layout == "dockarea") { + container->layout = ContainerLayout::DOCKAREA; + } else if (layout == "output") { + container->layout = ContainerLayout::OUTPUT; + } else { + container->layout_raw = border; + I3IPC_WARN("Got a unknown \"layout\" property: \"" << layout << "\". Perhaps its neccessary to update i3ipc++. If you are using latest, note maintainer about this") + } + + Json::Value nodes = o["nodes"]; + if (!nodes.isNull()) { + IPC_JSON_ASSERT_TYPE_ARRAY(nodes, "nodes") + for (Json::ArrayIndex i = 0; i < nodes.size(); i++) { + container->nodes.push_back(parse_container_from_json(nodes[i])); + } + } + + return container; +#undef i3IPC_TYPE_STR +} + + +std::shared_ptr I3Connection::get_tree() const { +#define i3IPC_TYPE_STR "GET_TREE" + auto buf = i3_msg(m_main_socket, ClientMessageType::GET_TREE); + Json::Value root; + IPC_JSON_READ(root); + return parse_container_from_json(root); +#undef i3IPC_TYPE_STR +} + + std::vector I3Connection::get_outputs() const { #define i3IPC_TYPE_STR "GET_OUTPUTS" auto buf = i3_msg(m_main_socket, ClientMessageType::GET_OUTPUTS); From 88c350a3496edb8c797b13fb90d5690cdf804c98 Mon Sep 17 00:00:00 2001 From: Sergey Naumov Date: Wed, 20 Apr 2016 21:01:35 +0300 Subject: [PATCH 02/16] An example for get_tree() --- examples/workspaces.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/examples/workspaces.cpp b/examples/workspaces.cpp index f21710d..5b63483 100644 --- a/examples/workspaces.cpp +++ b/examples/workspaces.cpp @@ -2,6 +2,31 @@ #include + +void dump_tree_container(const i3ipc::container_t& c, std::string& prefix) { + std::cout << prefix << "ID: " << c.id << " (i3's; X11's - " << c.xwindow_id << ")" << std::endl; + prefix.push_back('\t'); + std::cout << prefix << "name = \"" << c.name << "\"" << std::endl; + std::cout << prefix << "type = \"" << c.type << "\"" << std::endl; + std::cout << prefix << "border = \"" << c.border_raw << "\"" << std::endl; + std::cout << prefix << "current_border_width = " << c.current_border_width << std::endl; + std::cout << prefix << "layout = \"" << c.layout_raw << "\"" << std::endl; + std::cout << prefix << "percent = " << c.percent << std::endl; + if (c.urgent) { + std::cout << prefix << "urgent" << std::endl; + } + if (c.focused) { + std::cout << prefix << "focused" << std::endl; + } + prefix.push_back('\t'); + for (auto& n : c.nodes) { + dump_tree_container(*n, prefix); + } + prefix.pop_back(); + prefix.pop_back(); +} + + int main() { i3ipc::I3Connection conn; for (auto& w : conn.get_workspaces()) { @@ -18,5 +43,8 @@ int main() { << "\n\tOutput: " << w.output << std::endl; } + std::string prefix_buf; + dump_tree_container(*conn.get_tree(), prefix_buf); + return 0; } From abe80f965e83b57b438f0c55558a3a44ebd7a1ac Mon Sep 17 00:00:00 2001 From: Sergey Naumov Date: Thu, 21 Apr 2016 06:51:49 +0300 Subject: [PATCH 03/16] Refraction of JSON parsing --- src/ipc.cpp | 192 +++++++++++++++++++++++++++------------------------- 1 file changed, 100 insertions(+), 92 deletions(-) diff --git a/src/ipc.cpp b/src/ipc.cpp index 739e6de..13fd63a 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -50,6 +50,104 @@ inline rect_t parse_rect_from_json(const Json::Value& value) { } +static std::shared_ptr parse_container_from_json(const Json::Value& o) { +#define i3IPC_TYPE_STR "GET_TREE" // FIXME + std::shared_ptr container (new container_t()); + IPC_JSON_ASSERT_TYPE_OBJECT(o, "o") + + container->id = o["id"].asUInt64(); + container->xwindow_id= o["window"].asUInt64(); + container->name = o["name"].asString(); + container->type = o["type"].asString(); + container->current_border_width = o["current_border_width"].asInt(); + container->percent = o["percent"].asFloat(); + container->rect = parse_rect_from_json(o["rect"]); + container->window_rect = parse_rect_from_json(o["window_rect"]); + container->deco_rect = parse_rect_from_json(o["deco_rect"]); + container->geometry = parse_rect_from_json(o["geometry"]); + container->urgent = o["urgent"].asBool(); + container->focused = o["focused"].asBool(); + + container->border = BorderStyle::UNKNOWN; + std::string border = o["border"].asString(); + if (border == "normal") { + container->border = BorderStyle::NORMAL; + } else if (border == "none") { + container->border = BorderStyle::NONE; + } else if (border == "1pixel") { + container->border = BorderStyle::ONE_PIXEL; + } else { + container->border_raw = border; + I3IPC_WARN("Got a unknown \"border\" property: \"" << border << "\". Perhaps its neccessary to update i3ipc++. If you are using latest, note maintainer about this") + } + + container->layout = ContainerLayout::UNKNOWN; + std::string layout = o["layout"].asString(); + + if (layout == "splith") { + container->layout = ContainerLayout::SPLIT_H; + } else if (layout == "splitv") { + container->layout = ContainerLayout::SPLIT_V; + } else if (layout == "stacked") { + container->layout = ContainerLayout::STACKED; + } else if (layout == "tabbed") { + container->layout = ContainerLayout::TABBED; + } else if (layout == "dockarea") { + container->layout = ContainerLayout::DOCKAREA; + } else if (layout == "output") { + container->layout = ContainerLayout::OUTPUT; + } else { + container->layout_raw = border; + I3IPC_WARN("Got a unknown \"layout\" property: \"" << layout << "\". Perhaps its neccessary to update i3ipc++. If you are using latest, note maintainer about this") + } + + Json::Value nodes = o["nodes"]; + if (!nodes.isNull()) { + IPC_JSON_ASSERT_TYPE_ARRAY(nodes, "nodes") + for (Json::ArrayIndex i = 0; i < nodes.size(); i++) { + container->nodes.push_back(parse_container_from_json(nodes[i])); + } + } + + return container; +#undef i3IPC_TYPE_STR +} + +static workspace_t parse_workspace_from_json(const Json::Value& value) { + Json::Value num = value["num"]; + Json::Value name = value["name"]; + Json::Value visible = value["visible"]; + Json::Value focused = value["focused"]; + Json::Value urgent = value["urgent"]; + Json::Value rect = value["rect"]; + Json::Value output = value["output"]; + + return { + .num = num.asInt(), + .name = name.asString(), + .visible = visible.asBool(), + .focused = focused.asBool(), + .urgent = urgent.asBool(), + .rect = parse_rect_from_json(rect), + .output = output.asString(), + }; +} + +static output_t parse_output_from_json(const Json::Value& value) { + Json::Value name = value["name"]; + Json::Value active = value["active"]; + Json::Value current_workspace = value["current_workspace"]; + Json::Value rect = value["rect"]; + + return { + .name = name.asString(), + .active = active.asBool(), + .current_workspace = (current_workspace.isNull() ? std::string() : current_workspace.asString()), + .rect = parse_rect_from_json(rect), + }; +} + + std::string get_socketpath() { std::string str; { @@ -224,70 +322,6 @@ version_t I3Connection::get_version() const { } -static std::shared_ptr parse_container_from_json(const Json::Value& o) { -#define i3IPC_TYPE_STR "GET_TREE" - std::shared_ptr container (new container_t()); - IPC_JSON_ASSERT_TYPE_OBJECT(o, "o") - - container->id = o["id"].asUInt64(); - container->xwindow_id= o["window"].asUInt64(); - container->name = o["name"].asString(); - container->type = o["type"].asString(); - container->current_border_width = o["current_border_width"].asInt(); - container->percent = o["percent"].asFloat(); - container->rect = parse_rect_from_json(o["rect"]); - container->window_rect = parse_rect_from_json(o["window_rect"]); - container->deco_rect = parse_rect_from_json(o["deco_rect"]); - container->geometry = parse_rect_from_json(o["geometry"]); - container->urgent = o["urgent"].asBool(); - container->focused = o["focused"].asBool(); - - container->border = BorderStyle::UNKNOWN; - std::string border = o["border"].asString(); - if (border == "normal") { - container->border = BorderStyle::NORMAL; - } else if (border == "none") { - container->border = BorderStyle::NONE; - } else if (border == "1pixel") { - container->border = BorderStyle::ONE_PIXEL; - } else { - container->border_raw = border; - I3IPC_WARN("Got a unknown \"border\" property: \"" << border << "\". Perhaps its neccessary to update i3ipc++. If you are using latest, note maintainer about this") - } - - container->layout = ContainerLayout::UNKNOWN; - std::string layout = o["layout"].asString(); - - if (layout == "splith") { - container->layout = ContainerLayout::SPLIT_H; - } else if (layout == "splitv") { - container->layout = ContainerLayout::SPLIT_V; - } else if (layout == "stacked") { - container->layout = ContainerLayout::STACKED; - } else if (layout == "tabbed") { - container->layout = ContainerLayout::TABBED; - } else if (layout == "dockarea") { - container->layout = ContainerLayout::DOCKAREA; - } else if (layout == "output") { - container->layout = ContainerLayout::OUTPUT; - } else { - container->layout_raw = border; - I3IPC_WARN("Got a unknown \"layout\" property: \"" << layout << "\". Perhaps its neccessary to update i3ipc++. If you are using latest, note maintainer about this") - } - - Json::Value nodes = o["nodes"]; - if (!nodes.isNull()) { - IPC_JSON_ASSERT_TYPE_ARRAY(nodes, "nodes") - for (Json::ArrayIndex i = 0; i < nodes.size(); i++) { - container->nodes.push_back(parse_container_from_json(nodes[i])); - } - } - - return container; -#undef i3IPC_TYPE_STR -} - - std::shared_ptr I3Connection::get_tree() const { #define i3IPC_TYPE_STR "GET_TREE" auto buf = i3_msg(m_main_socket, ClientMessageType::GET_TREE); @@ -308,17 +342,7 @@ std::vector I3Connection::get_outputs() const { std::vector outputs; for (auto w : root) { - Json::Value name = w["name"]; - Json::Value active = w["active"]; - Json::Value current_workspace = w["current_workspace"]; - Json::Value rect = w["rect"]; - - outputs.push_back({ - .name = name.asString(), - .active = active.asBool(), - .current_workspace = (current_workspace.isNull() ? std::string() : current_workspace.asString()), - .rect = parse_rect_from_json(rect), - }); + outputs.push_back(parse_output_from_json(w)); } return outputs; @@ -336,23 +360,7 @@ std::vector I3Connection::get_workspaces() const { std::vector workspaces; for (auto w : root) { - Json::Value num = w["num"]; - Json::Value name = w["name"]; - Json::Value visible = w["visible"]; - Json::Value focused = w["focused"]; - Json::Value urgent = w["urgent"]; - Json::Value rect = w["rect"]; - Json::Value output = w["output"]; - - workspaces.push_back({ - .num = num.asInt(), - .name = name.asString(), - .visible = visible.asBool(), - .focused = focused.asBool(), - .urgent = urgent.asBool(), - .rect = parse_rect_from_json(rect), - .output = output.asString(), - }); + workspaces.push_back(parse_workspace_from_json(w)); } return workspaces; From b6f819cf42f9ae15f8d9c2b3122ec7c9e345e657 Mon Sep 17 00:00:00 2001 From: Sergey Naumov Date: Thu, 21 Apr 2016 06:55:26 +0300 Subject: [PATCH 04/16] Doc-comments fix --- include/i3ipc++/ipc-util.hpp | 10 ++--- include/i3ipc++/ipc.hpp | 86 ++++++++++++++++++------------------ 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/include/i3ipc++/ipc-util.hpp b/include/i3ipc++/ipc-util.hpp index b046eea..a25d3f8 100644 --- a/include/i3ipc++/ipc-util.hpp +++ b/include/i3ipc++/ipc-util.hpp @@ -23,9 +23,9 @@ namespace i3ipc { */ struct header_t { /* 6 = strlen(I3_IPC_MAGIC) */ - char magic[6]; /**< Magic string @see I3_IPC_MAGIC */ - uint32_t size; /**< Size of payload */ - uint32_t type; /**< Message type */ + char magic[6]; ///< Magic string @see I3_IPC_MAGIC + uint32_t size; ///< Size of payload + uint32_t type; ///< Message type } __attribute__ ((packed)); @@ -84,8 +84,8 @@ enum class ReplyType : uint32_t { * @brief i3 IPC message buffer */ struct buf_t { - uint32_t size; /**< @brief Size of whole buffer */ - uint8_t* data; /**< @brief Pointer to the message */ + uint32_t size; ///< @brief Size of whole buffer + uint8_t* data; ///< @brief Pointer to the message /** * @brief i3 IPC message header diff --git a/include/i3ipc++/ipc.hpp b/include/i3ipc++/ipc.hpp index ad6287a..15c66fd 100644 --- a/include/i3ipc++/ipc.hpp +++ b/include/i3ipc++/ipc.hpp @@ -27,44 +27,44 @@ std::string get_socketpath(); * Primitive of rectangle */ struct rect_t { - int x; /**< Position on X axis */ - int y; /**< Position on Y axis */ - int width; /**< Width of rectangle */ - int height; /**< Height of rectangle */ + int x; ///< Position on X axis + int y; ///< Position on Y axis + int width; ///< Width of rectangle + int height; ///< Height of rectangle }; /** * i3's workspace */ struct workspace_t { - int num; /**< Index of the worksapce */ - std::string name; /**< Name of the workspace */ - bool visible; /**< Is the workspace visible */ - bool focused; /**< Is the workspace is currently focused */ - bool urgent; /**< Is the workspace is urgent */ - rect_t rect; /**< A size of the workspace */ - std::string output; /**< An output of the workspace */ + int num; ///< Index of the worksapce + std::string name; ///< Name of the workspace + bool visible; ///< Is the workspace visible + bool focused; ///< Is the workspace is currently focused + bool urgent; ///< Is the workspace is urgent + rect_t rect; ///< A size of the workspace + std::string output; ///< An output of the workspace }; /** * i3's output */ struct output_t { - std::string name; /**< Name of the output */ - bool active; /**< Is the output currently active */ - std::string current_workspace; /**< Name of current workspace */ - rect_t rect; /**< Size of the output */ + std::string name; ///< Name of the output + bool active; ///< Is the output currently active + std::string current_workspace; ///< Name of current workspace + rect_t rect; ///< Size of the output }; /** * Version of i3 */ struct version_t { - std::string human_readable; /**< Human redable version string */ - std::string loaded_config_file_name; /**< Path to current config of i3 */ - uint32_t major; /**< Major version of i3 */ - uint32_t minor; /**< Minor version of i3 */ - uint32_t patch; /**< Patch number of i3 */ + std::string human_readable; ///< Human redable version string + std::string loaded_config_file_name; ///< Path to current config of i3 + uint32_t major; ///< Major version of i3 + uint32_t minor; ///< Minor version of i3 + uint32_t patch; ///< Patch number of i3 }; @@ -72,35 +72,35 @@ struct version_t { * Types of the events of i3 */ enum EventType { - ET_WORKSPACE = (1 << 0), /**< Workspace event */ - ET_OUTPUT = (1 << 1), /**< Output event */ - ET_MODE = (1 << 2), /**< Output mode event */ - ET_WINDOW = (1 << 3), /**< Window event */ - ET_BARCONFIG_UPDATE = (1 << 4), /**< Bar config update event @attention Yet is not implemented as signal in I3Connection */ + ET_WORKSPACE = (1 << 0), ///< Workspace event + ET_OUTPUT = (1 << 1), ///< Output event + ET_MODE = (1 << 2), ///< Output mode event + ET_WINDOW = (1 << 3), ///< Window event + ET_BARCONFIG_UPDATE = (1 << 4), ///< Bar config update event @attention Yet is not implemented as signal in I3Connection }; /** * Types of workspace events */ enum class WorkspaceEventType : char { - FOCUS = 'f', /**< Focused */ - INIT = 'i', /**< Initialized */ - EMPTY = 'e', /**< Became empty */ - URGENT = 'u', /**< Became urgent */ + FOCUS = 'f', ///< Focused + INIT = 'i', ///< Initialized + EMPTY = 'e', ///< Became empty + URGENT = 'u', ///< Became urgent }; /** * Types of window events */ enum class WindowEventType : char { - NEW = 'n', /**< Window created */ - CLOSE = 'c', /**< Window closed */ - FOCUS = 'f', /**< Window got focus */ - TITLE = 't', /**< Title of window has been changed */ - FULLSCREEN_MODE = 'F', /**< Window toggled to fullscreen mode */ - MOVE = 'M', /**< Window moved */ - FLOATING = '_', /**< Window toggled floating mode */ - URGENT = 'u', /**< Window became urgent */ + NEW = 'n', ///< Window created + CLOSE = 'c', ///< Window closed + FOCUS = 'f', ///< Window got focus + TITLE = 't', ///< Title of window has been changed + FULLSCREEN_MODE = 'F', ///< Window toggled to fullscreen mode + MOVE = 'M', ///< Window moved + FLOATING = '_', ///< Window toggled floating mode + URGENT = 'u', ///< Window became urgent }; @@ -226,12 +226,12 @@ public: */ void handle_event(); - sigc::signal signal_workspace_event; /**< Workspace event signal */ - sigc::signal signal_output_event; /**< Output event signal */ - sigc::signal signal_mode_event; /**< Output mode event signal */ - sigc::signal signal_window_event; /**< Window event signal */ - sigc::signal signal_barconfig_update_event; /**< Barconfig update event signal */ - sigc::signal&> signal_event; /**< i3 event signal @note Default handler routes event to signal according to type */ + sigc::signal signal_workspace_event; ///< Workspace event signal + sigc::signal signal_output_event; ///< Output event signal + sigc::signal signal_mode_event; ///< Output mode event signal + sigc::signal signal_window_event; ///< Window event signal + sigc::signal signal_barconfig_update_event; ///< Barconfig update event signal + sigc::signal&> signal_event; ///< i3 event signal @note Default handler routes event to signal according to type private: const int32_t m_main_socket; int32_t m_event_socket; From 2d69c454957eddac0ce0df266ab872070b0ba66f Mon Sep 17 00:00:00 2001 From: Sergey Naumov Date: Thu, 21 Apr 2016 07:06:19 +0300 Subject: [PATCH 05/16] i3ipc::I3Connection renamed to i3ipc::connection --- examples/workspaces.cpp | 2 +- include/i3ipc++/ipc.hpp | 15 ++++++++++----- src/ipc.cpp | 20 ++++++++++---------- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/examples/workspaces.cpp b/examples/workspaces.cpp index 5b63483..acde6fa 100644 --- a/examples/workspaces.cpp +++ b/examples/workspaces.cpp @@ -28,7 +28,7 @@ void dump_tree_container(const i3ipc::container_t& c, std::string& prefix) { int main() { - i3ipc::I3Connection conn; + i3ipc::connection conn; for (auto& w : conn.get_workspaces()) { std::cout << '#' << std::hex << w.num << std::dec << "\n\tName: " << w.name diff --git a/include/i3ipc++/ipc.hpp b/include/i3ipc++/ipc.hpp index 15c66fd..50c535e 100644 --- a/include/i3ipc++/ipc.hpp +++ b/include/i3ipc++/ipc.hpp @@ -76,7 +76,7 @@ enum EventType { ET_OUTPUT = (1 << 1), ///< Output event ET_MODE = (1 << 2), ///< Output mode event ET_WINDOW = (1 << 3), ///< Window event - ET_BARCONFIG_UPDATE = (1 << 4), ///< Bar config update event @attention Yet is not implemented as signal in I3Connection + ET_BARCONFIG_UPDATE = (1 << 4), ///< Bar config update event @attention Yet is not implemented as signal in connection }; /** @@ -153,18 +153,23 @@ struct container_t { std::list< std::shared_ptr > nodes; }; +/** + * @deprecated + */ +typedef class connection I3Connection; + struct buf_t; /** * Connection to the i3 */ -class I3Connection { +class connection { public: /** * Connect to the i3 * @param socket_path path to a i3 IPC socket */ - I3Connection(const std::string& socket_path = get_socketpath()); - ~I3Connection(); + connection(const std::string& socket_path = get_socketpath()); + ~connection(); /** * Send a command to i3 @@ -205,7 +210,7 @@ public: * * Example: * @code{.cpp} - * I3Connection conn; + * connection conn; * conn.subscribe(i3ipc::ipc::ET_WORKSPACE | i3ipc::ipc::ET_WINDOW); * @endcode * diff --git a/src/ipc.cpp b/src/ipc.cpp index 13fd63a..efdb34b 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -171,7 +171,7 @@ std::string get_socketpath() { } -I3Connection::I3Connection(const std::string& socket_path) : m_main_socket(i3_connect(socket_path)), m_event_socket(-1), m_subscriptions(0), m_socket_path(socket_path) { +connection::connection(const std::string& socket_path) : m_main_socket(i3_connect(socket_path)), m_event_socket(-1), m_subscriptions(0), m_socket_path(socket_path) { #define i3IPC_TYPE_STR "i3's event" signal_event.connect([this](EventType event_type, const std::shared_ptr& buf) { switch (event_type) { @@ -240,18 +240,18 @@ I3Connection::I3Connection(const std::string& socket_path) : m_main_socket(i3_c }); #undef i3IPC_TYPE_STR } -I3Connection::~I3Connection() { +connection::~connection() { i3_disconnect(m_main_socket); if (m_event_socket > 0) i3_disconnect(m_event_socket); } -void I3Connection::prepare_to_event_handling() { +void connection::prepare_to_event_handling() { m_event_socket = i3_connect(m_socket_path); this->subscribe(m_subscriptions); } -void I3Connection::handle_event() { +void connection::handle_event() { if (m_event_socket <= 0) { throw std::runtime_error("event_socket_fd <= 0"); } @@ -261,7 +261,7 @@ void I3Connection::handle_event() { } -bool I3Connection::subscribe(const int32_t events) { +bool connection::subscribe(const int32_t events) { #define i3IPC_TYPE_STR "SUBSCRIBE" if (m_event_socket <= 0) { m_subscriptions |= events; @@ -304,7 +304,7 @@ bool I3Connection::subscribe(const int32_t events) { } -version_t I3Connection::get_version() const { +version_t connection::get_version() const { #define i3IPC_TYPE_STR "GET_VERSION" auto buf = i3_msg(m_main_socket, ClientMessageType::GET_VERSION); Json::Value root; @@ -322,7 +322,7 @@ version_t I3Connection::get_version() const { } -std::shared_ptr I3Connection::get_tree() const { +std::shared_ptr connection::get_tree() const { #define i3IPC_TYPE_STR "GET_TREE" auto buf = i3_msg(m_main_socket, ClientMessageType::GET_TREE); Json::Value root; @@ -332,7 +332,7 @@ std::shared_ptr I3Connection::get_tree() const { } -std::vector I3Connection::get_outputs() const { +std::vector connection::get_outputs() const { #define i3IPC_TYPE_STR "GET_OUTPUTS" auto buf = i3_msg(m_main_socket, ClientMessageType::GET_OUTPUTS); Json::Value root; @@ -350,7 +350,7 @@ std::vector I3Connection::get_outputs() const { } -std::vector I3Connection::get_workspaces() const { +std::vector connection::get_workspaces() const { #define i3IPC_TYPE_STR "GET_WORKSPACES" auto buf = i3_msg(m_main_socket, ClientMessageType::GET_WORKSPACES); Json::Value root; @@ -368,7 +368,7 @@ std::vector I3Connection::get_workspaces() const { } -bool I3Connection::send_command(const std::string& command) const { +bool connection::send_command(const std::string& command) const { #define i3IPC_TYPE_STR "COMMAND" auto buf = i3_msg(m_main_socket, ClientMessageType::COMMAND, command); Json::Value root; From 2962a3cc7afc696344e1b6519c167cb2f8ff5d35 Mon Sep 17 00:00:00 2001 From: Sergey Naumov Date: Thu, 21 Apr 2016 17:35:45 +0300 Subject: [PATCH 06/16] Minor fix --- src/ipc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ipc.cpp b/src/ipc.cpp index efdb34b..db19ede 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -51,7 +51,7 @@ inline rect_t parse_rect_from_json(const Json::Value& value) { static std::shared_ptr parse_container_from_json(const Json::Value& o) { -#define i3IPC_TYPE_STR "GET_TREE" // FIXME +#define i3IPC_TYPE_STR "PARSE CONTAINER FROM JSON" std::shared_ptr container (new container_t()); IPC_JSON_ASSERT_TYPE_OBJECT(o, "o") From 19f9acb482a5d640e64ebf1d0b0bbfca3d15aad5 Mon Sep 17 00:00:00 2001 From: Sergey Naumov Date: Sun, 24 Apr 2016 10:33:19 +0300 Subject: [PATCH 07/16] Shipping heavy objects in std::shared_ptr --- examples/workspaces.cpp | 20 ++++++++++---------- include/i3ipc++/ipc.hpp | 4 ++-- src/ipc.cpp | 42 ++++++++++++++++++++--------------------- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/examples/workspaces.cpp b/examples/workspaces.cpp index acde6fa..174914c 100644 --- a/examples/workspaces.cpp +++ b/examples/workspaces.cpp @@ -30,17 +30,17 @@ void dump_tree_container(const i3ipc::container_t& c, std::string& prefix) { int main() { i3ipc::connection conn; for (auto& w : conn.get_workspaces()) { - std::cout << '#' << std::hex << w.num << std::dec - << "\n\tName: " << w.name - << "\n\tVisible: " << w.visible - << "\n\tFocused: " << w.focused - << "\n\tUrgent: " << w.urgent + std::cout << '#' << std::hex << w->num << std::dec + << "\n\tName: " << w->name + << "\n\tVisible: " << w->visible + << "\n\tFocused: " << w->focused + << "\n\tUrgent: " << w->urgent << "\n\tRect: " - << "\n\t\tX: " << w.rect.x - << "\n\t\tY: " << w.rect.y - << "\n\t\tWidth: " << w.rect.width - << "\n\t\tHeight: " << w.rect.height - << "\n\tOutput: " << w.output + << "\n\t\tX: " << w->rect.x + << "\n\t\tY: " << w->rect.y + << "\n\t\tWidth: " << w->rect.width + << "\n\t\tHeight: " << w->rect.height + << "\n\tOutput: " << w->output << std::endl; } std::string prefix_buf; diff --git a/include/i3ipc++/ipc.hpp b/include/i3ipc++/ipc.hpp index 50c535e..ab8eb91 100644 --- a/include/i3ipc++/ipc.hpp +++ b/include/i3ipc++/ipc.hpp @@ -182,13 +182,13 @@ public: * Request a list of workspaces * @return List of workspaces */ - std::vector get_workspaces() const; + std::vector< std::shared_ptr > get_workspaces() const; /** * Request a list of outputs * @return List of outputs */ - std::vector get_outputs() const; + std::vector< std::shared_ptr > get_outputs() const; /** * Request a version of i3 diff --git a/src/ipc.cpp b/src/ipc.cpp index db19ede..e4409f5 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -113,7 +113,7 @@ static std::shared_ptr parse_container_from_json(const Json::Value #undef i3IPC_TYPE_STR } -static workspace_t parse_workspace_from_json(const Json::Value& value) { +static std::shared_ptr parse_workspace_from_json(const Json::Value& value) { Json::Value num = value["num"]; Json::Value name = value["name"]; Json::Value visible = value["visible"]; @@ -122,29 +122,29 @@ static workspace_t parse_workspace_from_json(const Json::Value& value) { Json::Value rect = value["rect"]; Json::Value output = value["output"]; - return { - .num = num.asInt(), - .name = name.asString(), - .visible = visible.asBool(), - .focused = focused.asBool(), - .urgent = urgent.asBool(), - .rect = parse_rect_from_json(rect), - .output = output.asString(), - }; + std::shared_ptr p; + p->num = num.asInt(); + p->name = name.asString(); + p->visible = visible.asBool(); + p->focused = focused.asBool(); + p->urgent = urgent.asBool(); + p->rect = parse_rect_from_json(rect); + p->output = output.asString(); + return p; } -static output_t parse_output_from_json(const Json::Value& value) { +static std::shared_ptr parse_output_from_json(const Json::Value& value) { Json::Value name = value["name"]; Json::Value active = value["active"]; Json::Value current_workspace = value["current_workspace"]; Json::Value rect = value["rect"]; - return { - .name = name.asString(), - .active = active.asBool(), - .current_workspace = (current_workspace.isNull() ? std::string() : current_workspace.asString()), - .rect = parse_rect_from_json(rect), - }; + std::shared_ptr p; + p->name = name.asString(); + p->active = active.asBool(); + p->current_workspace = (current_workspace.isNull() ? std::string() : current_workspace.asString()); + p->rect = parse_rect_from_json(rect); + return p; } @@ -332,14 +332,14 @@ std::shared_ptr connection::get_tree() const { } -std::vector connection::get_outputs() const { +std::vector< std::shared_ptr > connection::get_outputs() const { #define i3IPC_TYPE_STR "GET_OUTPUTS" auto buf = i3_msg(m_main_socket, ClientMessageType::GET_OUTPUTS); Json::Value root; IPC_JSON_READ(root) IPC_JSON_ASSERT_TYPE_ARRAY(root, "root") - std::vector outputs; + std::vector< std::shared_ptr > outputs; for (auto w : root) { outputs.push_back(parse_output_from_json(w)); @@ -350,14 +350,14 @@ std::vector connection::get_outputs() const { } -std::vector connection::get_workspaces() const { +std::vector< std::shared_ptr > connection::get_workspaces() const { #define i3IPC_TYPE_STR "GET_WORKSPACES" auto buf = i3_msg(m_main_socket, ClientMessageType::GET_WORKSPACES); Json::Value root; IPC_JSON_READ(root) IPC_JSON_ASSERT_TYPE_ARRAY(root, "root") - std::vector workspaces; + std::vector< std::shared_ptr > workspaces; for (auto w : root) { workspaces.push_back(parse_workspace_from_json(w)); From b94c4653274d7179573c0c6384c011a4de2211d5 Mon Sep 17 00:00:00 2001 From: Sergey Naumov Date: Sun, 24 Apr 2016 10:40:43 +0300 Subject: [PATCH 08/16] Shipping all payload in workspace event --- include/i3ipc++/ipc.hpp | 13 ++++++++++++- src/ipc.cpp | 22 ++++++++++++++++------ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/include/i3ipc++/ipc.hpp b/include/i3ipc++/ipc.hpp index ab8eb91..584252d 100644 --- a/include/i3ipc++/ipc.hpp +++ b/include/i3ipc++/ipc.hpp @@ -153,6 +153,17 @@ struct container_t { std::list< std::shared_ptr > nodes; }; + +/** + * A workspace event + */ +struct workspace_event_t { + WorkspaceEventType type; + std::shared_ptr current; ///< Current focused workspace + std::shared_ptr old; ///< Old (previous) workspace @note With some WindowEventType could be null +}; + + /** * @deprecated */ @@ -231,7 +242,7 @@ public: */ void handle_event(); - sigc::signal signal_workspace_event; ///< Workspace event signal + sigc::signal signal_workspace_event; ///< Workspace event signal sigc::signal signal_output_event; ///< Output event signal sigc::signal signal_mode_event; ///< Output mode event signal sigc::signal signal_window_event; ///< Window event signal diff --git a/src/ipc.cpp b/src/ipc.cpp index e4409f5..b08d1dd 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -176,25 +176,35 @@ connection::connection(const std::string& socket_path) : m_main_socket(i3_conne signal_event.connect([this](EventType event_type, const std::shared_ptr& buf) { switch (event_type) { case ET_WORKSPACE: { - WorkspaceEventType type; + workspace_event_t ev; Json::Value root; IPC_JSON_READ(root); std::string change = root["change"].asString(); if (change == "focus") { - type = WorkspaceEventType::FOCUS; + ev.type = WorkspaceEventType::FOCUS; } else if (change == "init") { - type = WorkspaceEventType::INIT; + ev.type = WorkspaceEventType::INIT; } else if (change == "empty") { - type = WorkspaceEventType::EMPTY; + ev.type = WorkspaceEventType::EMPTY; } else if (change == "urgent") { - type = WorkspaceEventType::URGENT; + ev.type = WorkspaceEventType::URGENT; } else { I3IPC_WARN("Unknown workspace event type " << change) break; } I3IPC_DEBUG("WORKSPACE " << change) - signal_workspace_event.emit(type); + Json::Value current = root["current"]; + Json::Value old = root["current"]; + + if (!current.isNull()) { + ev.current = parse_workspace_from_json(current); + } + if (!old.isNull()) { + ev.old = parse_workspace_from_json(old); + } + + signal_workspace_event.emit(ev); break; } case ET_OUTPUT: From 61cd3686da8af50f237acffeb325e4ecbce77564 Mon Sep 17 00:00:00 2001 From: Sergey Naumov Date: Sun, 24 Apr 2016 10:47:31 +0300 Subject: [PATCH 09/16] Shipping all payload in window event --- include/i3ipc++/ipc.hpp | 11 ++++++++++- src/ipc.cpp | 25 +++++++++++++++---------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/include/i3ipc++/ipc.hpp b/include/i3ipc++/ipc.hpp index 584252d..a36b297 100644 --- a/include/i3ipc++/ipc.hpp +++ b/include/i3ipc++/ipc.hpp @@ -164,6 +164,15 @@ struct workspace_event_t { }; +/** + * A window event + */ +struct window_event_t { + WindowEventType type; + std::shared_ptr container; ///< A container event associated with @note With some WindowEventType could be null +}; + + /** * @deprecated */ @@ -245,7 +254,7 @@ public: sigc::signal signal_workspace_event; ///< Workspace event signal sigc::signal signal_output_event; ///< Output event signal sigc::signal signal_mode_event; ///< Output mode event signal - sigc::signal signal_window_event; ///< Window event signal + sigc::signal signal_window_event; ///< Window event signal sigc::signal signal_barconfig_update_event; ///< Barconfig update event signal sigc::signal&> signal_event; ///< i3 event signal @note Default handler routes event to signal according to type private: diff --git a/src/ipc.cpp b/src/ipc.cpp index b08d1dd..76714a9 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -216,30 +216,35 @@ connection::connection(const std::string& socket_path) : m_main_socket(i3_conne signal_mode_event.emit(); break; case ET_WINDOW: { - WindowEventType type; + window_event_t ev; Json::Value root; IPC_JSON_READ(root); std::string change = root["change"].asString(); if (change == "new") { - type = WindowEventType::NEW; + ev.type = WindowEventType::NEW; } else if (change == "close") { - type = WindowEventType::CLOSE; + ev.type = WindowEventType::CLOSE; } else if (change == "focus") { - type = WindowEventType::FOCUS; + ev.type = WindowEventType::FOCUS; } else if (change == "title") { - type = WindowEventType::TITLE; + ev.type = WindowEventType::TITLE; } else if (change == "fullscreen_mode") { - type = WindowEventType::FULLSCREEN_MODE; + ev.type = WindowEventType::FULLSCREEN_MODE; } else if (change == "move") { - type = WindowEventType::MOVE; + ev.type = WindowEventType::MOVE; } else if (change == "floating") { - type = WindowEventType::FLOATING; + ev.type = WindowEventType::FLOATING; } else if (change == "urgent") { - type = WindowEventType::URGENT; + ev.type = WindowEventType::URGENT; } I3IPC_DEBUG("WINDOW " << change) - signal_window_event.emit(type); + Json::Value container = root["container"]; + if (!container.isNull()) { + ev.container = parse_container_from_json(container); + } + + signal_window_event.emit(ev); break; } case ET_BARCONFIG_UPDATE: From ed49910c92862e5a5e70f88fe170f65f442635b9 Mon Sep 17 00:00:00 2001 From: Sergey Naumov Date: Sun, 24 Apr 2016 10:57:11 +0300 Subject: [PATCH 10/16] Removed alias I3Connection --- include/i3ipc++/ipc.hpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/include/i3ipc++/ipc.hpp b/include/i3ipc++/ipc.hpp index a36b297..198ad99 100644 --- a/include/i3ipc++/ipc.hpp +++ b/include/i3ipc++/ipc.hpp @@ -173,11 +173,6 @@ struct window_event_t { }; -/** - * @deprecated - */ -typedef class connection I3Connection; - struct buf_t; /** * Connection to the i3 From d110532fda37ccd7887db614175bd87525b1c8ff Mon Sep 17 00:00:00 2001 From: Sergey Naumov Date: Sun, 24 Apr 2016 10:59:39 +0300 Subject: [PATCH 11/16] Changelog update --- CHANGELOG | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 CHANGELOG diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..37a16fe --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,10 @@ +0.2.0 + + Implemented GET_TREE (i3ipc::connection::get_tree()) + + ~ Shipping all available payload with workspace and window events (issue #2) + ~ i3ipc::I3Connection renamed to i3ipc::connection + + ~ Internal refreactoring + + * Fixing failed build: Parts of a struct were initialised in wrong order, C99-style designated initialisers did not prevent this from causing an error [mox] + * Minor documentation and code fixies From f63bff821fb26280c3ee4092585289118e5d5c87 Mon Sep 17 00:00:00 2001 From: Sergey Naumov Date: Sun, 24 Apr 2016 11:15:26 +0300 Subject: [PATCH 12/16] Fix of SIGSEGV in parse_*_from_json functions --- src/ipc.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ipc.cpp b/src/ipc.cpp index 76714a9..687f169 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -52,6 +52,8 @@ inline rect_t parse_rect_from_json(const Json::Value& value) { static std::shared_ptr parse_container_from_json(const Json::Value& o) { #define i3IPC_TYPE_STR "PARSE CONTAINER FROM JSON" + if (o.isNull()) + return std::shared_ptr(); std::shared_ptr container (new container_t()); IPC_JSON_ASSERT_TYPE_OBJECT(o, "o") @@ -114,6 +116,8 @@ static std::shared_ptr parse_container_from_json(const Json::Value } static std::shared_ptr parse_workspace_from_json(const Json::Value& value) { + if (value.isNull()) + return std::shared_ptr(); Json::Value num = value["num"]; Json::Value name = value["name"]; Json::Value visible = value["visible"]; @@ -122,7 +126,7 @@ static std::shared_ptr parse_workspace_from_json(const Json::Value Json::Value rect = value["rect"]; Json::Value output = value["output"]; - std::shared_ptr p; + std::shared_ptr p (new workspace_t()); p->num = num.asInt(); p->name = name.asString(); p->visible = visible.asBool(); @@ -134,12 +138,14 @@ static std::shared_ptr parse_workspace_from_json(const Json::Value } static std::shared_ptr parse_output_from_json(const Json::Value& value) { + if (value.isNull()) + return std::shared_ptr(); Json::Value name = value["name"]; Json::Value active = value["active"]; Json::Value current_workspace = value["current_workspace"]; Json::Value rect = value["rect"]; - std::shared_ptr p; + std::shared_ptr p (new output_t()); p->name = name.asString(); p->active = active.asBool(); p->current_workspace = (current_workspace.isNull() ? std::string() : current_workspace.asString()); From c5735c4c1e444f285d81c9842a5259866ae13434 Mon Sep 17 00:00:00 2001 From: Sergey Naumov Date: Sun, 24 Apr 2016 11:15:47 +0300 Subject: [PATCH 13/16] Example of event handling --- examples/CMakeLists.txt | 3 +++ examples/events.cpp | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 examples/events.cpp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 3be1743..f7b7de7 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -15,3 +15,6 @@ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2") add_executable(workspaces workspaces.cpp) target_link_libraries(workspaces ${I3IPCpp_LIBRARIES}) + +add_executable(events events.cpp) +target_link_libraries(events ${I3IPCpp_LIBRARIES}) diff --git a/examples/events.cpp b/examples/events.cpp new file mode 100644 index 0000000..efcf81c --- /dev/null +++ b/examples/events.cpp @@ -0,0 +1,25 @@ +#include + +#include + + +int main() { + i3ipc::connection conn; + conn.subscribe(i3ipc::ET_WORKSPACE | i3ipc::ET_WINDOW); + + conn.signal_workspace_event.connect([](const i3ipc::workspace_event_t& ev) { + std::cout << "workspace_event: " << (char)ev.type << std::endl; + }); + conn.signal_window_event.connect([](const i3ipc::window_event_t& ev) { + std::cout << "window_event: " << (char)ev.type << std::endl; + }); + + // Don't forget this: + conn.prepare_to_event_handling(); + + while (true) { + conn.handle_event(); + } + + return 0; +} From fa0faab8d5a7898fc8d6e32fc449061d5abb70d8 Mon Sep 17 00:00:00 2001 From: Sergey Naumov Date: Sun, 24 Apr 2016 11:16:33 +0300 Subject: [PATCH 14/16] Changelog update --- CHANGELOG | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 37a16fe..75eb532 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +0.2.1 + + Added example of event handling + * Fixed SIGSEGV in parse_*_from_json functions + 0.2.0 + Implemented GET_TREE (i3ipc::connection::get_tree()) From d2d90107aa120401f0135c53e9fdc7821aae7ed8 Mon Sep 17 00:00:00 2001 From: notfound4 Date: Mon, 9 May 2016 21:04:12 +0200 Subject: [PATCH 15/16] Added a method to get access to the i3 file descriptor --- include/i3ipc++/ipc.hpp | 6 ++++++ src/ipc.cpp | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/include/i3ipc++/ipc.hpp b/include/i3ipc++/ipc.hpp index 198ad99..31e1c31 100644 --- a/include/i3ipc++/ipc.hpp +++ b/include/i3ipc++/ipc.hpp @@ -246,6 +246,12 @@ public: */ void handle_event(); + /** + * Get the file descriptor associated to i3. + * @return the file descriptor associated to i3, -1 if not created yet. + */ + int32_t get_file_descriptor(); + sigc::signal signal_workspace_event; ///< Workspace event signal sigc::signal signal_output_event; ///< Output event signal sigc::signal signal_mode_event; ///< Output mode event signal diff --git a/src/ipc.cpp b/src/ipc.cpp index 687f169..0bd20b6 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -410,4 +410,8 @@ bool connection::send_command(const std::string& command) const { #undef i3IPC_TYPE_STR } +int32_t connection::get_file_descriptor() { + return m_event_socket; +} + } From f8ca6b633f59347055c9b84482acaa96fbdcc493 Mon Sep 17 00:00:00 2001 From: Michael Hoang Date: Sat, 28 May 2016 22:46:52 +1000 Subject: [PATCH 16/16] Fix CMakeLists file --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 931a762..d956298 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ include_directories( ) link_directories( - ${SIBCPP_LIBRARY_DIRS} + ${SIGCPP_LIBRARY_DIRS} 3rd/jsoncpp/src/lib_json/ ) @@ -34,6 +34,7 @@ add_library(i3ipc++_static STATIC ${SRC}) set(I3IPCpp_LIBRARY_DIRS ${CMAKE_CURRENT_BINARY_DIR}) set(I3IPCpp_INCLUDE_DIRS + ${SIGCPP_INCLUDE_DIRS} 3rd/auss/include ${CMAKE_CURRENT_SOURCE_DIR}/include/ )