This commit is contained in:
Ryan Dwyer 2018-05-07 01:25:03 +00:00 committed by GitHub
commit 264d8b3b6d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 171 additions and 28 deletions

View file

@ -20,11 +20,15 @@ enum sway_view_prop {
VIEW_PROP_APP_ID,
VIEW_PROP_CLASS,
VIEW_PROP_INSTANCE,
VIEW_PROP_WINDOW_TYPE,
VIEW_PROP_WINDOW_ROLE,
VIEW_PROP_X11_WINDOW_ID,
};
struct sway_view_impl {
const char *(*get_prop)(struct sway_view *view,
const char *(*get_string_prop)(struct sway_view *view,
enum sway_view_prop prop);
uint32_t (*get_int_prop)(struct sway_view *view, enum sway_view_prop prop);
void (*configure)(struct sway_view *view, double ox, double oy, int width,
int height);
void (*set_activated)(struct sway_view *view, bool activated);
@ -52,6 +56,8 @@ struct sway_view {
enum sway_container_border border;
int border_thickness;
list_t *executed_criteria;
union {
struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6;
struct wlr_xwayland_surface *wlr_xwayland_surface;
@ -91,6 +97,9 @@ struct sway_xwayland_view {
struct wl_listener request_maximize;
struct wl_listener request_configure;
struct wl_listener request_fullscreen;
struct wl_listener set_title;
struct wl_listener set_class;
struct wl_listener set_window_type;
struct wl_listener map;
struct wl_listener unmap;
struct wl_listener destroy;
@ -165,6 +174,12 @@ const char *view_get_class(struct sway_view *view);
const char *view_get_instance(struct sway_view *view);
uint32_t view_get_x11_window_id(struct sway_view *view);
uint32_t view_get_window_type(struct sway_view *view);
uint32_t view_get_window_role(struct sway_view *view);
const char *view_get_type(struct sway_view *view);
void view_configure(struct sway_view *view, double ox, double oy, int width,
@ -217,4 +232,10 @@ void view_child_destroy(struct sway_view_child *child);
*/
void view_update_title(struct sway_view *view, bool force);
/**
* Run any criteria that match the view and haven't been run on this view
* before.
*/
void view_execute_criteria(struct sway_view *view);
#endif

View file

@ -287,7 +287,7 @@ static bool criteria_test(struct sway_container *cont, list_t *tokens) {
break;
}
if (crit->regex && regex_cmp(class, crit->regex) == 0) {
matches++;
++matches;
}
break;
}
@ -308,8 +308,16 @@ static bool criteria_test(struct sway_container *cont, list_t *tokens) {
// TODO
break;
case CRIT_ID:
// TODO
break;
{
char *endptr;
size_t crit_id = strtoul(crit->raw, &endptr, 10);
if (*endptr == 0
&& view_get_x11_window_id(cont->sway_view) == crit_id) {
++matches;
}
break;
}
case CRIT_APP_ID:
{
const char *app_id = view_get_app_id(cont->sway_view);
@ -318,7 +326,7 @@ static bool criteria_test(struct sway_container *cont, list_t *tokens) {
}
if (crit->regex && regex_cmp(app_id, crit->regex) == 0) {
matches++;
++matches;
}
break;
}
@ -330,12 +338,13 @@ static bool criteria_test(struct sway_container *cont, list_t *tokens) {
}
if (crit->regex && regex_cmp(instance, crit->regex) == 0) {
matches++;
++matches;
}
break;
}
case CRIT_TILING:
// TODO
++matches;
break;
case CRIT_TITLE:
{
@ -345,7 +354,7 @@ static bool criteria_test(struct sway_container *cont, list_t *tokens) {
}
if (crit->regex && regex_cmp(title, crit->regex) == 0) {
matches++;
++matches;
}
break;
}
@ -359,8 +368,13 @@ static bool criteria_test(struct sway_container *cont, list_t *tokens) {
// TODO
break;
case CRIT_WORKSPACE:
// TODO
break;
{
struct sway_container *ws = container_parent(cont, C_WORKSPACE);
if (ws && strcmp(ws->name, crit->raw) == 0) {
++matches;
}
break;
}
default:
sway_abort("Invalid criteria type (%i)", crit->type);
break;

View file

@ -20,7 +20,7 @@ static struct sway_wl_shell_view *wl_shell_view_from_view(
return (struct sway_wl_shell_view *)view;
}
static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) {
static const char *get_string_prop(struct sway_view *view, enum sway_view_prop prop) {
if (wl_shell_view_from_view(view) == NULL) {
return NULL;
}
@ -70,7 +70,7 @@ static void set_fullscreen(struct sway_view *view, bool fullscreen) {
}
static const struct sway_view_impl view_impl = {
.get_prop = get_prop,
.get_string_prop = get_string_prop,
.configure = configure,
.close = _close,
.destroy = destroy,

View file

@ -80,7 +80,7 @@ static struct sway_xdg_shell_v6_view *xdg_shell_v6_view_from_view(
return (struct sway_xdg_shell_v6_view *)view;
}
static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) {
static const char *get_string_prop(struct sway_view *view, enum sway_view_prop prop) {
if (xdg_shell_v6_view_from_view(view) == NULL) {
return NULL;
}
@ -158,7 +158,7 @@ static void destroy(struct sway_view *view) {
}
static const struct sway_view_impl view_impl = {
.get_prop = get_prop,
.get_string_prop = get_string_prop,
.configure = configure,
.set_activated = set_activated,
.set_fullscreen = set_fullscreen,

View file

@ -126,7 +126,7 @@ static struct sway_xwayland_view *xwayland_view_from_view(
return (struct sway_xwayland_view *)view;
}
static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) {
static const char *get_string_prop(struct sway_view *view, enum sway_view_prop prop) {
if (xwayland_view_from_view(view) == NULL) {
return NULL;
}
@ -135,11 +135,29 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) {
return view->wlr_xwayland_surface->title;
case VIEW_PROP_CLASS:
return view->wlr_xwayland_surface->class;
case VIEW_PROP_INSTANCE:
return view->wlr_xwayland_surface->instance;
default:
return NULL;
}
}
static uint32_t get_int_prop(struct sway_view *view, enum sway_view_prop prop) {
if (xwayland_view_from_view(view) == NULL) {
return 0;
}
switch (prop) {
case VIEW_PROP_X11_WINDOW_ID:
return view->wlr_xwayland_surface->window_id;
case VIEW_PROP_WINDOW_TYPE:
return *view->wlr_xwayland_surface->window_type;
case VIEW_PROP_WINDOW_ROLE:
return 0;
default:
return 0;
}
}
static void configure(struct sway_view *view, double ox, double oy, int width,
int height) {
struct sway_xwayland_view *xwayland_view = xwayland_view_from_view(view);
@ -200,13 +218,17 @@ static void destroy(struct sway_view *view) {
wl_list_remove(&xwayland_view->destroy.link);
wl_list_remove(&xwayland_view->request_configure.link);
wl_list_remove(&xwayland_view->request_fullscreen.link);
wl_list_remove(&xwayland_view->set_title.link);
wl_list_remove(&xwayland_view->set_class.link);
wl_list_remove(&xwayland_view->set_window_type.link);
wl_list_remove(&xwayland_view->map.link);
wl_list_remove(&xwayland_view->unmap.link);
free(xwayland_view);
}
static const struct sway_view_impl view_impl = {
.get_prop = get_prop,
.get_string_prop = get_string_prop,
.get_int_prop = get_int_prop,
.configure = configure,
.set_activated = set_activated,
.set_fullscreen = set_fullscreen,
@ -223,7 +245,6 @@ static void handle_commit(struct wl_listener *listener, void *data) {
view_update_size(view, xwayland_view->pending_width,
xwayland_view->pending_height);
view_damage(view, false);
view_update_title(view, false);
}
static void handle_unmap(struct wl_listener *listener, void *data) {
@ -285,6 +306,40 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
view_set_fullscreen(view, xsurface->fullscreen);
}
static void handle_set_title(struct wl_listener *listener, void *data) {
struct sway_xwayland_view *xwayland_view =
wl_container_of(listener, xwayland_view, set_title);
struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
if (!xsurface->mapped) {
return;
}
view_update_title(view, false);
view_execute_criteria(view);
}
static void handle_set_class(struct wl_listener *listener, void *data) {
struct sway_xwayland_view *xwayland_view =
wl_container_of(listener, xwayland_view, set_class);
struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
if (!xsurface->mapped) {
return;
}
view_execute_criteria(view);
}
static void handle_set_window_type(struct wl_listener *listener, void *data) {
struct sway_xwayland_view *xwayland_view =
wl_container_of(listener, xwayland_view, set_window_type);
struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
if (!xsurface->mapped) {
return;
}
view_execute_criteria(view);
}
void handle_xwayland_surface(struct wl_listener *listener, void *data) {
struct sway_server *server = wl_container_of(listener, server,
xwayland_surface);
@ -323,6 +378,16 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
&xwayland_view->request_fullscreen);
xwayland_view->request_fullscreen.notify = handle_request_fullscreen;
wl_signal_add(&xsurface->events.set_title, &xwayland_view->set_title);
xwayland_view->set_title.notify = handle_set_title;
wl_signal_add(&xsurface->events.set_class, &xwayland_view->set_class);
xwayland_view->set_class.notify = handle_set_class;
wl_signal_add(&xsurface->events.set_window_type,
&xwayland_view->set_window_type);
xwayland_view->set_window_type.notify = handle_set_window_type;
wl_signal_add(&xsurface->events.unmap, &xwayland_view->unmap);
xwayland_view->unmap.notify = handle_unmap;

View file

@ -3,6 +3,7 @@
#include <wayland-server.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_output_layout.h>
#include "list.h"
#include "log.h"
#include "sway/criteria.h"
#include "sway/commands.h"
@ -19,6 +20,7 @@ void view_init(struct sway_view *view, enum sway_view_type type,
const struct sway_view_impl *impl) {
view->type = type;
view->impl = impl;
view->executed_criteria = create_list();
wl_signal_init(&view->events.unmap);
}
@ -31,6 +33,8 @@ void view_destroy(struct sway_view *view) {
view_unmap(view);
}
list_free(view->executed_criteria);
container_destroy(view->swayc);
if (view->impl->destroy) {
@ -41,33 +45,54 @@ void view_destroy(struct sway_view *view) {
}
const char *view_get_title(struct sway_view *view) {
if (view->impl->get_prop) {
return view->impl->get_prop(view, VIEW_PROP_TITLE);
if (view->impl->get_string_prop) {
return view->impl->get_string_prop(view, VIEW_PROP_TITLE);
}
return NULL;
}
const char *view_get_app_id(struct sway_view *view) {
if (view->impl->get_prop) {
return view->impl->get_prop(view, VIEW_PROP_APP_ID);
if (view->impl->get_string_prop) {
return view->impl->get_string_prop(view, VIEW_PROP_APP_ID);
}
return NULL;
}
const char *view_get_class(struct sway_view *view) {
if (view->impl->get_prop) {
return view->impl->get_prop(view, VIEW_PROP_CLASS);
if (view->impl->get_string_prop) {
return view->impl->get_string_prop(view, VIEW_PROP_CLASS);
}
return NULL;
}
const char *view_get_instance(struct sway_view *view) {
if (view->impl->get_prop) {
return view->impl->get_prop(view, VIEW_PROP_INSTANCE);
if (view->impl->get_string_prop) {
return view->impl->get_string_prop(view, VIEW_PROP_INSTANCE);
}
return NULL;
}
uint32_t view_get_x11_window_id(struct sway_view *view) {
if (view->impl->get_int_prop) {
return view->impl->get_int_prop(view, VIEW_PROP_X11_WINDOW_ID);
}
return 0;
}
uint32_t view_get_window_type(struct sway_view *view) {
if (view->impl->get_int_prop) {
return view->impl->get_int_prop(view, VIEW_PROP_WINDOW_TYPE);
}
return 0;
}
uint32_t view_get_window_role(struct sway_view *view) {
if (view->impl->get_int_prop) {
return view->impl->get_int_prop(view, VIEW_PROP_WINDOW_ROLE);
}
return 0;
}
const char *view_get_type(struct sway_view *view) {
switch(view->type) {
case SWAY_VIEW_WL_SHELL:
@ -282,8 +307,19 @@ static void view_handle_container_reparent(struct wl_listener *listener,
}
}
static void view_execute_criteria(struct sway_view *view) {
if (!sway_assert(view->swayc, "cannot run criteria for unmapped view")) {
static bool view_has_executed_criteria(struct sway_view *view,
struct criteria *criteria) {
for (int i = 0; i < view->executed_criteria->length; ++i) {
struct criteria *item = view->executed_criteria->items[i];
if (item == criteria) {
return true;
}
}
return false;
}
void view_execute_criteria(struct sway_view *view) {
if (!view->swayc) {
return;
}
struct sway_seat *seat = input_manager_current_seat(input_manager);
@ -292,8 +328,14 @@ static void view_execute_criteria(struct sway_view *view) {
list_t *criteria = criteria_for(view->swayc);
for (int i = 0; i < criteria->length; i++) {
struct criteria *crit = criteria->items[i];
wlr_log(L_DEBUG, "for_window '%s' matches new view %p, cmd: '%s'",
wlr_log(L_DEBUG, "Checking criteria %s", crit->crit_raw);
if (view_has_executed_criteria(view, crit)) {
wlr_log(L_DEBUG, "Criteria already executed");
continue;
}
wlr_log(L_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
crit->crit_raw, view, crit->cmdlist);
list_add(view->executed_criteria, crit);
struct cmd_results *res = execute_command(crit->cmdlist, NULL);
if (res->status != CMD_SUCCESS) {
wlr_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error);
@ -336,6 +378,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
view_damage(view, true);
view_handle_container_reparent(&view->container_reparent, NULL);
view_update_title(view, false);
view_execute_criteria(view);
}