|
|
|
/*
|
|
|
|
* Copyright © 2010-2012 Intel Corporation
|
|
|
|
* Copyright © 2011-2012 Collabora, Ltd.
|
|
|
|
* Copyright © 2013 Raspberry Pi Foundation
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
* Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
* DEALINGS IN THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <linux/input.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
|
|
#include "shell.h"
|
|
|
|
#include "weston.h"
|
|
|
|
#include "weston-desktop-shell-server-protocol.h"
|
|
|
|
#include "shared/config-parser.h"
|
|
|
|
#include "shared/helpers.h"
|
|
|
|
#include "xdg-shell-unstable-v5-server-protocol.h"
|
|
|
|
|
|
|
|
#define DEFAULT_NUM_WORKSPACES 1
|
|
|
|
#define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200
|
|
|
|
|
|
|
|
#ifndef static_assert
|
|
|
|
#define static_assert(cond, msg)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
struct focus_state {
|
|
|
|
struct weston_seat *seat;
|
|
|
|
struct workspace *ws;
|
|
|
|
struct weston_surface *keyboard_focus;
|
|
|
|
struct wl_list link;
|
|
|
|
struct wl_listener seat_destroy_listener;
|
|
|
|
struct wl_listener surface_destroy_listener;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum shell_surface_type {
|
|
|
|
SHELL_SURFACE_NONE,
|
|
|
|
SHELL_SURFACE_TOPLEVEL,
|
|
|
|
SHELL_SURFACE_POPUP,
|
|
|
|
SHELL_SURFACE_XWAYLAND
|
|
|
|
};
|
|
|
|
|
|
|
|
struct shell_client;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Surface stacking and ordering.
|
|
|
|
*
|
|
|
|
* This is handled using several linked lists of surfaces, organised into
|
|
|
|
* ‘layers’. The layers are ordered, and each of the surfaces in one layer are
|
|
|
|
* above all of the surfaces in the layer below. The set of layers is static and
|
|
|
|
* in the following order (top-most first):
|
|
|
|
* • Lock layer (only ever displayed on its own)
|
|
|
|
* • Cursor layer
|
|
|
|
* • Input panel layer
|
|
|
|
* • Fullscreen layer
|
|
|
|
* • Panel layer
|
|
|
|
* • Workspace layers
|
|
|
|
* • Background layer
|
|
|
|
*
|
|
|
|
* The list of layers may be manipulated to remove whole layers of surfaces from
|
|
|
|
* display. For example, when locking the screen, all layers except the lock
|
|
|
|
* layer are removed.
|
|
|
|
*
|
|
|
|
* A surface’s layer is modified on configuring the surface, in
|
|
|
|
* set_surface_type() (which is only called when the surface’s type change is
|
|
|
|
* _committed_). If a surface’s type changes (e.g. when making a window
|
|
|
|
* fullscreen) its layer changes too.
|
|
|
|
*
|
|
|
|
* In order to allow popup and transient surfaces to be correctly stacked above
|
|
|
|
* their parent surfaces, each surface tracks both its parent surface, and a
|
|
|
|
* linked list of its children. When a surface’s layer is updated, so are the
|
|
|
|
* layers of its children. Note that child surfaces are *not* the same as
|
|
|
|
* subsurfaces — child/parent surfaces are purely for maintaining stacking
|
|
|
|
* order.
|
|
|
|
*
|
|
|
|
* The children_link list of siblings of a surface (i.e. those surfaces which
|
|
|
|
* have the same parent) only contains weston_surfaces which have a
|
|
|
|
* shell_surface. Stacking is not implemented for non-shell_surface
|
|
|
|
* weston_surfaces. This means that the following implication does *not* hold:
|
|
|
|
* (shsurf->parent != NULL) ⇒ !wl_list_is_empty(shsurf->children_link)
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct shell_surface {
|
|
|
|
struct wl_resource *resource;
|
|
|
|
struct wl_signal destroy_signal;
|
|
|
|
struct shell_client *owner;
|
|
|
|
struct wl_resource *owner_resource;
|
|
|
|
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
13 years ago
|
|
|
struct weston_surface *surface;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *view;
|
|
|
|
int32_t last_width, last_height;
|
|
|
|
struct wl_listener surface_destroy_listener;
|
|
|
|
struct wl_listener resource_destroy_listener;
|
|
|
|
|
|
|
|
struct weston_surface *parent;
|
|
|
|
struct wl_list children_list; /* child surfaces of this one */
|
|
|
|
struct wl_list children_link; /* sibling surfaces of this one */
|
|
|
|
struct desktop_shell *shell;
|
|
|
|
|
|
|
|
enum shell_surface_type type;
|
|
|
|
char *title, *class;
|
|
|
|
int32_t saved_x, saved_y;
|
|
|
|
bool saved_position_valid;
|
|
|
|
bool saved_rotation_valid;
|
|
|
|
int unresponsive, grabbed;
|
|
|
|
uint32_t resize_edges;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
struct weston_transform transform;
|
|
|
|
struct weston_matrix rotation;
|
|
|
|
} rotation;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
struct wl_list grab_link;
|
|
|
|
int32_t x, y;
|
|
|
|
struct shell_seat *shseat;
|
|
|
|
uint32_t serial;
|
|
|
|
} popup;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
int32_t x, y;
|
|
|
|
uint32_t flags;
|
|
|
|
} transient;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
enum wl_shell_surface_fullscreen_method type;
|
|
|
|
struct weston_transform transform; /* matrix from x, y */
|
|
|
|
uint32_t framerate;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *black_view;
|
|
|
|
} fullscreen;
|
|
|
|
|
|
|
|
struct weston_transform workspace_transform;
|
|
|
|
|
|
|
|
struct weston_output *fullscreen_output;
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
13 years ago
|
|
|
struct weston_output *output;
|
|
|
|
struct wl_list link;
|
|
|
|
|
|
|
|
const struct weston_shell_client *client;
|
|
|
|
|
shell: Centralize management of sending configure requests
Currently, there's a giant bug in how xdg-shell state management
is done. If a client calls set_fullscreen and then set_maximized,
it will get two configure events:
=> set_fullscreen
<= configure(800, 600, [STATE_FULLSCREEN])
=> set_maximized
<= configure(800, 560, [STATE_FULLSCREEN, STATE_MAXIMIZED])
Since fullscreen takes precedence over maximized, the client will
render full-screen at 800x600 first, and then 800x560 next. As
a result, the surface gets the wrong size.
This is because the code that sends out configure requests is
"immediate" -- when an app calls set_maximized, we immediately
send out the configure event that would have happened if we
transitioned immediately into maximized mode.
In wl_shell, this is correct behavior. However, in xdg-shell,
this is wrong. State needs to be more carefully managed in
xdg-shell, as states aren't exclusive.
Pull all the code that sends out configure events out and send
them centrally, based on Weston's on surface state management.
This should work with both wl_shell and xdg_shell's strategies.
11 years ago
|
|
|
struct surface_state {
|
|
|
|
bool maximized;
|
|
|
|
bool fullscreen;
|
|
|
|
bool relative;
|
|
|
|
bool lowered;
|
|
|
|
} state, next_state, requested_state; /* surface states */
|
|
|
|
bool state_changed;
|
|
|
|
bool state_requested;
|
|
|
|
|
|
|
|
struct {
|
shell: Replace set_margin with set_window_geometry
Currently, there is a fun flicker when toggling maximization or
fullscreen on a window in mutter or more sophisicated compositors
and WMs.
What happens is that the client want so go maximized, so we
calculate the size that we want the window to resize to (640x480),
and then add on its margins to find the buffer size (+10 = 660x500),
and then send out a configure event for that size. The client
renders to that size, realizes that it's maximized, and then
says "oh hey, my margins are actually 0 now!", and so the compositor
has to send out another configure event.
In order to fix this, make the the configure request correspond to
the window geometry we'd like the window to be at. At the same time,
replace set_margin with set_window_geometry, where we specify a rect
rather than a border around the window.
11 years ago
|
|
|
int32_t x, y, width, height;
|
|
|
|
} geometry, next_geometry;
|
|
|
|
bool has_set_geometry, has_next_geometry;
|
|
|
|
|
|
|
|
int focus_count;
|
|
|
|
|
|
|
|
bool destroying;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct shell_grab {
|
|
|
|
struct weston_pointer_grab grab;
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
struct wl_listener shsurf_destroy_listener;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct shell_touch_grab {
|
|
|
|
struct weston_touch_grab grab;
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
struct wl_listener shsurf_destroy_listener;
|
|
|
|
struct weston_touch *touch;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct weston_move_grab {
|
|
|
|
struct shell_grab base;
|
|
|
|
wl_fixed_t dx, dy;
|
|
|
|
bool client_initiated;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct weston_touch_move_grab {
|
|
|
|
struct shell_touch_grab base;
|
|
|
|
int active;
|
|
|
|
wl_fixed_t dx, dy;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct rotate_grab {
|
|
|
|
struct shell_grab base;
|
|
|
|
struct weston_matrix rotation;
|
|
|
|
struct {
|
|
|
|
float x;
|
|
|
|
float y;
|
|
|
|
} center;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct shell_seat {
|
|
|
|
struct weston_seat *seat;
|
|
|
|
struct wl_listener seat_destroy_listener;
|
|
|
|
struct weston_surface *focused_surface;
|
|
|
|
|
|
|
|
struct wl_listener caps_changed_listener;
|
|
|
|
struct wl_listener pointer_focus_listener;
|
|
|
|
struct wl_listener keyboard_focus_listener;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
struct weston_pointer_grab grab;
|
|
|
|
struct weston_touch_grab touch_grab;
|
|
|
|
struct wl_list surfaces_list;
|
|
|
|
struct wl_client *client;
|
|
|
|
int32_t initial_up;
|
|
|
|
enum { POINTER, TOUCH } type;
|
|
|
|
} popup_grab;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct shell_client {
|
|
|
|
struct wl_resource *resource;
|
|
|
|
struct wl_client *client;
|
|
|
|
struct desktop_shell *shell;
|
|
|
|
struct wl_listener destroy_listener;
|
|
|
|
struct wl_event_source *ping_timer;
|
|
|
|
uint32_t ping_serial;
|
|
|
|
int unresponsive;
|
|
|
|
struct wl_list surface_list;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct desktop_shell *
|
|
|
|
shell_surface_get_shell(struct shell_surface *shsurf);
|
|
|
|
|
|
|
|
static void
|
|
|
|
surface_rotate(struct shell_surface *surface, struct weston_pointer *pointer);
|
|
|
|
|
shell: wait for desktop-shell init before fade in
On Raspberry Pi, weston-desktop-shell is so slow to start, that the
compositor has time to run the fade-in before the wallpaper is up. The
user launching Weston sees the screen flipping to black, the fbcon
fading in, and then the desktop popping up.
To fix this, wait for the weston-desktop-shell to draw
everything before starting the initial fade-in. A new request is
added to the private desktop-shell protocol to signal it. If a
desktop-shell client does not support the new request, the fade-in
happens already at bind time.
If weston-desktop-shell crashes, or does not send the 'desktop_ready'
request in 15 seconds, the compositor will fade in anyway. This should
avoid a blocked screen in case weston-desktop-shell malfunction.
shell_fade_startup() does not directly start the fade-in but schedules
an idle callback, so that the compositor can process all pending events
before starting the fade clock. Otherwise (on RPi) we risk skipping part
of the animation. Yes, it is a hack, that should have been done in
window.c and weston-desktop-shell instead.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
12 years ago
|
|
|
static void
|
|
|
|
shell_fade_startup(struct desktop_shell *shell);
|
|
|
|
|
|
|
|
static struct shell_seat *
|
|
|
|
get_shell_seat(struct weston_seat *seat);
|
|
|
|
|
|
|
|
static void
|
|
|
|
get_output_panel_size(struct desktop_shell *shell,
|
|
|
|
struct weston_output *output,
|
|
|
|
int *width, int *height);
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_update_child_surface_layers(struct shell_surface *shsurf);
|
|
|
|
|
|
|
|
static bool
|
|
|
|
shell_surface_is_wl_shell_surface(struct shell_surface *shsurf);
|
|
|
|
|
|
|
|
static bool
|
|
|
|
shell_surface_is_xdg_surface(struct shell_surface *shsurf);
|
|
|
|
|
|
|
|
static bool
|
|
|
|
shell_surface_is_xdg_popup(struct shell_surface *shsurf);
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_set_parent(struct shell_surface *shsurf,
|
|
|
|
struct weston_surface *parent);
|
|
|
|
|
compositor: add weston_surface_set_label_func()
When printing out logs from Weston's actions, mainly for debugging, it
can be very difficult to identify the different surfaces. Inspecting
the configure function pointer is not useful, as the configure functions
may live in modules.
Add vfunc get_label to weston_surface, which will produce a short,
human-readable description of the surface, which allows identifying it
better, rather than just looking at the surface size, for instance.
Set the label function from most parts of Weston, to identify cursors and
drag icons, and panels, backgrounds, screensavers and lock surfaces, and
the desktop shell's application surfaces.
v2: renamed 'description' to 'label', so we get
weston_surface_set_label_func().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
11 years ago
|
|
|
static int
|
|
|
|
shell_surface_get_label(struct weston_surface *surface, char *buf, size_t len)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
const char *typestr[] = {
|
|
|
|
[SHELL_SURFACE_NONE] = "unidentified",
|
|
|
|
[SHELL_SURFACE_TOPLEVEL] = "top-level",
|
|
|
|
[SHELL_SURFACE_POPUP] = "popup",
|
|
|
|
[SHELL_SURFACE_XWAYLAND] = "Xwayland",
|
|
|
|
};
|
|
|
|
const char *t, *c;
|
|
|
|
|
|
|
|
shsurf = get_shell_surface(surface);
|
|
|
|
if (!shsurf)
|
|
|
|
return snprintf(buf, len, "unidentified window");
|
|
|
|
|
|
|
|
t = shsurf->title;
|
|
|
|
c = shsurf->class;
|
|
|
|
|
|
|
|
return snprintf(buf, len, "%s window%s%s%s%s%s",
|
|
|
|
typestr[shsurf->type],
|
|
|
|
t ? " '" : "", t ?: "", t ? "'" : "",
|
|
|
|
c ? " of " : "", c ?: "");
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
shell_surface_is_top_fullscreen(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell;
|
|
|
|
struct weston_view *view;
|
|
|
|
struct shell_surface *top_fs_shsurf = NULL;
|
|
|
|
|
|
|
|
shell = shell_surface_get_shell(shsurf);
|
|
|
|
|
|
|
|
if (wl_list_empty(&shell->fullscreen_layer.view_list.link))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/* Find topmost shsurf on the same fullscreen output on which shsurf
|
|
|
|
* is displaying. We don't care about other outputs.
|
|
|
|
*/
|
|
|
|
wl_list_for_each(view, &shell->fullscreen_layer.view_list.link,
|
|
|
|
layer_link.link) {
|
|
|
|
struct shell_surface *cand_shsurf = get_shell_surface(view->surface);
|
|
|
|
|
|
|
|
if (cand_shsurf &&
|
|
|
|
(cand_shsurf->fullscreen_output == shsurf->fullscreen_output)) {
|
|
|
|
top_fs_shsurf = cand_shsurf;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (shsurf == top_fs_shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
destroy_shell_grab_shsurf(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct shell_grab *grab;
|
|
|
|
|
|
|
|
grab = container_of(listener, struct shell_grab,
|
|
|
|
shsurf_destroy_listener);
|
|
|
|
|
|
|
|
grab->shsurf = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct weston_view *
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
get_default_view(struct weston_surface *surface)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
struct weston_view *view;
|
|
|
|
|
|
|
|
if (!surface || wl_list_empty(&surface->views))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
shsurf = get_shell_surface(surface);
|
|
|
|
if (shsurf)
|
|
|
|
return shsurf->view;
|
|
|
|
|
|
|
|
wl_list_for_each(view, &surface->views, surface_link)
|
|
|
|
if (weston_view_is_mapped(view))
|
|
|
|
return view;
|
|
|
|
|
|
|
|
return container_of(surface->views.next, struct weston_view, surface_link);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
popup_grab_end(struct weston_pointer *pointer);
|
|
|
|
static void
|
|
|
|
touch_popup_grab_end(struct weston_touch *touch);
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_grab_start(struct shell_grab *grab,
|
|
|
|
const struct weston_pointer_grab_interface *interface,
|
|
|
|
struct shell_surface *shsurf,
|
|
|
|
struct weston_pointer *pointer,
|
|
|
|
enum weston_desktop_shell_cursor cursor)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = shsurf->shell;
|
|
|
|
struct weston_touch *touch = weston_seat_get_touch(pointer->seat);
|
|
|
|
|
|
|
|
popup_grab_end(pointer);
|
|
|
|
if (touch)
|
|
|
|
touch_popup_grab_end(touch);
|
|
|
|
|
|
|
|
grab->grab.interface = interface;
|
|
|
|
grab->shsurf = shsurf;
|
|
|
|
grab->shsurf_destroy_listener.notify = destroy_shell_grab_shsurf;
|
|
|
|
wl_signal_add(&shsurf->destroy_signal,
|
|
|
|
&grab->shsurf_destroy_listener);
|
|
|
|
|
|
|
|
shsurf->grabbed = 1;
|
|
|
|
weston_pointer_start_grab(pointer, &grab->grab);
|
|
|
|
if (shell->child.desktop_shell) {
|
|
|
|
weston_desktop_shell_send_grab_cursor(shell->child.desktop_shell,
|
|
|
|
cursor);
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_pointer_set_focus(pointer,
|
|
|
|
get_default_view(shell->grab_surface),
|
|
|
|
wl_fixed_from_int(0),
|
|
|
|
wl_fixed_from_int(0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
get_output_panel_size(struct desktop_shell *shell,
|
|
|
|
struct weston_output *output,
|
|
|
|
int *width,
|
|
|
|
int *height)
|
shell: Centralize management of sending configure requests
Currently, there's a giant bug in how xdg-shell state management
is done. If a client calls set_fullscreen and then set_maximized,
it will get two configure events:
=> set_fullscreen
<= configure(800, 600, [STATE_FULLSCREEN])
=> set_maximized
<= configure(800, 560, [STATE_FULLSCREEN, STATE_MAXIMIZED])
Since fullscreen takes precedence over maximized, the client will
render full-screen at 800x600 first, and then 800x560 next. As
a result, the surface gets the wrong size.
This is because the code that sends out configure requests is
"immediate" -- when an app calls set_maximized, we immediately
send out the configure event that would have happened if we
transitioned immediately into maximized mode.
In wl_shell, this is correct behavior. However, in xdg-shell,
this is wrong. State needs to be more carefully managed in
xdg-shell, as states aren't exclusive.
Pull all the code that sends out configure events out and send
them centrally, based on Weston's on surface state management.
This should work with both wl_shell and xdg_shell's strategies.
11 years ago
|
|
|
{
|
|
|
|
struct weston_view *view;
|
|
|
|
|
|
|
|
*width = 0;
|
|
|
|
*height = 0;
|
shell: Centralize management of sending configure requests
Currently, there's a giant bug in how xdg-shell state management
is done. If a client calls set_fullscreen and then set_maximized,
it will get two configure events:
=> set_fullscreen
<= configure(800, 600, [STATE_FULLSCREEN])
=> set_maximized
<= configure(800, 560, [STATE_FULLSCREEN, STATE_MAXIMIZED])
Since fullscreen takes precedence over maximized, the client will
render full-screen at 800x600 first, and then 800x560 next. As
a result, the surface gets the wrong size.
This is because the code that sends out configure requests is
"immediate" -- when an app calls set_maximized, we immediately
send out the configure event that would have happened if we
transitioned immediately into maximized mode.
In wl_shell, this is correct behavior. However, in xdg-shell,
this is wrong. State needs to be more carefully managed in
xdg-shell, as states aren't exclusive.
Pull all the code that sends out configure events out and send
them centrally, based on Weston's on surface state management.
This should work with both wl_shell and xdg_shell's strategies.
11 years ago
|
|
|
|
|
|
|
if (!output)
|
|
|
|
return;
|
shell: Centralize management of sending configure requests
Currently, there's a giant bug in how xdg-shell state management
is done. If a client calls set_fullscreen and then set_maximized,
it will get two configure events:
=> set_fullscreen
<= configure(800, 600, [STATE_FULLSCREEN])
=> set_maximized
<= configure(800, 560, [STATE_FULLSCREEN, STATE_MAXIMIZED])
Since fullscreen takes precedence over maximized, the client will
render full-screen at 800x600 first, and then 800x560 next. As
a result, the surface gets the wrong size.
This is because the code that sends out configure requests is
"immediate" -- when an app calls set_maximized, we immediately
send out the configure event that would have happened if we
transitioned immediately into maximized mode.
In wl_shell, this is correct behavior. However, in xdg-shell,
this is wrong. State needs to be more carefully managed in
xdg-shell, as states aren't exclusive.
Pull all the code that sends out configure events out and send
them centrally, based on Weston's on surface state management.
This should work with both wl_shell and xdg_shell's strategies.
11 years ago
|
|
|
|
|
|
|
wl_list_for_each(view, &shell->panel_layer.view_list.link, layer_link.link) {
|
|
|
|
float x, y;
|
|
|
|
|
|
|
|
if (view->surface->output != output)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
switch (shell->panel_position) {
|
|
|
|
case WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP:
|
|
|
|
case WESTON_DESKTOP_SHELL_PANEL_POSITION_BOTTOM:
|
|
|
|
weston_view_to_global_float(view,
|
|
|
|
view->surface->width, 0,
|
|
|
|
&x, &y);
|
|
|
|
|
|
|
|
*width = (int)x - output->x;
|
|
|
|
*height = view->surface->height + (int) y - output->y;
|
|
|
|
return;
|
|
|
|
|
|
|
|
case WESTON_DESKTOP_SHELL_PANEL_POSITION_LEFT:
|
|
|
|
case WESTON_DESKTOP_SHELL_PANEL_POSITION_RIGHT:
|
|
|
|
weston_view_to_global_float(view,
|
|
|
|
0, view->surface->height,
|
|
|
|
&x, &y);
|
|
|
|
|
|
|
|
*width = view->surface->width + (int)x - output->x;
|
|
|
|
*height = (int)y - output->y;
|
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* we've already set width and height to
|
|
|
|
* fallback values. */
|
shell: Centralize management of sending configure requests
Currently, there's a giant bug in how xdg-shell state management
is done. If a client calls set_fullscreen and then set_maximized,
it will get two configure events:
=> set_fullscreen
<= configure(800, 600, [STATE_FULLSCREEN])
=> set_maximized
<= configure(800, 560, [STATE_FULLSCREEN, STATE_MAXIMIZED])
Since fullscreen takes precedence over maximized, the client will
render full-screen at 800x600 first, and then 800x560 next. As
a result, the surface gets the wrong size.
This is because the code that sends out configure requests is
"immediate" -- when an app calls set_maximized, we immediately
send out the configure event that would have happened if we
transitioned immediately into maximized mode.
In wl_shell, this is correct behavior. However, in xdg-shell,
this is wrong. State needs to be more carefully managed in
xdg-shell, as states aren't exclusive.
Pull all the code that sends out configure events out and send
them centrally, based on Weston's on surface state management.
This should work with both wl_shell and xdg_shell's strategies.
11 years ago
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* the correct view wasn't found */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
get_output_work_area(void *data,
|
|
|
|
struct weston_output *output,
|
|
|
|
pixman_rectangle32_t *area)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = data;
|
|
|
|
int32_t panel_width = 0, panel_height = 0;
|
|
|
|
|
|
|
|
area->x = output->x;
|
|
|
|
area->y = output->y;
|
|
|
|
|
|
|
|
get_output_panel_size(shell, output, &panel_width, &panel_height);
|
|
|
|
switch (shell->panel_position) {
|
|
|
|
case WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP:
|
|
|
|
default:
|
|
|
|
area->y += panel_height;
|
|
|
|
case WESTON_DESKTOP_SHELL_PANEL_POSITION_BOTTOM:
|
|
|
|
area->width = output->width;
|
|
|
|
area->height = output->height - panel_height;
|
|
|
|
break;
|
|
|
|
case WESTON_DESKTOP_SHELL_PANEL_POSITION_LEFT:
|
|
|
|
area->x += panel_width;
|
|
|
|
case WESTON_DESKTOP_SHELL_PANEL_POSITION_RIGHT:
|
|
|
|
area->width = output->width - panel_width;
|
|
|
|
area->height = output->height;
|
|
|
|
break;
|
|
|
|
}
|
shell: Centralize management of sending configure requests
Currently, there's a giant bug in how xdg-shell state management
is done. If a client calls set_fullscreen and then set_maximized,
it will get two configure events:
=> set_fullscreen
<= configure(800, 600, [STATE_FULLSCREEN])
=> set_maximized
<= configure(800, 560, [STATE_FULLSCREEN, STATE_MAXIMIZED])
Since fullscreen takes precedence over maximized, the client will
render full-screen at 800x600 first, and then 800x560 next. As
a result, the surface gets the wrong size.
This is because the code that sends out configure requests is
"immediate" -- when an app calls set_maximized, we immediately
send out the configure event that would have happened if we
transitioned immediately into maximized mode.
In wl_shell, this is correct behavior. However, in xdg-shell,
this is wrong. State needs to be more carefully managed in
xdg-shell, as states aren't exclusive.
Pull all the code that sends out configure events out and send
them centrally, based on Weston's on surface state management.
This should work with both wl_shell and xdg_shell's strategies.
11 years ago
|
|
|
}
|
|
|
|
|
|
|
|
static struct shell_surface *
|
|
|
|
find_toplevel_surface(struct shell_surface *in_surface)
|
|
|
|
{
|
|
|
|
struct shell_surface *surface = in_surface;
|
|
|
|
|
|
|
|
while (surface) {
|
|
|
|
if (surface->type == SHELL_SURFACE_TOPLEVEL)
|
|
|
|
return surface;
|
|
|
|
surface = get_shell_surface(surface->parent);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If no top level surface was found, just use whatever surface was
|
|
|
|
originally provided. */
|
|
|
|
return in_surface;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
shell: Centralize management of sending configure requests
Currently, there's a giant bug in how xdg-shell state management
is done. If a client calls set_fullscreen and then set_maximized,
it will get two configure events:
=> set_fullscreen
<= configure(800, 600, [STATE_FULLSCREEN])
=> set_maximized
<= configure(800, 560, [STATE_FULLSCREEN, STATE_MAXIMIZED])
Since fullscreen takes precedence over maximized, the client will
render full-screen at 800x600 first, and then 800x560 next. As
a result, the surface gets the wrong size.
This is because the code that sends out configure requests is
"immediate" -- when an app calls set_maximized, we immediately
send out the configure event that would have happened if we
transitioned immediately into maximized mode.
In wl_shell, this is correct behavior. However, in xdg-shell,
this is wrong. State needs to be more carefully managed in
xdg-shell, as states aren't exclusive.
Pull all the code that sends out configure events out and send
them centrally, based on Weston's on surface state management.
This should work with both wl_shell and xdg_shell's strategies.
11 years ago
|
|
|
send_configure_for_surface(struct shell_surface *shsurf)
|
|
|
|
{
|
shell: Centralize management of sending configure requests
Currently, there's a giant bug in how xdg-shell state management
is done. If a client calls set_fullscreen and then set_maximized,
it will get two configure events:
=> set_fullscreen
<= configure(800, 600, [STATE_FULLSCREEN])
=> set_maximized
<= configure(800, 560, [STATE_FULLSCREEN, STATE_MAXIMIZED])
Since fullscreen takes precedence over maximized, the client will
render full-screen at 800x600 first, and then 800x560 next. As
a result, the surface gets the wrong size.
This is because the code that sends out configure requests is
"immediate" -- when an app calls set_maximized, we immediately
send out the configure event that would have happened if we
transitioned immediately into maximized mode.
In wl_shell, this is correct behavior. However, in xdg-shell,
this is wrong. State needs to be more carefully managed in
xdg-shell, as states aren't exclusive.
Pull all the code that sends out configure events out and send
them centrally, based on Weston's on surface state management.
This should work with both wl_shell and xdg_shell's strategies.
11 years ago
|
|
|
int32_t width, height;
|
|
|
|
struct surface_state *state;
|
|
|
|
|
|
|
|
if (shsurf->state_requested)
|
|
|
|
state = &shsurf->requested_state;
|
|
|
|
else if (shsurf->state_changed)
|
|
|
|
state = &shsurf->next_state;
|
|
|
|
else
|
|
|
|
state = &shsurf->state;
|
|
|
|
|
|
|
|
if (state->fullscreen) {
|
|
|
|
width = shsurf->output->width;
|
|
|
|
height = shsurf->output->height;
|
|
|
|
} else if (state->maximized) {
|
|
|
|
struct desktop_shell *shell;
|
|
|
|
pixman_rectangle32_t area;
|
shell: Centralize management of sending configure requests
Currently, there's a giant bug in how xdg-shell state management
is done. If a client calls set_fullscreen and then set_maximized,
it will get two configure events:
=> set_fullscreen
<= configure(800, 600, [STATE_FULLSCREEN])
=> set_maximized
<= configure(800, 560, [STATE_FULLSCREEN, STATE_MAXIMIZED])
Since fullscreen takes precedence over maximized, the client will
render full-screen at 800x600 first, and then 800x560 next. As
a result, the surface gets the wrong size.
This is because the code that sends out configure requests is
"immediate" -- when an app calls set_maximized, we immediately
send out the configure event that would have happened if we
transitioned immediately into maximized mode.
In wl_shell, this is correct behavior. However, in xdg-shell,
this is wrong. State needs to be more carefully managed in
xdg-shell, as states aren't exclusive.
Pull all the code that sends out configure events out and send
them centrally, based on Weston's on surface state management.
This should work with both wl_shell and xdg_shell's strategies.
11 years ago
|
|
|
|
|
|
|
shell = shell_surface_get_shell(shsurf);
|
|
|
|
get_output_work_area(shell, shsurf->output, &area);
|
shell: Centralize management of sending configure requests
Currently, there's a giant bug in how xdg-shell state management
is done. If a client calls set_fullscreen and then set_maximized,
it will get two configure events:
=> set_fullscreen
<= configure(800, 600, [STATE_FULLSCREEN])
=> set_maximized
<= configure(800, 560, [STATE_FULLSCREEN, STATE_MAXIMIZED])
Since fullscreen takes precedence over maximized, the client will
render full-screen at 800x600 first, and then 800x560 next. As
a result, the surface gets the wrong size.
This is because the code that sends out configure requests is
"immediate" -- when an app calls set_maximized, we immediately
send out the configure event that would have happened if we
transitioned immediately into maximized mode.
In wl_shell, this is correct behavior. However, in xdg-shell,
this is wrong. State needs to be more carefully managed in
xdg-shell, as states aren't exclusive.
Pull all the code that sends out configure events out and send
them centrally, based on Weston's on surface state management.
This should work with both wl_shell and xdg_shell's strategies.
11 years ago
|
|
|
|
|
|
|
width = area.width;
|
|
|
|
height = area.height;
|
|
|
|
} else if (shsurf->resize_edges) {
|
|
|
|
width = shsurf->geometry.width;
|
|
|
|
height = shsurf->geometry.height;
|
shell: Centralize management of sending configure requests
Currently, there's a giant bug in how xdg-shell state management
is done. If a client calls set_fullscreen and then set_maximized,
it will get two configure events:
=> set_fullscreen
<= configure(800, 600, [STATE_FULLSCREEN])
=> set_maximized
<= configure(800, 560, [STATE_FULLSCREEN, STATE_MAXIMIZED])
Since fullscreen takes precedence over maximized, the client will
render full-screen at 800x600 first, and then 800x560 next. As
a result, the surface gets the wrong size.
This is because the code that sends out configure requests is
"immediate" -- when an app calls set_maximized, we immediately
send out the configure event that would have happened if we
transitioned immediately into maximized mode.
In wl_shell, this is correct behavior. However, in xdg-shell,
this is wrong. State needs to be more carefully managed in
xdg-shell, as states aren't exclusive.
Pull all the code that sends out configure events out and send
them centrally, based on Weston's on surface state management.
This should work with both wl_shell and xdg_shell's strategies.
11 years ago
|
|
|
} else {
|
|
|
|
width = 0;
|
|
|
|
height = 0;
|
|
|
|
}
|
shell: Centralize management of sending configure requests
Currently, there's a giant bug in how xdg-shell state management
is done. If a client calls set_fullscreen and then set_maximized,
it will get two configure events:
=> set_fullscreen
<= configure(800, 600, [STATE_FULLSCREEN])
=> set_maximized
<= configure(800, 560, [STATE_FULLSCREEN, STATE_MAXIMIZED])
Since fullscreen takes precedence over maximized, the client will
render full-screen at 800x600 first, and then 800x560 next. As
a result, the surface gets the wrong size.
This is because the code that sends out configure requests is
"immediate" -- when an app calls set_maximized, we immediately
send out the configure event that would have happened if we
transitioned immediately into maximized mode.
In wl_shell, this is correct behavior. However, in xdg-shell,
this is wrong. State needs to be more carefully managed in
xdg-shell, as states aren't exclusive.
Pull all the code that sends out configure events out and send
them centrally, based on Weston's on surface state management.
This should work with both wl_shell and xdg_shell's strategies.
11 years ago
|
|
|
|
|
|
|
shsurf->client->send_configure(shsurf->surface, width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_state_changed(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
if (shell_surface_is_xdg_surface(shsurf))
|
|
|
|
send_configure_for_surface(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_grab_end(struct shell_grab *grab)
|
|
|
|
{
|
|
|
|
if (grab->shsurf) {
|
|
|
|
wl_list_remove(&grab->shsurf_destroy_listener.link);
|
|
|
|
grab->shsurf->grabbed = 0;
|
|
|
|
|
|
|
|
if (grab->shsurf->resize_edges) {
|
|
|
|
grab->shsurf->resize_edges = 0;
|
|
|
|
shell_surface_state_changed(grab->shsurf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
weston_pointer_end_grab(grab->grab.pointer);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_touch_grab_start(struct shell_touch_grab *grab,
|
|
|
|
const struct weston_touch_grab_interface *interface,
|
|
|
|
struct shell_surface *shsurf,
|
|
|
|
struct weston_touch *touch)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = shsurf->shell;
|
|
|
|
struct weston_pointer *pointer = weston_seat_get_pointer(touch->seat);
|
|
|
|
|
|
|
|
touch_popup_grab_end(touch);
|
|
|
|
if (pointer)
|
|
|
|
popup_grab_end(pointer);
|
|
|
|
|
|
|
|
grab->grab.interface = interface;
|
|
|
|
grab->shsurf = shsurf;
|
|
|
|
grab->shsurf_destroy_listener.notify = destroy_shell_grab_shsurf;
|
|
|
|
wl_signal_add(&shsurf->destroy_signal,
|
|
|
|
&grab->shsurf_destroy_listener);
|
|
|
|
|
|
|
|
grab->touch = touch;
|
|
|
|
shsurf->grabbed = 1;
|
|
|
|
|
|
|
|
weston_touch_start_grab(touch, &grab->grab);
|
|
|
|
if (shell->child.desktop_shell)
|
|
|
|
weston_touch_set_focus(touch,
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
get_default_view(shell->grab_surface));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_touch_grab_end(struct shell_touch_grab *grab)
|
|
|
|
{
|
|
|
|
if (grab->shsurf) {
|
|
|
|
wl_list_remove(&grab->shsurf_destroy_listener.link);
|
|
|
|
grab->shsurf->grabbed = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
weston_touch_end_grab(grab->touch);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
center_on_output(struct weston_view *view,
|
|
|
|
struct weston_output *output);
|
|
|
|
|
|
|
|
static enum weston_keyboard_modifier
|
|
|
|
get_modifier(char *modifier)
|
|
|
|
{
|
|
|
|
if (!modifier)
|
|
|
|
return MODIFIER_SUPER;
|
|
|
|
|
|
|
|
if (!strcmp("ctrl", modifier))
|
|
|
|
return MODIFIER_CTRL;
|
|
|
|
else if (!strcmp("alt", modifier))
|
|
|
|
return MODIFIER_ALT;
|
|
|
|
else if (!strcmp("super", modifier))
|
|
|
|
return MODIFIER_SUPER;
|
|
|
|
else if (!strcmp("none", modifier))
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return MODIFIER_SUPER;
|
|
|
|
}
|
|
|
|
|
|
|
|
static enum animation_type
|
|
|
|
get_animation_type(char *animation)
|
|
|
|
{
|
|
|
|
if (!animation)
|
|
|
|
return ANIMATION_NONE;
|
|
|
|
|
|
|
|
if (!strcmp("zoom", animation))
|
|
|
|
return ANIMATION_ZOOM;
|
|
|
|
else if (!strcmp("fade", animation))
|
|
|
|
return ANIMATION_FADE;
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
else if (!strcmp("dim-layer", animation))
|
|
|
|
return ANIMATION_DIM_LAYER;
|
|
|
|
else
|
|
|
|
return ANIMATION_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_configuration(struct desktop_shell *shell)
|
|
|
|
{
|
|
|
|
struct weston_config_section *section;
|
|
|
|
char *s, *client;
|
|
|
|
int ret;
|
|
|
|
int allow_zap;
|
|
|
|
|
|
|
|
section = weston_config_get_section(wet_get_config(shell->compositor),
|
|
|
|
"shell", NULL, NULL);
|
|
|
|
ret = asprintf(&client, "%s/%s", weston_config_get_libexec_dir(),
|
|
|
|
WESTON_SHELL_CLIENT);
|
|
|
|
if (ret < 0)
|
|
|
|
client = NULL;
|
|
|
|
weston_config_section_get_string(section,
|
|
|
|
"client", &s, client);
|
|
|
|
free(client);
|
|
|
|
shell->client = s;
|
|
|
|
|
|
|
|
weston_config_section_get_bool(section,
|
|
|
|
"allow-zap", &allow_zap, true);
|
|
|
|
shell->allow_zap = allow_zap;
|
|
|
|
|
|
|
|
weston_config_section_get_string(section,
|
|
|
|
"binding-modifier", &s, "super");
|
|
|
|
shell->binding_modifier = get_modifier(s);
|
|
|
|
free(s);
|
|
|
|
|
|
|
|
weston_config_section_get_string(section,
|
|
|
|
"exposay-modifier", &s, "none");
|
|
|
|
shell->exposay_modifier = get_modifier(s);
|
|
|
|
free(s);
|
|
|
|
|
|
|
|
weston_config_section_get_string(section, "animation", &s, "none");
|
|
|
|
shell->win_animation_type = get_animation_type(s);
|
|
|
|
free(s);
|
|
|
|
weston_config_section_get_string(section, "close-animation", &s, "fade");
|
|
|
|
shell->win_close_animation_type = get_animation_type(s);
|
|
|
|
free(s);
|
|
|
|
weston_config_section_get_string(section,
|
|
|
|
"startup-animation", &s, "fade");
|
|
|
|
shell->startup_animation_type = get_animation_type(s);
|
|
|
|
free(s);
|
|
|
|
if (shell->startup_animation_type == ANIMATION_ZOOM)
|
|
|
|
shell->startup_animation_type = ANIMATION_NONE;
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct weston_output *
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
get_default_output(struct weston_compositor *compositor)
|
|
|
|
{
|
|
|
|
return container_of(compositor->output_list.next,
|
|
|
|
struct weston_output, link);
|
|
|
|
}
|
|
|
|
|
compositor: add weston_surface_set_label_func()
When printing out logs from Weston's actions, mainly for debugging, it
can be very difficult to identify the different surfaces. Inspecting
the configure function pointer is not useful, as the configure functions
may live in modules.
Add vfunc get_label to weston_surface, which will produce a short,
human-readable description of the surface, which allows identifying it
better, rather than just looking at the surface size, for instance.
Set the label function from most parts of Weston, to identify cursors and
drag icons, and panels, backgrounds, screensavers and lock surfaces, and
the desktop shell's application surfaces.
v2: renamed 'description' to 'label', so we get
weston_surface_set_label_func().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
11 years ago
|
|
|
static int
|
|
|
|
focus_surface_get_label(struct weston_surface *surface, char *buf, size_t len)
|
|
|
|
{
|
|
|
|
return snprintf(buf, len, "focus highlight effect for output %s",
|
|
|
|
surface->output->name);
|
|
|
|
}
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
|
|
|
|
/* no-op func for checking focus surface */
|
|
|
|
static void
|
|
|
|
focus_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct focus_surface *
|
|
|
|
get_focus_surface(struct weston_surface *surface)
|
|
|
|
{
|
|
|
|
if (surface->configure == focus_surface_configure)
|
|
|
|
return surface->configure_private;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
is_focus_surface (struct weston_surface *es)
|
|
|
|
{
|
|
|
|
return (es->configure == focus_surface_configure);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
is_focus_view (struct weston_view *view)
|
|
|
|
{
|
|
|
|
return is_focus_surface (view->surface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct focus_surface *
|
|
|
|
create_focus_surface(struct weston_compositor *ec,
|
|
|
|
struct weston_output *output)
|
|
|
|
{
|
|
|
|
struct focus_surface *fsurf = NULL;
|
|
|
|
struct weston_surface *surface = NULL;
|
|
|
|
|
|
|
|
fsurf = malloc(sizeof *fsurf);
|
|
|
|
if (!fsurf)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
fsurf->surface = weston_surface_create(ec);
|
|
|
|
surface = fsurf->surface;
|
|
|
|
if (surface == NULL) {
|
|
|
|
free(fsurf);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
surface->configure = focus_surface_configure;
|
|
|
|
surface->output = output;
|
|
|
|
surface->configure_private = fsurf;
|
compositor: add weston_surface_set_label_func()
When printing out logs from Weston's actions, mainly for debugging, it
can be very difficult to identify the different surfaces. Inspecting
the configure function pointer is not useful, as the configure functions
may live in modules.
Add vfunc get_label to weston_surface, which will produce a short,
human-readable description of the surface, which allows identifying it
better, rather than just looking at the surface size, for instance.
Set the label function from most parts of Weston, to identify cursors and
drag icons, and panels, backgrounds, screensavers and lock surfaces, and
the desktop shell's application surfaces.
v2: renamed 'description' to 'label', so we get
weston_surface_set_label_func().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
11 years ago
|
|
|
weston_surface_set_label_func(surface, focus_surface_get_label);
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
|
|
|
|
fsurf->view = weston_view_create(surface);
|
|
|
|
if (fsurf->view == NULL) {
|
|
|
|
weston_surface_destroy(surface);
|
|
|
|
free(fsurf);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
fsurf->view->output = output;
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
|
|
|
|
weston_surface_set_size(surface, output->width, output->height);
|
|
|
|
weston_view_set_position(fsurf->view, output->x, output->y);
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0);
|
|
|
|
pixman_region32_fini(&surface->opaque);
|
|
|
|
pixman_region32_init_rect(&surface->opaque, output->x, output->y,
|
|
|
|
output->width, output->height);
|
|
|
|
pixman_region32_fini(&surface->input);
|
|
|
|
pixman_region32_init(&surface->input);
|
|
|
|
|
|
|
|
wl_list_init(&fsurf->workspace_transform.link);
|
|
|
|
|
|
|
|
return fsurf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
focus_surface_destroy(struct focus_surface *fsurf)
|
|
|
|
{
|
|
|
|
weston_surface_destroy(fsurf->surface);
|
|
|
|
free(fsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
focus_animation_done(struct weston_view_animation *animation, void *data)
|
|
|
|
{
|
|
|
|
struct workspace *ws = data;
|
|
|
|
|
|
|
|
ws->focus_animation = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
focus_state_destroy(struct focus_state *state)
|
|
|
|
{
|
|
|
|
wl_list_remove(&state->seat_destroy_listener.link);
|
|
|
|
wl_list_remove(&state->surface_destroy_listener.link);
|
|
|
|
free(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
focus_state_seat_destroy(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct focus_state *state = container_of(listener,
|
|
|
|
struct focus_state,
|
|
|
|
seat_destroy_listener);
|
|
|
|
|
|
|
|
wl_list_remove(&state->link);
|
|
|
|
focus_state_destroy(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
focus_state_surface_destroy(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct focus_state *state = container_of(listener,
|
|
|
|
struct focus_state,
|
|
|
|
surface_destroy_listener);
|
|
|
|
struct desktop_shell *shell;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_surface *main_surface, *next;
|
|
|
|
struct weston_view *view;
|
|
|
|
|
shell: keyboard focus and restacking fixes for sub-surfaces
The shell needs to redirect some actions to the parent surface, when
they originally target a sub-surface. This patch implements the
following:
- Move, resize, and rotate bindings always target the parent surface.
- Opacity (full-surface alpha) binding targets the parent surface. This
is broken, because it should change the opacity of the whole compound
window, which is difficult to implement in the renderer.
- click_to_activate_binding() needs to check the shell surface type from
the main surface, because sub-surface would produce SHELL_SURFACE_NONE
and prevent activation.
- Also activate() needs to check the type from the main surface, and
restack the main surface. Keyboard focus is assigned to the original
(sub-)surface.
- focus_state_surface_destroy() needs to handle sub-surfaces: only the
main surface will be in a layer list. If the destroyed surface is
indeed a sub-surface, activate the main surface next. This way a
client that destroys a focused sub-surface still retains focus in the
same window.
- The workspace_manager.move_surface request can accept also
sub-surfaces, and it will move the corresponding main surface.
Changes in v2:
- do not special-case keyboard focus for sub-surfaces
- fix surface type checks for sub-surfaces in shell, fix restacking of
sub-surfaces in shell, fix focus_state_surface_destroy()
Changes in v3:
- Renamed weston_surface_get_parent() to
weston_surface_get_main_surface() to be more explicit that this is
about sub-surfaces
- Fixed move_surface_to_workspace() to handle keyboard focus on a
sub-surface.
- Used a temporary variable in several places to clarify code, instead
of reassigning a variable.
- Fixed workspace_manager_move_surface() to deal with sub-surfaces.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
12 years ago
|
|
|
main_surface = weston_surface_get_main_surface(state->keyboard_focus);
|
|
|
|
|
|
|
|
next = NULL;
|
|
|
|
wl_list_for_each(view,
|
|
|
|
&state->ws->layer.view_list.link, layer_link.link) {
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
if (view->surface == main_surface)
|
|
|
|
continue;
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
if (is_focus_view(view))
|
|
|
|
continue;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
next = view->surface;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
shell: keyboard focus and restacking fixes for sub-surfaces
The shell needs to redirect some actions to the parent surface, when
they originally target a sub-surface. This patch implements the
following:
- Move, resize, and rotate bindings always target the parent surface.
- Opacity (full-surface alpha) binding targets the parent surface. This
is broken, because it should change the opacity of the whole compound
window, which is difficult to implement in the renderer.
- click_to_activate_binding() needs to check the shell surface type from
the main surface, because sub-surface would produce SHELL_SURFACE_NONE
and prevent activation.
- Also activate() needs to check the type from the main surface, and
restack the main surface. Keyboard focus is assigned to the original
(sub-)surface.
- focus_state_surface_destroy() needs to handle sub-surfaces: only the
main surface will be in a layer list. If the destroyed surface is
indeed a sub-surface, activate the main surface next. This way a
client that destroys a focused sub-surface still retains focus in the
same window.
- The workspace_manager.move_surface request can accept also
sub-surfaces, and it will move the corresponding main surface.
Changes in v2:
- do not special-case keyboard focus for sub-surfaces
- fix surface type checks for sub-surfaces in shell, fix restacking of
sub-surfaces in shell, fix focus_state_surface_destroy()
Changes in v3:
- Renamed weston_surface_get_parent() to
weston_surface_get_main_surface() to be more explicit that this is
about sub-surfaces
- Fixed move_surface_to_workspace() to handle keyboard focus on a
sub-surface.
- Used a temporary variable in several places to clarify code, instead
of reassigning a variable.
- Fixed workspace_manager_move_surface() to deal with sub-surfaces.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
12 years ago
|
|
|
/* if the focus was a sub-surface, activate its main surface */
|
|
|
|
if (main_surface != state->keyboard_focus)
|
|
|
|
next = main_surface;
|
|
|
|
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
shell = state->seat->compositor->shell_interface.shell;
|
|
|
|
if (next) {
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
state->keyboard_focus = NULL;
|
|
|
|
activate(shell, next, state->seat, true);
|
|
|
|
} else {
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
if (shell->focus_animation_type == ANIMATION_DIM_LAYER) {
|
|
|
|
if (state->ws->focus_animation)
|
|
|
|
weston_view_animation_destroy(state->ws->focus_animation);
|
|
|
|
|
|
|
|
state->ws->focus_animation = weston_fade_run(
|
|
|
|
state->ws->fsurf_front->view,
|
|
|
|
state->ws->fsurf_front->view->alpha, 0.0, 300,
|
|
|
|
focus_animation_done, state->ws);
|
|
|
|
}
|
|
|
|
|
|
|
|
wl_list_remove(&state->link);
|
|
|
|
focus_state_destroy(state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct focus_state *
|
|
|
|
focus_state_create(struct weston_seat *seat, struct workspace *ws)
|
|
|
|
{
|
|
|
|
struct focus_state *state;
|
|
|
|
|
|
|
|
state = malloc(sizeof *state);
|
|
|
|
if (state == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
state->keyboard_focus = NULL;
|
|
|
|
state->ws = ws;
|
|
|
|
state->seat = seat;
|
|
|
|
wl_list_insert(&ws->focus_list, &state->link);
|
|
|
|
|
|
|
|
state->seat_destroy_listener.notify = focus_state_seat_destroy;
|
|
|
|
state->surface_destroy_listener.notify = focus_state_surface_destroy;
|
|
|
|
wl_signal_add(&seat->destroy_signal,
|
|
|
|
&state->seat_destroy_listener);
|
|
|
|
wl_list_init(&state->surface_destroy_listener.link);
|
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct focus_state *
|
|
|
|
ensure_focus_state(struct desktop_shell *shell, struct weston_seat *seat)
|
|
|
|
{
|
|
|
|
struct workspace *ws = get_current_workspace(shell);
|
|
|
|
struct focus_state *state;
|
|
|
|
|
|
|
|
wl_list_for_each(state, &ws->focus_list, link)
|
|
|
|
if (state->seat == seat)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (&state->link == &ws->focus_list)
|
|
|
|
state = focus_state_create(seat, ws);
|
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
focus_state_set_focus(struct focus_state *state,
|
|
|
|
struct weston_surface *surface)
|
|
|
|
{
|
|
|
|
if (state->keyboard_focus) {
|
|
|
|
wl_list_remove(&state->surface_destroy_listener.link);
|
|
|
|
wl_list_init(&state->surface_destroy_listener.link);
|
|
|
|
}
|
|
|
|
|
|
|
|
state->keyboard_focus = surface;
|
|
|
|
if (surface)
|
|
|
|
wl_signal_add(&surface->destroy_signal,
|
|
|
|
&state->surface_destroy_listener);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
restore_focus_state(struct desktop_shell *shell, struct workspace *ws)
|
|
|
|
{
|
|
|
|
struct focus_state *state, *next;
|
|
|
|
struct weston_surface *surface;
|
|
|
|
struct wl_list pending_seat_list;
|
|
|
|
struct weston_seat *seat, *next_seat;
|
|
|
|
|
|
|
|
/* Temporarily steal the list of seats so that we can keep
|
|
|
|
* track of the seats we've already processed */
|
|
|
|
wl_list_init(&pending_seat_list);
|
|
|
|
wl_list_insert_list(&pending_seat_list, &shell->compositor->seat_list);
|
|
|
|
wl_list_init(&shell->compositor->seat_list);
|
|
|
|
|
|
|
|
wl_list_for_each_safe(state, next, &ws->focus_list, link) {
|
|
|
|
struct weston_keyboard *keyboard =
|
|
|
|
weston_seat_get_keyboard(state->seat);
|
|
|
|
|
|
|
|
wl_list_remove(&state->seat->link);
|
|
|
|
wl_list_insert(&shell->compositor->seat_list,
|
|
|
|
&state->seat->link);
|
|
|
|
|
|
|
|
if (!keyboard)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
surface = state->keyboard_focus;
|
|
|
|
|
|
|
|
weston_keyboard_set_focus(keyboard, surface);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* For any remaining seats that we don't have a focus state
|
|
|
|
* for we'll reset the keyboard focus to NULL */
|
|
|
|
wl_list_for_each_safe(seat, next_seat, &pending_seat_list, link) {
|
|
|
|
struct weston_keyboard *keyboard =
|
|
|
|
weston_seat_get_keyboard(seat);
|
|
|
|
|
|
|
|
wl_list_insert(&shell->compositor->seat_list, &seat->link);
|
|
|
|
|
|
|
|
if (!keyboard)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
weston_keyboard_set_focus(keyboard, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
struct focus_state *state;
|
|
|
|
|
|
|
|
wl_list_for_each(state, &ws->focus_list, link)
|
|
|
|
if (state->keyboard_focus == surface)
|
|
|
|
focus_state_set_focus(state, NULL);
|
|
|
|
}
|
|
|
|
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
static void
|
|
|
|
animate_focus_change(struct desktop_shell *shell, struct workspace *ws,
|
|
|
|
struct weston_view *from, struct weston_view *to)
|
|
|
|
{
|
|
|
|
struct weston_output *output;
|
|
|
|
bool focus_surface_created = false;
|
|
|
|
|
|
|
|
/* FIXME: Only support dim animation using two layers */
|
|
|
|
if (from == to || shell->focus_animation_type != ANIMATION_DIM_LAYER)
|
|
|
|
return;
|
|
|
|
|
|
|
|
output = get_default_output(shell->compositor);
|
|
|
|
if (ws->fsurf_front == NULL && (from || to)) {
|
|
|
|
ws->fsurf_front = create_focus_surface(shell->compositor, output);
|
|
|
|
if (ws->fsurf_front == NULL)
|
|
|
|
return;
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
ws->fsurf_front->view->alpha = 0.0;
|
|
|
|
|
|
|
|
ws->fsurf_back = create_focus_surface(shell->compositor, output);
|
|
|
|
if (ws->fsurf_back == NULL) {
|
|
|
|
focus_surface_destroy(ws->fsurf_front);
|
|
|
|
return;
|
|
|
|
}
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
ws->fsurf_back->view->alpha = 0.0;
|
|
|
|
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
focus_surface_created = true;
|
|
|
|
} else {
|
|
|
|
weston_layer_entry_remove(&ws->fsurf_front->view->layer_link);
|
|
|
|
weston_layer_entry_remove(&ws->fsurf_back->view->layer_link);
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
}
|
|
|
|
|
|
|
|
if (ws->focus_animation) {
|
|
|
|
weston_view_animation_destroy(ws->focus_animation);
|
|
|
|
ws->focus_animation = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (to)
|
|
|
|
weston_layer_entry_insert(&to->layer_link,
|
|
|
|
&ws->fsurf_front->view->layer_link);
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
else if (from)
|
|
|
|
weston_layer_entry_insert(&ws->layer.view_list,
|
|
|
|
&ws->fsurf_front->view->layer_link);
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
|
|
|
|
if (focus_surface_created) {
|
|
|
|
ws->focus_animation = weston_fade_run(
|
|
|
|
ws->fsurf_front->view,
|
|
|
|
ws->fsurf_front->view->alpha, 0.4, 300,
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
focus_animation_done, ws);
|
|
|
|
} else if (from) {
|
|
|
|
weston_layer_entry_insert(&from->layer_link,
|
|
|
|
&ws->fsurf_back->view->layer_link);
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
ws->focus_animation = weston_stable_fade_run(
|
|
|
|
ws->fsurf_front->view, 0.0,
|
|
|
|
ws->fsurf_back->view, 0.4,
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
focus_animation_done, ws);
|
|
|
|
} else if (to) {
|
|
|
|
weston_layer_entry_insert(&ws->layer.view_list,
|
|
|
|
&ws->fsurf_back->view->layer_link);
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
ws->focus_animation = weston_stable_fade_run(
|
|
|
|
ws->fsurf_front->view, 0.0,
|
|
|
|
ws->fsurf_back->view, 0.4,
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
focus_animation_done, ws);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
workspace_destroy(struct workspace *ws)
|
|
|
|
{
|
|
|
|
struct focus_state *state, *next;
|
|
|
|
|
|
|
|
wl_list_for_each_safe(state, next, &ws->focus_list, link)
|
|
|
|
focus_state_destroy(state);
|
|
|
|
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
if (ws->fsurf_front)
|
|
|
|
focus_surface_destroy(ws->fsurf_front);
|
|
|
|
if (ws->fsurf_back)
|
|
|
|
focus_surface_destroy(ws->fsurf_back);
|
|
|
|
|
|
|
|
free(ws);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
seat_destroyed(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct weston_seat *seat = data;
|
|
|
|
struct focus_state *state, *next;
|
|
|
|
struct workspace *ws = container_of(listener,
|
|
|
|
struct workspace,
|
|
|
|
seat_destroyed_listener);
|
|
|
|
|
|
|
|
wl_list_for_each_safe(state, next, &ws->focus_list, link)
|
|
|
|
if (state->seat == seat)
|
|
|
|
wl_list_remove(&state->link);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct workspace *
|
|
|
|
workspace_create(void)
|
|
|
|
{
|
|
|
|
struct workspace *ws = malloc(sizeof *ws);
|
|
|
|
if (ws == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
weston_layer_init(&ws->layer, NULL);
|
|
|
|
|
|
|
|
wl_list_init(&ws->focus_list);
|
|
|
|
wl_list_init(&ws->seat_destroyed_listener.link);
|
|
|
|
ws->seat_destroyed_listener.notify = seat_destroyed;
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
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);
|
|
|
|
wl_list_insert(&shell->panel_layer.link, &ws->layer.link);
|
|
|
|
|
|
|
|
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 void
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
view_translate(struct workspace *ws, struct weston_view *view, double d)
|
|
|
|
{
|
|
|
|
struct weston_transform *transform;
|
|
|
|
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
if (is_focus_view(view)) {
|
|
|
|
struct focus_surface *fsurf = get_focus_surface(view->surface);
|
|
|
|
transform = &fsurf->workspace_transform;
|
|
|
|
} else {
|
|
|
|
struct shell_surface *shsurf = get_shell_surface(view->surface);
|
|
|
|
transform = &shsurf->workspace_transform;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wl_list_empty(&transform->link))
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
wl_list_insert(view->geometry.transformation_list.prev,
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
&transform->link);
|
|
|
|
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
weston_matrix_init(&transform->matrix);
|
|
|
|
weston_matrix_translate(&transform->matrix,
|
|
|
|
0.0, d, 0.0);
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_geometry_dirty(view);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
workspace_translate_out(struct workspace *ws, double fraction)
|
|
|
|
{
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *view;
|
|
|
|
unsigned int height;
|
|
|
|
double d;
|
|
|
|
|
|
|
|
wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) {
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
height = get_output_height(view->surface->output);
|
|
|
|
d = height * fraction;
|
|
|
|
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
view_translate(ws, view, d);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
workspace_translate_in(struct workspace *ws, double fraction)
|
|
|
|
{
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *view;
|
|
|
|
unsigned int height;
|
|
|
|
double d;
|
|
|
|
|
|
|
|
wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) {
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
height = get_output_height(view->surface->output);
|
|
|
|
|
|
|
|
if (fraction > 0)
|
|
|
|
d = -(height - height * fraction);
|
|
|
|
else
|
|
|
|
d = height + height * fraction;
|
|
|
|
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
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 = 0;
|
|
|
|
|
|
|
|
weston_compositor_schedule_repaint(shell->compositor);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
workspace_deactivate_transforms(struct workspace *ws)
|
|
|
|
{
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *view;
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
struct weston_transform *transform;
|
|
|
|
|
|
|
|
wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) {
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
if (is_focus_view(view)) {
|
|
|
|
struct focus_surface *fsurf = get_focus_surface(view->surface);
|
|
|
|
transform = &fsurf->workspace_transform;
|
|
|
|
} else {
|
|
|
|
struct shell_surface *shsurf = get_shell_surface(view->surface);
|
|
|
|
transform = &shsurf->workspace_transform;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!wl_list_empty(&transform->link)) {
|
|
|
|
wl_list_remove(&transform->link);
|
|
|
|
wl_list_init(&transform->link);
|
|
|
|
}
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
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;
|
|
|
|
|
|
|
|
wl_list_remove(&shell->workspaces.anim_from->layer.link);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
animate_workspace_change_frame(struct weston_animation *animation,
|
|
|
|
struct weston_output *output, uint32_t msecs)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
uint32_t t;
|
|
|
|
double x, y;
|
|
|
|
|
|
|
|
if (workspace_is_empty(from) && workspace_is_empty(to)) {
|
|
|
|
finish_workspace_change_animation(shell, from, to);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (shell->workspaces.anim_timestamp == 0) {
|
|
|
|
if (shell->workspaces.anim_current == 0.0)
|
|
|
|
shell->workspaces.anim_timestamp = msecs;
|
|
|
|
else
|
|
|
|
shell->workspaces.anim_timestamp =
|
|
|
|
msecs -
|
|
|
|
/* Invers of movement function 'y' below. */
|
|
|
|
(asin(1.0 - shell->workspaces.anim_current) *
|
|
|
|
DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH *
|
|
|
|
M_2_PI);
|
|
|
|
}
|
|
|
|
|
|
|
|
t = msecs - 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 = 0;
|
|
|
|
|
|
|
|
output = container_of(shell->compositor->output_list.next,
|
|
|
|
struct weston_output, link);
|
|
|
|
wl_list_insert(&output->animation_list,
|
|
|
|
&shell->workspaces.animation.link);
|
|
|
|
|
|
|
|
wl_list_insert(from->layer.link.prev, &to->layer.link);
|
|
|
|
|
|
|
|
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;
|
|
|
|
wl_list_insert(&from->layer.link, &to->layer.link);
|
|
|
|
wl_list_remove(&from->layer.link);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
change_workspace(struct desktop_shell *shell, unsigned int index)
|
|
|
|
{
|
|
|
|
struct workspace *from;
|
|
|
|
struct workspace *to;
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
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);
|
|
|
|
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
surface_keyboard_focus_lost(struct weston_surface *surface)
|
|
|
|
{
|
|
|
|
struct weston_compositor *compositor = surface->compositor;
|
|
|
|
struct weston_seat *seat;
|
|
|
|
struct weston_surface *focus;
|
|
|
|
|
|
|
|
wl_list_for_each(seat, &compositor->seat_list, link) {
|
|
|
|
struct weston_keyboard *keyboard =
|
|
|
|
weston_seat_get_keyboard(seat);
|
|
|
|
|
|
|
|
if (!keyboard)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
focus = weston_surface_get_main_surface(keyboard->focus);
|
|
|
|
if (focus == surface)
|
|
|
|
weston_keyboard_set_focus(keyboard, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
shell: keyboard focus and restacking fixes for sub-surfaces
The shell needs to redirect some actions to the parent surface, when
they originally target a sub-surface. This patch implements the
following:
- Move, resize, and rotate bindings always target the parent surface.
- Opacity (full-surface alpha) binding targets the parent surface. This
is broken, because it should change the opacity of the whole compound
window, which is difficult to implement in the renderer.
- click_to_activate_binding() needs to check the shell surface type from
the main surface, because sub-surface would produce SHELL_SURFACE_NONE
and prevent activation.
- Also activate() needs to check the type from the main surface, and
restack the main surface. Keyboard focus is assigned to the original
(sub-)surface.
- focus_state_surface_destroy() needs to handle sub-surfaces: only the
main surface will be in a layer list. If the destroyed surface is
indeed a sub-surface, activate the main surface next. This way a
client that destroys a focused sub-surface still retains focus in the
same window.
- The workspace_manager.move_surface request can accept also
sub-surfaces, and it will move the corresponding main surface.
Changes in v2:
- do not special-case keyboard focus for sub-surfaces
- fix surface type checks for sub-surfaces in shell, fix restacking of
sub-surfaces in shell, fix focus_state_surface_destroy()
Changes in v3:
- Renamed weston_surface_get_parent() to
weston_surface_get_main_surface() to be more explicit that this is
about sub-surfaces
- Fixed move_surface_to_workspace() to handle keyboard focus on a
sub-surface.
- Used a temporary variable in several places to clarify code, instead
of reassigning a variable.
- Fixed workspace_manager_move_surface() to deal with sub-surfaces.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
12 years ago
|
|
|
struct weston_surface *surface;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
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);
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
view = get_default_view(surface);
|
|
|
|
if (view == NULL ||
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
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) {
|
|
|
|
wl_list_remove(&to->layer.link);
|
|
|
|
wl_list_insert(from->layer.link.prev, &to->layer.link);
|
|
|
|
|
|
|
|
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, uint32_t time,
|
|
|
|
int touch_id, wl_fixed_t x, wl_fixed_t y)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
touch_move_grab_up(struct weston_touch_grab *grab, uint32_t time, int touch_id)
|
|
|
|
{
|
|
|
|
struct weston_touch_move_grab *move =
|
|
|
|
(struct weston_touch_move_grab *) container_of(
|
|
|
|
grab, struct shell_touch_grab, grab);
|
|
|
|
|
|
|
|
if (touch_id == 0)
|
|
|
|
move->active = 0;
|
|
|
|
|
|
|
|
if (grab->touch->num_tp == 0) {
|
|
|
|
shell_touch_grab_end(&move->base);
|
|
|
|
free(move);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time,
|
|
|
|
int touch_id, wl_fixed_t x, wl_fixed_t y)
|
|
|
|
{
|
|
|
|
struct weston_touch_move_grab *move = (struct weston_touch_move_grab *) grab;
|
|
|
|
struct shell_surface *shsurf = move->base.shsurf;
|
|
|
|
struct weston_surface *es;
|
|
|
|
int dx = wl_fixed_to_int(grab->touch->grab_x + move->dx);
|
|
|
|
int dy = wl_fixed_to_int(grab->touch->grab_y + move->dy);
|
|
|
|
|
|
|
|
if (!shsurf || !move->active)
|
|
|
|
return;
|
|
|
|
|
|
|
|
es = shsurf->surface;
|
|
|
|
|
|
|
|
weston_view_set_position(shsurf->view, dx, dy);
|
|
|
|
|
|
|
|
weston_compositor_schedule_repaint(es->compositor);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
touch_move_grab_frame(struct weston_touch_grab *grab)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
touch_move_grab_cancel(struct weston_touch_grab *grab)
|
|
|
|
{
|
|
|
|
struct weston_touch_move_grab *move =
|
|
|
|
(struct weston_touch_move_grab *) container_of(
|
|
|
|
grab, struct shell_touch_grab, grab);
|
|
|
|
|
|
|
|
shell_touch_grab_end(&move->base);
|
|
|
|
free(move);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct weston_touch_grab_interface touch_move_grab_interface = {
|
|
|
|
touch_move_grab_down,
|
|
|
|
touch_move_grab_up,
|
|
|
|
touch_move_grab_motion,
|
|
|
|
touch_move_grab_frame,
|
|
|
|
touch_move_grab_cancel,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
surface_touch_move(struct shell_surface *shsurf, struct weston_touch *touch)
|
|
|
|
{
|
|
|
|
struct weston_touch_move_grab *move;
|
|
|
|
|
|
|
|
if (!shsurf)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (shsurf->state.fullscreen || shsurf->state.maximized)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
move = malloc(sizeof *move);
|
|
|
|
if (!move)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
move->active = 1;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
move->dx = wl_fixed_from_double(shsurf->view->geometry.x) -
|
|
|
|
touch->grab_x;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
move->dy = wl_fixed_from_double(shsurf->view->geometry.y) -
|
|
|
|
touch->grab_y;
|
|
|
|
|
|
|
|
shell_touch_grab_start(&move->base, &touch_move_grab_interface, shsurf,
|
|
|
|
touch);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
noop_grab_focus(struct weston_pointer_grab *grab)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
noop_grab_axis(struct weston_pointer_grab *grab,
|
|
|
|
uint32_t time, struct weston_pointer_axis_event *event)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
noop_grab_axis_source(struct weston_pointer_grab *grab,
|
|
|
|
uint32_t source)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
noop_grab_frame(struct weston_pointer_grab *grab)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
constrain_position(struct weston_move_grab *move, int *cx, int *cy)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = move->base.shsurf;
|
|
|
|
struct weston_pointer *pointer = move->base.grab.pointer;
|
|
|
|
int x, y, bottom;
|
|
|
|
const int safety = 50;
|
|
|
|
pixman_rectangle32_t area;
|
|
|
|
|
|
|
|
x = wl_fixed_to_int(pointer->x + move->dx);
|
|
|
|
y = wl_fixed_to_int(pointer->y + move->dy);
|
|
|
|
|
|
|
|
if (shsurf->shell->panel_position ==
|
|
|
|
WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP) {
|
|
|
|
get_output_work_area(shsurf->shell,
|
|
|
|
shsurf->surface->output,
|
|
|
|
&area);
|
|
|
|
|
|
|
|
bottom = y + shsurf->geometry.height + shsurf->geometry.y;
|
|
|
|
if (bottom - safety < area.y)
|
|
|
|
y = area.y + safety - shsurf->geometry.height
|
|
|
|
- shsurf->geometry.y;
|
|
|
|
|
|
|
|
if (move->client_initiated &&
|
|
|
|
y + shsurf->geometry.y < area.y)
|
|
|
|
y = area.y - shsurf->geometry.y;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
*cx = x;
|
|
|
|
*cy = y;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
move_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
|
|
|
|
struct weston_pointer_motion_event *event)
|
|
|
|
{
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
13 years ago
|
|
|
struct weston_move_grab *move = (struct weston_move_grab *) grab;
|
|
|
|
struct weston_pointer *pointer = grab->pointer;
|
|
|
|
struct shell_surface *shsurf = move->base.shsurf;
|
|
|
|
int cx, cy;
|
|
|
|
|
|
|
|
weston_pointer_move(pointer, event);
|
|
|
|
if (!shsurf)
|
|
|
|
return;
|
|
|
|
|
|
|
|
constrain_position(move, &cx, &cy);
|
|
|
|
|
|
|
|
weston_view_set_position(shsurf->view, cx, cy);
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_compositor_schedule_repaint(shsurf->surface->compositor);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
move_grab_button(struct weston_pointer_grab *grab,
|
|
|
|
uint32_t time, uint32_t button, uint32_t state_w)
|
|
|
|
{
|
|
|
|
struct shell_grab *shell_grab = container_of(grab, struct shell_grab,
|
|
|
|
grab);
|
|
|
|
struct weston_pointer *pointer = grab->pointer;
|
|
|
|
enum wl_pointer_button_state state = state_w;
|
|
|
|
|
|
|
|
if (pointer->button_count == 0 &&
|
|
|
|
state == WL_POINTER_BUTTON_STATE_RELEASED) {
|
|
|
|
shell_grab_end(shell_grab);
|
|
|
|
free(grab);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
move_grab_cancel(struct weston_pointer_grab *grab)
|
|
|
|
{
|
|
|
|
struct shell_grab *shell_grab =
|
|
|
|
container_of(grab, struct shell_grab, grab);
|
|
|
|
|
|
|
|
shell_grab_end(shell_grab);
|
|
|
|
free(grab);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct weston_pointer_grab_interface move_grab_interface = {
|
|
|
|
noop_grab_focus,
|
|
|
|
move_grab_motion,
|
|
|
|
move_grab_button,
|
|
|
|
noop_grab_axis,
|
|
|
|
noop_grab_axis_source,
|
|
|
|
noop_grab_frame,
|
|
|
|
move_grab_cancel,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
surface_move(struct shell_surface *shsurf, struct weston_pointer *pointer,
|
|
|
|
bool client_initiated)
|
|
|
|
{
|
|
|
|
struct weston_move_grab *move;
|
|
|
|
|
|
|
|
if (!shsurf)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
shsurf = find_toplevel_surface(shsurf);
|
|
|
|
|
|
|
|
if (shsurf->grabbed ||
|
|
|
|
shsurf->state.fullscreen || shsurf->state.maximized)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
move = malloc(sizeof *move);
|
|
|
|
if (!move)
|
|
|
|
return -1;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
move->dx = wl_fixed_from_double(shsurf->view->geometry.x) -
|
|
|
|
pointer->grab_x;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
move->dy = wl_fixed_from_double(shsurf->view->geometry.y) -
|
|
|
|
pointer->grab_y;
|
|
|
|
move->client_initiated = client_initiated;
|
|
|
|
|
|
|
|
shell_grab_start(&move->base, &move_grab_interface, shsurf,
|
|
|
|
pointer, WESTON_DESKTOP_SHELL_CURSOR_MOVE);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
common_surface_move(struct wl_resource *resource,
|
|
|
|
struct wl_resource *seat_resource, uint32_t serial)
|
|
|
|
{
|
|
|
|
struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
|
|
|
|
struct weston_pointer *pointer = weston_seat_get_pointer(seat);
|
|
|
|
struct weston_touch *touch = weston_seat_get_touch(seat);
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
struct weston_surface *surface;
|
|
|
|
|
|
|
|
if (pointer &&
|
|
|
|
pointer->focus &&
|
|
|
|
pointer->button_count > 0 &&
|
|
|
|
pointer->grab_serial == serial) {
|
|
|
|
surface = weston_surface_get_main_surface(pointer->focus->surface);
|
|
|
|
if ((surface == shsurf->surface) &&
|
|
|
|
(surface_move(shsurf, pointer, true) < 0))
|
|
|
|
wl_resource_post_no_memory(resource);
|
|
|
|
} else if (touch &&
|
|
|
|
touch->focus &&
|
|
|
|
touch->grab_serial == serial) {
|
|
|
|
surface = weston_surface_get_main_surface(touch->focus->surface);
|
|
|
|
if ((surface == shsurf->surface) &&
|
|
|
|
(surface_touch_move(shsurf, touch) < 0))
|
|
|
|
wl_resource_post_no_memory(resource);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_move(struct wl_client *client, struct wl_resource *resource,
|
|
|
|
struct wl_resource *seat_resource, uint32_t serial)
|
|
|
|
{
|
|
|
|
common_surface_move(resource, seat_resource, serial);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct weston_resize_grab {
|
|
|
|
struct shell_grab base;
|
|
|
|
uint32_t edges;
|
|
|
|
int32_t width, height;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
resize_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
|
|
|
|
struct weston_pointer_motion_event *event)
|
|
|
|
{
|
|
|
|
struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
|
|
|
|
struct weston_pointer *pointer = grab->pointer;
|
|
|
|
struct shell_surface *shsurf = resize->base.shsurf;
|
|
|
|
int32_t width, height;
|
|
|
|
wl_fixed_t from_x, from_y;
|
|
|
|
wl_fixed_t to_x, to_y;
|
|
|
|
|
|
|
|
weston_pointer_move(pointer, event);
|
|
|
|
|
|
|
|
if (!shsurf)
|
|
|
|
return;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_from_global_fixed(shsurf->view,
|
|
|
|
pointer->grab_x, pointer->grab_y,
|
|
|
|
&from_x, &from_y);
|
|
|
|
weston_view_from_global_fixed(shsurf->view,
|
|
|
|
pointer->x, pointer->y, &to_x, &to_y);
|
|
|
|
|
|
|
|
width = resize->width;
|
|
|
|
if (resize->edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
|
|
|
|
width += wl_fixed_to_int(from_x - to_x);
|
|
|
|
} else if (resize->edges & WL_SHELL_SURFACE_RESIZE_RIGHT) {
|
|
|
|
width += wl_fixed_to_int(to_x - from_x);
|
|
|
|
}
|
|
|
|
|
|
|
|
height = resize->height;
|
|
|
|
if (resize->edges & WL_SHELL_SURFACE_RESIZE_TOP) {
|
|
|
|
height += wl_fixed_to_int(from_y - to_y);
|
|
|
|
} else if (resize->edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) {
|
|
|
|
height += wl_fixed_to_int(to_y - from_y);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (width < 1)
|
|
|
|
width = 1;
|
|
|
|
if (height < 1)
|
|
|
|
height = 1;
|
|
|
|
shsurf->client->send_configure(shsurf->surface, width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
send_configure(struct weston_surface *surface, int32_t width, int32_t height)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = get_shell_surface(surface);
|
|
|
|
|
|
|
|
assert(shsurf);
|
|
|
|
|
|
|
|
if (shsurf->resource)
|
|
|
|
wl_shell_surface_send_configure(shsurf->resource,
|
|
|
|
shsurf->resize_edges,
|
|
|
|
width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct weston_shell_client shell_client = {
|
|
|
|
send_configure,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
resize_grab_button(struct weston_pointer_grab *grab,
|
|
|
|
uint32_t time, uint32_t button, uint32_t state_w)
|
|
|
|
{
|
|
|
|
struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
|
|
|
|
struct weston_pointer *pointer = grab->pointer;
|
|
|
|
enum wl_pointer_button_state state = state_w;
|
|
|
|
|
|
|
|
if (pointer->button_count == 0 &&
|
|
|
|
state == WL_POINTER_BUTTON_STATE_RELEASED) {
|
|
|
|
shell_grab_end(&resize->base);
|
|
|
|
free(grab);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
resize_grab_cancel(struct weston_pointer_grab *grab)
|
|
|
|
{
|
|
|
|
struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
|
|
|
|
|
|
|
|
shell_grab_end(&resize->base);
|
|
|
|
free(grab);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct weston_pointer_grab_interface resize_grab_interface = {
|
|
|
|
noop_grab_focus,
|
|
|
|
resize_grab_motion,
|
|
|
|
resize_grab_button,
|
|
|
|
noop_grab_axis,
|
|
|
|
noop_grab_axis_source,
|
|
|
|
noop_grab_frame,
|
|
|
|
resize_grab_cancel,
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns the bounding box of a surface and all its sub-surfaces,
|
|
|
|
* in surface-local coordinates. */
|
|
|
|
static void
|
|
|
|
surface_subsurfaces_boundingbox(struct weston_surface *surface, int32_t *x,
|
|
|
|
int32_t *y, int32_t *w, int32_t *h) {
|
|
|
|
pixman_region32_t region;
|
|
|
|
pixman_box32_t *box;
|
|
|
|
struct weston_subsurface *subsurface;
|
|
|
|
|
|
|
|
pixman_region32_init_rect(®ion, 0, 0,
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
surface->width,
|
|
|
|
surface->height);
|
|
|
|
|
|
|
|
wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) {
|
|
|
|
pixman_region32_union_rect(®ion, ®ion,
|
|
|
|
subsurface->position.x,
|
|
|
|
subsurface->position.y,
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
subsurface->surface->width,
|
|
|
|
subsurface->surface->height);
|
|
|
|
}
|
|
|
|
|
|
|
|
box = pixman_region32_extents(®ion);
|
|
|
|
if (x)
|
|
|
|
*x = box->x1;
|
|
|
|
if (y)
|
|
|
|
*y = box->y1;
|
|
|
|
if (w)
|
|
|
|
*w = box->x2 - box->x1;
|
|
|
|
if (h)
|
|
|
|
*h = box->y2 - box->y1;
|
|
|
|
|
|
|
|
pixman_region32_fini(®ion);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
surface_resize(struct shell_surface *shsurf,
|
|
|
|
struct weston_pointer *pointer, uint32_t edges)
|
|
|
|
{
|
|
|
|
struct weston_resize_grab *resize;
|
|
|
|
const unsigned resize_topbottom =
|
|
|
|
WL_SHELL_SURFACE_RESIZE_TOP | WL_SHELL_SURFACE_RESIZE_BOTTOM;
|
|
|
|
const unsigned resize_leftright =
|
|
|
|
WL_SHELL_SURFACE_RESIZE_LEFT | WL_SHELL_SURFACE_RESIZE_RIGHT;
|
|
|
|
const unsigned resize_any = resize_topbottom | resize_leftright;
|
|
|
|
|
|
|
|
if (shsurf->grabbed ||
|
|
|
|
shsurf->state.fullscreen || shsurf->state.maximized)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Check for invalid edge combinations. */
|
|
|
|
if (edges == WL_SHELL_SURFACE_RESIZE_NONE || edges > resize_any ||
|
|
|
|
(edges & resize_topbottom) == resize_topbottom ||
|
|
|
|
(edges & resize_leftright) == resize_leftright)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
resize = malloc(sizeof *resize);
|
|
|
|
if (!resize)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
resize->edges = edges;
|
|
|
|
|
shell: Replace set_margin with set_window_geometry
Currently, there is a fun flicker when toggling maximization or
fullscreen on a window in mutter or more sophisicated compositors
and WMs.
What happens is that the client want so go maximized, so we
calculate the size that we want the window to resize to (640x480),
and then add on its margins to find the buffer size (+10 = 660x500),
and then send out a configure event for that size. The client
renders to that size, realizes that it's maximized, and then
says "oh hey, my margins are actually 0 now!", and so the compositor
has to send out another configure event.
In order to fix this, make the the configure request correspond to
the window geometry we'd like the window to be at. At the same time,
replace set_margin with set_window_geometry, where we specify a rect
rather than a border around the window.
11 years ago
|
|
|
resize->width = shsurf->geometry.width;
|
|
|
|
resize->height = shsurf->geometry.height;
|
|
|
|
|
|
|
|
shsurf->resize_edges = edges;
|
|
|
|
shell_surface_state_changed(shsurf);
|
|
|
|
shell_grab_start(&resize->base, &resize_grab_interface, shsurf,
|
|
|
|
pointer, edges);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
common_surface_resize(struct wl_resource *resource,
|
|
|
|
struct wl_resource *seat_resource, uint32_t serial,
|
|
|
|
uint32_t edges)
|
|
|
|
{
|
|
|
|
struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
|
|
|
|
struct weston_pointer *pointer = weston_seat_get_pointer(seat);
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
struct weston_surface *surface;
|
|
|
|
|
|
|
|
if (!pointer ||
|
|
|
|
pointer->button_count == 0 ||
|
|
|
|
pointer->grab_serial != serial ||
|
|
|
|
pointer->focus == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
surface = weston_surface_get_main_surface(pointer->focus->surface);
|
|
|
|
if (surface != shsurf->surface)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (surface_resize(shsurf, pointer, edges) < 0)
|
|
|
|
wl_resource_post_no_memory(resource);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
|
|
|
|
struct wl_resource *seat_resource, uint32_t serial,
|
|
|
|
uint32_t edges)
|
|
|
|
{
|
|
|
|
common_surface_resize(resource, seat_resource, serial, edges);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
busy_cursor_grab_focus(struct weston_pointer_grab *base)
|
|
|
|
{
|
|
|
|
struct shell_grab *grab = (struct shell_grab *) base;
|
|
|
|
struct weston_pointer *pointer = base->pointer;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *view;
|
|
|
|
wl_fixed_t sx, sy;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
view = weston_compositor_pick_view(pointer->seat->compositor,
|
|
|
|
pointer->x, pointer->y,
|
|
|
|
&sx, &sy);
|
|
|
|
|
|
|
|
if (!grab->shsurf || grab->shsurf->surface != view->surface) {
|
|
|
|
shell_grab_end(grab);
|
|
|
|
free(grab);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
busy_cursor_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
|
|
|
|
struct weston_pointer_motion_event *event)
|
|
|
|
{
|
|
|
|
weston_pointer_move(grab->pointer, event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
busy_cursor_grab_button(struct weston_pointer_grab *base,
|
|
|
|
uint32_t time, uint32_t button, uint32_t state)
|
|
|
|
{
|
|
|
|
struct shell_grab *grab = (struct shell_grab *) base;
|
|
|
|
struct shell_surface *shsurf = grab->shsurf;
|
|
|
|
struct weston_pointer *pointer = grab->grab.pointer;
|
|
|
|
struct weston_seat *seat = pointer->seat;
|
|
|
|
|
|
|
|
if (shsurf && button == BTN_LEFT && state) {
|
|
|
|
activate(shsurf->shell, shsurf->surface, seat, true);
|
|
|
|
surface_move(shsurf, pointer, false);
|
|
|
|
} else if (shsurf && button == BTN_RIGHT && state) {
|
|
|
|
activate(shsurf->shell, shsurf->surface, seat, true);
|
|
|
|
surface_rotate(shsurf, pointer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
busy_cursor_grab_cancel(struct weston_pointer_grab *base)
|
|
|
|
{
|
|
|
|
struct shell_grab *grab = (struct shell_grab *) base;
|
|
|
|
|
|
|
|
shell_grab_end(grab);
|
|
|
|
free(grab);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct weston_pointer_grab_interface busy_cursor_grab_interface = {
|
|
|
|
busy_cursor_grab_focus,
|
|
|
|
busy_cursor_grab_motion,
|
|
|
|
busy_cursor_grab_button,
|
|
|
|
noop_grab_axis,
|
|
|
|
noop_grab_axis_source,
|
|
|
|
noop_grab_frame,
|
|
|
|
busy_cursor_grab_cancel,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_busy_cursor(struct shell_surface *shsurf, struct weston_pointer *pointer)
|
|
|
|
{
|
|
|
|
struct shell_grab *grab;
|
|
|
|
|
|
|
|
if (pointer->grab->interface == &busy_cursor_grab_interface)
|
|
|
|
return;
|
|
|
|
|
|
|
|
grab = malloc(sizeof *grab);
|
|
|
|
if (!grab)
|
|
|
|
return;
|
|
|
|
|
|
|
|
shell_grab_start(grab, &busy_cursor_grab_interface, shsurf, pointer,
|
|
|
|
WESTON_DESKTOP_SHELL_CURSOR_BUSY);
|
|
|
|
/* Mark the shsurf as ungrabbed so that button binding is able
|
|
|
|
* to move it. */
|
|
|
|
shsurf->grabbed = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
end_busy_cursor(struct weston_compositor *compositor, struct wl_client *client)
|
|
|
|
{
|
|
|
|
struct shell_grab *grab;
|
|
|
|
struct weston_seat *seat;
|
|
|
|
|
|
|
|
wl_list_for_each(seat, &compositor->seat_list, link) {
|
|
|
|
struct weston_pointer *pointer = weston_seat_get_pointer(seat);
|
|
|
|
|
|
|
|
if (!pointer)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
grab = (struct shell_grab *) pointer->grab;
|
|
|
|
if (grab->grab.interface == &busy_cursor_grab_interface &&
|
|
|
|
grab->shsurf->resource &&
|
|
|
|
wl_resource_get_client(grab->shsurf->resource) == client) {
|
|
|
|
shell_grab_end(grab);
|
|
|
|
free(grab);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_shell_client_destroy(struct wl_listener *listener, void *data);
|
|
|
|
|
|
|
|
static int
|
|
|
|
xdg_ping_timeout_handler(void *data)
|
|
|
|
{
|
|
|
|
struct shell_client *sc = data;
|
|
|
|
struct weston_seat *seat;
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
|
|
|
|
/* Client is not responding */
|
|
|
|
sc->unresponsive = 1;
|
|
|
|
wl_list_for_each(seat, &sc->shell->compositor->seat_list, link) {
|
|
|
|
struct weston_pointer *pointer = weston_seat_get_pointer(seat);
|
|
|
|
|
|
|
|
if (!pointer ||
|
|
|
|
!pointer->focus ||
|
|
|
|
!pointer->focus->surface->resource)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
shsurf = get_shell_surface(pointer->focus->surface);
|
|
|
|
if (shsurf && shsurf->resource &&
|
|
|
|
wl_resource_get_client(shsurf->resource) == sc->client)
|
|
|
|
set_busy_cursor(shsurf, pointer);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_xdg_ping(struct shell_surface *shsurf, uint32_t serial)
|
|
|
|
{
|
|
|
|
struct weston_compositor *compositor = shsurf->shell->compositor;
|
|
|
|
struct shell_client *sc = shsurf->owner;
|
|
|
|
struct wl_event_loop *loop;
|
|
|
|
static const int ping_timeout = 200;
|
|
|
|
|
|
|
|
if (sc->unresponsive) {
|
|
|
|
xdg_ping_timeout_handler(sc);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sc->ping_serial = serial;
|
|
|
|
loop = wl_display_get_event_loop(compositor->wl_display);
|
|
|
|
if (sc->ping_timer == NULL)
|
|
|
|
sc->ping_timer =
|
|
|
|
wl_event_loop_add_timer(loop,
|
|
|
|
xdg_ping_timeout_handler, sc);
|
|
|
|
if (sc->ping_timer == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
wl_event_source_timer_update(sc->ping_timer, ping_timeout);
|
|
|
|
|
|
|
|
if (shell_surface_is_xdg_surface(shsurf) ||
|
|
|
|
shell_surface_is_xdg_popup(shsurf))
|
|
|
|
xdg_shell_send_ping(sc->resource, serial);
|
|
|
|
else if (shell_surface_is_wl_shell_surface(shsurf)
|
|
|
|
&& shsurf->resource)
|
|
|
|
wl_shell_surface_send_ping(shsurf->resource, serial);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ping_handler(struct weston_surface *surface, uint32_t serial)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = get_shell_surface(surface);
|
|
|
|
|
|
|
|
if (!shsurf)
|
|
|
|
return;
|
|
|
|
if (!shsurf->resource)
|
|
|
|
return;
|
|
|
|
if (shsurf->surface == shsurf->shell->grab_surface)
|
|
|
|
return;
|
|
|
|
if (!shsurf->owner)
|
|
|
|
return;
|
|
|
|
|
|
|
|
handle_xdg_ping(shsurf, serial);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_pointer_focus(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct weston_pointer *pointer = data;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *view = pointer->focus;
|
|
|
|
struct weston_compositor *compositor;
|
|
|
|
uint32_t serial;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
if (!view)
|
|
|
|
return;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
compositor = view->surface->compositor;
|
|
|
|
serial = wl_display_next_serial(compositor->wl_display);
|
|
|
|
ping_handler(view->surface, serial);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_lose_keyboard_focus(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
if (--shsurf->focus_count == 0)
|
|
|
|
shell_surface_state_changed(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_gain_keyboard_focus(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
if (shsurf->focus_count++ == 0)
|
|
|
|
shell_surface_state_changed(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_keyboard_focus(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct weston_keyboard *keyboard = data;
|
|
|
|
struct shell_seat *seat = get_shell_seat(keyboard->seat);
|
|
|
|
|
|
|
|
if (seat->focused_surface) {
|
|
|
|
struct shell_surface *shsurf = get_shell_surface(seat->focused_surface);
|
|
|
|
if (shsurf)
|
|
|
|
shell_surface_lose_keyboard_focus(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
seat->focused_surface = keyboard->focus;
|
|
|
|
|
|
|
|
if (seat->focused_surface) {
|
|
|
|
struct shell_surface *shsurf = get_shell_surface(seat->focused_surface);
|
|
|
|
if (shsurf)
|
|
|
|
shell_surface_gain_keyboard_focus(shsurf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_client_pong(struct shell_client *sc, uint32_t serial)
|
|
|
|
{
|
|
|
|
if (sc->ping_serial != serial)
|
|
|
|
return;
|
|
|
|
|
|
|
|
sc->unresponsive = 0;
|
|
|
|
end_busy_cursor(sc->shell->compositor, sc->client);
|
|
|
|
|
|
|
|
if (sc->ping_timer) {
|
|
|
|
wl_event_source_remove(sc->ping_timer);
|
|
|
|
sc->ping_timer = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_pong(struct wl_client *client,
|
|
|
|
struct wl_resource *resource, uint32_t serial)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
struct shell_client *sc = shsurf->owner;
|
|
|
|
|
|
|
|
shell_client_pong(sc, serial);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_title(struct shell_surface *shsurf, const char *title)
|
|
|
|
{
|
|
|
|
free(shsurf->title);
|
|
|
|
shsurf->title = strdup(title);
|
compositor: Implement JSON-timeline logging
Logging is activated and deactivated with the debug key binding 't'.
When activated, it creates a new log file, where it records the events.
The log file contains events and detailed object information entries in
JSON format, and is meant to be parsed in sequence from beginning to the
end.
The emitted events are mostly related to the output repaint cycle, like
when repaint begins, is submitted to GPU, and when it completes on a
vblank. This is recorded per-output. Also some per-surface events are
recorded, including when surface damage is flushed.
To reduce the log size, events refer to objects like outputs and
surfaces by id numbers. Detailed object information is emitted only as
needed: on the first object occurrence, and afterwards only if
weston_timeline_object::force_refresh asks for it.
The detailed information for surfaces includes the string returned by
weston_surface::get_label. Therefore it is important to set
weston_timeline_object::force_refresh = 1 whenever the string would
change, so that the new details get recorded.
A rudimentary parser and SVG generator can be found at:
https://github.com/ppaalanen/wesgr
The timeline logs can answer questions including:
- How does the compositor repaint cycle work timing-wise?
- When was the vblank deadline missed?
- What is the latency from surface commit to showing the new content on
screen?
- How long does it take to process the scenegraph?
v2: weston_surface::get_description renamed to get_label.
v3: reafctor a bit into fprint_quoted_string().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
10 years ago
|
|
|
shsurf->surface->timeline.force_refresh = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_pid(struct shell_surface *shsurf, pid_t pid)
|
|
|
|
{
|
|
|
|
/* We have no use for it */
|
|
|
|
}
|
|
|
|
|
compositor: Implement JSON-timeline logging
Logging is activated and deactivated with the debug key binding 't'.
When activated, it creates a new log file, where it records the events.
The log file contains events and detailed object information entries in
JSON format, and is meant to be parsed in sequence from beginning to the
end.
The emitted events are mostly related to the output repaint cycle, like
when repaint begins, is submitted to GPU, and when it completes on a
vblank. This is recorded per-output. Also some per-surface events are
recorded, including when surface damage is flushed.
To reduce the log size, events refer to objects like outputs and
surfaces by id numbers. Detailed object information is emitted only as
needed: on the first object occurrence, and afterwards only if
weston_timeline_object::force_refresh asks for it.
The detailed information for surfaces includes the string returned by
weston_surface::get_label. Therefore it is important to set
weston_timeline_object::force_refresh = 1 whenever the string would
change, so that the new details get recorded.
A rudimentary parser and SVG generator can be found at:
https://github.com/ppaalanen/wesgr
The timeline logs can answer questions including:
- How does the compositor repaint cycle work timing-wise?
- When was the vblank deadline missed?
- What is the latency from surface commit to showing the new content on
screen?
- How long does it take to process the scenegraph?
v2: weston_surface::get_description renamed to get_label.
v3: reafctor a bit into fprint_quoted_string().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
10 years ago
|
|
|
static void
|
|
|
|
set_type(struct shell_surface *shsurf, enum shell_surface_type t)
|
|
|
|
{
|
|
|
|
shsurf->type = t;
|
|
|
|
shsurf->surface->timeline.force_refresh = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
shell: Replace set_margin with set_window_geometry
Currently, there is a fun flicker when toggling maximization or
fullscreen on a window in mutter or more sophisicated compositors
and WMs.
What happens is that the client want so go maximized, so we
calculate the size that we want the window to resize to (640x480),
and then add on its margins to find the buffer size (+10 = 660x500),
and then send out a configure event for that size. The client
renders to that size, realizes that it's maximized, and then
says "oh hey, my margins are actually 0 now!", and so the compositor
has to send out another configure event.
In order to fix this, make the the configure request correspond to
the window geometry we'd like the window to be at. At the same time,
replace set_margin with set_window_geometry, where we specify a rect
rather than a border around the window.
11 years ago
|
|
|
set_window_geometry(struct shell_surface *shsurf,
|
|
|
|
int32_t x, int32_t y, int32_t width, int32_t height)
|
|
|
|
{
|
shell: Replace set_margin with set_window_geometry
Currently, there is a fun flicker when toggling maximization or
fullscreen on a window in mutter or more sophisicated compositors
and WMs.
What happens is that the client want so go maximized, so we
calculate the size that we want the window to resize to (640x480),
and then add on its margins to find the buffer size (+10 = 660x500),
and then send out a configure event for that size. The client
renders to that size, realizes that it's maximized, and then
says "oh hey, my margins are actually 0 now!", and so the compositor
has to send out another configure event.
In order to fix this, make the the configure request correspond to
the window geometry we'd like the window to be at. At the same time,
replace set_margin with set_window_geometry, where we specify a rect
rather than a border around the window.
11 years ago
|
|
|
shsurf->next_geometry.x = x;
|
|
|
|
shsurf->next_geometry.y = y;
|
|
|
|
shsurf->next_geometry.width = width;
|
|
|
|
shsurf->next_geometry.height = height;
|
|
|
|
shsurf->has_next_geometry = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_set_title(struct wl_client *client,
|
|
|
|
struct wl_resource *resource, const char *title)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
|
|
|
|
set_title(shsurf, title);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_set_class(struct wl_client *client,
|
|
|
|
struct wl_resource *resource, const char *class)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
|
|
|
|
free(shsurf->class);
|
|
|
|
shsurf->class = strdup(class);
|
compositor: Implement JSON-timeline logging
Logging is activated and deactivated with the debug key binding 't'.
When activated, it creates a new log file, where it records the events.
The log file contains events and detailed object information entries in
JSON format, and is meant to be parsed in sequence from beginning to the
end.
The emitted events are mostly related to the output repaint cycle, like
when repaint begins, is submitted to GPU, and when it completes on a
vblank. This is recorded per-output. Also some per-surface events are
recorded, including when surface damage is flushed.
To reduce the log size, events refer to objects like outputs and
surfaces by id numbers. Detailed object information is emitted only as
needed: on the first object occurrence, and afterwards only if
weston_timeline_object::force_refresh asks for it.
The detailed information for surfaces includes the string returned by
weston_surface::get_label. Therefore it is important to set
weston_timeline_object::force_refresh = 1 whenever the string would
change, so that the new details get recorded.
A rudimentary parser and SVG generator can be found at:
https://github.com/ppaalanen/wesgr
The timeline logs can answer questions including:
- How does the compositor repaint cycle work timing-wise?
- When was the vblank deadline missed?
- What is the latency from surface commit to showing the new content on
screen?
- How long does it take to process the scenegraph?
v2: weston_surface::get_description renamed to get_label.
v3: reafctor a bit into fprint_quoted_string().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
10 years ago
|
|
|
shsurf->surface->timeline.force_refresh = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
restore_output_mode(struct weston_output *output)
|
|
|
|
{
|
|
|
|
if (output->original_mode)
|
|
|
|
weston_output_mode_switch_to_native(output);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
restore_all_output_modes(struct weston_compositor *compositor)
|
|
|
|
{
|
|
|
|
struct weston_output *output;
|
|
|
|
|
|
|
|
wl_list_for_each(output, &compositor->output_list, link)
|
|
|
|
restore_output_mode(output);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The surface will be inserted into the list immediately after the link
|
|
|
|
* returned by this function (i.e. will be stacked immediately above the
|
|
|
|
* returned link). */
|
|
|
|
static struct weston_layer_entry *
|
|
|
|
shell_surface_calculate_layer_link (struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
struct workspace *ws;
|
|
|
|
struct weston_view *parent;
|
|
|
|
|
|
|
|
switch (shsurf->type) {
|
|
|
|
case SHELL_SURFACE_XWAYLAND:
|
|
|
|
return &shsurf->shell->fullscreen_layer.view_list;
|
|
|
|
|
|
|
|
case SHELL_SURFACE_NONE:
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
case SHELL_SURFACE_POPUP:
|
|
|
|
case SHELL_SURFACE_TOPLEVEL:
|
|
|
|
if (shsurf->state.fullscreen && !shsurf->state.lowered) {
|
|
|
|
return &shsurf->shell->fullscreen_layer.view_list;
|
|
|
|
} else if (shsurf->parent) {
|
|
|
|
/* Move the surface to its parent layer so
|
|
|
|
* that surfaces which are transient for
|
|
|
|
* fullscreen surfaces don't get hidden by the
|
|
|
|
* fullscreen surfaces. */
|
|
|
|
|
|
|
|
/* TODO: Handle a parent with multiple views */
|
|
|
|
parent = get_default_view(shsurf->parent);
|
|
|
|
if (parent)
|
|
|
|
return container_of(parent->layer_link.link.prev,
|
|
|
|
struct weston_layer_entry, link);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Move the surface to a normal workspace layer so that surfaces
|
|
|
|
* which were previously fullscreen or transient are no longer
|
|
|
|
* rendered on top. */
|
|
|
|
ws = get_current_workspace(shsurf->shell);
|
|
|
|
return &ws->layer.view_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(0 && "Unknown shell surface type");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_update_child_surface_layers (struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
struct shell_surface *child;
|
|
|
|
struct weston_layer_entry *prev;
|
|
|
|
|
|
|
|
/* Move the child layers to the same workspace as shsurf. They will be
|
|
|
|
* stacked above shsurf. */
|
|
|
|
wl_list_for_each_reverse(child, &shsurf->children_list, children_link) {
|
|
|
|
if (shsurf->view->layer_link.link.prev != &child->view->layer_link.link) {
|
|
|
|
weston_view_damage_below(child->view);
|
|
|
|
weston_view_geometry_dirty(child->view);
|
|
|
|
prev = container_of(shsurf->view->layer_link.link.prev,
|
|
|
|
struct weston_layer_entry, link);
|
|
|
|
weston_layer_entry_remove(&child->view->layer_link);
|
|
|
|
weston_layer_entry_insert(prev,
|
|
|
|
&child->view->layer_link);
|
|
|
|
weston_view_geometry_dirty(child->view);
|
|
|
|
weston_surface_damage(child->surface);
|
|
|
|
|
|
|
|
/* Recurse. We don’t expect this to recurse very far (if
|
|
|
|
* at all) because that would imply we have transient
|
|
|
|
* (or popup) children of transient surfaces, which
|
|
|
|
* would be unusual. */
|
|
|
|
shell_surface_update_child_surface_layers(child);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update the surface’s layer. Mark both the old and new views as having dirty
|
|
|
|
* geometry to ensure the changes are redrawn.
|
|
|
|
*
|
|
|
|
* If any child surfaces exist and are mapped, ensure they’re in the same layer
|
|
|
|
* as this surface. */
|
|
|
|
static void
|
|
|
|
shell_surface_update_layer(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
struct weston_layer_entry *new_layer_link;
|
|
|
|
|
|
|
|
new_layer_link = shell_surface_calculate_layer_link(shsurf);
|
|
|
|
|
|
|
|
if (new_layer_link == NULL)
|
|
|
|
return;
|
|
|
|
if (new_layer_link == &shsurf->view->layer_link)
|
|
|
|
return;
|
|
|
|
|
|
|
|
weston_view_geometry_dirty(shsurf->view);
|
|
|
|
weston_layer_entry_remove(&shsurf->view->layer_link);
|
|
|
|
weston_layer_entry_insert(new_layer_link, &shsurf->view->layer_link);
|
|
|
|
weston_view_geometry_dirty(shsurf->view);
|
|
|
|
weston_surface_damage(shsurf->surface);
|
|
|
|
|
|
|
|
shell_surface_update_child_surface_layers(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_set_parent(struct shell_surface *shsurf,
|
|
|
|
struct weston_surface *parent)
|
|
|
|
{
|
|
|
|
shsurf->parent = parent;
|
|
|
|
|
|
|
|
wl_list_remove(&shsurf->children_link);
|
|
|
|
wl_list_init(&shsurf->children_link);
|
|
|
|
|
|
|
|
/* Insert into the parent surface’s child list. */
|
|
|
|
if (parent != NULL) {
|
|
|
|
struct shell_surface *parent_shsurf = get_shell_surface(parent);
|
|
|
|
if (parent_shsurf != NULL)
|
|
|
|
wl_list_insert(&parent_shsurf->children_list,
|
|
|
|
&shsurf->children_link);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_set_output(struct shell_surface *shsurf,
|
|
|
|
struct weston_output *output)
|
|
|
|
{
|
|
|
|
struct weston_surface *es = shsurf->surface;
|
|
|
|
|
|
|
|
/* get the default output, if the client set it as NULL
|
|
|
|
check whether the ouput is available */
|
|
|
|
if (output)
|
|
|
|
shsurf->output = output;
|
|
|
|
else if (es->output)
|
|
|
|
shsurf->output = es->output;
|
|
|
|
else
|
|
|
|
shsurf->output = get_default_output(es->compositor);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
surface_clear_next_states(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
shsurf->next_state.maximized = false;
|
|
|
|
shsurf->next_state.fullscreen = false;
|
|
|
|
|
|
|
|
if ((shsurf->next_state.maximized != shsurf->state.maximized) ||
|
|
|
|
(shsurf->next_state.fullscreen != shsurf->state.fullscreen))
|
|
|
|
shsurf->state_changed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_toplevel(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
shell_surface_set_parent(shsurf, NULL);
|
|
|
|
surface_clear_next_states(shsurf);
|
compositor: Implement JSON-timeline logging
Logging is activated and deactivated with the debug key binding 't'.
When activated, it creates a new log file, where it records the events.
The log file contains events and detailed object information entries in
JSON format, and is meant to be parsed in sequence from beginning to the
end.
The emitted events are mostly related to the output repaint cycle, like
when repaint begins, is submitted to GPU, and when it completes on a
vblank. This is recorded per-output. Also some per-surface events are
recorded, including when surface damage is flushed.
To reduce the log size, events refer to objects like outputs and
surfaces by id numbers. Detailed object information is emitted only as
needed: on the first object occurrence, and afterwards only if
weston_timeline_object::force_refresh asks for it.
The detailed information for surfaces includes the string returned by
weston_surface::get_label. Therefore it is important to set
weston_timeline_object::force_refresh = 1 whenever the string would
change, so that the new details get recorded.
A rudimentary parser and SVG generator can be found at:
https://github.com/ppaalanen/wesgr
The timeline logs can answer questions including:
- How does the compositor repaint cycle work timing-wise?
- When was the vblank deadline missed?
- What is the latency from surface commit to showing the new content on
screen?
- How long does it take to process the scenegraph?
v2: weston_surface::get_description renamed to get_label.
v3: reafctor a bit into fprint_quoted_string().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
10 years ago
|
|
|
set_type(shsurf, SHELL_SURFACE_TOPLEVEL);
|
|
|
|
|
|
|
|
/* The layer_link is updated in set_surface_type(),
|
|
|
|
* called from configure. */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_set_toplevel(struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
struct shell_surface *surface = wl_resource_get_user_data(resource);
|
|
|
|
|
|
|
|
set_toplevel(surface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_transient(struct shell_surface *shsurf,
|
|
|
|
struct weston_surface *parent, int x, int y, uint32_t flags)
|
|
|
|
{
|
|
|
|
assert(parent != NULL);
|
|
|
|
|
|
|
|
shell_surface_set_parent(shsurf, parent);
|
|
|
|
|
|
|
|
surface_clear_next_states(shsurf);
|
|
|
|
|
|
|
|
shsurf->transient.x = x;
|
|
|
|
shsurf->transient.y = y;
|
|
|
|
shsurf->transient.flags = flags;
|
|
|
|
|
|
|
|
shsurf->next_state.relative = true;
|
|
|
|
shsurf->state_changed = true;
|
compositor: Implement JSON-timeline logging
Logging is activated and deactivated with the debug key binding 't'.
When activated, it creates a new log file, where it records the events.
The log file contains events and detailed object information entries in
JSON format, and is meant to be parsed in sequence from beginning to the
end.
The emitted events are mostly related to the output repaint cycle, like
when repaint begins, is submitted to GPU, and when it completes on a
vblank. This is recorded per-output. Also some per-surface events are
recorded, including when surface damage is flushed.
To reduce the log size, events refer to objects like outputs and
surfaces by id numbers. Detailed object information is emitted only as
needed: on the first object occurrence, and afterwards only if
weston_timeline_object::force_refresh asks for it.
The detailed information for surfaces includes the string returned by
weston_surface::get_label. Therefore it is important to set
weston_timeline_object::force_refresh = 1 whenever the string would
change, so that the new details get recorded.
A rudimentary parser and SVG generator can be found at:
https://github.com/ppaalanen/wesgr
The timeline logs can answer questions including:
- How does the compositor repaint cycle work timing-wise?
- When was the vblank deadline missed?
- What is the latency from surface commit to showing the new content on
screen?
- How long does it take to process the scenegraph?
v2: weston_surface::get_description renamed to get_label.
v3: reafctor a bit into fprint_quoted_string().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
10 years ago
|
|
|
set_type(shsurf, SHELL_SURFACE_TOPLEVEL);
|
|
|
|
|
|
|
|
/* The layer_link is updated in set_surface_type(),
|
|
|
|
* called from configure. */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_set_transient(struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
struct wl_resource *parent_resource,
|
|
|
|
int x, int y, uint32_t flags)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
struct weston_surface *parent =
|
|
|
|
wl_resource_get_user_data(parent_resource);
|
|
|
|
|
|
|
|
set_transient(shsurf, parent, x, y, flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_fullscreen(struct shell_surface *shsurf,
|
|
|
|
uint32_t method,
|
|
|
|
uint32_t framerate,
|
|
|
|
struct weston_output *output)
|
|
|
|
{
|
|
|
|
shell_surface_set_output(shsurf, output);
|
compositor: Implement JSON-timeline logging
Logging is activated and deactivated with the debug key binding 't'.
When activated, it creates a new log file, where it records the events.
The log file contains events and detailed object information entries in
JSON format, and is meant to be parsed in sequence from beginning to the
end.
The emitted events are mostly related to the output repaint cycle, like
when repaint begins, is submitted to GPU, and when it completes on a
vblank. This is recorded per-output. Also some per-surface events are
recorded, including when surface damage is flushed.
To reduce the log size, events refer to objects like outputs and
surfaces by id numbers. Detailed object information is emitted only as
needed: on the first object occurrence, and afterwards only if
weston_timeline_object::force_refresh asks for it.
The detailed information for surfaces includes the string returned by
weston_surface::get_label. Therefore it is important to set
weston_timeline_object::force_refresh = 1 whenever the string would
change, so that the new details get recorded.
A rudimentary parser and SVG generator can be found at:
https://github.com/ppaalanen/wesgr
The timeline logs can answer questions including:
- How does the compositor repaint cycle work timing-wise?
- When was the vblank deadline missed?
- What is the latency from surface commit to showing the new content on
screen?
- How long does it take to process the scenegraph?
v2: weston_surface::get_description renamed to get_label.
v3: reafctor a bit into fprint_quoted_string().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
10 years ago
|
|
|
set_type(shsurf, SHELL_SURFACE_TOPLEVEL);
|
|
|
|
|
|
|
|
shsurf->fullscreen_output = shsurf->output;
|
|
|
|
shsurf->fullscreen.type = method;
|
|
|
|
shsurf->fullscreen.framerate = framerate;
|
|
|
|
|
shell: Centralize management of sending configure requests
Currently, there's a giant bug in how xdg-shell state management
is done. If a client calls set_fullscreen and then set_maximized,
it will get two configure events:
=> set_fullscreen
<= configure(800, 600, [STATE_FULLSCREEN])
=> set_maximized
<= configure(800, 560, [STATE_FULLSCREEN, STATE_MAXIMIZED])
Since fullscreen takes precedence over maximized, the client will
render full-screen at 800x600 first, and then 800x560 next. As
a result, the surface gets the wrong size.
This is because the code that sends out configure requests is
"immediate" -- when an app calls set_maximized, we immediately
send out the configure event that would have happened if we
transitioned immediately into maximized mode.
In wl_shell, this is correct behavior. However, in xdg-shell,
this is wrong. State needs to be more carefully managed in
xdg-shell, as states aren't exclusive.
Pull all the code that sends out configure events out and send
them centrally, based on Weston's on surface state management.
This should work with both wl_shell and xdg_shell's strategies.
11 years ago
|
|
|
send_configure_for_surface(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
weston_view_set_initial_position(struct weston_view *view,
|
|
|
|
struct desktop_shell *shell);
|
|
|
|
|
|
|
|
static void
|
|
|
|
unset_fullscreen(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
/* Unset the fullscreen output, driver configuration and transforms. */
|
|
|
|
if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
|
|
|
|
shell_surface_is_top_fullscreen(shsurf)) {
|
|
|
|
restore_output_mode(shsurf->fullscreen_output);
|
|
|
|
}
|
|
|
|
|
|
|
|
shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
|
|
|
|
shsurf->fullscreen.framerate = 0;
|
|
|
|
|
|
|
|
wl_list_remove(&shsurf->fullscreen.transform.link);
|
|
|
|
wl_list_init(&shsurf->fullscreen.transform.link);
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
if (shsurf->fullscreen.black_view)
|
|
|
|
weston_surface_destroy(shsurf->fullscreen.black_view->surface);
|
|
|
|
shsurf->fullscreen.black_view = NULL;
|
|
|
|
|
|
|
|
if (shsurf->saved_position_valid)
|
|
|
|
weston_view_set_position(shsurf->view,
|
|
|
|
shsurf->saved_x, shsurf->saved_y);
|
|
|
|
else
|
|
|
|
weston_view_set_initial_position(shsurf->view, shsurf->shell);
|
|
|
|
|
|
|
|
if (shsurf->saved_rotation_valid) {
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
wl_list_insert(&shsurf->view->geometry.transformation_list,
|
|
|
|
&shsurf->rotation.transform.link);
|
|
|
|
shsurf->saved_rotation_valid = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Layer is updated in set_surface_type(). */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_set_fullscreen(struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t method,
|
|
|
|
uint32_t framerate,
|
|
|
|
struct wl_resource *output_resource)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
struct weston_output *output;
|
|
|
|
|
|
|
|
if (shsurf->fullscreen_output == shsurf->output &&
|
|
|
|
shsurf->fullscreen.type == method &&
|
|
|
|
shsurf->fullscreen.framerate == framerate) {
|
|
|
|
send_configure_for_surface(shsurf);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (output_resource)
|
|
|
|
output = wl_resource_get_user_data(output_resource);
|
|
|
|
else
|
|
|
|
output = NULL;
|
|
|
|
|
|
|
|
shell_surface_set_parent(shsurf, NULL);
|
|
|
|
|
|
|
|
surface_clear_next_states(shsurf);
|
|
|
|
shsurf->next_state.fullscreen = true;
|
|
|
|
shsurf->state_changed = true;
|
shell: Centralize management of sending configure requests
Currently, there's a giant bug in how xdg-shell state management
is done. If a client calls set_fullscreen and then set_maximized,
it will get two configure events:
=> set_fullscreen
<= configure(800, 600, [STATE_FULLSCREEN])
=> set_maximized
<= configure(800, 560, [STATE_FULLSCREEN, STATE_MAXIMIZED])
Since fullscreen takes precedence over maximized, the client will
render full-screen at 800x600 first, and then 800x560 next. As
a result, the surface gets the wrong size.
This is because the code that sends out configure requests is
"immediate" -- when an app calls set_maximized, we immediately
send out the configure event that would have happened if we
transitioned immediately into maximized mode.
In wl_shell, this is correct behavior. However, in xdg-shell,
this is wrong. State needs to be more carefully managed in
xdg-shell, as states aren't exclusive.
Pull all the code that sends out configure events out and send
them centrally, based on Weston's on surface state management.
This should work with both wl_shell and xdg_shell's strategies.
11 years ago
|
|
|
set_fullscreen(shsurf, method, framerate, output);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_popup(struct shell_surface *shsurf,
|
|
|
|
struct weston_surface *parent,
|
|
|
|
struct weston_seat *seat,
|
|
|
|
uint32_t serial,
|
|
|
|
int32_t x,
|
|
|
|
int32_t y)
|
|
|
|
{
|
|
|
|
assert(parent != NULL);
|
|
|
|
|
|
|
|
shsurf->popup.shseat = get_shell_seat(seat);
|
|
|
|
shsurf->popup.serial = serial;
|
|
|
|
shsurf->popup.x = x;
|
|
|
|
shsurf->popup.y = y;
|
|
|
|
|
compositor: Implement JSON-timeline logging
Logging is activated and deactivated with the debug key binding 't'.
When activated, it creates a new log file, where it records the events.
The log file contains events and detailed object information entries in
JSON format, and is meant to be parsed in sequence from beginning to the
end.
The emitted events are mostly related to the output repaint cycle, like
when repaint begins, is submitted to GPU, and when it completes on a
vblank. This is recorded per-output. Also some per-surface events are
recorded, including when surface damage is flushed.
To reduce the log size, events refer to objects like outputs and
surfaces by id numbers. Detailed object information is emitted only as
needed: on the first object occurrence, and afterwards only if
weston_timeline_object::force_refresh asks for it.
The detailed information for surfaces includes the string returned by
weston_surface::get_label. Therefore it is important to set
weston_timeline_object::force_refresh = 1 whenever the string would
change, so that the new details get recorded.
A rudimentary parser and SVG generator can be found at:
https://github.com/ppaalanen/wesgr
The timeline logs can answer questions including:
- How does the compositor repaint cycle work timing-wise?
- When was the vblank deadline missed?
- What is the latency from surface commit to showing the new content on
screen?
- How long does it take to process the scenegraph?
v2: weston_surface::get_description renamed to get_label.
v3: reafctor a bit into fprint_quoted_string().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
10 years ago
|
|
|
set_type(shsurf, SHELL_SURFACE_POPUP);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_set_popup(struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
struct wl_resource *seat_resource,
|
|
|
|
uint32_t serial,
|
|
|
|
struct wl_resource *parent_resource,
|
|
|
|
int32_t x, int32_t y, uint32_t flags)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
struct weston_surface *parent =
|
|
|
|
wl_resource_get_user_data(parent_resource);
|
|
|
|
|
|
|
|
shell_surface_set_parent(shsurf, parent);
|
|
|
|
|
|
|
|
surface_clear_next_states(shsurf);
|
|
|
|
set_popup(shsurf,
|
|
|
|
parent,
|
|
|
|
wl_resource_get_user_data(seat_resource),
|
|
|
|
serial, x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
unset_maximized(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
/* undo all maximized things here */
|
|
|
|
shsurf->output = get_default_output(shsurf->surface->compositor);
|
|
|
|
|
|
|
|
if (shsurf->saved_position_valid)
|
|
|
|
weston_view_set_position(shsurf->view,
|
|
|
|
shsurf->saved_x, shsurf->saved_y);
|
|
|
|
else
|
|
|
|
weston_view_set_initial_position(shsurf->view, shsurf->shell);
|
|
|
|
|
|
|
|
if (shsurf->saved_rotation_valid) {
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
wl_list_insert(&shsurf->view->geometry.transformation_list,
|
|
|
|
&shsurf->rotation.transform.link);
|
|
|
|
shsurf->saved_rotation_valid = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Layer is updated in set_surface_type(). */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_minimized(struct weston_surface *surface)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
struct workspace *current_ws;
|
|
|
|
struct weston_view *view;
|
|
|
|
|
|
|
|
view = get_default_view(surface);
|
|
|
|
if (!view)
|
|
|
|
return;
|
|
|
|
|
|
|
|
assert(weston_surface_get_main_surface(view->surface) == view->surface);
|
|
|
|
|
|
|
|
shsurf = get_shell_surface(surface);
|
|
|
|
current_ws = get_current_workspace(shsurf->shell);
|
|
|
|
|
|
|
|
weston_layer_entry_remove(&view->layer_link);
|
|
|
|
weston_layer_entry_insert(&shsurf->shell->minimized_layer.view_list, &view->layer_link);
|
|
|
|
|
|
|
|
drop_focus_state(shsurf->shell, current_ws, view->surface);
|
|
|
|
surface_keyboard_focus_lost(surface);
|
|
|
|
|
|
|
|
shell_surface_update_child_surface_layers(shsurf);
|
|
|
|
weston_view_damage_below(view);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_set_maximized(struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
struct wl_resource *output_resource)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
struct weston_output *output;
|
|
|
|
|
|
|
|
surface_clear_next_states(shsurf);
|
|
|
|
shsurf->next_state.maximized = true;
|
|
|
|
shsurf->state_changed = true;
|
|
|
|
|
compositor: Implement JSON-timeline logging
Logging is activated and deactivated with the debug key binding 't'.
When activated, it creates a new log file, where it records the events.
The log file contains events and detailed object information entries in
JSON format, and is meant to be parsed in sequence from beginning to the
end.
The emitted events are mostly related to the output repaint cycle, like
when repaint begins, is submitted to GPU, and when it completes on a
vblank. This is recorded per-output. Also some per-surface events are
recorded, including when surface damage is flushed.
To reduce the log size, events refer to objects like outputs and
surfaces by id numbers. Detailed object information is emitted only as
needed: on the first object occurrence, and afterwards only if
weston_timeline_object::force_refresh asks for it.
The detailed information for surfaces includes the string returned by
weston_surface::get_label. Therefore it is important to set
weston_timeline_object::force_refresh = 1 whenever the string would
change, so that the new details get recorded.
A rudimentary parser and SVG generator can be found at:
https://github.com/ppaalanen/wesgr
The timeline logs can answer questions including:
- How does the compositor repaint cycle work timing-wise?
- When was the vblank deadline missed?
- What is the latency from surface commit to showing the new content on
screen?
- How long does it take to process the scenegraph?
v2: weston_surface::get_description renamed to get_label.
v3: reafctor a bit into fprint_quoted_string().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
10 years ago
|
|
|
set_type(shsurf, SHELL_SURFACE_TOPLEVEL);
|
|
|
|
shell_surface_set_parent(shsurf, NULL);
|
|
|
|
|
|
|
|
if (output_resource)
|
|
|
|
output = wl_resource_get_user_data(output_resource);
|
|
|
|
else
|
|
|
|
output = NULL;
|
|
|
|
|
|
|
|
shell_surface_set_output(shsurf, output);
|
|
|
|
|
|
|
|
send_configure_for_surface(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This is only ever called from set_surface_type(), so there’s no need to
|
|
|
|
* update layer_links here, since they’ll be updated when we return. */
|
|
|
|
static int
|
|
|
|
reset_surface_type(struct shell_surface *surface)
|
|
|
|
{
|
|
|
|
if (surface->state.fullscreen)
|
|
|
|
unset_fullscreen(surface);
|
|
|
|
if (surface->state.maximized)
|
|
|
|
unset_maximized(surface);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_full_output(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
shsurf->saved_x = shsurf->view->geometry.x;
|
|
|
|
shsurf->saved_y = shsurf->view->geometry.y;
|
|
|
|
shsurf->saved_position_valid = true;
|
|
|
|
|
|
|
|
if (!wl_list_empty(&shsurf->rotation.transform.link)) {
|
|
|
|
wl_list_remove(&shsurf->rotation.transform.link);
|
|
|
|
wl_list_init(&shsurf->rotation.transform.link);
|
|
|
|
weston_view_geometry_dirty(shsurf->view);
|
|
|
|
shsurf->saved_rotation_valid = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_surface_type(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
struct weston_surface *pes = shsurf->parent;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *pev = get_default_view(pes);
|
|
|
|
|
|
|
|
reset_surface_type(shsurf);
|
|
|
|
|
|
|
|
shsurf->state = shsurf->next_state;
|
|
|
|
shsurf->state_changed = false;
|
|
|
|
|
|
|
|
switch (shsurf->type) {
|
|
|
|
case SHELL_SURFACE_TOPLEVEL:
|
|
|
|
if (shsurf->state.maximized || shsurf->state.fullscreen) {
|
|
|
|
set_full_output(shsurf);
|
|
|
|
} else if (shsurf->state.relative && pev) {
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_set_position(shsurf->view,
|
|
|
|
pev->geometry.x + shsurf->transient.x,
|
|
|
|
pev->geometry.y + shsurf->transient.y);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SHELL_SURFACE_XWAYLAND:
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_set_position(shsurf->view, shsurf->transient.x,
|
|
|
|
shsurf->transient.y);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SHELL_SURFACE_POPUP:
|
|
|
|
case SHELL_SURFACE_NONE:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update the surface’s layer. */
|
|
|
|
shell_surface_update_layer(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct desktop_shell *
|
|
|
|
shell_surface_get_shell(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
return shsurf->shell;
|
|
|
|
}
|
|
|
|
|
compositor: add weston_surface_set_label_func()
When printing out logs from Weston's actions, mainly for debugging, it
can be very difficult to identify the different surfaces. Inspecting
the configure function pointer is not useful, as the configure functions
may live in modules.
Add vfunc get_label to weston_surface, which will produce a short,
human-readable description of the surface, which allows identifying it
better, rather than just looking at the surface size, for instance.
Set the label function from most parts of Weston, to identify cursors and
drag icons, and panels, backgrounds, screensavers and lock surfaces, and
the desktop shell's application surfaces.
v2: renamed 'description' to 'label', so we get
weston_surface_set_label_func().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
11 years ago
|
|
|
static int
|
|
|
|
black_surface_get_label(struct weston_surface *surface, char *buf, size_t len)
|
|
|
|
{
|
|
|
|
struct weston_surface *fs_surface = surface->configure_private;
|
|
|
|
int n;
|
|
|
|
int rem;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
n = snprintf(buf, len, "black background surface for ");
|
|
|
|
if (n < 0)
|
|
|
|
return n;
|
|
|
|
|
|
|
|
rem = (int)len - n;
|
|
|
|
if (rem < 0)
|
|
|
|
rem = 0;
|
|
|
|
|
|
|
|
if (fs_surface->get_label)
|
|
|
|
ret = fs_surface->get_label(fs_surface, buf + n, rem);
|
|
|
|
else
|
|
|
|
ret = snprintf(buf + n, rem, "<unknown>");
|
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
return n;
|
|
|
|
|
|
|
|
return n + ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy);
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
static struct weston_view *
|
|
|
|
create_black_surface(struct weston_compositor *ec,
|
|
|
|
struct weston_surface *fs_surface,
|
|
|
|
float x, float y, int w, int h)
|
|
|
|
{
|
|
|
|
struct weston_surface *surface = NULL;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *view;
|
|
|
|
|
|
|
|
surface = weston_surface_create(ec);
|
|
|
|
if (surface == NULL) {
|
|
|
|
weston_log("no memory\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
view = weston_view_create(surface);
|
|
|
|
if (surface == NULL) {
|
|
|
|
weston_log("no memory\n");
|
|
|
|
weston_surface_destroy(surface);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
surface->configure = black_surface_configure;
|
|
|
|
surface->configure_private = fs_surface;
|
compositor: add weston_surface_set_label_func()
When printing out logs from Weston's actions, mainly for debugging, it
can be very difficult to identify the different surfaces. Inspecting
the configure function pointer is not useful, as the configure functions
may live in modules.
Add vfunc get_label to weston_surface, which will produce a short,
human-readable description of the surface, which allows identifying it
better, rather than just looking at the surface size, for instance.
Set the label function from most parts of Weston, to identify cursors and
drag icons, and panels, backgrounds, screensavers and lock surfaces, and
the desktop shell's application surfaces.
v2: renamed 'description' to 'label', so we get
weston_surface_set_label_func().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
11 years ago
|
|
|
weston_surface_set_label_func(surface, black_surface_get_label);
|
|
|
|
weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
|
|
|
|
pixman_region32_fini(&surface->opaque);
|
|
|
|
pixman_region32_init_rect(&surface->opaque, 0, 0, w, h);
|
|
|
|
pixman_region32_fini(&surface->input);
|
|
|
|
pixman_region32_init_rect(&surface->input, 0, 0, w, h);
|
|
|
|
|
|
|
|
weston_surface_set_size(surface, w, h);
|
|
|
|
weston_view_set_position(view, x, y);
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
|
|
|
|
return view;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_ensure_fullscreen_black_view(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
struct weston_output *output = shsurf->fullscreen_output;
|
|
|
|
|
|
|
|
assert(shsurf->state.fullscreen);
|
|
|
|
|
|
|
|
if (!shsurf->fullscreen.black_view)
|
|
|
|
shsurf->fullscreen.black_view =
|
|
|
|
create_black_surface(shsurf->surface->compositor,
|
|
|
|
shsurf->surface,
|
|
|
|
output->x, output->y,
|
|
|
|
output->width,
|
|
|
|
output->height);
|
|
|
|
|
|
|
|
weston_view_geometry_dirty(shsurf->fullscreen.black_view);
|
|
|
|
weston_layer_entry_remove(&shsurf->fullscreen.black_view->layer_link);
|
|
|
|
weston_layer_entry_insert(&shsurf->view->layer_link,
|
|
|
|
&shsurf->fullscreen.black_view->layer_link);
|
|
|
|
weston_view_geometry_dirty(shsurf->fullscreen.black_view);
|
|
|
|
weston_surface_damage(shsurf->surface);
|
|
|
|
|
|
|
|
shsurf->state.lowered = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create black surface and append it to the associated fullscreen surface.
|
|
|
|
* Handle size dismatch and positioning according to the method. */
|
|
|
|
static void
|
|
|
|
shell_configure_fullscreen(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
struct weston_output *output = shsurf->fullscreen_output;
|
|
|
|
struct weston_surface *surface = shsurf->surface;
|
|
|
|
struct weston_matrix *matrix;
|
|
|
|
float scale, output_aspect, surface_aspect, x, y;
|
|
|
|
int32_t surf_x, surf_y, surf_width, surf_height;
|
|
|
|
|
|
|
|
if (shsurf->fullscreen.type != WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER)
|
|
|
|
restore_output_mode(output);
|
|
|
|
|
|
|
|
/* Reverse the effect of lower_fullscreen_layer() */
|
|
|
|
weston_layer_entry_remove(&shsurf->view->layer_link);
|
|
|
|
weston_layer_entry_insert(&shsurf->shell->fullscreen_layer.view_list, &shsurf->view->layer_link);
|
|
|
|
|
|
|
|
shell_ensure_fullscreen_black_view(shsurf);
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y,
|
|
|
|
&surf_width, &surf_height);
|
|
|
|
|
|
|
|
switch (shsurf->fullscreen.type) {
|
|
|
|
case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT:
|
compositor: introduce weston_buffer_reference
The wl_buffer reference counting API has been inconsistent. You would
manually increment the refcount and register a destroy listener, as
opposed to calling weston_buffer_post_release(), which internally
decremented the refcount, and then removing a list item.
Replace both cases with a single function:
weston_buffer_reference(weston_buffer_reference *ref, wl_buffer *buffer)
Buffer is assigned to ref->buffer, while taking care of all the refcounting
and release posting. You take a reference by passing a non-NULL buffer, and
release a reference by passing NULL as buffer. The function uses an
internal wl_buffer destroy listener, so the pointer gets reset on
destruction automatically.
This is inspired by the pipe_resource_reference() of Mesa, and modified
by krh's suggestion to add struct weston_buffer_reference.
Additionally, when a surface gets destroyed, the associated wl_buffer
will send a release event. Often the buffer is already destroyed on
client side, so the event will be discarded by libwayland-client.
Compositor-drm.c is converted to use weston_buffer_reference.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
12 years ago
|
|
|
if (surface->buffer_ref.buffer)
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
center_on_output(shsurf->view, shsurf->fullscreen_output);
|
|
|
|
break;
|
|
|
|
case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE:
|
|
|
|
/* 1:1 mapping between surface and output dimensions */
|
|
|
|
if (output->width == surf_width &&
|
|
|
|
output->height == surf_height) {
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_set_position(shsurf->view,
|
|
|
|
output->x - surf_x,
|
|
|
|
output->y - surf_y);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
matrix = &shsurf->fullscreen.transform.matrix;
|
|
|
|
weston_matrix_init(matrix);
|
|
|
|
|
|
|
|
output_aspect = (float) output->width /
|
|
|
|
(float) output->height;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
/* XXX: Use surf_width and surf_height here? */
|
|
|
|
surface_aspect = (float) surface->width /
|
|
|
|
(float) surface->height;
|
|
|
|
if (output_aspect < surface_aspect)
|
|
|
|
scale = (float) output->width /
|
|
|
|
(float) surf_width;
|
|
|
|
else
|
|
|
|
scale = (float) output->height /
|
|
|
|
(float) surf_height;
|
|
|
|
|
|
|
|
weston_matrix_scale(matrix, scale, scale, 1);
|
|
|
|
wl_list_remove(&shsurf->fullscreen.transform.link);
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
wl_list_insert(&shsurf->view->geometry.transformation_list,
|
|
|
|
&shsurf->fullscreen.transform.link);
|
|
|
|
x = output->x + (output->width - surf_width * scale) / 2 - surf_x;
|
|
|
|
y = output->y + (output->height - surf_height * scale) / 2 - surf_y;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_set_position(shsurf->view, x, y);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
|
|
|
|
if (shell_surface_is_top_fullscreen(shsurf)) {
|
|
|
|
struct weston_mode mode = {0,
|
|
|
|
surf_width * surface->buffer_viewport.buffer.scale,
|
|
|
|
surf_height * surface->buffer_viewport.buffer.scale,
|
|
|
|
shsurf->fullscreen.framerate};
|
|
|
|
|
|
|
|
if (weston_output_mode_switch_to_temporary(output, &mode,
|
|
|
|
surface->buffer_viewport.buffer.scale) == 0) {
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_set_position(shsurf->view,
|
|
|
|
output->x - surf_x,
|
|
|
|
output->y - surf_y);
|
|
|
|
shsurf->fullscreen.black_view->surface->width = output->width;
|
|
|
|
shsurf->fullscreen.black_view->surface->height = output->height;
|
|
|
|
weston_view_set_position(shsurf->fullscreen.black_view,
|
|
|
|
output->x - surf_x,
|
|
|
|
output->y - surf_y);
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
weston_log("shell: Can't switch to temporary mode.\n");
|
|
|
|
restore_output_mode(output);
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
center_on_output(shsurf->view, output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
center_on_output(shsurf->view, output);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_map_fullscreen(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
shell_configure_fullscreen(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_xwayland(struct shell_surface *shsurf, int x, int y, uint32_t flags)
|
|
|
|
{
|
|
|
|
/* XXX: using the same fields for transient type */
|
|
|
|
surface_clear_next_states(shsurf);
|
|
|
|
shsurf->transient.x = x;
|
|
|
|
shsurf->transient.y = y;
|
|
|
|
shsurf->transient.flags = flags;
|
|
|
|
|
|
|
|
shell_surface_set_parent(shsurf, NULL);
|
|
|
|
|
compositor: Implement JSON-timeline logging
Logging is activated and deactivated with the debug key binding 't'.
When activated, it creates a new log file, where it records the events.
The log file contains events and detailed object information entries in
JSON format, and is meant to be parsed in sequence from beginning to the
end.
The emitted events are mostly related to the output repaint cycle, like
when repaint begins, is submitted to GPU, and when it completes on a
vblank. This is recorded per-output. Also some per-surface events are
recorded, including when surface damage is flushed.
To reduce the log size, events refer to objects like outputs and
surfaces by id numbers. Detailed object information is emitted only as
needed: on the first object occurrence, and afterwards only if
weston_timeline_object::force_refresh asks for it.
The detailed information for surfaces includes the string returned by
weston_surface::get_label. Therefore it is important to set
weston_timeline_object::force_refresh = 1 whenever the string would
change, so that the new details get recorded.
A rudimentary parser and SVG generator can be found at:
https://github.com/ppaalanen/wesgr
The timeline logs can answer questions including:
- How does the compositor repaint cycle work timing-wise?
- When was the vblank deadline missed?
- What is the latency from surface commit to showing the new content on
screen?
- How long does it take to process the scenegraph?
v2: weston_surface::get_description renamed to get_label.
v3: reafctor a bit into fprint_quoted_string().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
10 years ago
|
|
|
set_type(shsurf, SHELL_SURFACE_XWAYLAND);
|
|
|
|
shsurf->state_changed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_interface_set_fullscreen(struct shell_surface *shsurf,
|
|
|
|
uint32_t method,
|
|
|
|
uint32_t framerate,
|
|
|
|
struct weston_output *output)
|
|
|
|
{
|
|
|
|
surface_clear_next_states(shsurf);
|
|
|
|
shsurf->next_state.fullscreen = true;
|
|
|
|
shsurf->state_changed = true;
|
|
|
|
|
|
|
|
set_fullscreen(shsurf, method, framerate, output);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct weston_output *
|
|
|
|
get_focused_output(struct weston_compositor *compositor)
|
|
|
|
{
|
|
|
|
struct weston_seat *seat;
|
|
|
|
struct weston_output *output = NULL;
|
|
|
|
|
|
|
|
wl_list_for_each(seat, &compositor->seat_list, link) {
|
|
|
|
struct weston_touch *touch = weston_seat_get_touch(seat);
|
|
|
|
struct weston_pointer *pointer = weston_seat_get_pointer(seat);
|
|
|
|
struct weston_keyboard *keyboard =
|
|
|
|
weston_seat_get_keyboard(seat);
|
|
|
|
|
|
|
|
/* Priority has touch focus, then pointer and
|
|
|
|
* then keyboard focus. We should probably have
|
|
|
|
* three for loops and check frist for touch,
|
|
|
|
* then for pointer, etc. but unless somebody has some
|
|
|
|
* objections, I think this is sufficient. */
|
|
|
|
if (touch && touch->focus)
|
|
|
|
output = touch->focus->output;
|
|
|
|
else if (pointer && pointer->focus)
|
|
|
|
output = pointer->focus->output;
|
|
|
|
else if (keyboard && keyboard->focus)
|
|
|
|
output = keyboard->focus->output;
|
|
|
|
|
|
|
|
if (output)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_interface_set_maximized(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
struct weston_output *output;
|
|
|
|
|
|
|
|
surface_clear_next_states(shsurf);
|
|
|
|
shsurf->next_state.maximized = true;
|
|
|
|
shsurf->state_changed = true;
|
|
|
|
shsurf->type = SHELL_SURFACE_TOPLEVEL;
|
|
|
|
|
|
|
|
if (!weston_surface_is_mapped(shsurf->surface))
|
|
|
|
output = get_focused_output(shsurf->surface->compositor);
|
|
|
|
else
|
|
|
|
output = shsurf->surface->output;
|
|
|
|
|
|
|
|
shell_surface_set_output(shsurf, output);
|
|
|
|
send_configure_for_surface(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
shell_interface_move(struct shell_surface *shsurf, struct weston_pointer *pointer)
|
|
|
|
{
|
|
|
|
return surface_move(shsurf, pointer, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
shell_interface_resize(struct shell_surface *shsurf,
|
|
|
|
struct weston_pointer *pointer,
|
|
|
|
uint32_t edges)
|
|
|
|
{
|
|
|
|
return surface_resize(shsurf, pointer, edges);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct weston_pointer_grab_interface popup_grab_interface;
|
|
|
|
|
|
|
|
static void
|
|
|
|
destroy_shell_seat(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct shell_seat *shseat =
|
|
|
|
container_of(listener,
|
|
|
|
struct shell_seat, seat_destroy_listener);
|
|
|
|
struct shell_surface *shsurf, *next;
|
|
|
|
|
|
|
|
if (shseat->popup_grab.grab.interface == &popup_grab_interface) {
|
|
|
|
weston_pointer_end_grab(shseat->popup_grab.grab.pointer);
|
|
|
|
shseat->popup_grab.client = NULL;
|
|
|
|
|
|
|
|
wl_list_for_each_safe(shsurf, next,
|
|
|
|
&shseat->popup_grab.surfaces_list,
|
|
|
|
popup.grab_link) {
|
|
|
|
shsurf->popup.shseat = NULL;
|
|
|
|
wl_list_init(&shsurf->popup.grab_link);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
wl_list_remove(&shseat->seat_destroy_listener.link);
|
|
|
|
free(shseat);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_seat_caps_changed(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct weston_keyboard *keyboard;
|
|
|
|
struct weston_pointer *pointer;
|
|
|
|
struct shell_seat *seat;
|
|
|
|
|
|
|
|
seat = container_of(listener, struct shell_seat, caps_changed_listener);
|
|
|
|
keyboard = weston_seat_get_keyboard(seat->seat);
|
|
|
|
pointer = weston_seat_get_pointer(seat->seat);
|
|
|
|
|
|
|
|
if (keyboard &&
|
|
|
|
wl_list_empty(&seat->keyboard_focus_listener.link)) {
|
|
|
|
wl_signal_add(&keyboard->focus_signal,
|
|
|
|
&seat->keyboard_focus_listener);
|
|
|
|
} else if (!keyboard) {
|
|
|
|
wl_list_remove(&seat->keyboard_focus_listener.link);
|
|
|
|
wl_list_init(&seat->keyboard_focus_listener.link);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pointer &&
|
|
|
|
wl_list_empty(&seat->pointer_focus_listener.link)) {
|
|
|
|
wl_signal_add(&pointer->focus_signal,
|
|
|
|
&seat->pointer_focus_listener);
|
|
|
|
} else if (!pointer) {
|
|
|
|
wl_list_remove(&seat->pointer_focus_listener.link);
|
|
|
|
wl_list_init(&seat->pointer_focus_listener.link);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct shell_seat *
|
|
|
|
create_shell_seat(struct weston_seat *seat)
|
|
|
|
{
|
|
|
|
struct shell_seat *shseat;
|
|
|
|
|
|
|
|
shseat = calloc(1, sizeof *shseat);
|
|
|
|
if (!shseat) {
|
|
|
|
weston_log("no memory to allocate shell seat\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
shseat->seat = seat;
|
|
|
|
wl_list_init(&shseat->popup_grab.surfaces_list);
|
|
|
|
|
|
|
|
shseat->seat_destroy_listener.notify = destroy_shell_seat;
|
|
|
|
wl_signal_add(&seat->destroy_signal,
|
|
|
|
&shseat->seat_destroy_listener);
|
|
|
|
|
|
|
|
shseat->keyboard_focus_listener.notify = handle_keyboard_focus;
|
|
|
|
wl_list_init(&shseat->keyboard_focus_listener.link);
|
|
|
|
|
|
|
|
shseat->pointer_focus_listener.notify = handle_pointer_focus;
|
|
|
|
wl_list_init(&shseat->pointer_focus_listener.link);
|
|
|
|
|
|
|
|
shseat->caps_changed_listener.notify = shell_seat_caps_changed;
|
|
|
|
wl_signal_add(&seat->updated_caps_signal,
|
|
|
|
&shseat->caps_changed_listener);
|
|
|
|
shell_seat_caps_changed(&shseat->caps_changed_listener, NULL);
|
|
|
|
|
|
|
|
return shseat;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct shell_seat *
|
|
|
|
get_shell_seat(struct weston_seat *seat)
|
|
|
|
{
|
|
|
|
struct wl_listener *listener;
|
|
|
|
|
|
|
|
listener = wl_signal_get(&seat->destroy_signal, destroy_shell_seat);
|
|
|
|
assert(listener != NULL);
|
|
|
|
|
|
|
|
return container_of(listener,
|
|
|
|
struct shell_seat, seat_destroy_listener);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
popup_grab_focus(struct weston_pointer_grab *grab)
|
|
|
|
{
|
|
|
|
struct weston_pointer *pointer = grab->pointer;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *view;
|
|
|
|
struct shell_seat *shseat =
|
|
|
|
container_of(grab, struct shell_seat, popup_grab.grab);
|
|
|
|
struct wl_client *client = shseat->popup_grab.client;
|
|
|
|
wl_fixed_t sx, sy;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
view = weston_compositor_pick_view(pointer->seat->compositor,
|
|
|
|
pointer->x, pointer->y,
|
|
|
|
&sx, &sy);
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
if (view && view->surface->resource &&
|
|
|
|
wl_resource_get_client(view->surface->resource) == client) {
|
|
|
|
weston_pointer_set_focus(pointer, view, sx, sy);
|
|
|
|
} else {
|
|
|
|
weston_pointer_clear_focus(pointer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
popup_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
|
|
|
|
struct weston_pointer_motion_event *event)
|
|
|
|
{
|
|
|
|
struct weston_pointer *pointer = grab->pointer;
|
|
|
|
struct wl_resource *resource;
|
|
|
|
struct wl_list *resource_list;
|
|
|
|
wl_fixed_t x, y;
|
|
|
|
wl_fixed_t sx, sy;
|
|
|
|
|
|
|
|
if (pointer->focus) {
|
|
|
|
weston_pointer_motion_to_abs(pointer, event, &x, &y);
|
|
|
|
weston_view_from_global_fixed(pointer->focus, x, y,
|
|
|
|
&pointer->sx, &pointer->sy);
|
|
|
|
}
|
|
|
|
|
|
|
|
weston_pointer_move(pointer, event);
|
|
|
|
|
|
|
|
if (!pointer->focus_client)
|
|
|
|
return;
|
|
|
|
|
|
|
|
resource_list = &pointer->focus_client->pointer_resources;
|
|
|
|
wl_resource_for_each(resource, resource_list) {
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_from_global_fixed(pointer->focus,
|
|
|
|
pointer->x, pointer->y,
|
|
|
|
&sx, &sy);
|
|
|
|
wl_pointer_send_motion(resource, time, sx, sy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
popup_grab_button(struct weston_pointer_grab *grab,
|
|
|
|
uint32_t time, uint32_t button, uint32_t state_w)
|
|
|
|
{
|
|
|
|
struct wl_resource *resource;
|
|
|
|
struct shell_seat *shseat =
|
|
|
|
container_of(grab, struct shell_seat, popup_grab.grab);
|
|
|
|
struct wl_display *display = shseat->seat->compositor->wl_display;
|
|
|
|
enum wl_pointer_button_state state = state_w;
|
|
|
|
uint32_t serial;
|
|
|
|
struct wl_list *resource_list = NULL;
|
|
|
|
|
|
|
|
if (grab->pointer->focus_client)
|
|
|
|
resource_list = &grab->pointer->focus_client->pointer_resources;
|
|
|
|
if (resource_list && !wl_list_empty(resource_list)) {
|
|
|
|
serial = wl_display_get_serial(display);
|
|
|
|
wl_resource_for_each(resource, resource_list) {
|
|
|
|
wl_pointer_send_button(resource, serial,
|
|
|
|
time, button, state);
|
|
|
|
}
|
|
|
|
} else if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
|
|
|
|
(shseat->popup_grab.initial_up ||
|
|
|
|
time - grab->pointer->grab_time > 500)) {
|
|
|
|
popup_grab_end(grab->pointer);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state == WL_POINTER_BUTTON_STATE_RELEASED)
|
|
|
|
shseat->popup_grab.initial_up = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
popup_grab_axis(struct weston_pointer_grab *grab,
|
|
|
|
uint32_t time,
|
|
|
|
struct weston_pointer_axis_event *event)
|
|
|
|
{
|
|
|
|
weston_pointer_send_axis(grab->pointer, time, event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
popup_grab_axis_source(struct weston_pointer_grab *grab, uint32_t source)
|
|
|
|
{
|
|
|
|
weston_pointer_send_axis_source(grab->pointer, source);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
popup_grab_frame(struct weston_pointer_grab *grab)
|
|
|
|
{
|
|
|
|
weston_pointer_send_frame(grab->pointer);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
popup_grab_cancel(struct weston_pointer_grab *grab)
|
|
|
|
{
|
|
|
|
popup_grab_end(grab->pointer);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct weston_pointer_grab_interface popup_grab_interface = {
|
|
|
|
popup_grab_focus,
|
|
|
|
popup_grab_motion,
|
|
|
|
popup_grab_button,
|
|
|
|
popup_grab_axis,
|
|
|
|
popup_grab_axis_source,
|
|
|
|
popup_grab_frame,
|
|
|
|
popup_grab_cancel,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
touch_popup_grab_down(struct weston_touch_grab *grab, uint32_t time,
|
|
|
|
int touch_id, wl_fixed_t x, wl_fixed_t y)
|
|
|
|
{
|
|
|
|
struct wl_resource *resource;
|
|
|
|
struct shell_seat *shseat =
|
|
|
|
container_of(grab, struct shell_seat, popup_grab.touch_grab);
|
|
|
|
struct wl_display *display = shseat->seat->compositor->wl_display;
|
|
|
|
uint32_t serial;
|
|
|
|
struct wl_list *resource_list;
|
|
|
|
wl_fixed_t sx, sy;
|
|
|
|
|
|
|
|
weston_view_from_global_fixed(grab->touch->focus, x, y, &sx, &sy);
|
|
|
|
|
|
|
|
resource_list = &grab->touch->focus_resource_list;
|
|
|
|
if (!wl_list_empty(resource_list)) {
|
|
|
|
serial = wl_display_get_serial(display);
|
|
|
|
wl_resource_for_each(resource, resource_list) {
|
|
|
|
wl_touch_send_down(resource, serial, time,
|
|
|
|
grab->touch->focus->surface->resource,
|
|
|
|
touch_id, sx, sy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
touch_popup_grab_up(struct weston_touch_grab *grab, uint32_t time, int touch_id)
|
|
|
|
{
|
|
|
|
struct wl_resource *resource;
|
|
|
|
struct shell_seat *shseat =
|
|
|
|
container_of(grab, struct shell_seat, popup_grab.touch_grab);
|
|
|
|
struct wl_display *display = shseat->seat->compositor->wl_display;
|
|
|
|
uint32_t serial;
|
|
|
|
struct wl_list *resource_list;
|
|
|
|
|
|
|
|
resource_list = &grab->touch->focus_resource_list;
|
|
|
|
if (!wl_list_empty(resource_list)) {
|
|
|
|
serial = wl_display_get_serial(display);
|
|
|
|
wl_resource_for_each(resource, resource_list) {
|
|
|
|
wl_touch_send_up(resource, serial, time, touch_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
touch_popup_grab_motion(struct weston_touch_grab *grab, uint32_t time,
|
|
|
|
int touch_id, wl_fixed_t x, wl_fixed_t y)
|
|
|
|
{
|
|
|
|
struct wl_resource *resource;
|
|
|
|
struct wl_list *resource_list;
|
|
|
|
wl_fixed_t sx, sy;
|
|
|
|
|
|
|
|
weston_view_from_global_fixed(grab->touch->focus, x, y, &sx, &sy);
|
|
|
|
|
|
|
|
resource_list = &grab->touch->focus_resource_list;
|
|
|
|
if (!wl_list_empty(resource_list)) {
|
|
|
|
wl_resource_for_each(resource, resource_list) {
|
|
|
|
wl_touch_send_motion(resource, time, touch_id, sx, sy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
touch_popup_grab_frame(struct weston_touch_grab *grab)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
touch_popup_grab_cancel(struct weston_touch_grab *grab)
|
|
|
|
{
|
|
|
|
touch_popup_grab_end(grab->touch);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct weston_touch_grab_interface touch_popup_grab_interface = {
|
|
|
|
touch_popup_grab_down,
|
|
|
|
touch_popup_grab_up,
|
|
|
|
touch_popup_grab_motion,
|
|
|
|
touch_popup_grab_frame,
|
|
|
|
touch_popup_grab_cancel,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_send_popup_done(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
if (shsurf->resource == NULL)
|
|
|
|
return;
|
|
|
|
else if (shell_surface_is_wl_shell_surface(shsurf))
|
|
|
|
wl_shell_surface_send_popup_done(shsurf->resource);
|
|
|
|
else if (shell_surface_is_xdg_popup(shsurf))
|
|
|
|
xdg_popup_send_popup_done(shsurf->resource);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
popup_grab_end(struct weston_pointer *pointer)
|
|
|
|
{
|
|
|
|
struct weston_pointer_grab *grab = pointer->grab;
|
|
|
|
struct shell_seat *shseat =
|
|
|
|
container_of(grab, struct shell_seat, popup_grab.grab);
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
struct shell_surface *next;
|
|
|
|
|
|
|
|
if (pointer->grab->interface == &popup_grab_interface) {
|
|
|
|
weston_pointer_end_grab(grab->pointer);
|
|
|
|
shseat->popup_grab.client = NULL;
|
|
|
|
shseat->popup_grab.grab.interface = NULL;
|
|
|
|
assert(!wl_list_empty(&shseat->popup_grab.surfaces_list));
|
|
|
|
/* Send the popup_done event to all the popups open */
|
|
|
|
wl_list_for_each_safe(shsurf, next,
|
|
|
|
&shseat->popup_grab.surfaces_list,
|
|
|
|
popup.grab_link) {
|
|
|
|
shell_surface_send_popup_done(shsurf);
|
|
|
|
shsurf->popup.shseat = NULL;
|
|
|
|
wl_list_init(&shsurf->popup.grab_link);
|
|
|
|
}
|
|
|
|
wl_list_init(&shseat->popup_grab.surfaces_list);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
touch_popup_grab_end(struct weston_touch *touch)
|
|
|
|
{
|
|
|
|
struct weston_touch_grab *grab = touch->grab;
|
|
|
|
struct shell_seat *shseat =
|
|
|
|
container_of(grab, struct shell_seat, popup_grab.touch_grab);
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
struct shell_surface *next;
|
|
|
|
|
|
|
|
if (touch->grab->interface == &touch_popup_grab_interface) {
|
|
|
|
weston_touch_end_grab(grab->touch);
|
|
|
|
shseat->popup_grab.client = NULL;
|
|
|
|
shseat->popup_grab.touch_grab.interface = NULL;
|
|
|
|
assert(!wl_list_empty(&shseat->popup_grab.surfaces_list));
|
|
|
|
/* Send the popup_done event to all the popups open */
|
|
|
|
wl_list_for_each_safe(shsurf, next,
|
|
|
|
&shseat->popup_grab.surfaces_list,
|
|
|
|
popup.grab_link) {
|
|
|
|
shell_surface_send_popup_done(shsurf);
|
|
|
|
shsurf->popup.shseat = NULL;
|
|
|
|
wl_list_init(&shsurf->popup.grab_link);
|
|
|
|
}
|
|
|
|
wl_list_init(&shseat->popup_grab.surfaces_list);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct shell_surface *
|
|
|
|
get_top_popup(struct shell_seat *shseat)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
|
|
|
|
if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
|
|
|
|
return NULL;
|
|
|
|
} else {
|
|
|
|
shsurf = container_of(shseat->popup_grab.surfaces_list.next,
|
|
|
|
struct shell_surface,
|
|
|
|
popup.grab_link);
|
|
|
|
return shsurf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
add_popup_grab(struct shell_surface *shsurf,
|
|
|
|
struct shell_seat *shseat,
|
|
|
|
int32_t type)
|
|
|
|
{
|
|
|
|
struct weston_seat *seat = shseat->seat;
|
|
|
|
struct shell_surface *parent, *top_surface;
|
|
|
|
struct weston_pointer *pointer = weston_seat_get_pointer(seat);
|
|
|
|
struct weston_touch *touch = weston_seat_get_touch(seat);
|
|
|
|
|
|
|
|
parent = get_shell_surface(shsurf->parent);
|
|
|
|
top_surface = get_top_popup(shseat);
|
|
|
|
if (shell_surface_is_xdg_popup(shsurf) &&
|
|
|
|
(!parent ||
|
|
|
|
(top_surface == NULL && !shell_surface_is_xdg_surface(parent)) ||
|
|
|
|
(top_surface != NULL && parent != top_surface))) {
|
|
|
|
wl_resource_post_error(shsurf->owner_resource,
|
|
|
|
XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP,
|
|
|
|
"xdg_popup was not created on the "
|
|
|
|
"topmost popup");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
|
|
|
|
shseat->popup_grab.type = type;
|
|
|
|
shseat->popup_grab.client =
|
|
|
|
wl_resource_get_client(shsurf->resource);
|
|
|
|
|
|
|
|
if (type == POINTER) {
|
|
|
|
shseat->popup_grab.grab.interface =
|
|
|
|
&popup_grab_interface;
|
|
|
|
|
|
|
|
/* We must make sure here that this popup was opened
|
|
|
|
* after a mouse press, and not just by moving around
|
|
|
|
* with other popups already open. */
|
|
|
|
if (pointer->button_count > 0)
|
|
|
|
shseat->popup_grab.initial_up = 0;
|
|
|
|
} else if (type == TOUCH) {
|
|
|
|
shseat->popup_grab.touch_grab.interface =
|
|
|
|
&touch_popup_grab_interface;
|
|
|
|
}
|
|
|
|
|
|
|
|
wl_list_insert(&shseat->popup_grab.surfaces_list,
|
|
|
|
&shsurf->popup.grab_link);
|
|
|
|
|
|
|
|
if (type == POINTER) {
|
|
|
|
weston_pointer_start_grab(pointer,
|
|
|
|
&shseat->popup_grab.grab);
|
|
|
|
} else if (type == TOUCH) {
|
|
|
|
weston_touch_start_grab(touch,
|
|
|
|
&shseat->popup_grab.touch_grab);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
wl_list_insert(&shseat->popup_grab.surfaces_list,
|
|
|
|
&shsurf->popup.grab_link);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
remove_popup_grab(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
struct shell_seat *shseat = shsurf->popup.shseat;
|
|
|
|
|
|
|
|
if (shell_surface_is_xdg_popup(shsurf) &&
|
|
|
|
get_top_popup(shseat) != shsurf) {
|
|
|
|
wl_resource_post_error(shsurf->owner_resource,
|
|
|
|
XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP,
|
|
|
|
"xdg_popup was destroyed while it was "
|
|
|
|
"not the topmost popup.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
wl_list_remove(&shsurf->popup.grab_link);
|
|
|
|
wl_list_init(&shsurf->popup.grab_link);
|
|
|
|
if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
|
|
|
|
if (shseat->popup_grab.type == POINTER) {
|
|
|
|
weston_pointer_end_grab(shseat->popup_grab.grab.pointer);
|
|
|
|
shseat->popup_grab.grab.interface = NULL;
|
|
|
|
} else if (shseat->popup_grab.type == TOUCH) {
|
|
|
|
weston_touch_end_grab(shseat->popup_grab.touch_grab.touch);
|
|
|
|
shseat->popup_grab.touch_grab.interface = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
shell_map_popup(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
struct shell_seat *shseat = shsurf->popup.shseat;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *parent_view = get_default_view(shsurf->parent);
|
|
|
|
struct weston_pointer *pointer = weston_seat_get_pointer(shseat->seat);
|
|
|
|
struct weston_touch *touch = weston_seat_get_touch(shseat->seat);
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
shsurf->surface->output = parent_view->output;
|
|
|
|
shsurf->view->output = parent_view->output;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_set_transform_parent(shsurf->view, parent_view);
|
|
|
|
weston_view_set_position(shsurf->view, shsurf->popup.x, shsurf->popup.y);
|
|
|
|
weston_view_update_transform(shsurf->view);
|
|
|
|
|
|
|
|
if (pointer &&
|
|
|
|
pointer->grab_serial == shsurf->popup.serial) {
|
|
|
|
if (add_popup_grab(shsurf, shseat, POINTER) != 0)
|
|
|
|
return -1;
|
|
|
|
} else if (touch &&
|
|
|
|
touch->grab_serial == shsurf->popup.serial) {
|
|
|
|
if (add_popup_grab(shsurf, shseat, TOUCH) != 0)
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
shell_surface_send_popup_done(shsurf);
|
|
|
|
shseat->popup_grab.client = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct wl_shell_surface_interface shell_surface_implementation = {
|
|
|
|
shell_surface_pong,
|
|
|
|
shell_surface_move,
|
|
|
|
shell_surface_resize,
|
|
|
|
shell_surface_set_toplevel,
|
|
|
|
shell_surface_set_transient,
|
|
|
|
shell_surface_set_fullscreen,
|
|
|
|
shell_surface_set_popup,
|
|
|
|
shell_surface_set_maximized,
|
|
|
|
shell_surface_set_title,
|
|
|
|
shell_surface_set_class
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
destroy_shell_surface(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
struct shell_surface *child, *next;
|
|
|
|
|
|
|
|
wl_signal_emit(&shsurf->destroy_signal, shsurf);
|
|
|
|
|
|
|
|
if (!wl_list_empty(&shsurf->popup.grab_link)) {
|
|
|
|
remove_popup_grab(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
|
|
|
|
shell_surface_is_top_fullscreen(shsurf))
|
|
|
|
restore_output_mode (shsurf->fullscreen_output);
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
if (shsurf->fullscreen.black_view)
|
|
|
|
weston_surface_destroy(shsurf->fullscreen.black_view->surface);
|
|
|
|
|
|
|
|
/* As destroy_resource() use wl_list_for_each_safe(),
|
|
|
|
* we can always remove the listener.
|
|
|
|
*/
|
|
|
|
wl_list_remove(&shsurf->surface_destroy_listener.link);
|
|
|
|
shsurf->surface->configure = NULL;
|
compositor: add weston_surface_set_label_func()
When printing out logs from Weston's actions, mainly for debugging, it
can be very difficult to identify the different surfaces. Inspecting
the configure function pointer is not useful, as the configure functions
may live in modules.
Add vfunc get_label to weston_surface, which will produce a short,
human-readable description of the surface, which allows identifying it
better, rather than just looking at the surface size, for instance.
Set the label function from most parts of Weston, to identify cursors and
drag icons, and panels, backgrounds, screensavers and lock surfaces, and
the desktop shell's application surfaces.
v2: renamed 'description' to 'label', so we get
weston_surface_set_label_func().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
11 years ago
|
|
|
weston_surface_set_label_func(shsurf->surface, NULL);
|
|
|
|
free(shsurf->title);
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_destroy(shsurf->view);
|
|
|
|
|
|
|
|
wl_list_remove(&shsurf->children_link);
|
|
|
|
wl_list_for_each_safe(child, next, &shsurf->children_list, children_link)
|
|
|
|
shell_surface_set_parent(child, NULL);
|
|
|
|
|
|
|
|
wl_list_remove(&shsurf->link);
|
|
|
|
free(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_destroy_shell_surface(struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
|
|
|
|
if (!wl_list_empty(&shsurf->popup.grab_link))
|
|
|
|
remove_popup_grab(shsurf);
|
|
|
|
if (shsurf->resource)
|
|
|
|
wl_list_remove(wl_resource_get_link(shsurf->resource));
|
|
|
|
shsurf->resource = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_handle_surface_destroy(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = container_of(listener,
|
|
|
|
struct shell_surface,
|
|
|
|
surface_destroy_listener);
|
|
|
|
|
|
|
|
if (shsurf->resource)
|
|
|
|
wl_resource_destroy(shsurf->resource);
|
|
|
|
|
|
|
|
destroy_shell_surface(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fade_out_done_idle_cb(void *data)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = data;
|
|
|
|
|
|
|
|
weston_surface_destroy(shsurf->surface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fade_out_done(struct weston_view_animation *animation, void *data)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = data;
|
|
|
|
struct wl_event_loop *loop;
|
|
|
|
|
|
|
|
loop = wl_display_get_event_loop(
|
|
|
|
shsurf->surface->compositor->wl_display);
|
|
|
|
|
|
|
|
if (!shsurf->destroying) {
|
|
|
|
wl_event_loop_add_idle(loop, fade_out_done_idle_cb, shsurf);
|
|
|
|
shsurf->destroying = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_resource_destroy(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf =
|
|
|
|
container_of(listener, struct shell_surface,
|
|
|
|
resource_destroy_listener);
|
|
|
|
|
|
|
|
if (!weston_surface_is_mapped(shsurf->surface))
|
|
|
|
return;
|
|
|
|
|
|
|
|
shsurf->surface->ref_count++;
|
|
|
|
|
|
|
|
pixman_region32_fini(&shsurf->surface->pending.input);
|
|
|
|
pixman_region32_init(&shsurf->surface->pending.input);
|
|
|
|
pixman_region32_fini(&shsurf->surface->input);
|
|
|
|
pixman_region32_init(&shsurf->surface->input);
|
|
|
|
if (shsurf->shell->win_close_animation_type == ANIMATION_FADE) {
|
|
|
|
weston_fade_run(shsurf->view, 1.0, 0.0, 300.0,
|
|
|
|
fade_out_done, shsurf);
|
|
|
|
} else {
|
|
|
|
weston_surface_destroy(shsurf->surface);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_configure(struct weston_surface *, int32_t, int32_t);
|
|
|
|
|
|
|
|
struct shell_surface *
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
13 years ago
|
|
|
get_shell_surface(struct weston_surface *surface)
|
|
|
|
{
|
|
|
|
if (surface->configure == shell_surface_configure)
|
|
|
|
return surface->configure_private;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct shell_surface *
|
|
|
|
create_common_surface(struct shell_client *owner, void *shell,
|
|
|
|
struct weston_surface *surface,
|
|
|
|
const struct weston_shell_client *client)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
|
compositor: send error for surface role resets
With the more accurate definition of wl_surface roles in Wayland,
enforce the restriction: a role is always set permanently, and
attempting to change it is a protocol error.
This patch is based on Jasper's patch:
http://lists.freedesktop.org/archives/wayland-devel/2014-August/016811.html
The difference in this patch compared to his are:
- send role errors on the interface whose request triggers it, not on
wl_surface
- an interface could have several requests assigning different roles,
cannot use wl_interface as the unique key; use an arbitary string
instead
- ensure in window-manager.c that create_shell_surface() ->
create_common_surface() is never called with surface->configure set,
to avoid compositor abort
- use wl_resource_post_no_memory() where appropriate instead of
hand-rolling it with wl_resource_post_error()
Ideally we would not add weston_surface::role_name field, but use
weston_surface::configure. At the moment this is not possible though,
because at least shell.c uses several different roles with the same
configure function. Drag'n'drop uses two configure functions for the
same role. The configure hook is also reset in several places,
which is not good for role tracking.
This patch overlooks the wl_surface roles assigned in privileged
extensions: screensaver, panel, background, lock, input panel.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
10 years ago
|
|
|
assert(surface->configure == NULL);
|
|
|
|
|
|
|
|
shsurf = calloc(1, sizeof *shsurf);
|
|
|
|
if (!shsurf) {
|
|
|
|
weston_log("no memory to allocate shell surface\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
shsurf->view = weston_view_create(surface);
|
|
|
|
if (!shsurf->view) {
|
|
|
|
weston_log("no memory to allocate shell surface\n");
|
|
|
|
free(shsurf);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
surface->configure = shell_surface_configure;
|
|
|
|
surface->configure_private = shsurf;
|
compositor: add weston_surface_set_label_func()
When printing out logs from Weston's actions, mainly for debugging, it
can be very difficult to identify the different surfaces. Inspecting
the configure function pointer is not useful, as the configure functions
may live in modules.
Add vfunc get_label to weston_surface, which will produce a short,
human-readable description of the surface, which allows identifying it
better, rather than just looking at the surface size, for instance.
Set the label function from most parts of Weston, to identify cursors and
drag icons, and panels, backgrounds, screensavers and lock surfaces, and
the desktop shell's application surfaces.
v2: renamed 'description' to 'label', so we get
weston_surface_set_label_func().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
11 years ago
|
|
|
weston_surface_set_label_func(surface, shell_surface_get_label);
|
|
|
|
|
|
|
|
shsurf->resource_destroy_listener.notify = handle_resource_destroy;
|
|
|
|
wl_resource_add_destroy_listener(surface->resource,
|
|
|
|
&shsurf->resource_destroy_listener);
|
|
|
|
shsurf->owner = owner;
|
|
|
|
|
|
|
|
shsurf->shell = (struct desktop_shell *) shell;
|
|
|
|
shsurf->unresponsive = 0;
|
|
|
|
shsurf->saved_position_valid = false;
|
|
|
|
shsurf->saved_rotation_valid = false;
|
|
|
|
shsurf->surface = surface;
|
|
|
|
shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
|
|
|
|
shsurf->fullscreen.framerate = 0;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
shsurf->fullscreen.black_view = NULL;
|
|
|
|
wl_list_init(&shsurf->fullscreen.transform.link);
|
|
|
|
|
|
|
|
shsurf->output = get_default_output(shsurf->shell->compositor);
|
|
|
|
|
|
|
|
wl_signal_init(&shsurf->destroy_signal);
|
|
|
|
shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
|
|
|
|
wl_signal_add(&surface->destroy_signal,
|
|
|
|
&shsurf->surface_destroy_listener);
|
|
|
|
|
|
|
|
/* init link so its safe to always remove it in destroy_shell_surface */
|
|
|
|
wl_list_init(&shsurf->link);
|
|
|
|
wl_list_init(&shsurf->popup.grab_link);
|
|
|
|
|
|
|
|
/* empty when not in use */
|
|
|
|
wl_list_init(&shsurf->rotation.transform.link);
|
|
|
|
weston_matrix_init(&shsurf->rotation.rotation);
|
|
|
|
|
|
|
|
wl_list_init(&shsurf->workspace_transform.link);
|
|
|
|
|
|
|
|
wl_list_init(&shsurf->children_link);
|
|
|
|
wl_list_init(&shsurf->children_list);
|
|
|
|
shsurf->parent = NULL;
|
|
|
|
|
compositor: Implement JSON-timeline logging
Logging is activated and deactivated with the debug key binding 't'.
When activated, it creates a new log file, where it records the events.
The log file contains events and detailed object information entries in
JSON format, and is meant to be parsed in sequence from beginning to the
end.
The emitted events are mostly related to the output repaint cycle, like
when repaint begins, is submitted to GPU, and when it completes on a
vblank. This is recorded per-output. Also some per-surface events are
recorded, including when surface damage is flushed.
To reduce the log size, events refer to objects like outputs and
surfaces by id numbers. Detailed object information is emitted only as
needed: on the first object occurrence, and afterwards only if
weston_timeline_object::force_refresh asks for it.
The detailed information for surfaces includes the string returned by
weston_surface::get_label. Therefore it is important to set
weston_timeline_object::force_refresh = 1 whenever the string would
change, so that the new details get recorded.
A rudimentary parser and SVG generator can be found at:
https://github.com/ppaalanen/wesgr
The timeline logs can answer questions including:
- How does the compositor repaint cycle work timing-wise?
- When was the vblank deadline missed?
- What is the latency from surface commit to showing the new content on
screen?
- How long does it take to process the scenegraph?
v2: weston_surface::get_description renamed to get_label.
v3: reafctor a bit into fprint_quoted_string().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
10 years ago
|
|
|
set_type(shsurf, SHELL_SURFACE_NONE);
|
|
|
|
|
|
|
|
shsurf->client = client;
|
|
|
|
|
|
|
|
return shsurf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct shell_surface *
|
|
|
|
create_shell_surface(void *shell, struct weston_surface *surface,
|
|
|
|
const struct weston_shell_client *client)
|
|
|
|
{
|
|
|
|
return create_common_surface(NULL, shell, surface, client);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_get_shell_surface(struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t id,
|
|
|
|
struct wl_resource *surface_resource)
|
|
|
|
{
|
|
|
|
struct weston_surface *surface =
|
|
|
|
wl_resource_get_user_data(surface_resource);
|
|
|
|
struct shell_client *sc = wl_resource_get_user_data(resource);
|
|
|
|
struct desktop_shell *shell = sc->shell;
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
|
compositor: send error for surface role resets
With the more accurate definition of wl_surface roles in Wayland,
enforce the restriction: a role is always set permanently, and
attempting to change it is a protocol error.
This patch is based on Jasper's patch:
http://lists.freedesktop.org/archives/wayland-devel/2014-August/016811.html
The difference in this patch compared to his are:
- send role errors on the interface whose request triggers it, not on
wl_surface
- an interface could have several requests assigning different roles,
cannot use wl_interface as the unique key; use an arbitary string
instead
- ensure in window-manager.c that create_shell_surface() ->
create_common_surface() is never called with surface->configure set,
to avoid compositor abort
- use wl_resource_post_no_memory() where appropriate instead of
hand-rolling it with wl_resource_post_error()
Ideally we would not add weston_surface::role_name field, but use
weston_surface::configure. At the moment this is not possible though,
because at least shell.c uses several different roles with the same
configure function. Drag'n'drop uses two configure functions for the
same role. The configure hook is also reset in several places,
which is not good for role tracking.
This patch overlooks the wl_surface roles assigned in privileged
extensions: screensaver, panel, background, lock, input panel.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
10 years ago
|
|
|
if (weston_surface_set_role(surface, "wl_shell_surface",
|
|
|
|
resource, WL_SHELL_ERROR_ROLE) < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
shsurf = create_common_surface(sc, shell, surface, &shell_client);
|
|
|
|
if (!shsurf) {
|
compositor: send error for surface role resets
With the more accurate definition of wl_surface roles in Wayland,
enforce the restriction: a role is always set permanently, and
attempting to change it is a protocol error.
This patch is based on Jasper's patch:
http://lists.freedesktop.org/archives/wayland-devel/2014-August/016811.html
The difference in this patch compared to his are:
- send role errors on the interface whose request triggers it, not on
wl_surface
- an interface could have several requests assigning different roles,
cannot use wl_interface as the unique key; use an arbitary string
instead
- ensure in window-manager.c that create_shell_surface() ->
create_common_surface() is never called with surface->configure set,
to avoid compositor abort
- use wl_resource_post_no_memory() where appropriate instead of
hand-rolling it with wl_resource_post_error()
Ideally we would not add weston_surface::role_name field, but use
weston_surface::configure. At the moment this is not possible though,
because at least shell.c uses several different roles with the same
configure function. Drag'n'drop uses two configure functions for the
same role. The configure hook is also reset in several places,
which is not good for role tracking.
This patch overlooks the wl_surface roles assigned in privileged
extensions: screensaver, panel, background, lock, input panel.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
10 years ago
|
|
|
wl_resource_post_no_memory(surface_resource);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
shsurf->resource =
|
|
|
|
wl_resource_create(client,
|
|
|
|
&wl_shell_surface_interface, 1, id);
|
|
|
|
if (!shsurf->resource) {
|
|
|
|
wl_resource_post_no_memory(surface_resource);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
wl_resource_set_implementation(shsurf->resource,
|
|
|
|
&shell_surface_implementation,
|
|
|
|
shsurf, shell_destroy_shell_surface);
|
|
|
|
wl_list_insert(&sc->surface_list,
|
|
|
|
wl_resource_get_link(shsurf->resource));
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
shell_surface_is_wl_shell_surface(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
/* A shell surface without a resource is created from xwayland
|
|
|
|
* and is considered a wl_shell surface for now. */
|
|
|
|
|
|
|
|
return shsurf->resource == NULL ||
|
|
|
|
wl_resource_instance_of(shsurf->resource,
|
|
|
|
&wl_shell_surface_interface,
|
|
|
|
&shell_surface_implementation);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct wl_shell_interface shell_implementation = {
|
|
|
|
shell_get_shell_surface
|
|
|
|
};
|
|
|
|
|
|
|
|
/****************************
|
|
|
|
* xdg-shell implementation */
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_destroy(struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
wl_resource_destroy(resource);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_set_parent(struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
struct wl_resource *parent_resource)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
struct shell_surface *parent;
|
|
|
|
|
|
|
|
if (parent_resource) {
|
|
|
|
parent = wl_resource_get_user_data(parent_resource);
|
|
|
|
shell_surface_set_parent(shsurf, parent->surface);
|
|
|
|
} else {
|
|
|
|
shell_surface_set_parent(shsurf, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_set_app_id(struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
const char *app_id)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
|
|
|
|
free(shsurf->class);
|
|
|
|
shsurf->class = strdup(app_id);
|
compositor: Implement JSON-timeline logging
Logging is activated and deactivated with the debug key binding 't'.
When activated, it creates a new log file, where it records the events.
The log file contains events and detailed object information entries in
JSON format, and is meant to be parsed in sequence from beginning to the
end.
The emitted events are mostly related to the output repaint cycle, like
when repaint begins, is submitted to GPU, and when it completes on a
vblank. This is recorded per-output. Also some per-surface events are
recorded, including when surface damage is flushed.
To reduce the log size, events refer to objects like outputs and
surfaces by id numbers. Detailed object information is emitted only as
needed: on the first object occurrence, and afterwards only if
weston_timeline_object::force_refresh asks for it.
The detailed information for surfaces includes the string returned by
weston_surface::get_label. Therefore it is important to set
weston_timeline_object::force_refresh = 1 whenever the string would
change, so that the new details get recorded.
A rudimentary parser and SVG generator can be found at:
https://github.com/ppaalanen/wesgr
The timeline logs can answer questions including:
- How does the compositor repaint cycle work timing-wise?
- When was the vblank deadline missed?
- What is the latency from surface commit to showing the new content on
screen?
- How long does it take to process the scenegraph?
v2: weston_surface::get_description renamed to get_label.
v3: reafctor a bit into fprint_quoted_string().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
10 years ago
|
|
|
shsurf->surface->timeline.force_refresh = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_show_window_menu(struct wl_client *client,
|
|
|
|
struct wl_resource *surface_resource,
|
|
|
|
struct wl_resource *seat_resource,
|
|
|
|
uint32_t serial,
|
|
|
|
int32_t x,
|
|
|
|
int32_t y)
|
|
|
|
{
|
|
|
|
/* TODO */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_set_title(struct wl_client *client,
|
|
|
|
struct wl_resource *resource, const char *title)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
|
|
|
|
set_title(shsurf, title);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_move(struct wl_client *client, struct wl_resource *resource,
|
|
|
|
struct wl_resource *seat_resource, uint32_t serial)
|
|
|
|
{
|
|
|
|
common_surface_move(resource, seat_resource, serial);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_resize(struct wl_client *client, struct wl_resource *resource,
|
|
|
|
struct wl_resource *seat_resource, uint32_t serial,
|
|
|
|
uint32_t edges)
|
|
|
|
{
|
|
|
|
common_surface_resize(resource, seat_resource, serial, edges);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_ack_configure(struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t serial)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
|
|
|
|
if (shsurf->state_requested) {
|
|
|
|
shsurf->next_state = shsurf->requested_state;
|
|
|
|
shsurf->state_changed = true;
|
|
|
|
shsurf->state_requested = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
shell: Replace set_margin with set_window_geometry
Currently, there is a fun flicker when toggling maximization or
fullscreen on a window in mutter or more sophisicated compositors
and WMs.
What happens is that the client want so go maximized, so we
calculate the size that we want the window to resize to (640x480),
and then add on its margins to find the buffer size (+10 = 660x500),
and then send out a configure event for that size. The client
renders to that size, realizes that it's maximized, and then
says "oh hey, my margins are actually 0 now!", and so the compositor
has to send out another configure event.
In order to fix this, make the the configure request correspond to
the window geometry we'd like the window to be at. At the same time,
replace set_margin with set_window_geometry, where we specify a rect
rather than a border around the window.
11 years ago
|
|
|
static void
|
|
|
|
xdg_surface_set_window_geometry(struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
int32_t x,
|
|
|
|
int32_t y,
|
|
|
|
int32_t width,
|
|
|
|
int32_t height)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
|
|
|
|
set_window_geometry(shsurf, x, y, width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_set_maximized(struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
struct weston_output *output;
|
|
|
|
|
|
|
|
shsurf->state_requested = true;
|
|
|
|
shsurf->requested_state.maximized = true;
|
|
|
|
|
|
|
|
if (!weston_surface_is_mapped(shsurf->surface))
|
|
|
|
output = get_focused_output(shsurf->surface->compositor);
|
|
|
|
else
|
|
|
|
output = shsurf->surface->output;
|
|
|
|
|
|
|
|
shell_surface_set_output(shsurf, output);
|
|
|
|
send_configure_for_surface(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_unset_maximized(struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
|
|
|
|
shsurf->state_requested = true;
|
|
|
|
shsurf->requested_state.maximized = false;
|
shell: Centralize management of sending configure requests
Currently, there's a giant bug in how xdg-shell state management
is done. If a client calls set_fullscreen and then set_maximized,
it will get two configure events:
=> set_fullscreen
<= configure(800, 600, [STATE_FULLSCREEN])
=> set_maximized
<= configure(800, 560, [STATE_FULLSCREEN, STATE_MAXIMIZED])
Since fullscreen takes precedence over maximized, the client will
render full-screen at 800x600 first, and then 800x560 next. As
a result, the surface gets the wrong size.
This is because the code that sends out configure requests is
"immediate" -- when an app calls set_maximized, we immediately
send out the configure event that would have happened if we
transitioned immediately into maximized mode.
In wl_shell, this is correct behavior. However, in xdg-shell,
this is wrong. State needs to be more carefully managed in
xdg-shell, as states aren't exclusive.
Pull all the code that sends out configure events out and send
them centrally, based on Weston's on surface state management.
This should work with both wl_shell and xdg_shell's strategies.
11 years ago
|
|
|
send_configure_for_surface(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_set_fullscreen(struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
struct wl_resource *output_resource)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
struct weston_output *output;
|
|
|
|
|
|
|
|
shsurf->state_requested = true;
|
|
|
|
shsurf->requested_state.fullscreen = true;
|
|
|
|
|
|
|
|
if (output_resource)
|
|
|
|
output = wl_resource_get_user_data(output_resource);
|
|
|
|
else
|
|
|
|
output = NULL;
|
|
|
|
|
|
|
|
/* handle clients launching in fullscreen */
|
|
|
|
if (output == NULL && !weston_surface_is_mapped(shsurf->surface)) {
|
|
|
|
/* Set the output to the one that has focus currently. */
|
|
|
|
assert(shsurf->surface);
|
|
|
|
output = get_focused_output(shsurf->surface->compositor);
|
|
|
|
}
|
|
|
|
|
|
|
|
shell_surface_set_output(shsurf, output);
|
|
|
|
shsurf->fullscreen_output = shsurf->output;
|
|
|
|
|
|
|
|
send_configure_for_surface(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_unset_fullscreen(struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
|
|
|
|
shsurf->state_requested = true;
|
|
|
|
shsurf->requested_state.fullscreen = false;
|
shell: Centralize management of sending configure requests
Currently, there's a giant bug in how xdg-shell state management
is done. If a client calls set_fullscreen and then set_maximized,
it will get two configure events:
=> set_fullscreen
<= configure(800, 600, [STATE_FULLSCREEN])
=> set_maximized
<= configure(800, 560, [STATE_FULLSCREEN, STATE_MAXIMIZED])
Since fullscreen takes precedence over maximized, the client will
render full-screen at 800x600 first, and then 800x560 next. As
a result, the surface gets the wrong size.
This is because the code that sends out configure requests is
"immediate" -- when an app calls set_maximized, we immediately
send out the configure event that would have happened if we
transitioned immediately into maximized mode.
In wl_shell, this is correct behavior. However, in xdg-shell,
this is wrong. State needs to be more carefully managed in
xdg-shell, as states aren't exclusive.
Pull all the code that sends out configure events out and send
them centrally, based on Weston's on surface state management.
This should work with both wl_shell and xdg_shell's strategies.
11 years ago
|
|
|
send_configure_for_surface(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_set_minimized(struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
|
|
|
|
|
|
|
|
if (shsurf->type != SHELL_SURFACE_TOPLEVEL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* apply compositor's own minimization logic (hide) */
|
|
|
|
set_minimized(shsurf->surface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct xdg_surface_interface xdg_surface_implementation = {
|
|
|
|
xdg_surface_destroy,
|
|
|
|
xdg_surface_set_parent,
|
|
|
|
xdg_surface_set_title,
|
|
|
|
xdg_surface_set_app_id,
|
|
|
|
xdg_surface_show_window_menu,
|
|
|
|
xdg_surface_move,
|
|
|
|
xdg_surface_resize,
|
|
|
|
xdg_surface_ack_configure,
|
shell: Replace set_margin with set_window_geometry
Currently, there is a fun flicker when toggling maximization or
fullscreen on a window in mutter or more sophisicated compositors
and WMs.
What happens is that the client want so go maximized, so we
calculate the size that we want the window to resize to (640x480),
and then add on its margins to find the buffer size (+10 = 660x500),
and then send out a configure event for that size. The client
renders to that size, realizes that it's maximized, and then
says "oh hey, my margins are actually 0 now!", and so the compositor
has to send out another configure event.
In order to fix this, make the the configure request correspond to
the window geometry we'd like the window to be at. At the same time,
replace set_margin with set_window_geometry, where we specify a rect
rather than a border around the window.
11 years ago
|
|
|
xdg_surface_set_window_geometry,
|
|
|
|
xdg_surface_set_maximized,
|
|
|
|
xdg_surface_unset_maximized,
|
|
|
|
xdg_surface_set_fullscreen,
|
|
|
|
xdg_surface_unset_fullscreen,
|
|
|
|
xdg_surface_set_minimized,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_send_configure(struct weston_surface *surface,
|
|
|
|
int32_t width, int32_t height)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = get_shell_surface(surface);
|
|
|
|
uint32_t *s;
|
|
|
|
struct wl_array states;
|
|
|
|
uint32_t serial;
|
|
|
|
|
|
|
|
assert(shsurf);
|
|
|
|
|
|
|
|
if (!shsurf->resource)
|
|
|
|
return;
|
|
|
|
|
|
|
|
wl_array_init(&states);
|
|
|
|
if (shsurf->requested_state.fullscreen) {
|
|
|
|
s = wl_array_add(&states, sizeof *s);
|
|
|
|
*s = XDG_SURFACE_STATE_FULLSCREEN;
|
|
|
|
} else if (shsurf->requested_state.maximized) {
|
|
|
|
s = wl_array_add(&states, sizeof *s);
|
|
|
|
*s = XDG_SURFACE_STATE_MAXIMIZED;
|
|
|
|
}
|
|
|
|
if (shsurf->resize_edges != 0) {
|
|
|
|
s = wl_array_add(&states, sizeof *s);
|
|
|
|
*s = XDG_SURFACE_STATE_RESIZING;
|
|
|
|
}
|
|
|
|
if (shsurf->focus_count > 0) {
|
|
|
|
s = wl_array_add(&states, sizeof *s);
|
|
|
|
*s = XDG_SURFACE_STATE_ACTIVATED;
|
|
|
|
}
|
|
|
|
|
|
|
|
serial = wl_display_next_serial(shsurf->surface->compositor->wl_display);
|
|
|
|
xdg_surface_send_configure(shsurf->resource, width, height, &states, serial);
|
|
|
|
|
|
|
|
wl_array_release(&states);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct weston_shell_client xdg_client = {
|
|
|
|
xdg_send_configure,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_shell_destroy(struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
struct shell_client *sc = wl_resource_get_user_data(resource);
|
|
|
|
struct wl_resource *shsurf_resource;
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
|
|
|
|
wl_resource_for_each(shsurf_resource, &sc->surface_list) {
|
|
|
|
shsurf = wl_resource_get_user_data(shsurf_resource);
|
|
|
|
if (shsurf->owner_resource == resource) {
|
|
|
|
wl_resource_post_error(
|
|
|
|
resource,
|
|
|
|
XDG_SHELL_ERROR_DEFUNCT_SURFACES,
|
|
|
|
"not all child surface objects destroyed");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
wl_resource_destroy(resource);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_use_unstable_version(struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
int32_t version)
|
|
|
|
{
|
|
|
|
if (version > 1) {
|
|
|
|
wl_resource_post_error(resource,
|
|
|
|
1,
|
|
|
|
"xdg-shell:: version not implemented yet.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct shell_surface *
|
|
|
|
create_xdg_surface(struct shell_client *owner, void *shell,
|
|
|
|
struct weston_surface *surface,
|
|
|
|
const struct weston_shell_client *client)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
|
|
|
|
shsurf = create_common_surface(owner, shell, surface, client);
|
|
|
|
if (!shsurf)
|
|
|
|
return NULL;
|
|
|
|
|
compositor: Implement JSON-timeline logging
Logging is activated and deactivated with the debug key binding 't'.
When activated, it creates a new log file, where it records the events.
The log file contains events and detailed object information entries in
JSON format, and is meant to be parsed in sequence from beginning to the
end.
The emitted events are mostly related to the output repaint cycle, like
when repaint begins, is submitted to GPU, and when it completes on a
vblank. This is recorded per-output. Also some per-surface events are
recorded, including when surface damage is flushed.
To reduce the log size, events refer to objects like outputs and
surfaces by id numbers. Detailed object information is emitted only as
needed: on the first object occurrence, and afterwards only if
weston_timeline_object::force_refresh asks for it.
The detailed information for surfaces includes the string returned by
weston_surface::get_label. Therefore it is important to set
weston_timeline_object::force_refresh = 1 whenever the string would
change, so that the new details get recorded.
A rudimentary parser and SVG generator can be found at:
https://github.com/ppaalanen/wesgr
The timeline logs can answer questions including:
- How does the compositor repaint cycle work timing-wise?
- When was the vblank deadline missed?
- What is the latency from surface commit to showing the new content on
screen?
- How long does it take to process the scenegraph?
v2: weston_surface::get_description renamed to get_label.
v3: reafctor a bit into fprint_quoted_string().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
10 years ago
|
|
|
set_type(shsurf, SHELL_SURFACE_TOPLEVEL);
|
|
|
|
|
|
|
|
return shsurf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_get_xdg_surface(struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t id,
|
|
|
|
struct wl_resource *surface_resource)
|
|
|
|
{
|
|
|
|
struct weston_surface *surface =
|
|
|
|
wl_resource_get_user_data(surface_resource);
|
|
|
|
struct shell_client *sc = wl_resource_get_user_data(resource);
|
|
|
|
struct desktop_shell *shell = sc->shell;
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
|
|
|
|
shsurf = get_shell_surface(surface);
|
|
|
|
if (shsurf && shell_surface_is_xdg_surface(shsurf)) {
|
|
|
|
wl_resource_post_error(resource, XDG_SHELL_ERROR_ROLE,
|
|
|
|
"This wl_surface is already an "
|
|
|
|
"xdg_surface");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
compositor: send error for surface role resets
With the more accurate definition of wl_surface roles in Wayland,
enforce the restriction: a role is always set permanently, and
attempting to change it is a protocol error.
This patch is based on Jasper's patch:
http://lists.freedesktop.org/archives/wayland-devel/2014-August/016811.html
The difference in this patch compared to his are:
- send role errors on the interface whose request triggers it, not on
wl_surface
- an interface could have several requests assigning different roles,
cannot use wl_interface as the unique key; use an arbitary string
instead
- ensure in window-manager.c that create_shell_surface() ->
create_common_surface() is never called with surface->configure set,
to avoid compositor abort
- use wl_resource_post_no_memory() where appropriate instead of
hand-rolling it with wl_resource_post_error()
Ideally we would not add weston_surface::role_name field, but use
weston_surface::configure. At the moment this is not possible though,
because at least shell.c uses several different roles with the same
configure function. Drag'n'drop uses two configure functions for the
same role. The configure hook is also reset in several places,
which is not good for role tracking.
This patch overlooks the wl_surface roles assigned in privileged
extensions: screensaver, panel, background, lock, input panel.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
10 years ago
|
|
|
if (weston_surface_set_role(surface, "xdg_surface",
|
|
|
|
resource, XDG_SHELL_ERROR_ROLE) < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
shsurf = create_xdg_surface(sc, shell, surface, &xdg_client);
|
|
|
|
if (!shsurf) {
|
compositor: send error for surface role resets
With the more accurate definition of wl_surface roles in Wayland,
enforce the restriction: a role is always set permanently, and
attempting to change it is a protocol error.
This patch is based on Jasper's patch:
http://lists.freedesktop.org/archives/wayland-devel/2014-August/016811.html
The difference in this patch compared to his are:
- send role errors on the interface whose request triggers it, not on
wl_surface
- an interface could have several requests assigning different roles,
cannot use wl_interface as the unique key; use an arbitary string
instead
- ensure in window-manager.c that create_shell_surface() ->
create_common_surface() is never called with surface->configure set,
to avoid compositor abort
- use wl_resource_post_no_memory() where appropriate instead of
hand-rolling it with wl_resource_post_error()
Ideally we would not add weston_surface::role_name field, but use
weston_surface::configure. At the moment this is not possible though,
because at least shell.c uses several different roles with the same
configure function. Drag'n'drop uses two configure functions for the
same role. The configure hook is also reset in several places,
which is not good for role tracking.
This patch overlooks the wl_surface roles assigned in privileged
extensions: screensaver, panel, background, lock, input panel.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
10 years ago
|
|
|
wl_resource_post_no_memory(surface_resource);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
shsurf->resource =
|
|
|
|
wl_resource_create(client,
|
|
|
|
&xdg_surface_interface, 1, id);
|
|
|
|
if (!shsurf->resource) {
|
|
|
|
wl_resource_post_no_memory(surface_resource);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
wl_resource_set_implementation(shsurf->resource,
|
|
|
|
&xdg_surface_implementation,
|
|
|
|
shsurf, shell_destroy_shell_surface);
|
|
|
|
shsurf->owner_resource = resource;
|
|
|
|
wl_list_insert(&sc->surface_list,
|
|
|
|
wl_resource_get_link(shsurf->resource));
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
shell_surface_is_xdg_surface(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
return shsurf->resource &&
|
|
|
|
wl_resource_instance_of(shsurf->resource,
|
|
|
|
&xdg_surface_interface,
|
|
|
|
&xdg_surface_implementation);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* xdg-popup implementation */
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_popup_destroy(struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
wl_resource_destroy(resource);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct xdg_popup_interface xdg_popup_implementation = {
|
|
|
|
xdg_popup_destroy,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_popup_send_configure(struct weston_surface *surface,
|
|
|
|
int32_t width, int32_t height)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct weston_shell_client xdg_popup_client = {
|
|
|
|
xdg_popup_send_configure,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct shell_surface *
|
|
|
|
create_xdg_popup(struct shell_client *owner, void *shell,
|
|
|
|
struct weston_surface *surface,
|
|
|
|
const struct weston_shell_client *client,
|
|
|
|
struct weston_surface *parent,
|
|
|
|
struct shell_seat *seat,
|
|
|
|
uint32_t serial,
|
|
|
|
int32_t x, int32_t y)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
|
|
|
|
shsurf = create_common_surface(owner, shell, surface, client);
|
|
|
|
if (!shsurf)
|
|
|
|
return NULL;
|
|
|
|
|
compositor: Implement JSON-timeline logging
Logging is activated and deactivated with the debug key binding 't'.
When activated, it creates a new log file, where it records the events.
The log file contains events and detailed object information entries in
JSON format, and is meant to be parsed in sequence from beginning to the
end.
The emitted events are mostly related to the output repaint cycle, like
when repaint begins, is submitted to GPU, and when it completes on a
vblank. This is recorded per-output. Also some per-surface events are
recorded, including when surface damage is flushed.
To reduce the log size, events refer to objects like outputs and
surfaces by id numbers. Detailed object information is emitted only as
needed: on the first object occurrence, and afterwards only if
weston_timeline_object::force_refresh asks for it.
The detailed information for surfaces includes the string returned by
weston_surface::get_label. Therefore it is important to set
weston_timeline_object::force_refresh = 1 whenever the string would
change, so that the new details get recorded.
A rudimentary parser and SVG generator can be found at:
https://github.com/ppaalanen/wesgr
The timeline logs can answer questions including:
- How does the compositor repaint cycle work timing-wise?
- When was the vblank deadline missed?
- What is the latency from surface commit to showing the new content on
screen?
- How long does it take to process the scenegraph?
v2: weston_surface::get_description renamed to get_label.
v3: reafctor a bit into fprint_quoted_string().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
10 years ago
|
|
|
set_type(shsurf, SHELL_SURFACE_POPUP);
|
|
|
|
shsurf->popup.shseat = seat;
|
|
|
|
shsurf->popup.serial = serial;
|
|
|
|
shsurf->popup.x = x;
|
|
|
|
shsurf->popup.y = y;
|
|
|
|
shell_surface_set_parent(shsurf, parent);
|
|
|
|
|
|
|
|
return shsurf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_get_xdg_popup(struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t id,
|
|
|
|
struct wl_resource *surface_resource,
|
|
|
|
struct wl_resource *parent_resource,
|
|
|
|
struct wl_resource *seat_resource,
|
|
|
|
uint32_t serial,
|
|
|
|
int32_t x, int32_t y)
|
|
|
|
{
|
|
|
|
struct weston_surface *surface =
|
|
|
|
wl_resource_get_user_data(surface_resource);
|
|
|
|
struct shell_client *sc = wl_resource_get_user_data(resource);
|
|
|
|
struct desktop_shell *shell = sc->shell;
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
struct shell_surface *parent_shsurf;
|
|
|
|
struct weston_surface *parent;
|
|
|
|
struct shell_seat *seat;
|
|
|
|
|
|
|
|
shsurf = get_shell_surface(surface);
|
|
|
|
if (shsurf && shell_surface_is_xdg_popup(shsurf)) {
|
|
|
|
wl_resource_post_error(resource, XDG_SHELL_ERROR_ROLE,
|
|
|
|
"This wl_surface is already an "
|
|
|
|
"xdg_popup");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
compositor: send error for surface role resets
With the more accurate definition of wl_surface roles in Wayland,
enforce the restriction: a role is always set permanently, and
attempting to change it is a protocol error.
This patch is based on Jasper's patch:
http://lists.freedesktop.org/archives/wayland-devel/2014-August/016811.html
The difference in this patch compared to his are:
- send role errors on the interface whose request triggers it, not on
wl_surface
- an interface could have several requests assigning different roles,
cannot use wl_interface as the unique key; use an arbitary string
instead
- ensure in window-manager.c that create_shell_surface() ->
create_common_surface() is never called with surface->configure set,
to avoid compositor abort
- use wl_resource_post_no_memory() where appropriate instead of
hand-rolling it with wl_resource_post_error()
Ideally we would not add weston_surface::role_name field, but use
weston_surface::configure. At the moment this is not possible though,
because at least shell.c uses several different roles with the same
configure function. Drag'n'drop uses two configure functions for the
same role. The configure hook is also reset in several places,
which is not good for role tracking.
This patch overlooks the wl_surface roles assigned in privileged
extensions: screensaver, panel, background, lock, input panel.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
10 years ago
|
|
|
if (weston_surface_set_role(surface, "xdg_popup",
|
|
|
|
resource, XDG_SHELL_ERROR_ROLE) < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!parent_resource) {
|
|
|
|
wl_resource_post_error(surface_resource,
|
|
|
|
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
|
|
|
"xdg_shell::get_xdg_popup requires a parent shell surface");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
parent = wl_resource_get_user_data(parent_resource);
|
|
|
|
seat = get_shell_seat(wl_resource_get_user_data(seat_resource));
|
|
|
|
|
|
|
|
/* Verify that we are creating the top most popup when mapping,
|
|
|
|
* as it's not until then we know whether it was mapped as most
|
|
|
|
* top level or not. */
|
|
|
|
|
|
|
|
parent_shsurf = get_shell_surface(parent);
|
|
|
|
if (!parent_shsurf ||
|
|
|
|
(!shell_surface_is_xdg_popup(parent_shsurf) &&
|
|
|
|
!shell_surface_is_xdg_surface(parent_shsurf))) {
|
|
|
|
wl_resource_post_error(resource,
|
|
|
|
XDG_SHELL_ERROR_INVALID_POPUP_PARENT,
|
|
|
|
"xdg_popup parent was invalid");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
shsurf = create_xdg_popup(sc, shell, surface, &xdg_popup_client,
|
|
|
|
parent, seat, serial, x, y);
|
|
|
|
if (!shsurf) {
|
compositor: send error for surface role resets
With the more accurate definition of wl_surface roles in Wayland,
enforce the restriction: a role is always set permanently, and
attempting to change it is a protocol error.
This patch is based on Jasper's patch:
http://lists.freedesktop.org/archives/wayland-devel/2014-August/016811.html
The difference in this patch compared to his are:
- send role errors on the interface whose request triggers it, not on
wl_surface
- an interface could have several requests assigning different roles,
cannot use wl_interface as the unique key; use an arbitary string
instead
- ensure in window-manager.c that create_shell_surface() ->
create_common_surface() is never called with surface->configure set,
to avoid compositor abort
- use wl_resource_post_no_memory() where appropriate instead of
hand-rolling it with wl_resource_post_error()
Ideally we would not add weston_surface::role_name field, but use
weston_surface::configure. At the moment this is not possible though,
because at least shell.c uses several different roles with the same
configure function. Drag'n'drop uses two configure functions for the
same role. The configure hook is also reset in several places,
which is not good for role tracking.
This patch overlooks the wl_surface roles assigned in privileged
extensions: screensaver, panel, background, lock, input panel.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
10 years ago
|
|
|
wl_resource_post_no_memory(surface_resource);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
shsurf->resource =
|
|
|
|
wl_resource_create(client,
|
|
|
|
&xdg_popup_interface, 1, id);
|
|
|
|
if (!shsurf->resource) {
|
|
|
|
wl_resource_post_no_memory(surface_resource);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
wl_resource_set_implementation(shsurf->resource,
|
|
|
|
&xdg_popup_implementation,
|
|
|
|
shsurf, shell_destroy_shell_surface);
|
|
|
|
shsurf->owner_resource = resource;
|
|
|
|
wl_list_insert(&sc->surface_list,
|
|
|
|
wl_resource_get_link(shsurf->resource));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_pong(struct wl_client *client,
|
|
|
|
struct wl_resource *resource, uint32_t serial)
|
|
|
|
{
|
|
|
|
struct shell_client *sc = wl_resource_get_user_data(resource);
|
|
|
|
|
|
|
|
shell_client_pong(sc, serial);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
shell_surface_is_xdg_popup(struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
return (shsurf->resource &&
|
|
|
|
wl_resource_instance_of(shsurf->resource,
|
|
|
|
&xdg_popup_interface,
|
|
|
|
&xdg_popup_implementation));
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct xdg_shell_interface xdg_implementation = {
|
|
|
|
xdg_shell_destroy,
|
|
|
|
xdg_use_unstable_version,
|
|
|
|
xdg_get_xdg_surface,
|
|
|
|
xdg_get_xdg_popup,
|
|
|
|
xdg_pong
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
xdg_shell_unversioned_dispatch(const void *implementation,
|
|
|
|
void *_target, uint32_t opcode,
|
|
|
|
const struct wl_message *message,
|
|
|
|
union wl_argument *args)
|
|
|
|
{
|
|
|
|
struct wl_resource *resource = _target;
|
|
|
|
struct shell_client *sc = wl_resource_get_user_data(resource);
|
|
|
|
|
|
|
|
if (opcode != 1 /* XDG_SHELL_USE_UNSTABLE_VERSION */) {
|
|
|
|
wl_resource_post_error(resource,
|
|
|
|
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
|
|
|
"must call use_unstable_version first");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define XDG_SERVER_VERSION 5
|
|
|
|
|
|
|
|
static_assert(XDG_SERVER_VERSION == XDG_SHELL_VERSION_CURRENT,
|
|
|
|
"shell implementation doesn't match protocol version");
|
|
|
|
|
|
|
|
if (args[0].i != XDG_SERVER_VERSION) {
|
|
|
|
wl_resource_post_error(resource,
|
|
|
|
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
|
|
|
"incompatible version, server is %d "
|
|
|
|
"client wants %d",
|
|
|
|
XDG_SERVER_VERSION, args[0].i);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
wl_resource_set_implementation(resource, &xdg_implementation,
|
|
|
|
sc, NULL);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* end of xdg-shell implementation */
|
|
|
|
/***********************************/
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_fade(struct desktop_shell *shell, enum fade_type type);
|
|
|
|
|
|
|
|
static void
|
|
|
|
configure_static_view(struct weston_view *ev, struct weston_layer *layer)
|
|
|
|
{
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *v, *next;
|
|
|
|
|
|
|
|
wl_list_for_each_safe(v, next, &layer->view_list.link, layer_link.link) {
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
if (v->output == ev->output && v != ev) {
|
|
|
|
weston_view_unmap(v);
|
|
|
|
v->surface->configure = NULL;
|
compositor: add weston_surface_set_label_func()
When printing out logs from Weston's actions, mainly for debugging, it
can be very difficult to identify the different surfaces. Inspecting
the configure function pointer is not useful, as the configure functions
may live in modules.
Add vfunc get_label to weston_surface, which will produce a short,
human-readable description of the surface, which allows identifying it
better, rather than just looking at the surface size, for instance.
Set the label function from most parts of Weston, to identify cursors and
drag icons, and panels, backgrounds, screensavers and lock surfaces, and
the desktop shell's application surfaces.
v2: renamed 'description' to 'label', so we get
weston_surface_set_label_func().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
11 years ago
|
|
|
weston_surface_set_label_func(v->surface, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
weston_view_set_position(ev, ev->output->x, ev->output->y);
|
|
|
|
|
|
|
|
if (wl_list_empty(&ev->layer_link.link)) {
|
|
|
|
weston_layer_entry_insert(&layer->view_list, &ev->layer_link);
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_compositor_schedule_repaint(ev->surface->compositor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static struct shell_output *
|
|
|
|
find_shell_output_from_weston_output(struct desktop_shell *shell, struct weston_output *output)
|
|
|
|
{
|
|
|
|
struct shell_output *shell_output;
|
|
|
|
|
|
|
|
wl_list_for_each(shell_output, &shell->output_list, link) {
|
|
|
|
if (shell_output->output == output)
|
|
|
|
return shell_output;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
compositor: add weston_surface_set_label_func()
When printing out logs from Weston's actions, mainly for debugging, it
can be very difficult to identify the different surfaces. Inspecting
the configure function pointer is not useful, as the configure functions
may live in modules.
Add vfunc get_label to weston_surface, which will produce a short,
human-readable description of the surface, which allows identifying it
better, rather than just looking at the surface size, for instance.
Set the label function from most parts of Weston, to identify cursors and
drag icons, and panels, backgrounds, screensavers and lock surfaces, and
the desktop shell's application surfaces.
v2: renamed 'description' to 'label', so we get
weston_surface_set_label_func().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
11 years ago
|
|
|
static int
|
|
|
|
background_get_label(struct weston_surface *surface, char *buf, size_t len)
|
|
|
|
{
|
|
|
|
return snprintf(buf, len, "background for output %s",
|
|
|
|
surface->output->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
background_configure(struct weston_surface *es, int32_t sx, int32_t sy)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = es->configure_private;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *view;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
view = container_of(es->views.next, struct weston_view, surface_link);
|
|
|
|
|
|
|
|
configure_static_view(view, &shell->background_layer);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_background_surface_destroy(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct shell_output *output =
|
|
|
|
container_of(listener, struct shell_output, background_surface_listener);
|
|
|
|
|
|
|
|
weston_log("background surface gone\n");
|
|
|
|
output->background_surface = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
desktop_shell_set_background(struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
struct wl_resource *output_resource,
|
|
|
|
struct wl_resource *surface_resource)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = wl_resource_get_user_data(resource);
|
|
|
|
struct weston_surface *surface =
|
|
|
|
wl_resource_get_user_data(surface_resource);
|
|
|
|
struct shell_output *sh_output;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *view, *next;
|
|
|
|
|
|
|
|
if (surface->configure) {
|
|
|
|
wl_resource_post_error(surface_resource,
|
|
|
|
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
|
|
|
"surface role already assigned");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
wl_list_for_each_safe(view, next, &surface->views, surface_link)
|
|
|
|
weston_view_destroy(view);
|
|
|
|
view = weston_view_create(surface);
|
|
|
|
|
|
|
|
surface->configure = background_configure;
|
|
|
|
surface->configure_private = shell;
|
compositor: add weston_surface_set_label_func()
When printing out logs from Weston's actions, mainly for debugging, it
can be very difficult to identify the different surfaces. Inspecting
the configure function pointer is not useful, as the configure functions
may live in modules.
Add vfunc get_label to weston_surface, which will produce a short,
human-readable description of the surface, which allows identifying it
better, rather than just looking at the surface size, for instance.
Set the label function from most parts of Weston, to identify cursors and
drag icons, and panels, backgrounds, screensavers and lock surfaces, and
the desktop shell's application surfaces.
v2: renamed 'description' to 'label', so we get
weston_surface_set_label_func().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
11 years ago
|
|
|
weston_surface_set_label_func(surface, background_get_label);
|
|
|
|
surface->output = wl_resource_get_user_data(output_resource);
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
view->output = surface->output;
|
|
|
|
weston_desktop_shell_send_configure(resource, 0,
|
|
|
|
surface_resource,
|
|
|
|
surface->output->width,
|
|
|
|
surface->output->height);
|
|
|
|
|
|
|
|
sh_output = find_shell_output_from_weston_output(shell, surface->output);
|
|
|
|
sh_output->background_surface = surface;
|
|
|
|
|
|
|
|
sh_output->background_surface_listener.notify = handle_background_surface_destroy;
|
|
|
|
wl_signal_add(&surface->destroy_signal, &sh_output->background_surface_listener);
|
|
|
|
}
|
|
|
|
|
compositor: add weston_surface_set_label_func()
When printing out logs from Weston's actions, mainly for debugging, it
can be very difficult to identify the different surfaces. Inspecting
the configure function pointer is not useful, as the configure functions
may live in modules.
Add vfunc get_label to weston_surface, which will produce a short,
human-readable description of the surface, which allows identifying it
better, rather than just looking at the surface size, for instance.
Set the label function from most parts of Weston, to identify cursors and
drag icons, and panels, backgrounds, screensavers and lock surfaces, and
the desktop shell's application surfaces.
v2: renamed 'description' to 'label', so we get
weston_surface_set_label_func().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
11 years ago
|
|
|
static int
|
|
|
|
panel_get_label(struct weston_surface *surface, char *buf, size_t len)
|
|
|
|
{
|
|
|
|
return snprintf(buf, len, "panel for output %s",
|
|
|
|
surface->output->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
panel_configure(struct weston_surface *es, int32_t sx, int32_t sy)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = es->configure_private;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *view;
|
|
|
|
|
|
|
|
view = container_of(es->views.next, struct weston_view, surface_link);
|
|
|
|
|
|
|
|
configure_static_view(view, &shell->panel_layer);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_panel_surface_destroy(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct shell_output *output =
|
|
|
|
container_of(listener, struct shell_output, panel_surface_listener);
|
|
|
|
|
|
|
|
weston_log("panel surface gone\n");
|
|
|
|
output->panel_surface = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
desktop_shell_set_panel(struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
struct wl_resource *output_resource,
|
|
|
|
struct wl_resource *surface_resource)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = wl_resource_get_user_data(resource);
|
|
|
|
struct weston_surface *surface =
|
|
|
|
wl_resource_get_user_data(surface_resource);
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *view, *next;
|
|
|
|
struct shell_output *sh_output;
|
|
|
|
|
|
|
|
if (surface->configure) {
|
|
|
|
wl_resource_post_error(surface_resource,
|
|
|
|
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
|
|
|
"surface role already assigned");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
wl_list_for_each_safe(view, next, &surface->views, surface_link)
|
|
|
|
weston_view_destroy(view);
|
|
|
|
view = weston_view_create(surface);
|
|
|
|
|
|
|
|
surface->configure = panel_configure;
|
|
|
|
surface->configure_private = shell;
|
compositor: add weston_surface_set_label_func()
When printing out logs from Weston's actions, mainly for debugging, it
can be very difficult to identify the different surfaces. Inspecting
the configure function pointer is not useful, as the configure functions
may live in modules.
Add vfunc get_label to weston_surface, which will produce a short,
human-readable description of the surface, which allows identifying it
better, rather than just looking at the surface size, for instance.
Set the label function from most parts of Weston, to identify cursors and
drag icons, and panels, backgrounds, screensavers and lock surfaces, and
the desktop shell's application surfaces.
v2: renamed 'description' to 'label', so we get
weston_surface_set_label_func().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
11 years ago
|
|
|
weston_surface_set_label_func(surface, panel_get_label);
|
|
|
|
surface->output = wl_resource_get_user_data(output_resource);
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
view->output = surface->output;
|
|
|
|
weston_desktop_shell_send_configure(resource, 0,
|
|
|
|
surface_resource,
|
|
|
|
surface->output->width,
|
|
|
|
surface->output->height);
|
|
|
|
|
|
|
|
sh_output = find_shell_output_from_weston_output(shell, surface->output);
|
|
|
|
sh_output->panel_surface = surface;
|
|
|
|
|
|
|
|
sh_output->panel_surface_listener.notify = handle_panel_surface_destroy;
|
|
|
|
wl_signal_add(&surface->destroy_signal, &sh_output->panel_surface_listener);
|
|
|
|
}
|
|
|
|
|
compositor: add weston_surface_set_label_func()
When printing out logs from Weston's actions, mainly for debugging, it
can be very difficult to identify the different surfaces. Inspecting
the configure function pointer is not useful, as the configure functions
may live in modules.
Add vfunc get_label to weston_surface, which will produce a short,
human-readable description of the surface, which allows identifying it
better, rather than just looking at the surface size, for instance.
Set the label function from most parts of Weston, to identify cursors and
drag icons, and panels, backgrounds, screensavers and lock surfaces, and
the desktop shell's application surfaces.
v2: renamed 'description' to 'label', so we get
weston_surface_set_label_func().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
11 years ago
|
|
|
static int
|
|
|
|
lock_surface_get_label(struct weston_surface *surface, char *buf, size_t len)
|
|
|
|
{
|
|
|
|
return snprintf(buf, len, "lock window");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lock_surface_configure(struct weston_surface *surface, int32_t sx, int32_t sy)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = surface->configure_private;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *view;
|
|
|
|
|
|
|
|
view = container_of(surface->views.next, struct weston_view, surface_link);
|
|
|
|
|
|
|
|
if (surface->width == 0)
|
|
|
|
return;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
center_on_output(view, get_default_output(shell->compositor));
|
|
|
|
|
|
|
|
if (!weston_surface_is_mapped(surface)) {
|
|
|
|
weston_layer_entry_insert(&shell->lock_layer.view_list,
|
|
|
|
&view->layer_link);
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_update_transform(view);
|
|
|
|
shell_fade(shell, FADE_IN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_lock_surface_destroy(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell =
|
|
|
|
container_of(listener, struct desktop_shell, lock_surface_listener);
|
|
|
|
|
|
|
|
weston_log("lock surface gone\n");
|
|
|
|
shell->lock_surface = NULL;
|
|
|
|
}
|
|
|
|
|
desktop-shell: screen locking protocol
Add protocol and functions for supporting screen locking, triggered by
activity timeout.
After activity timeout, compositor starts the fade to black, and then
enters SLEEPING state. At that point it calls lock() in the shell
plugin.
When input events trigger a wakeup, unlock() in the shell plugin is
called. This sends prepare_lock_surface event to the desktop-shell
client. The screen stays locked while the compositor starts fade-in.
At this point, desktop-shell client usually creates a surface for the
unlocking GUI (e.g. a password prompt), and sends it with the
set_lock_surface request. The compositor supposedly shows and allows
interaction only with the given lock surface (not yet implemented).
When desktop-shell has authenticated the user, or instead of issuing
set_lock_surface, it sends the unlock request. Upon receiving the unlock
request, the shell plugin unlocks the screen.
If desktop-shell client dies, the screen is unlocked automatically.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
13 years ago
|
|
|
static void
|
|
|
|
desktop_shell_set_lock_surface(struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
struct wl_resource *surface_resource)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = wl_resource_get_user_data(resource);
|
|
|
|
struct weston_surface *surface =
|
|
|
|
wl_resource_get_user_data(surface_resource);
|
|
|
|
|
|
|
|
shell->prepare_event_sent = false;
|
|
|
|
|
|
|
|
if (!shell->locked)
|
|
|
|
return;
|
|
|
|
|
|
|
|
shell->lock_surface = surface;
|
|
|
|
|
|
|
|
shell->lock_surface_listener.notify = handle_lock_surface_destroy;
|
|
|
|
wl_signal_add(&surface->destroy_signal,
|
|
|
|
&shell->lock_surface_listener);
|
|
|
|
|
|
|
|
weston_view_create(surface);
|
|
|
|
surface->configure = lock_surface_configure;
|
|
|
|
surface->configure_private = shell;
|
compositor: add weston_surface_set_label_func()
When printing out logs from Weston's actions, mainly for debugging, it
can be very difficult to identify the different surfaces. Inspecting
the configure function pointer is not useful, as the configure functions
may live in modules.
Add vfunc get_label to weston_surface, which will produce a short,
human-readable description of the surface, which allows identifying it
better, rather than just looking at the surface size, for instance.
Set the label function from most parts of Weston, to identify cursors and
drag icons, and panels, backgrounds, screensavers and lock surfaces, and
the desktop shell's application surfaces.
v2: renamed 'description' to 'label', so we get
weston_surface_set_label_func().
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
11 years ago
|
|
|
weston_surface_set_label_func(surface, lock_surface_get_label);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
resume_desktop(struct desktop_shell *shell)
|
|
|
|
{
|
|
|
|
struct workspace *ws = get_current_workspace(shell);
|
|
|
|
|
|
|
|
wl_list_remove(&shell->lock_layer.link);
|
|
|
|
if (shell->showing_input_panels) {
|
|
|
|
wl_list_insert(&shell->compositor->cursor_layer.link,
|
|
|
|
&shell->input_panel_layer.link);
|
|
|
|
wl_list_insert(&shell->input_panel_layer.link,
|
|
|
|
&shell->fullscreen_layer.link);
|
|
|
|
} else {
|
|
|
|
wl_list_insert(&shell->compositor->cursor_layer.link,
|
|
|
|
&shell->fullscreen_layer.link);
|
|
|
|
}
|
|
|
|
wl_list_insert(&shell->fullscreen_layer.link,
|
|
|
|
&shell->panel_layer.link);
|
|
|
|
wl_list_insert(&shell->panel_layer.link,
|
|
|
|
&ws->layer.link),
|
|
|
|
|
|
|
|
restore_focus_state(shell, get_current_workspace(shell));
|
|
|
|
|
|
|
|
shell->locked = false;
|
|
|
|
shell_fade(shell, FADE_IN);
|
|
|
|
weston_compositor_damage_all(shell->compositor);
|
desktop-shell: screen locking protocol
Add protocol and functions for supporting screen locking, triggered by
activity timeout.
After activity timeout, compositor starts the fade to black, and then
enters SLEEPING state. At that point it calls lock() in the shell
plugin.
When input events trigger a wakeup, unlock() in the shell plugin is
called. This sends prepare_lock_surface event to the desktop-shell
client. The screen stays locked while the compositor starts fade-in.
At this point, desktop-shell client usually creates a surface for the
unlocking GUI (e.g. a password prompt), and sends it with the
set_lock_surface request. The compositor supposedly shows and allows
interaction only with the given lock surface (not yet implemented).
When desktop-shell has authenticated the user, or instead of issuing
set_lock_surface, it sends the unlock request. Upon receiving the unlock
request, the shell plugin unlocks the screen.
If desktop-shell client dies, the screen is unlocked automatically.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
13 years ago
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
desktop_shell_unlock(struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = wl_resource_get_user_data(resource);
|
desktop-shell: screen locking protocol
Add protocol and functions for supporting screen locking, triggered by
activity timeout.
After activity timeout, compositor starts the fade to black, and then
enters SLEEPING state. At that point it calls lock() in the shell
plugin.
When input events trigger a wakeup, unlock() in the shell plugin is
called. This sends prepare_lock_surface event to the desktop-shell
client. The screen stays locked while the compositor starts fade-in.
At this point, desktop-shell client usually creates a surface for the
unlocking GUI (e.g. a password prompt), and sends it with the
set_lock_surface request. The compositor supposedly shows and allows
interaction only with the given lock surface (not yet implemented).
When desktop-shell has authenticated the user, or instead of issuing
set_lock_surface, it sends the unlock request. Upon receiving the unlock
request, the shell plugin unlocks the screen.
If desktop-shell client dies, the screen is unlocked automatically.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
13 years ago
|
|
|
|
|
|
|
shell->prepare_event_sent = false;
|
|
|
|
|
|
|
|
if (shell->locked)
|
|
|
|
resume_desktop(shell);
|
desktop-shell: screen locking protocol
Add protocol and functions for supporting screen locking, triggered by
activity timeout.
After activity timeout, compositor starts the fade to black, and then
enters SLEEPING state. At that point it calls lock() in the shell
plugin.
When input events trigger a wakeup, unlock() in the shell plugin is
called. This sends prepare_lock_surface event to the desktop-shell
client. The screen stays locked while the compositor starts fade-in.
At this point, desktop-shell client usually creates a surface for the
unlocking GUI (e.g. a password prompt), and sends it with the
set_lock_surface request. The compositor supposedly shows and allows
interaction only with the given lock surface (not yet implemented).
When desktop-shell has authenticated the user, or instead of issuing
set_lock_surface, it sends the unlock request. Upon receiving the unlock
request, the shell plugin unlocks the screen.
If desktop-shell client dies, the screen is unlocked automatically.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
13 years ago
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
desktop_shell_set_grab_surface(struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
struct wl_resource *surface_resource)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = wl_resource_get_user_data(resource);
|
|
|
|
|
|
|
|
shell->grab_surface = wl_resource_get_user_data(surface_resource);
|
|
|
|
weston_view_create(shell->grab_surface);
|
|
|
|
}
|
|
|
|
|
shell: wait for desktop-shell init before fade in
On Raspberry Pi, weston-desktop-shell is so slow to start, that the
compositor has time to run the fade-in before the wallpaper is up. The
user launching Weston sees the screen flipping to black, the fbcon
fading in, and then the desktop popping up.
To fix this, wait for the weston-desktop-shell to draw
everything before starting the initial fade-in. A new request is
added to the private desktop-shell protocol to signal it. If a
desktop-shell client does not support the new request, the fade-in
happens already at bind time.
If weston-desktop-shell crashes, or does not send the 'desktop_ready'
request in 15 seconds, the compositor will fade in anyway. This should
avoid a blocked screen in case weston-desktop-shell malfunction.
shell_fade_startup() does not directly start the fade-in but schedules
an idle callback, so that the compositor can process all pending events
before starting the fade clock. Otherwise (on RPi) we risk skipping part
of the animation. Yes, it is a hack, that should have been done in
window.c and weston-desktop-shell instead.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
12 years ago
|
|
|
static void
|
|
|
|
desktop_shell_desktop_ready(struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = wl_resource_get_user_data(resource);
|
shell: wait for desktop-shell init before fade in
On Raspberry Pi, weston-desktop-shell is so slow to start, that the
compositor has time to run the fade-in before the wallpaper is up. The
user launching Weston sees the screen flipping to black, the fbcon
fading in, and then the desktop popping up.
To fix this, wait for the weston-desktop-shell to draw
everything before starting the initial fade-in. A new request is
added to the private desktop-shell protocol to signal it. If a
desktop-shell client does not support the new request, the fade-in
happens already at bind time.
If weston-desktop-shell crashes, or does not send the 'desktop_ready'
request in 15 seconds, the compositor will fade in anyway. This should
avoid a blocked screen in case weston-desktop-shell malfunction.
shell_fade_startup() does not directly start the fade-in but schedules
an idle callback, so that the compositor can process all pending events
before starting the fade clock. Otherwise (on RPi) we risk skipping part
of the animation. Yes, it is a hack, that should have been done in
window.c and weston-desktop-shell instead.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
12 years ago
|
|
|
|
|
|
|
shell_fade_startup(shell);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
desktop_shell_set_panel_position(struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t position)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = wl_resource_get_user_data(resource);
|
|
|
|
|
|
|
|
if (position != WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP &&
|
|
|
|
position != WESTON_DESKTOP_SHELL_PANEL_POSITION_BOTTOM &&
|
|
|
|
position != WESTON_DESKTOP_SHELL_PANEL_POSITION_LEFT &&
|
|
|
|
position != WESTON_DESKTOP_SHELL_PANEL_POSITION_RIGHT) {
|
|
|
|
wl_resource_post_error(resource,
|
|
|
|
WESTON_DESKTOP_SHELL_ERROR_INVALID_ARGUMENT,
|
|
|
|
"bad position argument");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
shell->panel_position = position;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct weston_desktop_shell_interface desktop_shell_implementation = {
|
|
|
|
desktop_shell_set_background,
|
desktop-shell: screen locking protocol
Add protocol and functions for supporting screen locking, triggered by
activity timeout.
After activity timeout, compositor starts the fade to black, and then
enters SLEEPING state. At that point it calls lock() in the shell
plugin.
When input events trigger a wakeup, unlock() in the shell plugin is
called. This sends prepare_lock_surface event to the desktop-shell
client. The screen stays locked while the compositor starts fade-in.
At this point, desktop-shell client usually creates a surface for the
unlocking GUI (e.g. a password prompt), and sends it with the
set_lock_surface request. The compositor supposedly shows and allows
interaction only with the given lock surface (not yet implemented).
When desktop-shell has authenticated the user, or instead of issuing
set_lock_surface, it sends the unlock request. Upon receiving the unlock
request, the shell plugin unlocks the screen.
If desktop-shell client dies, the screen is unlocked automatically.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
13 years ago
|
|
|
desktop_shell_set_panel,
|
|
|
|
desktop_shell_set_lock_surface,
|
|
|
|
desktop_shell_unlock,
|
shell: wait for desktop-shell init before fade in
On Raspberry Pi, weston-desktop-shell is so slow to start, that the
compositor has time to run the fade-in before the wallpaper is up. The
user launching Weston sees the screen flipping to black, the fbcon
fading in, and then the desktop popping up.
To fix this, wait for the weston-desktop-shell to draw
everything before starting the initial fade-in. A new request is
added to the private desktop-shell protocol to signal it. If a
desktop-shell client does not support the new request, the fade-in
happens already at bind time.
If weston-desktop-shell crashes, or does not send the 'desktop_ready'
request in 15 seconds, the compositor will fade in anyway. This should
avoid a blocked screen in case weston-desktop-shell malfunction.
shell_fade_startup() does not directly start the fade-in but schedules
an idle callback, so that the compositor can process all pending events
before starting the fade clock. Otherwise (on RPi) we risk skipping part
of the animation. Yes, it is a hack, that should have been done in
window.c and weston-desktop-shell instead.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
12 years ago
|
|
|
desktop_shell_set_grab_surface,
|
|
|
|
desktop_shell_desktop_ready,
|
|
|
|
desktop_shell_set_panel_position
|
|
|
|
};
|
|
|
|
|
|
|
|
static enum shell_surface_type
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
13 years ago
|
|
|
get_shell_surface_type(struct weston_surface *surface)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
|
|
|
|
shsurf = get_shell_surface(surface);
|
|
|
|
if (!shsurf)
|
|
|
|
return SHELL_SURFACE_NONE;
|
|
|
|
return shsurf->type;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
move_binding(struct weston_pointer *pointer, uint32_t time,
|
|
|
|
uint32_t button, void *data)
|
|
|
|
{
|
|
|
|
struct weston_surface *focus;
|
shell: keyboard focus and restacking fixes for sub-surfaces
The shell needs to redirect some actions to the parent surface, when
they originally target a sub-surface. This patch implements the
following:
- Move, resize, and rotate bindings always target the parent surface.
- Opacity (full-surface alpha) binding targets the parent surface. This
is broken, because it should change the opacity of the whole compound
window, which is difficult to implement in the renderer.
- click_to_activate_binding() needs to check the shell surface type from
the main surface, because sub-surface would produce SHELL_SURFACE_NONE
and prevent activation.
- Also activate() needs to check the type from the main surface, and
restack the main surface. Keyboard focus is assigned to the original
(sub-)surface.
- focus_state_surface_destroy() needs to handle sub-surfaces: only the
main surface will be in a layer list. If the destroyed surface is
indeed a sub-surface, activate the main surface next. This way a
client that destroys a focused sub-surface still retains focus in the
same window.
- The workspace_manager.move_surface request can accept also
sub-surfaces, and it will move the corresponding main surface.
Changes in v2:
- do not special-case keyboard focus for sub-surfaces
- fix surface type checks for sub-surfaces in shell, fix restacking of
sub-surfaces in shell, fix focus_state_surface_destroy()
Changes in v3:
- Renamed weston_surface_get_parent() to
weston_surface_get_main_surface() to be more explicit that this is
about sub-surfaces
- Fixed move_surface_to_workspace() to handle keyboard focus on a
sub-surface.
- Used a temporary variable in several places to clarify code, instead
of reassigning a variable.
- Fixed workspace_manager_move_surface() to deal with sub-surfaces.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
12 years ago
|
|
|
struct weston_surface *surface;
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
|
|
|
|
if (pointer->focus == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
focus = pointer->focus->surface;
|
|
|
|
|
shell: keyboard focus and restacking fixes for sub-surfaces
The shell needs to redirect some actions to the parent surface, when
they originally target a sub-surface. This patch implements the
following:
- Move, resize, and rotate bindings always target the parent surface.
- Opacity (full-surface alpha) binding targets the parent surface. This
is broken, because it should change the opacity of the whole compound
window, which is difficult to implement in the renderer.
- click_to_activate_binding() needs to check the shell surface type from
the main surface, because sub-surface would produce SHELL_SURFACE_NONE
and prevent activation.
- Also activate() needs to check the type from the main surface, and
restack the main surface. Keyboard focus is assigned to the original
(sub-)surface.
- focus_state_surface_destroy() needs to handle sub-surfaces: only the
main surface will be in a layer list. If the destroyed surface is
indeed a sub-surface, activate the main surface next. This way a
client that destroys a focused sub-surface still retains focus in the
same window.
- The workspace_manager.move_surface request can accept also
sub-surfaces, and it will move the corresponding main surface.
Changes in v2:
- do not special-case keyboard focus for sub-surfaces
- fix surface type checks for sub-surfaces in shell, fix restacking of
sub-surfaces in shell, fix focus_state_surface_destroy()
Changes in v3:
- Renamed weston_surface_get_parent() to
weston_surface_get_main_surface() to be more explicit that this is
about sub-surfaces
- Fixed move_surface_to_workspace() to handle keyboard focus on a
sub-surface.
- Used a temporary variable in several places to clarify code, instead
of reassigning a variable.
- Fixed workspace_manager_move_surface() to deal with sub-surfaces.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
12 years ago
|
|
|
surface = weston_surface_get_main_surface(focus);
|
|
|
|
if (surface == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
shsurf = get_shell_surface(surface);
|
|
|
|
if (shsurf == NULL || shsurf->state.fullscreen ||
|
|
|
|
shsurf->state.maximized)
|
|
|
|
return;
|
|
|
|
|
|
|
|
surface_move(shsurf, pointer, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
maximize_binding(struct weston_keyboard *keyboard, uint32_t time,
|
|
|
|
uint32_t button, void *data)
|
|
|
|
{
|
|
|
|
struct weston_surface *focus = keyboard->focus;
|
|
|
|
struct weston_surface *surface;
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
|
|
|
|
surface = weston_surface_get_main_surface(focus);
|
|
|
|
if (surface == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
shsurf = get_shell_surface(surface);
|
|
|
|
if (shsurf == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!shell_surface_is_xdg_surface(shsurf))
|
|
|
|
return;
|
|
|
|
|
|
|
|
shsurf->state_requested = true;
|
|
|
|
shsurf->requested_state.maximized = !shsurf->state.maximized;
|
|
|
|
send_configure_for_surface(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fullscreen_binding(struct weston_keyboard *keyboard, uint32_t time,
|
|
|
|
uint32_t button, void *data)
|
|
|
|
{
|
|
|
|
struct weston_surface *focus = keyboard->focus;
|
|
|
|
struct weston_surface *surface;
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
|
|
|
|
surface = weston_surface_get_main_surface(focus);
|
|
|
|
if (surface == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
shsurf = get_shell_surface(surface);
|
|
|
|
if (shsurf == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!shell_surface_is_xdg_surface(shsurf))
|
|
|
|
return;
|
|
|
|
|
|
|
|
shsurf->state_requested = true;
|
|
|
|
shsurf->requested_state.fullscreen = !shsurf->state.fullscreen;
|
|
|
|
shsurf->fullscreen_output = shsurf->output;
|
|
|
|
send_configure_for_surface(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
touch_move_binding(struct weston_touch *touch, uint32_t time, void *data)
|
|
|
|
{
|
|
|
|
struct weston_surface *focus;
|
|
|
|
struct weston_surface *surface;
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
|
|
|
|
if (touch->focus == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
focus = touch->focus->surface;
|
|
|
|
surface = weston_surface_get_main_surface(focus);
|
|
|
|
if (surface == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
shsurf = get_shell_surface(surface);
|
|
|
|
if (shsurf == NULL || shsurf->state.fullscreen ||
|
|
|
|
shsurf->state.maximized)
|
|
|
|
return;
|
|
|
|
|
|
|
|
surface_touch_move(shsurf, touch);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
resize_binding(struct weston_pointer *pointer, uint32_t time,
|
|
|
|
uint32_t button, void *data)
|
|
|
|
{
|
|
|
|
struct weston_surface *focus;
|
shell: keyboard focus and restacking fixes for sub-surfaces
The shell needs to redirect some actions to the parent surface, when
they originally target a sub-surface. This patch implements the
following:
- Move, resize, and rotate bindings always target the parent surface.
- Opacity (full-surface alpha) binding targets the parent surface. This
is broken, because it should change the opacity of the whole compound
window, which is difficult to implement in the renderer.
- click_to_activate_binding() needs to check the shell surface type from
the main surface, because sub-surface would produce SHELL_SURFACE_NONE
and prevent activation.
- Also activate() needs to check the type from the main surface, and
restack the main surface. Keyboard focus is assigned to the original
(sub-)surface.
- focus_state_surface_destroy() needs to handle sub-surfaces: only the
main surface will be in a layer list. If the destroyed surface is
indeed a sub-surface, activate the main surface next. This way a
client that destroys a focused sub-surface still retains focus in the
same window.
- The workspace_manager.move_surface request can accept also
sub-surfaces, and it will move the corresponding main surface.
Changes in v2:
- do not special-case keyboard focus for sub-surfaces
- fix surface type checks for sub-surfaces in shell, fix restacking of
sub-surfaces in shell, fix focus_state_surface_destroy()
Changes in v3:
- Renamed weston_surface_get_parent() to
weston_surface_get_main_surface() to be more explicit that this is
about sub-surfaces
- Fixed move_surface_to_workspace() to handle keyboard focus on a
sub-surface.
- Used a temporary variable in several places to clarify code, instead
of reassigning a variable.
- Fixed workspace_manager_move_surface() to deal with sub-surfaces.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
12 years ago
|
|
|
struct weston_surface *surface;
|
|
|
|
uint32_t edges = 0;
|
|
|
|
int32_t x, y;
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
|
|
|
|
if (pointer->focus == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
focus = pointer->focus->surface;
|
|
|
|
|
shell: keyboard focus and restacking fixes for sub-surfaces
The shell needs to redirect some actions to the parent surface, when
they originally target a sub-surface. This patch implements the
following:
- Move, resize, and rotate bindings always target the parent surface.
- Opacity (full-surface alpha) binding targets the parent surface. This
is broken, because it should change the opacity of the whole compound
window, which is difficult to implement in the renderer.
- click_to_activate_binding() needs to check the shell surface type from
the main surface, because sub-surface would produce SHELL_SURFACE_NONE
and prevent activation.
- Also activate() needs to check the type from the main surface, and
restack the main surface. Keyboard focus is assigned to the original
(sub-)surface.
- focus_state_surface_destroy() needs to handle sub-surfaces: only the
main surface will be in a layer list. If the destroyed surface is
indeed a sub-surface, activate the main surface next. This way a
client that destroys a focused sub-surface still retains focus in the
same window.
- The workspace_manager.move_surface request can accept also
sub-surfaces, and it will move the corresponding main surface.
Changes in v2:
- do not special-case keyboard focus for sub-surfaces
- fix surface type checks for sub-surfaces in shell, fix restacking of
sub-surfaces in shell, fix focus_state_surface_destroy()
Changes in v3:
- Renamed weston_surface_get_parent() to
weston_surface_get_main_surface() to be more explicit that this is
about sub-surfaces
- Fixed move_surface_to_workspace() to handle keyboard focus on a
sub-surface.
- Used a temporary variable in several places to clarify code, instead
of reassigning a variable.
- Fixed workspace_manager_move_surface() to deal with sub-surfaces.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
12 years ago
|
|
|
surface = weston_surface_get_main_surface(focus);
|
|
|
|
if (surface == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
shsurf = get_shell_surface(surface);
|
|
|
|
if (shsurf == NULL || shsurf->state.fullscreen ||
|
|
|
|
shsurf->state.maximized)
|
|
|
|
return;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_from_global(shsurf->view,
|
|
|
|
wl_fixed_to_int(pointer->grab_x),
|
|
|
|
wl_fixed_to_int(pointer->grab_y),
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
&x, &y);
|
|
|
|
|
|
|
|
if (x < shsurf->surface->width / 3)
|
|
|
|
edges |= WL_SHELL_SURFACE_RESIZE_LEFT;
|
|
|
|
else if (x < 2 * shsurf->surface->width / 3)
|
|
|
|
edges |= 0;
|
|
|
|
else
|
|
|
|
edges |= WL_SHELL_SURFACE_RESIZE_RIGHT;
|
|
|
|
|
|
|
|
if (y < shsurf->surface->height / 3)
|
|
|
|
edges |= WL_SHELL_SURFACE_RESIZE_TOP;
|
|
|
|
else if (y < 2 * shsurf->surface->height / 3)
|
|
|
|
edges |= 0;
|
|
|
|
else
|
|
|
|
edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
|
|
|
|
|
|
|
|
surface_resize(shsurf, pointer, edges);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
surface_opacity_binding(struct weston_pointer *pointer, uint32_t time,
|
|
|
|
struct weston_pointer_axis_event *event,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
float step = 0.005;
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
struct weston_surface *focus = pointer->focus->surface;
|
shell: keyboard focus and restacking fixes for sub-surfaces
The shell needs to redirect some actions to the parent surface, when
they originally target a sub-surface. This patch implements the
following:
- Move, resize, and rotate bindings always target the parent surface.
- Opacity (full-surface alpha) binding targets the parent surface. This
is broken, because it should change the opacity of the whole compound
window, which is difficult to implement in the renderer.
- click_to_activate_binding() needs to check the shell surface type from
the main surface, because sub-surface would produce SHELL_SURFACE_NONE
and prevent activation.
- Also activate() needs to check the type from the main surface, and
restack the main surface. Keyboard focus is assigned to the original
(sub-)surface.
- focus_state_surface_destroy() needs to handle sub-surfaces: only the
main surface will be in a layer list. If the destroyed surface is
indeed a sub-surface, activate the main surface next. This way a
client that destroys a focused sub-surface still retains focus in the
same window.
- The workspace_manager.move_surface request can accept also
sub-surfaces, and it will move the corresponding main surface.
Changes in v2:
- do not special-case keyboard focus for sub-surfaces
- fix surface type checks for sub-surfaces in shell, fix restacking of
sub-surfaces in shell, fix focus_state_surface_destroy()
Changes in v3:
- Renamed weston_surface_get_parent() to
weston_surface_get_main_surface() to be more explicit that this is
about sub-surfaces
- Fixed move_surface_to_workspace() to handle keyboard focus on a
sub-surface.
- Used a temporary variable in several places to clarify code, instead
of reassigning a variable.
- Fixed workspace_manager_move_surface() to deal with sub-surfaces.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
12 years ago
|
|
|
struct weston_surface *surface;
|
|
|
|
|
shell: keyboard focus and restacking fixes for sub-surfaces
The shell needs to redirect some actions to the parent surface, when
they originally target a sub-surface. This patch implements the
following:
- Move, resize, and rotate bindings always target the parent surface.
- Opacity (full-surface alpha) binding targets the parent surface. This
is broken, because it should change the opacity of the whole compound
window, which is difficult to implement in the renderer.
- click_to_activate_binding() needs to check the shell surface type from
the main surface, because sub-surface would produce SHELL_SURFACE_NONE
and prevent activation.
- Also activate() needs to check the type from the main surface, and
restack the main surface. Keyboard focus is assigned to the original
(sub-)surface.
- focus_state_surface_destroy() needs to handle sub-surfaces: only the
main surface will be in a layer list. If the destroyed surface is
indeed a sub-surface, activate the main surface next. This way a
client that destroys a focused sub-surface still retains focus in the
same window.
- The workspace_manager.move_surface request can accept also
sub-surfaces, and it will move the corresponding main surface.
Changes in v2:
- do not special-case keyboard focus for sub-surfaces
- fix surface type checks for sub-surfaces in shell, fix restacking of
sub-surfaces in shell, fix focus_state_surface_destroy()
Changes in v3:
- Renamed weston_surface_get_parent() to
weston_surface_get_main_surface() to be more explicit that this is
about sub-surfaces
- Fixed move_surface_to_workspace() to handle keyboard focus on a
sub-surface.
- Used a temporary variable in several places to clarify code, instead
of reassigning a variable.
- Fixed workspace_manager_move_surface() to deal with sub-surfaces.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
12 years ago
|
|
|
/* XXX: broken for windows containing sub-surfaces */
|
|
|
|
surface = weston_surface_get_main_surface(focus);
|
|
|
|
if (surface == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
shsurf = get_shell_surface(surface);
|
|
|
|
if (!shsurf)
|
|
|
|
return;
|
|
|
|
|
|
|
|
shsurf->view->alpha -= event->value * step;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
if (shsurf->view->alpha > 1.0)
|
|
|
|
shsurf->view->alpha = 1.0;
|
|
|
|
if (shsurf->view->alpha < step)
|
|
|
|
shsurf->view->alpha = step;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_geometry_dirty(shsurf->view);
|
|
|
|
weston_surface_damage(surface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
do_zoom(struct weston_seat *seat, uint32_t time, uint32_t key, uint32_t axis,
|
|
|
|
double value)
|
|
|
|
{
|
|
|
|
struct weston_compositor *compositor = seat->compositor;
|
|
|
|
struct weston_pointer *pointer = weston_seat_get_pointer(seat);
|
|
|
|
struct weston_output *output;
|
|
|
|
float increment;
|
|
|
|
|
|
|
|
if (!pointer) {
|
|
|
|
weston_log("Zoom hotkey pressed but seat '%s' contains no pointer.\n", seat->seat_name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
wl_list_for_each(output, &compositor->output_list, link) {
|
|
|
|
if (pixman_region32_contains_point(&output->region,
|
|
|
|
wl_fixed_to_double(pointer->x),
|
|
|
|
wl_fixed_to_double(pointer->y),
|
|
|
|
NULL)) {
|
|
|
|
if (key == KEY_PAGEUP)
|
|
|
|
increment = output->zoom.increment;
|
|
|
|
else if (key == KEY_PAGEDOWN)
|
|
|
|
increment = -output->zoom.increment;
|
|
|
|
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
|
|
|
|
/* For every pixel zoom 20th of a step */
|
|
|
|
increment = output->zoom.increment *
|
|
|
|
-value / 20.0;
|
|
|
|
else
|
|
|
|
increment = 0;
|
|
|
|
|
|
|
|
output->zoom.level += increment;
|
|
|
|
|
|
|
|
if (output->zoom.level < 0.0)
|
|
|
|
output->zoom.level = 0.0;
|
|
|
|
else if (output->zoom.level > output->zoom.max_level)
|
|
|
|
output->zoom.level = output->zoom.max_level;
|
|
|
|
|
|
|
|
if (!output->zoom.active) {
|
|
|
|
if (output->zoom.level <= 0.0)
|
|
|
|
continue;
|
|
|
|
weston_output_activate_zoom(output, seat);
|
|
|
|
}
|
|
|
|
|
|
|
|
output->zoom.spring_z.target = output->zoom.level;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_output_update_zoom(output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
zoom_axis_binding(struct weston_pointer *pointer, uint32_t time,
|
|
|
|
struct weston_pointer_axis_event *event,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
do_zoom(pointer->seat, time, 0, event->axis, event->value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
zoom_key_binding(struct weston_keyboard *keyboard, uint32_t time,
|
|
|
|
uint32_t key, void *data)
|
|
|
|
{
|
|
|
|
do_zoom(keyboard->seat, time, key, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
terminate_binding(struct weston_keyboard *keyboard, uint32_t time,
|
|
|
|
uint32_t key, void *data)
|
|
|
|
{
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
13 years ago
|
|
|
struct weston_compositor *compositor = data;
|
|
|
|
|
|
|
|
wl_display_terminate(compositor->wl_display);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rotate_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
|
|
|
|
struct weston_pointer_motion_event *event)
|
|
|
|
{
|
|
|
|
struct rotate_grab *rotate =
|
|
|
|
container_of(grab, struct rotate_grab, base.grab);
|
|
|
|
struct weston_pointer *pointer = grab->pointer;
|
|
|
|
struct shell_surface *shsurf = rotate->base.shsurf;
|
|
|
|
float cx, cy, dx, dy, cposx, cposy, dposx, dposy, r;
|
|
|
|
|
|
|
|
weston_pointer_move(pointer, event);
|
|
|
|
|
|
|
|
if (!shsurf)
|
|
|
|
return;
|
|
|
|
|
|
|
|
cx = 0.5f * shsurf->surface->width;
|
|
|
|
cy = 0.5f * shsurf->surface->height;
|
|
|
|
|
|
|
|
dx = wl_fixed_to_double(pointer->x) - rotate->center.x;
|
|
|
|
dy = wl_fixed_to_double(pointer->y) - rotate->center.y;
|
|
|
|
r = sqrtf(dx * dx + dy * dy);
|
|
|
|
|
|
|
|
wl_list_remove(&shsurf->rotation.transform.link);
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_geometry_dirty(shsurf->view);
|
|
|
|
|
|
|
|
if (r > 20.0f) {
|
|
|
|
struct weston_matrix *matrix =
|
|
|
|
&shsurf->rotation.transform.matrix;
|
|
|
|
|
|
|
|
weston_matrix_init(&rotate->rotation);
|
|
|
|
weston_matrix_rotate_xy(&rotate->rotation, dx / r, dy / r);
|
|
|
|
|
|
|
|
weston_matrix_init(matrix);
|
|
|
|
weston_matrix_translate(matrix, -cx, -cy, 0.0f);
|
|
|
|
weston_matrix_multiply(matrix, &shsurf->rotation.rotation);
|
|
|
|
weston_matrix_multiply(matrix, &rotate->rotation);
|
|
|
|
weston_matrix_translate(matrix, cx, cy, 0.0f);
|
|
|
|
|
|
|
|
wl_list_insert(
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
&shsurf->view->geometry.transformation_list,
|
|
|
|
&shsurf->rotation.transform.link);
|
|
|
|
} else {
|
|
|
|
wl_list_init(&shsurf->rotation.transform.link);
|
|
|
|
weston_matrix_init(&shsurf->rotation.rotation);
|
|
|
|
weston_matrix_init(&rotate->rotation);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We need to adjust the position of the surface
|
|
|
|
* in case it was resized in a rotated state before */
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
cposx = shsurf->view->geometry.x + cx;
|
|
|
|
cposy = shsurf->view->geometry.y + cy;
|
|
|
|
dposx = rotate->center.x - cposx;
|
|
|
|
dposy = rotate->center.y - cposy;
|
|
|
|
if (dposx != 0.0f || dposy != 0.0f) {
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_set_position(shsurf->view,
|
|
|
|
shsurf->view->geometry.x + dposx,
|
|
|
|
shsurf->view->geometry.y + dposy);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Repaint implies weston_view_update_transform(), which
|
|
|
|
* lazily applies the damage due to rotation update.
|
|
|
|
*/
|
|
|
|
weston_compositor_schedule_repaint(shsurf->surface->compositor);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rotate_grab_button(struct weston_pointer_grab *grab,
|
|
|
|
uint32_t time, uint32_t button, uint32_t state_w)
|
|
|
|
{
|
|
|
|
struct rotate_grab *rotate =
|
|
|
|
container_of(grab, struct rotate_grab, base.grab);
|
|
|
|
struct weston_pointer *pointer = grab->pointer;
|
|
|
|
struct shell_surface *shsurf = rotate->base.shsurf;
|
|
|
|
enum wl_pointer_button_state state = state_w;
|
|
|
|
|
|
|
|
if (pointer->button_count == 0 &&
|
|
|
|
state == WL_POINTER_BUTTON_STATE_RELEASED) {
|
|
|
|
if (shsurf)
|
|
|
|
weston_matrix_multiply(&shsurf->rotation.rotation,
|
|
|
|
&rotate->rotation);
|
|
|
|
shell_grab_end(&rotate->base);
|
|
|
|
free(rotate);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rotate_grab_cancel(struct weston_pointer_grab *grab)
|
|
|
|
{
|
|
|
|
struct rotate_grab *rotate =
|
|
|
|
container_of(grab, struct rotate_grab, base.grab);
|
|
|
|
|
|
|
|
shell_grab_end(&rotate->base);
|
|
|
|
free(rotate);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct weston_pointer_grab_interface rotate_grab_interface = {
|
|
|
|
noop_grab_focus,
|
|
|
|
rotate_grab_motion,
|
|
|
|
rotate_grab_button,
|
|
|
|
noop_grab_axis,
|
|
|
|
noop_grab_axis_source,
|
|
|
|
noop_grab_frame,
|
|
|
|
rotate_grab_cancel,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
surface_rotate(struct shell_surface *surface, struct weston_pointer *pointer)
|
|
|
|
{
|
|
|
|
struct rotate_grab *rotate;
|
|
|
|
float dx, dy;
|
|
|
|
float r;
|
|
|
|
|
|
|
|
surface = find_toplevel_surface(surface);
|
|
|
|
|
|
|
|
rotate = malloc(sizeof *rotate);
|
|
|
|
if (!rotate)
|
|
|
|
return;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_to_global_float(surface->view,
|
|
|
|
surface->surface->width * 0.5f,
|
|
|
|
surface->surface->height * 0.5f,
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
&rotate->center.x, &rotate->center.y);
|
|
|
|
|
|
|
|
dx = wl_fixed_to_double(pointer->x) - rotate->center.x;
|
|
|
|
dy = wl_fixed_to_double(pointer->y) - rotate->center.y;
|
|
|
|
r = sqrtf(dx * dx + dy * dy);
|
|
|
|
if (r > 20.0f) {
|
|
|
|
struct weston_matrix inverse;
|
|
|
|
|
|
|
|
weston_matrix_init(&inverse);
|
|
|
|
weston_matrix_rotate_xy(&inverse, dx / r, -dy / r);
|
|
|
|
weston_matrix_multiply(&surface->rotation.rotation, &inverse);
|
|
|
|
|
|
|
|
weston_matrix_init(&rotate->rotation);
|
|
|
|
weston_matrix_rotate_xy(&rotate->rotation, dx / r, dy / r);
|
|
|
|
} else {
|
|
|
|
weston_matrix_init(&surface->rotation.rotation);
|
|
|
|
weston_matrix_init(&rotate->rotation);
|
|
|
|
}
|
|
|
|
|
|
|
|
shell_grab_start(&rotate->base, &rotate_grab_interface, surface,
|
|
|
|
pointer, WESTON_DESKTOP_SHELL_CURSOR_ARROW);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rotate_binding(struct weston_pointer *pointer, uint32_t time, uint32_t button,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
struct weston_surface *focus;
|
shell: keyboard focus and restacking fixes for sub-surfaces
The shell needs to redirect some actions to the parent surface, when
they originally target a sub-surface. This patch implements the
following:
- Move, resize, and rotate bindings always target the parent surface.
- Opacity (full-surface alpha) binding targets the parent surface. This
is broken, because it should change the opacity of the whole compound
window, which is difficult to implement in the renderer.
- click_to_activate_binding() needs to check the shell surface type from
the main surface, because sub-surface would produce SHELL_SURFACE_NONE
and prevent activation.
- Also activate() needs to check the type from the main surface, and
restack the main surface. Keyboard focus is assigned to the original
(sub-)surface.
- focus_state_surface_destroy() needs to handle sub-surfaces: only the
main surface will be in a layer list. If the destroyed surface is
indeed a sub-surface, activate the main surface next. This way a
client that destroys a focused sub-surface still retains focus in the
same window.
- The workspace_manager.move_surface request can accept also
sub-surfaces, and it will move the corresponding main surface.
Changes in v2:
- do not special-case keyboard focus for sub-surfaces
- fix surface type checks for sub-surfaces in shell, fix restacking of
sub-surfaces in shell, fix focus_state_surface_destroy()
Changes in v3:
- Renamed weston_surface_get_parent() to
weston_surface_get_main_surface() to be more explicit that this is
about sub-surfaces
- Fixed move_surface_to_workspace() to handle keyboard focus on a
sub-surface.
- Used a temporary variable in several places to clarify code, instead
of reassigning a variable.
- Fixed workspace_manager_move_surface() to deal with sub-surfaces.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
12 years ago
|
|
|
struct weston_surface *base_surface;
|
|
|
|
struct shell_surface *surface;
|
|
|
|
|
|
|
|
if (pointer->focus == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
focus = pointer->focus->surface;
|
|
|
|
|
shell: keyboard focus and restacking fixes for sub-surfaces
The shell needs to redirect some actions to the parent surface, when
they originally target a sub-surface. This patch implements the
following:
- Move, resize, and rotate bindings always target the parent surface.
- Opacity (full-surface alpha) binding targets the parent surface. This
is broken, because it should change the opacity of the whole compound
window, which is difficult to implement in the renderer.
- click_to_activate_binding() needs to check the shell surface type from
the main surface, because sub-surface would produce SHELL_SURFACE_NONE
and prevent activation.
- Also activate() needs to check the type from the main surface, and
restack the main surface. Keyboard focus is assigned to the original
(sub-)surface.
- focus_state_surface_destroy() needs to handle sub-surfaces: only the
main surface will be in a layer list. If the destroyed surface is
indeed a sub-surface, activate the main surface next. This way a
client that destroys a focused sub-surface still retains focus in the
same window.
- The workspace_manager.move_surface request can accept also
sub-surfaces, and it will move the corresponding main surface.
Changes in v2:
- do not special-case keyboard focus for sub-surfaces
- fix surface type checks for sub-surfaces in shell, fix restacking of
sub-surfaces in shell, fix focus_state_surface_destroy()
Changes in v3:
- Renamed weston_surface_get_parent() to
weston_surface_get_main_surface() to be more explicit that this is
about sub-surfaces
- Fixed move_surface_to_workspace() to handle keyboard focus on a
sub-surface.
- Used a temporary variable in several places to clarify code, instead
of reassigning a variable.
- Fixed workspace_manager_move_surface() to deal with sub-surfaces.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
12 years ago
|
|
|
base_surface = weston_surface_get_main_surface(focus);
|
|
|
|
if (base_surface == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
surface = get_shell_surface(base_surface);
|
|
|
|
if (surface == NULL || surface->state.fullscreen ||
|
|
|
|
surface->state.maximized)
|
|
|
|
return;
|
|
|
|
|
|
|
|
surface_rotate(surface, pointer);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Move all fullscreen layers down to the current workspace and hide their
|
|
|
|
* black views. The surfaces' state is set to both fullscreen and lowered,
|
|
|
|
* and this is reversed when such a surface is re-configured, see
|
|
|
|
* shell_configure_fullscreen() and shell_ensure_fullscreen_black_view().
|
|
|
|
*
|
|
|
|
* lowering_output = NULL - Lower on all outputs, else only lower on the
|
|
|
|
* specified output.
|
|
|
|
*
|
|
|
|
* This should be used when implementing shell-wide overlays, such as
|
|
|
|
* the alt-tab switcher, which need to de-promote fullscreen layers. */
|
|
|
|
void
|
|
|
|
lower_fullscreen_layer(struct desktop_shell *shell,
|
|
|
|
struct weston_output *lowering_output)
|
|
|
|
{
|
|
|
|
struct workspace *ws;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *view, *prev;
|
|
|
|
|
|
|
|
ws = get_current_workspace(shell);
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
wl_list_for_each_reverse_safe(view, prev,
|
|
|
|
&shell->fullscreen_layer.view_list.link,
|
|
|
|
layer_link.link) {
|
|
|
|
struct shell_surface *shsurf = get_shell_surface(view->surface);
|
|
|
|
|
|
|
|
if (!shsurf)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Only lower surfaces which have lowering_output as their fullscreen
|
|
|
|
* output, unless a NULL output asks for lowering on all outputs.
|
|
|
|
*/
|
|
|
|
if (lowering_output && (shsurf->fullscreen_output != lowering_output))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* We can have a non-fullscreen popup for a fullscreen surface
|
|
|
|
* in the fullscreen layer. */
|
|
|
|
if (shsurf->state.fullscreen) {
|
|
|
|
/* Hide the black view */
|
|
|
|
weston_layer_entry_remove(&shsurf->fullscreen.black_view->layer_link);
|
|
|
|
wl_list_init(&shsurf->fullscreen.black_view->layer_link.link);
|
|
|
|
weston_view_damage_below(shsurf->fullscreen.black_view);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Lower the view to the workspace layer */
|
|
|
|
weston_layer_entry_remove(&view->layer_link);
|
|
|
|
weston_layer_entry_insert(&ws->layer.view_list, &view->layer_link);
|
|
|
|
weston_view_damage_below(view);
|
|
|
|
weston_surface_damage(view->surface);
|
|
|
|
|
|
|
|
shsurf->state.lowered = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
activate(struct desktop_shell *shell, struct weston_surface *es,
|
|
|
|
struct weston_seat *seat, bool configure)
|
|
|
|
{
|
shell: keyboard focus and restacking fixes for sub-surfaces
The shell needs to redirect some actions to the parent surface, when
they originally target a sub-surface. This patch implements the
following:
- Move, resize, and rotate bindings always target the parent surface.
- Opacity (full-surface alpha) binding targets the parent surface. This
is broken, because it should change the opacity of the whole compound
window, which is difficult to implement in the renderer.
- click_to_activate_binding() needs to check the shell surface type from
the main surface, because sub-surface would produce SHELL_SURFACE_NONE
and prevent activation.
- Also activate() needs to check the type from the main surface, and
restack the main surface. Keyboard focus is assigned to the original
(sub-)surface.
- focus_state_surface_destroy() needs to handle sub-surfaces: only the
main surface will be in a layer list. If the destroyed surface is
indeed a sub-surface, activate the main surface next. This way a
client that destroys a focused sub-surface still retains focus in the
same window.
- The workspace_manager.move_surface request can accept also
sub-surfaces, and it will move the corresponding main surface.
Changes in v2:
- do not special-case keyboard focus for sub-surfaces
- fix surface type checks for sub-surfaces in shell, fix restacking of
sub-surfaces in shell, fix focus_state_surface_destroy()
Changes in v3:
- Renamed weston_surface_get_parent() to
weston_surface_get_main_surface() to be more explicit that this is
about sub-surfaces
- Fixed move_surface_to_workspace() to handle keyboard focus on a
sub-surface.
- Used a temporary variable in several places to clarify code, instead
of reassigning a variable.
- Fixed workspace_manager_move_surface() to deal with sub-surfaces.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
12 years ago
|
|
|
struct weston_surface *main_surface;
|
|
|
|
struct focus_state *state;
|
|
|
|
struct workspace *ws;
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
struct weston_surface *old_es;
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
|
shell: keyboard focus and restacking fixes for sub-surfaces
The shell needs to redirect some actions to the parent surface, when
they originally target a sub-surface. This patch implements the
following:
- Move, resize, and rotate bindings always target the parent surface.
- Opacity (full-surface alpha) binding targets the parent surface. This
is broken, because it should change the opacity of the whole compound
window, which is difficult to implement in the renderer.
- click_to_activate_binding() needs to check the shell surface type from
the main surface, because sub-surface would produce SHELL_SURFACE_NONE
and prevent activation.
- Also activate() needs to check the type from the main surface, and
restack the main surface. Keyboard focus is assigned to the original
(sub-)surface.
- focus_state_surface_destroy() needs to handle sub-surfaces: only the
main surface will be in a layer list. If the destroyed surface is
indeed a sub-surface, activate the main surface next. This way a
client that destroys a focused sub-surface still retains focus in the
same window.
- The workspace_manager.move_surface request can accept also
sub-surfaces, and it will move the corresponding main surface.
Changes in v2:
- do not special-case keyboard focus for sub-surfaces
- fix surface type checks for sub-surfaces in shell, fix restacking of
sub-surfaces in shell, fix focus_state_surface_destroy()
Changes in v3:
- Renamed weston_surface_get_parent() to
weston_surface_get_main_surface() to be more explicit that this is
about sub-surfaces
- Fixed move_surface_to_workspace() to handle keyboard focus on a
sub-surface.
- Used a temporary variable in several places to clarify code, instead
of reassigning a variable.
- Fixed workspace_manager_move_surface() to deal with sub-surfaces.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
12 years ago
|
|
|
main_surface = weston_surface_get_main_surface(es);
|
|
|
|
shsurf = get_shell_surface(main_surface);
|
|
|
|
assert(shsurf);
|
|
|
|
|
|
|
|
/* Only demote fullscreen surfaces on the output of activated shsurf.
|
|
|
|
* Leave fullscreen surfaces on unrelated outputs alone. */
|
|
|
|
lower_fullscreen_layer(shell, shsurf->output);
|
shell: keyboard focus and restacking fixes for sub-surfaces
The shell needs to redirect some actions to the parent surface, when
they originally target a sub-surface. This patch implements the
following:
- Move, resize, and rotate bindings always target the parent surface.
- Opacity (full-surface alpha) binding targets the parent surface. This
is broken, because it should change the opacity of the whole compound
window, which is difficult to implement in the renderer.
- click_to_activate_binding() needs to check the shell surface type from
the main surface, because sub-surface would produce SHELL_SURFACE_NONE
and prevent activation.
- Also activate() needs to check the type from the main surface, and
restack the main surface. Keyboard focus is assigned to the original
(sub-)surface.
- focus_state_surface_destroy() needs to handle sub-surfaces: only the
main surface will be in a layer list. If the destroyed surface is
indeed a sub-surface, activate the main surface next. This way a
client that destroys a focused sub-surface still retains focus in the
same window.
- The workspace_manager.move_surface request can accept also
sub-surfaces, and it will move the corresponding main surface.
Changes in v2:
- do not special-case keyboard focus for sub-surfaces
- fix surface type checks for sub-surfaces in shell, fix restacking of
sub-surfaces in shell, fix focus_state_surface_destroy()
Changes in v3:
- Renamed weston_surface_get_parent() to
weston_surface_get_main_surface() to be more explicit that this is
about sub-surfaces
- Fixed move_surface_to_workspace() to handle keyboard focus on a
sub-surface.
- Used a temporary variable in several places to clarify code, instead
of reassigning a variable.
- Fixed workspace_manager_move_surface() to deal with sub-surfaces.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
12 years ago
|
|
|
|
|
|
|
weston_surface_activate(es, seat);
|
|
|
|
|
|
|
|
state = ensure_focus_state(shell, seat);
|
|
|
|
if (state == NULL)
|
|
|
|
return;
|
|
|
|
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
old_es = state->keyboard_focus;
|
|
|
|
focus_state_set_focus(state, es);
|
|
|
|
|
|
|
|
if (shsurf->state.fullscreen && configure)
|
|
|
|
shell_configure_fullscreen(shsurf);
|
|
|
|
else
|
|
|
|
restore_output_mode(shsurf->output);
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
|
|
|
|
/* Update the surface’s layer. This brings it to the top of the stacking
|
|
|
|
* order as appropriate. */
|
|
|
|
shell_surface_update_layer(shsurf);
|
|
|
|
|
|
|
|
if (shell->focus_animation_type != ANIMATION_NONE) {
|
|
|
|
ws = get_current_workspace(shell);
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
animate_focus_change(shell, ws, get_default_view(old_es), get_default_view(es));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* no-op func for checking black surface */
|
|
|
|
static void
|
|
|
|
black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
is_black_surface (struct weston_surface *es, struct weston_surface **fs_surface)
|
|
|
|
{
|
|
|
|
if (es->configure == black_surface_configure) {
|
|
|
|
if (fs_surface)
|
|
|
|
*fs_surface = (struct weston_surface *)es->configure_private;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
activate_binding(struct weston_seat *seat,
|
|
|
|
struct desktop_shell *shell,
|
|
|
|
struct weston_view *focus_view)
|
|
|
|
{
|
|
|
|
struct focus_state *state;
|
|
|
|
struct weston_surface *focus;
|
shell: keyboard focus and restacking fixes for sub-surfaces
The shell needs to redirect some actions to the parent surface, when
they originally target a sub-surface. This patch implements the
following:
- Move, resize, and rotate bindings always target the parent surface.
- Opacity (full-surface alpha) binding targets the parent surface. This
is broken, because it should change the opacity of the whole compound
window, which is difficult to implement in the renderer.
- click_to_activate_binding() needs to check the shell surface type from
the main surface, because sub-surface would produce SHELL_SURFACE_NONE
and prevent activation.
- Also activate() needs to check the type from the main surface, and
restack the main surface. Keyboard focus is assigned to the original
(sub-)surface.
- focus_state_surface_destroy() needs to handle sub-surfaces: only the
main surface will be in a layer list. If the destroyed surface is
indeed a sub-surface, activate the main surface next. This way a
client that destroys a focused sub-surface still retains focus in the
same window.
- The workspace_manager.move_surface request can accept also
sub-surfaces, and it will move the corresponding main surface.
Changes in v2:
- do not special-case keyboard focus for sub-surfaces
- fix surface type checks for sub-surfaces in shell, fix restacking of
sub-surfaces in shell, fix focus_state_surface_destroy()
Changes in v3:
- Renamed weston_surface_get_parent() to
weston_surface_get_main_surface() to be more explicit that this is
about sub-surfaces
- Fixed move_surface_to_workspace() to handle keyboard focus on a
sub-surface.
- Used a temporary variable in several places to clarify code, instead
of reassigning a variable.
- Fixed workspace_manager_move_surface() to deal with sub-surfaces.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
12 years ago
|
|
|
struct weston_surface *main_surface;
|
|
|
|
|
|
|
|
focus = focus_view->surface;
|
|
|
|
|
shell: keyboard focus and restacking fixes for sub-surfaces
The shell needs to redirect some actions to the parent surface, when
they originally target a sub-surface. This patch implements the
following:
- Move, resize, and rotate bindings always target the parent surface.
- Opacity (full-surface alpha) binding targets the parent surface. This
is broken, because it should change the opacity of the whole compound
window, which is difficult to implement in the renderer.
- click_to_activate_binding() needs to check the shell surface type from
the main surface, because sub-surface would produce SHELL_SURFACE_NONE
and prevent activation.
- Also activate() needs to check the type from the main surface, and
restack the main surface. Keyboard focus is assigned to the original
(sub-)surface.
- focus_state_surface_destroy() needs to handle sub-surfaces: only the
main surface will be in a layer list. If the destroyed surface is
indeed a sub-surface, activate the main surface next. This way a
client that destroys a focused sub-surface still retains focus in the
same window.
- The workspace_manager.move_surface request can accept also
sub-surfaces, and it will move the corresponding main surface.
Changes in v2:
- do not special-case keyboard focus for sub-surfaces
- fix surface type checks for sub-surfaces in shell, fix restacking of
sub-surfaces in shell, fix focus_state_surface_destroy()
Changes in v3:
- Renamed weston_surface_get_parent() to
weston_surface_get_main_surface() to be more explicit that this is
about sub-surfaces
- Fixed move_surface_to_workspace() to handle keyboard focus on a
sub-surface.
- Used a temporary variable in several places to clarify code, instead
of reassigning a variable.
- Fixed workspace_manager_move_surface() to deal with sub-surfaces.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
12 years ago
|
|
|
if (is_black_surface(focus, &main_surface))
|
|
|
|
focus = main_surface;
|
|
|
|
|
shell: keyboard focus and restacking fixes for sub-surfaces
The shell needs to redirect some actions to the parent surface, when
they originally target a sub-surface. This patch implements the
following:
- Move, resize, and rotate bindings always target the parent surface.
- Opacity (full-surface alpha) binding targets the parent surface. This
is broken, because it should change the opacity of the whole compound
window, which is difficult to implement in the renderer.
- click_to_activate_binding() needs to check the shell surface type from
the main surface, because sub-surface would produce SHELL_SURFACE_NONE
and prevent activation.
- Also activate() needs to check the type from the main surface, and
restack the main surface. Keyboard focus is assigned to the original
(sub-)surface.
- focus_state_surface_destroy() needs to handle sub-surfaces: only the
main surface will be in a layer list. If the destroyed surface is
indeed a sub-surface, activate the main surface next. This way a
client that destroys a focused sub-surface still retains focus in the
same window.
- The workspace_manager.move_surface request can accept also
sub-surfaces, and it will move the corresponding main surface.
Changes in v2:
- do not special-case keyboard focus for sub-surfaces
- fix surface type checks for sub-surfaces in shell, fix restacking of
sub-surfaces in shell, fix focus_state_surface_destroy()
Changes in v3:
- Renamed weston_surface_get_parent() to
weston_surface_get_main_surface() to be more explicit that this is
about sub-surfaces
- Fixed move_surface_to_workspace() to handle keyboard focus on a
sub-surface.
- Used a temporary variable in several places to clarify code, instead
of reassigning a variable.
- Fixed workspace_manager_move_surface() to deal with sub-surfaces.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
12 years ago
|
|
|
main_surface = weston_surface_get_main_surface(focus);
|
|
|
|
if (get_shell_surface_type(main_surface) == SHELL_SURFACE_NONE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
state = ensure_focus_state(shell, seat);
|
|
|
|
if (state == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (state->keyboard_focus == focus)
|
|
|
|
return;
|
|
|
|
|
|
|
|
activate(shell, focus, seat, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
click_to_activate_binding(struct weston_pointer *pointer, uint32_t time,
|
|
|
|
uint32_t button, void *data)
|
|
|
|
{
|
|
|
|
if (pointer->grab != &pointer->default_grab)
|
|
|
|
return;
|
|
|
|
if (pointer->focus == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
activate_binding(pointer->seat, data, pointer->focus);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
touch_to_activate_binding(struct weston_touch *touch, uint32_t time,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
if (touch->grab != &touch->default_grab)
|
|
|
|
return;
|
|
|
|
if (touch->focus == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
activate_binding(touch->seat, data, touch->focus);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
unfocus_all_seats(struct desktop_shell *shell)
|
|
|
|
{
|
|
|
|
struct weston_seat *seat, *next;
|
|
|
|
|
|
|
|
wl_list_for_each_safe(seat, next, &shell->compositor->seat_list, link) {
|
|
|
|
struct weston_keyboard *keyboard =
|
|
|
|
weston_seat_get_keyboard(seat);
|
|
|
|
|
|
|
|
if (!keyboard)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
weston_keyboard_set_focus(keyboard, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
lock(struct desktop_shell *shell)
|
|
|
|
{
|
|
|
|
struct workspace *ws = get_current_workspace(shell);
|
|
|
|
|
|
|
|
if (shell->locked) {
|
|
|
|
weston_compositor_sleep(shell->compositor);
|
|
|
|
return;
|
|
|
|
}
|
desktop-shell: screen locking protocol
Add protocol and functions for supporting screen locking, triggered by
activity timeout.
After activity timeout, compositor starts the fade to black, and then
enters SLEEPING state. At that point it calls lock() in the shell
plugin.
When input events trigger a wakeup, unlock() in the shell plugin is
called. This sends prepare_lock_surface event to the desktop-shell
client. The screen stays locked while the compositor starts fade-in.
At this point, desktop-shell client usually creates a surface for the
unlocking GUI (e.g. a password prompt), and sends it with the
set_lock_surface request. The compositor supposedly shows and allows
interaction only with the given lock surface (not yet implemented).
When desktop-shell has authenticated the user, or instead of issuing
set_lock_surface, it sends the unlock request. Upon receiving the unlock
request, the shell plugin unlocks the screen.
If desktop-shell client dies, the screen is unlocked automatically.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
13 years ago
|
|
|
|
|
|
|
shell->locked = true;
|
|
|
|
|
|
|
|
/* Hide all surfaces by removing the fullscreen, panel and
|
|
|
|
* toplevel layers. This way nothing else can show or receive
|
|
|
|
* input events while we are locked. */
|
|
|
|
|
|
|
|
wl_list_remove(&shell->panel_layer.link);
|
|
|
|
wl_list_remove(&shell->fullscreen_layer.link);
|
|
|
|
if (shell->showing_input_panels)
|
|
|
|
wl_list_remove(&shell->input_panel_layer.link);
|
|
|
|
wl_list_remove(&ws->layer.link);
|
|
|
|
wl_list_insert(&shell->compositor->cursor_layer.link,
|
|
|
|
&shell->lock_layer.link);
|
|
|
|
|
|
|
|
weston_compositor_sleep(shell->compositor);
|
|
|
|
|
|
|
|
/* Remove the keyboard focus on all seats. This will be
|
|
|
|
* restored to the workspace's saved state via
|
|
|
|
* restore_focus_state when the compositor is unlocked */
|
|
|
|
unfocus_all_seats(shell);
|
|
|
|
|
|
|
|
/* TODO: disable bindings that should not work while locked. */
|
|
|
|
|
|
|
|
/* All this must be undone in resume_desktop(). */
|
desktop-shell: screen locking protocol
Add protocol and functions for supporting screen locking, triggered by
activity timeout.
After activity timeout, compositor starts the fade to black, and then
enters SLEEPING state. At that point it calls lock() in the shell
plugin.
When input events trigger a wakeup, unlock() in the shell plugin is
called. This sends prepare_lock_surface event to the desktop-shell
client. The screen stays locked while the compositor starts fade-in.
At this point, desktop-shell client usually creates a surface for the
unlocking GUI (e.g. a password prompt), and sends it with the
set_lock_surface request. The compositor supposedly shows and allows
interaction only with the given lock surface (not yet implemented).
When desktop-shell has authenticated the user, or instead of issuing
set_lock_surface, it sends the unlock request. Upon receiving the unlock
request, the shell plugin unlocks the screen.
If desktop-shell client dies, the screen is unlocked automatically.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
13 years ago
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
unlock(struct desktop_shell *shell)
|
desktop-shell: screen locking protocol
Add protocol and functions for supporting screen locking, triggered by
activity timeout.
After activity timeout, compositor starts the fade to black, and then
enters SLEEPING state. At that point it calls lock() in the shell
plugin.
When input events trigger a wakeup, unlock() in the shell plugin is
called. This sends prepare_lock_surface event to the desktop-shell
client. The screen stays locked while the compositor starts fade-in.
At this point, desktop-shell client usually creates a surface for the
unlocking GUI (e.g. a password prompt), and sends it with the
set_lock_surface request. The compositor supposedly shows and allows
interaction only with the given lock surface (not yet implemented).
When desktop-shell has authenticated the user, or instead of issuing
set_lock_surface, it sends the unlock request. Upon receiving the unlock
request, the shell plugin unlocks the screen.
If desktop-shell client dies, the screen is unlocked automatically.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
13 years ago
|
|
|
{
|
|
|
|
struct wl_resource *shell_resource;
|
|
|
|
|
|
|
|
if (!shell->locked || shell->lock_surface) {
|
|
|
|
shell_fade(shell, FADE_IN);
|
desktop-shell: screen locking protocol
Add protocol and functions for supporting screen locking, triggered by
activity timeout.
After activity timeout, compositor starts the fade to black, and then
enters SLEEPING state. At that point it calls lock() in the shell
plugin.
When input events trigger a wakeup, unlock() in the shell plugin is
called. This sends prepare_lock_surface event to the desktop-shell
client. The screen stays locked while the compositor starts fade-in.
At this point, desktop-shell client usually creates a surface for the
unlocking GUI (e.g. a password prompt), and sends it with the
set_lock_surface request. The compositor supposedly shows and allows
interaction only with the given lock surface (not yet implemented).
When desktop-shell has authenticated the user, or instead of issuing
set_lock_surface, it sends the unlock request. Upon receiving the unlock
request, the shell plugin unlocks the screen.
If desktop-shell client dies, the screen is unlocked automatically.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
13 years ago
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If desktop-shell client has gone away, unlock immediately. */
|
|
|
|
if (!shell->child.desktop_shell) {
|
|
|
|
resume_desktop(shell);
|
desktop-shell: screen locking protocol
Add protocol and functions for supporting screen locking, triggered by
activity timeout.
After activity timeout, compositor starts the fade to black, and then
enters SLEEPING state. At that point it calls lock() in the shell
plugin.
When input events trigger a wakeup, unlock() in the shell plugin is
called. This sends prepare_lock_surface event to the desktop-shell
client. The screen stays locked while the compositor starts fade-in.
At this point, desktop-shell client usually creates a surface for the
unlocking GUI (e.g. a password prompt), and sends it with the
set_lock_surface request. The compositor supposedly shows and allows
interaction only with the given lock surface (not yet implemented).
When desktop-shell has authenticated the user, or instead of issuing
set_lock_surface, it sends the unlock request. Upon receiving the unlock
request, the shell plugin unlocks the screen.
If desktop-shell client dies, the screen is unlocked automatically.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
13 years ago
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (shell->prepare_event_sent)
|
|
|
|
return;
|
|
|
|
|
|
|
|
shell_resource = shell->child.desktop_shell;
|
|
|
|
weston_desktop_shell_send_prepare_lock_surface(shell_resource);
|
desktop-shell: screen locking protocol
Add protocol and functions for supporting screen locking, triggered by
activity timeout.
After activity timeout, compositor starts the fade to black, and then
enters SLEEPING state. At that point it calls lock() in the shell
plugin.
When input events trigger a wakeup, unlock() in the shell plugin is
called. This sends prepare_lock_surface event to the desktop-shell
client. The screen stays locked while the compositor starts fade-in.
At this point, desktop-shell client usually creates a surface for the
unlocking GUI (e.g. a password prompt), and sends it with the
set_lock_surface request. The compositor supposedly shows and allows
interaction only with the given lock surface (not yet implemented).
When desktop-shell has authenticated the user, or instead of issuing
set_lock_surface, it sends the unlock request. Upon receiving the unlock
request, the shell plugin unlocks the screen.
If desktop-shell client dies, the screen is unlocked automatically.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
13 years ago
|
|
|
shell->prepare_event_sent = true;
|
|
|
|
}
|
|
|
|
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
static void
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
shell_fade_done(struct weston_view_animation *animation, void *data)
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
{
|
|
|
|
struct desktop_shell *shell = data;
|
|
|
|
|
|
|
|
shell->fade.animation = NULL;
|
|
|
|
|
|
|
|
switch (shell->fade.type) {
|
|
|
|
case FADE_IN:
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_surface_destroy(shell->fade.view->surface);
|
|
|
|
shell->fade.view = NULL;
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
break;
|
|
|
|
case FADE_OUT:
|
|
|
|
lock(shell);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
static struct weston_view *
|
shell: wait for desktop-shell init before fade in
On Raspberry Pi, weston-desktop-shell is so slow to start, that the
compositor has time to run the fade-in before the wallpaper is up. The
user launching Weston sees the screen flipping to black, the fbcon
fading in, and then the desktop popping up.
To fix this, wait for the weston-desktop-shell to draw
everything before starting the initial fade-in. A new request is
added to the private desktop-shell protocol to signal it. If a
desktop-shell client does not support the new request, the fade-in
happens already at bind time.
If weston-desktop-shell crashes, or does not send the 'desktop_ready'
request in 15 seconds, the compositor will fade in anyway. This should
avoid a blocked screen in case weston-desktop-shell malfunction.
shell_fade_startup() does not directly start the fade-in but schedules
an idle callback, so that the compositor can process all pending events
before starting the fade clock. Otherwise (on RPi) we risk skipping part
of the animation. Yes, it is a hack, that should have been done in
window.c and weston-desktop-shell instead.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
12 years ago
|
|
|
shell_fade_create_surface(struct desktop_shell *shell)
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
{
|
|
|
|
struct weston_compositor *compositor = shell->compositor;
|
|
|
|
struct weston_surface *surface;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *view;
|
shell: wait for desktop-shell init before fade in
On Raspberry Pi, weston-desktop-shell is so slow to start, that the
compositor has time to run the fade-in before the wallpaper is up. The
user launching Weston sees the screen flipping to black, the fbcon
fading in, and then the desktop popping up.
To fix this, wait for the weston-desktop-shell to draw
everything before starting the initial fade-in. A new request is
added to the private desktop-shell protocol to signal it. If a
desktop-shell client does not support the new request, the fade-in
happens already at bind time.
If weston-desktop-shell crashes, or does not send the 'desktop_ready'
request in 15 seconds, the compositor will fade in anyway. This should
avoid a blocked screen in case weston-desktop-shell malfunction.
shell_fade_startup() does not directly start the fade-in but schedules
an idle callback, so that the compositor can process all pending events
before starting the fade clock. Otherwise (on RPi) we risk skipping part
of the animation. Yes, it is a hack, that should have been done in
window.c and weston-desktop-shell instead.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
12 years ago
|
|
|
|
|
|
|
surface = weston_surface_create(compositor);
|
|
|
|
if (!surface)
|
|
|
|
return NULL;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
view = weston_view_create(surface);
|
|
|
|
if (!view) {
|
|
|
|
weston_surface_destroy(surface);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
weston_surface_set_size(surface, 8192, 8192);
|
|
|
|
weston_view_set_position(view, 0, 0);
|
shell: wait for desktop-shell init before fade in
On Raspberry Pi, weston-desktop-shell is so slow to start, that the
compositor has time to run the fade-in before the wallpaper is up. The
user launching Weston sees the screen flipping to black, the fbcon
fading in, and then the desktop popping up.
To fix this, wait for the weston-desktop-shell to draw
everything before starting the initial fade-in. A new request is
added to the private desktop-shell protocol to signal it. If a
desktop-shell client does not support the new request, the fade-in
happens already at bind time.
If weston-desktop-shell crashes, or does not send the 'desktop_ready'
request in 15 seconds, the compositor will fade in anyway. This should
avoid a blocked screen in case weston-desktop-shell malfunction.
shell_fade_startup() does not directly start the fade-in but schedules
an idle callback, so that the compositor can process all pending events
before starting the fade clock. Otherwise (on RPi) we risk skipping part
of the animation. Yes, it is a hack, that should have been done in
window.c and weston-desktop-shell instead.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
12 years ago
|
|
|
weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0);
|
|
|
|
weston_layer_entry_insert(&compositor->fade_layer.view_list,
|
|
|
|
&view->layer_link);
|
shell: wait for desktop-shell init before fade in
On Raspberry Pi, weston-desktop-shell is so slow to start, that the
compositor has time to run the fade-in before the wallpaper is up. The
user launching Weston sees the screen flipping to black, the fbcon
fading in, and then the desktop popping up.
To fix this, wait for the weston-desktop-shell to draw
everything before starting the initial fade-in. A new request is
added to the private desktop-shell protocol to signal it. If a
desktop-shell client does not support the new request, the fade-in
happens already at bind time.
If weston-desktop-shell crashes, or does not send the 'desktop_ready'
request in 15 seconds, the compositor will fade in anyway. This should
avoid a blocked screen in case weston-desktop-shell malfunction.
shell_fade_startup() does not directly start the fade-in but schedules
an idle callback, so that the compositor can process all pending events
before starting the fade clock. Otherwise (on RPi) we risk skipping part
of the animation. Yes, it is a hack, that should have been done in
window.c and weston-desktop-shell instead.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
12 years ago
|
|
|
pixman_region32_init(&surface->input);
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
return view;
|
shell: wait for desktop-shell init before fade in
On Raspberry Pi, weston-desktop-shell is so slow to start, that the
compositor has time to run the fade-in before the wallpaper is up. The
user launching Weston sees the screen flipping to black, the fbcon
fading in, and then the desktop popping up.
To fix this, wait for the weston-desktop-shell to draw
everything before starting the initial fade-in. A new request is
added to the private desktop-shell protocol to signal it. If a
desktop-shell client does not support the new request, the fade-in
happens already at bind time.
If weston-desktop-shell crashes, or does not send the 'desktop_ready'
request in 15 seconds, the compositor will fade in anyway. This should
avoid a blocked screen in case weston-desktop-shell malfunction.
shell_fade_startup() does not directly start the fade-in but schedules
an idle callback, so that the compositor can process all pending events
before starting the fade clock. Otherwise (on RPi) we risk skipping part
of the animation. Yes, it is a hack, that should have been done in
window.c and weston-desktop-shell instead.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
12 years ago
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_fade(struct desktop_shell *shell, enum fade_type type)
|
|
|
|
{
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
float tint;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case FADE_IN:
|
|
|
|
tint = 0.0;
|
|
|
|
break;
|
|
|
|
case FADE_OUT:
|
|
|
|
tint = 1.0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
weston_log("shell: invalid fade type\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
shell->fade.type = type;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
if (shell->fade.view == NULL) {
|
|
|
|
shell->fade.view = shell_fade_create_surface(shell);
|
|
|
|
if (!shell->fade.view)
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
return;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
shell->fade.view->alpha = 1.0 - tint;
|
|
|
|
weston_view_update_transform(shell->fade.view);
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
}
|
|
|
|
|
|
|
|
if (shell->fade.view->output == NULL) {
|
|
|
|
/* If the black view gets a NULL output, we lost the
|
|
|
|
* last output and we'll just cancel the fade. This
|
|
|
|
* happens when you close the last window under the
|
|
|
|
* X11 or Wayland backends. */
|
|
|
|
shell->locked = false;
|
|
|
|
weston_surface_destroy(shell->fade.view->surface);
|
|
|
|
shell->fade.view = NULL;
|
|
|
|
} else if (shell->fade.animation) {
|
|
|
|
weston_fade_update(shell->fade.animation, tint);
|
|
|
|
} else {
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
shell->fade.animation =
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_fade_run(shell->fade.view,
|
|
|
|
1.0 - tint, tint, 300.0,
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
shell_fade_done, shell);
|
|
|
|
}
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
}
|
|
|
|
|
shell: wait for desktop-shell init before fade in
On Raspberry Pi, weston-desktop-shell is so slow to start, that the
compositor has time to run the fade-in before the wallpaper is up. The
user launching Weston sees the screen flipping to black, the fbcon
fading in, and then the desktop popping up.
To fix this, wait for the weston-desktop-shell to draw
everything before starting the initial fade-in. A new request is
added to the private desktop-shell protocol to signal it. If a
desktop-shell client does not support the new request, the fade-in
happens already at bind time.
If weston-desktop-shell crashes, or does not send the 'desktop_ready'
request in 15 seconds, the compositor will fade in anyway. This should
avoid a blocked screen in case weston-desktop-shell malfunction.
shell_fade_startup() does not directly start the fade-in but schedules
an idle callback, so that the compositor can process all pending events
before starting the fade clock. Otherwise (on RPi) we risk skipping part
of the animation. Yes, it is a hack, that should have been done in
window.c and weston-desktop-shell instead.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
12 years ago
|
|
|
static void
|
|
|
|
do_shell_fade_startup(void *data)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = data;
|
|
|
|
|
|
|
|
if (shell->startup_animation_type == ANIMATION_FADE) {
|
|
|
|
shell_fade(shell, FADE_IN);
|
|
|
|
} else {
|
|
|
|
weston_log("desktop shell: "
|
|
|
|
"unexpected fade-in animation type %d\n",
|
|
|
|
shell->startup_animation_type);
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_surface_destroy(shell->fade.view->surface);
|
|
|
|
shell->fade.view = NULL;
|
|
|
|
}
|
shell: wait for desktop-shell init before fade in
On Raspberry Pi, weston-desktop-shell is so slow to start, that the
compositor has time to run the fade-in before the wallpaper is up. The
user launching Weston sees the screen flipping to black, the fbcon
fading in, and then the desktop popping up.
To fix this, wait for the weston-desktop-shell to draw
everything before starting the initial fade-in. A new request is
added to the private desktop-shell protocol to signal it. If a
desktop-shell client does not support the new request, the fade-in
happens already at bind time.
If weston-desktop-shell crashes, or does not send the 'desktop_ready'
request in 15 seconds, the compositor will fade in anyway. This should
avoid a blocked screen in case weston-desktop-shell malfunction.
shell_fade_startup() does not directly start the fade-in but schedules
an idle callback, so that the compositor can process all pending events
before starting the fade clock. Otherwise (on RPi) we risk skipping part
of the animation. Yes, it is a hack, that should have been done in
window.c and weston-desktop-shell instead.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
12 years ago
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_fade_startup(struct desktop_shell *shell)
|
|
|
|
{
|
|
|
|
struct wl_event_loop *loop;
|
|
|
|
|
|
|
|
if (!shell->fade.startup_timer)
|
|
|
|
return;
|
|
|
|
|
|
|
|
wl_event_source_remove(shell->fade.startup_timer);
|
|
|
|
shell->fade.startup_timer = NULL;
|
|
|
|
|
|
|
|
loop = wl_display_get_event_loop(shell->compositor->wl_display);
|
|
|
|
wl_event_loop_add_idle(loop, do_shell_fade_startup, shell);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fade_startup_timeout(void *data)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = data;
|
|
|
|
|
|
|
|
shell_fade_startup(shell);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_fade_init(struct desktop_shell *shell)
|
|
|
|
{
|
|
|
|
/* Make compositor output all black, and wait for the desktop-shell
|
|
|
|
* client to signal it is ready, then fade in. The timer triggers a
|
|
|
|
* fade-in, in case the desktop-shell client takes too long.
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct wl_event_loop *loop;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
if (shell->fade.view != NULL) {
|
shell: wait for desktop-shell init before fade in
On Raspberry Pi, weston-desktop-shell is so slow to start, that the
compositor has time to run the fade-in before the wallpaper is up. The
user launching Weston sees the screen flipping to black, the fbcon
fading in, and then the desktop popping up.
To fix this, wait for the weston-desktop-shell to draw
everything before starting the initial fade-in. A new request is
added to the private desktop-shell protocol to signal it. If a
desktop-shell client does not support the new request, the fade-in
happens already at bind time.
If weston-desktop-shell crashes, or does not send the 'desktop_ready'
request in 15 seconds, the compositor will fade in anyway. This should
avoid a blocked screen in case weston-desktop-shell malfunction.
shell_fade_startup() does not directly start the fade-in but schedules
an idle callback, so that the compositor can process all pending events
before starting the fade clock. Otherwise (on RPi) we risk skipping part
of the animation. Yes, it is a hack, that should have been done in
window.c and weston-desktop-shell instead.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
12 years ago
|
|
|
weston_log("%s: warning: fade surface already exists\n",
|
|
|
|
__func__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (shell->startup_animation_type == ANIMATION_NONE)
|
|
|
|
return;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
shell->fade.view = shell_fade_create_surface(shell);
|
|
|
|
if (!shell->fade.view)
|
shell: wait for desktop-shell init before fade in
On Raspberry Pi, weston-desktop-shell is so slow to start, that the
compositor has time to run the fade-in before the wallpaper is up. The
user launching Weston sees the screen flipping to black, the fbcon
fading in, and then the desktop popping up.
To fix this, wait for the weston-desktop-shell to draw
everything before starting the initial fade-in. A new request is
added to the private desktop-shell protocol to signal it. If a
desktop-shell client does not support the new request, the fade-in
happens already at bind time.
If weston-desktop-shell crashes, or does not send the 'desktop_ready'
request in 15 seconds, the compositor will fade in anyway. This should
avoid a blocked screen in case weston-desktop-shell malfunction.
shell_fade_startup() does not directly start the fade-in but schedules
an idle callback, so that the compositor can process all pending events
before starting the fade clock. Otherwise (on RPi) we risk skipping part
of the animation. Yes, it is a hack, that should have been done in
window.c and weston-desktop-shell instead.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
12 years ago
|
|
|
return;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_update_transform(shell->fade.view);
|
|
|
|
weston_surface_damage(shell->fade.view->surface);
|
shell: wait for desktop-shell init before fade in
On Raspberry Pi, weston-desktop-shell is so slow to start, that the
compositor has time to run the fade-in before the wallpaper is up. The
user launching Weston sees the screen flipping to black, the fbcon
fading in, and then the desktop popping up.
To fix this, wait for the weston-desktop-shell to draw
everything before starting the initial fade-in. A new request is
added to the private desktop-shell protocol to signal it. If a
desktop-shell client does not support the new request, the fade-in
happens already at bind time.
If weston-desktop-shell crashes, or does not send the 'desktop_ready'
request in 15 seconds, the compositor will fade in anyway. This should
avoid a blocked screen in case weston-desktop-shell malfunction.
shell_fade_startup() does not directly start the fade-in but schedules
an idle callback, so that the compositor can process all pending events
before starting the fade clock. Otherwise (on RPi) we risk skipping part
of the animation. Yes, it is a hack, that should have been done in
window.c and weston-desktop-shell instead.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
12 years ago
|
|
|
|
|
|
|
loop = wl_display_get_event_loop(shell->compositor->wl_display);
|
|
|
|
shell->fade.startup_timer =
|
|
|
|
wl_event_loop_add_timer(loop, fade_startup_timeout, shell);
|
|
|
|
wl_event_source_timer_update(shell->fade.startup_timer, 15000);
|
|
|
|
}
|
|
|
|
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
static void
|
|
|
|
idle_handler(struct wl_listener *listener, void *data)
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
{
|
|
|
|
struct desktop_shell *shell =
|
|
|
|
container_of(listener, struct desktop_shell, idle_listener);
|
|
|
|
struct weston_seat *seat;
|
|
|
|
|
|
|
|
wl_list_for_each(seat, &shell->compositor->seat_list, link) {
|
|
|
|
struct weston_touch *touch = weston_seat_get_touch(seat);
|
|
|
|
struct weston_pointer *pointer = weston_seat_get_pointer(seat);
|
|
|
|
|
|
|
|
if (pointer)
|
|
|
|
popup_grab_end(pointer);
|
|
|
|
if (touch)
|
|
|
|
touch_popup_grab_end(touch);
|
|
|
|
}
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
|
|
|
|
shell_fade(shell, FADE_OUT);
|
|
|
|
/* lock() is called from shell_fade_done() */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
wake_handler(struct wl_listener *listener, void *data)
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
{
|
|
|
|
struct desktop_shell *shell =
|
|
|
|
container_of(listener, struct desktop_shell, wake_listener);
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
|
|
|
|
unlock(shell);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
transform_handler(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct weston_surface *surface = data;
|
|
|
|
struct shell_surface *shsurf = get_shell_surface(surface);
|
|
|
|
struct weston_view *view;;
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
if (!shsurf || !shsurf->client->send_position)
|
|
|
|
return;
|
|
|
|
|
|
|
|
view = shsurf->view;
|
|
|
|
if (!view || !weston_view_is_mapped(view))
|
|
|
|
return;
|
|
|
|
|
|
|
|
x = view->geometry.x;
|
|
|
|
y = view->geometry.y;
|
|
|
|
|
|
|
|
shsurf->client->send_position(surface, x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
center_on_output(struct weston_view *view, struct weston_output *output)
|
|
|
|
{
|
|
|
|
int32_t surf_x, surf_y, width, height;
|
|
|
|
float x, y;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
surface_subsurfaces_boundingbox(view->surface, &surf_x, &surf_y, &width, &height);
|
|
|
|
|
|
|
|
x = output->x + (output->width - width) / 2 - surf_x / 2;
|
|
|
|
y = output->y + (output->height - height) / 2 - surf_y / 2;
|
|
|
|
|
|
|
|
weston_view_set_position(view, x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_set_initial_position(struct weston_view *view,
|
|
|
|
struct desktop_shell *shell)
|
|
|
|
{
|
|
|
|
struct weston_compositor *compositor = shell->compositor;
|
|
|
|
int ix = 0, iy = 0;
|
|
|
|
int32_t range_x, range_y;
|
|
|
|
int32_t x, y;
|
|
|
|
struct weston_output *output, *target_output = NULL;
|
|
|
|
struct weston_seat *seat;
|
|
|
|
pixman_rectangle32_t area;
|
|
|
|
|
|
|
|
/* As a heuristic place the new window on the same output as the
|
|
|
|
* pointer. Falling back to the output containing 0, 0.
|
|
|
|
*
|
|
|
|
* TODO: Do something clever for touch too?
|
|
|
|
*/
|
|
|
|
wl_list_for_each(seat, &compositor->seat_list, link) {
|
|
|
|
struct weston_pointer *pointer = weston_seat_get_pointer(seat);
|
|
|
|
|
|
|
|
if (pointer) {
|
|
|
|
ix = wl_fixed_to_int(pointer->x);
|
|
|
|
iy = wl_fixed_to_int(pointer->y);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
wl_list_for_each(output, &compositor->output_list, link) {
|
|
|
|
if (pixman_region32_contains_point(&output->region, ix, iy, NULL)) {
|
|
|
|
target_output = output;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!target_output) {
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_set_position(view, 10 + random() % 400,
|
|
|
|
10 + random() % 400);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Valid range within output where the surface will still be onscreen.
|
|
|
|
* If this is negative it means that the surface is bigger than
|
|
|
|
* output.
|
|
|
|
*/
|
|
|
|
get_output_work_area(shell, target_output, &area);
|
|
|
|
|
|
|
|
x = area.x;
|
|
|
|
y = area.y;
|
|
|
|
range_x = area.width - view->surface->width;
|
|
|
|
range_y = area.height - view->surface->height;
|
|
|
|
|
|
|
|
if (range_x > 0)
|
|
|
|
x += random() % range_x;
|
|
|
|
|
|
|
|
if (range_y > 0)
|
|
|
|
y += random() % range_y;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_set_position(view, x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_maximized_position(struct desktop_shell *shell,
|
|
|
|
struct shell_surface *shsurf)
|
|
|
|
{
|
|
|
|
int32_t surf_x, surf_y;
|
|
|
|
pixman_rectangle32_t area;
|
|
|
|
|
|
|
|
get_output_work_area(shell, shsurf->output, &area);
|
|
|
|
if (shsurf->has_set_geometry) {
|
|
|
|
surf_x = shsurf->geometry.x;
|
|
|
|
surf_y = shsurf->geometry.y;
|
|
|
|
} else {
|
|
|
|
surface_subsurfaces_boundingbox(shsurf->surface,
|
|
|
|
&surf_x, &surf_y, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
weston_view_set_position(shsurf->view,
|
|
|
|
area.x - surf_x,
|
|
|
|
area.y - surf_y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
map(struct desktop_shell *shell, struct shell_surface *shsurf,
|
|
|
|
int32_t sx, int32_t sy)
|
|
|
|
{
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
13 years ago
|
|
|
struct weston_compositor *compositor = shell->compositor;
|
|
|
|
struct weston_seat *seat;
|
|
|
|
|
|
|
|
/* initial positioning, see also configure() */
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
switch (shsurf->type) {
|
|
|
|
case SHELL_SURFACE_TOPLEVEL:
|
|
|
|
if (shsurf->state.fullscreen) {
|
|
|
|
center_on_output(shsurf->view, shsurf->fullscreen_output);
|
|
|
|
shell_map_fullscreen(shsurf);
|
|
|
|
} else if (shsurf->state.maximized) {
|
|
|
|
set_maximized_position(shell, shsurf);
|
|
|
|
} else if (!shsurf->state.relative) {
|
|
|
|
weston_view_set_initial_position(shsurf->view, shell);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SHELL_SURFACE_POPUP:
|
|
|
|
if (shell_map_popup(shsurf) != 0)
|
|
|
|
return;
|
|
|
|
break;
|
|
|
|
case SHELL_SURFACE_NONE:
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_set_position(shsurf->view,
|
|
|
|
shsurf->view->geometry.x + sx,
|
|
|
|
shsurf->view->geometry.y + sy);
|
|
|
|
break;
|
|
|
|
case SHELL_SURFACE_XWAYLAND:
|
|
|
|
default:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Surface stacking order, see also activate(). */
|
|
|
|
shell_surface_update_layer(shsurf);
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
if (shsurf->type != SHELL_SURFACE_NONE) {
|
|
|
|
weston_view_update_transform(shsurf->view);
|
|
|
|
if (shsurf->state.maximized) {
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
shsurf->surface->output = shsurf->output;
|
|
|
|
shsurf->view->output = shsurf->output;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
switch (shsurf->type) {
|
|
|
|
/* XXX: xwayland's using the same fields for transient type */
|
|
|
|
case SHELL_SURFACE_XWAYLAND:
|
|
|
|
if (shsurf->transient.flags ==
|
|
|
|
WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
|
|
|
|
break;
|
|
|
|
case SHELL_SURFACE_TOPLEVEL:
|
|
|
|
if (shsurf->state.relative &&
|
|
|
|
shsurf->transient.flags == WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
|
|
|
|
break;
|
|
|
|
if (shell->locked)
|
|
|
|
break;
|
|
|
|
wl_list_for_each(seat, &compositor->seat_list, link)
|
|
|
|
activate(shell, shsurf->surface, seat, true);
|
|
|
|
break;
|
|
|
|
case SHELL_SURFACE_POPUP:
|
|
|
|
case SHELL_SURFACE_NONE:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (shsurf->type == SHELL_SURFACE_TOPLEVEL &&
|
|
|
|
!shsurf->state.maximized && !shsurf->state.fullscreen)
|
|
|
|
{
|
|
|
|
switch (shell->win_animation_type) {
|
|
|
|
case ANIMATION_FADE:
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_fade_run(shsurf->view, 0.0, 1.0, 300.0, NULL, NULL);
|
|
|
|
break;
|
|
|
|
case ANIMATION_ZOOM:
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_zoom_run(shsurf->view, 0.5, 1.0, NULL, NULL);
|
|
|
|
break;
|
|
|
|
case ANIMATION_NONE:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
configure(struct desktop_shell *shell, struct weston_surface *surface,
|
|
|
|
float x, float y)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *view;
|
|
|
|
|
|
|
|
shsurf = get_shell_surface(surface);
|
|
|
|
|
|
|
|
assert(shsurf);
|
|
|
|
|
|
|
|
if (shsurf->state.fullscreen)
|
|
|
|
shell_configure_fullscreen(shsurf);
|
|
|
|
else if (shsurf->state.maximized) {
|
|
|
|
set_maximized_position(shell, shsurf);
|
|
|
|
} else {
|
|
|
|
weston_view_set_position(shsurf->view, x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX: would a fullscreen surface need the same handling? */
|
|
|
|
if (surface->output) {
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
wl_list_for_each(view, &surface->views, surface_link)
|
|
|
|
weston_view_update_transform(view);
|
|
|
|
|
|
|
|
if (shsurf->state.maximized)
|
|
|
|
surface->output = shsurf->output;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
|
|
|
|
{
|
|
|
|
struct shell_surface *shsurf = get_shell_surface(es);
|
|
|
|
struct desktop_shell *shell;
|
|
|
|
int type_changed = 0;
|
|
|
|
|
|
|
|
assert(shsurf);
|
|
|
|
|
|
|
|
shell = shsurf->shell;
|
|
|
|
|
|
|
|
if (!weston_surface_is_mapped(es) &&
|
|
|
|
!wl_list_empty(&shsurf->popup.grab_link)) {
|
|
|
|
remove_popup_grab(shsurf);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (es->width == 0)
|
|
|
|
return;
|
|
|
|
|
shell: Replace set_margin with set_window_geometry
Currently, there is a fun flicker when toggling maximization or
fullscreen on a window in mutter or more sophisicated compositors
and WMs.
What happens is that the client want so go maximized, so we
calculate the size that we want the window to resize to (640x480),
and then add on its margins to find the buffer size (+10 = 660x500),
and then send out a configure event for that size. The client
renders to that size, realizes that it's maximized, and then
says "oh hey, my margins are actually 0 now!", and so the compositor
has to send out another configure event.
In order to fix this, make the the configure request correspond to
the window geometry we'd like the window to be at. At the same time,
replace set_margin with set_window_geometry, where we specify a rect
rather than a border around the window.
11 years ago
|
|
|
if (shsurf->has_next_geometry) {
|
|
|
|
shsurf->geometry = shsurf->next_geometry;
|
|
|
|
shsurf->has_next_geometry = false;
|
|
|
|
shsurf->has_set_geometry = true;
|
|
|
|
} else if (!shsurf->has_set_geometry) {
|
|
|
|
surface_subsurfaces_boundingbox(shsurf->surface,
|
|
|
|
&shsurf->geometry.x,
|
|
|
|
&shsurf->geometry.y,
|
|
|
|
&shsurf->geometry.width,
|
|
|
|
&shsurf->geometry.height);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (shsurf->state_changed) {
|
|
|
|
set_surface_type(shsurf);
|
|
|
|
type_changed = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!weston_surface_is_mapped(es)) {
|
|
|
|
map(shell, shsurf, sx, sy);
|
|
|
|
} else if (type_changed || sx != 0 || sy != 0 ||
|
|
|
|
shsurf->last_width != es->width ||
|
|
|
|
shsurf->last_height != es->height) {
|
|
|
|
float from_x, from_y;
|
|
|
|
float to_x, to_y;
|
|
|
|
|
|
|
|
if (shsurf->resize_edges) {
|
|
|
|
sx = 0;
|
|
|
|
sy = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (shsurf->resize_edges & WL_SHELL_SURFACE_RESIZE_LEFT)
|
|
|
|
sx = shsurf->last_width - es->width;
|
|
|
|
if (shsurf->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP)
|
|
|
|
sy = shsurf->last_height - es->height;
|
|
|
|
|
|
|
|
shsurf->last_width = es->width;
|
|
|
|
shsurf->last_height = es->height;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
weston_view_to_global_float(shsurf->view, 0, 0, &from_x, &from_y);
|
|
|
|
weston_view_to_global_float(shsurf->view, sx, sy, &to_x, &to_y);
|
|
|
|
configure(shell, es,
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
shsurf->view->geometry.x + to_x - from_x,
|
|
|
|
shsurf->view->geometry.y + to_y - from_y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
check_desktop_shell_crash_too_early(struct desktop_shell *shell)
|
|
|
|
{
|
|
|
|
struct timespec now;
|
|
|
|
|
|
|
|
if (clock_gettime(CLOCK_MONOTONIC, &now) < 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the shell helper client dies before the session has been
|
|
|
|
* up for roughly 30 seconds, better just make Weston shut down,
|
|
|
|
* because the user likely has no way to interact with the desktop
|
|
|
|
* anyway.
|
|
|
|
*/
|
|
|
|
if (now.tv_sec - shell->startup_time.tv_sec < 30) {
|
|
|
|
weston_log("Error: %s apparently cannot run at all.\n",
|
|
|
|
shell->client);
|
|
|
|
weston_log_continue(STAMP_SPACE "Quitting...");
|
|
|
|
wl_display_terminate(shell->compositor->wl_display);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void launch_desktop_shell_process(void *data);
|
|
|
|
|
|
|
|
static void
|
shell: fix race on desktop-shell exit
The desktop shell plugin registers both a wl_client destroy signal
listener, and a sigchld handler, when launching weston-desktop-shell.
However, nothing guarantees in which order do the wl_client destructor
and the sigchld handler run.
Luckily, the sigchld handler cannot interrupt any code, because we
handle the signal via signalfd, which means it is handled like any event
in the compositor's main event loop.
Still, shell.c has a race, that when lost, can cause a crash, as
described in bug #82957.
If the sigchld handler happens to run first, it will try to launch a new
weston-desktop-shell without removing the destroy listener from the old
wl_client first. This leads to list corruption, that may cause a crash
when the old wl_client gets destroyed.
Simply removing the destroy listener in the sigchld handler is not
enough, because respawning sets shell->child.client pointer, and if
the wl_client destructor runs after, it will reset it to NULL.
OTOH, the wl_client destroy handler cannot reset shell->child.process,
because that would cause the sigchld handler in weston core to not find
the process tracker anymore, and report that an unknown process exited.
Turns out, that to make everything work, we would need to wait for both
the wl_client destructor and the sigchld handler to have run, before
respawn. This gets tricky.
Instead, solve the problem by removing shell->child.process. Use the new
weston_client_start() which automatically creates and manages the struct
weston_process. The shell does not need to know about the process exit,
it only needs to know about the client disconnect. Weston-desktop-shell
will never attempt to reconnect, and it would not work even if it did,
so disconnect is equivalent to weston-desktop-shell exiting.
This should permanently solve the race for weston-desktop-shell.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=82957
Cc: Boyan Ding <stu_dby@126.com>
Cc: Derek Foreman <derekf@osg.samsung.com>
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Derek Foreman <derekf@osg.samsung.com>
10 years ago
|
|
|
respawn_desktop_shell_process(struct desktop_shell *shell)
|
|
|
|
{
|
|
|
|
uint32_t time;
|
|
|
|
|
|
|
|
/* if desktop-shell dies more than 5 times in 30 seconds, give up */
|
|
|
|
time = weston_compositor_get_time();
|
|
|
|
if (time - shell->child.deathstamp > 30000) {
|
|
|
|
shell->child.deathstamp = time;
|
|
|
|
shell->child.deathcount = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
shell->child.deathcount++;
|
|
|
|
if (shell->child.deathcount > 5) {
|
shell: fix race on desktop-shell exit
The desktop shell plugin registers both a wl_client destroy signal
listener, and a sigchld handler, when launching weston-desktop-shell.
However, nothing guarantees in which order do the wl_client destructor
and the sigchld handler run.
Luckily, the sigchld handler cannot interrupt any code, because we
handle the signal via signalfd, which means it is handled like any event
in the compositor's main event loop.
Still, shell.c has a race, that when lost, can cause a crash, as
described in bug #82957.
If the sigchld handler happens to run first, it will try to launch a new
weston-desktop-shell without removing the destroy listener from the old
wl_client first. This leads to list corruption, that may cause a crash
when the old wl_client gets destroyed.
Simply removing the destroy listener in the sigchld handler is not
enough, because respawning sets shell->child.client pointer, and if
the wl_client destructor runs after, it will reset it to NULL.
OTOH, the wl_client destroy handler cannot reset shell->child.process,
because that would cause the sigchld handler in weston core to not find
the process tracker anymore, and report that an unknown process exited.
Turns out, that to make everything work, we would need to wait for both
the wl_client destructor and the sigchld handler to have run, before
respawn. This gets tricky.
Instead, solve the problem by removing shell->child.process. Use the new
weston_client_start() which automatically creates and manages the struct
weston_process. The shell does not need to know about the process exit,
it only needs to know about the client disconnect. Weston-desktop-shell
will never attempt to reconnect, and it would not work even if it did,
so disconnect is equivalent to weston-desktop-shell exiting.
This should permanently solve the race for weston-desktop-shell.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=82957
Cc: Boyan Ding <stu_dby@126.com>
Cc: Derek Foreman <derekf@osg.samsung.com>
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Derek Foreman <derekf@osg.samsung.com>
10 years ago
|
|
|
weston_log("%s disconnected, giving up.\n", shell->client);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
shell: fix race on desktop-shell exit
The desktop shell plugin registers both a wl_client destroy signal
listener, and a sigchld handler, when launching weston-desktop-shell.
However, nothing guarantees in which order do the wl_client destructor
and the sigchld handler run.
Luckily, the sigchld handler cannot interrupt any code, because we
handle the signal via signalfd, which means it is handled like any event
in the compositor's main event loop.
Still, shell.c has a race, that when lost, can cause a crash, as
described in bug #82957.
If the sigchld handler happens to run first, it will try to launch a new
weston-desktop-shell without removing the destroy listener from the old
wl_client first. This leads to list corruption, that may cause a crash
when the old wl_client gets destroyed.
Simply removing the destroy listener in the sigchld handler is not
enough, because respawning sets shell->child.client pointer, and if
the wl_client destructor runs after, it will reset it to NULL.
OTOH, the wl_client destroy handler cannot reset shell->child.process,
because that would cause the sigchld handler in weston core to not find
the process tracker anymore, and report that an unknown process exited.
Turns out, that to make everything work, we would need to wait for both
the wl_client destructor and the sigchld handler to have run, before
respawn. This gets tricky.
Instead, solve the problem by removing shell->child.process. Use the new
weston_client_start() which automatically creates and manages the struct
weston_process. The shell does not need to know about the process exit,
it only needs to know about the client disconnect. Weston-desktop-shell
will never attempt to reconnect, and it would not work even if it did,
so disconnect is equivalent to weston-desktop-shell exiting.
This should permanently solve the race for weston-desktop-shell.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=82957
Cc: Boyan Ding <stu_dby@126.com>
Cc: Derek Foreman <derekf@osg.samsung.com>
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Derek Foreman <derekf@osg.samsung.com>
10 years ago
|
|
|
weston_log("%s disconnected, respawning...\n", shell->client);
|
|
|
|
launch_desktop_shell_process(shell);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
desktop_shell_client_destroy(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell;
|
|
|
|
|
|
|
|
shell = container_of(listener, struct desktop_shell,
|
|
|
|
child.client_destroy_listener);
|
|
|
|
|
shell: fix race on desktop-shell exit
The desktop shell plugin registers both a wl_client destroy signal
listener, and a sigchld handler, when launching weston-desktop-shell.
However, nothing guarantees in which order do the wl_client destructor
and the sigchld handler run.
Luckily, the sigchld handler cannot interrupt any code, because we
handle the signal via signalfd, which means it is handled like any event
in the compositor's main event loop.
Still, shell.c has a race, that when lost, can cause a crash, as
described in bug #82957.
If the sigchld handler happens to run first, it will try to launch a new
weston-desktop-shell without removing the destroy listener from the old
wl_client first. This leads to list corruption, that may cause a crash
when the old wl_client gets destroyed.
Simply removing the destroy listener in the sigchld handler is not
enough, because respawning sets shell->child.client pointer, and if
the wl_client destructor runs after, it will reset it to NULL.
OTOH, the wl_client destroy handler cannot reset shell->child.process,
because that would cause the sigchld handler in weston core to not find
the process tracker anymore, and report that an unknown process exited.
Turns out, that to make everything work, we would need to wait for both
the wl_client destructor and the sigchld handler to have run, before
respawn. This gets tricky.
Instead, solve the problem by removing shell->child.process. Use the new
weston_client_start() which automatically creates and manages the struct
weston_process. The shell does not need to know about the process exit,
it only needs to know about the client disconnect. Weston-desktop-shell
will never attempt to reconnect, and it would not work even if it did,
so disconnect is equivalent to weston-desktop-shell exiting.
This should permanently solve the race for weston-desktop-shell.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=82957
Cc: Boyan Ding <stu_dby@126.com>
Cc: Derek Foreman <derekf@osg.samsung.com>
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Derek Foreman <derekf@osg.samsung.com>
10 years ago
|
|
|
wl_list_remove(&shell->child.client_destroy_listener.link);
|
|
|
|
shell->child.client = NULL;
|
shell: fix race on desktop-shell exit
The desktop shell plugin registers both a wl_client destroy signal
listener, and a sigchld handler, when launching weston-desktop-shell.
However, nothing guarantees in which order do the wl_client destructor
and the sigchld handler run.
Luckily, the sigchld handler cannot interrupt any code, because we
handle the signal via signalfd, which means it is handled like any event
in the compositor's main event loop.
Still, shell.c has a race, that when lost, can cause a crash, as
described in bug #82957.
If the sigchld handler happens to run first, it will try to launch a new
weston-desktop-shell without removing the destroy listener from the old
wl_client first. This leads to list corruption, that may cause a crash
when the old wl_client gets destroyed.
Simply removing the destroy listener in the sigchld handler is not
enough, because respawning sets shell->child.client pointer, and if
the wl_client destructor runs after, it will reset it to NULL.
OTOH, the wl_client destroy handler cannot reset shell->child.process,
because that would cause the sigchld handler in weston core to not find
the process tracker anymore, and report that an unknown process exited.
Turns out, that to make everything work, we would need to wait for both
the wl_client destructor and the sigchld handler to have run, before
respawn. This gets tricky.
Instead, solve the problem by removing shell->child.process. Use the new
weston_client_start() which automatically creates and manages the struct
weston_process. The shell does not need to know about the process exit,
it only needs to know about the client disconnect. Weston-desktop-shell
will never attempt to reconnect, and it would not work even if it did,
so disconnect is equivalent to weston-desktop-shell exiting.
This should permanently solve the race for weston-desktop-shell.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=82957
Cc: Boyan Ding <stu_dby@126.com>
Cc: Derek Foreman <derekf@osg.samsung.com>
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Derek Foreman <derekf@osg.samsung.com>
10 years ago
|
|
|
/*
|
|
|
|
* unbind_desktop_shell() will reset shell->child.desktop_shell
|
|
|
|
* before the respawned process has a chance to create a new
|
|
|
|
* desktop_shell object, because we are being called from the
|
|
|
|
* wl_client destructor which destroys all wl_resources before
|
|
|
|
* returning.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!check_desktop_shell_crash_too_early(shell))
|
|
|
|
respawn_desktop_shell_process(shell);
|
|
|
|
|
shell: fix race on desktop-shell exit
The desktop shell plugin registers both a wl_client destroy signal
listener, and a sigchld handler, when launching weston-desktop-shell.
However, nothing guarantees in which order do the wl_client destructor
and the sigchld handler run.
Luckily, the sigchld handler cannot interrupt any code, because we
handle the signal via signalfd, which means it is handled like any event
in the compositor's main event loop.
Still, shell.c has a race, that when lost, can cause a crash, as
described in bug #82957.
If the sigchld handler happens to run first, it will try to launch a new
weston-desktop-shell without removing the destroy listener from the old
wl_client first. This leads to list corruption, that may cause a crash
when the old wl_client gets destroyed.
Simply removing the destroy listener in the sigchld handler is not
enough, because respawning sets shell->child.client pointer, and if
the wl_client destructor runs after, it will reset it to NULL.
OTOH, the wl_client destroy handler cannot reset shell->child.process,
because that would cause the sigchld handler in weston core to not find
the process tracker anymore, and report that an unknown process exited.
Turns out, that to make everything work, we would need to wait for both
the wl_client destructor and the sigchld handler to have run, before
respawn. This gets tricky.
Instead, solve the problem by removing shell->child.process. Use the new
weston_client_start() which automatically creates and manages the struct
weston_process. The shell does not need to know about the process exit,
it only needs to know about the client disconnect. Weston-desktop-shell
will never attempt to reconnect, and it would not work even if it did,
so disconnect is equivalent to weston-desktop-shell exiting.
This should permanently solve the race for weston-desktop-shell.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=82957
Cc: Boyan Ding <stu_dby@126.com>
Cc: Derek Foreman <derekf@osg.samsung.com>
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Derek Foreman <derekf@osg.samsung.com>
10 years ago
|
|
|
shell_fade_startup(shell);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
launch_desktop_shell_process(void *data)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = data;
|
|
|
|
|
shell: fix race on desktop-shell exit
The desktop shell plugin registers both a wl_client destroy signal
listener, and a sigchld handler, when launching weston-desktop-shell.
However, nothing guarantees in which order do the wl_client destructor
and the sigchld handler run.
Luckily, the sigchld handler cannot interrupt any code, because we
handle the signal via signalfd, which means it is handled like any event
in the compositor's main event loop.
Still, shell.c has a race, that when lost, can cause a crash, as
described in bug #82957.
If the sigchld handler happens to run first, it will try to launch a new
weston-desktop-shell without removing the destroy listener from the old
wl_client first. This leads to list corruption, that may cause a crash
when the old wl_client gets destroyed.
Simply removing the destroy listener in the sigchld handler is not
enough, because respawning sets shell->child.client pointer, and if
the wl_client destructor runs after, it will reset it to NULL.
OTOH, the wl_client destroy handler cannot reset shell->child.process,
because that would cause the sigchld handler in weston core to not find
the process tracker anymore, and report that an unknown process exited.
Turns out, that to make everything work, we would need to wait for both
the wl_client destructor and the sigchld handler to have run, before
respawn. This gets tricky.
Instead, solve the problem by removing shell->child.process. Use the new
weston_client_start() which automatically creates and manages the struct
weston_process. The shell does not need to know about the process exit,
it only needs to know about the client disconnect. Weston-desktop-shell
will never attempt to reconnect, and it would not work even if it did,
so disconnect is equivalent to weston-desktop-shell exiting.
This should permanently solve the race for weston-desktop-shell.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=82957
Cc: Boyan Ding <stu_dby@126.com>
Cc: Derek Foreman <derekf@osg.samsung.com>
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Derek Foreman <derekf@osg.samsung.com>
10 years ago
|
|
|
shell->child.client = weston_client_start(shell->compositor,
|
|
|
|
shell->client);
|
|
|
|
|
|
|
|
if (!shell->child.client) {
|
|
|
|
weston_log("not able to start %s\n", shell->client);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
shell->child.client_destroy_listener.notify =
|
|
|
|
desktop_shell_client_destroy;
|
|
|
|
wl_client_add_destroy_listener(shell->child.client,
|
|
|
|
&shell->child.client_destroy_listener);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_shell_client_destroy(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct shell_client *sc =
|
|
|
|
container_of(listener, struct shell_client, destroy_listener);
|
|
|
|
struct wl_resource *shsurf_resource;
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
|
|
|
|
if (sc->ping_timer)
|
|
|
|
wl_event_source_remove(sc->ping_timer);
|
|
|
|
|
|
|
|
/* Since we're about to free shell_client, we remove it from the
|
|
|
|
* head of the surface list so we don't use that freed list node
|
|
|
|
* during surface clean up later on.
|
|
|
|
*/
|
|
|
|
wl_resource_for_each(shsurf_resource, &sc->surface_list) {
|
|
|
|
shsurf = wl_resource_get_user_data(shsurf_resource);
|
|
|
|
shsurf->owner = NULL;
|
|
|
|
}
|
|
|
|
wl_list_remove(&sc->surface_list);
|
|
|
|
|
|
|
|
free(sc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct shell_client *
|
|
|
|
shell_client_create(struct wl_client *client, struct desktop_shell *shell,
|
|
|
|
const struct wl_interface *interface, uint32_t id)
|
|
|
|
{
|
|
|
|
struct shell_client *sc;
|
|
|
|
|
|
|
|
sc = zalloc(sizeof *sc);
|
|
|
|
if (sc == NULL) {
|
|
|
|
wl_client_post_no_memory(client);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
sc->resource = wl_resource_create(client, interface, 1, id);
|
|
|
|
if (sc->resource == NULL) {
|
|
|
|
free(sc);
|
|
|
|
wl_client_post_no_memory(client);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
sc->client = client;
|
|
|
|
sc->shell = shell;
|
|
|
|
sc->destroy_listener.notify = handle_shell_client_destroy;
|
|
|
|
wl_client_add_destroy_listener(client, &sc->destroy_listener);
|
|
|
|
wl_list_init(&sc->surface_list);
|
|
|
|
|
|
|
|
return sc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = data;
|
|
|
|
struct shell_client *sc;
|
|
|
|
|
|
|
|
sc = shell_client_create(client, shell, &wl_shell_interface, id);
|
|
|
|
if (sc)
|
|
|
|
wl_resource_set_implementation(sc->resource,
|
|
|
|
&shell_implementation,
|
|
|
|
sc, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bind_xdg_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = data;
|
|
|
|
struct shell_client *sc;
|
|
|
|
|
|
|
|
sc = shell_client_create(client, shell, &xdg_shell_interface, id);
|
|
|
|
if (sc)
|
|
|
|
wl_resource_set_dispatcher(sc->resource,
|
|
|
|
xdg_shell_unversioned_dispatch,
|
|
|
|
NULL, sc, NULL);
|
|
|
|
}
|
|
|
|
|
desktop-shell: screen locking protocol
Add protocol and functions for supporting screen locking, triggered by
activity timeout.
After activity timeout, compositor starts the fade to black, and then
enters SLEEPING state. At that point it calls lock() in the shell
plugin.
When input events trigger a wakeup, unlock() in the shell plugin is
called. This sends prepare_lock_surface event to the desktop-shell
client. The screen stays locked while the compositor starts fade-in.
At this point, desktop-shell client usually creates a surface for the
unlocking GUI (e.g. a password prompt), and sends it with the
set_lock_surface request. The compositor supposedly shows and allows
interaction only with the given lock surface (not yet implemented).
When desktop-shell has authenticated the user, or instead of issuing
set_lock_surface, it sends the unlock request. Upon receiving the unlock
request, the shell plugin unlocks the screen.
If desktop-shell client dies, the screen is unlocked automatically.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
13 years ago
|
|
|
static void
|
|
|
|
unbind_desktop_shell(struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = wl_resource_get_user_data(resource);
|
|
|
|
|
|
|
|
if (shell->locked)
|
|
|
|
resume_desktop(shell);
|
|
|
|
|
desktop-shell: screen locking protocol
Add protocol and functions for supporting screen locking, triggered by
activity timeout.
After activity timeout, compositor starts the fade to black, and then
enters SLEEPING state. At that point it calls lock() in the shell
plugin.
When input events trigger a wakeup, unlock() in the shell plugin is
called. This sends prepare_lock_surface event to the desktop-shell
client. The screen stays locked while the compositor starts fade-in.
At this point, desktop-shell client usually creates a surface for the
unlocking GUI (e.g. a password prompt), and sends it with the
set_lock_surface request. The compositor supposedly shows and allows
interaction only with the given lock surface (not yet implemented).
When desktop-shell has authenticated the user, or instead of issuing
set_lock_surface, it sends the unlock request. Upon receiving the unlock
request, the shell plugin unlocks the screen.
If desktop-shell client dies, the screen is unlocked automatically.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
13 years ago
|
|
|
shell->child.desktop_shell = NULL;
|
|
|
|
shell->prepare_event_sent = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bind_desktop_shell(struct wl_client *client,
|
|
|
|
void *data, uint32_t version, uint32_t id)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = data;
|
|
|
|
struct wl_resource *resource;
|
|
|
|
|
|
|
|
resource = wl_resource_create(client, &weston_desktop_shell_interface,
|
|
|
|
1, id);
|
|
|
|
|
desktop-shell: screen locking protocol
Add protocol and functions for supporting screen locking, triggered by
activity timeout.
After activity timeout, compositor starts the fade to black, and then
enters SLEEPING state. At that point it calls lock() in the shell
plugin.
When input events trigger a wakeup, unlock() in the shell plugin is
called. This sends prepare_lock_surface event to the desktop-shell
client. The screen stays locked while the compositor starts fade-in.
At this point, desktop-shell client usually creates a surface for the
unlocking GUI (e.g. a password prompt), and sends it with the
set_lock_surface request. The compositor supposedly shows and allows
interaction only with the given lock surface (not yet implemented).
When desktop-shell has authenticated the user, or instead of issuing
set_lock_surface, it sends the unlock request. Upon receiving the unlock
request, the shell plugin unlocks the screen.
If desktop-shell client dies, the screen is unlocked automatically.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
13 years ago
|
|
|
if (client == shell->child.client) {
|
|
|
|
wl_resource_set_implementation(resource,
|
|
|
|
&desktop_shell_implementation,
|
|
|
|
shell, unbind_desktop_shell);
|
desktop-shell: screen locking protocol
Add protocol and functions for supporting screen locking, triggered by
activity timeout.
After activity timeout, compositor starts the fade to black, and then
enters SLEEPING state. At that point it calls lock() in the shell
plugin.
When input events trigger a wakeup, unlock() in the shell plugin is
called. This sends prepare_lock_surface event to the desktop-shell
client. The screen stays locked while the compositor starts fade-in.
At this point, desktop-shell client usually creates a surface for the
unlocking GUI (e.g. a password prompt), and sends it with the
set_lock_surface request. The compositor supposedly shows and allows
interaction only with the given lock surface (not yet implemented).
When desktop-shell has authenticated the user, or instead of issuing
set_lock_surface, it sends the unlock request. Upon receiving the unlock
request, the shell plugin unlocks the screen.
If desktop-shell client dies, the screen is unlocked automatically.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
13 years ago
|
|
|
shell->child.desktop_shell = resource;
|
|
|
|
return;
|
desktop-shell: screen locking protocol
Add protocol and functions for supporting screen locking, triggered by
activity timeout.
After activity timeout, compositor starts the fade to black, and then
enters SLEEPING state. At that point it calls lock() in the shell
plugin.
When input events trigger a wakeup, unlock() in the shell plugin is
called. This sends prepare_lock_surface event to the desktop-shell
client. The screen stays locked while the compositor starts fade-in.
At this point, desktop-shell client usually creates a surface for the
unlocking GUI (e.g. a password prompt), and sends it with the
set_lock_surface request. The compositor supposedly shows and allows
interaction only with the given lock surface (not yet implemented).
When desktop-shell has authenticated the user, or instead of issuing
set_lock_surface, it sends the unlock request. Upon receiving the unlock
request, the shell plugin unlocks the screen.
If desktop-shell client dies, the screen is unlocked automatically.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
13 years ago
|
|
|
}
|
|
|
|
|
|
|
|
wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
|
|
|
|
"permission to bind desktop_shell denied");
|
|
|
|
}
|
|
|
|
|
|
|
|
struct switcher {
|
|
|
|
struct desktop_shell *shell;
|
|
|
|
struct weston_surface *current;
|
|
|
|
struct wl_listener listener;
|
|
|
|
struct weston_keyboard_grab grab;
|
|
|
|
struct wl_array minimized_array;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
switcher_next(struct switcher *switcher)
|
|
|
|
{
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *view;
|
|
|
|
struct weston_surface *first = NULL, *prev = NULL, *next = NULL;
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
struct workspace *ws = get_current_workspace(switcher->shell);
|
|
|
|
|
|
|
|
/* temporary re-display minimized surfaces */
|
|
|
|
struct weston_view *tmp;
|
|
|
|
struct weston_view **minimized;
|
|
|
|
wl_list_for_each_safe(view, tmp, &switcher->shell->minimized_layer.view_list.link, layer_link.link) {
|
|
|
|
weston_layer_entry_remove(&view->layer_link);
|
|
|
|
weston_layer_entry_insert(&ws->layer.view_list, &view->layer_link);
|
|
|
|
minimized = wl_array_add(&switcher->minimized_array, sizeof *minimized);
|
|
|
|
*minimized = view;
|
|
|
|
}
|
|
|
|
|
|
|
|
wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) {
|
|
|
|
shsurf = get_shell_surface(view->surface);
|
|
|
|
if (shsurf &&
|
|
|
|
shsurf->type == SHELL_SURFACE_TOPLEVEL &&
|
|
|
|
shsurf->parent == NULL) {
|
|
|
|
if (first == NULL)
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
first = view->surface;
|
|
|
|
if (prev == switcher->current)
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
next = view->surface;
|
|
|
|
prev = view->surface;
|
|
|
|
view->alpha = 0.25;
|
|
|
|
weston_view_geometry_dirty(view);
|
|
|
|
weston_surface_damage(view->surface);
|
|
|
|
}
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
if (is_black_surface(view->surface, NULL)) {
|
|
|
|
view->alpha = 0.25;
|
|
|
|
weston_view_geometry_dirty(view);
|
|
|
|
weston_surface_damage(view->surface);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (next == NULL)
|
|
|
|
next = first;
|
|
|
|
|
|
|
|
if (next == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
wl_list_remove(&switcher->listener.link);
|
|
|
|
wl_signal_add(&next->destroy_signal, &switcher->listener);
|
|
|
|
|
|
|
|
switcher->current = next;
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
wl_list_for_each(view, &next->views, surface_link)
|
|
|
|
view->alpha = 1.0;
|
|
|
|
|
|
|
|
shsurf = get_shell_surface(switcher->current);
|
|
|
|
if (shsurf && shsurf->state.fullscreen)
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
shsurf->fullscreen.black_view->alpha = 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
switcher_handle_surface_destroy(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct switcher *switcher =
|
|
|
|
container_of(listener, struct switcher, listener);
|
|
|
|
|
|
|
|
switcher_next(switcher);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
switcher_destroy(struct switcher *switcher)
|
|
|
|
{
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
struct weston_view *view;
|
|
|
|
struct weston_keyboard *keyboard = switcher->grab.keyboard;
|
|
|
|
struct workspace *ws = get_current_workspace(switcher->shell);
|
|
|
|
|
|
|
|
wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) {
|
animation, shell: add kbd focus change animation
When enabled, this will make all but the keyboard-focused window dim.
Also the background gets dimmed, if there are any windows open. The
panel is not dimmed.
When the keyboard focus changes, the change in dimming is animated.
The dimming is implemented with transparent solid-color surfaces, two at
most. The net effect of two overlapping dim surfaces is kept constant
during animations (stable fade animation).
There is a new weston.ini option "focus-animation", that defaults to
none, and can be set to "dim-layer" to enable the focus change
animation.
[pq: Sliced, squashed, and rebased the patch series. Fixed surface alpha
interaction with the switcher. Wrote the commit message.]
[pochu: rebased, ported to weston_view]
11 years ago
|
|
|
if (is_focus_view(view))
|
|
|
|
continue;
|
|
|
|
|
Split the geometry information from weston_surface out into weston_view
The weston_surface structure is split into two structures:
* The weston_surface structure storres everything required for a
client-side or server-side surface. This includes buffers; callbacks;
backend private data; input, damage, and opaque regions; and a few other
bookkeeping bits.
* The weston_view structure represents an entity in the scenegraph and
storres all of the geometry information. This includes clip region,
alpha, position, and the transformation list as well as all of the
temporary information derived from the geometry state. Because a view,
and not a surface, is a scenegraph element, the view is what is placed
in layers and planes.
There are a few things worth noting about the surface/view split:
1. This is *not* a modification to the protocol. It is, instead, a
modification to Weston's internal scenegraph to allow a single surface
to exist in multiple places at a time. Clients are completely unaware
of how many views to a particular surface exist.
2. A view is considered a direct child of a surface and is destroyed when
the surface is destroyed. Because of this, the view.surface pointer is
always valid and non-null.
3. The compositor's surface_list is replaced with a view_list. Due to
subsurfaces, building the view list is a little more complicated than
it used to be and involves building a tree of views on the fly whenever
subsurfaces are used. However, this means that backends can remain
completely subsurface-agnostic.
4. Surfaces and views both keep track of which outputs they are on.
5. The weston_surface structure now has width and height fields. These
are populated when a new buffer is attached before surface.configure
is called. This is because there are many surface-based operations
that really require the width and height and digging through the views
didn't work well.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
11 years ago
|
|
|
view->alpha = 1.0;
|
|
|
|
weston_surface_damage(view->surface);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (switcher->current)
|
|
|
|
activate(switcher->shell, switcher->current,
|
|
|
|
keyboard->seat, true);
|
|
|
|
wl_list_remove(&switcher->listener.link);
|
|
|
|
weston_keyboard_end_grab(keyboard);
|
|
|
|
if (keyboard->input_method_resource)
|
|
|
|
keyboard->grab = &keyboard->input_method_grab;
|
|
|
|
|
|
|
|
/* re-hide surfaces that were temporary shown during the switch */
|
|
|
|
struct weston_view **minimized;
|
|
|
|
wl_array_for_each(minimized, &switcher->minimized_array) {
|
|
|
|
/* with the exception of the current selected */
|
|
|
|
if ((*minimized)->surface != switcher->current) {
|
|
|
|
weston_layer_entry_remove(&(*minimized)->layer_link);
|
|
|
|
weston_layer_entry_insert(&switcher->shell->minimized_layer.view_list, &(*minimized)->layer_link);
|
|
|
|
weston_view_damage_below(*minimized);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
wl_array_release(&switcher->minimized_array);
|
|
|
|
|
|
|
|
free(switcher);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
switcher_key(struct weston_keyboard_grab *grab,
|
|
|
|
uint32_t time, uint32_t key, uint32_t state_w)
|
|
|
|
{
|
|
|
|
struct switcher *switcher = container_of(grab, struct switcher, grab);
|
|
|
|
enum wl_keyboard_key_state state = state_w;
|
|
|
|
|
|
|
|
if (key == KEY_TAB && state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
|
|
|
switcher_next(switcher);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
switcher_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
|
|
|
|
uint32_t mods_depressed, uint32_t mods_latched,
|
|
|
|
uint32_t mods_locked, uint32_t group)
|
|
|
|
{
|
|
|
|
struct switcher *switcher = container_of(grab, struct switcher, grab);
|
|
|
|
struct weston_seat *seat = grab->keyboard->seat;
|
|
|
|
|
|
|
|
if ((seat->modifier_state & switcher->shell->binding_modifier) == 0)
|
|
|
|
switcher_destroy(switcher);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
switcher_cancel(struct weston_keyboard_grab *grab)
|
|
|
|
{
|
|
|
|
struct switcher *switcher = container_of(grab, struct switcher, grab);
|
|
|
|
|
|
|
|
switcher_destroy(switcher);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct weston_keyboard_grab_interface switcher_grab = {
|
|
|
|
switcher_key,
|
|
|
|
switcher_modifier,
|
|
|
|
switcher_cancel,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
switcher_binding(struct weston_keyboard *keyboard, uint32_t time,
|
|
|
|
uint32_t key, void *data)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell = data;
|
|
|
|
struct switcher *switcher;
|
|
|
|
|
|
|
|
switcher = malloc(sizeof *switcher);
|
|
|
|
switcher->shell = shell;
|
|
|
|
switcher->current = NULL;
|
|
|
|
switcher->listener.notify = switcher_handle_surface_destroy;
|
|
|
|
wl_list_init(&switcher->listener.link);
|
|
|
|
wl_array_init(&switcher->minimized_array);
|
|
|
|
|
|
|
|
restore_all_output_modes(shell->compositor);
|
|
|
|
lower_fullscreen_layer(switcher->shell, NULL);
|
|
|
|
switcher->grab.interface = &switcher_grab;
|
|
|
|
weston_keyboard_start_grab(keyboard, &switcher->grab);
|
|
|
|
weston_keyboard_set_focus(keyboard, NULL);
|
|
|
|
switcher_next(switcher);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
backlight_binding(struct weston_keyboard *keyboard, uint32_t time,
|
|
|
|
uint32_t key, void *data)
|
|
|
|
{
|
|
|
|
struct weston_compositor *compositor = data;
|
|
|
|
struct weston_output *output;
|
|
|
|
long backlight_new = 0;
|
|
|
|
|
|
|
|
/* TODO: we're limiting to simple use cases, where we assume just
|
|
|
|
* control on the primary display. We'd have to extend later if we
|
|
|
|
* ever get support for setting backlights on random desktop LCD
|
|
|
|
* panels though */
|
|
|
|
output = get_default_output(compositor);
|
|
|
|
if (!output)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!output->set_backlight)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (key == KEY_F9 || key == KEY_BRIGHTNESSDOWN)
|
|
|
|
backlight_new = output->backlight_current - 25;
|
|
|
|
else if (key == KEY_F10 || key == KEY_BRIGHTNESSUP)
|
|
|
|
backlight_new = output->backlight_current + 25;
|
|
|
|
|
|
|
|
if (backlight_new < 5)
|
|
|
|
backlight_new = 5;
|
|
|
|
if (backlight_new > 255)
|
|
|
|
backlight_new = 255;
|
|
|
|
|
|
|
|
output->backlight_current = backlight_new;
|
|
|
|
output->set_backlight(output, output->backlight_current);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
force_kill_binding(struct weston_keyboard *keyboard, uint32_t time,
|
|
|
|
uint32_t key, void *data)
|
|
|
|
{
|
|
|
|
struct weston_surface *focus_surface;
|
|
|
|
struct wl_client *client;
|
|
|
|
struct desktop_shell *shell = data;
|
|
|
|
struct weston_compositor *compositor = shell->compositor;
|
|
|
|
pid_t pid;
|
|
|
|
|
|
|
|
focus_surface = keyboard->focus;
|
|
|
|
if (!focus_surface)
|
|
|
|
return;
|
|
|
|
|
|
|
|
wl_signal_emit(&compositor->kill_signal, focus_surface);
|
|
|
|
|
|
|
|
client = wl_resource_get_client(focus_surface->resource);
|
|
|
|
wl_client_get_credentials(client, &pid, NULL, NULL);
|
|
|
|
|
|
|
|
/* Skip clients that we launched ourselves (the credentials of
|
|
|
|
* the socketpair is ours) */
|
|
|
|
if (pid == getpid())
|
|
|
|
return;
|
|
|
|
|
|
|
|
kill(pid, SIGKILL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
workspace_up_binding(struct weston_keyboard *keyboard, uint32_t 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, uint32_t 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, uint32_t 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,
|
|
|
|
uint32_t 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,
|
|
|
|
uint32_t 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_destroy(struct weston_view *view)
|
|
|
|
{
|
|
|
|
struct weston_output *output, *first_output;
|
|
|
|
struct weston_compositor *ec = view->surface->compositor;
|
|
|
|
struct shell_surface *shsurf;
|
|
|
|
float x, y;
|
|
|
|
int visible;
|
|
|
|
|
|
|
|
x = view->geometry.x;
|
|
|
|
y = view->geometry.y;
|
|
|
|
|
|
|
|
/* At this point the destroyed output is not in the list anymore.
|
|
|
|
* If the view is still visible somewhere, we leave where it is,
|
|
|
|
* otherwise, move it to the first output. */
|
|
|
|
visible = 0;
|
|
|
|
wl_list_for_each(output, &ec->output_list, link) {
|
|
|
|
if (pixman_region32_contains_point(&output->region,
|
|
|
|
x, y, NULL)) {
|
|
|
|
visible = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!visible) {
|
|
|
|
first_output = container_of(ec->output_list.next,
|
|
|
|
struct weston_output, link);
|
|
|
|
|
|
|
|
x = first_output->x + first_output->width / 4;
|
|
|
|
y = first_output->y + first_output->height / 4;
|
|
|
|
|
|
|
|
weston_view_set_position(view, x, y);
|
|
|
|
} else {
|
|
|
|
weston_view_geometry_dirty(view);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
shsurf = get_shell_surface(view->surface);
|
|
|
|
|
|
|
|
if (shsurf) {
|
|
|
|
shsurf->saved_position_valid = false;
|
|
|
|
shsurf->next_state.maximized = false;
|
|
|
|
shsurf->next_state.fullscreen = false;
|
|
|
|
shsurf->state_changed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_output_destroy_move_layer(struct desktop_shell *shell,
|
|
|
|
struct weston_layer *layer,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
struct weston_output *output = data;
|
|
|
|
struct weston_view *view;
|
|
|
|
|
|
|
|
wl_list_for_each(view, &layer->view_list.link, layer_link.link) {
|
|
|
|
if (view->output != output)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
shell_reposition_view_on_output_destroy(view);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_output_destroy(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct shell_output *output_listener =
|
|
|
|
container_of(listener, struct shell_output, destroy_listener);
|
|
|
|
struct weston_output *output = output_listener->output;
|
|
|
|
struct desktop_shell *shell = output_listener->shell;
|
|
|
|
|
|
|
|
shell_for_each_layer(shell, shell_output_destroy_move_layer, output);
|
|
|
|
|
|
|
|
wl_list_remove(&output_listener->destroy_listener.link);
|
|
|
|
wl_list_remove(&output_listener->link);
|
|
|
|
free(output_listener);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_resize_surface_to_output(struct desktop_shell *shell,
|
|
|
|
struct weston_surface *surface,
|
|
|
|
const struct weston_output *output)
|
|
|
|
{
|
|
|
|
if (!surface)
|
|
|
|
return;
|
|
|
|
|
|
|
|
weston_desktop_shell_send_configure(shell->child.desktop_shell, 0,
|
|
|
|
surface->resource,
|
|
|
|
output->width,
|
|
|
|
output->height);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_output_resized(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell =
|
|
|
|
container_of(listener, struct desktop_shell, resized_listener);
|
|
|
|
struct weston_output *output = (struct weston_output *)data;
|
|
|
|
struct shell_output *sh_output = find_shell_output_from_weston_output(shell, output);
|
|
|
|
|
|
|
|
shell_resize_surface_to_output(shell, sh_output->background_surface, output);
|
|
|
|
shell_resize_surface_to_output(shell, sh_output->panel_surface, output);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
create_shell_output(struct desktop_shell *shell,
|
|
|
|
struct weston_output *output)
|
|
|
|
{
|
|
|
|
struct shell_output *shell_output;
|
|
|
|
|
|
|
|
shell_output = zalloc(sizeof *shell_output);
|
|
|
|
if (shell_output == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
shell_output->output = output;
|
|
|
|
shell_output->shell = shell;
|
|
|
|
shell_output->destroy_listener.notify = handle_output_destroy;
|
|
|
|
wl_signal_add(&output->destroy_signal,
|
|
|
|
&shell_output->destroy_listener);
|
|
|
|
wl_list_insert(shell->output_list.prev, &shell_output->link);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_output_create(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell =
|
|
|
|
container_of(listener, struct desktop_shell, output_create_listener);
|
|
|
|
struct weston_output *output = (struct weston_output *)data;
|
|
|
|
|
|
|
|
create_shell_output(shell, output);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_output_move_layer(struct desktop_shell *shell,
|
|
|
|
struct weston_layer *layer, void *data)
|
|
|
|
{
|
|
|
|
struct weston_output *output = data;
|
|
|
|
struct weston_view *view;
|
|
|
|
float x, y;
|
|
|
|
|
|
|
|
wl_list_for_each(view, &layer->view_list.link, layer_link.link) {
|
|
|
|
if (view->output != output)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
x = view->geometry.x + output->move_x;
|
|
|
|
y = view->geometry.y + output->move_y;
|
|
|
|
weston_view_set_position(view, x, y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_output_move(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct desktop_shell *shell;
|
|
|
|
|
|
|
|
shell = container_of(listener, struct desktop_shell,
|
|
|
|
output_move_listener);
|
|
|
|
|
|
|
|
shell_for_each_layer(shell, handle_output_move_layer, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
setup_output_destroy_handler(struct weston_compositor *ec,
|
|
|
|
struct desktop_shell *shell)
|
|
|
|
{
|
|
|
|
struct weston_output *output;
|
|
|
|
|
|
|
|
wl_list_init(&shell->output_list);
|
|
|
|
wl_list_for_each(output, &ec->output_list, link)
|
|
|
|
create_shell_output(shell, output);
|
|
|
|
|
|
|
|
shell->output_create_listener.notify = handle_output_create;
|
|
|
|
wl_signal_add(&ec->output_created_signal,
|
|
|
|
&shell->output_create_listener);
|
|
|
|
|
|
|
|
shell->output_move_listener.notify = handle_output_move;
|
|
|
|
wl_signal_add(&ec->output_moved_signal, &shell->output_move_listener);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
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;
|
|
|
|
|
|
|
|
/* Force state to unlocked so we don't try to fade */
|
|
|
|
shell->locked = false;
|
shell: fix race on desktop-shell exit
The desktop shell plugin registers both a wl_client destroy signal
listener, and a sigchld handler, when launching weston-desktop-shell.
However, nothing guarantees in which order do the wl_client destructor
and the sigchld handler run.
Luckily, the sigchld handler cannot interrupt any code, because we
handle the signal via signalfd, which means it is handled like any event
in the compositor's main event loop.
Still, shell.c has a race, that when lost, can cause a crash, as
described in bug #82957.
If the sigchld handler happens to run first, it will try to launch a new
weston-desktop-shell without removing the destroy listener from the old
wl_client first. This leads to list corruption, that may cause a crash
when the old wl_client gets destroyed.
Simply removing the destroy listener in the sigchld handler is not
enough, because respawning sets shell->child.client pointer, and if
the wl_client destructor runs after, it will reset it to NULL.
OTOH, the wl_client destroy handler cannot reset shell->child.process,
because that would cause the sigchld handler in weston core to not find
the process tracker anymore, and report that an unknown process exited.
Turns out, that to make everything work, we would need to wait for both
the wl_client destructor and the sigchld handler to have run, before
respawn. This gets tricky.
Instead, solve the problem by removing shell->child.process. Use the new
weston_client_start() which automatically creates and manages the struct
weston_process. The shell does not need to know about the process exit,
it only needs to know about the client disconnect. Weston-desktop-shell
will never attempt to reconnect, and it would not work even if it did,
so disconnect is equivalent to weston-desktop-shell exiting.
This should permanently solve the race for weston-desktop-shell.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=82957
Cc: Boyan Ding <stu_dby@126.com>
Cc: Derek Foreman <derekf@osg.samsung.com>
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Derek Foreman <derekf@osg.samsung.com>
10 years ago
|
|
|
|
|
|
|
if (shell->child.client) {
|
|
|
|
/* disable respawn */
|
|
|
|
wl_list_remove(&shell->child.client_destroy_listener.link);
|
|
|
|
wl_client_destroy(shell->child.client);
|
shell: fix race on desktop-shell exit
The desktop shell plugin registers both a wl_client destroy signal
listener, and a sigchld handler, when launching weston-desktop-shell.
However, nothing guarantees in which order do the wl_client destructor
and the sigchld handler run.
Luckily, the sigchld handler cannot interrupt any code, because we
handle the signal via signalfd, which means it is handled like any event
in the compositor's main event loop.
Still, shell.c has a race, that when lost, can cause a crash, as
described in bug #82957.
If the sigchld handler happens to run first, it will try to launch a new
weston-desktop-shell without removing the destroy listener from the old
wl_client first. This leads to list corruption, that may cause a crash
when the old wl_client gets destroyed.
Simply removing the destroy listener in the sigchld handler is not
enough, because respawning sets shell->child.client pointer, and if
the wl_client destructor runs after, it will reset it to NULL.
OTOH, the wl_client destroy handler cannot reset shell->child.process,
because that would cause the sigchld handler in weston core to not find
the process tracker anymore, and report that an unknown process exited.
Turns out, that to make everything work, we would need to wait for both
the wl_client destructor and the sigchld handler to have run, before
respawn. This gets tricky.
Instead, solve the problem by removing shell->child.process. Use the new
weston_client_start() which automatically creates and manages the struct
weston_process. The shell does not need to know about the process exit,
it only needs to know about the client disconnect. Weston-desktop-shell
will never attempt to reconnect, and it would not work even if it did,
so disconnect is equivalent to weston-desktop-shell exiting.
This should permanently solve the race for weston-desktop-shell.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=82957
Cc: Boyan Ding <stu_dby@126.com>
Cc: Derek Foreman <derekf@osg.samsung.com>
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Derek Foreman <derekf@osg.samsung.com>
10 years ago
|
|
|
}
|
|
|
|
|
|
|
|
wl_list_remove(&shell->idle_listener.link);
|
|
|
|
wl_list_remove(&shell->wake_listener.link);
|
|
|
|
wl_list_remove(&shell->transform_listener.link);
|
|
|
|
|
text_backend: make destructor call explicit
We used to rely on the order in which the
weston_compositor::destroy_signal callbacks happened, to not access
freed memory. Don't know when, but this broke at least with ivi-shell,
which caused crashes in random places on compositor shutdown.
Valgrind found the following:
Invalid write of size 8
at 0xC2EDC69: unbind_input_panel (input-panel-ivi.c:340)
by 0x4E3B6BB: destroy_resource (wayland-server.c:537)
by 0x4E3E085: for_each_helper.isra.0 (wayland-util.c:359)
by 0x4E3E60D: wl_map_for_each (wayland-util.c:365)
by 0x4E3BEC7: wl_client_destroy (wayland-server.c:675)
by 0x4182F2: text_backend_notifier_destroy (text-backend.c:1047)
by 0x4084FB: wl_signal_emit (wayland-server-core.h:264)
by 0x4084FB: main (compositor.c:5465)
Address 0x67ea360 is 208 bytes inside a block of size 232 free'd
at 0x4C2A6BC: free (vg_replace_malloc.c:473)
by 0x4084FB: wl_signal_emit (wayland-server-core.h:264)
by 0x4084FB: main (compositor.c:5465)
Invalid write of size 8
at 0x4E3E0D7: wl_list_remove (wayland-util.c:57)
by 0xC2EDEE9: destroy_input_panel_surface (input-panel-ivi.c:191)
by 0x4E3B6BB: destroy_resource (wayland-server.c:537)
by 0x4E3BC7B: wl_resource_destroy (wayland-server.c:550)
by 0x40DB8B: wl_signal_emit (wayland-server-core.h:264)
by 0x40DB8B: weston_surface_destroy (compositor.c:1883)
by 0x40DB8B: weston_surface_destroy (compositor.c:1873)
by 0x4E3B6BB: destroy_resource (wayland-server.c:537)
by 0x4E3E085: for_each_helper.isra.0 (wayland-util.c:359)
by 0x4E3E60D: wl_map_for_each (wayland-util.c:365)
by 0x4E3BEC7: wl_client_destroy (wayland-server.c:675)
by 0x4182F2: text_backend_notifier_destroy (text-backend.c:1047)
by 0x4084FB: wl_signal_emit (wayland-server-core.h:264)
by 0x4084FB: main (compositor.c:5465)
Address 0x67ea370 is 224 bytes inside a block of size 232 free'd
at 0x4C2A6BC: free (vg_replace_malloc.c:473)
by 0x4084FB: wl_signal_emit (wayland-server-core.h:264)
by 0x4084FB: main (compositor.c:5465)
Invalid write of size 8
at 0x4E3E0E7: wl_list_remove (wayland-util.c:58)
by 0xC2EDEE9: destroy_input_panel_surface (input-panel-ivi.c:191)
by 0x4E3B6BB: destroy_resource (wayland-server.c:537)
by 0x4E3BC7B: wl_resource_destroy (wayland-server.c:550)
by 0x40DB8B: wl_signal_emit (wayland-server-core.h:264)
by 0x40DB8B: weston_surface_destroy (compositor.c:1883)
by 0x40DB8B: weston_surface_destroy (compositor.c:1873)
by 0x4E3B6BB: destroy_resource (wayland-server.c:537)
by 0x4E3E085: for_each_helper.isra.0 (wayland-util.c:359)
by 0x4E3E60D: wl_map_for_each (wayland-util.c:365)
by 0x4E3BEC7: wl_client_destroy (wayland-server.c:675)
by 0x4182F2: text_backend_notifier_destroy (text-backend.c:1047)
by 0x4084FB: wl_signal_emit (wayland-server-core.h:264)
by 0x4084FB: main (compositor.c:5465)
Address 0x67ea368 is 216 bytes inside a block of size 232 free'd
at 0x4C2A6BC: free (vg_replace_malloc.c:473)
by 0x4084FB: wl_signal_emit (wayland-server-core.h:264)
by 0x4084FB: main (compositor.c:5465)
Looking at the first of these, unbind_input_panel() gets called when the
text-backend destroys its helper client which has bound to input_panel
interface. This happens after the shell's destroy_signal callback has
been called, so the shell has already been freed.
The other two errors come from
wl_list_remove(&input_panel_surface->link);
which has gone stale when the shell was destroyed
(shell->input_panel.surfaces list).
Rather than creating even more destroy listeners and hooking them up in
spaghetti, modify text-backend to not hook up to the compositor destroy
signal. Instead, make it the text_backend_init() callers' responsibility
to also call text_backend_destroy() appropriately, before the shell goes
away.
This fixed all the above Valgrind errors, and avoid a crash with
ivi-shell when exiting Weston.
Also using desktop-shell exhibited similar Valgrind errors which are
fixed by this patch, but those didn't happen to cause any crashes AFAIK.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-By: Derek Foreman <derekf@osg.samsung.com>
10 years ago
|
|
|
text_backend_destroy(shell->text_backend);
|
|
|
|
input_panel_destroy(shell);
|
|
|
|
|
|
|
|
wl_list_for_each_safe(shell_output, tmp, &shell->output_list, link) {
|
|
|
|
wl_list_remove(&shell_output->destroy_listener.link);
|
|
|
|
wl_list_remove(&shell_output->link);
|
|
|
|
free(shell_output);
|
|
|
|
}
|
|
|
|
|
|
|
|
wl_list_remove(&shell->output_create_listener.link);
|
|
|
|
wl_list_remove(&shell->output_move_listener.link);
|
|
|
|
wl_list_remove(&shell->resized_listener.link);
|
|
|
|
|
|
|
|
wl_array_for_each(ws, &shell->workspaces.array)
|
|
|
|
workspace_destroy(*ws);
|
|
|
|
wl_array_release(&shell->workspaces.array);
|
|
|
|
|
|
|
|
free(shell->client);
|
|
|
|
free(shell);
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
MODIFIER_CTRL | MODIFIER_ALT,
|
|
|
|
terminate_binding, ec);
|
|
|
|
|
|
|
|
/* fixed bindings */
|
|
|
|
weston_compositor_add_button_binding(ec, BTN_LEFT, 0,
|
|
|
|
click_to_activate_binding,
|
|
|
|
shell);
|
|
|
|
weston_compositor_add_button_binding(ec, BTN_RIGHT, 0,
|
|
|
|
click_to_activate_binding,
|
|
|
|
shell);
|
|
|
|
weston_compositor_add_touch_binding(ec, 0,
|
|
|
|
touch_to_activate_binding,
|
|
|
|
shell);
|
|
|
|
weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
|
|
|
|
MODIFIER_SUPER | MODIFIER_ALT,
|
|
|
|
surface_opacity_binding, NULL);
|
|
|
|
weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
|
|
|
|
MODIFIER_SUPER, zoom_axis_binding,
|
|
|
|
NULL);
|
|
|
|
weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSDOWN, 0,
|
|
|
|
backlight_binding, ec);
|
|
|
|
weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSUP, 0,
|
|
|
|
backlight_binding, ec);
|
|
|
|
|
|
|
|
/* configurable bindings */
|
|
|
|
if (shell->exposay_modifier)
|
|
|
|
weston_compositor_add_modifier_binding(ec, shell->exposay_modifier,
|
|
|
|
exposay_binding, shell);
|
|
|
|
|
|
|
|
mod = shell->binding_modifier;
|
|
|
|
if (!mod)
|
|
|
|
return;
|
|
|
|
|
|
|
|
weston_compositor_add_key_binding(ec, KEY_PAGEUP, mod,
|
|
|
|
zoom_key_binding, NULL);
|
|
|
|
weston_compositor_add_key_binding(ec, KEY_PAGEDOWN, mod,
|
|
|
|
zoom_key_binding, NULL);
|
|
|
|
weston_compositor_add_key_binding(ec, KEY_M, mod | MODIFIER_SHIFT,
|
|
|
|
maximize_binding, NULL);
|
|
|
|
weston_compositor_add_key_binding(ec, KEY_F, mod | MODIFIER_SHIFT,
|
|
|
|
fullscreen_binding, NULL);
|
|
|
|
weston_compositor_add_button_binding(ec, BTN_LEFT, mod, move_binding,
|
|
|
|
shell);
|
|
|
|
weston_compositor_add_touch_binding(ec, mod, touch_move_binding, shell);
|
|
|
|
weston_compositor_add_button_binding(ec, BTN_RIGHT, mod,
|
|
|
|
resize_binding, shell);
|
|
|
|
weston_compositor_add_button_binding(ec, BTN_LEFT,
|
|
|
|
mod | MODIFIER_SHIFT,
|
|
|
|
resize_binding, shell);
|
|
|
|
|
|
|
|
if (ec->capabilities & WESTON_CAP_ROTATION_ANY)
|
|
|
|
weston_compositor_add_button_binding(ec, BTN_MIDDLE, mod,
|
|
|
|
rotate_binding, NULL);
|
|
|
|
|
|
|
|
weston_compositor_add_key_binding(ec, KEY_TAB, mod, switcher_binding,
|
|
|
|
shell);
|
|
|
|
weston_compositor_add_key_binding(ec, KEY_F9, mod, backlight_binding,
|
|
|
|
ec);
|
|
|
|
weston_compositor_add_key_binding(ec, KEY_F10, mod, backlight_binding,
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_seat_created(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
struct weston_seat *seat = data;
|
|
|
|
|
|
|
|
create_shell_seat(seat);
|
|
|
|
}
|
|
|
|
|
|
|
|
WL_EXPORT int
|
|
|
|
module_init(struct weston_compositor *ec,
|
|
|
|
int *argc, char *argv[])
|
|
|
|
{
|
|
|
|
struct weston_seat *seat;
|
|
|
|
struct desktop_shell *shell;
|
|
|
|
struct workspace **pws;
|
|
|
|
unsigned int i;
|
|
|
|
struct wl_event_loop *loop;
|
|
|
|
|
|
|
|
shell = zalloc(sizeof *shell);
|
|
|
|
if (shell == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
shell->compositor = ec;
|
|
|
|
|
|
|
|
shell->destroy_listener.notify = shell_destroy;
|
|
|
|
wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
|
|
|
|
shell->idle_listener.notify = idle_handler;
|
|
|
|
wl_signal_add(&ec->idle_signal, &shell->idle_listener);
|
|
|
|
shell->wake_listener.notify = wake_handler;
|
|
|
|
wl_signal_add(&ec->wake_signal, &shell->wake_listener);
|
|
|
|
shell->transform_listener.notify = transform_handler;
|
|
|
|
wl_signal_add(&ec->transform_signal, &shell->transform_listener);
|
|
|
|
|
|
|
|
ec->shell_interface.shell = shell;
|
|
|
|
ec->shell_interface.create_shell_surface = create_shell_surface;
|
|
|
|
ec->shell_interface.set_toplevel = set_toplevel;
|
|
|
|
ec->shell_interface.set_transient = set_transient;
|
|
|
|
ec->shell_interface.set_fullscreen = shell_interface_set_fullscreen;
|
|
|
|
ec->shell_interface.set_xwayland = set_xwayland;
|
|
|
|
ec->shell_interface.move = shell_interface_move;
|
|
|
|
ec->shell_interface.resize = shell_interface_resize;
|
|
|
|
ec->shell_interface.set_title = set_title;
|
shell: Replace set_margin with set_window_geometry
Currently, there is a fun flicker when toggling maximization or
fullscreen on a window in mutter or more sophisicated compositors
and WMs.
What happens is that the client want so go maximized, so we
calculate the size that we want the window to resize to (640x480),
and then add on its margins to find the buffer size (+10 = 660x500),
and then send out a configure event for that size. The client
renders to that size, realizes that it's maximized, and then
says "oh hey, my margins are actually 0 now!", and so the compositor
has to send out another configure event.
In order to fix this, make the the configure request correspond to
the window geometry we'd like the window to be at. At the same time,
replace set_margin with set_window_geometry, where we specify a rect
rather than a border around the window.
11 years ago
|
|
|
ec->shell_interface.set_window_geometry = set_window_geometry;
|
|
|
|
ec->shell_interface.set_maximized = shell_interface_set_maximized;
|
|
|
|
ec->shell_interface.set_pid = set_pid;
|
|
|
|
ec->shell_interface.get_output_work_area = get_output_work_area;
|
|
|
|
|
|
|
|
weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link);
|
|
|
|
weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link);
|
|
|
|
weston_layer_init(&shell->background_layer, &shell->panel_layer.link);
|
|
|
|
weston_layer_init(&shell->lock_layer, NULL);
|
|
|
|
weston_layer_init(&shell->input_panel_layer, NULL);
|
|
|
|
|
|
|
|
wl_array_init(&shell->workspaces.array);
|
|
|
|
wl_list_init(&shell->workspaces.client_list);
|
|
|
|
|
|
|
|
if (input_panel_setup(shell) < 0)
|
|
|
|
return -1;
|
|
|
|
|
text_backend: make destructor call explicit
We used to rely on the order in which the
weston_compositor::destroy_signal callbacks happened, to not access
freed memory. Don't know when, but this broke at least with ivi-shell,
which caused crashes in random places on compositor shutdown.
Valgrind found the following:
Invalid write of size 8
at 0xC2EDC69: unbind_input_panel (input-panel-ivi.c:340)
by 0x4E3B6BB: destroy_resource (wayland-server.c:537)
by 0x4E3E085: for_each_helper.isra.0 (wayland-util.c:359)
by 0x4E3E60D: wl_map_for_each (wayland-util.c:365)
by 0x4E3BEC7: wl_client_destroy (wayland-server.c:675)
by 0x4182F2: text_backend_notifier_destroy (text-backend.c:1047)
by 0x4084FB: wl_signal_emit (wayland-server-core.h:264)
by 0x4084FB: main (compositor.c:5465)
Address 0x67ea360 is 208 bytes inside a block of size 232 free'd
at 0x4C2A6BC: free (vg_replace_malloc.c:473)
by 0x4084FB: wl_signal_emit (wayland-server-core.h:264)
by 0x4084FB: main (compositor.c:5465)
Invalid write of size 8
at 0x4E3E0D7: wl_list_remove (wayland-util.c:57)
by 0xC2EDEE9: destroy_input_panel_surface (input-panel-ivi.c:191)
by 0x4E3B6BB: destroy_resource (wayland-server.c:537)
by 0x4E3BC7B: wl_resource_destroy (wayland-server.c:550)
by 0x40DB8B: wl_signal_emit (wayland-server-core.h:264)
by 0x40DB8B: weston_surface_destroy (compositor.c:1883)
by 0x40DB8B: weston_surface_destroy (compositor.c:1873)
by 0x4E3B6BB: destroy_resource (wayland-server.c:537)
by 0x4E3E085: for_each_helper.isra.0 (wayland-util.c:359)
by 0x4E3E60D: wl_map_for_each (wayland-util.c:365)
by 0x4E3BEC7: wl_client_destroy (wayland-server.c:675)
by 0x4182F2: text_backend_notifier_destroy (text-backend.c:1047)
by 0x4084FB: wl_signal_emit (wayland-server-core.h:264)
by 0x4084FB: main (compositor.c:5465)
Address 0x67ea370 is 224 bytes inside a block of size 232 free'd
at 0x4C2A6BC: free (vg_replace_malloc.c:473)
by 0x4084FB: wl_signal_emit (wayland-server-core.h:264)
by 0x4084FB: main (compositor.c:5465)
Invalid write of size 8
at 0x4E3E0E7: wl_list_remove (wayland-util.c:58)
by 0xC2EDEE9: destroy_input_panel_surface (input-panel-ivi.c:191)
by 0x4E3B6BB: destroy_resource (wayland-server.c:537)
by 0x4E3BC7B: wl_resource_destroy (wayland-server.c:550)
by 0x40DB8B: wl_signal_emit (wayland-server-core.h:264)
by 0x40DB8B: weston_surface_destroy (compositor.c:1883)
by 0x40DB8B: weston_surface_destroy (compositor.c:1873)
by 0x4E3B6BB: destroy_resource (wayland-server.c:537)
by 0x4E3E085: for_each_helper.isra.0 (wayland-util.c:359)
by 0x4E3E60D: wl_map_for_each (wayland-util.c:365)
by 0x4E3BEC7: wl_client_destroy (wayland-server.c:675)
by 0x4182F2: text_backend_notifier_destroy (text-backend.c:1047)
by 0x4084FB: wl_signal_emit (wayland-server-core.h:264)
by 0x4084FB: main (compositor.c:5465)
Address 0x67ea368 is 216 bytes inside a block of size 232 free'd
at 0x4C2A6BC: free (vg_replace_malloc.c:473)
by 0x4084FB: wl_signal_emit (wayland-server-core.h:264)
by 0x4084FB: main (compositor.c:5465)
Looking at the first of these, unbind_input_panel() gets called when the
text-backend destroys its helper client which has bound to input_panel
interface. This happens after the shell's destroy_signal callback has
been called, so the shell has already been freed.
The other two errors come from
wl_list_remove(&input_panel_surface->link);
which has gone stale when the shell was destroyed
(shell->input_panel.surfaces list).
Rather than creating even more destroy listeners and hooking them up in
spaghetti, modify text-backend to not hook up to the compositor destroy
signal. Instead, make it the text_backend_init() callers' responsibility
to also call text_backend_destroy() appropriately, before the shell goes
away.
This fixed all the above Valgrind errors, and avoid a crash with
ivi-shell when exiting Weston.
Also using desktop-shell exhibited similar Valgrind errors which are
fixed by this patch, but those didn't happen to cause any crashes AFAIK.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-By: Derek Foreman <derekf@osg.samsung.com>
10 years ago
|
|
|
shell->text_backend = text_backend_init(ec);
|
|
|
|
if (!shell->text_backend)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
shell_configuration(shell);
|
|
|
|
|
|
|
|
shell->exposay.state_cur = EXPOSAY_LAYOUT_INACTIVE;
|
|
|
|
shell->exposay.state_target = EXPOSAY_TARGET_CANCEL;
|
|
|
|
|
|
|
|
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();
|
|
|
|
if (*pws == NULL)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
activate_workspace(shell, 0);
|
|
|
|
|
|
|
|
weston_layer_init(&shell->minimized_layer, NULL);
|
|
|
|
|
|
|
|
wl_list_init(&shell->workspaces.anim_sticky_list);
|
|
|
|
wl_list_init(&shell->workspaces.animation.link);
|
|
|
|
shell->workspaces.animation.frame = animate_workspace_change_frame;
|
|
|
|
|
|
|
|
if (wl_global_create(ec->wl_display, &wl_shell_interface, 1,
|
|
|
|
shell, bind_shell) == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (wl_global_create(ec->wl_display, &xdg_shell_interface, 1,
|
|
|
|
shell, bind_xdg_shell) == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (wl_global_create(ec->wl_display,
|
|
|
|
&weston_desktop_shell_interface, 1,
|
|
|
|
shell, bind_desktop_shell) == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
shell->child.deathstamp = weston_compositor_get_time();
|
|
|
|
|
|
|
|
shell->panel_position = WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP;
|
|
|
|
|
|
|
|
setup_output_destroy_handler(ec, shell);
|
|
|
|
|
|
|
|
loop = wl_display_get_event_loop(ec->wl_display);
|
|
|
|
wl_event_loop_add_idle(loop, launch_desktop_shell_process, shell);
|
|
|
|
|
|
|
|
wl_list_for_each(seat, &ec->seat_list, link)
|
|
|
|
handle_seat_created(NULL, seat);
|
|
|
|
shell->seat_create_listener.notify = handle_seat_created;
|
|
|
|
wl_signal_add(&ec->seat_created_signal, &shell->seat_create_listener);
|
|
|
|
|
|
|
|
shell->resized_listener.notify = handle_output_resized;
|
|
|
|
wl_signal_add(&ec->output_resized_signal, &shell->resized_listener);
|
|
|
|
|
|
|
|
screenshooter_create(ec);
|
|
|
|
|
|
|
|
shell_add_bindings(ec, shell);
|
|
|
|
|
shell: wait for desktop-shell init before fade in
On Raspberry Pi, weston-desktop-shell is so slow to start, that the
compositor has time to run the fade-in before the wallpaper is up. The
user launching Weston sees the screen flipping to black, the fbcon
fading in, and then the desktop popping up.
To fix this, wait for the weston-desktop-shell to draw
everything before starting the initial fade-in. A new request is
added to the private desktop-shell protocol to signal it. If a
desktop-shell client does not support the new request, the fade-in
happens already at bind time.
If weston-desktop-shell crashes, or does not send the 'desktop_ready'
request in 15 seconds, the compositor will fade in anyway. This should
avoid a blocked screen in case weston-desktop-shell malfunction.
shell_fade_startup() does not directly start the fade-in but schedules
an idle callback, so that the compositor can process all pending events
before starting the fade clock. Otherwise (on RPi) we risk skipping part
of the animation. Yes, it is a hack, that should have been done in
window.c and weston-desktop-shell instead.
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
12 years ago
|
|
|
shell_fade_init(shell);
|
compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
12 years ago
|
|
|
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &shell->startup_time);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|