Merge pull request #3168 from mihaicmn/scratchpad-events

Fix missing IPC scratchpad replies/move events
This commit is contained in:
Brian Ashworth 2018-11-26 12:02:27 -05:00 committed by GitHub
commit a22e7b13ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 184 additions and 104 deletions

View file

@ -15,6 +15,9 @@
#include <xkbcommon/xkbcommon.h> #include <xkbcommon/xkbcommon.h>
#include "wlr-layer-shell-unstable-v1-protocol.h" #include "wlr-layer-shell-unstable-v1-protocol.h"
static const int i3_output_id = INT32_MAX;
static const int i3_scratch_id = INT32_MAX - 1;
static const char *ipc_json_layout_description(enum sway_container_layout l) { static const char *ipc_json_layout_description(enum sway_container_layout l) {
switch (l) { switch (l) {
case L_VERT: case L_VERT:
@ -32,15 +35,66 @@ static const char *ipc_json_layout_description(enum sway_container_layout l) {
} }
static const char *ipc_json_orientation_description(enum sway_container_layout l) { static const char *ipc_json_orientation_description(enum sway_container_layout l) {
if (l == L_VERT) { switch (l) {
case L_VERT:
return "vertical"; return "vertical";
} case L_HORIZ:
if (l == L_HORIZ) {
return "horizontal"; return "horizontal";
default:
return "none";
}
} }
static const char *ipc_json_border_description(enum sway_container_border border) {
switch (border) {
case B_NONE:
return "none"; return "none";
case B_PIXEL:
return "pixel";
case B_NORMAL:
return "normal";
case B_CSD:
return "csd";
}
return "unknown";
}
static const char *ipc_json_output_transform_description(enum wl_output_transform transform) {
switch (transform) {
case WL_OUTPUT_TRANSFORM_NORMAL:
return "normal";
case WL_OUTPUT_TRANSFORM_90:
return "90";
case WL_OUTPUT_TRANSFORM_180:
return "180";
case WL_OUTPUT_TRANSFORM_270:
return "270";
case WL_OUTPUT_TRANSFORM_FLIPPED:
return "flipped";
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
return "flipped-90";
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
return "flipped-180";
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
return "flipped-270";
}
return NULL;
}
static const char *ipc_json_device_type_description(struct sway_input_device *device) {
switch (device->wlr_device->type) {
case WLR_INPUT_DEVICE_POINTER:
return "pointer";
case WLR_INPUT_DEVICE_KEYBOARD:
return "keyboard";
case WLR_INPUT_DEVICE_TOUCH:
return "touch";
case WLR_INPUT_DEVICE_TABLET_TOOL:
return "tablet_tool";
case WLR_INPUT_DEVICE_TABLET_PAD:
return "tablet_pad";
}
return "unknown";
} }
json_object *ipc_json_get_version(void) { json_object *ipc_json_get_version(void) {
@ -76,30 +130,43 @@ static json_object *ipc_json_create_empty_rect(void) {
return ipc_json_create_rect(&empty); return ipc_json_create_rect(&empty);
} }
static void ipc_json_describe_root(struct sway_root *root, json_object *object) { static json_object *ipc_json_create_node(int id, char *name,
json_object_object_add(object, "type", json_object_new_string("root")); bool focused, json_object *focus, struct wlr_box *box) {
json_object *object = json_object_new_object();
json_object_object_add(object, "id", json_object_new_int(id));
json_object_object_add(object, "name",
name ? json_object_new_string(name) : NULL);
json_object_object_add(object, "rect", ipc_json_create_rect(box));
json_object_object_add(object, "focused", json_object_new_boolean(focused));
json_object_object_add(object, "focus", focus);
// set default values to be compatible with i3
json_object_object_add(object, "border",
json_object_new_string(
ipc_json_border_description(B_NONE)));
json_object_object_add(object, "current_border_width",
json_object_new_int(0));
json_object_object_add(object, "layout",
json_object_new_string(
ipc_json_layout_description(L_HORIZ)));
json_object_object_add(object, "orientation",
json_object_new_string(
ipc_json_orientation_description(L_HORIZ)));
json_object_object_add(object, "percent", NULL);
json_object_object_add(object, "window_rect", ipc_json_create_empty_rect());
json_object_object_add(object, "deco_rect", ipc_json_create_empty_rect());
json_object_object_add(object, "geometry", ipc_json_create_empty_rect());
json_object_object_add(object, "window", NULL);
json_object_object_add(object, "urgent", json_object_new_boolean(false));
json_object_object_add(object, "floating_nodes", json_object_new_array());
json_object_object_add(object, "sticky", json_object_new_boolean(false));
return object;
} }
static const char *ipc_json_get_output_transform(enum wl_output_transform transform) { static void ipc_json_describe_root(struct sway_root *root, json_object *object) {
switch (transform) { json_object_object_add(object, "type", json_object_new_string("root"));
case WL_OUTPUT_TRANSFORM_NORMAL:
return "normal";
case WL_OUTPUT_TRANSFORM_90:
return "90";
case WL_OUTPUT_TRANSFORM_180:
return "180";
case WL_OUTPUT_TRANSFORM_270:
return "270";
case WL_OUTPUT_TRANSFORM_FLIPPED:
return "flipped";
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
return "flipped-90";
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
return "flipped-180";
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
return "flipped-270";
}
return NULL;
} }
static void ipc_json_describe_output(struct sway_output *output, static void ipc_json_describe_output(struct sway_output *output,
@ -110,7 +177,8 @@ static void ipc_json_describe_output(struct sway_output *output,
json_object_object_add(object, "primary", json_object_new_boolean(false)); json_object_object_add(object, "primary", json_object_new_boolean(false));
json_object_object_add(object, "layout", json_object_new_string("output")); json_object_object_add(object, "layout", json_object_new_string("output"));
json_object_object_add(object, "orientation", json_object_object_add(object, "orientation",
json_object_new_string(ipc_json_orientation_description(L_NONE))); json_object_new_string(
ipc_json_orientation_description(L_NONE)));
json_object_object_add(object, "make", json_object_object_add(object, "make",
json_object_new_string(wlr_output->make)); json_object_new_string(wlr_output->make));
json_object_object_add(object, "model", json_object_object_add(object, "model",
@ -121,7 +189,7 @@ static void ipc_json_describe_output(struct sway_output *output,
json_object_new_double(wlr_output->scale)); json_object_new_double(wlr_output->scale));
json_object_object_add(object, "transform", json_object_object_add(object, "transform",
json_object_new_string( json_object_new_string(
ipc_json_get_output_transform(wlr_output->transform))); ipc_json_output_transform_description(wlr_output->transform)));
struct sway_workspace *ws = output_get_active_workspace(output); struct sway_workspace *ws = output_get_active_workspace(output);
json_object_object_add(object, "current_workspace", json_object_object_add(object, "current_workspace",
@ -187,6 +255,52 @@ json_object *ipc_json_describe_disabled_output(struct sway_output *output) {
return object; return object;
} }
static json_object *ipc_json_describe_scratchpad_output(void) {
struct wlr_box box;
root_get_box(root, &box);
// Create focus stack for __i3_scratch workspace
json_object *workspace_focus = json_object_new_array();
for (int i = root->scratchpad->length - 1; i >= 0; --i) {
struct sway_container *container = root->scratchpad->items[i];
json_object_array_add(workspace_focus,
json_object_new_int(container->node.id));
}
json_object *workspace = ipc_json_create_node(i3_scratch_id,
"__i3_scratch", false, workspace_focus, &box);
json_object_object_add(workspace, "type",
json_object_new_string("workspace"));
// List all hidden scratchpad containers as floating nodes
json_object *floating_array = json_object_new_array();
for (int i = 0; i < root->scratchpad->length; ++i) {
struct sway_container *container = root->scratchpad->items[i];
if (!container->workspace) {
json_object_array_add(floating_array,
ipc_json_describe_node_recursive(&container->node));
}
}
json_object_object_add(workspace, "floating_nodes", floating_array);
// Create focus stack for __i3 output
json_object *output_focus = json_object_new_array();
json_object_array_add(output_focus, json_object_new_int(i3_scratch_id));
json_object *output = ipc_json_create_node(i3_output_id,
"__i3", false, output_focus, &box);
json_object_object_add(output, "type",
json_object_new_string("output"));
json_object_object_add(output, "layout",
json_object_new_string("output"));
json_object *nodes = json_object_new_array();
json_object_array_add(nodes, workspace);
json_object_object_add(output, "nodes", nodes);
return output;
}
static void ipc_json_describe_workspace(struct sway_workspace *workspace, static void ipc_json_describe_workspace(struct sway_workspace *workspace,
json_object *object) { json_object *object) {
int num = isdigit(workspace->name[0]) ? atoi(workspace->name) : -1; int num = isdigit(workspace->name[0]) ? atoi(workspace->name) : -1;
@ -200,11 +314,12 @@ static void ipc_json_describe_workspace(struct sway_workspace *workspace,
json_object_object_add(object, "representation", workspace->representation ? json_object_object_add(object, "representation", workspace->representation ?
json_object_new_string(workspace->representation) : NULL); json_object_new_string(workspace->representation) : NULL);
const char *layout = ipc_json_layout_description(workspace->layout); json_object_object_add(object, "layout",
json_object_object_add(object, "layout", json_object_new_string(layout)); json_object_new_string(
ipc_json_layout_description(workspace->layout)));
const char *orientation = ipc_json_orientation_description(workspace->layout); json_object_object_add(object, "orientation",
json_object_object_add(object, "orientation", json_object_new_string(orientation)); json_object_new_string(
ipc_json_orientation_description(workspace->layout)));
// Floating // Floating
json_object *floating_array = json_object_new_array(); json_object *floating_array = json_object_new_array();
@ -216,20 +331,6 @@ static void ipc_json_describe_workspace(struct sway_workspace *workspace,
json_object_object_add(object, "floating_nodes", floating_array); json_object_object_add(object, "floating_nodes", floating_array);
} }
static const char *describe_container_border(enum sway_container_border border) {
switch (border) {
case B_NONE:
return "none";
case B_PIXEL:
return "pixel";
case B_NORMAL:
return "normal";
case B_CSD:
return "csd";
}
return "unknown";
}
static void ipc_json_describe_view(struct sway_container *c, json_object *object) { static void ipc_json_describe_view(struct sway_container *c, json_object *object) {
json_object_object_add(object, "pid", json_object_new_int(c->view->pid)); json_object_object_add(object, "pid", json_object_new_int(c->view->pid));
@ -307,10 +408,12 @@ static void ipc_json_describe_container(struct sway_container *c, json_object *o
json_object_new_string(container_is_floating(c) ? "floating_con" : "con")); json_object_new_string(container_is_floating(c) ? "floating_con" : "con"));
json_object_object_add(object, "layout", json_object_object_add(object, "layout",
json_object_new_string(ipc_json_layout_description(c->layout))); json_object_new_string(
ipc_json_layout_description(c->layout)));
json_object_object_add(object, "orientation", json_object_object_add(object, "orientation",
json_object_new_string(ipc_json_orientation_description(c->layout))); json_object_new_string(
ipc_json_orientation_description(c->layout)));
bool urgent = c->view ? bool urgent = c->view ?
view_is_urgent(c->view) : container_has_urgent_child(c); view_is_urgent(c->view) : container_has_urgent_child(c);
@ -331,7 +434,8 @@ static void ipc_json_describe_container(struct sway_container *c, json_object *o
} }
json_object_object_add(object, "border", json_object_object_add(object, "border",
json_object_new_string(describe_container_border(c->current.border))); json_object_new_string(
ipc_json_border_description(c->current.border)));
json_object_object_add(object, "current_border_width", json_object_object_add(object, "current_border_width",
json_object_new_int(c->current.border_thickness)); json_object_new_int(c->current.border_thickness));
json_object_object_add(object, "floating_nodes", json_object_new_array()); json_object_object_add(object, "floating_nodes", json_object_new_array());
@ -372,17 +476,10 @@ static void focus_inactive_children_iterator(struct sway_node *node,
json_object *ipc_json_describe_node(struct sway_node *node) { json_object *ipc_json_describe_node(struct sway_node *node) {
struct sway_seat *seat = input_manager_get_default_seat(); struct sway_seat *seat = input_manager_get_default_seat();
bool focused = seat_get_focus(seat) == node; bool focused = seat_get_focus(seat) == node;
json_object *object = json_object_new_object();
char *name = node_get_name(node); char *name = node_get_name(node);
struct wlr_box box; struct wlr_box box;
node_get_box(node, &box); node_get_box(node, &box);
json_object_object_add(object, "id", json_object_new_int((int)node->id));
json_object_object_add(object, "name",
name ? json_object_new_string(name) : NULL);
json_object_object_add(object, "rect", ipc_json_create_rect(&box));
json_object_object_add(object, "focused", json_object_new_boolean(focused));
json_object *focus = json_object_new_array(); json_object *focus = json_object_new_array();
struct focus_inactive_data data = { struct focus_inactive_data data = {
@ -390,24 +487,9 @@ json_object *ipc_json_describe_node(struct sway_node *node) {
.object = focus, .object = focus,
}; };
seat_for_each_node(seat, focus_inactive_children_iterator, &data); seat_for_each_node(seat, focus_inactive_children_iterator, &data);
json_object_object_add(object, "focus", focus);
// set default values to be compatible with i3 json_object *object = ipc_json_create_node(
json_object_object_add(object, "border", (int)node->id, name, focused, focus, &box);
json_object_new_string(describe_container_border(B_NONE)));
json_object_object_add(object, "current_border_width", json_object_new_int(0));
json_object_object_add(object, "layout",
json_object_new_string(ipc_json_layout_description(L_HORIZ)));
json_object_object_add(object, "orientation",
json_object_new_string(ipc_json_orientation_description(L_HORIZ)));
json_object_object_add(object, "percent", NULL);
json_object_object_add(object, "window_rect", ipc_json_create_empty_rect());
json_object_object_add(object, "deco_rect", ipc_json_create_empty_rect());
json_object_object_add(object, "geometry", ipc_json_create_empty_rect());
json_object_object_add(object, "window", NULL);
json_object_object_add(object, "urgent", json_object_new_boolean(false));
json_object_object_add(object, "floating_nodes", json_object_new_array());
json_object_object_add(object, "sticky", json_object_new_boolean(false));
switch (node->type) { switch (node->type) {
case N_ROOT: case N_ROOT:
@ -434,6 +516,8 @@ json_object *ipc_json_describe_node_recursive(struct sway_node *node) {
json_object *children = json_object_new_array(); json_object *children = json_object_new_array();
switch (node->type) { switch (node->type) {
case N_ROOT: case N_ROOT:
json_object_array_add(children,
ipc_json_describe_scratchpad_output());
for (i = 0; i < root->outputs->length; ++i) { for (i = 0; i < root->outputs->length; ++i) {
struct sway_output *output = root->outputs->items[i]; struct sway_output *output = root->outputs->items[i];
json_object_array_add(children, json_object_array_add(children,
@ -470,22 +554,6 @@ json_object *ipc_json_describe_node_recursive(struct sway_node *node) {
return object; return object;
} }
static const char *describe_device_type(struct sway_input_device *device) {
switch (device->wlr_device->type) {
case WLR_INPUT_DEVICE_POINTER:
return "pointer";
case WLR_INPUT_DEVICE_KEYBOARD:
return "keyboard";
case WLR_INPUT_DEVICE_TOUCH:
return "touch";
case WLR_INPUT_DEVICE_TABLET_TOOL:
return "tablet_tool";
case WLR_INPUT_DEVICE_TABLET_PAD:
return "tablet_pad";
}
return "unknown";
}
json_object *ipc_json_describe_input(struct sway_input_device *device) { json_object *ipc_json_describe_input(struct sway_input_device *device) {
if (!(sway_assert(device, "Device must not be null"))) { if (!(sway_assert(device, "Device must not be null"))) {
return NULL; return NULL;
@ -502,7 +570,8 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) {
json_object_object_add(object, "product", json_object_object_add(object, "product",
json_object_new_int(device->wlr_device->product)); json_object_new_int(device->wlr_device->product));
json_object_object_add(object, "type", json_object_object_add(object, "type",
json_object_new_string(describe_device_type(device))); json_object_new_string(
ipc_json_device_type_description(device)));
if (device->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD) { if (device->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD) {
struct wlr_keyboard *keyboard = device->wlr_device->keyboard; struct wlr_keyboard *keyboard = device->wlr_device->keyboard;

View file

@ -5,6 +5,7 @@
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include "sway/desktop/transaction.h" #include "sway/desktop/transaction.h"
#include "sway/input/seat.h" #include "sway/input/seat.h"
#include "sway/ipc-server.h"
#include "sway/output.h" #include "sway/output.h"
#include "sway/tree/arrange.h" #include "sway/tree/arrange.h"
#include "sway/tree/container.h" #include "sway/tree/container.h"
@ -75,6 +76,8 @@ void root_scratchpad_add_container(struct sway_container *con) {
arrange_workspace(workspace); arrange_workspace(workspace);
seat_set_focus(seat, seat_get_focus_inactive(seat, &workspace->node)); seat_set_focus(seat, seat_get_focus_inactive(seat, &workspace->node));
} }
ipc_event_window(con, "move");
} }
void root_scratchpad_remove_container(struct sway_container *con) { void root_scratchpad_remove_container(struct sway_container *con) {
@ -85,45 +88,51 @@ void root_scratchpad_remove_container(struct sway_container *con) {
int index = list_find(root->scratchpad, con); int index = list_find(root->scratchpad, con);
if (index != -1) { if (index != -1) {
list_del(root->scratchpad, index); list_del(root->scratchpad, index);
ipc_event_window(con, "move");
} }
} }
void root_scratchpad_show(struct sway_container *con) { void root_scratchpad_show(struct sway_container *con) {
struct sway_seat *seat = input_manager_current_seat(); struct sway_seat *seat = input_manager_current_seat();
struct sway_workspace *ws = seat_get_focused_workspace(seat); struct sway_workspace *new_ws = seat_get_focused_workspace(seat);
struct sway_workspace *old_ws = con->workspace;
// If the current con or any of its parents are in fullscreen mode, we // If the current con or any of its parents are in fullscreen mode, we
// first need to disable it before showing the scratchpad con. // first need to disable it before showing the scratchpad con.
if (ws->fullscreen) { if (new_ws->fullscreen) {
container_set_fullscreen(ws->fullscreen, false); container_set_fullscreen(new_ws->fullscreen, false);
} }
// Show the container // Show the container
if (con->workspace) { if (old_ws) {
container_detach(con); container_detach(con);
} }
workspace_add_floating(ws, con); workspace_add_floating(new_ws, con);
// Make sure the container's center point overlaps this workspace // Make sure the container's center point overlaps this workspace
double center_lx = con->x + con->width / 2; double center_lx = con->x + con->width / 2;
double center_ly = con->y + con->height / 2; double center_ly = con->y + con->height / 2;
struct wlr_box workspace_box; struct wlr_box workspace_box;
workspace_get_box(ws, &workspace_box); workspace_get_box(new_ws, &workspace_box);
if (!wlr_box_contains_point(&workspace_box, center_lx, center_ly)) { if (!wlr_box_contains_point(&workspace_box, center_lx, center_ly)) {
// Maybe resize it // Maybe resize it
if (con->width > ws->width || con->height > ws->height) { if (con->width > new_ws->width || con->height > new_ws->height) {
container_init_floating(con); container_init_floating(con);
} }
// Center it // Center it
double new_lx = ws->x + (ws->width - con->width) / 2; double new_lx = new_ws->x + (new_ws->width - con->width) / 2;
double new_ly = ws->y + (ws->height - con->height) / 2; double new_ly = new_ws->y + (new_ws->height - con->height) / 2;
container_floating_move_to(con, new_lx, new_ly); container_floating_move_to(con, new_lx, new_ly);
} }
arrange_workspace(ws); arrange_workspace(new_ws);
seat_set_focus(seat, seat_get_focus_inactive(seat, &con->node)); seat_set_focus(seat, seat_get_focus_inactive(seat, &con->node));
if (new_ws != old_ws) {
ipc_event_window(con, "move");
}
} }
void root_scratchpad_hide(struct sway_container *con) { void root_scratchpad_hide(struct sway_container *con) {
@ -137,6 +146,8 @@ void root_scratchpad_hide(struct sway_container *con) {
seat_set_focus(seat, seat_get_focus_inactive(seat, &ws->node)); seat_set_focus(seat, seat_get_focus_inactive(seat, &ws->node));
} }
list_move_to_end(root->scratchpad, con); list_move_to_end(root->scratchpad, con);
ipc_event_window(con, "move");
} }
struct pid_workspace { struct pid_workspace {