desktop-shell: Remove multiple workspace support

It's not the most code ever, but it does make desktop-shell somewhat
more complicated for questionable (i.e. no) end-user benefit.

When desktop-shell is back in more healthy shape it could potentially be
reintroduced, but for now it's just making it more difficult to reason
about desktop-shell and fix it.

Signed-off-by: Daniel Stone <daniels@collabora.com>
dev
Daniel Stone 2 years ago committed by Marius Vlad
parent 48e8c158ea
commit 61d8238874
  1. 568
      desktop-shell/shell.c
  2. 17
      desktop-shell/shell.h
  3. 15
      man/weston-bindings.man
  4. 5
      man/weston.ini.man

@ -126,8 +126,6 @@ struct shell_surface {
struct weston_curtain *black_view;
} fullscreen;
struct weston_transform workspace_transform;
struct weston_output *fullscreen_output;
struct weston_output *output;
struct wl_listener output_destroy_listener;
@ -516,9 +514,6 @@ shell_configuration(struct desktop_shell *shell)
weston_config_section_get_string(section, "focus-animation", &s, "none");
shell->focus_animation_type = get_animation_type(s);
free(s);
weston_config_section_get_uint(section, "num-workspaces",
&shell->workspaces.num,
DEFAULT_NUM_WORKSPACES);
}
static int
@ -534,15 +529,6 @@ focus_surface_committed(struct weston_surface *es, int32_t sx, int32_t sy)
{
}
static struct focus_surface *
get_focus_surface(struct weston_surface *surface)
{
if (surface->committed == focus_surface_committed)
return surface->committed_private;
else
return NULL;
}
static bool
is_focus_view (struct weston_view *view)
{
@ -574,8 +560,6 @@ create_focus_surface(struct weston_compositor *ec,
weston_view_set_output(fsurf->curtain->view, output);
fsurf->curtain->view->is_mapped = true;
wl_list_init(&fsurf->workspace_transform.link);
return fsurf;
}
@ -768,21 +752,6 @@ restore_focus_state(struct desktop_shell *shell, struct workspace *ws)
}
}
static void
replace_focus_state(struct desktop_shell *shell, struct workspace *ws,
struct weston_seat *seat)
{
struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
struct focus_state *state;
wl_list_for_each(state, &ws->focus_list, link) {
if (state->seat == seat) {
focus_state_set_focus(state, keyboard->focus);
return;
}
}
}
static void
drop_focus_state(struct desktop_shell *shell, struct workspace *ws,
struct weston_surface *surface)
@ -876,7 +845,6 @@ workspace_destroy(struct workspace *ws)
focus_surface_destroy(ws->fsurf_back);
desktop_shell_destroy_layer(&ws->layer);
free(ws);
}
static void
@ -893,14 +861,13 @@ seat_destroyed(struct wl_listener *listener, void *data)
wl_list_remove(&state->link);
}
static struct workspace *
static void
workspace_create(struct desktop_shell *shell)
{
struct workspace *ws = malloc(sizeof *ws);
if (ws == NULL)
return NULL;
struct workspace *ws = &shell->workspace;
weston_layer_init(&ws->layer, shell->compositor);
weston_layer_set_position(&ws->layer, WESTON_LAYER_POSITION_NORMAL);
wl_list_init(&ws->focus_list);
wl_list_init(&ws->seat_destroyed_listener.link);
@ -908,343 +875,12 @@ workspace_create(struct desktop_shell *shell)
ws->fsurf_front = NULL;
ws->fsurf_back = NULL;
ws->focus_animation = NULL;
return ws;
}
static int
workspace_is_empty(struct workspace *ws)
{
return wl_list_empty(&ws->layer.view_list.link);
}
static struct workspace *
get_workspace(struct desktop_shell *shell, unsigned int index)
{
struct workspace **pws = shell->workspaces.array.data;
assert(index < shell->workspaces.num);
pws += index;
return *pws;
}
struct workspace *
get_current_workspace(struct desktop_shell *shell)
{
return get_workspace(shell, shell->workspaces.current);
}
static void
activate_workspace(struct desktop_shell *shell, unsigned int index)
{
struct workspace *ws;
ws = get_workspace(shell, index);
weston_layer_set_position(&ws->layer, WESTON_LAYER_POSITION_NORMAL);
shell->workspaces.current = index;
}
static unsigned int
get_output_height(struct weston_output *output)
{
return abs(output->region.extents.y1 - output->region.extents.y2);
}
static struct weston_transform *
view_get_transform(struct weston_view *view)
{
struct focus_surface *fsurf = NULL;
struct shell_surface *shsurf = NULL;
if (is_focus_view(view)) {
fsurf = get_focus_surface(view->surface);
return &fsurf->workspace_transform;
}
shsurf = get_shell_surface(view->surface);
if (shsurf)
return &shsurf->workspace_transform;
return NULL;
}
static void
view_translate(struct workspace *ws, struct weston_view *view, double d)
{
struct weston_transform *transform = view_get_transform(view);
if (!transform)
return;
if (wl_list_empty(&transform->link))
wl_list_insert(view->geometry.transformation_list.prev,
&transform->link);
weston_matrix_init(&transform->matrix);
weston_matrix_translate(&transform->matrix,
0.0, d, 0.0);
weston_view_geometry_dirty(view);
}
static void
workspace_translate_out(struct workspace *ws, double fraction)
{
struct weston_view *view;
unsigned int height;
double d;
wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) {
height = get_output_height(view->surface->output);
d = height * fraction;
view_translate(ws, view, d);
}
}
static void
workspace_translate_in(struct workspace *ws, double fraction)
{
struct weston_view *view;
unsigned int height;
double d;
wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) {
height = get_output_height(view->surface->output);
if (fraction > 0)
d = -(height - height * fraction);
else
d = height + height * fraction;
view_translate(ws, view, d);
}
}
static void
reverse_workspace_change_animation(struct desktop_shell *shell,
unsigned int index,
struct workspace *from,
struct workspace *to)
{
shell->workspaces.current = index;
shell->workspaces.anim_to = to;
shell->workspaces.anim_from = from;
shell->workspaces.anim_dir = -1 * shell->workspaces.anim_dir;
shell->workspaces.anim_timestamp = (struct timespec) { 0 };
weston_layer_set_position(&to->layer, WESTON_LAYER_POSITION_NORMAL);
weston_layer_set_position(&from->layer, WESTON_LAYER_POSITION_NORMAL - 1);
weston_compositor_schedule_repaint(shell->compositor);
}
static void
workspace_deactivate_transforms(struct workspace *ws)
{
struct weston_view *view;
struct weston_transform *transform;
wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) {
transform = view_get_transform(view);
if (!transform)
continue;
if (!wl_list_empty(&transform->link)) {
wl_list_remove(&transform->link);
wl_list_init(&transform->link);
}
weston_view_geometry_dirty(view);
}
}
static void
finish_workspace_change_animation(struct desktop_shell *shell,
struct workspace *from,
struct workspace *to)
{
struct weston_view *view;
weston_compositor_schedule_repaint(shell->compositor);
/* Views that extend past the bottom of the output are still
* visible after the workspace animation ends but before its layer
* is hidden. In that case, we need to damage below those views so
* that the screen is properly repainted. */
wl_list_for_each(view, &from->layer.view_list.link, layer_link.link)
weston_view_damage_below(view);
wl_list_remove(&shell->workspaces.animation.link);
workspace_deactivate_transforms(from);
workspace_deactivate_transforms(to);
shell->workspaces.anim_to = NULL;
weston_layer_unset_position(&shell->workspaces.anim_from->layer);
}
static void
animate_workspace_change_frame(struct weston_animation *animation,
struct weston_output *output,
const struct timespec *time)
{
struct desktop_shell *shell =
container_of(animation, struct desktop_shell,
workspaces.animation);
struct workspace *from = shell->workspaces.anim_from;
struct workspace *to = shell->workspaces.anim_to;
int64_t t;
double x, y;
if (workspace_is_empty(from) && workspace_is_empty(to)) {
finish_workspace_change_animation(shell, from, to);
return;
}
if (timespec_is_zero(&shell->workspaces.anim_timestamp)) {
if (shell->workspaces.anim_current == 0.0)
shell->workspaces.anim_timestamp = *time;
else
timespec_add_msec(&shell->workspaces.anim_timestamp,
time,
/* Inverse of movement function 'y' below. */
-(asin(1.0 - shell->workspaces.anim_current) *
DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH *
M_2_PI));
}
t = timespec_sub_to_msec(time, &shell->workspaces.anim_timestamp);
/*
* x = [0, π/2]
* y(x) = sin(x)
*/
x = t * (1.0/DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH) * M_PI_2;
y = sin(x);
if (t < DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH) {
weston_compositor_schedule_repaint(shell->compositor);
workspace_translate_out(from, shell->workspaces.anim_dir * y);
workspace_translate_in(to, shell->workspaces.anim_dir * y);
shell->workspaces.anim_current = y;
weston_compositor_schedule_repaint(shell->compositor);
}
else
finish_workspace_change_animation(shell, from, to);
}
static void
animate_workspace_change(struct desktop_shell *shell,
unsigned int index,
struct workspace *from,
struct workspace *to)
{
struct weston_output *output;
int dir;
if (index > shell->workspaces.current)
dir = -1;
else
dir = 1;
shell->workspaces.current = index;
shell->workspaces.anim_dir = dir;
shell->workspaces.anim_from = from;
shell->workspaces.anim_to = to;
shell->workspaces.anim_current = 0.0;
shell->workspaces.anim_timestamp = (struct timespec) { 0 };
output = container_of(shell->compositor->output_list.next,
struct weston_output, link);
wl_list_insert(&output->animation_list,
&shell->workspaces.animation.link);
weston_layer_set_position(&to->layer, WESTON_LAYER_POSITION_NORMAL);
weston_layer_set_position(&from->layer, WESTON_LAYER_POSITION_NORMAL - 1);
workspace_translate_in(to, 0);
restore_focus_state(shell, to);
weston_compositor_schedule_repaint(shell->compositor);
}
static void
update_workspace(struct desktop_shell *shell, unsigned int index,
struct workspace *from, struct workspace *to)
{
shell->workspaces.current = index;
weston_layer_set_position(&to->layer, WESTON_LAYER_POSITION_NORMAL);
weston_layer_unset_position(&from->layer);
}
static void
change_workspace(struct desktop_shell *shell, unsigned int index)
{
struct workspace *from;
struct workspace *to;
struct focus_state *state;
if (index == shell->workspaces.current)
return;
/* Don't change workspace when there is any fullscreen surfaces. */
if (!wl_list_empty(&shell->fullscreen_layer.view_list.link))
return;
from = get_current_workspace(shell);
to = get_workspace(shell, index);
if (shell->workspaces.anim_from == to &&
shell->workspaces.anim_to == from) {
restore_focus_state(shell, to);
reverse_workspace_change_animation(shell, index, from, to);
return;
}
if (shell->workspaces.anim_to != NULL)
finish_workspace_change_animation(shell,
shell->workspaces.anim_from,
shell->workspaces.anim_to);
restore_focus_state(shell, to);
if (shell->focus_animation_type != ANIMATION_NONE) {
wl_list_for_each(state, &from->focus_list, link)
if (state->keyboard_focus)
animate_focus_change(shell, from,
get_default_view(state->keyboard_focus), NULL);
wl_list_for_each(state, &to->focus_list, link)
if (state->keyboard_focus)
animate_focus_change(shell, to,
NULL, get_default_view(state->keyboard_focus));
}
if (workspace_is_empty(to) && workspace_is_empty(from))
update_workspace(shell, index, from, to);
else
animate_workspace_change(shell, index, from, to);
}
static bool
workspace_has_only(struct workspace *ws, struct weston_surface *surface)
{
struct wl_list *list = &ws->layer.view_list.link;
struct wl_list *e;
if (wl_list_empty(list))
return false;
e = list->next;
if (e->next != list)
return false;
return container_of(e, struct weston_view, layer_link.link)->surface == surface;
return &shell->workspace;
}
static void
@ -1267,68 +903,6 @@ surface_keyboard_focus_lost(struct weston_surface *surface)
}
}
static void
take_surface_to_workspace_by_seat(struct desktop_shell *shell,
struct weston_seat *seat,
unsigned int index)
{
struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
struct weston_surface *surface;
struct weston_view *view;
struct shell_surface *shsurf;
struct workspace *from;
struct workspace *to;
struct focus_state *state;
surface = weston_surface_get_main_surface(keyboard->focus);
view = get_default_view(surface);
if (view == NULL ||
index == shell->workspaces.current ||
is_focus_view(view))
return;
from = get_current_workspace(shell);
to = get_workspace(shell, index);
weston_layer_entry_remove(&view->layer_link);
weston_layer_entry_insert(&to->layer.view_list, &view->layer_link);
shsurf = get_shell_surface(surface);
if (shsurf != NULL)
shell_surface_update_child_surface_layers(shsurf);
replace_focus_state(shell, to, seat);
drop_focus_state(shell, from, surface);
if (shell->workspaces.anim_from == to &&
shell->workspaces.anim_to == from) {
reverse_workspace_change_animation(shell, index, from, to);
return;
}
if (shell->workspaces.anim_to != NULL)
finish_workspace_change_animation(shell,
shell->workspaces.anim_from,
shell->workspaces.anim_to);
if (workspace_is_empty(from) &&
workspace_has_only(to, surface))
update_workspace(shell, index, from, to);
else {
if (shsurf != NULL &&
wl_list_empty(&shsurf->workspace_transform.link))
wl_list_insert(&shell->workspaces.anim_sticky_list,
&shsurf->workspace_transform.link);
animate_workspace_change(shell, index, from, to);
}
state = ensure_focus_state(shell, seat);
if (state != NULL)
focus_state_set_focus(state, surface);
}
static void
touch_move_grab_down(struct weston_touch_grab *grab,
const struct timespec *time,
@ -2306,8 +1880,6 @@ desktop_surface_added(struct weston_desktop_surface *desktop_surface,
wl_list_init(&shsurf->rotation.transform.link);
weston_matrix_init(&shsurf->rotation.rotation);
wl_list_init(&shsurf->workspace_transform.link);
/*
* initialize list as well as link. The latter allows to use
* wl_list_remove() even when this surface is not in another list.
@ -4570,86 +4142,6 @@ force_kill_binding(struct weston_keyboard *keyboard,
kill(pid, SIGKILL);
}
static void
workspace_up_binding(struct weston_keyboard *keyboard,
const struct timespec *time, uint32_t key, void *data)
{
struct desktop_shell *shell = data;
unsigned int new_index = shell->workspaces.current;
if (shell->locked)
return;
if (new_index != 0)
new_index--;
change_workspace(shell, new_index);
}
static void
workspace_down_binding(struct weston_keyboard *keyboard,
const struct timespec *time, uint32_t key, void *data)
{
struct desktop_shell *shell = data;
unsigned int new_index = shell->workspaces.current;
if (shell->locked)
return;
if (new_index < shell->workspaces.num - 1)
new_index++;
change_workspace(shell, new_index);
}
static void
workspace_f_binding(struct weston_keyboard *keyboard,
const struct timespec *time, uint32_t key, void *data)
{
struct desktop_shell *shell = data;
unsigned int new_index;
if (shell->locked)
return;
new_index = key - KEY_F1;
if (new_index >= shell->workspaces.num)
new_index = shell->workspaces.num - 1;
change_workspace(shell, new_index);
}
static void
workspace_move_surface_up_binding(struct weston_keyboard *keyboard,
const struct timespec *time, uint32_t key,
void *data)
{
struct desktop_shell *shell = data;
unsigned int new_index = shell->workspaces.current;
if (shell->locked)
return;
if (new_index != 0)
new_index--;
take_surface_to_workspace_by_seat(shell, keyboard->seat, new_index);
}
static void
workspace_move_surface_down_binding(struct weston_keyboard *keyboard,
const struct timespec *time, uint32_t key,
void *data)
{
struct desktop_shell *shell = data;
unsigned int new_index = shell->workspaces.current;
if (shell->locked)
return;
if (new_index < shell->workspaces.num - 1)
new_index++;
take_surface_to_workspace_by_seat(shell, keyboard->seat, new_index);
}
static void
shell_reposition_view_on_output_change(struct weston_view *view)
{
@ -4703,16 +4195,12 @@ void
shell_for_each_layer(struct desktop_shell *shell,
shell_for_each_layer_func_t func, void *data)
{
struct workspace **ws;
func(shell, &shell->fullscreen_layer, data);
func(shell, &shell->panel_layer, data);
func(shell, &shell->background_layer, data);
func(shell, &shell->lock_layer, data);
func(shell, &shell->input_panel_layer, data);
wl_array_for_each(ws, &shell->workspaces.array)
func(shell, &(*ws)->layer, data);
func(shell, &shell->workspace.layer, data);
}
static void
@ -4917,7 +4405,6 @@ shell_destroy(struct wl_listener *listener, void *data)
{
struct desktop_shell *shell =
container_of(listener, struct desktop_shell, destroy_listener);
struct workspace **ws;
struct shell_output *shell_output, *tmp;
struct shell_seat *shseat, *shseat_next;
@ -4950,9 +4437,7 @@ shell_destroy(struct wl_listener *listener, void *data)
weston_desktop_destroy(shell->desktop);
wl_array_for_each(ws, &shell->workspaces.array)
workspace_destroy(*ws);
wl_array_release(&shell->workspaces.array);
workspace_destroy(&shell->workspace);
desktop_shell_destroy_layer(&shell->panel_layer);
desktop_shell_destroy_layer(&shell->background_layer);
@ -4969,7 +4454,6 @@ static void
shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
{
uint32_t mod;
int i, num_workspace_bindings;
if (shell->allow_zap)
weston_compositor_add_key_binding(ec, KEY_BACKSPACE,
@ -5026,27 +4510,6 @@ shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
ec);
weston_compositor_add_key_binding(ec, KEY_K, mod,
force_kill_binding, shell);
weston_compositor_add_key_binding(ec, KEY_UP, mod,
workspace_up_binding, shell);
weston_compositor_add_key_binding(ec, KEY_DOWN, mod,
workspace_down_binding, shell);
weston_compositor_add_key_binding(ec, KEY_UP, mod | MODIFIER_SHIFT,
workspace_move_surface_up_binding,
shell);
weston_compositor_add_key_binding(ec, KEY_DOWN, mod | MODIFIER_SHIFT,
workspace_move_surface_down_binding,
shell);
/* Add bindings for mod+F[1-6] for workspace 1 to 6. */
if (shell->workspaces.num > 1) {
num_workspace_bindings = shell->workspaces.num;
if (num_workspace_bindings > 6)
num_workspace_bindings = 6;
for (i = 0; i < num_workspace_bindings; i++)
weston_compositor_add_key_binding(ec, KEY_F1 + i, mod,
workspace_f_binding,
shell);
}
weston_install_debug_key_binding(ec, mod);
}
@ -5067,8 +4530,6 @@ wet_shell_init(struct weston_compositor *ec,
{
struct weston_seat *seat;
struct desktop_shell *shell;
struct workspace **pws;
unsigned int i;
struct wl_event_loop *loop;
shell = zalloc(sizeof *shell);
@ -5104,8 +4565,6 @@ wet_shell_init(struct weston_compositor *ec,
weston_layer_set_position(&shell->background_layer,
WESTON_LAYER_POSITION_BACKGROUND);
wl_array_init(&shell->workspaces.array);
wl_list_init(&shell->workspaces.client_list);
wl_list_init(&shell->seat_list);
if (input_panel_setup(shell) < 0)
@ -5117,23 +4576,10 @@ wet_shell_init(struct weston_compositor *ec,
shell_configuration(shell);
for (i = 0; i < shell->workspaces.num; i++) {
pws = wl_array_add(&shell->workspaces.array, sizeof *pws);
if (pws == NULL)
return -1;
*pws = workspace_create(shell);
if (*pws == NULL)
return -1;
}
activate_workspace(shell, 0);
workspace_create(shell);
weston_layer_init(&shell->minimized_layer, ec);
wl_list_init(&shell->workspaces.anim_sticky_list);
wl_list_init(&shell->workspaces.animation.link);
shell->workspaces.animation.frame = animate_workspace_change_frame;
shell->desktop = weston_desktop_create(ec, &shell_desktop_api, shell);
if (!shell->desktop)
return -1;

@ -47,7 +47,6 @@ enum fade_type {
struct focus_surface {
struct weston_curtain *curtain;
struct weston_transform workspace_transform;
};
struct workspace {
@ -128,21 +127,7 @@ struct desktop_shell {
struct weston_surface *lock_surface;
struct wl_listener lock_surface_listener;
struct {
struct wl_array array;
unsigned int current;
unsigned int num;
struct wl_list client_list;
struct weston_animation animation;
struct wl_list anim_sticky_list;
int anim_dir;
struct timespec anim_timestamp;
double anim_current;
struct workspace *anim_from;
struct workspace *anim_to;
} workspaces;
struct workspace workspace;
struct {
struct wl_resource *binding;

@ -43,21 +43,6 @@ Zoom desktop in (or out)
Switch active window
.P
.RE
.B mod + Up, mod + Down
.RS 4
Increment/decrement active workspace number, if there are multiple
.P
.RE
.B mod + Shift + Up, mod + Shift + Down
.RS 4
Move active window to the succeeding/preceding workspace, if possible
.P
.RE
.B mod + F1/F2/F3/F4/F5/F6
.RS 4
Jump to the numbered workspace, if it exists
.P
.RE
.B Ctrl + Alt + Backspace
.RS 4
If supported, terminate Weston. (Note this combination often is used to hard restart Xorg.)

@ -426,11 +426,6 @@ for windows, controlling the backlight and zooming the desktop. See
.BR weston-bindings (7).
Possible values: none, ctrl, alt, super (default)
.TP 7
.BI "num-workspaces=" 6
defines the number of workspaces (unsigned integer). The user can switch
workspaces by using the
binding+F1, F2 keys. If this key is not set, fall back to one workspace.
.TP 7
.BI "cursor-theme=" theme
sets the cursor theme (string).
.TP 7

Loading…
Cancel
Save