Compare commits
2 Commits
af4b373478
...
06c25ff838
Author | SHA1 | Date | |
---|---|---|---|
06c25ff838 | |||
5cbe15a899 |
87
src/client.h
87
src/client.h
@ -49,31 +49,118 @@ struct Client {
|
||||
bool is_pid_set;
|
||||
};
|
||||
|
||||
/**
|
||||
* Client functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Converts the position of `c` to a `XWindowChanges` structure.
|
||||
*/
|
||||
XWindowChanges wm_client_to_xwchanges(Client *c);
|
||||
|
||||
/**
|
||||
* Returns the client associated with `w`.
|
||||
* Returns NULL if it could not find the client.
|
||||
*/
|
||||
Client* wm_client_find(Wm* wm, Window w);
|
||||
|
||||
/**
|
||||
* Initializes a new Client.
|
||||
*/
|
||||
Client* wm_client_create(Wm *wm, Window w);
|
||||
|
||||
void wm_client_handle_window_types(Wm *wm, Client *c, XMapRequestEvent e);
|
||||
|
||||
/**
|
||||
* Unmaps `c->window` and `c->frame`.
|
||||
*/
|
||||
void wm_client_hide(Wm *wm, Client *c);
|
||||
|
||||
/**
|
||||
* Maps `c->window` and `c->frame`.
|
||||
*/
|
||||
void wm_client_show(Wm* wm, Client *c);
|
||||
|
||||
/**
|
||||
* Focuses `c`.
|
||||
*/
|
||||
void wm_client_focus(Wm* wm, Client *c);
|
||||
|
||||
/**
|
||||
* Focuses the client in the direction `dir`, relative to the current focused
|
||||
* client.
|
||||
*/
|
||||
void wm_client_focus_dir(Wm* wm, Client *c, int dir);
|
||||
|
||||
/**
|
||||
* Swaps the client in the direction `dir`, relative to the current focused
|
||||
* client.
|
||||
*/
|
||||
void wm_client_swap_dir(Wm* wm, Client *c, int dir);
|
||||
|
||||
/**
|
||||
* Frees `c`, and its dynamically allocated fields.
|
||||
*/
|
||||
void wm_client_free(Wm *wm, Client *c);
|
||||
|
||||
/**
|
||||
* Destroys the window and frame associated with `c`, frees `c`, and recalculates
|
||||
* the layout.
|
||||
*/
|
||||
void wm_client_kill(Wm *wm, Client *c);
|
||||
|
||||
/**
|
||||
* Sets the window property with the atom of `name`, with the value `data`.
|
||||
*/
|
||||
void wm_client_set_atom(Wm *wm, Client *c, const char *name, const unsigned char *data,
|
||||
Atom type, int nelements);
|
||||
|
||||
/**
|
||||
* Reads the window poperty with the atom of `name`, and returns the value
|
||||
* in `atom_ret`, and returns the number of read items in `nitems_ret`.
|
||||
*/
|
||||
Atom wm_client_get_atom(Wm *wm, Client *c, const char *name, unsigned char **atom_ret,
|
||||
unsigned long *nitems_ret);
|
||||
|
||||
|
||||
/**
|
||||
* Finds the client in the direction `dir` relative to `c`.
|
||||
*/
|
||||
Client* wm_client_get_dir_rel_c(Client *c, int dir);
|
||||
|
||||
/**
|
||||
* Returns the currently focused client.
|
||||
*/
|
||||
Client* wm_client_get_focused(Wm* wm);
|
||||
|
||||
/**
|
||||
* Draws border for client `c`.
|
||||
*/
|
||||
void wm_client_border(Wm* wm, Client *c);
|
||||
|
||||
/**
|
||||
* Draws focused border for client `c`.
|
||||
*/
|
||||
void wm_client_border_focused(Wm* wm, Client *c);
|
||||
|
||||
/**
|
||||
* Draws borders for all clients in `m`.
|
||||
*/
|
||||
void wm_monitor_clients_border(Wm* wm, Monitor *m);
|
||||
|
||||
/**
|
||||
* Returns true if `c` is focused, false if `c` is not focused.
|
||||
*/
|
||||
bool wm_client_is_focused(Wm* wm, Client *c);
|
||||
|
||||
/**
|
||||
* Draws server-side decorations for `c`.
|
||||
*/
|
||||
void wm_client_draw_frame(Wm *wm, Client *c);
|
||||
|
||||
/**
|
||||
* Draws server-side decorations for all clients in `m`.
|
||||
*/
|
||||
void wm_monitor_draw_all_clients_frame(Wm* wm, Monitor *m);
|
||||
|
||||
#endif
|
||||
|
43
src/util.c
43
src/util.c
@ -225,10 +225,8 @@ UIntArray* wm_nonempty_workspaces_to_strptrarray(Wm *wm)
|
||||
return ret;
|
||||
}
|
||||
|
||||
json_object* wm_state_to_json_object(Wm *wm, const char *prefixstr)
|
||||
json_object* wm_state_to_json_object(Wm *wm)
|
||||
{
|
||||
assert(prefixstr);
|
||||
|
||||
json_object *ret = json_object_new_object();
|
||||
|
||||
UIntArray *ws_str = wm_nonempty_workspaces_to_strptrarray(wm);
|
||||
@ -244,6 +242,7 @@ json_object* wm_state_to_json_object(Wm *wm, const char *prefixstr)
|
||||
free(ws_with_index->str);
|
||||
free(ws_with_index);
|
||||
}
|
||||
wm_uintarray_free(ws_str);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -258,7 +257,7 @@ void wm_log_state(Wm *wm, const char *prefixstr, const char* logfile)
|
||||
char prefix[WM_PREFIX_LEN + 32] = {0};
|
||||
snprintf(prefix, sizeof(prefix), "%lu:%s", time(NULL), prefixstr);
|
||||
|
||||
json_object *log_entry_obj = wm_state_to_json_object(wm, prefixstr);
|
||||
json_object *log_entry_obj = wm_state_to_json_object(wm);
|
||||
|
||||
int fd = -1;
|
||||
struct json_object *jobj = NULL;
|
||||
@ -503,14 +502,6 @@ UIntArray* wm_treenode_all_keyroots_index(TreeNode *node)
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool wm_nodes_are_equal(TreeNode *node1, TreeNode *node2)
|
||||
{
|
||||
if (node1->type != node2->type)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://github.com/timtadh/zhang-shasha
|
||||
void wm_treedist(TreeNode *tree1, TreeNode *tree2, size_t i, size_t j,
|
||||
UIntArray *dists, TreeEditDistanceCosts costs)
|
||||
@ -798,11 +789,12 @@ static void recursive_mkdir(char *path, mode_t mode)
|
||||
|
||||
void wm_logfile_init(const char *path)
|
||||
{
|
||||
char *dup = strdup(path);
|
||||
char *log_file_dir = dirname(dup);
|
||||
|
||||
if (access(path, F_OK) == 0) return;
|
||||
|
||||
char *dup = strdup(path);
|
||||
char *log_file_dir = dirname(dup);
|
||||
|
||||
int ret = access(log_file_dir, W_OK | R_OK);
|
||||
|
||||
if (ret == 0) {
|
||||
@ -987,16 +979,6 @@ void wm_tree_to_DOT(TreeNode *root, const char *filename)
|
||||
wm_nodearray_free(all_nodes);
|
||||
}
|
||||
|
||||
int wm_get_node_index(TreeNode *parent, unsigned int node_id)
|
||||
{
|
||||
for (size_t i = 0; i < parent->children->size; i++) {
|
||||
if (node_id == parent->children->nodes[i]->id)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void wm_treenode_remove_node(Wm *wm, TreeNode *root, TreeNode *node)
|
||||
{
|
||||
DEBUG_PRINT("%s\n", __func__);
|
||||
@ -1393,7 +1375,18 @@ void wm_logentries_free(UIntArray *entries)
|
||||
|
||||
for (size_t j = 0; j < entry->workspaces->size; j++) {
|
||||
TreeNode *node = entry->workspaces->nodes[j];
|
||||
if (node != NULL) wm_treenode_free(node);
|
||||
if (node == NULL) continue;
|
||||
|
||||
NodeArray *children = wm_postorder_traversal(node);
|
||||
for (size_t k = 0; k < children->size; k++) {
|
||||
if (children->nodes[k]->type == NODE_CLIENT) {
|
||||
free(children->nodes[k]->client->name);
|
||||
free(children->nodes[k]->client);
|
||||
}
|
||||
wm_treenode_free(children->nodes[k]);
|
||||
}
|
||||
|
||||
wm_nodearray_free(children);
|
||||
}
|
||||
|
||||
wm_nodearray_free(entry->workspaces);
|
||||
|
280
src/util.h
280
src/util.h
@ -77,76 +77,308 @@ typedef struct {
|
||||
UpdateCostFunction update_cost_function;
|
||||
} TreeEditDistanceCosts;
|
||||
|
||||
/**
|
||||
* Functions for NodeArray operations
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initializes a new NodeArray.
|
||||
*/
|
||||
NodeArray* wm_nodearray_new();
|
||||
void wm_nodearray_set(NodeArray *arr, size_t index, uint64_t value);
|
||||
|
||||
/**
|
||||
* Adds `node` to the end of `arr`. If the capacity is lower than the
|
||||
* new size, it resizes the array.
|
||||
*/
|
||||
void wm_nodearray_push(NodeArray *arr, TreeNode *node);
|
||||
|
||||
/**
|
||||
* Removes the last element, and returns it in `ret`.
|
||||
*/
|
||||
bool wm_nodearray_pop(NodeArray *arr, TreeNode **ret);
|
||||
|
||||
/**
|
||||
* Removes the first element, and returns it in `ret`.
|
||||
*/
|
||||
bool wm_nodearray_pop_front(NodeArray *arr, TreeNode **ret);
|
||||
|
||||
/**
|
||||
* Removes all elements from `arr`, and sets its size to 0.
|
||||
*/
|
||||
void wm_nodearray_clear(NodeArray *arr);
|
||||
|
||||
/**
|
||||
* Removes the element at the provided index. Returns true on success, false
|
||||
* on failure.
|
||||
*/
|
||||
bool wm_nodearray_remove(NodeArray *arr, size_t index);
|
||||
|
||||
/**
|
||||
* Frees the array.
|
||||
*/
|
||||
void wm_nodearray_free(NodeArray *arr);
|
||||
TreeNode* wm_nodearray_at(NodeArray *arr, size_t index);
|
||||
|
||||
/**
|
||||
* Functions for TreeNode operations
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initializes a new TreeNode.
|
||||
*/
|
||||
TreeNode* wm_treenode_new(NodeType type, TreeNode *parent);
|
||||
void wm_treenode_free(TreeNode *node);
|
||||
bool wm_treenode_is_empty(TreeNode *node);
|
||||
void wm_treenode_split_space(TreeNode *node, Rect *ret1, Rect *ret2);
|
||||
void wm_treenode_recalculate_space(TreeNode *node);
|
||||
void wm_treenode_swap(TreeNode *root, TreeNode *node1, TreeNode* node2);
|
||||
void wm_treenode_add_child(TreeNode *node, TreeNode *child);
|
||||
TreeNode* wm_treenode_remove_client(Wm *wm, TreeNode *root, Client *client);
|
||||
void wm_treenode_remove_node(Wm *wm, TreeNode *root, TreeNode *node);
|
||||
int wm_get_node_index(TreeNode *parent, unsigned int node_id);
|
||||
|
||||
/**
|
||||
* Frees `node`, and the `children` NodeArray field.
|
||||
*/
|
||||
void wm_treenode_free(TreeNode *node);
|
||||
|
||||
/**
|
||||
* Returns true if `node` has no children.
|
||||
*/
|
||||
bool wm_treenode_is_empty(TreeNode *node);
|
||||
|
||||
/**
|
||||
* Splits the available space between `ret1` and `ret2`, based on `node->type`.
|
||||
*/
|
||||
void wm_treenode_split_space(TreeNode *node, Rect *ret1, Rect *ret2);
|
||||
|
||||
/**
|
||||
* Asserts `node->children->size == 2`, and calls split_space on first and second
|
||||
* child.
|
||||
*/
|
||||
void wm_treenode_recalculate_space(TreeNode *node);
|
||||
|
||||
/**
|
||||
* Swaps the clients of the `node1` and `node2`.
|
||||
*/
|
||||
void wm_treenode_swap(TreeNode *root, TreeNode *node1, TreeNode* node2);
|
||||
|
||||
/**
|
||||
* Pushes child to `node->children`, and sets `child->parent` to node.
|
||||
*/
|
||||
void wm_treenode_add_child(TreeNode *node, TreeNode *child);
|
||||
|
||||
/**
|
||||
* Finds `client` in `root`, removes and frees the node associated with it,
|
||||
* and recalculates layout.
|
||||
*/
|
||||
TreeNode* wm_treenode_remove_client(Wm *wm, TreeNode *root, Client *client);
|
||||
|
||||
/**
|
||||
* Finds `node` in `root`, removes and frees it, and recalculates layout.
|
||||
*/
|
||||
void wm_treenode_remove_node(Wm *wm, TreeNode *root, TreeNode *node);
|
||||
|
||||
/**
|
||||
* Converts `tree` to DOT file format.
|
||||
* Use `dot <filename> -Tsvg > output.svg` to convert the DOT file to svg.
|
||||
*/
|
||||
void wm_tree_to_DOT(TreeNode *root, const char *filename);
|
||||
|
||||
/**
|
||||
* Converts `type` to a string, and writes it to `buf`.
|
||||
*/
|
||||
void wm_node_type_to_str(NodeType type, char *buf, size_t bufsize);
|
||||
|
||||
/**
|
||||
* Finds non empty workspaces, and converts them to JSON strings.
|
||||
* Return value: `UIntArray<WmWorkspaceToStrRet*>`
|
||||
*/
|
||||
UIntArray* wm_nonempty_workspaces_to_strptrarray(Wm *wm);
|
||||
|
||||
/**
|
||||
* Converts a string to NodeType.
|
||||
*/
|
||||
NodeType wm_node_type_from_str(char *buf, size_t bufsize);
|
||||
|
||||
/**
|
||||
* Converts `node` to a JSON string.
|
||||
*/
|
||||
char* wm_treenode_to_str(TreeNode *node);
|
||||
|
||||
/**
|
||||
* Converts `node` to a JSON string, and if DEBUG is defined, prints it to stderr.
|
||||
*/
|
||||
void wm_treenode_print(TreeNode *node);
|
||||
|
||||
/**
|
||||
* Parses a `json_object` to a TreeNode.
|
||||
*/
|
||||
TreeNode* wm_json_obj_to_treenode(struct json_object *jobj);
|
||||
|
||||
|
||||
/**
|
||||
* Functions for UIntArray operations
|
||||
* UIntArray can be used as a generic pointer container, if
|
||||
* `_Static_assert(sizeof(uint64_t) == sizeof(<pointer_type>), "")`.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initializes a new UIntArray.
|
||||
*/
|
||||
UIntArray* wm_uintarray_new();
|
||||
|
||||
/**
|
||||
* Asserts `index < arr->size`, and returns `arr->elements[index]`.
|
||||
*/
|
||||
uint64_t wm_uintarray_at(UIntArray *arr, size_t index);
|
||||
void wm_uintarray_set(UIntArray *arr, size_t index, uint64_t value);
|
||||
|
||||
/**
|
||||
* Adds `node` to the end of `arr`. If the capacity is lower than the
|
||||
* new size, it resizes the array.
|
||||
*/
|
||||
void wm_uintarray_push(UIntArray *arr, uint64_t element);
|
||||
|
||||
/**
|
||||
* Removes the last element, and returns it in `ret`.
|
||||
*/
|
||||
bool wm_uintarray_pop(UIntArray *arr, uint64_t *ret);
|
||||
|
||||
/**
|
||||
* Removes the first element, and returns it in `ret`.
|
||||
*/
|
||||
bool wm_uintarray_pop_front(UIntArray *arr, uint64_t *ret);
|
||||
|
||||
/**
|
||||
* Removes the element at the provided index. Returns true on success, false
|
||||
* on failure.
|
||||
*/
|
||||
bool wm_uintarray_remove(UIntArray *arr, size_t index);
|
||||
|
||||
/**
|
||||
* Frees the array.
|
||||
*/
|
||||
void wm_uintarray_free(UIntArray *arr);
|
||||
|
||||
/**
|
||||
* Returns ((uint64_t**)arr->elements)[i][j].
|
||||
*/
|
||||
uint64_t wm_uintarray_2d_index(UIntArray *arr, size_t i, size_t j);
|
||||
|
||||
/**
|
||||
* TreeNode utility functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Find the node associated with the currently focused client, and returns it.
|
||||
* Returns NULL if no client is focused.
|
||||
*/
|
||||
TreeNode* wm_treenode_ptr_find_focused_client_node(TreeNode *root);
|
||||
|
||||
/**
|
||||
* Find the node associated with `client`, and returns it.
|
||||
* Returns NULL if it could not find `client`.
|
||||
*/
|
||||
TreeNode* wm_treenode_ptr_find_client_node(TreeNode *root, Client *client);
|
||||
|
||||
/**
|
||||
* Returns all `NODE_CLIENT` type descendant nodes of `root`.
|
||||
*/
|
||||
NodeArray* wm_treenode_find_client_nodes(TreeNode *root);
|
||||
|
||||
/**
|
||||
* Returns the sibling node of `node`.
|
||||
* Returns NULL on error.
|
||||
*/
|
||||
TreeNode* wm_treenode_split_get_sibling(TreeNode *node);
|
||||
|
||||
/**
|
||||
* Returns descendant nodes of `root`.
|
||||
*/
|
||||
NodeArray* wm_all_nodes_to_array(TreeNode *root);
|
||||
json_object* wm_state_to_json_object(Wm *wm, const char *prefixstr);
|
||||
|
||||
/**
|
||||
* Converts all non empty workspace trees to a `json_object`.
|
||||
*/
|
||||
json_object* wm_state_to_json_object(Wm *wm);
|
||||
|
||||
/**
|
||||
* Writes current state encoded as JSON to logfile.
|
||||
* If logfile exists, and is not empty, appends the state to the JSON object in
|
||||
* logfile.
|
||||
*/
|
||||
void wm_log_state(Wm *wm, const char *prefixstr, const char* logfile);
|
||||
|
||||
TreeNode* wm_treenode_lmd(TreeNode *node);
|
||||
NodeArray* wm_treenode_all_lmds(TreeNode *node);
|
||||
UIntArray* wm_treenode_all_lmds_index(TreeNode *node);
|
||||
NodeArray* wm_postorder_traversal(TreeNode *tree);
|
||||
bool wm_is_treenode_keyroot(TreeNode *node, NodeArray *postorder);
|
||||
NodeArray* wm_treenode_all_keyroots(TreeNode *node);
|
||||
UIntArray* wm_treenode_all_keyroots_index(TreeNode *node);
|
||||
bool wm_nodes_are_equal(TreeNode *node1, TreeNode *node2);
|
||||
|
||||
/**
|
||||
* Utility functions for tree edit distance
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the leftmost descendant of `node`.
|
||||
*/
|
||||
TreeNode* wm_treenode_lmd(TreeNode *node);
|
||||
|
||||
/**
|
||||
* Returns all leftmost descendants of `node`.
|
||||
*/
|
||||
NodeArray* wm_treenode_all_lmds(TreeNode *node);
|
||||
|
||||
/**
|
||||
* Returns all leftmost descendants of `node`, as indexes of a postorder
|
||||
* traversal array.
|
||||
*/
|
||||
UIntArray* wm_treenode_all_lmds_index(TreeNode *node);
|
||||
|
||||
/**
|
||||
* Returns all nodes of `tree`, in postorder traversal order.
|
||||
*/
|
||||
NodeArray* wm_postorder_traversal(TreeNode *tree);
|
||||
|
||||
/**
|
||||
* Returns true of `node` is a keyroot.
|
||||
* LR_keyroots(T) = {k | there exists no k’ > k such that l(k)= l(k’)}.
|
||||
* l = leftmost descendant
|
||||
*/
|
||||
bool wm_is_treenode_keyroot(TreeNode *node, NodeArray *postorder);
|
||||
|
||||
/**
|
||||
* Returns all keyroots of `node`.
|
||||
*/
|
||||
NodeArray* wm_treenode_all_keyroots(TreeNode *node);
|
||||
|
||||
/**
|
||||
* Returns all keyroots of `node`, as indexes of a postorder traversal array.
|
||||
*/
|
||||
UIntArray* wm_treenode_all_keyroots_index(TreeNode *node);
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the distance of the subtrees of `tree1` and `tree2`, at indexes
|
||||
* `i` and `j`.
|
||||
*/
|
||||
void wm_treedist(TreeNode *tree1, TreeNode *tree2, size_t i, size_t j,
|
||||
UIntArray *dists, TreeEditDistanceCosts costs);
|
||||
|
||||
/**
|
||||
* Calculates the distance of `tree1` and `tree2` using the edit costs `costs`.
|
||||
*/
|
||||
size_t wm_tree_edit_distance(TreeNode *tree1, TreeNode *tree2, TreeEditDistanceCosts costs);
|
||||
|
||||
/**
|
||||
* Creates the logfile at the provided path.
|
||||
*/
|
||||
void wm_logfile_init(const char *path);
|
||||
|
||||
/* UIntArray<LogEntry*> */
|
||||
/**
|
||||
* Frees all dynamically allocated fields of the array elements, and frees the
|
||||
* array.
|
||||
* Type of `entries`: UIntArray<LogEntry*>
|
||||
*/
|
||||
void wm_logentries_free(UIntArray *entries);
|
||||
|
||||
/* UIntArray<LogEntry*> */
|
||||
/**
|
||||
* Parses the JSON objects in the file at path `filename`, and populates a LogEntry*
|
||||
* array with the parsed values.
|
||||
* Return type: UIntArray<LogEntry*>
|
||||
*/
|
||||
UIntArray* wm_read_log(const char* filename);
|
||||
|
||||
/* UIntArray<LogEntry*> */
|
||||
/**
|
||||
* Calculates the tree edit distance of `log_entries[i]` and `curr_tree`.
|
||||
* Stores the distance in `log_entries[i]->workspaces[j]->tree->distance`.
|
||||
* Type of `log_entries`: UIntArray<LogEntry*>
|
||||
*/
|
||||
void wm_logentries_calculate_distances(UIntArray *log_entries, TreeNode *curr_tree,
|
||||
UpdateCostFunction update_cost_function);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user