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_APP_ID,
VIEW_PROP_CLASS, VIEW_PROP_CLASS,
VIEW_PROP_INSTANCE, VIEW_PROP_INSTANCE,
VIEW_PROP_WINDOW_TYPE,
VIEW_PROP_WINDOW_ROLE,
VIEW_PROP_X11_WINDOW_ID,
}; };
struct sway_view_impl { 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); 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, void (*configure)(struct sway_view *view, double ox, double oy, int width,
int height); int height);
void (*set_activated)(struct sway_view *view, bool activated); void (*set_activated)(struct sway_view *view, bool activated);
@ -52,6 +56,8 @@ struct sway_view {
enum sway_container_border border; enum sway_container_border border;
int border_thickness; int border_thickness;
list_t *executed_criteria;
union { union {
struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6;
struct wlr_xwayland_surface *wlr_xwayland_surface; struct wlr_xwayland_surface *wlr_xwayland_surface;
@ -91,6 +97,9 @@ struct sway_xwayland_view {
struct wl_listener request_maximize; struct wl_listener request_maximize;
struct wl_listener request_configure; struct wl_listener request_configure;
struct wl_listener request_fullscreen; 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 map;
struct wl_listener unmap; struct wl_listener unmap;
struct wl_listener destroy; 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); 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); const char *view_get_type(struct sway_view *view);
void view_configure(struct sway_view *view, double ox, double oy, int width, 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); 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 #endif

View file

@ -287,7 +287,7 @@ static bool criteria_test(struct sway_container *cont, list_t *tokens) {
break; break;
} }
if (crit->regex && regex_cmp(class, crit->regex) == 0) { if (crit->regex && regex_cmp(class, crit->regex) == 0) {
matches++; ++matches;
} }
break; break;
} }
@ -308,8 +308,16 @@ static bool criteria_test(struct sway_container *cont, list_t *tokens) {
// TODO // TODO
break; break;
case CRIT_ID: 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: case CRIT_APP_ID:
{ {
const char *app_id = view_get_app_id(cont->sway_view); 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) { if (crit->regex && regex_cmp(app_id, crit->regex) == 0) {
matches++; ++matches;
} }
break; 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) { if (crit->regex && regex_cmp(instance, crit->regex) == 0) {
matches++; ++matches;
} }
break; break;
} }
case CRIT_TILING: case CRIT_TILING:
// TODO // TODO
++matches;
break; break;
case CRIT_TITLE: 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) { if (crit->regex && regex_cmp(title, crit->regex) == 0) {
matches++; ++matches;
} }
break; break;
} }
@ -359,8 +368,13 @@ static bool criteria_test(struct sway_container *cont, list_t *tokens) {
// TODO // TODO
break; break;
case CRIT_WORKSPACE: 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: default:
sway_abort("Invalid criteria type (%i)", crit->type); sway_abort("Invalid criteria type (%i)", crit->type);
break; break;
@ -440,6 +454,6 @@ list_t *container_for_crit_tokens(list_t *tokens) {
&list_tokens); &list_tokens);
// TODO look in the scratchpad // TODO look in the scratchpad
return list_tokens.list; return list_tokens.list;
} }

View file

@ -20,7 +20,7 @@ static struct sway_wl_shell_view *wl_shell_view_from_view(
return (struct sway_wl_shell_view *)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) { if (wl_shell_view_from_view(view) == NULL) {
return 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 = { static const struct sway_view_impl view_impl = {
.get_prop = get_prop, .get_string_prop = get_string_prop,
.configure = configure, .configure = configure,
.close = _close, .close = _close,
.destroy = destroy, .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; 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) { if (xdg_shell_v6_view_from_view(view) == NULL) {
return NULL; return NULL;
} }
@ -158,7 +158,7 @@ static void destroy(struct sway_view *view) {
} }
static const struct sway_view_impl view_impl = { static const struct sway_view_impl view_impl = {
.get_prop = get_prop, .get_string_prop = get_string_prop,
.configure = configure, .configure = configure,
.set_activated = set_activated, .set_activated = set_activated,
.set_fullscreen = set_fullscreen, .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; 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) { if (xwayland_view_from_view(view) == NULL) {
return 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; return view->wlr_xwayland_surface->title;
case VIEW_PROP_CLASS: case VIEW_PROP_CLASS:
return view->wlr_xwayland_surface->class; return view->wlr_xwayland_surface->class;
case VIEW_PROP_INSTANCE:
return view->wlr_xwayland_surface->instance;
default: default:
return NULL; 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, static void configure(struct sway_view *view, double ox, double oy, int width,
int height) { int height) {
struct sway_xwayland_view *xwayland_view = xwayland_view_from_view(view); 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->destroy.link);
wl_list_remove(&xwayland_view->request_configure.link); wl_list_remove(&xwayland_view->request_configure.link);
wl_list_remove(&xwayland_view->request_fullscreen.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->map.link);
wl_list_remove(&xwayland_view->unmap.link); wl_list_remove(&xwayland_view->unmap.link);
free(xwayland_view); free(xwayland_view);
} }
static const struct sway_view_impl view_impl = { 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, .configure = configure,
.set_activated = set_activated, .set_activated = set_activated,
.set_fullscreen = set_fullscreen, .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, view_update_size(view, xwayland_view->pending_width,
xwayland_view->pending_height); xwayland_view->pending_height);
view_damage(view, false); view_damage(view, false);
view_update_title(view, false);
} }
static void handle_unmap(struct wl_listener *listener, void *data) { 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); 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) { void handle_xwayland_surface(struct wl_listener *listener, void *data) {
struct sway_server *server = wl_container_of(listener, server, struct sway_server *server = wl_container_of(listener, server,
xwayland_surface); xwayland_surface);
@ -323,6 +378,16 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
&xwayland_view->request_fullscreen); &xwayland_view->request_fullscreen);
xwayland_view->request_fullscreen.notify = handle_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); wl_signal_add(&xsurface->events.unmap, &xwayland_view->unmap);
xwayland_view->unmap.notify = handle_unmap; xwayland_view->unmap.notify = handle_unmap;

View file

@ -3,6 +3,7 @@
#include <wayland-server.h> #include <wayland-server.h>
#include <wlr/render/wlr_renderer.h> #include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include "list.h"
#include "log.h" #include "log.h"
#include "sway/criteria.h" #include "sway/criteria.h"
#include "sway/commands.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) { const struct sway_view_impl *impl) {
view->type = type; view->type = type;
view->impl = impl; view->impl = impl;
view->executed_criteria = create_list();
wl_signal_init(&view->events.unmap); wl_signal_init(&view->events.unmap);
} }
@ -31,6 +33,8 @@ void view_destroy(struct sway_view *view) {
view_unmap(view); view_unmap(view);
} }
list_free(view->executed_criteria);
container_destroy(view->swayc); container_destroy(view->swayc);
if (view->impl->destroy) { if (view->impl->destroy) {
@ -41,33 +45,54 @@ void view_destroy(struct sway_view *view) {
} }
const char *view_get_title(struct sway_view *view) { const char *view_get_title(struct sway_view *view) {
if (view->impl->get_prop) { if (view->impl->get_string_prop) {
return view->impl->get_prop(view, VIEW_PROP_TITLE); return view->impl->get_string_prop(view, VIEW_PROP_TITLE);
} }
return NULL; return NULL;
} }
const char *view_get_app_id(struct sway_view *view) { const char *view_get_app_id(struct sway_view *view) {
if (view->impl->get_prop) { if (view->impl->get_string_prop) {
return view->impl->get_prop(view, VIEW_PROP_APP_ID); return view->impl->get_string_prop(view, VIEW_PROP_APP_ID);
} }
return NULL; return NULL;
} }
const char *view_get_class(struct sway_view *view) { const char *view_get_class(struct sway_view *view) {
if (view->impl->get_prop) { if (view->impl->get_string_prop) {
return view->impl->get_prop(view, VIEW_PROP_CLASS); return view->impl->get_string_prop(view, VIEW_PROP_CLASS);
} }
return NULL; return NULL;
} }
const char *view_get_instance(struct sway_view *view) { const char *view_get_instance(struct sway_view *view) {
if (view->impl->get_prop) { if (view->impl->get_string_prop) {
return view->impl->get_prop(view, VIEW_PROP_INSTANCE); return view->impl->get_string_prop(view, VIEW_PROP_INSTANCE);
} }
return NULL; 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) { const char *view_get_type(struct sway_view *view) {
switch(view->type) { switch(view->type) {
case SWAY_VIEW_WL_SHELL: 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) { static bool view_has_executed_criteria(struct sway_view *view,
if (!sway_assert(view->swayc, "cannot run criteria for unmapped 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; return;
} }
struct sway_seat *seat = input_manager_current_seat(input_manager); 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); list_t *criteria = criteria_for(view->swayc);
for (int i = 0; i < criteria->length; i++) { for (int i = 0; i < criteria->length; i++) {
struct criteria *crit = criteria->items[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); crit->crit_raw, view, crit->cmdlist);
list_add(view->executed_criteria, crit);
struct cmd_results *res = execute_command(crit->cmdlist, NULL); struct cmd_results *res = execute_command(crit->cmdlist, NULL);
if (res->status != CMD_SUCCESS) { if (res->status != CMD_SUCCESS) {
wlr_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error); 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_damage(view, true);
view_handle_container_reparent(&view->container_reparent, NULL); view_handle_container_reparent(&view->container_reparent, NULL);
view_update_title(view, false);
view_execute_criteria(view); view_execute_criteria(view);
} }