This commit is contained in:
Drew DeVault 2016-01-29 10:08:37 +00:00
commit 53dea65cd0
11 changed files with 130 additions and 68 deletions

View file

@ -77,6 +77,9 @@ struct sway_container {
bool is_focused; bool is_focused;
bool sticky; // floating view always visible on its output bool sticky; // floating view always visible on its output
// Custom arrange function
void (*arrange)(struct sway_container *, double width, double height);
// Attributes that mostly views have. // Attributes that mostly views have.
char *name; char *name;
char *class; char *class;

View file

@ -5,40 +5,43 @@
#include <wlc/wlc-wayland.h> #include <wlc/wlc-wayland.h>
#include "wayland-desktop-shell-server-protocol.h" #include "wayland-desktop-shell-server-protocol.h"
#include "list.h" #include "list.h"
#include "container.h"
struct background_config { struct background_config {
wlc_handle output; wlc_handle output;
wlc_resource surface; wlc_handle handle;
// we need the wl_resource of the surface in the destructor wlc_resource surface;
struct wl_resource *wl_surface_res; // we need the wl_resource of the surface in the destructor
struct wl_resource *wl_surface_res;
}; };
struct panel_config { struct panel_config {
// wayland resource used in callbacks, is used to track this panel // wayland resource used in callbacks, is used to track this panel
struct wl_resource *wl_resource; struct wl_resource *wl_resource;
wlc_handle output; wlc_handle output;
wlc_resource surface; wlc_resource surface;
// we need the wl_resource of the surface in the destructor // we need the wl_resource of the surface in the destructor
struct wl_resource *wl_surface_res; struct wl_resource *wl_surface_res;
enum desktop_shell_panel_position panel_position; enum desktop_shell_panel_position panel_position;
}; };
struct desktop_shell_state { struct desktop_shell_state {
list_t *backgrounds; list_t *backgrounds;
list_t *panels; list_t *panels;
list_t *lock_surfaces; list_t *lock_surfaces;
bool is_locked; bool is_locked;
struct wlc_size panel_size; struct wlc_size panel_size;
}; };
struct swaylock_state { struct swaylock_state {
bool active; bool active;
wlc_handle output; wlc_handle output;
wlc_resource surface; wlc_resource surface;
}; };
extern struct desktop_shell_state desktop_shell; extern struct desktop_shell_state desktop_shell;
void register_extensions(void); void register_extensions(void);
void arrange_background_view(swayc_t *view, double width, double height);
#endif #endif

View file

@ -16,4 +16,6 @@ void get_absolute_position(swayc_t *container, struct wlc_point *point);
// given wlc_point. // given wlc_point.
void get_absolute_center_position(swayc_t *container, struct wlc_point *point); void get_absolute_center_position(swayc_t *container, struct wlc_point *point);
struct output_config *config_for_output(wlc_handle output);
#endif #endif

View file

@ -686,6 +686,7 @@ void apply_output_config(struct output_config *oc, swayc_t *output) {
snprintf(output_id, bufsize, "%d", output_i); snprintf(output_id, bufsize, "%d", output_i);
output_id[bufsize-1] = 0; output_id[bufsize-1] = 0;
#ifdef NDEBUG
char *const cmd[] = { char *const cmd[] = {
"swaybg", "swaybg",
output_id, output_id,
@ -693,6 +694,15 @@ void apply_output_config(struct output_config *oc, swayc_t *output) {
oc->background_option, oc->background_option,
NULL, NULL,
}; };
#else
char *const cmd[] = {
"./bin/swaybg",
output_id,
oc->background,
oc->background_option,
NULL,
};
#endif
output->bg_pid = fork(); output->bg_pid = fork();
if (output->bg_pid == 0) { if (output->bg_pid == 0) {

View file

@ -11,6 +11,7 @@
#include "layout.h" #include "layout.h"
#include "input_state.h" #include "input_state.h"
#include "log.h" #include "log.h"
#include "output.h"
#define ASSERT_NONNULL(PTR) \ #define ASSERT_NONNULL(PTR) \
sway_assert (PTR, #PTR "must be non-null") sway_assert (PTR, #PTR "must be non-null")
@ -90,21 +91,7 @@ swayc_t *new_output(wlc_handle handle) {
sway_log(L_DEBUG, "New output %lu:%s", handle, name); sway_log(L_DEBUG, "New output %lu:%s", handle, name);
struct output_config *oc = NULL; struct output_config *oc = config_for_output(handle);
int i;
for (i = 0; i < config->output_configs->length; ++i) {
struct output_config *cur = config->output_configs->items[i];
if (strcasecmp(name, cur->name) == 0) {
sway_log(L_DEBUG, "Matched output config for %s", name);
oc = cur;
break;
}
if (strcasecmp("*", cur->name) == 0) {
sway_log(L_DEBUG, "Matched wildcard output config for %s", name);
oc = cur;
break;
}
}
if (oc && !oc->enabled) { if (oc && !oc->enabled) {
return NULL; return NULL;
@ -125,6 +112,7 @@ swayc_t *new_output(wlc_handle handle) {
// Create workspace // Create workspace
char *ws_name = NULL; char *ws_name = NULL;
if (name) { if (name) {
int i;
for (i = 0; i < config->workspace_outputs->length; ++i) { for (i = 0; i < config->workspace_outputs->length; ++i) {
struct workspace_output *wso = config->workspace_outputs->items[i]; struct workspace_output *wso = config->workspace_outputs->items[i];
if (strcasecmp(wso->output, name) == 0) { if (strcasecmp(wso->output, name) == 0) {

View file

@ -24,18 +24,6 @@ static struct panel_config *find_or_create_panel_config(struct wl_resource *reso
return config; return config;
} }
void background_surface_destructor(struct wl_resource *resource) {
sway_log(L_DEBUG, "Background surface killed");
int i;
for (i = 0; i < desktop_shell.backgrounds->length; ++i) {
struct background_config *config = desktop_shell.backgrounds->items[i];
if (config->wl_surface_res == resource) {
list_del(desktop_shell.backgrounds, i);
break;
}
}
}
void panel_surface_destructor(struct wl_resource *resource) { void panel_surface_destructor(struct wl_resource *resource) {
sway_log(L_DEBUG, "Panel surface killed"); sway_log(L_DEBUG, "Panel surface killed");
int i; int i;
@ -63,6 +51,19 @@ void lock_surface_destructor(struct wl_resource *resource) {
} }
} }
void arrange_background_view(swayc_t *view, double width, double height) {
sway_log(L_DEBUG, "Arranging background view %p", view);
int i;
for (i = 0; i < desktop_shell.backgrounds->length; ++i) {
struct background_config *config = desktop_shell.backgrounds->items[i];
if (config->handle == view->handle) {
struct wlc_size resolution = *wlc_output_get_resolution(config->output);
wlc_view_set_geometry(view->handle, WLC_RESIZE_EDGE_NONE, &(struct wlc_geometry){ wlc_origin_zero, resolution });
wlc_view_send_to_back(view->handle);
}
}
}
static void set_background(struct wl_client *client, struct wl_resource *resource, static void set_background(struct wl_client *client, struct wl_resource *resource,
struct wl_resource *_output, struct wl_resource *surface) { struct wl_resource *_output, struct wl_resource *surface) {
wlc_handle output = wlc_handle_from_wl_output_resource(_output); wlc_handle output = wlc_handle_from_wl_output_resource(_output);
@ -73,9 +74,14 @@ static void set_background(struct wl_client *client, struct wl_resource *resourc
struct background_config *config = malloc(sizeof(struct background_config)); struct background_config *config = malloc(sizeof(struct background_config));
config->output = output; config->output = output;
config->surface = wlc_resource_from_wl_surface_resource(surface); config->surface = wlc_resource_from_wl_surface_resource(surface);
config->handle = wlc_handle_from_wl_surface_resource(surface);
config->wl_surface_res = surface; config->wl_surface_res = surface;
list_add(desktop_shell.backgrounds, config); list_add(desktop_shell.backgrounds, config);
wl_resource_set_destructor(surface, background_surface_destructor);
swayc_t *view = swayc_by_handle(config->handle);
if (view) {
view->arrange = arrange_background_view;
}
} }
static void set_panel(struct wl_client *client, struct wl_resource *resource, static void set_panel(struct wl_client *client, struct wl_resource *resource,

View file

@ -106,18 +106,10 @@ static void handle_output_destroyed(wlc_handle output) {
} }
} }
static void handle_output_pre_render(wlc_handle output) { static void handle_output_post_render(wlc_handle output) {
struct wlc_size resolution = *wlc_output_get_resolution(output); struct wlc_size resolution = *wlc_output_get_resolution(output);
int i; int i;
for (i = 0; i < desktop_shell.backgrounds->length; ++i) {
struct background_config *config = desktop_shell.backgrounds->items[i];
if (config->output == output) {
wlc_surface_render(config->surface, &(struct wlc_geometry){ wlc_origin_zero, resolution });
break;
}
}
for (i = 0; i < desktop_shell.panels->length; ++i) { for (i = 0; i < desktop_shell.panels->length; ++i) {
struct panel_config *config = desktop_shell.panels->items[i]; struct panel_config *config = desktop_shell.panels->items[i];
if (config->output == output) { if (config->output == output) {
@ -153,6 +145,10 @@ static void handle_output_resolution_change(wlc_handle output, const struct wlc_
sway_log(L_DEBUG, "Output %u resolution changed to %d x %d", (unsigned int)output, to->w, to->h); sway_log(L_DEBUG, "Output %u resolution changed to %d x %d", (unsigned int)output, to->w, to->h);
swayc_t *c = swayc_by_handle(output); swayc_t *c = swayc_by_handle(output);
if (!c) return; if (!c) return;
struct output_config *oc = config_for_output(output);
if (oc) {
apply_output_config(oc, c);
}
c->width = to->w; c->width = to->w;
c->height = to->h; c->height = to->h;
arrange_windows(&root_container, -1, -1); arrange_windows(&root_container, -1, -1);
@ -237,12 +233,25 @@ static bool handle_view_created(wlc_handle handle) {
} }
if (newview) { if (newview) {
int i;
set_focused_container(newview); set_focused_container(newview);
// Check if this view has a special role
wlc_resource resource = wlc_view_get_surface(handle);
for (i = 0; i < desktop_shell.backgrounds->length; ++i) {
struct background_config *config = desktop_shell.backgrounds->items[i];
if (config->surface == resource) {
sway_log(L_DEBUG, "Setting view %p as background", newview);
newview->handle = handle;
newview->arrange = arrange_background_view;
}
}
swayc_t *output = swayc_parent_by_type(newview, C_OUTPUT); swayc_t *output = swayc_parent_by_type(newview, C_OUTPUT);
arrange_windows(output, -1, -1); arrange_windows(output, -1, -1);
// check if it matches for_window in config and execute if so // check if it matches for_window in config and execute if so
list_t *criteria = criteria_for(newview); list_t *criteria = criteria_for(newview);
for (int i = 0; i < criteria->length; i++) { for (i = 0; i < criteria->length; i++) {
struct criteria *crit = criteria->items[i]; struct criteria *crit = criteria->items[i];
sway_log(L_DEBUG, "for_window '%s' matches new view %p, cmd: '%s'", sway_log(L_DEBUG, "for_window '%s' matches new view %p, cmd: '%s'",
crit->crit_raw, newview, crit->cmdlist); crit->crit_raw, newview, crit->cmdlist);
@ -674,7 +683,7 @@ struct wlc_interface interface = {
.resolution = handle_output_resolution_change, .resolution = handle_output_resolution_change,
.focus = handle_output_focused, .focus = handle_output_focused,
.render = { .render = {
.pre = handle_output_pre_render .post = handle_output_post_render
} }
}, },
.view = { .view = {

View file

@ -445,6 +445,12 @@ static void arrange_windows_r(swayc_t *container, double width, double height) {
sway_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", container, sway_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", container,
container->name, container->width, container->height, container->x, container->y); container->name, container->width, container->height, container->x, container->y);
if (container->arrange) {
sway_log(L_DEBUG, "Invoking arrangement override handler for container %p", container);
container->arrange(container, width, height);
return;
}
double x = 0, y = 0; double x = 0, y = 0;
switch (container->type) { switch (container->type) {
case C_ROOT: case C_ROOT:
@ -525,16 +531,26 @@ static void arrange_windows_r(swayc_t *container, double width, double height) {
break; break;
} }
int total_children = 0; // not including arrangement override containers
for (i = 0; i < container->children->length; ++i) {
swayc_t *child = container->children->items[i];
if (!child->arrange) {
total_children++;
}
}
double scale = 0; double scale = 0;
switch (container->layout) { switch (container->layout) {
case L_HORIZ: case L_HORIZ:
default: default:
// Calculate total width // Calculate total width
for (i = 0; i < container->children->length; ++i) { for (i = 0; i < container->children->length; ++i) {
double *old_width = &((swayc_t *)container->children->items[i])->width; swayc_t *child = container->children->items[i];
if (child->arrange) continue;
double *old_width = &child->width;
if (*old_width <= 0) { if (*old_width <= 0) {
if (container->children->length > 1) { if (total_children > 1) {
*old_width = width / (container->children->length - 1); *old_width = width / (total_children - 1);
} else { } else {
*old_width = width; *old_width = width;
} }
@ -547,6 +563,7 @@ static void arrange_windows_r(swayc_t *container, double width, double height) {
sway_log(L_DEBUG, "Arranging %p horizontally", container); sway_log(L_DEBUG, "Arranging %p horizontally", container);
for (i = 0; i < container->children->length; ++i) { for (i = 0; i < container->children->length; ++i) {
swayc_t *child = container->children->items[i]; swayc_t *child = container->children->items[i];
if (child->arrange) continue;
sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, width, scale); sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, width, scale);
child->x = x; child->x = x;
child->y = y; child->y = y;
@ -563,10 +580,12 @@ static void arrange_windows_r(swayc_t *container, double width, double height) {
case L_VERT: case L_VERT:
// Calculate total height // Calculate total height
for (i = 0; i < container->children->length; ++i) { for (i = 0; i < container->children->length; ++i) {
double *old_height = &((swayc_t *)container->children->items[i])->height; swayc_t *child = container->children->items[i];
if (child->arrange) continue;
double *old_height = &child->height;
if (*old_height <= 0) { if (*old_height <= 0) {
if (container->children->length > 1) { if (total_children > 1) {
*old_height = height / (container->children->length - 1); *old_height = height / (total_children - 1);
} else { } else {
*old_height = height; *old_height = height;
} }
@ -579,6 +598,7 @@ static void arrange_windows_r(swayc_t *container, double width, double height) {
sway_log(L_DEBUG, "Arranging %p vertically", container); sway_log(L_DEBUG, "Arranging %p vertically", container);
for (i = 0; i < container->children->length; ++i) { for (i = 0; i < container->children->length; ++i) {
swayc_t *child = container->children->items[i]; swayc_t *child = container->children->items[i];
if (child->arrange) continue;
sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, height, scale); sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, height, scale);
child->x = x; child->x = x;
child->y = y; child->y = y;

View file

@ -1,4 +1,5 @@
#include <strings.h> #include <strings.h>
#include "config.h"
#include "output.h" #include "output.h"
#include "log.h" #include "log.h"
@ -22,6 +23,26 @@ swayc_t *output_by_name(const char* name, const struct wlc_point *abs_pos) {
return NULL; return NULL;
} }
struct output_config *config_for_output(wlc_handle output) {
const char *name = wlc_output_get_name(output);
struct output_config *oc = NULL;
int i;
for (i = 0; i < config->output_configs->length; ++i) {
struct output_config *cur = config->output_configs->items[i];
if (strcasecmp(name, cur->name) == 0) {
sway_log(L_DEBUG, "Matched output config for %s", name);
oc = cur;
break;
}
if (strcasecmp("*", cur->name) == 0) {
sway_log(L_DEBUG, "Matched wildcard output config for %s", name);
oc = cur;
break;
}
}
return oc;
}
// Position is where on the edge (as absolute position) the adjacent output should be searched for. // Position is where on the edge (as absolute position) the adjacent output should be searched for.
swayc_t *swayc_adjacent_output(swayc_t *output, enum movement_direction dir, swayc_t *swayc_adjacent_output(swayc_t *output, enum movement_direction dir,
const struct wlc_point *abs_pos, bool pick_closest) { const struct wlc_point *abs_pos, bool pick_closest) {

View file

@ -46,10 +46,10 @@ int main(int argc, const char **argv) {
} }
int desired_output = atoi(argv[1]); int desired_output = atoi(argv[1]);
sway_log(L_INFO, "Using output %d of %d", desired_output, registry->outputs->length);
int i;
struct output_state *output = registry->outputs->items[desired_output]; struct output_state *output = registry->outputs->items[desired_output];
struct window *window = window_setup(registry, output->width, output->height, false); sway_log(L_INFO, "Using output %d of %d (%dx%d)", desired_output, registry->outputs->length, output->width, output->height);
int i;
struct window *window = window_setup(registry, output->width, output->height, true);
if (!window) { if (!window) {
sway_abort("Failed to create surfaces."); sway_abort("Failed to create surfaces.");
} }

View file

@ -69,7 +69,7 @@ struct window *window_setup(struct registry *registry, uint32_t width, uint32_t
window->surface = wl_compositor_create_surface(registry->compositor); window->surface = wl_compositor_create_surface(registry->compositor);
if (shell_surface) { if (shell_surface) {
window->shell_surface = wl_shell_get_shell_surface(registry->shell, window->surface); window->shell_surface = wl_shell_get_shell_surface(window->registry->shell, window->surface);
wl_shell_surface_add_listener(window->shell_surface, &surface_listener, window); wl_shell_surface_add_listener(window->shell_surface, &surface_listener, window);
wl_shell_surface_set_toplevel(window->shell_surface); wl_shell_surface_set_toplevel(window->shell_surface);
} }