Inital
This commit is contained in:
160
include/ipc-util.hpp
Normal file
160
include/ipc-util.hpp
Normal file
@@ -0,0 +1,160 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
// extern "C" {
|
||||
// #include <i3/ipc.h>
|
||||
// }
|
||||
|
||||
namespace i3ipc {
|
||||
|
||||
/** @defgroup i3ipc_util i3 IPC internal utilities
|
||||
* Stuff for internal usage in I3Connection
|
||||
* @{
|
||||
*/
|
||||
|
||||
// extern "C" {
|
||||
|
||||
/**
|
||||
* i3 IPC header
|
||||
*/
|
||||
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 */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/**
|
||||
* @brief Base class of i3 IPC errors
|
||||
*/
|
||||
class ipc_error : public std::runtime_error { using std::runtime_error::runtime_error; };
|
||||
|
||||
/**
|
||||
* @brief Something wrong in message header (wrong magic number, message type etc.)
|
||||
*/
|
||||
class invalid_header_error : public ipc_error { using ipc_error::ipc_error; };
|
||||
|
||||
/**
|
||||
* @brief Socket return EOF, but expected a data
|
||||
*/
|
||||
class eof_error : public ipc_error { using ipc_error::ipc_error; };
|
||||
|
||||
/**
|
||||
* @brief If something wrong in a payload of i3's reply
|
||||
*/
|
||||
class invalid_reply_payload_error : public ipc_error { using ipc_error::ipc_error; };
|
||||
|
||||
|
||||
/**
|
||||
* @brief Messages (requests), that can be sended from the client
|
||||
*/
|
||||
enum class ClientMessageType : uint32_t {
|
||||
COMMAND = 0,
|
||||
GET_WORKSPACES = 1,
|
||||
SUBSCRIBE = 2,
|
||||
GET_OUTPUTS = 3,
|
||||
GET_TREE = 4,
|
||||
GET_MARKS = 5,
|
||||
GET_BAR_CONFIG = 6,
|
||||
GET_VERSION = 7,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Replies, that can be sended from the i3 to the client
|
||||
*/
|
||||
enum class ReplyType : uint32_t {
|
||||
COMMAND = 0,
|
||||
WORKSPACES = 1,
|
||||
SUBSCRIBE = 2,
|
||||
OUTPUTS = 3,
|
||||
TREE = 4,
|
||||
MARKS = 5,
|
||||
BAR_CONFIG = 6,
|
||||
VERSION = 7,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief i3 IPC message buffer
|
||||
*/
|
||||
struct buf_t {
|
||||
uint32_t size; /**< @brief Size of whole buffer */
|
||||
uint8_t* data; /**< @brief Pointer to the message */
|
||||
|
||||
/**
|
||||
* @brief i3 IPC message header
|
||||
*
|
||||
* Pointing on the begining
|
||||
*/
|
||||
header_t* header;
|
||||
|
||||
/**
|
||||
* @brief Message payload
|
||||
*
|
||||
* Pointing on the byte after the header
|
||||
*/
|
||||
char* payload;
|
||||
|
||||
buf_t(uint32_t payload_size);
|
||||
~buf_t();
|
||||
|
||||
/**
|
||||
* @brief Resize payload to the payload_size in the header
|
||||
*/
|
||||
void realloc_payload_to_header();
|
||||
};
|
||||
|
||||
/**
|
||||
* Connect to the i3 socket
|
||||
* @param socket_path a socket path
|
||||
* @return socket id
|
||||
*/
|
||||
int32_t i3_connect(const std::string& socket_path);
|
||||
|
||||
/**
|
||||
* @brief Close the connection
|
||||
* @param sockfd socket
|
||||
*/
|
||||
void i3_disconnect(const int32_t sockfd);
|
||||
|
||||
/**
|
||||
* @brief Send message to the socket
|
||||
* @param sockfd a socket
|
||||
* @param buff a message
|
||||
*/
|
||||
void i3_send(const int32_t sockfd, const buf_t& buff);
|
||||
|
||||
/**
|
||||
* @brief Recive a message from i3
|
||||
* @param sockfd a socket
|
||||
* @return a buffer of the message
|
||||
*/
|
||||
std::shared_ptr<buf_t> i3_recv(const int32_t sockfd) throw (invalid_header_error, eof_error);
|
||||
|
||||
/**
|
||||
* @brief Pack a buffer of message
|
||||
*/
|
||||
std::shared_ptr<buf_t> i3_pack(const ClientMessageType type, const std::string& payload);
|
||||
|
||||
/**
|
||||
* @brief Pack, send a message and receiv a reply
|
||||
*
|
||||
* Almost same to:
|
||||
* @code{.cpp}
|
||||
* i3_send(sockfd, i3_pack(type, payload));
|
||||
* auto reply = i3_recv(sockfd);
|
||||
* @endcode
|
||||
*/
|
||||
std::shared_ptr<buf_t> i3_msg(const int32_t sockfd, const ClientMessageType type, const std::string& payload = std::string()) throw (invalid_header_error, eof_error);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
}
|
||||
189
include/ipc.hpp
Normal file
189
include/ipc.hpp
Normal file
@@ -0,0 +1,189 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <sigc++/sigc++.h>
|
||||
|
||||
extern "C" {
|
||||
#include <i3/ipc.h>
|
||||
}
|
||||
|
||||
/**
|
||||
* @addtogroup i3ipc i3 IPC C++ binding
|
||||
* @{
|
||||
*/
|
||||
namespace i3ipc {
|
||||
|
||||
/**
|
||||
* Get path to the i3 IPC socket
|
||||
* @return Path to a socket
|
||||
*/
|
||||
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 */
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
};
|
||||
|
||||
/**
|
||||
* Types of workspace events
|
||||
*/
|
||||
enum class WorkspaceEventType : char {
|
||||
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 */
|
||||
};
|
||||
|
||||
struct buf_t;
|
||||
/**
|
||||
* Connection to the i3
|
||||
*/
|
||||
class I3Connection {
|
||||
public:
|
||||
/**
|
||||
* Connect to the i3
|
||||
* @param socket_path path to a i3 IPC socket
|
||||
*/
|
||||
I3Connection(const std::string& socket_path = get_socketpath());
|
||||
~I3Connection();
|
||||
|
||||
/**
|
||||
* Send a command to i3
|
||||
* @param command command
|
||||
* @return Is command successfully executed
|
||||
*/
|
||||
bool send_command(const std::string& command) const;
|
||||
|
||||
/**
|
||||
* Request a list of workspaces
|
||||
* @return List of workspaces
|
||||
*/
|
||||
std::vector<workspace_t> get_workspaces() const;
|
||||
|
||||
/**
|
||||
* Request a list of outputs
|
||||
* @return List of outputs
|
||||
*/
|
||||
std::vector<output_t> get_outputs() const;
|
||||
|
||||
/**
|
||||
* Request a version of i3
|
||||
* @return Version of i3
|
||||
*/
|
||||
version_t get_version() const;
|
||||
|
||||
/**
|
||||
* Subscribe on an events of i3
|
||||
*
|
||||
* If connection isn't handling events at the moment, event numer will be added to subscription list.
|
||||
* Else will also send subscripe request to i3
|
||||
*
|
||||
* Example:
|
||||
* @code{.cpp}
|
||||
* I3Connection conn;
|
||||
* conn.subscribe(lebar::ipc::ET_WORKSPACE | lebar::ipc::ET_WINDOW);
|
||||
* @endcode
|
||||
*
|
||||
* @param events event type (EventType enum)
|
||||
* @return Is successfully subscribed. If connection isn't handling events at the moment, then always true.
|
||||
*/
|
||||
bool subscribe(const int32_t events);
|
||||
|
||||
/**
|
||||
* Prepare connection to the handling of i3's events
|
||||
* @note Used only in main()
|
||||
*/
|
||||
void prepare_to_event_handling();
|
||||
|
||||
/**
|
||||
* Handle an event from i3
|
||||
* @note Used only in main()
|
||||
*/
|
||||
void handle_event();
|
||||
|
||||
sigc::signal<void, WorkspaceEventType> signal_workspace_event; /**< Workspace event signal */
|
||||
sigc::signal<void> signal_output_event; /**< Output event signal */
|
||||
sigc::signal<void> signal_mode_event; /**< Output mode event signal */
|
||||
sigc::signal<void, WindowEventType> signal_window_event; /**< Window event signal */
|
||||
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:
|
||||
const int32_t m_main_socket;
|
||||
int32_t m_event_socket;
|
||||
int32_t m_subscriptions;
|
||||
const std::string m_socket_path;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
Reference in New Issue
Block a user