Copyright © 2024 the Contributors to the Captured Surface Control Specification, published by the Screen Capture Community Group under the W3C Community Contributor License Agreement (CLA) . A human-readable summary is available.
Consider
a
Web
application
capturer
which
has
used
getDisplayMedia
()
to
start
capturing
another
display
surface
,
capturee
.
This
specification
introduces
a
set
of
APIs
that
allow
capturer
the
following
new
capabilities:
Initially, these are only specified for captured display surfaces of type browser , but an extension to window is considered.
This specification was published by the Screen Capture Community Group . It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups .
GitHub Issues are preferred for discussion of this specification.
Nearly all video-conferencing Web applications offer their users the ability to share display surfaces - typically a browser tab ( browser ), a native app's window ( window ), or an entire screen ( monitor ).
Many of these applications also show the local user a "preview tile" with a video of the captured display surface .
All these applications suffer from one key drawback - if the user wishes to interact with a captured display surface , the user must first switch to that surface, taking them away from the video-conferencing application. This presents a few issues:
It bears mentioning that Document Picture-in-Picture goes a long way towards addressing some of these issues. However, it not always a suitable solution, as not all use cases are adequately addressed by a floating window which will often be small, which obscures arbitrary other content on the screen, and whose size and positioning must be manually controlled by the user.
This
specification
defines
a
policy-controlled
feature
identified
by
the
string
"captured-surface-control"
.
Its
default
allowlist
is
"self"
.
The
API
surfaces
introduced
by
this
specification
can
be
categorized
as
either
read-access
or
write-access.
Note
that
only
the
write-access
APIs
(
setZoomLevel
and
)
are
gated
by
the
captureWheel
forwardGestures
"captured-surface-control"
permissions
policy.
We define a concept of an integer " zoom level " that can be applied to display surfaces of any type, and which is independent of the user agent and the platform. It is expected that in the case of browser display surfaces , this concept will match the concept of zoom level that user agents typically exposed to the user.
For a given display surface of type surfaceType , we define the user agent's set of supported zoom levels for surfaceType as a non-empty set of integers including at least the default zoom level (100), and not including any integers lesser than 1.
We define the permitted event types for setZoomLevel as a set composed of the following event types :
WebIDLpartial interface CaptureController {
sequence<long> getSupportedZoomLevels();
long getZoomLevel();
Promise<undefined> setZoomLevel(long zoomLevel);
attribute EventHandler oncapturedzoomlevelchange;
};
getSupportedZoomLevels()
This method allows applications to discover the set of zoom levels supported by the user agent.
When invoked, the user agent MUST run the following steps:
InvalidStateError
"
DOMException
.
NotSupportedError
"
DOMException
.
getZoomLevel()
This method allows applications to discover the captured display surface 's zoom level .
When invoked, the user agent MUST run the following steps:
InvalidStateError
"
DOMException
.
NotSupportedError
"
DOMException
.
setZoomLevel()
This method allows applications to set the captured display surface 's zoom level .
When invoked, the user agent MUST run the following steps:
DOMException
object
whose
name
attribute
has
the
value
InvalidStateError
.
DOMException
object
whose
name
attribute
has
the
value
NotSupportedError
.
Ensure that the code is running from within the context of an event handler which was triggered by the browser agent firing a trusted event, triggered by the user interacting with the user agent. To do so, run the following steps:
Window
.
event
.
undefined
,
return
a
promise
rejected
with
a
DOMException
object
whose
name
attribute
has
the
value
InvalidStateError
.
isTrusted
is
false
,
return
a
promise
rejected
with
a
DOMException
object
whose
name
attribute
has
the
value
InvalidStateError
.
type
is
not
in
permitted
event
types
for
setZoomLevel
,
return
a
promise
rejected
with
a
DOMException
object
whose
name
attribute
has
the
value
InvalidStateError
.
It
follows
from
these
steps
that
setZoomLevel
()
is
only
callable
with
transient
activation
,
because
permitted
event
types
for
setZoomLevel
only
contains
event
types
that
confer
this
activation.
In
fact,
our
API
shape
implies
a
stronger
guarantee
-
whereas
transient
activation
persists
for
several
seconds
after
the
user
action,
the
API
shape
here
limits
setZoomLevel
()
to
being
called
immediately
following
the
user's
action.
DOMException
object
whose
name
attribute
has
the
value
InvalidStateError
.
Promise
.
Run the following steps in parallel :
PermissionDescriptor
with
its
name
member
set
to
"captured-surface-control"
.
If
the
result
of
the
request
is
"
denied
",
reject
P
with
a
new
DOMException
object
whose
name
is
NotAllowedError
and
abort
these
steps.
oncapturedzoomlevelchange
The
user
agent
MUST
fire
a
blank
event
on
this
EventHandler
whenever
this
.
[[Source]]
's
zoom
level
changes.
Examples of causes include:
setZoomLevel
()
.
We
introuce
APIs
to
allow
forwarding
of
specific
gestures
from
the
capturing
application
to
the
captured
application.
The
set
of
gestures
comprises
those
gestures
that
are
considered
safe
to
forward,
subject
to
the
"captured-surface-control"
PermissionsPolicy
.
Future support for such gestures as "click" is NOT envisioned.
WebIDLdictionary ForwardedGestures { boolean wheel = false;
};
wheel
Whether
the
application
calling
forwardGestures
()
wants
wheel
events
to
be
forwarded
from
the
indicated
element
to
the
captured
surface.
WebIDLpartial interface CaptureController {
constructor();
Promise<undefined> forwardGestures(
HTMLElement element,
optional ForwardedGestures gestures = {});
};
constructor
CaptureController
's
constructor
is
extended
to
also
define
and
initialize
the
following
internal
slots:
| Internal Slot | Initial value |
|---|---|
|
|
|
captureWheel()
forwardGestures()
This
method
allows
applications
to
automatically
forward
gesture
events
(e.g.
wheel
events
)
from
an
HTMLElement
to
the
viewport
of
a
captured
display
surface
.
When invoked, the user agent MUST run the following steps:
DOMException
object
whose
name
attribute
has
the
value
InvalidStateError
.
DOMException
object
whose
name
attribute
has
the
value
NotSupportedError
.
Promise
.
"captured-surface-control"
.
If
the
result
is
NOT
"
granted
",
and
the
relevant
global
object
does
NOT
have
transient
activation
,
return
a
promise
rejected
with
a
DOMException
object
whose
name
attribute
has
the
value
InvalidStateError
.
This
step
ensures
that
on
the
one
hand,
permission
prompts
are
not
be
shown
without
transient
activation
,
while
on
the
one
hand,
if
the
permission
is
already
"
granted
",
captureWheel
forwardGestures
()
may
be
called
immediately
after
getDisplayMedia
()
resolves,
even
if
the
transient
activation
that
permitted
the
call
to
captureWheel
forwardGestures
()
has
since
expired.
PermissionDescriptor
with
its
name
member
set
to
"captured-surface-control"
.
If
the
result
of
the
request
is
"
denied
",
reject
P
with
a
new
DOMException
object
whose
name
is
NotAllowedError
and
abort
these
steps.
[[CaptureWheelElement]]
[[GestureForwardingElementsMap]]
[[CaptureWheelElement]]
[[GestureForwardingElement]]
to
element
.
[[CaptureWheelEventListener]]
[[GestureForwardingEventListener]]
to
null
.
[[CaptureWheelElement]]
[[GestureForwardingElement]]
is
null
,
resolve
P
and
abort
these
steps.
[[CaptureWheelEventListener]]
[[GestureForwardingEventListener]]
to
an
event
listener
defined
as
follows:
wheel
EventListener
instance
representing
a
reference
to
a
function
of
one
argument
of
type
Event
event
.
This
function
executes
the
forward
wheel
event
algorithm
given
this
and
event
.
Add an event listener with:
[[CaptureWheelElement]]
[[GestureForwardingElement]]
as
eventTarget
.
[[CaptureWheelEventListener]]
[[GestureForwardingEventListener]]
as
listener
.
To
determine
if
a
CaptureController
controller
is
actively
capturing
,
run
the
following
steps:
null
,
return
false
.
false
.
true
.
To determine if a display surface surfaceType is supported display surface type , run the following steps:
true
.
false
.
Whether window should be supported is under discussion.
The
forward
wheel
event
algorithm
takes
a
CaptureController
controller
and
a
WheelEvent
event
,
and
runs
the
following
steps:
"captured-surface-control"
.
If
the
result
is
NOT
"
granted
",
abort
these
steps.
isTrusted
is
false
,
abort
these
steps.
offsetX
,
event
.
offsetY
]
and
this
.
[[CaptureWheelElement]]
[[GestureForwardingElement]]
.
"wheel"
using
WheelEvent
with
the
x
attribute
initialized
to
scaledX
,
the
y
attribute
initialized
to
scaledY
,
the
deltaX
attribute
initialized
to
event
.
deltaX
and
the
deltaY
attribute
initialized
to
event
.
deltaY
,
at
controller
.
[[Source]]
's
viewport.
The
scale
element
coordinates
algorithm
takes
double
coordinates
[
x
,
y
]
and
a
CaptureController
controller
,
and
run
the
following
steps:
(
x
/
controller
.
[[CaptureWheelElement]]
[[GestureForwardingElement]]
.
getBoundingClientRect
()
.
width
)
.
(
x
/
controller
.
[[CaptureWheelElement]]
[[GestureForwardingElement]]
.
getBoundingClientRect
()
.
height
)
.
(
scaleFactorX
*
surfaceWidth
)
.
(
scaleFactorY
*
surfaceHeight
)
.
This subroutine assumes that controller is actively capturing .
The API surfaces introduced in this specification allow a capturing application limited control over a captured application. These APIs allow the capturing application to gain access to additional pixels in the captured application. This specification employs multiple means to ensure that new capabilities are used in accordance with the user's intentions. Among these means:
PermissionsPolicy
called
"captured-surface-control"
is
used.
captureWheel
forwardGestures
()
is
designed
such
that
only
the
user's
scrolling
over
an
Element
can
trigger
scrolling
in
the
captured
application.
This
API
shape
ensures
that
the
capturing
application
can
only
forward
wheel
events
to
the
captured
application
at
the
time
when
the
user
agent
dispatches
the
trusted
wheel
event
on
the
capturing
application
itself.
setZoomLevel
()
is
only
callable
from
event
handlers
of
specific
event
types
-
the
permitted
event
types
for
setZoomLevel
.
These
are
events
dispatched
directly
by
the
user
agent,
triggered
by
user
interaction.
This
specification
intentionally
excludes
from
this
set
such
events
as
"mousemove"
,
which
users
are
liable
to
trigger
inadvertently.
The
shape
of
captureWheel
forwardGestures
()
is
intentionally
chosen
to
limit
the
capturing
application's
control.
The
application
designates
a
specific
element
which,
when
the
user
scrolls
over
it,
the
corresponding
wheel
events
are
forwarded
to
the
captured
application.
This
is
in
intentional
contrast
to
a
prior
API
shape,
sendWheel()
,
whereby
the
capturing
application
could
instigate
scrolling
of
the
captured
application
at
any
time.
This
specification
does
not
limit
the
type
of
Element
for
which
either
setZoomLevel
()
or
captureWheel
forwardGestures
()
work.
Such
a
limitation
would
accomplish
nothing,
because
malicious
applications
could
always
overlay
transparent
permitted
Element
types
on
top
of
visible
non-permitted
Element
s,
thereby
bypassing
this
restriction.
The
limitation
of
interaction
types
is
sufficient.
This
is
accomplished
by
captureWheel
forwardGestures
()
through
its
shape,
and
by
setZoomLevel
()
through
its
gating
on
event
types
.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key word MUST in this document is to be interpreted as described in BCP 14 [ RFC2119 ] [ RFC8174 ] when, and only when, they appear in all capitals, as shown here.
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: