Did the merge work?

This commit is contained in:
mox
2016-06-11 14:33:54 +02:00
8 changed files with 382 additions and 135 deletions

14
CHANGELOG Normal file
View File

@@ -0,0 +1,14 @@
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())
~ 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

View File

@@ -29,7 +29,7 @@ include_directories(
) )
link_directories( link_directories(
${SIBCPP_LIBRARY_DIRS} ${SIGCPP_LIBRARY_DIRS}
3rd/jsoncpp/src/lib_json/ 3rd/jsoncpp/src/lib_json/
) )
@@ -42,6 +42,7 @@ add_library(i3ipc++_static STATIC ${SRC})
set(I3IPCpp_LIBRARY_DIRS ${CMAKE_CURRENT_BINARY_DIR}) set(I3IPCpp_LIBRARY_DIRS ${CMAKE_CURRENT_BINARY_DIR})
set(I3IPCpp_INCLUDE_DIRS set(I3IPCpp_INCLUDE_DIRS
${SIGCPP_INCLUDE_DIRS}
3rd/auss/include 3rd/auss/include
${CMAKE_CURRENT_SOURCE_DIR}/include/ ${CMAKE_CURRENT_SOURCE_DIR}/include/
) )

View File

@@ -15,3 +15,6 @@ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2")
add_executable(workspaces workspaces.cpp) add_executable(workspaces workspaces.cpp)
target_link_libraries(workspaces ${I3IPCpp_LIBRARIES}) target_link_libraries(workspaces ${I3IPCpp_LIBRARIES})
add_executable(events events.cpp)
target_link_libraries(events ${I3IPCpp_LIBRARIES})

25
examples/events.cpp Normal file
View File

@@ -0,0 +1,25 @@
#include <iostream>
#include <i3ipc++/ipc.hpp>
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;
}

View File

@@ -2,21 +2,49 @@
#include <i3ipc++/ipc.hpp> #include <i3ipc++/ipc.hpp>
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() { int main() {
i3ipc::I3Connection conn; i3ipc::connection conn;
for (auto& w : conn.get_workspaces()) { for (auto& w : conn.get_workspaces()) {
std::cout << '#' << std::hex << w.num << std::dec std::cout << '#' << std::hex << w->num << std::dec
<< "\n\tName: " << w.name << "\n\tName: " << w->name
<< "\n\tVisible: " << w.visible << "\n\tVisible: " << w->visible
<< "\n\tFocused: " << w.focused << "\n\tFocused: " << w->focused
<< "\n\tUrgent: " << w.urgent << "\n\tUrgent: " << w->urgent
<< "\n\tRect: " << "\n\tRect: "
<< "\n\t\tX: " << w.rect.x << "\n\t\tX: " << w->rect.x
<< "\n\t\tY: " << w.rect.y << "\n\t\tY: " << w->rect.y
<< "\n\t\tWidth: " << w.rect.width << "\n\t\tWidth: " << w->rect.width
<< "\n\t\tHeight: " << w.rect.height << "\n\t\tHeight: " << w->rect.height
<< "\n\tOutput: " << w.output << "\n\tOutput: " << w->output
<< std::endl; << std::endl;
} }
std::string prefix_buf;
dump_tree_container(*conn.get_tree(), prefix_buf);
return 0; return 0;
} }

View File

@@ -23,9 +23,9 @@ namespace i3ipc {
*/ */
struct header_t { struct header_t {
/* 6 = strlen(I3_IPC_MAGIC) */ /* 6 = strlen(I3_IPC_MAGIC) */
char magic[6]; /**< Magic string @see I3_IPC_MAGIC */ char magic[6]; ///< Magic string @see I3_IPC_MAGIC
uint32_t size; /**< Size of payload */ uint32_t size; ///< Size of payload
uint32_t type; /**< Message type */ uint32_t type; ///< Message type
} __attribute__ ((packed)); } __attribute__ ((packed));
@@ -84,8 +84,8 @@ enum class ReplyType : uint32_t {
* @brief i3 IPC message buffer * @brief i3 IPC message buffer
*/ */
struct buf_t { struct buf_t {
uint32_t size; /**< @brief Size of whole buffer */ uint32_t size; ///< @brief Size of whole buffer
uint8_t* data; /**< @brief Pointer to the message */ uint8_t* data; ///< @brief Pointer to the message
/** /**
* @brief i3 IPC message header * @brief i3 IPC message header

View File

@@ -33,55 +33,56 @@ std::string get_socketpath();
* Primitive of rectangle * Primitive of rectangle
*/ */
struct rect_t { struct rect_t {
int x; /**< Position on X axis */ int x; ///< Position on X axis
int y; /**< Position on Y axis */ int y; ///< Position on Y axis
int width; /**< Width of rectangle */ int width; ///< Width of rectangle
int height; /**< Height of rectangle */ int height; ///< Height of rectangle
}; };
/** /**
* i3's workspace * i3's workspace
*/ */
struct workspace_t { struct workspace_t {
int num; /**< Index of the worksapce */ int num; ///< Index of the worksapce
std::string name; /**< Name of the workspace */ std::string name; ///< Name of the workspace
bool visible; /**< Is the workspace visible */ bool visible; ///< Is the workspace visible
bool focused; /**< Is the workspace is currently focused */ bool focused; ///< Is the workspace is currently focused
bool urgent; /**< Is the workspace is urgent */ bool urgent; ///< Is the workspace is urgent
rect_t rect; /**< A size of the workspace */ rect_t rect; ///< A size of the workspace
std::string output; /**< An output of the workspace */ std::string output; ///< An output of the workspace
}; };
/** /**
* i3's output * i3's output
*/ */
struct output_t { struct output_t {
std::string name; /**< Name of the output */ std::string name; ///< Name of the output
bool active; /**< Is the output currently active */ bool active; ///< Is the output currently active
std::string current_workspace; /**< Name of current workspace */ std::string current_workspace; ///< Name of current workspace
rect_t rect; /**< Size of the output */ rect_t rect; ///< Size of the output
}; };
/** /**
* Version of i3 * Version of i3
*/ */
struct version_t { struct version_t {
std::string human_readable; /**< Human redable version string */ std::string human_readable; ///< Human redable version string
std::string loaded_config_file_name; /**< Path to current config of i3 */ std::string loaded_config_file_name; ///< Path to current config of i3
uint32_t major; /**< Major version of i3 */ uint32_t major; ///< Major version of i3
uint32_t minor; /**< Minor version of i3 */ uint32_t minor; ///< Minor version of i3
uint32_t patch; /**< Patch number of i3 */ uint32_t patch; ///< Patch number of i3
}; };
/** /**
* Types of the events of i3 * Types of the events of i3
*/ */
enum EventType { enum EventType {
ET_WORKSPACE = (1 << 0), /**< Workspace event */ ET_WORKSPACE = (1 << 0), ///< Workspace event
ET_OUTPUT = (1 << 1), /**< Output event */ ET_OUTPUT = (1 << 1), ///< Output event
ET_MODE = (1 << 2), /**< Output mode event */ ET_MODE = (1 << 2), ///< Output mode event
ET_WINDOW = (1 << 3), /**< Window 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
}; };
#ifndef I3IPCpp_USE_FULL_SIGNALS #ifndef I3IPCpp_USE_FULL_SIGNALS
@@ -89,39 +90,109 @@ enum EventType {
* Types of workspace events * Types of workspace events
*/ */
enum class WorkspaceEventType : char { enum class WorkspaceEventType : char {
FOCUS = 'f', /**< Focused */ FOCUS = 'f', ///< Focused
INIT = 'i', /**< Initialized */ INIT = 'i', ///< Initialized
EMPTY = 'e', /**< Became empty */ EMPTY = 'e', ///< Became empty
URGENT = 'u', /**< Became urgent */ URGENT = 'u', ///< Became urgent
}; };
/** /**
* Types of window events * Types of window events
*/ */
enum class WindowEventType : char { enum class WindowEventType : char {
NEW = 'n', /**< Window created */ NEW = 'n', ///< Window created
CLOSE = 'c', /**< Window closed */ CLOSE = 'c', ///< Window closed
FOCUS = 'f', /**< Window got focus */ FOCUS = 'f', ///< Window got focus
TITLE = 't', /**< Title of window has been changed */ TITLE = 't', ///< Title of window has been changed
FULLSCREEN_MODE = 'F', /**< Window toggled to fullscreen mode */ FULLSCREEN_MODE = 'F', ///< Window toggled to fullscreen mode
MOVE = 'M', /**< Window moved */ MOVE = 'M', ///< Window moved
FLOATING = '_', /**< Window toggled floating mode */ FLOATING = '_', ///< Window toggled floating mode
URGENT = 'u', /**< Window became urgent */ 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<container_t> > nodes;
}; };
#endif #endif
/**
* A workspace event
*/
struct workspace_event_t {
WorkspaceEventType type;
std::shared_ptr<workspace_t> current; ///< Current focused workspace
std::shared_ptr<workspace_t> old; ///< Old (previous) workspace @note With some WindowEventType could be null
};
/**
* A window event
*/
struct window_event_t {
WindowEventType type;
std::shared_ptr<container_t> container; ///< A container event associated with @note With some WindowEventType could be null
};
struct buf_t; struct buf_t;
/** /**
* Connection to the i3 * Connection to the i3
*/ */
class I3Connection { class connection {
public: public:
/** /**
* Connect to the i3 * Connect to the i3
* @param socket_path path to a i3 IPC socket * @param socket_path path to a i3 IPC socket
*/ */
I3Connection(const std::string& socket_path = get_socketpath()); connection(const std::string& socket_path = get_socketpath());
~I3Connection(); ~connection();
/** /**
* Send a command to i3 * Send a command to i3
@@ -134,13 +205,13 @@ public:
* Request a list of workspaces * Request a list of workspaces
* @return List of workspaces * @return List of workspaces
*/ */
std::vector<workspace_t> get_workspaces() const; std::vector< std::shared_ptr<workspace_t> > get_workspaces() const;
/** /**
* Request a list of outputs * Request a list of outputs
* @return List of outputs * @return List of outputs
*/ */
std::vector<output_t> get_outputs() const; std::vector< std::shared_ptr<output_t> > get_outputs() const;
/** /**
* Request a version of i3 * Request a version of i3
@@ -148,6 +219,12 @@ public:
*/ */
version_t get_version() const; version_t get_version() const;
/**
* Request a tree of windows
* @return A root container
*/
std::shared_ptr<container_t> get_tree() const;
/** /**
* Subscribe on an events of i3 * Subscribe on an events of i3
* *
@@ -156,7 +233,7 @@ public:
* *
* Example: * Example:
* @code{.cpp} * @code{.cpp}
* I3Connection conn; * connection conn;
* conn.subscribe(i3ipc::ipc::ET_WORKSPACE | i3ipc::ipc::ET_WINDOW); * conn.subscribe(i3ipc::ipc::ET_WORKSPACE | i3ipc::ipc::ET_WINDOW);
* @endcode * @endcode
* *
@@ -177,17 +254,18 @@ public:
*/ */
void handle_event(); void handle_event();
sigc::signal<void> signal_output_event; /**< Output event signal */ /**
sigc::signal<void> signal_mode_event; /**< Output mode event signal */ * Get the file descriptor associated to i3.
sigc::signal<void> signal_barconfig_update_event; /**< Barconfig update event signal */ * @return the file descriptor associated to i3, -1 if not created yet.
#ifdef I3IPCpp_USE_FULL_SIGNALS */
sigc::signal<void, const Json::Value&> signal_workspace_event; /**< Workspace event signal */ int32_t get_file_descriptor();
sigc::signal<void, const Json::Value&> signal_window_event; /**< Window event signal */
#else sigc::signal<void, const workspace_event_t&> signal_workspace_event; ///< Workspace event signal
sigc::signal<void, WorkspaceEventType> signal_workspace_event; /**< Workspace event signal */ sigc::signal<void> signal_output_event; ///< Output event signal
sigc::signal<void, WindowEventType> signal_window_event; /**< Window event signal */ sigc::signal<void> signal_mode_event; ///< Output mode event signal
#endif sigc::signal<void, const window_event_t&> signal_window_event; ///< Window event signal
sigc::signal<void, EventType, const std::shared_ptr<const buf_t>&> signal_event; /**< i3 event signal @note Default handler routes event to signal according to type */ sigc::signal<void> signal_barconfig_update_event; ///< Barconfig update event signal
sigc::signal<void, EventType, const std::shared_ptr<const buf_t>&> signal_event; ///< i3 event signal @note Default handler routes event to signal according to type
private: private:
const int32_t m_main_socket; const int32_t m_main_socket;
int32_t m_event_socket; int32_t m_event_socket;

View File

@@ -52,6 +52,110 @@ inline rect_t parse_rect_from_json(const Json::Value& value) {
} }
static std::shared_ptr<container_t> parse_container_from_json(const Json::Value& o) {
#define i3IPC_TYPE_STR "PARSE CONTAINER FROM JSON"
if (o.isNull())
return std::shared_ptr<container_t>();
std::shared_ptr<container_t> 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 std::shared_ptr<workspace_t> parse_workspace_from_json(const Json::Value& value) {
if (value.isNull())
return std::shared_ptr<workspace_t>();
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"];
std::shared_ptr<workspace_t> p (new workspace_t());
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 std::shared_ptr<output_t> parse_output_from_json(const Json::Value& value) {
if (value.isNull())
return std::shared_ptr<output_t>();
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<output_t> p (new output_t());
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;
}
std::string get_socketpath() { std::string get_socketpath() {
std::string str; std::string str;
{ {
@@ -74,35 +178,40 @@ std::string get_socketpath() {
return str; return str;
} }
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) {
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) {
#define i3IPC_TYPE_STR "i3's event" #define i3IPC_TYPE_STR "i3's event"
signal_event.connect([this](EventType event_type, const std::shared_ptr<const buf_t>& buf) { signal_event.connect([this](EventType event_type, const std::shared_ptr<const buf_t>& buf) {
switch (event_type) { switch (event_type) {
case ET_WORKSPACE: { case ET_WORKSPACE: {
workspace_event_t ev;
Json::Value root; Json::Value root;
IPC_JSON_READ(root); IPC_JSON_READ(root);
#ifdef I3IPCpp_USE_FULL_SIGNALS
signal_workspace_event.emit(root);
#else
WorkspaceEventType type;
std::string change = root["change"].asString(); std::string change = root["change"].asString();
if (change == "focus") { if (change == "focus") {
type = WorkspaceEventType::FOCUS; ev.type = WorkspaceEventType::FOCUS;
} else if (change == "init") { } else if (change == "init") {
type = WorkspaceEventType::INIT; ev.type = WorkspaceEventType::INIT;
} else if (change == "empty") { } else if (change == "empty") {
type = WorkspaceEventType::EMPTY; ev.type = WorkspaceEventType::EMPTY;
} else if (change == "urgent") { } else if (change == "urgent") {
type = WorkspaceEventType::URGENT; ev.type = WorkspaceEventType::URGENT;
} else { } else {
I3IPC_WARN("Unknown workspace event type " << change) I3IPC_WARN("Unknown workspace event type " << change)
break; break;
} }
I3IPC_DEBUG("WORKSPACE " << change) I3IPC_DEBUG("WORKSPACE " << change)
signal_workspace_event.emit(type); Json::Value current = root["current"];
#endif 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; break;
} }
case ET_OUTPUT: case ET_OUTPUT:
@@ -114,34 +223,35 @@ I3Connection::I3Connection(const std::string& socket_path) : m_main_socket(i3_c
signal_mode_event.emit(); signal_mode_event.emit();
break; break;
case ET_WINDOW: { case ET_WINDOW: {
window_event_t ev;
Json::Value root; Json::Value root;
IPC_JSON_READ(root); IPC_JSON_READ(root);
#ifdef I3IPCpp_USE_FULL_SIGNALS
signal_window_event.emit(root);
#else
WindowEventType type;
std::string change = root["change"].asString(); std::string change = root["change"].asString();
if (change == "new") { if (change == "new") {
type = WindowEventType::NEW; ev.type = WindowEventType::NEW;
} else if (change == "close") { } else if (change == "close") {
type = WindowEventType::CLOSE; ev.type = WindowEventType::CLOSE;
} else if (change == "focus") { } else if (change == "focus") {
type = WindowEventType::FOCUS; ev.type = WindowEventType::FOCUS;
} else if (change == "title") { } else if (change == "title") {
type = WindowEventType::TITLE; ev.type = WindowEventType::TITLE;
} else if (change == "fullscreen_mode") { } else if (change == "fullscreen_mode") {
type = WindowEventType::FULLSCREEN_MODE; ev.type = WindowEventType::FULLSCREEN_MODE;
} else if (change == "move") { } else if (change == "move") {
type = WindowEventType::MOVE; ev.type = WindowEventType::MOVE;
} else if (change == "floating") { } else if (change == "floating") {
type = WindowEventType::FLOATING; ev.type = WindowEventType::FLOATING;
} else if (change == "urgent") { } else if (change == "urgent") {
type = WindowEventType::URGENT; ev.type = WindowEventType::URGENT;
} }
I3IPC_DEBUG("WINDOW " << change) I3IPC_DEBUG("WINDOW " << change)
signal_window_event.emit(type); Json::Value container = root["container"];
#endif if (!container.isNull()) {
ev.container = parse_container_from_json(container);
}
signal_window_event.emit(ev);
break; break;
} }
case ET_BARCONFIG_UPDATE: case ET_BARCONFIG_UPDATE:
@@ -152,18 +262,18 @@ I3Connection::I3Connection(const std::string& socket_path) : m_main_socket(i3_c
}); });
#undef i3IPC_TYPE_STR #undef i3IPC_TYPE_STR
} }
I3Connection::~I3Connection() { connection::~connection() {
i3_disconnect(m_main_socket); i3_disconnect(m_main_socket);
if (m_event_socket > 0) if (m_event_socket > 0)
i3_disconnect(m_event_socket); 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); m_event_socket = i3_connect(m_socket_path);
this->subscribe(m_subscriptions); this->subscribe(m_subscriptions);
} }
void I3Connection::handle_event() { void connection::handle_event() {
if (m_event_socket <= 0) { if (m_event_socket <= 0) {
throw std::runtime_error("event_socket_fd <= 0"); throw std::runtime_error("event_socket_fd <= 0");
} }
@@ -173,7 +283,7 @@ void I3Connection::handle_event() {
} }
bool I3Connection::subscribe(const int32_t events) { bool connection::subscribe(const int32_t events) {
#define i3IPC_TYPE_STR "SUBSCRIBE" #define i3IPC_TYPE_STR "SUBSCRIBE"
if (m_event_socket <= 0) { if (m_event_socket <= 0) {
m_subscriptions |= events; m_subscriptions |= events;
@@ -216,7 +326,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" #define i3IPC_TYPE_STR "GET_VERSION"
auto buf = i3_msg(m_main_socket, ClientMessageType::GET_VERSION); auto buf = i3_msg(m_main_socket, ClientMessageType::GET_VERSION);
Json::Value root; Json::Value root;
@@ -234,27 +344,27 @@ version_t I3Connection::get_version() const {
} }
std::vector<output_t> I3Connection::get_outputs() const { std::shared_ptr<container_t> connection::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< std::shared_ptr<output_t> > connection::get_outputs() const {
#define i3IPC_TYPE_STR "GET_OUTPUTS" #define i3IPC_TYPE_STR "GET_OUTPUTS"
auto buf = i3_msg(m_main_socket, ClientMessageType::GET_OUTPUTS); auto buf = i3_msg(m_main_socket, ClientMessageType::GET_OUTPUTS);
Json::Value root; Json::Value root;
IPC_JSON_READ(root) IPC_JSON_READ(root)
IPC_JSON_ASSERT_TYPE_ARRAY(root, "root") IPC_JSON_ASSERT_TYPE_ARRAY(root, "root")
std::vector<output_t> outputs; std::vector< std::shared_ptr<output_t> > outputs;
for (auto w : root) { for (auto w : root) {
Json::Value name = w["name"]; outputs.push_back(parse_output_from_json(w));
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),
});
} }
return outputs; return outputs;
@@ -262,33 +372,17 @@ std::vector<output_t> I3Connection::get_outputs() const {
} }
std::vector<workspace_t> I3Connection::get_workspaces() const { std::vector< std::shared_ptr<workspace_t> > connection::get_workspaces() const {
#define i3IPC_TYPE_STR "GET_WORKSPACES" #define i3IPC_TYPE_STR "GET_WORKSPACES"
auto buf = i3_msg(m_main_socket, ClientMessageType::GET_WORKSPACES); auto buf = i3_msg(m_main_socket, ClientMessageType::GET_WORKSPACES);
Json::Value root; Json::Value root;
IPC_JSON_READ(root) IPC_JSON_READ(root)
IPC_JSON_ASSERT_TYPE_ARRAY(root, "root") IPC_JSON_ASSERT_TYPE_ARRAY(root, "root")
std::vector<workspace_t> workspaces; std::vector< std::shared_ptr<workspace_t> > workspaces;
for (auto w : root) { for (auto w : root) {
Json::Value num = w["num"]; workspaces.push_back(parse_workspace_from_json(w));
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(),
});
} }
return workspaces; return workspaces;
@@ -296,7 +390,7 @@ std::vector<workspace_t> 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" #define i3IPC_TYPE_STR "COMMAND"
auto buf = i3_msg(m_main_socket, ClientMessageType::COMMAND, command); auto buf = i3_msg(m_main_socket, ClientMessageType::COMMAND, command);
Json::Value root; Json::Value root;
@@ -317,4 +411,8 @@ bool I3Connection::send_command(const std::string& command) const {
#undef i3IPC_TYPE_STR #undef i3IPC_TYPE_STR
} }
int32_t connection::get_file_descriptor() {
return m_event_socket;
}
} }