Commit graph

114 commits

Author SHA1 Message Date
Daniel Eklöf
e6feed5311
wayland: remove debug logs 2020-03-06 19:19:18 +01:00
Daniel Eklöf
4f90cbda59
wayland: log: say 'requesting' instead of 'referring' client/server decorations 2020-03-06 19:18:59 +01:00
Daniel Eklöf
d76484ae50
wayland: set window geometry to exclude the invisible CSD borders
But it *does* include the title bar. This simplifies the 'adjustment'
needed to be done to the configured window size.

It also fixes a number of issues:

* the compositor will now properly snap the window to screen
  edges (before, there was an empty space between the edge and the
  window - the CSD border).
* This also removes the need for the mutter 'commit' workaround. We
  must be doing something right now.
2020-03-03 18:26:15 +01:00
Daniel Eklöf
f0892988c0
wayland: don't destroy keyboard/pointer if they haven't been removed
When the seat capabilities change, we used to destroy all pointers and
keyboards, and then re-creating them as necessary.

This caused a crash on mutter - probably because we removed a keyboard
device the compositor had already sent an event for (or was about to).

Now, we only destroy and create devices when it's needed.
2020-03-03 18:20:53 +01:00
Daniel Eklöf
9699c9b8bf
csd: initial implementation of minimize/maximize/close buttons 2020-03-02 20:29:28 +01:00
Daniel Eklöf
def4395bd1
wayland: log whether CSDs or SSDs are used at info level, not debug 2020-03-02 18:43:07 +01:00
Daniel Eklöf
22ce09eb44
config: make CSD user configurable
The user can now configure the following:

* Whether to prefer CSDs or SSDs. But note that this is only a hint to
  the compositor - it may deny our request. Furthermore, not all
  compositors implement the decoration manager protocol, meaning CSDs
  will be used regardless of the user configuration (GNOME/mutter
  being the most prominent one).
* Title bar size and color, including transparency
* Border size and color, including transparency

Also drop support for rendering the CSDs inside the main surface.
2020-03-02 18:42:49 +01:00
Daniel Eklöf
d6f0a47fb8
wayland: always update window->is_fullscreen, not just when using CSDs 2020-02-29 17:24:45 +01:00
Daniel Eklöf
32a3f56710
wayland: don't resize when we're not mapped anywhere
Normally, we resize and update the font's DPI whenever our window
enters or leaves an output.

This is since a change in the outputs we're mapped on means the scale
factor to use, or the DPI to use for the fonts may have changed.

However, a special case is when we're removed from the last
output. This should only happen at shutdown, when we're un-mapping
ourselves.

In this case, we typically don't have a access to e.g. the PTMX
fd (often, the reason we're shutting down is because the client
exited). This resulted in (harmless) error messages when emitting the
TIOCSWINSZ event.

Since we're shutting down anyway, we can simply skip the resize and
everything. This gets rid of the error message, and also means we're
shutting down faster.
2020-02-29 15:46:40 +01:00
Daniel Eklöf
43b07b122a
input: csd: add a small delay before initiating a move
This ensures the user has time to double-click to toggle the maximized
state.
2020-02-29 12:56:04 +01:00
Daniel Eklöf
c917a74f48
wayland: remove all usages of wayl_terminal_from_surface()
Use the 'user data' pointer from the wayland surface instead.
2020-02-29 12:13:58 +01:00
Daniel Eklöf
43c0551806
wayland: store pointer to window instance in all surfaces 2020-02-29 12:09:28 +01:00
Daniel Eklöf
6ba476b3bd
wayland: configure: work around GNOME/mutter weirdness
When resizing the window under mutter, mutter seems to expect a
configure ack *and* a surface commit *right* away, or things get out
of sync.

Unlike kwin, which is requires a commit for each configure ack, but is
fine with having the commit arrive later (after we've rendered it),
mutter is not.

I even tried delaying the configure ack until just before the commit,
but still no go.

So for now, detect when we're running under mutter and always do a
surface commit right away.

This can *not* be done on any other compositor as it breaks the CSD
and main surface synchronization; we've resized the CSDs, but not the
main surface.

I.e. this *should* not work, but for some reason is the *only* way to
make things work on mutter.

Interestingly, doing it any other way on mutter causes visual
glitches; window jumping around when resizing, or de-synchronized
CSDs/main surface.
2020-02-28 18:43:33 +01:00
Daniel Eklöf
b69c9b5f58
wayland: fix window size adjustment for CSDs placed outside main surface
* Do this both in XDG configure, and when the decoration manager
  switches between CSDs/SSDs at run-time.

* Exclude CSD borders when we're maximized
2020-02-28 18:42:10 +01:00
Daniel Eklöf
6c20abf279
wayland: warn when compositor doesn't implement the decoration manager interface 2020-02-28 18:37:07 +01:00
Daniel Eklöf
7d021b5b37
wayland: request server side decorations 2020-02-28 18:36:52 +01:00
Daniel Eklöf
3c7e17e8c1
wayland: drop required wl_output interface version from 3 -> 2
We don't need version 3, and mutter 3.34 only implements version 2.
2020-02-28 18:35:50 +01:00
Daniel Eklöf
02fedfb2fc
wayland: resize main surface when enabling CSDs runtime
When we position CSDs inside the main surface, and CSDs are switched
on run-time, we need to force a grid resize, since the actual window
content will now be smaller.

Alternative solution: call resize with width/height increased, to
account for the CSDs. This would increase the window size, but would
keep the grid size fixed.
2020-02-26 13:46:37 +01:00
Daniel Eklöf
5fbbd2f80e
wayland: track window maximized state 2020-02-26 13:23:00 +01:00
Daniel Eklöf
020ce60778
wayland: don't adjust size when CSDs are positioned inside main surface 2020-02-26 13:02:15 +01:00
Daniel Eklöf
6ca880bd3e
wayland: disable debug logs 2020-02-26 12:47:00 +01:00
Daniel Eklöf
1e1b204377
csd: don't draw CSDs in fullscreen mode 2020-02-26 12:39:17 +01:00
Daniel Eklöf
be5988dd3a
wayland: decoration configure: no need to force a resize - just update the CSDs 2020-02-26 12:28:12 +01:00
Daniel Eklöf
135ca0884d
wayland: configure: adjust configured size when using CSDs
The size (width, height) arguments provided by the compositor in the
XDG toplevel configure event *include* the surrounding CSDs.

Since our code assumes the size is for the main surface only (and then
positions the sub-surfaces *outside* the main surface), adjust the
provided size when using CSDs.

This ensures our actual window size ends up being what the compositor
wants it to be, and it fixes resize-glitches when resizing using CSDs.
2020-02-26 12:26:03 +01:00
Daniel Eklöf
ea97a0dc87
wayland: instantiate sub-surfaces on-demand
While most compositors handle instantiated but not-yet-mapped
sub-surfaces correctly, e.g. kwin does not.

For example, it will incorrectly offset the main surface both
horizontally and vertically with a couple of pixels, leaving two
transparent areas at the top and left, between the SSDs and the main
surface.

Note that a workaround is to position the sub-surfaces inside the main
surface while they're unmapped. However, since the surfaces may be
larger than the main surface (the CSDs, for examples, always are),
this doesn't quite work since kwin, at least, resizes the window to
include the sub-surfaces, even when unmapped.

So, instead we instantiate all sub-surfaces on demand, when we know
where to position them, and when they should be mapped.
2020-02-26 12:22:16 +01:00
Daniel Eklöf
2f587f6f3d
csd: position CSD sub-surfaces *outside* the main window
For now, this behavior is controlled with an ifdef. At least kwin
seems very buggy when the decorations are positioned like this (but
normally you'd use server-side decorations with kwin anyway).

This commit also changes 'use_csd' to be a tri-state variable;
when instantiating a window it is set to 'unknown'.

If there's no decoration manager available (e.g. weston), we
immediately set it to 'yes' (use CSDs).

Otherwise, we wait for the decoration manager callback to indicate
whether we should use CSDs or not.
2020-02-26 12:17:58 +01:00
Daniel Eklöf
2855d06c6e
wayland: mark the whole search surface as opaque 2020-02-25 19:57:19 +01:00
Daniel Eklöf
f05e0ad0ae
wayland: synchronize the CSD surfaces to the main surface 2020-02-25 19:56:56 +01:00
Daniel Eklöf
7e26d96d17
wayland: default to CSDs
Only when the compositor implements the XDG decoration manager
interface, and it tells us to use server side decorations to we do so.
2020-02-25 19:56:23 +01:00
Daniel Eklöf
8af5bf49b0
wayland: weston does not implement the xdg decoration manager interface 2020-02-25 19:56:17 +01:00
Daniel Eklöf
0126cee55d
wayland: xdg_surface_configure(): call wl_surface_commit()
It seems kwin expects a wl_surface_commit() for each
xdg_surface_ack_configure().

We don't want to commit before we've rendered a resized surface. So,
if we *did* change the window size, let the normal rendering path do
the surface commit.

Only when we did *not* change the window size do we need to explicitly
commit the surface in xdg_surface_configure().
2020-02-25 19:53:06 +01:00
Daniel Eklöf
a4d77608b9
wayland: decoration-configure: call render_resize() to add/remove CSDs
Call render_resize_force() when the decoration type changes
run-time. This ensures the CSDs are drawn when changing from server ->
client side decorations, and removed when going the other way.
2020-02-25 19:16:23 +01:00
Daniel Eklöf
b725ac4c73
wayland: terminal_from_surface(): use term_surface_kind() 2020-02-24 22:39:37 +01:00
Daniel Eklöf
8368e8184f
csd: wip: something to get started... 2020-02-23 14:17:48 +01:00
Daniel Eklöf
304f8d6982
wayland: output_mode: update PPI
Since we now use the width/height values from output_mode(), we also
need to update the PPI here.
2020-02-15 21:31:23 +01:00
Daniel Eklöf
291410bd71
wayland: debug: make sure state_str is properly NULL terminated 2020-02-15 19:30:59 +01:00
Daniel Eklöf
027696e9c6
wayland: calculate DPI from physical size, not logical size
xdg_output_handle_logical_size() reports _logical_ output size. That
is, it is scaled by the output's scale factor.

We want the _actual_ DPI. The _real_ output size is reported by
output_mode(), so use that instead.
2020-02-15 19:06:28 +01:00
Daniel Eklöf
ffcb09dd75
wayland: break out scale/resize updating to a new function
And call this function once from output_done(), rather than from each
output_*() callback.
2020-02-15 19:05:33 +01:00
Daniel Eklöf
5956faac01
term/wayland: use MONOTONIC timers 2020-01-10 21:33:40 +01:00
Daniel Eklöf
4e335422b8
wayland; fixup 2020-01-10 19:23:32 +01:00
Daniel Eklöf
7ce2cca49a
wayland: just to be sure, check return value of wl_display_read_events() 2020-01-10 19:23:08 +01:00
Daniel Eklöf
832e6f1370
wayland: make wayland socket non-blocking 2020-01-10 19:22:59 +01:00
Daniel Eklöf
ae82939158
wayland: wayl_flush: re-initialize fd array before each poll 2020-01-04 23:36:32 +01:00
Daniel Eklöf
11d381f0c3
wayland: add comment 2020-01-04 23:33:50 +01:00
Daniel Eklöf
d243a836ce
wayland: only call wl_display_prepare_read() if we read any events
That is, only call it if we have POLLIN. If not, then we never read
any events and we still hold the read lock and thus we shouldn't try
to acquire it again.
2020-01-04 23:32:00 +01:00
Daniel Eklöf
4cbd894803
wayland: use a low priority FDM hook to flush the wayland socket
This way, we don't have to manually insert flushes in code paths that
may execute outside of a wl_display_dispatch_pending().

(Those that execute inside a wl_display_dispatch_pending() are subject
to the flush performed at the end of the normal wayland FDM handler).
2020-01-04 23:27:59 +01:00
Daniel Eklöf
5ec447697c
render: throttle xcursor updates
With a bad behaving client (e.g. 'less' with mouse support enabled),
we can end up with a *lot* of xcursor updates (so much, that we
flooded the wayland socket before we implemented a blocking
wayl_flush()).

Since there's little point in updating the cursor more than once per
frame interval, use frame callbacks to throttle the updates.

This works more or lesslike normal terminal refreshes:

render_xcursor_set() stores the last terminal (window) that had (and
updated) the cursor.

The renderer's FDM hook checks if we have such a pending terminal set,
and if so, tries to refresh the cursor.

This is done by first checking if we're already waiting for a callback
from a previous cursor update, and if so we do nothing; the callback
will update the cursor for the next frame. If we're *not* already
waiting for a callback, we update the cursor immediately.
2020-01-04 22:58:32 +01:00
Daniel Eklöf
abc36d8f09
wayland: wl_display_flush() never blocks
Since it doesn't block, we need to detect EAGAIN failures and ensure
we actually flush everything.

If we don't, we sooner or later end up in a wayland client library
call that aborts due to the socket buffer being full.

Ideally, we'd simply enable POLLOUT in the FDM. However, we cannot
write *anything* to the wayland socket until we've actually managed to
send everything. This means enabling POLLOUT in the FDM wont work
since we may (*will*) end up trying to write more data to it before
we've flushed it.

So, add a wrapper function, wayl_flush(), that acts as a blocking
variant of wl_display_flush(), by detecting EAGAIN failiures and
calling poll() itself, on the wayland socket only, until all data has
been sent.
2020-01-04 21:10:08 +01:00
Daniel Eklöf
1178a7763b
wayland: window: optimize: set opaque region
When background alpha is 1.0 (0xffff), i.e. completely opaque, tell
the compositor this, via wl_surface_set_opaque_region().

This allows it to optimize drawing of surfaces _behind_ our window.
2020-01-03 21:53:38 +01:00
Daniel Eklöf
0ea0323d0f
wayland: don't use wl_display_dispatch()
wl_display_dispatch() calls poll(), which is unnecessary since we
already know the FD is readable.

Use the more lower level wl_display_read_events() +
wl_display_dispatch_pending().

These require wl_display_prepare_read() to have been called.

The idea is to call wl_display_prepare_read() **before** calling
poll().

Thus, we do this more or less last in wayl_init(), and at the **end**
of the FDM handler.

However, having taking this lock also means we no longer can call
wl_display_roundtrip() directly (it will hang).

So, add a wrapper, wayl_roundtrip(), that cancels the read intent,
does the roundtrip, and then re-acquires the read intent.
2020-01-03 21:02:12 +01:00