When maximizing a window, the previous location is saved so that
un-maximize would restore the same original window location.
However, if a Wayland client starts with a window maximized, the
previous location will be 0x0, so if we have to force placement in
xdg_toplevel_set_maximized(), we should update the location as well so
that the window is placed on the right monitor when un-maximizing.
For that purpose, add a new flag to force the update of the window
location, and use that flag from xdg_toplevel_set_maximized().
https://bugzilla.gnome.org/show_bug.cgi?id=783901
Wayland clients know their size better, so for Wayland we'd rather not
try to resize the client on un-maximize, but for this to work we need a
new MetaMoveResizeFlags.
https://bugzilla.gnome.org/show_bug.cgi?id=783901
When closing a window and showing a new one, the new one may not be
granted input focus until it gets a buffer on Wayland.
If another window is chosen to receive focus and raised on top of stack,
the newly mapped window is focused but placed underneath that other
window.
Meaning that for Wayland surfaces, we need to defer adding the window to
the stack until we actually get to show it, once we have a buffer
attached.
Rather that checking the windowing backend prior to decide if a window
is stackable or not, introduce a new vfunc is_stackable() which tells
if a window should be added to the stack regardless of the underlying
windowing system.
Also add meta_window_is_in_stack() API rather than checking the stack
position directly (replacing the define WINDOW_IN_STACK only available
in stack.c) and remove a window from the stack only if it is present
in the stack, so that the test in meta_stack_remote() becomes
irrelevant.
https://bugzilla.gnome.org/show_bug.cgi?id=780820
MetaWindowXwayland derives from MetaWindowX11 to allow for some Xwayland
specific vfunc that wouldn't apply to plain X11 windows, such as
shortcut inhibit routines.
https://bugzilla.gnome.org/show_bug.cgi?id=783342
When we received two hot plug events that both resulted in headless
configuration, we tried to find a new window monitor given the old.
That resulted in a null pointer dereference; avoid that by only trying
to find the same monitor if there was an old one.
https://bugzilla.gnome.org/show_bug.cgi?id=788607
GTK has the ability to handle client-decorated windows
in such a way that the behavior of these windows must
match the behavior of the current window manager.
In Mutter, windows can be tiled horizontally (and, in
the future, vertically as well), which comes with a few
requirements that the toolkit must supply. Tiled windows
have their borders' behavior changed depending on the
tiled position, and the toolkit must be aware of this
information in order to properly match the window manager
behavior.
In order to provide toolkits with more precise and general
data regarding resizable and constrained edges, this patch
makes MetaWindow track its own edge constraints.
This will later be used by the backends to send information
to the toolkit.
https://bugzilla.gnome.org/show_bug.cgi?id=751857
When computing a potential match for a tiled window, there is a
chance we face the case where 2 windows really complement each
other's tile mode (i.e. left and right) but they have different
sizes, and their borders don't really touch each other.
In that case, the current code would mistakenly assume they're
tile matches, and would resize them with either a hole or an
overlapping area between windows. This is clearly a misbehavior
that is a consequence of the previous assumptions pre-resizable
tiles.
This patch adapts the tile match algorithm to also consider the
touching edges when computing the matching tile, unless:
* the window is not currently tiled (for example when computing
the tile preview)
* the window is currently resized in tandem with an existing
tile match
https://bugzilla.gnome.org/show_bug.cgi?id=645153
bar
When a pair of tiled windows are grouped together, they
are treated as parts of a whole and interacting with one
affects the other.
Following the idea that sibling tiled windows are treated
as part of the same group, they should also be raised and
lowered together.
It is still possible to break tiled windows grouping by
simply untiling the window with the keyboard or by grabbing
and resizing or moving the window with the cursor.
This patch makes sibling tiled windows be lowered and raised
in tandem. For future reference, this behavior is documented
in [1].
[1] https://wiki.gnome.org/GeorgesNeto/MinutesOfFeaneron/Tilinghttps://bugzilla.gnome.org/show_bug.cgi?id=645153
When windows are tiled, it improves the interaction with
them when they have a set of snapping edges relative to
the monitor. For example, when there's a document editor
and a PDF file opened, I might want to rescale the former
to 2/3 of the screen and the latter to 1/3.
These snapping sections are not really tied to any other
window, and only depend on the current work area of the
window. Thus, it is not necessary to adapt the current
snapping edge detection algorithm.
This patch adds the necessary code in edge-resistance.c
to special-case tiled windows and allow them to cover
1/4, 1/3 and 1/2 (horizontally) of the screen. These
values are hardcoded.
https://bugzilla.gnome.org/show_bug.cgi?id=645153
After the introduction of the possibility to resize tiled windows,
it is a sensible decision to make windows aware of their tiling
match. A tiling match is another window that is tiled in such a
way that is the complement of the current window.
The newly introduced behavior attepts to make tiling as smooth as
possible, with the following rules:
* Windows now compute their tile match when tiling and, if there's
a match, they automatically complement the sibling's width.
* Resizing a window with a sibling automatically resizes the sibling
too to be the complement of the window's width.
* It is not possible to resize below windows' minimum widths.
https://bugzilla.gnome.org/show_bug.cgi?id=645153
Now that tiled windows are resizable, the user may grow a tiled
windows until it covers the entire work area. As this makes the
window state mostly indistinguishable from maximization, avoid
subtle differences by properly maximizing the window in that case.
https://bugzilla.gnome.org/show_bug.cgi?id=645153
Currently tiled windows are not resizable and their size is fixed
to half the screen width. Adjust the code to work with fractions
other than half, and allow users to adjust the split by dragging
the window edge that is not constrained by a monitor edge.
Follow-up patches will improve on that by resizing neighboring
tiled windows by a shared edge, and making the functionality
available to client-side decorated windows implementing the
new edge constraints protocol.
Now that the preview tile mode has been split from the window's
tile_mode property, it is much more natural to pass the requested
tile_mode to the tile() function instead of setting it externally
and calling the function to apply the state.
The existing semantics of the tile_mode property are terribly confusing,
as it depends on some other property whether it represents the requested
or current mode. Clear this up by just using separate variables for the
two. As it is unlikely that we will ever support more than one tile
preview, we can track the requested mode globally instead of adding
another per-window variable.
https://bugzilla.gnome.org/show_bug.cgi?id=645153
Automatic maximization is done when a window is almost the size of the
work area of a monitor. This makes no sense to try when there is no
monitor available, so skip trying to do this when headless.
https://bugzilla.gnome.org/show_bug.cgi?id=787637
When we are headless, treat this as if the window is always not monitor
sized. This might cause windows to temporarly become redirected while
being headless, but this is harmless as when a new monitor is
connected, we'll recalculate weather it should be redirected or not.
https://bugzilla.gnome.org/show_bug.cgi?id=787637
Also adds a soft assert to meta_window_is_on_primary_monitor() to make
it easier to spot when callers might want to handle headless
in a certain way.
https://bugzilla.gnome.org/show_bug.cgi?id=730551
For now we abuse of meta_window_get_flatpak_id not to break the APIs,
so that it's working seamlessly in gnone shell too.
Rename flatpak_id to sandboxed_app_id internally to get prepared to the future
API.
https://bugzilla.gnome.org/show_bug.cgi?id=788217
This avoids updating state (such as position, size etc) when going
headless. Eventually, when non-headless, things will be updated again,
and not until then will we be able to update to a valid state.
https://bugzilla.gnome.org/show_bug.cgi?id=730551
If there are no active logical monitors, don't try to dereference a
NULL one to get a preferred output winsys id. Instead just set an
invalid one.
https://bugzilla.gnome.org/show_bug.cgi?id=730551
Add a mechanism to MetaWaylandSurface that inhibits compositor's own
shortcuts when the surface has input focus, so that clients can receive
all key events regardless of the compositor own shortcuts.
This will help with implementing "fake" active grabs in Wayland and
XWayland clients.
https://bugzilla.gnome.org/show_bug.cgi?id=783342
When updating the main monitor, make sure to update the toplevel main
monitor before trying to use that as the main monitor for non-toplevel
windows (such as popups). Without this, when the main monitor is
updated as a side effect to monitors being changed (for example due to
a hot plug event, or coming back from being suspended) the
main monitor pointer may, after 'monitors-changed' has completed, point to
freed memory resulting in undefined behaviour.
https://bugzilla.gnome.org/show_bug.cgi?id=784867
This is used to request key focus on the close dialog whenever
a window that is frozen would receive key focus. Also, ensure
that the dialog gets focus when first shown if the window was
meant to receive input.
https://bugzilla.gnome.org/show_bug.cgi?id=762083
When moving a window between two non-adjecent logical monitors, don't
try to tile a window when the window position is outside of any logical
monitor.
https://bugzilla.gnome.org/show_bug.cgi?id=783630
While it doesn't make sense to set a window as transient to
itself, our existing check whether making a window transient
doesn't cover it, so it's still possible to create an infinite
loop.
https://bugzilla.gnome.org/show_bug.cgi?id=783502
For size change animations, plugins rely on the size change effect being
followed by size changed signal (or effects being kill altogether).
However unless the move_resize operation included the STATE_CHANGED flag,
the size changed event emitted when the compositor syncs the window
geometry only happens when the operation resulted in an actual change.
To avoid animations getting stuck in that case, make sure to include the
flag when tiling a window.
https://bugzilla.gnome.org/show_bug.cgi?id=783293
Call meta_compositor_size_change_window while tiling in order
to emit the size-change signal. Since the untiling action is
considered a unmaximize size change, treat tiling as a maximize
size change for consistency.
https://bugzilla.gnome.org/show_bug.cgi?id=782968
When terminating mutter running as a display server, don't try to resize
maximized windows when unmanaging, as at this point, they will have no
MetaWaylandSurface. Originally this was done instead of setting the
net_wm_state to not mess with future window managers, but when we're a
Wayland compositor, this does not matter.
https://bugzilla.gnome.org/show_bug.cgi?id=782156
When a state changed, e.g. a window went from unfullscreen to
fullscreen, always sync the window geometry, otherwise a compositor
application (e.g. gnome-shell) might end up with an unfinished window
state transition effect.
Without always syncing, the compositor plugin will see a 'size-change'
event, as a result of the state change, but if the size didn't change,
it would never see the 'size-changed' event. If an effect, for example
gnome-shell's fullscreen effect, is triggered on 'size-change' it might
rely on the actual size change to not get stuck. This commit allows it
to have this dependency.
This fixes a bug where a fullscreen effect gets "stuck" when a window
goes fullscreen without changing the window geometry.
https://bugzilla.gnome.org/show_bug.cgi?id=780292
Wayland windows are initially zero sized until clients commit the
first buffer. Despite being invisible, clients are allowed to request
such windows to be fullscreened on a specific output before they
attach the first buffer which means we need to be able to move them.
meta_window_move_to_monitor() doesn't handle this case because these
windows' initial monitor is a placeholder since their initial
coordinates are 0,0+0+0, which results in us using a rectangle as
old_area for meta_window_move_between_rects() that might be to the "right"
of the window causing the move to go further out of the visible
screen's coordinates. This is later "corrected" by the constraints
system but the window might end up in the wrong monitor.
To fix this, we can make meta_window_move_between_rects() accept a
NULL old_area, meaning that we move the window to the new_area without
trying to keep a relative position.
https://bugzilla.gnome.org/show_bug.cgi?id=772525
Instead of storing the logical monitors in an array and having users
either look up them in the array given an index or iterate using
indices, put it in a GList, and use GList iterators when iterating and
alternative API where array indices were previously used.
This allows for more liberty regarding the type of the logical monitor.
https://bugzilla.gnome.org/show_bug.cgi?id=777732
Rewrite check_fullscreen_func to not use indexes (and
offset-index-as-pointer) tricks. This also removes the usage of an API
constructing temporary logical monitor arrays carrying indices.
https://bugzilla.gnome.org/show_bug.cgi?id=777732
Let the backend initialize the cursor tracker, and change all call
sites to get the cursor tracker from the backend instead of from the
screen. It wasn't associated with the screen anyway, so the API was
missleading.
https://bugzilla.gnome.org/show_bug.cgi?id=777732
Instead of keeping around array indexes, keep track of them by storing
a pointer instead. This also changes from using an array (imitating the
X11 behaviour) to more explicit storing.
https://bugzilla.gnome.org/show_bug.cgi?id=777732
To complement the current API which takes an index referencing a
logical monitor in the logical monitor array, add API that takes a
direct reference to the logical monitor itself. The intention is to
replace the usage of the index based API with one that doesn't rely on
internal implementation details.
https://bugzilla.gnome.org/show_bug.cgi?id=777732
It was just pointer to the actual list; having to synchronize a list of
logical monitors with the actual monitors managed by the backend is
unnecessary.
https://bugzilla.gnome.org/show_bug.cgi?id=777732
The fullscreen monitors state is set given a set of xinerama monitor
identification numbers. When the monitor configuration changes (e.g. by
a hotplug event) these are no longer valid, and may point to
uninitialized or unallocated data. Avoid accessing
uninitialized/unallocated memory by clearing the fullscreen monitor
state when the monitor configuration changes.
https://bugzilla.gnome.org/show_bug.cgi?id=777732
In preparation for further refactorizations, rename the MetaMonitorInfo
struct to MetaLogicalMonitor. Eventually, part of MetaLogicalMonitor
will be split into a MetaMonitor type.
https://bugzilla.gnome.org/show_bug.cgi?id=777732
We currently only focus unfocused windows on button press if no
modifiers (or just ignored modifiers) are in effect. This behavior
seems surprising and counter-intuitive so let's do it for any modifier
combination instead.
https://bugzilla.gnome.org/show_bug.cgi?id=746642
A window's unconstrained_rect is essentially just the target rectangle
we hand to meta_window_move_resize_internal() except it's not updated
until the window actually moves or resizes.
As such, for wayland client resizes, since they're async, using
window->unconstrained_rect right after calling move_resize_internal()
to update the grab anchor position on unmaximize doesn't work as it
does for X clients.
To fix this, we can just use the target rectangle for the grab
anchor. Note that comment here was already wrong since it says we
should be taking constraints into account and yet the code used the
unconstrained rect anyway.
https://bugzilla.gnome.org/show_bug.cgi?id=770345
In order for the compositor plugin to be able to animate window size
changes properly we need to let it know of the starting and final
window sizes.
For X clients this can be done synchronously and thus with a single
call into the compositor plugin since it's us (the window manager)
who's in charge of the final window size.
Wayland clients though, have the final say over their window size
since it's determined from the client allocated buffer.
This patch moves the meta_compositor_size_change_window() calls before
move_resize_internal() which lets the compositor plugin know the old
window size and freezes the MetaWindowActor.
Then we get rid of the META_MOVE_RESIZE_DONT_SYNC_COMPOSITOR flag
since it's not needed anymore as the window actor is frozen and that
means we can use meta_compositor_sync_window_geometry() as the point
where we inform the compositor plugin of the final window size.
https://bugzilla.gnome.org/show_bug.cgi?id=770345
mutter would remove focus from a toplevel when showing one of its
transient window which is not on top and not focused.
When using xdg_popup without grab as allowed in xdg_shell v6, the popup
wouldn't be focused, and if an intermediate event occurs before the
popup is shown, it's not placed on top either, which could randomly
trigger a loss of focus in the corresponding toplevel window.
Remove that special case, it doesn't make much sense to globally unset
focus when mapping a new window.
https://bugzilla.gnome.org/show_bug.cgi?id=773210
GNOME Shell's window matching currently fails frequently with Flatpak
applications, as one of the primary hints used to link windows with
.desktop files - the WM_CLASS - no longer matches when flatpak renames
the exported .desktop file. Luckily, Flatpak provides us with a fail-safe
way to map from the PID to the corresponding application ID, so expose an
appropriate method that allows GNOME Shell to reliably match windows to
the corresponding Flatpak app.
https://bugzilla.gnome.org/show_bug.cgi?id=772614
It is often useful to identify the client process that created
a particular window, however the existing meta_window_get_pid()
method relies on _NET_WM_PID, which is only available on X11 and
depends on applications to set it correctly (which may not even
be possible when the app runs in its own PID namespace as Flatpak
apps do). So add a get_client_pid() method that uses windowing
system facilities to resolve the PID associated with a particular
window.
https://bugzilla.gnome.org/show_bug.cgi?id=772613
When a modal transient is unmanaging, most likely the parent of the
modal transient should be focused.
In Wayland, a MetaWindow is created when a shell surface role (like
xdg_toplevel) is created, but a window cannot be shown until a buffer
is attached. If a client would create two modal transients and make
them both have the same parent, but only one get a buffer attached
(i.e. shown), when unmanaging the modal transient that was showing,
when finding a new focus candidate, the stacking code will ignore the
not-to-be-shown buffer-less modal transient when finding a good
candidate for focusing. In the case described here, this means it will
find the parent of the unmanaging modal transient.
This newly chosen candidate will then be passed to meta_window_focus();
meta_window_focus() will then try to find any modal transient to focus
instead, will find the one without any buffer, then fail to focus it
because it cannot be mapped, thus making meta_window_focus() not focus
anything. Since meta_window_focus() didn't change any focus state, the
assert in meta_window_unmanage() checking that the unmanaging window
isn't focused anymore will be hit, causing mutter to abort.
For now, fix this by checking whether the modal transient can actually
be focused in meta_window_focus(). For X11 client windows, a window
will be defined to be focusable always, but for Wayland client windows,
a window will be determined focusable only if it has a buffer attached.
In the future, we should probably do a more thorough refactorization of
focus handling to get rid of any X11 - Wayland differences.
https://bugzilla.gnome.org/show_bug.cgi?id=757568
Even without a compositor grab, key events may still be expected to
be processed by the compositor and not applications, for instance
when using ctrl-alt-tab to keynav in the top bar. On X11, focus is
moved to the stage window in that case, so that events are processed
before they are dispatched by the window manager. On wayland, we need
to handle this case ourselves, so make sure to not pass key events to
wayland in that case, and move the key focus back to the stage when
appropriate.
https://bugzilla.gnome.org/show_bug.cgi?id=758167
For some reason, when a modal dialog was made an attaching
transient-for, if the window wasn't "constructing", it would be
unmanaged and rely on some side effect to be recreated. This side
effect is not triggered for Wayland clients, thus if one happen to set
a surface as "modal" via gtk_surface.set_modal before
xdg_toplevel.set_parent, it'd be unmanaged and never show up.
Instead, simply just set the tranciency anyway for Wayland clients.
This makes GTK+ clients that set_modal() before set_transient_for()
work.
https://bugzilla.gnome.org/show_bug.cgi?id=770324
Windows from Xwayland still needs to use the Wayland path, but is
represented an MetaWindowX11, thus the abstraction introduced in
"window: Make meta_window_has_pointer() per protocol implemented"
is wrong. Lets turn back time, and reconsider how this can be
abstracted more correctly in the future.
This reverts commit 9fb891d216.
Add support for assigning a window a custom window placement rule used
for calculating the initial window position as well as defining how a
window is constrained.
The custom rule is a declarative rule which defines a set of parameters
which the placing algorithm and constrain algorithm uses for
calculating the position of a window. It is meant to be used to
implement positioning of menus and other popup windows created via
Wayland.
A custom placement rule replaces any other placement or constraint
rule.
https://bugzilla.gnome.org/show_bug.cgi?id=769936
This layer isn't really being used and in fact, it causes
meta_stack_get_default_focus_window() to return a fullscreen window
even if the naturally topmost window in the stack isn't a fullscreen
one.
Note that commit a3bf9b01aa changed how
we choose the default focus window from the MRU to the topmost in the
stack.
https://bugzilla.gnome.org/show_bug.cgi?id=768221
printf string precision counts bytes so we may end up creating invalid
UTF-8 strings here. Instead, use glib's unicode aware methods to clip
the title.
https://bugzilla.gnome.org/show_bug.cgi?id=765535
If we try to send notify event (either from surface_state_changed()
or from meta_window_wayland_move_resize_internal()),
we will crash, because we don't have a sufrace anymore.
There's no reason why to resize the window that is being
unmanaged anyway.
https://bugzilla.gnome.org/show_bug.cgi?id=751847
Each wl_surface.commit with a newly attached buffer should result in
one wl_buffer.release for the attached buffer. For example attaching
the same buffer to two different surfaces must always result in two
wl_buffer.release events being emitted by the server. The client is
responsible for counting the wl_buffer.release events and be sure to
have received as many release events as it has attached and committed
the buffer, before reusing it.
https://bugzilla.gnome.org/show_bug.cgi?id=762828
If a broken or naughty application tries set up its windows to create
a loop in the transient relationship, mutter will hang, looping forever
in meta_window_foreach_ancestor()
To avoid looping infinitely at various point in the code, check for a
possible loop when setting the transient relationship and deny the
request to set a window transient for another if that would create a
loop.
Bugzilla: https://bugzilla.gnome.org/show_bug.cgi?id=759299
The new tiling code, instead of based around "tiling states", is instead
based around constrained edges. This allows us to have windows that have
three constrained edges, but keep one free-floating, e.g. a window tiled
to the left has the left, top, and bottom edges constrained, but the
right edge can be left resizable.
This system also is easily extended to support corner tiling. We also,
using the new "size state" system, also keep normal, tiled, and
maximized sizes independently, allowing the maximize button to bounce
between maximized and tiled states without reverting to normal in
between. Dragging from the top will always restore the normal state,
though.
https://bugzilla.gnome.org/show_bug.cgi?id=751857
In case a window is hidden when we're ordered to make it transient to
a different parent we must re-evaluate its visibility status or we'll
get into an inconsistent state where the parent is visible and the
child isn't.
https://bugzilla.gnome.org/show_bug.cgi?id=759297
This seems like a more generally useful and intuitive behavior. Note
that, in X sessions, this is what already happened in practice since
meta_display_begin_grab_op() calls meta_window_grab_all_keys() which,
on X11, does meta_window_focus().
https://bugzilla.gnome.org/show_bug.cgi?id=756789
Don't update the stack until after setting the window->transient_for
field. Updating before will cause the stack transient-for constraint to
be missing until the next time constraints are applied.
https://bugzilla.gnome.org/show_bug.cgi?id=755606
Wine removes the minimize func from its Motif hints on full-screen
windows, because, as the Win32 API literally says, the minimize button
is indeed not visible on full-screen windows.
Given that this code was added to prevent minimizing a panel by
accident, I don't necessarily think that it's relevant anymore.
https://bugzilla.gnome.org/show_bug.cgi?id=758186
When managing window, we queue showing the window.
Under wayland, if we commit surface quickly enough,
the showing is unqueued and commit procedure takes care
of mapping and placing the window. In the oposite case,
queue is processed before client sets all we need and
then we have wrong size of window, which leads to broken placement.
Therefore force placement in queue only if the window should already
be mapped. If it is not mapped, we don't care where it is anyway.
https://bugzilla.gnome.org/show_bug.cgi?id=751887
Displaying all Wayland windows with the XID of 0x0 makes it hard
to figure out what is going on ... use the recently-added
window->stamp to show Wayland windows as W1/W2/W3...
This was introduced in commit c6793d477a
to prevent window self-maximisation. It turns out that that bug seems
to have been fixed meanwhile in a different way since the reproducer
in https://bugzilla.gnome.org/show_bug.cgi?id=461927#c37 now works
fine with this special handling removed.
In fact, failing to set window->fullscreen immediately when loading
the initial set of X properties causes us to create a UI frame for a
window that sets _NET_WM_STATE_FULLSCREEN.
This, in turn, might cause the fullscreen constrain code to fail if
the window also sets min_width/min_height size hints to be the monitor
size since the UI frame size added to those makes the rectangle too
big to fit the monitor. If the window doesn't set these hints, we
fullscreen it but the window will get sized such that the UI frame is
taken into account while it really shouldn't (see the reproducer
above).
https://bugzilla.gnome.org/show_bug.cgi?id=753020
Since we scale surface actors given what main output their toplevel
window is on, also scale the window geometry coordinates and sizes
(window->rect size and window->custom_frame_extents.top/left) in order
to make the window geometry represent what is being rendered on the
stage.
https://bugzilla.gnome.org/show_bug.cgi?id=744934
The main monitor of a window is maintained as 'window->monitor' and is
updated when the window is resized or moved. Lets avoid calculating it
every time it`s needed.
https://bugzilla.gnome.org/show_bug.cgi?id=744934
A much less hacky version of maximize / unmaximize is reimplemented
in terms of this, but it could also eventually be used for fullscreen /
unfullscreen, and tile / untile.
This is an extremely niche feature, and conflicts with the rest of our
interface being consistent about not allowing resizing while tiled or
maximized.
Going from fullscreen to unfullscreen involves a frame border size, so
in order to properly interpret the saved rect size, we need to make sure
that the frame borders are fully up to date.
The "calc showing" operation is queued in a few places alongside MetaWindow
creation, we should be ignoring these until there is a buffer to show.
https://bugzilla.gnome.org/show_bug.cgi?id=750552