Compare commits

...

175 Commits

Author SHA1 Message Date
Florian Müllner
a84f714808 Bump version to 3.17.4
Update NEWS.
2015-07-23 12:41:03 +02:00
Florian Müllner
b41873dced window-x11: Remove duplicated code
meta_window_change_workspace_without_transients() already does
exactly that.
2015-07-23 12:13:45 +02:00
Florian Müllner
0a9511b24b window: Remove duplicated code
meta_window_change_workspace_without_transients() already does
exactly that.
2015-07-23 12:13:45 +02:00
Florian Müllner
17438ced91 core: Remove meta_core_get_frame_workspace() declaration
The definition was removed long ago in commit ff33209e1f ...
2015-07-23 12:13:45 +02:00
Florian Müllner
27c7512e4d core: Remove meta_core_change_workspace()
Unused since commit bf64e719a1 (2001!) ...
2015-07-23 12:13:45 +02:00
Florian Müllner
124888764d default-plugin: Replace deprecated macro 2015-07-22 16:01:13 +02:00
Rui Matos
7e1c6ff2a2 screen: On monitors-changed, update the window monitor before resizing
Since commit 14b0a83f64 we store the
main window monitor instead of computing it every time. This means
that we must now ensure that it's updated before trying to use it
which we do from meta_screen_resize_func() or else we'll crash on an
assertion later on when removing a monitor:

assertion failed: (which_monitor < workspace->screen->n_monitor_infos)

https://bugzilla.gnome.org/show_bug.cgi?id=752674
2015-07-21 16:46:09 +02:00
Rui Matos
2fb8da0d5a backends/monitor-manager: Validate EDID strings
Some monitors return a bunch of bytes on their display descriptor
which aren't valid utf8 and thus we fail to serialize them later on
for the DisplayConfig DBus API.

Let's fall back to the stringified product code and serial number in
that case.

https://bugzilla.gnome.org/show_bug.cgi?id=752673
2015-07-21 16:42:53 +02:00
Matthias Clasen
ad51c52b69 feedback actor: Fix a typo
The code for setting an anchor was comparing apples and oranges.
This was pointed out by coverity.

https://bugzilla.gnome.org/show_bug.cgi?id=752552
2015-07-20 17:39:09 -04:00
Matthias Clasen
1b22da0039 Monitor-config: Fix a copy-paste error
The code was checking width twice, instead of width and height,
as was clearly the intention. Coverity pointed this out.

https://bugzilla.gnome.org/show_bug.cgi?id=752551
2015-07-20 17:33:28 -04:00
Carlos Garnacho
8329e97502 backends: Trigger animated cursor animations on the native backend
We will need to update the timeout on either cursor changes, or
right when ticking to the next cursor frame.

https://bugzilla.gnome.org/show_bug.cgi?id=752342
2015-07-20 22:06:44 +02:00
Carlos Garnacho
74ca936a00 backend: Add meta_cursor_renderer_force_update()
There will be times where additional updates will be needed, such
as animated cursors. We should update the texture and redraw in
that case.

https://bugzilla.gnome.org/show_bug.cgi?id=752342
2015-07-20 22:06:44 +02:00
Carlos Garnacho
141760057b backend: Store XcursorImages for theme cursors
There's a chance the icon will be animated, so store the XcursorImages
instead of the individual XcursorImage, and handle that as a nimages=1
special case.

API to "tick" a cursor animation, and retrieve current frame timing
information has been added.

https://bugzilla.gnome.org/show_bug.cgi?id=752342
2015-07-20 22:06:44 +02:00
Carlos Garnacho
e648f2c244 events: Ensure touchpad gesture events go through clutter
They otherwise fall through paths that enable bypass_clutter, this
is necessary so they can be picked by captured-event handlers
along the actor hierarchy.

https://bugzilla.gnome.org/show_bug.cgi?id=752248
2015-07-20 22:01:05 +02:00
Jonas Ådahl
f01247d815 wayland: Fix calculation of window geometry when scaled
Take the surface actor scale into account when calculating the window
geometry.

https://bugzilla.gnome.org/show_bug.cgi?id=744934
2015-07-16 11:54:14 +08:00
Jonas Ådahl
db6caa2c49 wayland: Take scale into account when placing windows relatively
When placing a popup and the legacy transient wl_shell_surface surfaces,
take the current scale of the window into account. This commit doesn't
fix relative positioning in case a window scale would change, but since
the use case for relative positioning is mostly popups, which would be
dismissed before the parent window would be moved, it should not be that
much of a problem.

https://bugzilla.gnome.org/show_bug.cgi?id=744934
2015-07-16 11:54:14 +08:00
Jonas Ådahl
fbd237bc66 MetaWaylandSurface: Return top most toplevel window for popups
Make meta_wayland_surface_get_toplevel_window return the top most window
in case its a chain of popups. This is to make all popups in a chain
including the top most surface have the same scale.

The reason for this is that popups are mostly integrated part of the
user interface of its parent (such as menus). Having them in a different
scale would look awkward.

Note that this doesn't affect non-popup windows with parent-child
relationship, because such windows are typically not an integral part of
the user interface (settings window, dialogs, ..) and can typically be
moved independently. It would probably make sense to make attached modal
dialogs have the same scale as their parent windows, but modal dialogs
are currently not supported for Wayland clients.

https://bugzilla.gnome.org/show_bug.cgi?id=744934
2015-07-16 11:54:14 +08:00
Jonas Ådahl
f6c9261bf6 wayland: Scale window geometry rects given the main output
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
2015-07-16 11:54:14 +08:00
Jonas Ådahl
14b0a83f64 Don't calculate the main window monitor every time it`s needed
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
2015-07-16 11:54:14 +08:00
Jonas Ådahl
441efd17ce MetaMonitorInfo: Provide scale information
Tracking back from the monitor to the output every time we need to
figure out the scale of a window on a monitor is inconvenient, so
propagate the scale from the output to the monitor it is associated
with.

https://bugzilla.gnome.org/show_bug.cgi?id=744934
2015-07-16 11:53:40 +08:00
Jonas Ådahl
208da2316d wayland: Fix subsurface place_above/below type cast error
A MetaWaylandSurface was casted into a ClutterActor, but it should have
been the MetaSurfaceActor.

Move out parent_actor and surface_actor out of the loop while at it
since they won't change when iterating.

https://bugzilla.gnome.org/show_bug.cgi?id=745655
2015-07-16 11:43:19 +08:00
Jonas Ådahl
3b993131e8 wayland: Fix subsurface positioning on HiDPI
Keep the active position state in its original coordinate space, and
synchronize the surface actor with it when it changes and when
synchronizing the rest of the surface state, in case the surface scale
had changed.

https://bugzilla.gnome.org/show_bug.cgi?id=745655
2015-07-16 11:43:19 +08:00
Jonas Ådahl
117f57f74c wayland: Factor out some parts of meta_surface_actor_wayland_get_scale
Put a toplevel window getter in meta-wayland-surface.h and a main
monitor scale getter in window-wayland.h.

https://bugzilla.gnome.org/show_bug.cgi?id=745655
2015-07-16 11:43:19 +08:00
Marek Chalupa
b97ebc4124 frames: handle META_FRAME_CONTROL_NONE on left click
We can get this operation in some cases, for example when
we're trying to resize window that cannot be resized.
This can occur with maximized windows that have a border
(without border we couldn't resize them by mouse in maximized state).
In this case we reached abort() beacuse we did not handle this op.

https://bugzilla.gnome.org/show_bug.cgi?id=751884
2015-07-15 07:45:02 -05:00
Jonas Ådahl
5d10196919 MetaSurfaceActorWayland: Don't dereference surface before NULL check
Fixes regression introduced in ba7c524a18.

https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-07-15 17:10:48 +08:00
Jonas Ådahl
f295349e26 wayland: Don't crash if wl_output resource is destroyed after being removed
Previously a MetaWaylandOutput could be removed from the current outputs
table (by being unplugged for example). This would result in the global
object being removed and the MetaWaylandOutput instance freed, but the
wl_resource destructor would still try to remove itself from the list of
resources. Trying to do this, it'd try to access its user data pointer
which would point to the freed MetaWaylandOutput instance, and as a
result crash when trying to manipulate the freed data.

https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-07-15 14:55:55 +08:00
Jonas Ådahl
eb023ff2c9 wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.

DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.

https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-07-15 14:55:55 +08:00
Jonas Ådahl
ba7c524a18 MetaSurfaceActorWayland: Unset the MetaWaylandSurface pointer when it goes away
We may access it during painting even if it has been freed. For now,
manually unset it during the MetaWaylandSurface cleanup; in the future
make MetaWaylandSurface a GObject and make the surface pointer a weak
reference.

https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-07-15 14:55:55 +08:00
Jonas Ådahl
dc99af40f3 wayland: Make MetaWaylandOutput a GObject
This way we can later add signals to it.

https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-07-15 14:55:55 +08:00
Jonas Ådahl
1576b7d5a6 wayland: Put MetaWaylandOutput struct in header file
We need this in MetaWaylandSurface to be able to send
wl_surface.enter/leave.

https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-07-15 14:55:55 +08:00
Jonas Ådahl
6ec7fa2cbd wayland: Use surface role when special casing surface commits
Lets use the role when doing role specific commit actions. The
conditions effectively do that anyway, and this way we will get a
compiler warning here whenever we add a new role, as well as we avoid
having different variants of role-determination checks in different
places.

https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-07-15 14:55:55 +08:00
Jonas Ådahl
bede9970de nested: Allow configuration of dummy output configuration
Enable a user to test and debug multi output configurations on Wayland
without having the available hardware by enabling some basic
configuration of the dummy monitor manager.

Currently available configuration options are:

MUTTER_DEBUG_NUM_DUMMY_MONITORS - to set the number of monitors
MUTTER_DEBUG_DUMMY_MONITOR_SCALES - to configure the monitor scales

See src/backends/meta-monitor-manager-dummy.c for detailed description
of the available configuration parameters.

https://bugzilla.gnome.org/show_bug.cgi?id=747089
2015-07-15 14:55:55 +08:00
Peter Hutterer
5f1bcc124f input-settings-x11: check properties for correctness before changing them
Before submitting a new scroll mode, click method or sendevents mode check if
the value is supported by the device. This avoids BadValue errors when setting
two-finger scrolling on single-finger touchpad devices since we can't easily
handle BadValue (see 9747277b)

https://bugzilla.gnome.org/show_bug.cgi?id=750816

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2015-07-14 16:42:33 -05:00
Jasper St. Pierre
4d3419607a window: Don't reference a dead function
meta_window_move_resize has been gone for a while now.
2015-07-06 00:52:49 -07:00
Jasper St. Pierre
7dc0b0e602 Remove gtk-doc
The gtk-doc reference is woefully maintained, and trying to actually
generate it resulted in some extremely outdated and poor documentation.
If somebody wants to actually renew the docs, just revert this commit,
otherwise, I'm not going to bother.
2015-07-06 00:52:18 -07:00
Jasper St. Pierre
1545d4e638 Put G_GNUC_CONST at the end of the declarations
These attributes go at the end, not the beginning.
2015-07-06 00:29:23 -07:00
Jasper St. Pierre
a191554cf6 compositor: Export meta_shadow_factory_get_shadow to introspection
I forgot we had a separate list of headers for introspection to scan.
2015-07-06 00:27:03 -07:00
Jasper St. Pierre
b33a82eb7c Export the shadow factory
The elementary guys would like this as an API, and I don't see any
reason to refuse -- this is quite nice shadow painting code :)

For some reason, gobject-introspection can't seem to cope with
MetaWindowShape. I'll look into it a bit later, but for now, mark
the function it has trouble with as (skip).
2015-07-06 00:14:22 -07:00
Jasper St. Pierre
2705c87f74 window-group: Fix issues when translated
It seems that when translated, paint_offset and actor_offset will always
be the same, so our translation of the clip group won't work. For now,
until I figure out what's going on here, just use the painting offset,
since that what seems to make sense to me.

I didn't write this code, though, so I don't know why the actor's
allocation was involved in this computation at all.

I tested briefly with clones (magnifier, manual cloning through the
looking glass) and couldn't find any other artifacts, so I'm going to do
this for now.
2015-07-05 23:55:43 -07:00
Jasper St. Pierre
9fc1c919e8 window-actor: Replace no-shadow with a shadow-mode
The elementary guys want to be able to force shadows *on*, for use in
their overview.
2015-07-05 23:29:11 -07:00
Jasper St. Pierre
9f04c58ffe Implement a generic "size change" mechanism
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.
2015-07-05 23:03:36 -07:00
Jasper St. Pierre
7de1f3a7be plugin-manager: Make the event an enum 2015-07-05 22:01:59 -07:00
Jasper St. Pierre
fd443ecf2a plugin-manager: Clean up an unused define 2015-07-05 22:01:59 -07:00
Jasper St. Pierre
8979e52a6c Install enum types 2015-07-05 22:01:59 -07:00
Jasper St. Pierre
e8dd5601e7 window-group: Turn clipped redraws back on
Whoops -- I commented this out for debugging reasons.
2015-07-05 19:19:33 -07:00
Jasper St. Pierre
ccca810daf window-group: Improve performance by hacking around Clutter
The comment explains it better, but Clutter tries to be smart and
repaint actors when their allocations change. Since the window group's
allocation changes when windows move around, this means that moving a
window will always cause a full-stage repaint, which is super slow.

Hack around this for now.
2015-07-05 19:18:22 -07:00
Jasper St. Pierre
693456b644 shaped-texture: Remove unnecessary copies of the pipeline 2015-07-05 15:01:15 -07:00
Jasper St. Pierre
aacc3d5628 shaped-texture: Repeat edge pixels instead of mirroring the image
While nothing will completely fix X11's artifacts, this tends to look a
bit better, *especially* with mask textures that have black at the
edges (which are most of them).

It's also faster for GPUs to manage.
2015-07-05 15:00:38 -07:00
Jasper St. Pierre
1ea8efdeda stack: Don't prefer windows in the same group as not_this_one
The only time we ever execute this code is when we're minimizing or
hiding a window, in which case we should respect stacking order.

This fixes weird "bugs" where windows from the same app magically pop up
over other windows.
2015-07-05 14:33:08 -07:00
Jasper St. Pierre
a3fbbaabe8 delete: Remove old code
It doesn't compile
2015-07-05 14:29:56 -07:00
Florian Müllner
d5d95b2834 Bump version to 3.17.3
Update NEWS.
2015-07-02 13:51:22 +02:00
Cosimo Cecchi
659b8ed471 monitor-manager-xrandr: don't set underscan property when not supported
We should not be setting random output properties like this.
Use the function we just introduced to only set the underscan flag when
it's actually supported.
2015-07-01 18:22:48 -07:00
Cosimo Cecchi
94bce5a00f monitor-manager: add a property to discover if underscan is supported
So that clients such as the control center can decide to hide an
underscanning checkbutton when the output does not support it.

Support in the KMS / native backend to come later...
2015-07-01 18:20:57 -07:00
Jasper St. Pierre
91b7dedf36 Remove the ability to grab resize unmaximize
This is an extremely niche feature, and conflicts with the rest of our
interface being consistent about not allowing resizing while tiled or
maximized.
2015-07-01 16:27:19 -07:00
Jasper St. Pierre
aa1c819941 theme: Fix C++-ism 2015-07-01 16:26:51 -07:00
Pedro Albuquerque
be7e994abd Updated Portuguese translation 2015-07-01 21:59:38 +00:00
Florian Müllner
6c05eb583e stack: Don't try to focus hidden windows
A window may be hidden even if not minimized itself, for instance
when an ancestor is minimized. As meta_window_focus() will refuse
to actually focus the window in that case, don't pick it in the first
place.

https://bugzilla.gnome.org/show_bug.cgi?id=751715
2015-06-30 15:06:56 +02:00
Jonas Ådahl
5547c98f97 wayland: Make MetaWaylandDataSource ownership protocol specific
Firstly, this patch makes MetawaylandDataSource a GObject. This is in
order to easier track its lifetime without adding destroy signals etc. It
also makes the vfunc table GObject class functions instead while at it,
as well as moves protocol specific part of the source into their own
implementations.

An important part of this patch is the change of ownership. Prior to this
patch, MetaWaylandDataDevice would kind of own the source, but for
Wayland sources it would remove it if the corresponding wl_resource was
destroyed. For XWayland clients it would own it completely, and only
remove it if the source was replaced.

This patch changes so that the protocol implementation owns the source.
For Wayland sources, the wl_resource owns the source, and the
MetaWaylandDataDevice sets a weak reference (so in other words, no
semantical changes really). For XWayland sources, the source is owned by
the selection bridge, and not removed until replaced or if the client
goes away.

Given the changes in ownership, data offers may now properly track the
lifetime of a source it represents. Prior to this patch, if an offer with
an XWayland source would loose its source, it wouldn't get notified and
have an invalid pointer it would potentally crash on. For Wayland
sources, an offer would have a weak reference and clean itself up if the
source went away. This patch changes so the behavior is consistent,
meaning a weak reference is added to the source GObject so that the offer
can behave correctly both for Wayland sources and XWayland sources.

https://bugzilla.gnome.org/show_bug.cgi?id=750680
2015-06-30 11:23:40 +08:00
Carlos Garnacho
ea4979e182 data-device: Protect against destroyed dnd-focus clients
When a possible drag dest client crashes during DnD, it may happen
we receive first the destroy notification for the data_device, and
later the notification for the focus surface. When this happens we
unset the drag_focus_data_device first, and later on
meta_wayland_drag_grab_set_focus(grab, NULL) we assume it still
exists when sending the leave event, leading to mutter crashing
right after.

So, as we don't receive any ordering guarantees about resource
destruction, just prepare the meta_wayland_drag_grab_set_focus()
paths for this.
2015-06-29 18:38:50 +02:00
Jasper St. Pierre
8da5761ffc x11/xrandr: Use xcb to set properties on outputs
It seems that fglrx sometimes gives us absolute junk when requesting the
outputs, and if we don't trap errors, we'll just crash when trying to
configure a junk output. Use xcb so errors simply get ignored.
2015-06-28 13:25:49 -07:00
Jasper St. Pierre
aea71fbd01 group: Select for property notifies on group leaders 2015-06-27 00:53:22 -07:00
Peter Hutterer
b55f792302 input-settings-x11: don't create non-existing atoms
If the atom doesn't exist it won't exist on the device either so we can
shortcut the property retrieval/modification. Creating atoms by name but not
doing anything with them also confuses kcm_touchpad

https://bugzilla.redhat.com/show_bug.cgi?id=1199825

https://bugzilla.gnome.org/show_bug.cgi?id=751471
2015-06-26 21:52:45 -07:00
Jasper Lievisse Adriaanse
dd060d78ce prevent duplicate declaration of MetaUIFrame
fixes bug 747326
2015-06-26 21:40:44 -07:00
Jasper Lievisse Adriaanse
3fe281ada9 Prevent redefinition of MetaKeyCombo
Fixes bug 747326
2015-06-26 21:40:44 -07:00
Jasper St. Pierre
f041b35b9b xprops: Fix STRING types as well 2015-06-26 13:51:45 -07:00
Jasper St. Pierre
afa58746ea configure: Remove some old cruft 2015-06-24 16:52:41 -07:00
Jasper St. Pierre
6dbec6f81b xprops: More Xlib / long cleanliness with Motif WM hints
Fixes some CSD windows sometimes getting frames when they totes
shouldn't.
2015-06-24 14:34:48 -07:00
Jasper St. Pierre
2cbaa6660c backend-x11: Fix our awful hack for crossing events, too
For enter / leave events, which we use in the UI code, we need to make
sure that these coordinates are root-relative as well, otherwise the
cursor when entering frames might be incorrect.
2015-06-24 10:35:38 -07:00
Jasper St. Pierre
d74b0d5be8 window: Clear the frame borders before calculating the unfullscreen rect
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.
2015-06-23 17:05:27 -07:00
Ting-Wei Lan
6b82f61dba build: Fix non-wayland build
This fixes error introduced in 09120132ef.

https://bugzilla.gnome.org/show_bug.cgi?id=750552
2015-06-23 16:37:40 -07:00
Jasper St. Pierre
4c6866741d surface-actor-x11: Make sure to set a size when unredirected
When we're unredirected, we don't have a pixmap, and thus our allocation
becomes 0x0. So when events come in, they pass right through our actor,
going to the one underneath in the stack.

Fix this by having a fallback size on the shaped texture actor when
we're unredirected, causing it to always have a valid allocation.

This fixes clicking on stuff in sloppy / mouse mode focus.
2015-06-23 16:30:29 -07:00
Jasper St. Pierre
84baf4e181 shaped-texture: Clean up some internals
These are internal vfuncs, they don't need prechecks.
2015-06-23 16:18:38 -07:00
Jasper St. Pierre
3962f1d982 xprops: Apply the same Xlib / 64-bit hygiene to atom lists 2015-06-23 15:37:58 -07:00
Jasper St. Pierre
414be07a69 xprops: Remove unused synchronous property getters
No reason to keep these around..
2015-06-23 15:37:23 -07:00
Jasper St. Pierre
7f3ada7831 xprops: Some more cardinal-related hygiene 2015-06-23 15:32:07 -07:00
Jasper St. Pierre
12771a555a theme: Make sure to clear the entirety of buttons properly
In commit cc5def1, buttons were changed from GdkRectangles to
MetaButtonSpace units, but the corresponding memset hack was not.

This means that the clickable portion of the unshade rectangle
was always set to uninitalized memory. The effects of this were
random, but in cases where the moon is aligned just right, the
rectangle would graze over the borders, and so it would take priority
over other borders and show a pointer cursor instead of a resize
cursor.
2015-06-23 15:27:52 -07:00
Jasper St. Pierre
92d6a69153 xprops: Fix more gulong / 64-bit fallout from the xcb port 2015-06-23 15:09:32 -07:00
Jasper St. Pierre
734402e14d xprops: Cut off UTF-8 strings at n_items characters
There can be junk after here on some X servers.
2015-06-23 11:53:30 -07:00
Jasper St. Pierre
5d360a9bce xprops: Make sure that properties that failed to fetch are ignored 2015-06-23 11:52:49 -07:00
Jasper St. Pierre
f8cf5e373c mutter-Xatomtype: Fix the sizes of these structs
Since we're using xcb now, not Xlib, it doesn't have the stupid silly
thing where it copies all 32-bit data to 64-bit data to match the
long-y-ness of it.
2015-06-23 11:46:29 -07:00
Christian Kirbach
8df3fa4e67 Updated German translation 2015-06-20 08:10:09 +00:00
Jonas Ådahl
bbf2b4e60e xprops: Don't pass ULONG_MAX as a uint32_t parameter
It seems the largest possible value is to be passed, so actually pass
that instead. Note that even though the name of the xcb_get_property
parameter is called 'long_length' its actually a uint32_t.

https://bugzilla.gnome.org/show_bug.cgi?id=751136
2015-06-18 11:38:00 +08:00
Jonas Ådahl
bb4dcd62ec MetaWaylandDataDevice: Propagate the unsetting of a selection
If a client unsets a selection (calls set_selection with the offer
NULL), this should cause the compositor not to continue sending the
previously set offer.

https://bugzilla.gnome.org/show_bug.cgi?id=750007
2015-06-18 11:15:18 +08:00
Jasper St. Pierre
2345b9c6ad xprops: Fix syntax error 2015-06-17 18:19:53 -07:00
Jasper St. Pierre
af7cc87bfa xprops: More XFree => g_free compatibility 2015-06-17 18:18:43 -07:00
Jasper St. Pierre
af3b599cbb xprops: Remove cvtINT32toInt
These are awful compatibility hacks for systems without native 64-bit
support. We can trash these now.
2015-06-17 18:18:03 -07:00
Jasper St. Pierre
0e73ceb4bd x11: Remove async-getprop
xcb can do this for us now.
2015-06-17 18:08:11 -07:00
Carlos Garnacho
82a7060cdb x11: Fix touch events on nested wayland
If we're running as a nested compositor, we must not attempt to
passive grab on the root window, and we should be setting the
touch event mask on the stage window.

https://bugzilla.gnome.org/show_bug.cgi?id=751036
2015-06-16 20:39:46 +02:00
Carlos Garnacho
09120132ef core: Refrain from showing wayland windows when we don't have a buffer yet
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
2015-06-16 20:35:25 +02:00
Carlos Garnacho
cdac4d0e92 wayland: Ensure we queue a "calc showing" operation after we get a buffer
This will ensure the window is made visible, now that we're going to ignore
all previous petitions until we get a buffer.

https://bugzilla.gnome.org/show_bug.cgi?id=750552
2015-06-16 20:35:00 +02:00
Jasper St. Pierre
6aead0c67c backend-x11: Use a mode switch to determine whether we're nested or not
The "meta_is_wayland_compositor" checks were getting a bit difficult to read.
2015-06-16 08:13:13 -07:00
Olivier Fourdan
d593a61b39 wayland: do not generate motion events
Mutter generates a motion event for every button and scroll events,
which confuses Xwayland apps that rely on XMotionEvents for various
purposes, e.g. it fools rxvt jumpy mouse detection code.

Remove the call to notify_motion() from the button and scroll event
handlers to avoid these spurious motion events.

https://bugzilla.gnome.org/show_bug.cgi?id=748705
2015-06-12 11:14:21 -04:00
Jasper St. Pierre
9747277b7e Revert "input-settings-x11: Use xcb to change input settings"
This reverts commit 989f9630a4.

xcb is not smart enough to properly submit requests for
XIChangeProperty. Let's revert this until we can fix xcb.
2015-06-12 00:49:39 -04:00
Jasper St. Pierre
989f9630a4 input-settings-x11: Use xcb to change input settings
This way, we won't be hit with BadValue errors if we set it to a value
outside the X device's range. This can happen for touchpads without
two-finger scrolling, for instance.
2015-06-11 21:13:21 -04:00
Jonas Ådahl
daa15d94fd xdg-shell: Popups should be placed relative to the parent surface
According to the xdg-shell protocol specification the (x, y) coordinates
passed when creating a popup surface is relative to top left corner of
the parent surface, but prior to this patch, if the parent surface was
a xdg_surface, it'd position it relative to top left corner of the
window geometry of that xdg_surface.

https://bugzilla.gnome.org/show_bug.cgi?id=749716
2015-06-10 11:08:12 +08:00
Marek Černocký
999b99a077 Updated Czech translation 2015-06-05 10:05:44 +02:00
Marek Černocký
fd0b366a96 Updated Czech translation 2015-06-05 09:52:03 +02:00
Thomas Hellstrom
320e2d452f mutter/wayland: Add some missing output names
Sync with the drm_mode.h include file.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>

https://bugzilla.gnome.org/show_bug.cgi?id=750363
2015-06-03 13:28:19 -07:00
Thomas Hellstrom
4d5dd01b7d mutter/wayland: Improved preferred mode selection for the native backend
Instead of selecting the first drm mode as the preferred mode, select the
first drm mode marked as preferred. If there are no modes marked as
preferred, revert to the old behaviour and select the first mode.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>

https://bugzilla.gnome.org/show_bug.cgi?id=750363
2015-06-03 13:28:19 -07:00
Thomas Hellstrom
103c88bd72 mutter/wayland: Have the native backend read drm layout properties
Read the drm layout properties suggested_X, suggested_Y and
hotplug_mode_update and transfer them to the meta layer.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>

https://bugzilla.gnome.org/show_bug.cgi?id=750363
2015-06-03 13:28:19 -07:00
Jonas Ådahl
64cf87cfe1 MetaWaylandSurface: Create the window when creating wl_shell_surface
Some clients will do things like set_toplevel before committing the
buffer, so we need to have a window to manipulate before that.

https://bugzilla.gnome.org/show_bug.cgi?id=750256
2015-06-02 10:28:09 +08:00
Dave Airlie
9f65edd4f5 backend/x11: add support for setting randr 1.5 monitors
This interface allows us to propogate back the constructed
monitors to randr using the randr 1.5 protocol. Apps
should pick it up from there.
2015-06-01 09:38:13 -07:00
Dave Airlie
ea2496c80a monitors: construct tiled monitors info
The monitors info structure is created from the tiled outputs
and this is used as the central storage for info about a monitor
as opposed to the output state.

It appears at least the EDID mm w/h is for the whole monitor and
not per tile.
2015-06-01 09:38:13 -07:00
Dave Airlie
0c30ceddbe monitors: add tiled support to the linear config
This makes sure when we generate a linear config, that
tiles get placed in the correct position relative to each other.
2015-06-01 09:38:13 -07:00
Dave Airlie
5c9846c53a monitors: change find_primary to return an index
This will make it easier to add tiling support.
2015-06-01 09:38:13 -07:00
Dave Airlie
2a8563ab23 monitors: adds expose tile info as a property over dbus interface
This just adds 8 uint32s as a property to the dbus protocol.

This will be used by gnome-desktop to get the tile info.
2015-06-01 09:38:13 -07:00
Dave Airlie
6a77d9722a backend: add output tile info retrieval.
this just adds backend support for retrieving the tile
information from X11 (randr 1.5) and native backends.

It stores the tiling information into the output struct.
2015-06-01 09:38:13 -07:00
Dave Airlie
ef296031cb backends/x11: add a flag to denote randr 1.5 is in use.
If the server reports randr 1.5, just cache the information
for later patches to use.
2015-06-01 09:38:13 -07:00
Dave Airlie
e2d6028924 wayland: use monitors info for outputs instead of kms outputs
Wayland shouldn't use KMS outputs, it should use the monitor
infos to show its outputs, this will make tiled monitors work
with wayland.
2015-06-01 09:38:13 -07:00
Jasper St. Pierre
4d80a4cc31 Use more g_autofoo throughout mutter 2015-05-29 17:18:35 -07:00
Carlos Garnacho
4a968c3b4e xwayland: Implement X11-to-wayland DnD
When DnD is started from an X11 client, mutter now sets up an special
grab that 1) Ensures the drag source keeps receiving events, and 2)
Moves an internal X Window over wayland clients as soon as the pointer
enters over these.

That window will act as the X-side peer for the currently focused
wayland client, and will transform XdndEnter/Position/Leave/Drop
messages into wayland actions. If DnD happens between X11 clients,
the window will be moved away and unmapped, to let these operate as
usual.

https://bugzilla.gnome.org/show_bug.cgi?id=738312
2015-05-29 11:27:53 +02:00
Carlos Garnacho
ccb7833e99 xwayland: Implement wayland-to-X11 DnD
X11 client windows now hook a X11-specific MetaWaylandDragDestFuncs
that converts these into Xdnd* messages, and an additional selection
bridge has been added to take care of XdndSelection, and the data
transfers done through it.

https://bugzilla.gnome.org/show_bug.cgi?id=738312
2015-05-29 11:27:53 +02:00
Carlos Garnacho
b449ba942a xwayland: Refactor XFixesSelectionNotifyEvent handler
Prepare it for more selection atoms (i.e. XdndSelection) to come.

https://bugzilla.gnome.org/show_bug.cgi?id=738312
2015-05-29 11:27:53 +02:00
Carlos Garnacho
f53eea2c1c wayland: Refactor DnD target functions into MetaWaylandDragDestFuncs
This will be useful in order to interact with drag dest surfaces in
its windowing-specific ways, although everything defaults to the
wayland vfuncs.

https://bugzilla.gnome.org/show_bug.cgi?id=738312
2015-05-29 11:27:52 +02:00
Rui Matos
b62db404ee backends/native: Reset idle time when resuming from suspend
https://bugzilla.gnome.org/show_bug.cgi?id=749994
2015-05-28 13:47:08 +02:00
Rui Matos
90a28e7b1c native/meta-launcher: Reset idle time when our session becomes active
https://bugzilla.gnome.org/show_bug.cgi?id=749994
2015-05-28 13:47:08 +02:00
Florian Müllner
8d51a9db5b Bump version to 3.17.2
Update NEWS.
2015-05-27 10:28:44 +02:00
Rui Matos
b39c00f344 window: Fix meta_window_set_alive() not working if first ping fails
window->is_alive isn't initialized explicitly so it defaults to FALSE
meaning that if the first ping fails we'd short circuit and not show
the delete dialog as we should.

We could initialize the variable to TRUE but in fact we don't even
need the variable at all since our dialog management is enough to
manage all the state we need, i.e. we're only interested in knowing
whether we're already displaying a delete dialog.

This does change our behavior here since previously we wouldn't
display the dialog again if the next ping failed after the dialog is
dismissed but this was arguably a bug too since in that case there
wouldn't be a way to kill the window after waiting for a while and the
window kept being unresponsive.

https://bugzilla.gnome.org/show_bug.cgi?id=749711
2015-05-22 16:53:42 +02:00
Rui Matos
83ce71c3bf backend-native: Reset idle time on lid open events
This makes gnome-settings-daemon turn on the backlight and
gnome-shell's screen shield animate.

Note that on X sessions, gnome-settings-daemon uses the same upower
property to force an innocuous key event into the X server so that the
idle time gets reset since Xorg doesn't do this itself on lid events.

https://bugzilla.gnome.org/show_bug.cgi?id=749076
2015-05-22 16:53:42 +02:00
Rui Matos
f9d869a3dd backend-native: Remove unused variable
https://bugzilla.gnome.org/show_bug.cgi?id=749076
2015-05-22 16:43:44 +02:00
Carlos Garnacho
0b0ce4193f xwayland: Ensure we've got an owner when setting the X selection owner
Otherwise we may end up claiming the X selection when there's no wayland
selection owner.
2015-05-18 20:59:07 +02:00
Carlos Garnacho
719d8bd0c7 xwayland: remove unused struct field 2015-05-18 20:58:57 +02:00
Carlos Garnacho
4fc1811c15 wayland: Add X11/wayland selection interoperation
This piece of code hooks in both wl_data_device and the relevant X
selection events, an X11 Window is set up so it can act as the clipboard
owner when any wayland client owns the selection, reacting to
SelectionRequest events, and returning the data from the wayland client
FD to any X11 requestor through X properties.

In the opposite direction, SelectionNotify messages are received,
which results in the property contents being converted then written
into the wayland requestor's FD.

This code also takes care of the handling incremental transfers through
the INCR property type, reading/writing data chunk by chunk.

https://bugzilla.gnome.org/show_bug.cgi?id=738312
2015-05-15 17:43:53 +02:00
Carlos Garnacho
4b5f5abb4f wayland: refactor MetaWaylandDataSource
Expose it partly (in internal headers anyway), and pass a vtable for the
data source functions, the wayland vfuncs just delegate operations on the
wl_data_source resource. The resource has been also made optional, although
it'll be present on all data sources from wayland clients.

The ownership/lifetime of the DnD data source has also changed a bit,
belonging now to the MetaWaylandDataDevice like the selection one does, as
we can't guarantee how long it will be needed after the grab is finished,
it will be left inert and replaced the next time DnD is started at worst.

This allows the creation of custom/proxy data sources, which will turn out
useful for X11 selection interoperation.

https://bugzilla.gnome.org/show_bug.cgi?id=738312
2015-05-15 17:43:46 +02:00
Jasper St. Pierre
95ad52ba58 xrandr: Fix copy/paste typo in connector type heuristics 2015-05-12 18:17:16 -07:00
Rui Matos
dac30a222e input-settings-x11: Honor default value for click method setting
Now that xf86-input-libinput exposes default values we can honor the
gsettings value.

https://bugzilla.gnome.org/show_bug.cgi?id=746290
2015-05-08 17:44:59 +02:00
Rui Matos
7d1b593fbd input-settings-x11: Factor out a get_property() helper
We'll need to get the value of some properties. Fail if the number of
items returned is less than we expect and warn if it exceeds it so
that we can easily find out if items are added to a property later and
fix it.
2015-05-08 17:44:57 +02:00
Carlos Garnacho
d6a7559750 wayland: Fix c&p typo in wl_listener notify callback
The corresponding wl_notify field for destroy_data_device_icon()
is drag_grab->drag_icon_listener, otherwise we're fetching a pointer
that's slightly off where we want.
2015-05-01 18:50:06 +02:00
Florian Müllner
cff5ef0ec2 Bump version to 3.17.1
Update NEWS.
2015-04-30 17:35:43 +02:00
Rui Matos
d478d8f143 core/events: Invalidate monitor cache when we're a wayland compositor
When running as an X11 compositor we do this for every event we see on
the X event stream. As a wayland compositor we don't go through that
code path but since we see all events we can easily do this on motion
events.

In fact, we don't even need this caching when we're a wayland
compositor since we can always find where the pointer is without a
round trip but we're sharing the current monitor logic with the X
path so let's keep it as is for now.

https://bugzilla.gnome.org/show_bug.cgi?id=748478
2015-04-30 14:01:23 +02:00
Rui Matos
7eca43cec9 monitor-manager-kms: Avoid a couple of potential crashes
The drm API can return NULL and we could end up using uninitialized
memory if the driver private struct isn't cleared.
2015-04-28 18:00:45 +02:00
Rui Matos
9060190555 monitor-manager-kms: Read crtc props after determining the crtc ID
Otherwise we can't read the properties.
2015-04-28 18:00:44 +02:00
Jasper St. Pierre
0de3869656 core: Remove unused function 2015-04-27 18:14:15 -07:00
Jasper St. Pierre
9f13033f15 window-wayland.[ch] => meta-window-wayland.[ch]
This finishes off the meta- prefix for wayland/.
2015-04-27 18:09:16 -07:00
Jasper St. Pierre
48bf807430 monitor-manager-kms: Add support for underscan 2015-04-27 17:58:38 -07:00
Jasper St. Pierre
c68e43a97f monitor-manager-xrandr: Set the underscan border properties, too 2015-04-27 17:23:56 -07:00
Tomeu Vizoso
cc53d48fa8 MonitorManager: Add support for overscan compensation
Some DRM drivers have added a consistent set of properties that
allow compensating for the overscan that some TVs do, without the
user being able to disable.
2015-04-27 17:17:15 -07:00
Jasper St. Pierre
ca6e799b97 Move atomnames.h to x11/
This should *not* be part of the public API.
2015-04-27 16:36:56 -07:00
Jasper St. Pierre
0f8e387dc0 monitor-config: Allow loading from a system file 2015-04-27 16:31:11 -07:00
Rui Matos
d62c595e51 events: Ignore some event types when reseting idle time
These events don't result from actual hardware events so we shouldn't
use them to reset idle time.

https://bugzilla.gnome.org/show_bug.cgi?id=748541
2015-04-27 19:44:58 +02:00
Jasper St. Pierre
dd3cf94744 Properly implement wl_shell_surface's poor surface commit semantics 2015-04-25 11:19:25 -07:00
Ray Strode
eb56e0a3d7 xwayland: plug some leaks in stop function
This commit makes sure the lockfile and display
name are freed in meta_xwayland_stop.

https://bugzilla.gnome.org/show_bug.cgi?id=748380
2015-04-23 13:51:11 -04:00
Ray Strode
8937c32cd5 xwayland: rename lockfile to lock_file
The missing underscore is inconsistent with the
coding style of the surrounding code.

https://bugzilla.gnome.org/show_bug.cgi?id=748380
2015-04-23 13:51:11 -04:00
Ray Strode
a8a5da768a xwayland: don't unlink lock file twice in stop function
The stop function currently manually constructs the lock
filename from the display number and also calls unlink
on the same, already known lock filename from the manager
struct.

This commit gets rid fo the manual construction in favor
of the saved lock filename.

https://bugzilla.gnome.org/show_bug.cgi?id=748380
2015-04-23 13:51:11 -04:00
Ray Strode
33bfcf56ce xwayland: free lockfile in start function on error
Right now we just leak the lockfile.

https://bugzilla.gnome.org/show_bug.cgi?id=748380
2015-04-23 13:51:11 -04:00
Ray Strode
40cccb58a5 xwayland: use out label for cleanup in start function
The start function has a few exit paths that need to
perform clean up of the lock file.

This commit consolidates those exit paths at the end
using an out label and gotos.

https://bugzilla.gnome.org/show_bug.cgi?id=748380
2015-04-23 13:51:11 -04:00
Jonas Ådahl
eb6c70137b wayland: Add and implement set/unset_modal for the gtk_surface interface
Add set_modal ond unset_modal to the gtk_surface interface. When a
surface is modal, the compositor can treat it differently from non-modal
dialogs, for example attach it to the parent window if any. There is
currently no changes to input device focus; it is up to the client to
ignore events to the parent surface that is wanted.

This bumps the gtk_shell version to 2.

https://bugzilla.gnome.org/show_bug.cgi?id=745720
2015-04-23 16:02:37 +08:00
Jonas Ådahl
df3b412a25 wayland: Kill clients who try to bind an incompatible gtk_shell version
gtk_shell is not backward compatible, and clients binding to it should
check whether the advertised version is the same as the client supports.

https://bugzilla.gnome.org/show_bug.cgi?id=745720
2015-04-23 16:02:37 +08:00
Jonas Ådahl
cfba0a5dfc wayland: Sync protocol/gtk-shell.xml from GTK+
Had added a new capability enum value.

https://bugzilla.gnome.org/show_bug.cgi?id=745720
2015-04-23 16:02:37 +08:00
Ondrej Holy
3561b46fc6 backends/x11: Fix set_scroll_button
There is copy&pasted code in set_scroll_button, which is apparently
wrong, because it is trying to set scroll method instead of the scroll
button...

https://bugzilla.gnome.org/show_bug.cgi?id=747967
2015-04-17 10:50:33 +02:00
Carlos Garnacho
8dfb88b669 backend: Apply the right settings to the right input devices
Since 8769b3d55, the checks performed on which update_* function was
called for each device got quite more lax, leading to failed asserts
on code that assumed the previous behavior.

Change update_[mouse|touchpad|trackball]_* to bail out early if the
device received has not the right type, and remove the asserts.

https://bugzilla.gnome.org/show_bug.cgi?id=747886
2015-04-15 13:33:12 +02:00
Florian Müllner
2e3086e2aa screen: Add public method to get neighboring monitor
The existing private get_monitor_neighbor() function returns a
MetaMonitorInfo, which is private as well. Add a public wrapper
that returns a monitor index instead, as we do for other public
monitor-related methods.

https://bugzilla.gnome.org/show_bug.cgi?id=633994
2015-04-14 23:13:19 +02:00
Florian Müllner
f424056fea Bump version to 3.16.1
Update NEWS.
2015-04-14 22:38:41 +02:00
Rui Matos
cfb7297cf1 input-settings: Silence a glib critical
The scroll-wheel-emulation-button key is 'i' in the schema but it also
specifies a minimum range of 0 so using get_int() and casting is safe.
2015-04-14 18:27:52 +02:00
Rui Matos
8769b3d554 input-settings: Ensure that we always apply the same set of settings
This makes the hotplug and coldplug paths the same so that we don't
miss out on any setting.

https://bugzilla.gnome.org/show_bug.cgi?id=747434
2015-04-14 16:20:15 +02:00
Jasper St. Pierre
f8b82c376c cursor-tracker: Emit cursor-changed when XFixes tells us about it
Otherwise, we won't update the cursor in the magnifier / screen recorder
under X11.
2015-04-13 16:58:27 -07:00
Jonas Ådahl
868e1427a8 wayland: Rework synchronized state application semantics
When a parent of a subsurface gets it state applied (either by a
wl_surface.commit, wl_subsurface.set_desync or a recursive
wl_surface.commit on a parent surface), the pending position state
of the subsurface should be applied. If the subsurface is in effective
synchronized mode (i.e. if its in explicit synchronized mode or any of
its parent surfaces is a subsurface in explicit synchronized mode), the
cached state should also be applied at this point, including its
subsurface children, recursively.

https://bugzilla.gnome.org/show_bug.cgi?id=743617
2015-04-10 09:15:12 +08:00
Rui Matos
4aa74af694 wayland-keyboard: Disconnect from backend signals on release
Otherwise we'll access freed memory in the handlers.

The wayland keyboard is released when the seat loses the keyboard
capability which happens when leaving the VT so if there are keymap
changes while switched away from the VT we would crash.

https://bugzilla.gnome.org/show_bug.cgi?id=747263
2015-04-02 23:21:22 +02:00
Jasper St. Pierre
f3fecd478d frame: Always use the client window's visual for our frame
Since the frame is the window that's redirected, there's no reason for
it to match the root window. There *is*, however, a big incentive to
match the window's visual, since not doing so might trigger automatic
redirection.

On a specific platform, we construct a depth-32 root window, and stick a
depth-24 child window inside it. The frame ends up being created
depth-32, not depth-24, so we get automatic redirection.
2015-04-01 15:02:20 -07:00
Ray Strode
a5d1f67c34 wayland: try 50 times to create lock file again for login screen
since commit 8c16ac47c1, we started
creating the login screen on display 1024 instead of display 0.

This defeats this logic in try_display:

    display++;
    /* If display is above 50, then something's wrong. Just
     * abort in this case. */
    if (display > 50)

In practice it doesn't matter much since we only have one login
screen in most setups, but we should still fix the bug.

This commit introduces a separate counter to keep try of 50 tries,
rather than assuming "display number == number of tries".

https://bugzilla.gnome.org/show_bug.cgi?id=746545
2015-04-01 10:30:24 -04:00
Jasper St. Pierre
102fa0e373 xwayland: Don't leak the launcher 2015-03-31 11:47:34 -07:00
Jonas Ådahl
dbca3337b2 wayland: Fix damage of infinite regions
To avoid integer overflow when scaling "infinite" regions (0, 0)
(INT32_MAX, INT32_MAX), intersect with the surface rect before scaling,
instead of intersecting with the buffer rect afterwards.

https://bugzilla.gnome.org/show_bug.cgi?id=746510
2015-03-31 15:09:13 +08:00
Rui Matos
939f7ce781 meta-stage: To change the stage state we need to set the event type
https://bugzilla.gnome.org/show_bug.cgi?id=746670
2015-03-30 13:42:56 -04:00
Carlos Garnacho
c6e6ed87c5 backends: Center pointer on primary monitor on startup
This seems nicer/tidier than the current X11 (center on the span of all
monitors) or native (so close to the activities corner it's hard not
to trigger it) platform behaviors.

This code also takes over the native-specific pointer warping that
happens when the pointer was over a removed output.

https://bugzilla.gnome.org/show_bug.cgi?id=746896
2015-03-30 14:00:31 +02:00
Carlos Garnacho
8188cddcf7 backends: Add meta_monitor_manager_get_monitor_at_point()
This function returns the monitor_info index corresponding to the given
coordinates, or -1 if none is found at that point. The native backend
has been changed in places where it could make use of this function.

https://bugzilla.gnome.org/show_bug.cgi?id=746896
2015-03-30 14:00:31 +02:00
Ray Strode
9f17c05a15 wayland: manually activate/deactivate stage when taking/dropping grab
clutter currently never emits activated or deactivated signals on
the stage object when using the EGL backend. Since the stage never
gets activated, accessibility tools, like orca, don't work.

This commit makes mutter take on the responsibility, by tracking
when the stage gains/loses focus, and then synthesizing stage
CLUTTER_STAGE_STATE_ACTIVATED state events.

A limitation of this approach is that clutter's own notion of
the stage activeness won't reflect mutter's notion of the
stage activeness.  This isn't a problem, in practice, and can
be addressed in the medium-term after making changes to
clutter.

https://bugzilla.gnome.org/show_bug.cgi?id=746670
2015-03-28 11:20:48 -04:00
Calvin Walton
c3455b01af Include libXrender as a dependency, link it to libmutter
Mutter uses a function from libXrender (XRenderFindStandardFormat in
src/x11/iconcache.c), but doesn't link to libXrender. This causes
link issues on systems using the gold linker, particularly with
-Wl,--as-needed.

Since mutter is using a function from libXrender, adding 'xrender'
as a dependency seems appropriate, and fixes the issue.

https://bugzilla.gnome.org/show_bug.cgi?id=746692
2015-03-28 13:42:54 +01:00
Jasper St. Pierre
d4e8d97e58 xwayland: Port to GSubprocess 2015-03-27 13:58:56 -07:00
Jasper St. Pierre
a86368dcb1 xwayland: Prevent some boolean confusion
The original code in Weston that this was ported from returned an errno,
not a boolean, so we were inadvertently returning TRUE here during an
error path. Fix that up.
2015-03-27 13:58:56 -07:00
Giovanni Campagna
a13f906ed1 prefs: connect to changed:: before reading the value of a setting
Otherwise glib might skip registering to change notifications

https://bugzilla.gnome.org/show_bug.cgi?id=746509
2015-03-27 13:15:30 -07:00
Ondrej Holy
f9e91bf007 backends/native: Fix scroll method enums
The enums are swapped currently, because for edge scroll is enabled two finger
scroll and similary for two finger scroll is enabled edge scroll, what is
apparently wrong.

https://bugzilla.gnome.org/show_bug.cgi?id=746870
2015-03-27 13:08:11 +01:00
Rui Matos
7c5fe42835 meta-background: Add a function to refresh all background instances
We need to reload the FBOs under some circumstances, this adds a way
to easily do so.

https://bugzilla.gnome.org/show_bug.cgi?id=739178
2015-03-25 11:48:32 +01:00
Marek Černocký
e76decbcf2 Updated Czech translation 2015-03-25 08:45:07 +01:00
Jonas Ådahl
aac5a5dcaf MetaMonitorManager: Fix comment
https://bugzilla.gnome.org/show_bug.cgi?id=744932
2015-03-25 12:30:11 +08:00
Khaled Hosny
9b3186f8a5 Update Arabic translation 2015-03-23 21:46:18 +02:00
116 changed files with 8327 additions and 7973 deletions

6
.gitignore vendored
View File

@@ -57,10 +57,8 @@ testgradient
m4/*
INSTALL
mkinstalldirs
src/mutter-enum-types.[ch]
src/stamp-mutter-enum-types.h
src/mutter-marshal.[ch]
src/stamp-mutter-marshal.h
meta-enum-types.[ch]
src/stamp-meta-enum-types.h
src/meta-dbus-display-config.[ch]
src/meta-dbus-idle-monitor.[ch]
src/meta-dbus-login1.[ch]

View File

@@ -9,5 +9,3 @@ DISTCLEANFILES = \
intltool-update \
po/stamp-it \
po/.intltool-merge-cache
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc

69
NEWS
View File

@@ -1,3 +1,72 @@
3.17.4
======
* nested: Allow basic configuration of dummy outputs [Jonas; #747089]
* Send wl_surface.enter and wl_surface.leave on output changes [Jonas; #744453]
* Improve HiDPI handling on wayland [Jonas; #745655, #744934]
* Implement compositor-side animated cursors [Carlos; #752342]
* Misc. bug fixes [Peter, Marek, Carlos, Matthias, Rui; #750816, #751884,
#752248, #752551, #752552, #752673, #752674]
Contributors:
Jonas Ådahl, Marek Chalupa, Matthias Clasen, Carlos Garnacho, Peter Hutterer,
Rui Matos, Florian Müllner, Jasper St. Pierre
3.17.3
======
* Add X11/wayland clipboard interaction [Carlos; #738312]
* Support VM monitor layout hints on wayland [Thomas; #750363]
* Misc. bug fixes [Rui, Jonas, Olivier, Carlos, Ting-Wei, Peter, Florian;
#749994, #750256, #749716, #748705, #750552, #751036, #750007, #751136,
#750552, #751471, #751715, #750680]
Contributors:
Jonas Ådahl, Dave Airlie, Cosimo Cecchi, Olivier Fourdan, Carlos Garnacho,
Thomas Hellstrom, Peter Hutterer, Ting-Wei Lan, Jasper Lievisse Adriaanse,
Rui Matos, Florian Müllner, Jasper St. Pierre
Translations:
Marek Černocký [cs], Christian Kirbach [de], Pedro Albuquerque [pt]
3.17.2
======
* Honor default value for click method setting [Rui; #746290]
* Add X11/wayland clipboard interoperation [Carlos; #738312]
* Misc. bug fixes [Rui; #749076, #749711]
Contributors:
Carlos Garnacho, Rui Matos, Jasper St. Pierre
3.17.1
======
* Add public method to get neighboring monitor [Florian; #633994]
* Apply the right settings to the right input devices [Carlos; #747886]
* Fix scroll button setting [Ondrej; #747967]
* Add support for modal hint on wayland [Jonas; #745720]
* Don't reset idle time for non-hardware events [Rui; #748541]
* Misc. bug fixes [Ray, Rui; #748380, #748478]
Contributors:
Jonas Ådahl, Carlos Garnacho, Ondrej Holy, Rui Matos, Florian Müllner,
Jasper St. Pierre, Ray Strode, Tomeu Vizoso
3.16.1
======
* Add function to refresh all background instances [Rui; #739178]
* Fix swapped scroll methods on wayland [Ondrej; #746870]
* Manually activate stage to fix accessibility on wayland [Ray, Rui; #746670]
* Center pointer on primary monitor on startup [Carlos; #746896]
* wayland: Reword synchronized state application semantics [Jonas; #743617]
* Ensure input settings are applied on startup [Rui; #747434]
* Misc. bug fixes [Jonas, Giovanni, Calvin, Ray, Rui; #744932, #746509, #746692,
#746510, #746545, #747263]
Contributors:
Jonas Ådahl, Giovanni Campagna, Carlos Garnacho, Ondrej Holy, Rui Matos,
Jasper St. Pierre, Ray Strode, Calvin Walton
Translations:
Khaled Hosny [ar], Marek Černocký [cs]
3.16.0
======
* wayland: Don't skip notifying about initial maximized state [Jonas; #745303]

View File

@@ -1,8 +1,8 @@
AC_PREREQ(2.62)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [16])
m4_define([mutter_micro_version], [0])
m4_define([mutter_minor_version], [17])
m4_define([mutter_micro_version], [4])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@@ -52,19 +52,6 @@ PKG_PROG_PKG_CONFIG([0.21])
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS
AM_PATH_GLIB_2_0()
#### Integer sizes
AC_CHECK_SIZEOF(char)
AC_CHECK_SIZEOF(short)
AC_CHECK_SIZEOF(long)
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(void *)
AC_CHECK_SIZEOF(long long)
AC_CHECK_SIZEOF(__int64)
## byte order
AC_C_BIGENDIAN
CANBERRA_GTK=libcanberra-gtk3
CANBERRA_GTK_VERSION=0.26
@@ -90,6 +77,7 @@ MUTTER_PC_MODULES="
xkeyboard-config
xkbcommon >= 0.4.3
xkbcommon-x11
xrender
x11-xcb
xcb-randr
"
@@ -283,6 +271,8 @@ AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration,
if test "x$found_randr" = "xyes"; then
AC_DEFINE(HAVE_RANDR, , [Have the Xrandr extension library])
PKG_CHECK_EXISTS([xrandr >= 1.5.0],
AC_DEFINE([HAVE_XRANDR15],[1],[Define if you have support for XRandR 1.5 or greater]))
fi
MUTTER_LIBS="$MUTTER_LIBS $RANDR_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
@@ -329,8 +319,6 @@ if test "x$enable_debug" = "xyes"; then
CFLAGS="$CFLAGS -g -O"
fi
GTK_DOC_CHECK([1.15], [--flavour no-tmpl])
#### Warnings (last since -Werror can disturb other tests)
# Stay command-line compatible with the gnome-common configure option. Here
@@ -402,8 +390,6 @@ Makefile
data/Makefile
doc/Makefile
doc/man/Makefile
doc/reference/Makefile
doc/reference/meta-docs.sgml
src/Makefile
src/libmutter.pc
src/compositor/plugins/Makefile

View File

@@ -1,4 +1,4 @@
SUBDIRS = man reference
SUBDIRS = man
EXTRA_DIST = dialogs.txt code-overview.txt \
how-to-get-focus-right.txt rationales.txt

View File

@@ -1,183 +0,0 @@
## Process this file with automake to produce Makefile.in
# We require automake 1.6 at least.
AUTOMAKE_OPTIONS = 1.6
# This is a blank Makefile.am for using gtk-doc.
# Copy this to your project's API docs directory and modify the variables to
# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
# of using the various options.
# The name of the module, e.g. 'glib'.
DOC_MODULE=meta
# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
#DOC_MODULE_VERSION=2
# The top-level SGML file. You can change this if you want to.
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
# Directories containing the source code, relative to $(srcdir).
# gtk-doc will search all .c and .h files beneath these paths
# for inline comments documenting functions and macros.
# e.g. DOC_SOURCE_DIR=../../../gtk ../../../gdk
DOC_SOURCE_DIR=../../src/
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
SCANGOBJ_OPTIONS=
# Extra options to supply to gtkdoc-scan.
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
SCAN_OPTIONS=--rebuild-types
# Extra options to supply to gtkdoc-mkdb.
# e.g. MKDB_OPTIONS=--xml-mode --output-format=xml
MKDB_OPTIONS=--xml-mode --output-format=xml
# Extra options to supply to gtkdoc-mktmpl
# e.g. MKTMPL_OPTIONS=--only-section-tmpl
MKTMPL_OPTIONS=
# Extra options to supply to gtkdoc-mkhtml
MKHTML_OPTIONS=
# Extra options to supply to gtkdoc-fixref. Not normally needed.
# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
FIXXREF_OPTIONS=
# Used for dependencies. The docs will be rebuilt if any of these change.
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
HFILE_GLOB=$(top_srcdir)/src/*/*.h
CFILE_GLOB=$(top_srcdir)/src/*/*.c
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
EXTRA_HFILES=
# Header files or dirs to ignore when scanning. Use base file/dir names
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
IGNORE_HFILES= \
async-getprop.h \
atoms.h \
bell.h \
boxes-private.h \
clutter-utils.h \
cogl-utils.h \
compositor-private.h \
constraints.h \
core.h \
display-private.h \
draw-workspace.h \
edge-resistance.h \
eventqueue.h \
frame.h \
frames.h \
group-private.h \
group-props.h \
iconcache.h \
inlinepixbufs.h \
keybindings-private.h \
meta-background-actor-private.h \
meta-background-group-private.h \
meta-dbus-login1.h \
meta-module.h \
meta-plugin-manager.h \
meta-shadow-factory-private.h \
meta-texture-rectangle.h \
meta-texture-tower.h \
meta-window-actor-private.h \
meta-window-group.h \
meta-window-shape.h \
mutter-enum-types.h \
mutter-Xatomtype.h \
place.h \
preview-widget.h \
region-utils.h \
resizepopup.h \
screen-private.h \
session.h \
stack.h \
stack-tracker.h \
stamp-mutter-enum-types.h \
tabpopup.h \
theme.h \
theme-private.h \
tile-preview.h \
ui.h \
window-private.h \
window-props.h \
workspace-private.h \
xprops.h \
$(NULL)
if !HAVE_NATIVE_BACKEND
IGNORE_HFILES+= \
meta-backend-native.h \
meta-barrier-native.h \
meta-cursor-renderer-native.h \
meta-idle-monitor-native.h \
meta-input-settings-native.h \
meta-monitor-manager-kms.h \
$(NULL)
endif
if !HAVE_WAYLAND
IGNORE_HFILES += \
meta-surface-actor-wayland.h \
wayland \
$(NULL)
endif
MKDB_OPTIONS+=--ignore-files="$(IGNORE_HFILES)"
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
HTML_IMAGES=
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
content_files= \
mutter-overview.xml \
running-mutter.xml \
$(NULL)
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
# These files must be listed here *and* in content_files
# e.g. expand_content_files=running.sgml
expand_content_files= \
mutter-overview.xml \
running-mutter.xml \
$(NULL)
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
# signals and properties.
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS=$(MUTTER_CFLAGS)
GTKDOC_LIBS=$(MUTTER_LIBS) $(top_builddir)/src/libmutter.la
# This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make
# Other files to distribute
# e.g. EXTRA_DIST += version.xml.in
EXTRA_DIST +=
# Files not to distribute
# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
DISTCLEANFILES = $(DOC_MODULES).types
# Comment this out if you want 'make check' to test you doc status
# and run some sanity checks
if ENABLE_GTK_DOC
TESTS_ENVIRONMENT = cd $(srcdir) && \
DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \
SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir)
#TESTS = $(GTKDOC_CHECK)
endif
-include $(top_srcdir)/git.mk

View File

@@ -1,58 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
<!ENTITY version "@VERSION@">
]>
<book id="index">
<bookinfo>
<title>Mutter Reference Manual</title>
<releaseinfo>
This document is for Mutter &version;.
The latest version of this documentation can be found on-line at
<ulink role="online-location" url="http://developer.gnome.org/meta/">http://developer.gnome.org/meta/</ulink>.
</releaseinfo>
</bookinfo>
<xi:include href="xml/mutter-overview.xml"/>
<xi:include href="xml/running-mutter.xml"/>
<part id="core-reference">
<title>Mutter Core Reference</title>
<xi:include href="xml/main.xml"/>
<xi:include href="xml/common.xml"/>
<xi:include href="xml/prefs.xml"/>
<xi:include href="xml/util.xml"/>
<xi:include href="xml/errors.xml"/>
<xi:include href="xml/meta-plugin.xml"/>
<xi:include href="xml/barrier.xml"/>
<xi:include href="xml/boxes.xml"/>
<xi:include href="xml/compositor.xml"/>
<xi:include href="xml/display.xml"/>
<xi:include href="xml/group.xml"/>
<xi:include href="xml/keybindings.xml"/>
<xi:include href="xml/meta-background-actor.xml"/>
<xi:include href="xml/meta-shadow-factory.xml"/>
<xi:include href="xml/meta-shaped-texture.xml"/>
<xi:include href="xml/meta-window-actor.xml"/>
<xi:include href="xml/screen.xml"/>
<xi:include href="xml/window.xml"/>
<xi:include href="xml/workspace.xml"/>
</part>
<chapter id="object-tree">
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml"/>
</chapter>
<index id="api-index-full">
<title>API Index</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
</index>
<index id="deprecated-api-index" role="deprecated">
<title>Index of deprecated API</title>
<xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
</index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
</book>

View File

@@ -1,674 +0,0 @@
<SECTION>
<FILE>barrier</FILE>
<TITLE>MetaBarrier</TITLE>
MetaBarrier
MetaBarrierClass
meta_barrier_is_active
meta_barrier_destroy
meta_barrier_release
MetaBarrierDirection
MetaBarrierEvent
<SUBSECTION Standard>
META_BARRIER
META_BARRIER_CLASS
META_BARRIER_GET_CLASS
META_IS_BARRIER
META_IS_BARRIER_CLASS
META_TYPE_BARRIER
META_TYPE_BARRIER_EVENT
MetaBarrierPrivate
meta_barrier_event_get_type
meta_barrier_get_type
</SECTION>
<SECTION>
<FILE>boxes</FILE>
MetaRectangle
MetaStrut
MetaEdgeType
MetaEdge
meta_rectangle_copy
meta_rectangle_free
meta_rect
meta_rectangle_area
meta_rectangle_intersect
meta_rectangle_equal
meta_rectangle_union
meta_rectangle_overlap
meta_rectangle_vert_overlap
meta_rectangle_horiz_overlap
meta_rectangle_could_fit_rect
meta_rectangle_contains_rect
<SUBSECTION Standard>
META_TYPE_RECTANGLE
meta_rectangle_get_type
</SECTION>
<SECTION>
<FILE>common</FILE>
META_VIRTUAL_CORE_POINTER_ID
META_VIRTUAL_CORE_KEYBOARD_ID
MetaFrameFlags
MetaMenuOp
MetaWindowMenuFunc
MetaGrabOp
MetaCursor
MetaFrameType
MetaVirtualModifier
MetaDirection
MetaMotionDirection
MetaSide
MetaButtonFunction
MAX_BUTTONS_PER_CORNER
MetaButtonLayout
MetaFrameBorders
meta_frame_borders_clear
META_ICON_WIDTH
META_ICON_HEIGHT
META_MINI_ICON_WIDTH
META_MINI_ICON_HEIGHT
META_DEFAULT_ICON_NAME
META_PRIORITY_RESIZE
META_PRIORITY_BEFORE_REDRAW
META_PRIORITY_REDRAW
META_PRIORITY_PREFS_NOTIFY
POINT_IN_RECT
MetaStackLayer
MetaWindowMenu
MetaResizePopup
</SECTION>
<SECTION>
<FILE>compositor</FILE>
MetaCompEffect
MetaCompositor
meta_compositor_new
meta_compositor_destroy
meta_compositor_manage_screen
meta_compositor_unmanage_screen
meta_compositor_window_shape_changed
meta_compositor_process_event
meta_compositor_filter_keybinding
meta_compositor_add_window
meta_compositor_remove_window
meta_compositor_show_window
meta_compositor_hide_window
meta_compositor_switch_workspace
meta_compositor_maximize_window
meta_compositor_unmaximize_window
meta_compositor_sync_window_geometry
meta_compositor_set_updates_frozen
meta_compositor_queue_frame_drawn
meta_compositor_sync_stack
meta_compositor_sync_screen_size
meta_compositor_flash_screen
meta_get_stage_for_screen
meta_get_overlay_group_for_screen
meta_get_overlay_window
meta_get_window_actors
meta_get_window_group_for_screen
meta_get_top_window_group_for_screen
meta_disable_unredirect_for_screen
meta_enable_unredirect_for_screen
meta_set_stage_input_region
meta_empty_stage_input_region
</SECTION>
<SECTION>
<FILE>display</FILE>
MetaTabList
MetaTabShowType
meta_XFree
meta_display_get_compositor_version
meta_display_get_xinput_opcode
meta_display_supports_extended_barriers
meta_display_get_xdisplay
meta_display_get_compositor
meta_display_get_screens
meta_display_has_shape
meta_display_screen_for_root
meta_display_get_focus_window
meta_display_xwindow_is_a_no_focus_window
meta_display_get_damage_event_base
meta_display_get_shape_event_base
meta_display_xserver_time_is_before
meta_display_get_last_user_time
meta_display_get_current_time
meta_display_get_current_time_roundtrip
meta_display_get_ignored_modifier_mask
meta_display_get_tab_list
meta_display_get_tab_next
meta_display_get_tab_current
meta_display_begin_grab_op
meta_display_end_grab_op
meta_display_get_grab_op
meta_display_add_keybinding
meta_display_remove_keybinding
meta_display_get_keybinding_action
meta_display_set_input_focus_window
meta_display_focus_the_no_focus_window
meta_display_sort_windows_by_stacking
meta_display_get_leader_window
meta_display_add_ignored_crossing_serial
meta_display_unmanage_screen
meta_display_clear_mouse_mode
MetaDisplay
MetaDisplayClass
<SUBSECTION Standard>
META_DISPLAY
META_DISPLAY_CLASS
META_DISPLAY_GET_CLASS
META_IS_DISPLAY
META_IS_DISPLAY_CLASS
META_TYPE_DISPLAY
meta_display_get_type
</SECTION>
<SECTION>
<FILE>errors</FILE>
meta_error_trap_push
meta_error_trap_pop
meta_error_trap_push_with_return
meta_error_trap_pop_with_return
</SECTION>
<SECTION>
<FILE>group</FILE>
MetaGroup
meta_window_get_group
meta_window_compute_group
meta_window_shutdown_group
meta_window_group_leader_changed
meta_display_lookup_group
meta_group_list_windows
meta_group_update_layers
meta_group_get_startup_id
meta_group_get_size
meta_group_property_notify
</SECTION>
<SECTION>
<FILE>keybindings</FILE>
MetaKeyBinding
META_TYPE_KEY_BINDING
meta_key_binding_get_name
meta_key_binding_get_modifiers
meta_key_binding_get_mask
meta_key_binding_is_builtin
meta_keybindings_set_custom_handler
meta_screen_ungrab_all_keys
meta_screen_grab_all_keys
</SECTION>
<SECTION>
<FILE>main</FILE>
meta_get_option_context
meta_init
meta_run
meta_get_replace_current_wm
meta_set_wm_name
meta_set_gnome_wm_keybindings
MetaExitCode
meta_exit
meta_quit
</SECTION>
<SECTION>
<FILE>meta-background</FILE>
<TITLE>MetaBackground</TITLE>
MetaBackgroundEffects
MetaBackground
MetaBackgroundClass
meta_background_new
meta_background_copy
meta_background_load_gradient
meta_background_load_color
meta_background_load_still_frame
meta_background_load_file_async
meta_background_load_file_finish
meta_background_get_filename
meta_background_get_style
meta_background_get_shading
meta_background_get_color
meta_background_get_second_color
<SUBSECTION Standard>
META_BACKGROUND
META_BACKGROUND_CLASS
META_BACKGROUND_GET_CLASS
META_IS_BACKGROUND
META_IS_BACKGROUND_CLASS
META_TYPE_BACKGROUND
MetaBackgroundPrivate
meta_background_get_type
</SECTION>
<SECTION>
<FILE>meta-background-actor</FILE>
<TITLE>MetaBackgroundActor</TITLE>
MetaBackgroundActor
MetaBackgroundActorClass
meta_background_actor_new_for_screen
MetaSnippetHook
meta_background_actor_add_glsl_snippet
meta_background_actor_set_uniform_float
<SUBSECTION Standard>
META_BACKGROUND_ACTOR
META_BACKGROUND_ACTOR_CLASS
META_BACKGROUND_ACTOR_GET_CLASS
META_IS_BACKGROUND_ACTOR
META_IS_BACKGROUND_ACTOR_CLASS
META_TYPE_BACKGROUND_ACTOR
MetaBackgroundActorPrivate
meta_background_actor_get_type
</SECTION>
<SECTION>
<FILE>meta-background-group</FILE>
<TITLE>MetaBackgroundGroup</TITLE>
MetaBackgroundGroupClass
meta_background_group_new
<SUBSECTION Standard>
META_BACKGROUND_GROUP
META_BACKGROUND_GROUP_CLASS
META_BACKGROUND_GROUP_GET_CLASS
META_IS_BACKGROUND_GROUP
META_IS_BACKGROUND_GROUP_CLASS
META_TYPE_BACKGROUND_GROUP
MetaBackgroundGroupPrivate
meta_background_group_get_type
</SECTION>
<SECTION>
<FILE>meta-plugin</FILE>
<TITLE>MetaPlugin</TITLE>
MetaPlugin
MetaPluginClass
MetaPluginInfo
meta_plugin_running
meta_plugin_debug_mode
meta_plugin_get_info
MetaPluginVersion
META_PLUGIN_DECLARE
meta_plugin_switch_workspace_completed
meta_plugin_minimize_completed
meta_plugin_unminimize_completed
meta_plugin_maximize_completed
meta_plugin_unmaximize_completed
meta_plugin_map_completed
meta_plugin_destroy_completed
MetaModalOptions
meta_plugin_begin_modal
meta_plugin_end_modal
meta_plugin_get_screen
meta_plugin_manager_set_plugin_type
<SUBSECTION Standard>
META_IS_PLUGIN
META_IS_PLUGIN_CLASS
META_PLUGIN
META_PLUGIN_CLASS
META_PLUGIN_GET_CLASS
META_TYPE_PLUGIN
MetaPluginPrivate
meta_plugin_get_type
</SECTION>
<SECTION>
<FILE>meta-shadow-factory</FILE>
MetaShadowParams
meta_shadow_factory_get_default
meta_shadow_factory_set_params
meta_shadow_factory_get_params
MetaShadowFactory
MetaShadowFactoryClass
<SUBSECTION Standard>
META_IS_SHADOW_FACTORY
META_IS_SHADOW_FACTORY_CLASS
META_SHADOW_FACTORY
META_SHADOW_FACTORY_CLASS
META_SHADOW_FACTORY_GET_CLASS
META_TYPE_SHADOW_FACTORY
meta_shadow_factory_get_type
</SECTION>
<SECTION>
<FILE>meta-shaped-texture</FILE>
<TITLE>MetaShapedTexture</TITLE>
MetaShapedTexture
MetaShapedTextureClass
meta_shaped_texture_new
meta_shaped_texture_set_create_mipmaps
meta_shaped_texture_update_area
meta_shaped_texture_set_pixmap
meta_shaped_texture_get_texture
meta_shaped_texture_set_mask_texture
meta_shaped_texture_set_clip_region
meta_shaped_texture_get_image
<SUBSECTION Standard>
META_IS_SHAPED_TEXTURE
META_IS_SHAPED_TEXTURE_CLASS
META_SHAPED_TEXTURE
META_SHAPED_TEXTURE_CLASS
META_SHAPED_TEXTURE_GET_CLASS
META_TYPE_SHAPED_TEXTURE
MetaShapedTexturePrivate
meta_shaped_texture_get_type
</SECTION>
<SECTION>
<FILE>meta-window-actor</FILE>
<TITLE>MetaWindowActor</TITLE>
MetaWindowActor
MetaWindowActorClass
meta_window_actor_get_x_window
meta_window_actor_get_workspace
meta_window_actor_get_meta_window
meta_window_actor_get_texture
meta_window_actor_is_override_redirect
meta_window_actor_get_description
meta_window_actor_showing_on_its_workspace
meta_window_actor_is_destroyed
<SUBSECTION Standard>
META_IS_WINDOW_ACTOR
META_IS_WINDOW_ACTOR_CLASS
META_TYPE_WINDOW_ACTOR
META_WINDOW_ACTOR
META_WINDOW_ACTOR_CLASS
META_WINDOW_ACTOR_GET_CLASS
MetaWindowActorPrivate
meta_window_actor_get_type
</SECTION>
<SECTION>
<FILE>meta-cullable</FILE>
<TITLE>MetaCullable</TITLE>
MetaCullable
MetaCullableInterface
meta_cullable_cull_out
meta_cullable_reset_culling
meta_cullable_cull_out_children
meta_cullable_reset_culling_children
<SUBSECTION Standard>
META_TYPE_CULLABLE
META_CULLABLE
META_IS_CULLABLE
META_CULLABLE_GET_IFACE
meta_cullable_get_type
</SECTION>
<SECTION>
<FILE>prefs</FILE>
MetaPreference
MetaPrefsChangedFunc
meta_prefs_add_listener
meta_prefs_remove_listener
meta_prefs_init
meta_prefs_override_preference_schema
meta_preference_to_string
meta_prefs_get_mouse_button_mods
meta_prefs_get_mouse_button_resize
meta_prefs_get_mouse_button_menu
meta_prefs_get_focus_mode
meta_prefs_get_focus_new_windows
meta_prefs_get_attach_modal_dialogs
meta_prefs_get_raise_on_click
meta_prefs_get_theme
meta_prefs_get_titlebar_font
meta_prefs_get_num_workspaces
meta_prefs_get_dynamic_workspaces
meta_prefs_get_disable_workarounds
meta_prefs_get_auto_raise
meta_prefs_get_auto_raise_delay
meta_prefs_get_focus_change_on_pointer_rest
meta_prefs_get_gnome_accessibility
meta_prefs_get_gnome_animations
meta_prefs_get_edge_tiling
meta_prefs_get_auto_maximize
meta_prefs_get_button_layout
meta_prefs_get_action_double_click_titlebar
meta_prefs_get_action_middle_click_titlebar
meta_prefs_get_action_right_click_titlebar
meta_prefs_set_num_workspaces
meta_prefs_get_workspace_name
meta_prefs_change_workspace_name
meta_prefs_get_cursor_theme
meta_prefs_get_cursor_size
meta_prefs_get_compositing_manager
meta_prefs_get_force_fullscreen
meta_prefs_set_force_fullscreen
meta_prefs_get_workspaces_only_on_primary
meta_prefs_get_no_tab_popup
meta_prefs_set_no_tab_popup
meta_prefs_get_draggable_border_width
meta_prefs_get_ignore_request_hide_titlebar
meta_prefs_set_ignore_request_hide_titlebar
MetaKeyBindingAction
MetaKeyBindingFlags
MetaKeyCombo
MetaKeyHandlerFunc
meta_prefs_get_keybindings
meta_prefs_get_keybinding_action
meta_prefs_get_window_binding
meta_prefs_get_overlay_binding
meta_prefs_get_visual_bell
meta_prefs_bell_is_audible
meta_prefs_get_visual_bell_type
MetaKeyHandler
<SUBSECTION Standard>
meta_key_binding_get_type
</SECTION>
<SECTION>
<FILE>screen</FILE>
MetaScreen
MetaScreenClass
meta_screen_get_screen_number
meta_screen_get_display
meta_screen_get_xroot
meta_screen_get_size
meta_screen_get_compositor_data
meta_screen_set_compositor_data
meta_screen_for_x_screen
meta_screen_set_cm_selection
meta_screen_unset_cm_selection
meta_screen_get_startup_sequences
meta_screen_get_workspaces
meta_screen_get_n_workspaces
meta_screen_get_workspace_by_index
meta_screen_remove_workspace
meta_screen_append_new_workspace
meta_screen_get_active_workspace_index
meta_screen_get_active_workspace
meta_screen_get_n_monitors
meta_screen_get_primary_monitor
meta_screen_get_current_monitor
meta_screen_get_monitor_geometry
meta_screen_get_monitor_index_for_rect
meta_screen_focus_default_window
MetaScreenCorner
meta_screen_override_workspace_layout
<SUBSECTION Standard>
META_IS_SCREEN
META_IS_SCREEN_CLASS
META_SCREEN
META_SCREEN_CLASS
META_SCREEN_GET_CLASS
META_TYPE_SCREEN
meta_screen_get_type
</SECTION>
<SECTION>
<FILE>util</FILE>
meta_is_verbose
meta_set_verbose
meta_is_debugging
meta_set_debugging
meta_is_syncing
meta_set_syncing
meta_set_replace_current_wm
meta_debug_spew_real
meta_verbose_real
meta_bug
meta_warning
meta_fatal
MetaDebugTopic
meta_topic_real
meta_add_verbose_topic
meta_remove_verbose_topic
meta_push_no_msg_prefix
meta_pop_no_msg_prefix
meta_unsigned_long_equal
meta_unsigned_long_hash
meta_frame_type_to_string
meta_gravity_to_string
_
N_
meta_g_utf8_strndup
meta_free_gslist_and_elements
meta_show_dialog
meta_debug_spew
meta_verbose
meta_topic
MetaLaterType
meta_later_add
meta_later_remove
</SECTION>
<SECTION>
<FILE>window</FILE>
MetaWindow
MetaWindowClass
MetaWindowType
MetaMaximizeFlags
meta_window_get_frame
meta_window_has_focus
meta_window_appears_focused
meta_window_is_shaded
meta_window_is_monitor_sized
meta_window_is_override_redirect
meta_window_is_skip_taskbar
meta_window_get_rect
meta_window_get_buffer_rect
meta_window_get_frame_rect
meta_window_client_rect_to_frame_rect
meta_window_frame_rect_to_client_rect
meta_window_get_screen
meta_window_get_display
meta_window_get_xwindow
meta_window_get_window_type
meta_window_get_window_type_atom
meta_window_get_workspace
meta_window_get_monitor
meta_window_is_on_all_workspaces
meta_window_located_on_workspace
meta_window_is_hidden
meta_window_activate
meta_window_activate_with_workspace
meta_window_get_description
meta_window_get_wm_class
meta_window_get_wm_class_instance
meta_window_showing_on_its_workspace
meta_window_get_gtk_application_id
meta_window_get_gtk_unique_bus_name
meta_window_get_gtk_application_object_path
meta_window_get_gtk_window_object_path
meta_window_get_gtk_app_menu_object_path
meta_window_get_gtk_menubar_object_path
meta_window_move
meta_window_move_frame
meta_window_move_resize_frame
meta_window_move_to_monitor
meta_window_resize
meta_window_set_demands_attention
meta_window_unset_demands_attention
meta_window_get_startup_id
meta_window_change_workspace_by_index
meta_window_change_workspace
meta_window_get_compositor_private
meta_window_set_compositor_private
meta_window_configure_notify
meta_window_get_role
meta_window_get_layer
meta_window_find_root_ancestor
meta_window_is_ancestor_of_transient
MetaWindowForeachFunc
meta_window_foreach_transient
meta_window_foreach_ancestor
meta_window_get_maximized
meta_window_is_fullscreen
meta_window_is_on_primary_monitor
meta_window_requested_bypass_compositor
meta_window_requested_dont_bypass_compositor
meta_window_is_mapped
meta_window_toplevel_is_mapped
meta_window_get_icon_geometry
meta_window_set_icon_geometry
meta_window_maximize
meta_window_unmaximize
meta_window_minimize
meta_window_unminimize
meta_window_raise
meta_window_lower
meta_window_get_title
meta_window_get_transient_for
meta_window_get_transient_for_as_xid
meta_window_delete
meta_window_get_stable_sequence
meta_window_get_user_time
meta_window_get_pid
meta_window_get_client_machine
meta_window_is_remote
meta_window_is_modal
meta_window_is_attached_dialog
meta_window_get_mutter_hints
meta_window_get_frame_type
meta_window_get_frame_bounds
meta_window_get_tile_match
meta_window_make_fullscreen
meta_window_unmake_fullscreen
meta_window_make_above
meta_window_unmake_above
meta_window_shade
meta_window_unshade
meta_window_stick
meta_window_unstick
meta_window_kill
meta_window_focus
meta_window_check_alive
meta_window_get_work_area_current_monitor
meta_window_get_work_area_for_monitor
meta_window_get_work_area_all_monitors
meta_window_begin_grab_op
<SUBSECTION Standard>
META_IS_WINDOW
META_IS_WINDOW_CLASS
META_TYPE_WINDOW
META_WINDOW
META_WINDOW_CLASS
META_WINDOW_GET_CLASS
meta_window_get_type
</SECTION>
<SECTION>
<FILE>workspace</FILE>
MetaWorkspace
MetaWorkspaceClass
meta_workspace_index
meta_workspace_get_screen
meta_workspace_list_windows
meta_workspace_get_work_area_for_monitor
meta_workspace_get_work_area_all_monitors
meta_workspace_activate
meta_workspace_activate_with_focus
meta_workspace_update_window_hints
meta_workspace_set_builtin_struts
meta_workspace_get_neighbor
<SUBSECTION Standard>
META_IS_WORKSPACE
META_IS_WORKSPACE_CLASS
META_TYPE_WORKSPACE
META_WORKSPACE
META_WORKSPACE_CLASS
META_WORKSPACE_GET_CLASS
meta_workspace_get_type
</SECTION>

View File

@@ -1,15 +0,0 @@
<part id="mutter-overview">
<title>Overview</title>
<partintro>
<para>Mutter is a GObject-based library for creating compositing window managers.</para>
<para>Compositors that wish to use Mutter must implement a subclass of #MetaPlugin and register it with meta_plugin_manager_set_plugin_type() before calling meta_init() but after g_type_init().</para>
<para>#MetaPlugin provides virtual functions that allow to override default behavior in the window management code, such as the effect to perform when a window is created or when switching workspaces.</para>
</partintro>
</part>

View File

@@ -1,100 +0,0 @@
<part id="running-mutter">
<title>Running Mutter</title>
<partintro>
<section id="environment-variables">
<title>Environment Variables</title>
<para>
Mutter automatically checks environment variables during
its initialization. These environment variables are meant
as debug tools or overrides for default behaviours:
</para>
<variablelist>
<varlistentry>
<term>MUTTER_VERBOSE</term>
<listitem>
<para>Enable verbose mode, in which more information is printed to the console. Mutter needs to be built with the --enable-verbose-mode option (enabled by default). For more fine-grained control of the output, see meta_add_verbose_topic().</para>
</listitem>
</varlistentry>
<varlistentry>
<term>MUTTER_DEBUG</term>
<listitem>
<para>Traps and prints X errors to the console.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>MUTTER_G_FATAL_WARNINGS</term>
<listitem>
<para>Causes any logging from the domains Mutter, Gtk, Gdk, Pango or GLib to terminate the process (only when using the log functions in GLib).</para>
</listitem>
</varlistentry>
<varlistentry>
<term>MUTTER_USE_LOGFILE</term>
<listitem>
<para>Log all messages to a temporary file.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>MUTTER_DEBUG_XINERAMA</term>
<listitem>
<para>Log extra information about support of the XINERAMA extension.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>MUTTER_DEBUG_SM</term>
<listitem>
<para>Log extra information about session management.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>MUTTER_DEBUG_BUTTON_GRABS</term>
<listitem>
<para>Log extra information about button grabs.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>MUTTER_SYNC</term>
<listitem>
<para>Call XSync after each X call.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>MUTTER_DISPLAY</term>
<listitem>
<para>Name of the X11 display to use.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>META_DISABLE_MIPMAPS</term>
<listitem>
<para>Disable use of mipmaps for the textures that back window pixmaps.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>MUTTER_USE_STATIC_GRAVITY</term>
<listitem>
<para>Enable support for clients with static bit-gravity.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>MUTTER_WM_CLASS_FILTER</term>
<listitem>
<para>Comma-separated list of WM_CLASS names to which to restrict Mutter to.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>MUTTER_DISABLE_FALLBACK_COLOR</term>
<listitem>
<para>Disable fallback for themed colors, for easier detection of typographical errors.</para>
</listitem>
</varlistentry>
</variablelist>
</section>
</partintro>
</part>

2348
po/ar.po

File diff suppressed because it is too large Load Diff

102
po/cs.po
View File

@@ -12,7 +12,7 @@ msgstr ""
"Project-Id-Version: mutter\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2015-01-06 22:57+0000\n"
"POT-Creation-Date: 2015-03-24 23:25+0000\n"
"PO-Revision-Date: 2014-09-22 15:01+0200\n"
"Last-Translator: Petr Kovar <pknbe@volny.cz>\n"
"Language-Team: Czech <gnome-cs-list@gnome.org>\n"
@@ -30,91 +30,91 @@ msgstr "Navigace"
#: ../data/50-mutter-navigation.xml.in.h:2
msgid "Move window to workspace 1"
msgstr "Přesunout okno na plochu 1"
msgstr "Přesunout okno na pracovní plochu 1"
#: ../data/50-mutter-navigation.xml.in.h:3
msgid "Move window to workspace 2"
msgstr "Přesunout okno na plochu 2"
msgstr "Přesunout okno na pracovní plochu 2"
#: ../data/50-mutter-navigation.xml.in.h:4
msgid "Move window to workspace 3"
msgstr "Přesunout okno na plochu 3"
msgstr "Přesunout okno na pracovní plochu 3"
#: ../data/50-mutter-navigation.xml.in.h:5
msgid "Move window to workspace 4"
msgstr "Přesunout okno na plochu 4"
msgstr "Přesunout okno na pracovní plochu 4"
#: ../data/50-mutter-navigation.xml.in.h:6
msgid "Move window to last workspace"
msgstr "Přesunout okno na poslední plochu"
msgstr "Přesunout okno na poslední pracovní plochu"
#: ../data/50-mutter-navigation.xml.in.h:7
msgid "Move window one workspace to the left"
msgstr "Přesunout okno o plochu doleva"
msgstr "Přesunout okno o jednu pracovní plochu doleva"
#: ../data/50-mutter-navigation.xml.in.h:8
msgid "Move window one workspace to the right"
msgstr "Přesunout okno o plochu doprava"
msgstr "Přesunout okno o jednu pracovní plochu doprava"
#: ../data/50-mutter-navigation.xml.in.h:9
msgid "Move window one workspace up"
msgstr "Přesunout okno o plochu nahoru"
msgstr "Přesunout okno o jednu pracovní plochu nahoru"
#: ../data/50-mutter-navigation.xml.in.h:10
msgid "Move window one workspace down"
msgstr "Přesunout okno o plochu dolů"
msgstr "Přesunout okno o jednu pracovní plochu dolů"
#: ../data/50-mutter-navigation.xml.in.h:11
msgid "Move window one monitor to the left"
msgstr "Přesunout okno o monitor doleva"
msgstr "Přesunout okno o jeden monitor doleva"
#: ../data/50-mutter-navigation.xml.in.h:12
msgid "Move window one monitor to the right"
msgstr "Přesunout okno o monitor doprava"
msgstr "Přesunout okno o jeden monitor doprava"
#: ../data/50-mutter-navigation.xml.in.h:13
msgid "Move window one monitor up"
msgstr "Přesunout okno o monitor nahoru"
msgstr "Přesunout okno o jeden monitor nahoru"
#: ../data/50-mutter-navigation.xml.in.h:14
msgid "Move window one monitor down"
msgstr "Přesunout okno o monitor dolů"
msgstr "Přesunout okno o jeden monitor dolů"
#: ../data/50-mutter-navigation.xml.in.h:15
msgid "Switch applications"
msgstr "Přepnout mezi aplikacemi"
msgstr "Přepnout do jiné aplikace"
#: ../data/50-mutter-navigation.xml.in.h:16
msgid "Switch to previous application"
msgstr "Přepnout na předchozí aplikaci"
msgstr "Přepnout do předchozí aplikaci"
#: ../data/50-mutter-navigation.xml.in.h:17
msgid "Switch windows"
msgstr "Přepnout mezi okny"
msgstr "Přepnout do jiného okna"
#: ../data/50-mutter-navigation.xml.in.h:18
msgid "Switch to previous window"
msgstr "Přepnout na předchozí okno"
msgstr "Přepnout do minulého okna"
#: ../data/50-mutter-navigation.xml.in.h:19
msgid "Switch windows of an application"
msgstr "Přepnout mezi okny aplikace"
msgstr "Přepnout do jiného okna aplikace"
#: ../data/50-mutter-navigation.xml.in.h:20
msgid "Switch to previous window of an application"
msgstr "Přepnout na předchozí okno aplikace"
msgstr "Přepnout do předchozího okna aplikace"
#: ../data/50-mutter-navigation.xml.in.h:21
msgid "Switch system controls"
msgstr "Přepnout mezi systémovými ovládacími prvky"
msgstr "Přepnout na systémový ovládací prvek"
#: ../data/50-mutter-navigation.xml.in.h:22
msgid "Switch to previous system control"
msgstr "Přepnout na předchozí systémové ovládací prvky"
msgstr "Přepnout na minulý systémový ovládací prvek"
#: ../data/50-mutter-navigation.xml.in.h:23
msgid "Switch windows directly"
msgstr "Přepnout přímo mezi okny"
msgstr "Přepnout do minulého okna"
#: ../data/50-mutter-navigation.xml.in.h:24
msgid "Switch directly to previous window"
@@ -122,15 +122,15 @@ msgstr "Přepnout přímo na předchozí okno"
#: ../data/50-mutter-navigation.xml.in.h:25
msgid "Switch windows of an app directly"
msgstr "Přepnout přímo mezi okny aplikace"
msgstr "Přepnout do jiného okna aplikace"
#: ../data/50-mutter-navigation.xml.in.h:26
msgid "Switch directly to previous window of an app"
msgstr "Přepnout přímo na předchozí okno aplikace"
msgstr "Přepnout do předchozího okna aplikace"
#: ../data/50-mutter-navigation.xml.in.h:27
msgid "Switch system controls directly"
msgstr "Přepnout přímo mezi systémovými ovládacími prvky"
msgstr "Přepnout na minulý systémový ovládací prvek"
#: ../data/50-mutter-navigation.xml.in.h:28
msgid "Switch directly to previous system control"
@@ -198,7 +198,7 @@ msgstr "Aktivovat nabídku okna"
#: ../data/50-mutter-windows.xml.in.h:3
msgid "Toggle fullscreen mode"
msgstr "Přepnout režim na celou obrazovku"
msgstr "Přepnout režim celé obrazovky"
#: ../data/50-mutter-windows.xml.in.h:4
msgid "Toggle maximization state"
@@ -210,7 +210,7 @@ msgstr "Maximalizovat okno"
#: ../data/50-mutter-windows.xml.in.h:6
msgid "Restore window"
msgstr "Obnovit okno"
msgstr "Obnovit velikost okna"
#: ../data/50-mutter-windows.xml.in.h:7
msgid "Toggle shaded state"
@@ -234,20 +234,20 @@ msgstr "Změnit velikost okna"
#: ../data/50-mutter-windows.xml.in.h:12
msgid "Toggle window on all workspaces or one"
msgstr "Přepnout výskyt okna na všech plochách nebo jen na jedné"
msgstr "Přepnout okno na všechny/jednu pracovní plochu"
#: ../data/50-mutter-windows.xml.in.h:13
msgid "Raise window if covered, otherwise lower it"
msgstr ""
"Přenést okno do popředí, pokud je zakryté, jinak jej odsunout do pozadí"
"Když je okno zakryté vynést jej do popředí, jinak odsunout do pozadí"
#: ../data/50-mutter-windows.xml.in.h:14
msgid "Raise window above other windows"
msgstr "Přenést okno do popředí nad ostatní okna"
msgstr "Vynést okno do popředí nad ostatní okna"
#: ../data/50-mutter-windows.xml.in.h:15
msgid "Lower window below other windows"
msgstr "Odsunout okno do pozadí pod ostatní okna"
msgstr "Odsunout okno do pozadí za ostatní okna"
#: ../data/50-mutter-windows.xml.in.h:16
msgid "Maximize window vertically"
@@ -259,11 +259,11 @@ msgstr "Maximalizovat okno vodorovně"
#: ../data/50-mutter-windows.xml.in.h:18
msgid "View split on left"
msgstr "Zobrazit rozdělení nalevo"
msgstr "Rozdělit okno přes levou půlku obrazovky"
#: ../data/50-mutter-windows.xml.in.h:19
msgid "View split on right"
msgstr "Zobrazit rozdělení napravo"
msgstr "Rozdělit okno přes pravou půlku obrazovky"
#: ../data/mutter.desktop.in.h:1
msgid "Mutter"
@@ -437,22 +437,42 @@ msgstr "Přepnout na VT 6"
msgid "Switch to VT 7"
msgstr "Přepnout na VT 7"
#: ../src/backends/meta-monitor-manager.c:351
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:8
msgid "Switch to VT 8"
msgstr "Přepnout na VT 8"
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:9
msgid "Switch to VT 9"
msgstr "Přepnout na VT 9"
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:10
msgid "Switch to VT 10"
msgstr "Přepnout na VT 10"
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:11
msgid "Switch to VT 11"
msgstr "Přepnout na VT 11"
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:12
msgid "Switch to VT 12"
msgstr "Přepnout na VT 12"
#: ../src/backends/meta-monitor-manager.c:364
msgid "Built-in display"
msgstr "Vestavěný displej"
#: ../src/backends/meta-monitor-manager.c:378
#: ../src/backends/meta-monitor-manager.c:391
msgid "Unknown"
msgstr "Neznámý"
#: ../src/backends/meta-monitor-manager.c:380
#: ../src/backends/meta-monitor-manager.c:393
msgid "Unknown Display"
msgstr "Neznámý displej"
#. TRANSLATORS: this is a monitor vendor name, followed by a
#. * size in inches, like 'Dell 15"'
#.
#: ../src/backends/meta-monitor-manager.c:388
#: ../src/backends/meta-monitor-manager.c:401
#, c-format
msgid "%s %s"
msgstr "%s %s"
@@ -495,7 +515,7 @@ msgstr "_Počkat"
msgid "_Force Quit"
msgstr "_Vynutit ukončení"
#: ../src/core/display.c:561
#: ../src/core/display.c:562
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Nelze otevřít displej X Window System „%s“\n"
@@ -556,7 +576,7 @@ msgstr "Vypíše verzi"
msgid "Mutter plugin to use"
msgstr "Zásuvný modul Mutter, který se má použít"
#: ../src/core/prefs.c:2015
#: ../src/core/prefs.c:2004
#, c-format
msgid "Workspace %d"
msgstr "Plocha %d"
@@ -587,7 +607,7 @@ msgstr ""
"Tato okna nepodporují &quot;ukládání aktuálního nastavení&quot; a po vašem "
"příštím přihlášení je budete muset spustit ručně."
#: ../src/x11/window-props.c:558
#: ../src/x11/window-props.c:549
#, c-format
msgid "%s (on %s)"
msgstr "%s (na %s)"

1283
po/de.po

File diff suppressed because it is too large Load Diff

2516
po/pt.po

File diff suppressed because it is too large Load Diff

View File

@@ -41,9 +41,6 @@ endif
# Some random test programs for bits of the code
testboxes_SOURCES = core/testboxes.c
testasyncgetprop_SOURCES = x11/testasyncgetprop.c
noinst_PROGRAMS+=testboxes testasyncgetprop
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
noinst_PROGRAMS += testboxes

View File

@@ -39,8 +39,8 @@ mutter_built_sources = \
$(dbus_idle_built_sources) \
$(dbus_display_config_built_sources) \
$(dbus_login1_built_sources) \
mutter-enum-types.h \
mutter-enum-types.c \
meta/meta-enum-types.h \
meta-enum-types.c \
$(NULL)
if HAVE_WAYLAND
@@ -132,7 +132,6 @@ libmutter_la_SOURCES = \
compositor/meta-plugin-manager.c \
compositor/meta-plugin-manager.h \
compositor/meta-shadow-factory.c \
compositor/meta-shadow-factory-private.h \
compositor/meta-shaped-texture.c \
compositor/meta-shaped-texture-private.h \
compositor/meta-surface-actor.c \
@@ -148,7 +147,6 @@ libmutter_la_SOURCES = \
compositor/meta-window-group.c \
compositor/meta-window-group.h \
compositor/meta-window-shape.c \
compositor/meta-window-shape.h \
compositor/region-utils.c \
compositor/region-utils.h \
meta/compositor.h \
@@ -159,6 +157,7 @@ libmutter_la_SOURCES = \
meta/meta-plugin.h \
meta/meta-shadow-factory.h \
meta/meta-window-actor.h \
meta/meta-window-shape.h \
meta/compositor-mutter.h \
core/constraints.c \
core/constraints.h \
@@ -210,10 +209,7 @@ libmutter_la_SOURCES = \
meta/theme.h \
ui/theme-private.h \
ui/ui.c \
x11/iconcache.c \
x11/iconcache.h \
x11/async-getprop.c \
x11/async-getprop.h \
x11/atomnames.h \
x11/events.c \
x11/events.h \
x11/group-private.h \
@@ -221,6 +217,8 @@ libmutter_la_SOURCES = \
x11/group-props.h \
x11/group.c \
meta/group.h \
x11/iconcache.c \
x11/iconcache.h \
x11/session.c \
x11/session.h \
x11/window-props.c \
@@ -242,6 +240,8 @@ libmutter_la_SOURCES += \
wayland/meta-wayland-private.h \
wayland/meta-xwayland.c \
wayland/meta-xwayland.h \
wayland/meta-xwayland-selection.c \
wayland/meta-xwayland-selection-private.h \
wayland/meta-xwayland-private.h \
wayland/meta-wayland-buffer.c \
wayland/meta-wayland-buffer.h \
@@ -249,6 +249,7 @@ libmutter_la_SOURCES += \
wayland/meta-wayland-region.h \
wayland/meta-wayland-data-device.c \
wayland/meta-wayland-data-device.h \
wayland/meta-wayland-data-device-private.h \
wayland/meta-wayland-keyboard.c \
wayland/meta-wayland-keyboard.h \
wayland/meta-wayland-pointer.c \
@@ -265,8 +266,8 @@ libmutter_la_SOURCES += \
wayland/meta-wayland-versions.h \
wayland/meta-wayland-outputs.c \
wayland/meta-wayland-outputs.h \
wayland/window-wayland.c \
wayland/window-wayland.h \
wayland/meta-window-wayland.c \
wayland/meta-window-wayland.h \
$(NULL)
endif
@@ -322,6 +323,7 @@ libmutterinclude_headers = \
meta/meta-shaped-texture.h \
meta/meta-shadow-factory.h \
meta/meta-window-actor.h \
meta/meta-window-shape.h \
meta/prefs.h \
meta/screen.h \
meta/theme.h \
@@ -332,22 +334,18 @@ libmutterinclude_headers = \
$(NULL)
libmutterinclude_built_headers = \
meta/meta-version.h
meta/meta-version.h \
meta/meta-enum-types.h \
$(NULL)
libmutterinclude_base_headers = \
$(libmutterinclude_headers) \
$(libmutterinclude_built_headers)
# Excluded from scanning for introspection but installed
# atomnames.h: macros cause problems for scanning process
libmutterinclude_extra_headers = \
meta/atomnames.h
libmutterincludedir = $(includedir)/mutter/meta
libmutterinclude_HEADERS = \
$(libmutterinclude_headers) \
$(libmutterinclude_extra_headers)
$(libmutterinclude_headers)
nodist_libmutterinclude_HEADERS = \
$(libmutterinclude_built_headers)
@@ -390,7 +388,6 @@ Meta-$(api_version).gir: libmutter.la
@META_GIR@_CFLAGS = $(AM_CPPFLAGS)
@META_GIR@_LIBS = libmutter.la
@META_GIR@_FILES = \
mutter-enum-types.h \
$(libmutterinclude_base_headers) \
$(filter %.c,$(libmutter_la_SOURCES) $(nodist_libmutter_la_SOURCES))
@META_GIR@_SCANNERFLAGS = --warn-all --warn-error
@@ -413,8 +410,8 @@ pkgconfig_DATA = libmutter.pc
EXTRA_DIST += \
$(wayland_protocols) \
libmutter.pc.in \
mutter-enum-types.h.in \
mutter-enum-types.c.in \
meta-enum-types.h.in \
meta-enum-types.c.in \
org.freedesktop.login1.xml \
org.gnome.Mutter.DisplayConfig.xml \
org.gnome.Mutter.IdleMonitor.xml \
@@ -424,26 +421,26 @@ BUILT_SOURCES = \
$(mutter_built_sources) \
$(libmutterinclude_built_headers)
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
MUTTER_STAMP_FILES = stamp-meta-enum-types.h
CLEANFILES += $(MUTTER_STAMP_FILES)
mutter-enum-types.h: stamp-mutter-enum-types.h Makefile
meta/meta-enum-types.h: stamp-meta-enum-types.h Makefile
@true
stamp-mutter-enum-types.h: $(libmutterinclude_base_headers) mutter-enum-types.h.in
stamp-meta-enum-types.h: $(libmutterinclude_headers) meta-enum-types.h.in
$(AM_V_GEN) ( cd $(srcdir) && \
$(GLIB_MKENUMS) \
--template mutter-enum-types.h.in \
--template meta-enum-types.h.in \
$(libmutterinclude_base_headers) ) >> xgen-teth && \
(cmp -s xgen-teth mutter-enum-types.h || cp xgen-teth mutter-enum-types.h) && \
(cmp -s xgen-teth meta/meta-enum-types.h || cp xgen-teth meta/meta-enum-types.h) && \
rm -f xgen-teth && \
echo timestamp > $(@F)
mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in
meta-enum-types.c: stamp-meta-enum-types.h meta-enum-types.c.in
$(AM_V_GEN) ( cd $(srcdir) && \
$(GLIB_MKENUMS) \
--template mutter-enum-types.c.in \
--template meta-enum-types.c.in \
$(libmutterinclude_base_headers) ) >> xgen-tetc && \
cp xgen-tetc mutter-enum-types.c && \
cp xgen-tetc meta-enum-types.c && \
rm -f xgen-tetc
dbus_display_config_built_sources = meta-dbus-display-config.c meta-dbus-display-config.h

View File

@@ -92,12 +92,37 @@ meta_backend_sync_screen_size (MetaBackend *backend)
META_BACKEND_GET_CLASS (backend)->update_screen_size (backend, width, height);
}
static void
center_pointer (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
MetaMonitorInfo *monitors, *primary;
guint n_monitors;
monitors = meta_monitor_manager_get_monitor_infos (priv->monitor_manager, &n_monitors);
primary = &monitors[meta_monitor_manager_get_primary_index (priv->monitor_manager)];
meta_backend_warp_pointer (backend,
primary->rect.x + primary->rect.width / 2,
primary->rect.y + primary->rect.height / 2);
}
static void
on_monitors_changed (MetaMonitorManager *monitors,
gpointer user_data)
{
MetaBackend *backend = META_BACKEND (user_data);
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
ClutterInputDevice *device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE);
ClutterPoint point;
meta_backend_sync_screen_size (backend);
if (clutter_input_device_get_coords (device, NULL, &point))
{
/* If we're outside all monitors, warp the pointer back inside */
if (meta_monitor_manager_get_monitor_at_point (monitors, point.x, point.y) < 0)
center_pointer (backend);
}
}
static MetaIdleMonitor *
@@ -283,6 +308,8 @@ meta_backend_real_post_init (MetaBackend *backend)
}
priv->input_settings = meta_input_settings_create ();
center_pointer (backend);
}
static MetaCursorRenderer *

View File

@@ -16,7 +16,7 @@
#include "backends/native/meta-barrier-native.h"
#include "backends/x11/meta-backend-x11.h"
#include "backends/x11/meta-barrier-x11.h"
#include "mutter-enum-types.h"
#include <meta/meta-enum-types.h>
G_DEFINE_TYPE (MetaBarrier, meta_barrier, G_TYPE_OBJECT)
G_DEFINE_TYPE (MetaBarrierImpl, meta_barrier_impl, G_TYPE_OBJECT)

View File

@@ -24,6 +24,7 @@
#include "meta-cursor.h"
#include <X11/Xcursor/Xcursor.h>
#include <cogl/cogl.h>
#ifdef HAVE_NATIVE_BACKEND
@@ -42,6 +43,8 @@ typedef struct {
struct _MetaCursorReference {
int ref_count;
int current_frame;
XcursorImages *xcursor_images;
MetaCursor cursor;
MetaCursorImage image;
};
@@ -56,4 +59,8 @@ struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
int *hot_y);
#endif
gboolean meta_cursor_reference_is_animated (MetaCursorReference *self);
void meta_cursor_reference_tick_frame (MetaCursorReference *self);
guint meta_cursor_reference_get_current_frame_time (MetaCursorReference *self);
#endif /* META_CURSOR_PRIVATE_H */

View File

@@ -144,6 +144,13 @@ meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
update_cursor (renderer);
}
void
meta_cursor_renderer_force_update (MetaCursorRenderer *renderer)
{
update_cursor (renderer);
queue_redraw (renderer);
}
void
meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
int x, int y)

View File

@@ -61,6 +61,7 @@ void meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
void meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
int x, int y);
void meta_cursor_renderer_force_update (MetaCursorRenderer *renderer);
MetaCursorReference * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer);
const MetaRectangle * meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer);

View File

@@ -185,6 +185,7 @@ meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
return FALSE;
g_clear_pointer (&tracker->xfixes_cursor, meta_cursor_reference_unref);
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
return TRUE;
}

View File

@@ -67,6 +67,8 @@ meta_cursor_image_free (MetaCursorImage *image)
static void
meta_cursor_reference_free (MetaCursorReference *self)
{
if (self->xcursor_images)
XcursorImagesDestroy (self->xcursor_images);
meta_cursor_image_free (&self->image);
g_slice_free (MetaCursorReference, self);
}
@@ -135,12 +137,12 @@ meta_cursor_create_x_cursor (Display *xdisplay,
return XcursorLibraryLoadCursor (xdisplay, translate_meta_cursor (cursor));
}
static XcursorImage *
static XcursorImages *
load_cursor_on_client (MetaCursor cursor)
{
return XcursorLibraryLoadImage (translate_meta_cursor (cursor),
meta_prefs_get_cursor_theme (),
meta_prefs_get_cursor_size ());
return XcursorLibraryLoadImages (translate_meta_cursor (cursor),
meta_prefs_get_cursor_theme (),
meta_prefs_get_cursor_size ());
}
#ifdef HAVE_NATIVE_BACKEND
@@ -256,6 +258,46 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
#endif
}
static XcursorImage *
meta_cursor_reference_get_current_frame_image (MetaCursorReference *self)
{
return self->xcursor_images->images[self->current_frame];
}
void
meta_cursor_reference_tick_frame (MetaCursorReference *self)
{
XcursorImage *image;
if (!meta_cursor_reference_is_animated (self))
return;
self->current_frame++;
if (self->current_frame >= self->xcursor_images->nimage)
self->current_frame = 0;
meta_cursor_image_free (&self->image);
image = meta_cursor_reference_get_current_frame_image (self);
meta_cursor_image_load_from_xcursor_image (&self->image, image);
}
guint
meta_cursor_reference_get_current_frame_time (MetaCursorReference *self)
{
if (!meta_cursor_reference_is_animated (self))
return 0;
return self->xcursor_images->images[self->current_frame]->delay;
}
gboolean
meta_cursor_reference_is_animated (MetaCursorReference *self)
{
return (self->xcursor_images &&
self->xcursor_images->nimage > 1);
}
static void
load_cursor_image (MetaCursorReference *cursor)
{
@@ -266,12 +308,16 @@ load_cursor_image (MetaCursorReference *cursor)
* load this directly. */
g_assert (cursor->cursor != META_CURSOR_NONE);
image = load_cursor_on_client (cursor->cursor);
if (!image)
return;
if (!cursor->xcursor_images)
{
cursor->current_frame = 0;
cursor->xcursor_images = load_cursor_on_client (cursor->cursor);
if (!cursor->xcursor_images)
return;
}
image = meta_cursor_reference_get_current_frame_image (cursor);
meta_cursor_image_load_from_xcursor_image (&cursor->image, image);
XcursorImageDestroy (image);
}
MetaCursorReference *

View File

@@ -209,6 +209,10 @@ update_touchpad_left_handed (MetaInputSettings *input_settings,
MetaInputSettingsPrivate *priv;
gboolean enabled = FALSE;
if (device &&
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
return;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
handedness = g_settings_get_enum (priv->touchpad_settings, "left-handed");
@@ -230,7 +234,6 @@ update_touchpad_left_handed (MetaInputSettings *input_settings,
if (device)
{
g_assert (clutter_input_device_get_device_type (device) == CLUTTER_TOUCHPAD_DEVICE);
settings_device_set_bool_setting (input_settings, device,
input_settings_class->set_left_handed,
enabled);
@@ -251,13 +254,16 @@ update_mouse_left_handed (MetaInputSettings *input_settings,
MetaInputSettingsPrivate *priv;
gboolean enabled;
if (device &&
clutter_input_device_get_device_type (device) != CLUTTER_POINTER_DEVICE)
return;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
enabled = g_settings_get_boolean (priv->mouse_settings, "left-handed");
if (device)
{
g_assert (clutter_input_device_get_device_type (device) == CLUTTER_POINTER_DEVICE);
settings_device_set_bool_setting (input_settings, device,
input_settings_class->set_left_handed,
enabled);
@@ -279,51 +285,82 @@ update_mouse_left_handed (MetaInputSettings *input_settings,
}
}
static GSettings *
get_settings_for_device_type (MetaInputSettings *input_settings,
ClutterInputDeviceType type)
{
MetaInputSettingsPrivate *priv;
priv = meta_input_settings_get_instance_private (input_settings);
switch (type)
{
case CLUTTER_POINTER_DEVICE:
return priv->mouse_settings;
case CLUTTER_TOUCHPAD_DEVICE:
return priv->touchpad_settings;
default:
return NULL;
}
}
static void
update_device_speed (MetaInputSettings *input_settings,
GSettings *settings,
ClutterInputDevice *device,
ClutterInputDeviceType type)
ClutterInputDevice *device)
{
MetaInputSettingsClass *input_settings_class;
gdouble speed;
GSettings *settings;
ConfigDoubleFunc func;
const gchar *key = "speed";
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
speed = g_settings_get_double (settings, "speed");
func = META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_speed;
if (device)
settings_device_set_double_setting (input_settings, device,
input_settings_class->set_speed,
speed);
{
settings = get_settings_for_device_type (input_settings,
clutter_input_device_get_device_type (device));
if (!settings)
return;
settings_device_set_double_setting (input_settings, device, func,
g_settings_get_double (settings, key));
}
else
settings_set_double_setting (input_settings, type,
input_settings_class->set_speed,
speed);
{
settings = get_settings_for_device_type (input_settings, CLUTTER_POINTER_DEVICE);
settings_set_double_setting (input_settings, CLUTTER_POINTER_DEVICE, func,
g_settings_get_double (settings, key));
settings = get_settings_for_device_type (input_settings, CLUTTER_TOUCHPAD_DEVICE);
settings_set_double_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, func,
g_settings_get_double (settings, key));
}
}
static void
update_device_natural_scroll (MetaInputSettings *input_settings,
GSettings *settings,
ClutterInputDevice *device,
ClutterInputDeviceType type)
ClutterInputDevice *device)
{
MetaInputSettingsClass *input_settings_class;
gboolean enabled;
GSettings *settings;
ConfigBoolFunc func;
const gchar *key = "natural-scroll";
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
enabled = g_settings_get_boolean (settings, "natural-scroll");
func = META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_invert_scroll;
if (device)
{
settings_device_set_bool_setting (input_settings, device,
input_settings_class->set_invert_scroll,
enabled);
settings = get_settings_for_device_type (input_settings,
clutter_input_device_get_device_type (device));
if (!settings)
return;
settings_device_set_bool_setting (input_settings, device, func,
g_settings_get_boolean (settings, key));
}
else
{
settings_set_bool_setting (input_settings, type,
input_settings_class->set_invert_scroll,
enabled);
settings = get_settings_for_device_type (input_settings, CLUTTER_POINTER_DEVICE);
settings_set_bool_setting (input_settings, CLUTTER_POINTER_DEVICE, func,
g_settings_get_boolean (settings, key));
settings = get_settings_for_device_type (input_settings, CLUTTER_TOUCHPAD_DEVICE);
settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, func,
g_settings_get_boolean (settings, key));
}
}
@@ -335,6 +372,10 @@ update_touchpad_tap_enabled (MetaInputSettings *input_settings,
MetaInputSettingsPrivate *priv;
gboolean enabled;
if (device &&
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
return;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-to-click");
@@ -361,6 +402,10 @@ update_touchpad_scroll_method (MetaInputSettings *input_settings,
GDesktopTouchpadScrollMethod method;
MetaInputSettingsPrivate *priv;
if (device &&
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
return;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
method = g_settings_get_enum (priv->touchpad_settings, "scroll-method");
@@ -387,6 +432,10 @@ update_touchpad_click_method (MetaInputSettings *input_settings,
GDesktopTouchpadScrollMethod method;
MetaInputSettingsPrivate *priv;
if (device &&
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
return;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
method = g_settings_get_enum (priv->touchpad_settings, "click-method");
@@ -413,6 +462,10 @@ update_touchpad_send_events (MetaInputSettings *input_settings,
MetaInputSettingsPrivate *priv;
GDesktopDeviceSendEvents mode;
if (device &&
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
return;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
mode = g_settings_get_enum (priv->touchpad_settings, "send-events");
@@ -455,11 +508,16 @@ update_trackball_scroll_button (MetaInputSettings *input_settings,
MetaInputSettingsPrivate *priv;
guint button;
if (device && !device_is_trackball (device))
return;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
button = g_settings_get_uint (priv->trackball_settings, "scroll-wheel-emulation-button");
/* This key is 'i' in the schema but it also specifies a minimum
* range of 0 so the cast here is safe. */
button = (guint) g_settings_get_int (priv->trackball_settings, "scroll-wheel-emulation-button");
if (device && device_is_trackball (device))
if (device)
{
input_settings_class->set_scroll_button (input_settings, device, button);
}
@@ -573,22 +631,18 @@ meta_input_settings_changed_cb (GSettings *settings,
if (strcmp (key, "left-handed") == 0)
update_mouse_left_handed (input_settings, NULL);
else if (strcmp (key, "speed") == 0)
update_device_speed (input_settings, settings, NULL,
CLUTTER_POINTER_DEVICE);
update_device_speed (input_settings, NULL);
else if (strcmp (key, "natural-scroll") == 0)
update_device_natural_scroll (input_settings, settings,
NULL, CLUTTER_POINTER_DEVICE);
update_device_natural_scroll (input_settings, NULL);
}
else if (settings == priv->touchpad_settings)
{
if (strcmp (key, "left-handed") == 0)
update_touchpad_left_handed (input_settings, NULL);
else if (strcmp (key, "speed") == 0)
update_device_speed (input_settings, settings, NULL,
CLUTTER_TOUCHPAD_DEVICE);
update_device_speed (input_settings, NULL);
else if (strcmp (key, "natural-scroll") == 0)
update_device_natural_scroll (input_settings, settings,
NULL, CLUTTER_TOUCHPAD_DEVICE);
update_device_natural_scroll (input_settings, NULL);
else if (strcmp (key, "tap-to-click") == 0)
update_touchpad_tap_enabled (input_settings, NULL);
else if (strcmp (key, "send-events") == 0)
@@ -706,45 +760,35 @@ check_add_mappable_device (MetaInputSettings *input_settings,
return TRUE;
}
static void
apply_device_settings (MetaInputSettings *input_settings,
ClutterInputDevice *device)
{
update_mouse_left_handed (input_settings, device);
update_device_speed (input_settings, device);
update_device_natural_scroll (input_settings, device);
update_touchpad_left_handed (input_settings, device);
update_device_speed (input_settings, device);
update_device_natural_scroll (input_settings, device);
update_touchpad_tap_enabled (input_settings, device);
update_touchpad_send_events (input_settings, device);
update_touchpad_scroll_method (input_settings, device);
update_touchpad_click_method (input_settings, device);
update_trackball_scroll_button (input_settings, device);
}
static void
meta_input_settings_device_added (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
MetaInputSettings *input_settings)
{
ClutterInputDeviceType type;
MetaInputSettingsPrivate *priv;
if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER)
return;
priv = meta_input_settings_get_instance_private (input_settings);
type = clutter_input_device_get_device_type (device);
if (type == CLUTTER_POINTER_DEVICE)
{
update_mouse_left_handed (input_settings, device);
update_device_speed (input_settings, priv->mouse_settings, device, type);
if (device_is_trackball (device))
update_trackball_scroll_button (input_settings, device);
}
else if (type == CLUTTER_TOUCHPAD_DEVICE)
{
update_touchpad_left_handed (input_settings, device);
update_touchpad_tap_enabled (input_settings, device);
update_touchpad_scroll_method (input_settings, device);
update_touchpad_click_method (input_settings, device);
update_touchpad_send_events (input_settings, device);
update_device_speed (input_settings, priv->touchpad_settings,
device, type);
update_device_natural_scroll (input_settings, priv->touchpad_settings,
device, type);
}
else
{
check_add_mappable_device (input_settings, device);
}
apply_device_settings (input_settings, device);
check_add_mappable_device (input_settings, device);
}
static void
@@ -782,25 +826,9 @@ static void
meta_input_settings_constructed (GObject *object)
{
MetaInputSettings *input_settings = META_INPUT_SETTINGS (object);
MetaInputSettingsPrivate *priv;
priv = meta_input_settings_get_instance_private (input_settings);
update_mouse_left_handed (input_settings, NULL);
update_touchpad_left_handed (input_settings, NULL);
update_touchpad_tap_enabled (input_settings, NULL);
update_touchpad_send_events (input_settings, NULL);
update_device_natural_scroll (input_settings, priv->touchpad_settings,
NULL, CLUTTER_TOUCHPAD_DEVICE);
update_device_speed (input_settings, priv->touchpad_settings, NULL,
CLUTTER_TOUCHPAD_DEVICE);
update_device_speed (input_settings, priv->mouse_settings, NULL,
CLUTTER_POINTER_DEVICE);
apply_device_settings (input_settings, NULL);
update_keyboard_repeat (input_settings);
check_mappable_devices (input_settings);
}

View File

@@ -65,6 +65,7 @@ typedef struct {
gboolean is_primary;
gboolean is_presentation;
gboolean is_underscanning;
} MetaOutputConfig;
typedef struct {
@@ -82,7 +83,8 @@ struct _MetaMonitorConfig {
gboolean current_is_for_laptop_lid;
MetaConfiguration *previous;
GFile *file;
GFile *user_file;
GFile *system_file;
GCancellable *save_cancellable;
UpClient *up_client;
@@ -238,6 +240,7 @@ meta_monitor_config_init (MetaMonitorConfig *self)
{
const char *filename;
char *path;
const char * const *system_dirs;
self->configs = g_hash_table_new_full (config_hash, config_equal, NULL, (GDestroyNotify) config_unref);
@@ -246,9 +249,17 @@ meta_monitor_config_init (MetaMonitorConfig *self)
filename = "monitors.xml";
path = g_build_filename (g_get_user_config_dir (), filename, NULL);
self->file = g_file_new_for_path (path);
self->user_file = g_file_new_for_path (path);
g_free (path);
for (system_dirs = g_get_system_config_dirs (); !self->system_file && *system_dirs; system_dirs++)
{
path = g_build_filename (*system_dirs, filename, NULL);
if (g_file_test (path, G_FILE_TEST_EXISTS))
self->system_file = g_file_new_for_path (path);
g_free (path);
}
self->up_client = up_client_new ();
self->lid_is_closed = up_client_get_lid_is_closed (self->up_client);
@@ -393,7 +404,8 @@ handle_start_element (GMarkupParseContext *context,
strcmp (element_name, "reflect_x") == 0 ||
strcmp (element_name, "reflect_y") == 0 ||
strcmp (element_name, "primary") == 0 ||
strcmp (element_name, "presentation") == 0) && parser->unknown_count == 0)
strcmp (element_name, "presentation") == 0 ||
strcmp (element_name, "underscanning") == 0) && parser->unknown_count == 0)
{
parser->state = STATE_OUTPUT_FIELD;
@@ -477,8 +489,8 @@ handle_end_element (GMarkupParseContext *context,
}
else
{
if (parser->output.rect.width == 0 &&
parser->output.rect.width == 0)
if (parser->output.rect.width == 0 ||
parser->output.rect.height == 0)
parser->output.enabled = FALSE;
else
parser->output.enabled = TRUE;
@@ -700,6 +712,8 @@ handle_text (GMarkupParseContext *context,
parser->output.is_primary = read_bool (text, text_len, error);
else if (strcmp (parser->output_field, "presentation") == 0)
parser->output.is_presentation = read_bool (text, text_len, error);
else if (strcmp (parser->output_field, "underscanning") == 0)
parser->output.is_underscanning = read_bool (text, text_len, error);
else
g_assert_not_reached ();
return;
@@ -717,8 +731,8 @@ static const GMarkupParser config_parser = {
.text = handle_text,
};
static void
meta_monitor_config_load (MetaMonitorConfig *self)
static gboolean
load_config_file (MetaMonitorConfig *self, GFile *file)
{
char *contents;
gsize size;
@@ -736,14 +750,12 @@ meta_monitor_config_load (MetaMonitorConfig *self)
*/
error = NULL;
ok = g_file_load_contents (self->file, NULL, &contents, &size, NULL, &error);
ok = g_file_load_contents (file, NULL, &contents, &size, NULL, &error);
if (!ok)
{
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
meta_warning ("Failed to load stored monitor configuration: %s\n", error->message);
g_error_free (error);
return;
return FALSE;
}
memset (&parser, 0, sizeof (ConfigParser));
@@ -772,6 +784,17 @@ meta_monitor_config_load (MetaMonitorConfig *self)
g_markup_parse_context_free (context);
g_free (contents);
return ok;
}
static void
meta_monitor_config_load (MetaMonitorConfig *self)
{
if (self->user_file && load_config_file (self, self->user_file))
return;
if (self->system_file && load_config_file (self, self->system_file))
return;
}
MetaMonitorConfig *
@@ -863,14 +886,14 @@ apply_configuration (MetaMonitorConfig *self,
MetaConfiguration *config,
MetaMonitorManager *manager)
{
GPtrArray *crtcs, *outputs;
gboolean ret = FALSE;
g_autoptr(GPtrArray) crtcs = NULL;
g_autoptr(GPtrArray) outputs = NULL;
crtcs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_crtc_info_free);
outputs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_output_info_free);
if (!meta_monitor_config_assign_crtcs (config, manager, crtcs, outputs))
goto out;
return FALSE;
meta_monitor_manager_apply_configuration (manager,
(MetaCRTCInfo**)crtcs->pdata, crtcs->len,
@@ -882,12 +905,7 @@ apply_configuration (MetaMonitorConfig *self,
* inside turn_off_laptop_display / apply_configuration_with_lid */
self->current_is_for_laptop_lid = FALSE;
ret = TRUE;
out:
g_ptr_array_unref (crtcs);
g_ptr_array_unref (outputs);
return ret;
return TRUE;
}
static gboolean
@@ -1056,12 +1074,12 @@ meta_monitor_config_apply_stored (MetaMonitorConfig *self,
* which are internal monitors), or failing that, the one with the
* best resolution
*/
static MetaOutput *
static int
find_primary_output (MetaOutput *outputs,
unsigned n_outputs)
{
unsigned i;
MetaOutput *best;
int best;
int best_width, best_height;
g_assert (n_outputs >= 1);
@@ -1069,23 +1087,23 @@ find_primary_output (MetaOutput *outputs,
for (i = 0; i < n_outputs; i++)
{
if (outputs[i].is_primary)
return &outputs[i];
return i;
}
for (i = 0; i < n_outputs; i++)
{
if (output_is_laptop (&outputs[i]))
return &outputs[i];
return i;
}
best = NULL;
best = -1;
best_width = 0; best_height = 0;
for (i = 0; i < n_outputs; i++)
{
if (outputs[i].preferred_mode->width * outputs[i].preferred_mode->height >
best_width * best_height)
{
best = &outputs[i];
best = i;
best_width = outputs[i].preferred_mode->width;
best_height = outputs[i].preferred_mode->height;
}
@@ -1123,7 +1141,7 @@ make_suggested_config (MetaMonitorConfig *self,
MetaConfiguration *config)
{
unsigned int i;
MetaOutput *primary;
int primary;
GList *region = NULL;
g_return_val_if_fail (config != NULL, FALSE);
@@ -1131,7 +1149,7 @@ make_suggested_config (MetaMonitorConfig *self,
for (i = 0; i < n_outputs; i++)
{
gboolean is_primary = (&outputs[i] == primary);
gboolean is_primary = ((int)i == primary);
if (outputs[i].suggested_x < 0 || outputs[i].suggested_y < 0)
return FALSE;
@@ -1158,6 +1176,81 @@ make_suggested_config (MetaMonitorConfig *self,
return TRUE;
}
static void
config_one_untiled_output (MetaOutput *outputs,
MetaConfiguration *config,
int idx, gboolean is_primary,
int *x, unsigned long *output_configured_bitmap)
{
MetaOutput *output = &outputs[idx];
if (*output_configured_bitmap & (1 << idx))
return;
init_config_from_preferred_mode (&config->outputs[idx], output);
config->outputs[idx].is_primary = is_primary;
config->outputs[idx].rect.x = *x;
*x += config->outputs[idx].rect.width;
*output_configured_bitmap |= (1 << idx);
}
static void
config_one_tiled_group (MetaOutput *outputs,
MetaConfiguration *config,
int base_idx, gboolean is_primary,
int n_outputs,
int *x, unsigned long *output_configured_bitmap)
{
guint32 num_h_tile, num_v_tile, ht, vt;
int j;
int cur_x, cur_y, addx = 0;
if (*output_configured_bitmap & (1 << base_idx))
return;
if (outputs[base_idx].tile_info.group_id == 0)
return;
cur_x = cur_y = 0;
num_h_tile = outputs[base_idx].tile_info.max_h_tiles;
num_v_tile = outputs[base_idx].tile_info.max_v_tiles;
/* iterate over horizontal tiles */
cur_x = *x;
for (ht = 0; ht < num_h_tile; ht++)
{
cur_y = 0;
addx = 0;
for (vt = 0; vt < num_v_tile; vt++)
{
for (j = 0; j < n_outputs; j++)
{
if (outputs[j].tile_info.group_id != outputs[base_idx].tile_info.group_id)
continue;
if (outputs[j].tile_info.loc_h_tile != ht ||
outputs[j].tile_info.loc_v_tile != vt)
continue;
if (ht == 0 && vt == 0 && is_primary)
config->outputs[j].is_primary = TRUE;
init_config_from_preferred_mode (&config->outputs[j], &outputs[j]);
config->outputs[j].rect.x = cur_x;
config->outputs[j].rect.y = cur_y;
*output_configured_bitmap |= (1 << j);
cur_y += outputs[j].tile_info.tile_h;
if (vt == 0)
addx += outputs[j].tile_info.tile_w;
}
}
cur_x += addx;
}
*x = cur_x;
}
static void
make_linear_config (MetaMonitorConfig *self,
MetaOutput *outputs,
@@ -1166,31 +1259,41 @@ make_linear_config (MetaMonitorConfig *self,
int max_height,
MetaConfiguration *config)
{
MetaOutput *primary;
unsigned long output_configured_bitmap = 0;
unsigned i;
int x;
int primary;
g_return_if_fail (config != NULL);
primary = find_primary_output (outputs, n_outputs);
x = primary->preferred_mode->width;
x = 0;
/* set the primary up first at 0 */
if (outputs[primary].tile_info.group_id)
{
config_one_tiled_group (outputs, config, primary, TRUE, n_outputs,
&x, &output_configured_bitmap);
}
else
{
config_one_untiled_output (outputs, config, primary, TRUE,
&x, &output_configured_bitmap);
}
/* then add other tiled monitors */
for (i = 0; i < n_outputs; i++)
{
gboolean is_primary = (&outputs[i] == primary);
config_one_tiled_group (outputs, config, i, FALSE, n_outputs,
&x, &output_configured_bitmap);
}
init_config_from_preferred_mode (&config->outputs[i], &outputs[i]);
config->outputs[i].is_primary = is_primary;
/* then add remaining monitors */
for (i = 0; i < n_outputs; i++)
{
config_one_untiled_output (outputs, config, i, FALSE,
&x, &output_configured_bitmap);
if (is_primary)
{
config->outputs[i].rect.x = 0;
}
else
{
config->outputs[i].rect.x = x;
x += config->outputs[i].rect.width;
}
}
}
@@ -1314,7 +1417,7 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
unsigned n_outputs)
{
MetaConfiguration *config;
MetaOutput *primary;
int primary;
unsigned i;
/* Check that we have at least one active output */
@@ -1332,7 +1435,7 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
for (i = 0; i < n_outputs; i++)
{
gboolean is_primary = (&outputs[i] == primary);
gboolean is_primary = ((int)i == primary);
if (is_primary)
{
@@ -1408,6 +1511,7 @@ init_config_from_output (MetaOutputConfig *config,
config->transform = output->crtc->transform;
config->is_primary = output->is_primary;
config->is_presentation = output->is_presentation;
config->is_underscanning = output->is_underscanning;
}
void
@@ -1598,7 +1702,8 @@ meta_monitor_config_save (MetaMonitorConfig *self)
" <reflect_x>%s</reflect_x>\n"
" <reflect_y>no</reflect_y>\n"
" <primary>%s</primary>\n"
" <presentation>%s</presentation>\n",
" <presentation>%s</presentation>\n"
" <underscanning>%s</underscanning>\n",
output->rect.width,
output->rect.height,
refresh_rate,
@@ -1607,7 +1712,8 @@ meta_monitor_config_save (MetaMonitorConfig *self)
rotation_map[output->transform & 0x3],
output->transform >= META_MONITOR_TRANSFORM_FLIPPED ? "yes" : "no",
output->is_primary ? "yes" : "no",
output->is_presentation ? "yes" : "no");
output->is_presentation ? "yes" : "no",
output->is_underscanning ? "yes" : "no");
}
g_string_append (buffer, " </output>\n");
@@ -1622,7 +1728,7 @@ meta_monitor_config_save (MetaMonitorConfig *self)
closure->config = g_object_ref (self);
closure->buffer = buffer;
g_file_replace_contents_async (self->file,
g_file_replace_contents_async (self->user_file,
buffer->str, buffer->len,
NULL, /* etag */
TRUE,
@@ -1814,7 +1920,6 @@ real_assign_crtcs (CrtcAssignment *assignment,
MetaOutputKey *output_key;
MetaOutputConfig *output_config;
unsigned int i;
gboolean success;
if (output_num == assignment->config->n_outputs)
return TRUE;
@@ -1831,8 +1936,6 @@ real_assign_crtcs (CrtcAssignment *assignment,
&crtcs, &n_crtcs,
&outputs, &n_outputs);
success = FALSE;
for (i = 0; i < n_crtcs; i++)
{
MetaCRTC *crtc = &crtcs[i];
@@ -1879,10 +1982,7 @@ real_assign_crtcs (CrtcAssignment *assignment,
output))
{
if (real_assign_crtcs (assignment, output_num + 1))
{
success = TRUE;
goto out;
}
return TRUE;
crtc_assignment_unassign (assignment, crtc, output);
}
@@ -1891,8 +1991,7 @@ real_assign_crtcs (CrtcAssignment *assignment,
}
}
out:
return success;
return FALSE;
}
static gboolean
@@ -1941,6 +2040,7 @@ meta_monitor_config_assign_crtcs (MetaConfiguration *config,
&config->keys[i]);
output_info->is_primary = output_config->is_primary;
output_info->is_presentation = output_config->is_presentation;
output_info->is_underscanning = output_config->is_underscanning;
g_ptr_array_add (outputs, output_info);
}

View File

@@ -27,6 +27,10 @@
#include "meta-monitor-manager-dummy.h"
#include <stdlib.h>
#include <meta/util.h>
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
struct _MetaMonitorManagerDummy
@@ -44,9 +48,69 @@ G_DEFINE_TYPE (MetaMonitorManagerDummy, meta_monitor_manager_dummy, META_TYPE_MO
static void
meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
{
unsigned int num_monitors = 1;
int *monitor_scales = NULL;
const char *num_monitors_str;
const char *monitor_scales_str;
unsigned int i;
int current_x = 0;
/* To control what monitor configuration is generated, there are two available
* environmental variables that can be used:
*
* MUTTER_DEBUG_NUM_DUMMY_MONITORS
*
* Specifies the number of dummy monitors to include in the stage. Every
* monitor is 1024x786 pixels and they are placed on a horizontal row.
*
* MUTTER_DEBUG_DUMMY_MONITOR_SCALES
*
* A comma separated list that specifies the scales of the dummy monitors.
*
* For example the following configuration results in two monitors, where the
* first one has the monitor scale 1, and the other the monitor scale 2.
*
* MUTTER_DEBUG_NUM_DUMMY_MONITORS=2
* MUTTER_DEBUG_DUMMY_MONITOR_SCALES=1,2
*/
num_monitors_str = getenv ("MUTTER_DEBUG_NUM_DUMMY_MONITORS");
if (num_monitors_str)
{
num_monitors = g_ascii_strtoll (num_monitors_str, NULL, 10);
if (num_monitors <= 0)
{
meta_warning ("Invalid number of dummy monitors");
num_monitors = 1;
}
}
monitor_scales = g_newa (int, num_monitors);
for (i = 0; i < num_monitors; i++)
monitor_scales[i] = 1;
monitor_scales_str = getenv ("MUTTER_DEBUG_DUMMY_MONITOR_SCALES");
if (monitor_scales_str)
{
gchar **scales_str_list;
scales_str_list = g_strsplit (monitor_scales_str, ",", -1);
if (g_strv_length (scales_str_list) != num_monitors)
meta_warning ("Number of specified monitor scales differ from number "
"of monitors (defaults to 1).\n");
for (i = 0; i < num_monitors && scales_str_list[i]; i++)
{
int scale = g_ascii_strtoll (scales_str_list[i], NULL, 10);
if (scale == 1 || scale == 2)
monitor_scales[i] = scale;
else
meta_warning ("Invalid dummy monitor scale");
}
g_strfreev (scales_str_list);
}
manager->max_screen_width = 65535;
manager->max_screen_height = 65535;
manager->screen_width = 1024;
manager->screen_width = 1024 * num_monitors;
manager->screen_height = 768;
manager->modes = g_new0 (MetaMonitorMode, 1);
@@ -57,46 +121,52 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
manager->modes[0].height = 768;
manager->modes[0].refresh_rate = 60.0;
manager->crtcs = g_new0 (MetaCRTC, 1);
manager->n_crtcs = 1;
manager->crtcs = g_new0 (MetaCRTC, num_monitors);
manager->n_crtcs = num_monitors;
manager->outputs = g_new0 (MetaOutput, num_monitors);
manager->n_outputs = num_monitors;
manager->crtcs[0].crtc_id = 1;
manager->crtcs[0].rect.x = 0;
manager->crtcs[0].rect.y = 0;
manager->crtcs[0].rect.width = manager->modes[0].width;
manager->crtcs[0].rect.height = manager->modes[0].height;
manager->crtcs[0].current_mode = &manager->modes[0];
manager->crtcs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
manager->crtcs[0].all_transforms = ALL_TRANSFORMS;
manager->crtcs[0].is_dirty = FALSE;
manager->crtcs[0].logical_monitor = NULL;
for (i = 0; i < num_monitors; i++)
{
manager->crtcs[i].crtc_id = i + 1;
manager->crtcs[i].rect.x = current_x;
manager->crtcs[i].rect.y = 0;
manager->crtcs[i].rect.width = manager->modes[0].width;
manager->crtcs[i].rect.height = manager->modes[0].height;
manager->crtcs[i].current_mode = &manager->modes[0];
manager->crtcs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
manager->crtcs[i].all_transforms = ALL_TRANSFORMS;
manager->crtcs[i].is_dirty = FALSE;
manager->crtcs[i].logical_monitor = NULL;
manager->outputs = g_new0 (MetaOutput, 1);
manager->n_outputs = 1;
current_x += manager->crtcs[i].rect.width;
manager->outputs[0].crtc = &manager->crtcs[0];
manager->outputs[0].winsys_id = 1;
manager->outputs[0].name = g_strdup ("LVDS");
manager->outputs[0].vendor = g_strdup ("MetaProducts Inc.");
manager->outputs[0].product = g_strdup ("unknown");
manager->outputs[0].serial = g_strdup ("0xC0FFEE");
manager->outputs[0].width_mm = 222;
manager->outputs[0].height_mm = 125;
manager->outputs[0].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
manager->outputs[0].preferred_mode = &manager->modes[0];
manager->outputs[0].n_modes = 1;
manager->outputs[0].modes = g_new0 (MetaMonitorMode *, 1);
manager->outputs[0].modes[0] = &manager->modes[0];
manager->outputs[0].n_possible_crtcs = 1;
manager->outputs[0].possible_crtcs = g_new0 (MetaCRTC *, 1);
manager->outputs[0].possible_crtcs[0] = &manager->crtcs[0];
manager->outputs[0].n_possible_clones = 0;
manager->outputs[0].possible_clones = g_new0 (MetaOutput *, 0);
manager->outputs[0].backlight = -1;
manager->outputs[0].backlight_min = 0;
manager->outputs[0].backlight_max = 0;
manager->outputs[0].connector_type = META_CONNECTOR_TYPE_LVDS;
manager->outputs[0].scale = 1;
manager->outputs[i].crtc = &manager->crtcs[i];
manager->outputs[i].winsys_id = i + 1;
manager->outputs[i].name = g_strdup_printf ("LVDS%d", i + 1);
manager->outputs[i].vendor = g_strdup ("MetaProducts Inc.");
manager->outputs[i].product = g_strdup ("unknown");
manager->outputs[i].serial = g_strdup ("0xC0FFEE");
manager->outputs[i].suggested_x = -1;
manager->outputs[i].suggested_y = -1;
manager->outputs[i].width_mm = 222;
manager->outputs[i].height_mm = 125;
manager->outputs[i].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
manager->outputs[i].preferred_mode = &manager->modes[0];
manager->outputs[i].n_modes = 1;
manager->outputs[i].modes = g_new0 (MetaMonitorMode *, 1);
manager->outputs[i].modes[0] = &manager->modes[0];
manager->outputs[i].n_possible_crtcs = 1;
manager->outputs[i].possible_crtcs = g_new0 (MetaCRTC *, 1);
manager->outputs[i].possible_crtcs[0] = &manager->crtcs[i];
manager->outputs[i].n_possible_clones = 0;
manager->outputs[i].possible_clones = g_new0 (MetaOutput *, 0);
manager->outputs[i].backlight = -1;
manager->outputs[i].backlight_min = 0;
manager->outputs[i].backlight_max = 0;
manager->outputs[i].connector_type = META_CONNECTOR_TYPE_LVDS;
manager->outputs[i].scale = monitor_scales[i];
}
}
static void

View File

@@ -56,6 +56,7 @@ typedef struct _MetaMonitorMode MetaMonitorMode;
typedef struct _MetaMonitorInfo MetaMonitorInfo;
typedef struct _MetaCRTCInfo MetaCRTCInfo;
typedef struct _MetaOutputInfo MetaOutputInfo;
typedef struct _MetaTileInfo MetaTileInfo;
typedef enum {
META_MONITOR_TRANSFORM_NORMAL,
@@ -89,6 +90,17 @@ typedef enum {
META_CONNECTOR_TYPE_DSI = 16,
} MetaConnectorType;
struct _MetaTileInfo {
guint32 group_id;
guint32 flags;
guint32 max_h_tiles;
guint32 max_v_tiles;
guint32 loc_h_tile;
guint32 loc_v_tile;
guint32 tile_w;
guint32 tile_h;
};
struct _MetaOutput
{
/* The CRTC driving this output, NULL if the output is not enabled */
@@ -132,6 +144,8 @@ struct _MetaOutput
*/
gboolean is_primary;
gboolean is_presentation;
gboolean is_underscanning;
gboolean supports_underscanning;
gpointer driver_private;
GDestroyNotify driver_notify;
@@ -140,6 +154,8 @@ struct _MetaOutput
gboolean hotplug_mode_update;
gint suggested_x;
gint suggested_y;
MetaTileInfo tile_info;
};
struct _MetaCRTC
@@ -159,6 +175,9 @@ struct _MetaCRTC
gboolean is_dirty;
MetaCursorReference *cursor;
gpointer driver_private;
GDestroyNotify driver_notify;
};
struct _MetaMonitorMode
@@ -175,6 +194,7 @@ struct _MetaMonitorMode
GDestroyNotify driver_notify;
};
#define META_MAX_OUTPUTS_PER_MONITOR 4
/**
* MetaMonitorInfo:
*
@@ -190,9 +210,14 @@ struct _MetaMonitorInfo
int number;
int xinerama_index;
MetaRectangle rect;
/* for tiled monitors these are calculated, from untiled just copied */
float refresh_rate;
int width_mm;
int height_mm;
gboolean is_primary;
gboolean is_presentation; /* XXX: not yet used */
gboolean in_fullscreen;
int scale;
/* The primary or first output for this monitor, 0 if we can't figure out.
It can be matched to a winsys_id of a MetaOutput.
@@ -203,6 +228,12 @@ struct _MetaMonitorInfo
the primary one).
*/
glong winsys_id;
guint32 tile_group_id;
int monitor_winsys_xid;
int n_outputs;
MetaOutput *outputs[META_MAX_OUTPUTS_PER_MONITOR];
};
/*
@@ -224,12 +255,13 @@ struct _MetaCRTCInfo {
/*
* MetaOutputInfo:
* this is the same as MetaOutputInfo, but for CRTCs
* this is the same as MetaCRTCInfo, but for outputs
*/
struct _MetaOutputInfo {
MetaOutput *output;
gboolean is_primary;
gboolean is_presentation;
gboolean is_underscanning;
};
#define META_TYPE_MONITOR_MANAGER (meta_monitor_manager_get_type ())
@@ -319,6 +351,13 @@ struct _MetaMonitorManagerClass
unsigned short *,
unsigned short *,
unsigned short *);
void (*add_monitor) (MetaMonitorManager *,
MetaMonitorInfo *);
void (*delete_monitor) (MetaMonitorManager *,
int monitor_winsys_xid);
};
void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager);
@@ -370,6 +409,10 @@ gboolean meta_monitor_manager_get_monitor_matrix (MetaMonitorManager *
MetaOutput *output,
gfloat matrix[6]);
gint meta_monitor_manager_get_monitor_at_point (MetaMonitorManager *manager,
gfloat x,
gfloat y);
/* Returns true if transform causes width and height to be inverted
This is true for the odd transforms in the enum */
static inline gboolean

View File

@@ -71,6 +71,98 @@ meta_monitor_manager_init (MetaMonitorManager *manager)
{
}
/*
* rules for constructing a tiled monitor
* 1. find a tile_group_id
* 2. iterate over all outputs for that tile group id
* 3. see if output has a crtc and if it is configured for the tile size
* 4. calculate the total tile size
* 5. set tile finished size
* 6. check for more tile_group_id
*/
static void
construct_tile_monitor (MetaMonitorManager *manager,
GArray *monitor_infos,
guint32 tile_group_id)
{
MetaMonitorInfo info;
unsigned i;
for (i = 0; i < monitor_infos->len; i++)
{
MetaMonitorInfo *pinfo = &g_array_index (monitor_infos, MetaMonitorInfo, i);
if (pinfo->tile_group_id == tile_group_id)
return;
}
/* didn't find it */
info.number = monitor_infos->len;
info.tile_group_id = tile_group_id;
info.is_presentation = FALSE;
info.refresh_rate = 0.0;
info.width_mm = 0;
info.height_mm = 0;
info.is_primary = FALSE;
info.rect.x = INT_MAX;
info.rect.y = INT_MAX;
info.rect.width = 0;
info.rect.height = 0;
info.winsys_id = 0;
info.n_outputs = 0;
info.monitor_winsys_xid = 0;
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *output = &manager->outputs[i];
if (!output->tile_info.group_id)
continue;
if (output->tile_info.group_id != tile_group_id)
continue;
if (!output->crtc)
continue;
if (output->crtc->rect.width != (int)output->tile_info.tile_w ||
output->crtc->rect.height != (int)output->tile_info.tile_h)
continue;
if (output->tile_info.loc_h_tile == 0 && output->tile_info.loc_v_tile == 0)
{
info.refresh_rate = output->crtc->current_mode->refresh_rate;
info.width_mm = output->width_mm;
info.height_mm = output->height_mm;
info.winsys_id = output->winsys_id;
}
/* hack */
if (output->crtc->rect.x < info.rect.x)
info.rect.x = output->crtc->rect.x;
if (output->crtc->rect.y < info.rect.y)
info.rect.y = output->crtc->rect.y;
if (output->tile_info.loc_h_tile == 0)
info.rect.height += output->tile_info.tile_h;
if (output->tile_info.loc_v_tile == 0)
info.rect.width += output->tile_info.tile_w;
if (info.n_outputs > META_MAX_OUTPUTS_PER_MONITOR)
continue;
info.outputs[info.n_outputs++] = output;
}
/* if we don't have a winsys id, i.e. we haven't found tile 0,0
don't try and add this to the monitor infos */
if (!info.winsys_id)
return;
g_array_append_val (monitor_infos, info);
}
/*
* make_logical_config:
*
@@ -81,6 +173,7 @@ meta_monitor_manager_init (MetaMonitorManager *manager)
static void
make_logical_config (MetaMonitorManager *manager)
{
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (manager);
GArray *monitor_infos;
unsigned int i, j;
@@ -91,6 +184,15 @@ make_logical_config (MetaMonitorManager *manager)
for each of them, unless they reference a rectangle that
is already there.
*/
/* for tiling we need to work out how many tiled outputs there are */
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *output = &manager->outputs[i];
if (output->tile_info.group_id)
construct_tile_monitor (manager, monitor_infos, output->tile_info.group_id);
}
for (i = 0; i < manager->n_crtcs; i++)
{
MetaCRTC *crtc = &manager->crtcs[i];
@@ -102,8 +204,8 @@ make_logical_config (MetaMonitorManager *manager)
for (j = 0; j < monitor_infos->len; j++)
{
MetaMonitorInfo *info = &g_array_index (monitor_infos, MetaMonitorInfo, j);
if (meta_rectangle_equal (&crtc->rect,
&info->rect))
if (meta_rectangle_contains_rect (&info->rect,
&crtc->rect))
{
crtc->logical_monitor = info;
break;
@@ -115,7 +217,10 @@ make_logical_config (MetaMonitorManager *manager)
MetaMonitorInfo info;
info.number = monitor_infos->len;
info.tile_group_id = 0;
info.rect = crtc->rect;
info.refresh_rate = crtc->current_mode->refresh_rate;
info.scale = 1;
info.is_primary = FALSE;
/* This starts true because we want
is_presentation only if all outputs are
@@ -125,7 +230,8 @@ make_logical_config (MetaMonitorManager *manager)
info.is_presentation = TRUE;
info.in_fullscreen = -1;
info.winsys_id = 0;
info.n_outputs = 0;
info.monitor_winsys_xid = 0;
g_array_append_val (monitor_infos, info);
crtc->logical_monitor = &g_array_index (monitor_infos, MetaMonitorInfo,
@@ -147,6 +253,9 @@ make_logical_config (MetaMonitorManager *manager)
if (output->crtc == NULL)
continue;
if (output->tile_info.group_id)
continue;
/* We must have a logical monitor on every CRTC at this point */
g_assert (output->crtc->logical_monitor != NULL);
@@ -155,8 +264,17 @@ make_logical_config (MetaMonitorManager *manager)
info->is_primary = info->is_primary || output->is_primary;
info->is_presentation = info->is_presentation && output->is_presentation;
info->width_mm = output->width_mm;
info->height_mm = output->height_mm;
info->outputs[0] = output;
info->n_outputs = 1;
if (output->is_primary || info->winsys_id == 0)
info->winsys_id = output->winsys_id;
{
info->scale = output->scale;
info->winsys_id = output->winsys_id;
}
if (info->is_primary)
manager->primary_monitor_index = info->number;
@@ -164,6 +282,10 @@ make_logical_config (MetaMonitorManager *manager)
manager->n_monitor_infos = monitor_infos->len;
manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
if (manager_class->add_monitor)
for (i = 0; i < manager->n_monitor_infos; i++)
manager_class->add_monitor (manager, &manager->monitor_infos[i]);
}
static void
@@ -264,6 +386,21 @@ meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
g_free (old_modes);
}
static void
meta_monitor_manager_free_crtc_array (MetaCRTC *old_crtcs,
int n_old_crtcs)
{
int i;
for (i = 0; i < n_old_crtcs; i++)
{
if (old_crtcs[i].driver_notify)
old_crtcs[i].driver_notify (&old_crtcs[i]);
}
g_free (old_crtcs);
}
static void
meta_monitor_manager_finalize (GObject *object)
{
@@ -271,8 +408,8 @@ meta_monitor_manager_finalize (GObject *object)
meta_monitor_manager_free_output_array (manager->outputs, manager->n_outputs);
meta_monitor_manager_free_mode_array (manager->modes, manager->n_modes);
meta_monitor_manager_free_crtc_array (manager->crtcs, manager->n_crtcs);
g_free (manager->monitor_infos);
g_free (manager->crtcs);
G_OBJECT_CLASS (meta_monitor_manager_parent_class)->finalize (object);
}
@@ -353,16 +490,14 @@ static char *
make_display_name (MetaMonitorManager *manager,
MetaOutput *output)
{
char *inches = NULL;
char *vendor_name = NULL;
char *ret;
g_autofree char *inches = NULL;
g_autofree char *vendor_name = NULL;
switch (output->connector_type)
{
case META_CONNECTOR_TYPE_LVDS:
case META_CONNECTOR_TYPE_eDP:
ret = g_strdup (_("Built-in display"));
goto out;
return g_strdup (_("Built-in display"));
default:
break;
}
@@ -398,18 +533,12 @@ make_display_name (MetaMonitorManager *manager,
/* TRANSLATORS: this is a monitor vendor name, followed by a
* size in inches, like 'Dell 15"'
*/
ret = g_strdup_printf (_("%s %s"), vendor_name, inches);
return g_strdup_printf (_("%s %s"), vendor_name, inches);
}
else
{
ret = g_strdup (vendor_name);
return g_strdup (vendor_name);
}
out:
g_free (inches);
g_free (vendor_name);
return ret;
}
static const char *
@@ -520,6 +649,10 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_new_boolean (output->is_presentation));
g_variant_builder_add (&properties, "{sv}", "connector-type",
g_variant_new_string (get_connector_type_name (output->connector_type)));
g_variant_builder_add (&properties, "{sv}", "underscanning",
g_variant_new_boolean (output->is_underscanning));
g_variant_builder_add (&properties, "{sv}", "supports-underscanning",
g_variant_new_boolean (output->supports_underscanning));
edid_file = manager_class->get_edid_file (manager, output);
if (edid_file)
@@ -540,6 +673,20 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
}
}
if (output->tile_info.group_id)
{
g_variant_builder_add (&properties, "{sv}", "tile",
g_variant_new ("(uuuuuuuu)",
output->tile_info.group_id,
output->tile_info.flags,
output->tile_info.max_h_tiles,
output->tile_info.max_v_tiles,
output->tile_info.loc_h_tile,
output->tile_info.loc_v_tile,
output->tile_info.tile_w,
output->tile_info.tile_h));
}
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
i, /* ID */
(gint64)output->winsys_id,
@@ -808,7 +955,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_index, &properties))
{
MetaOutputInfo *output_info;
gboolean primary, presentation;
gboolean primary, presentation, underscanning;
if (output_index >= manager->n_outputs)
{
@@ -827,6 +974,9 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
if (g_variant_lookup (properties, "presentation", "b", &presentation))
output_info->is_presentation = presentation;
if (g_variant_lookup (properties, "underscanning", "b", &underscanning))
output_info->is_underscanning = underscanning;
g_ptr_array_add (output_infos, output_info);
}
@@ -1194,37 +1344,58 @@ meta_monitor_manager_read_current_config (MetaMonitorManager *manager)
MetaOutput *old_outputs;
MetaCRTC *old_crtcs;
MetaMonitorMode *old_modes;
unsigned int n_old_outputs, n_old_modes;
unsigned int n_old_outputs, n_old_crtcs, n_old_modes;
/* Some implementations of read_current use the existing information
* we have available, so don't free the old configuration until after
* read_current finishes. */
old_outputs = manager->outputs;
n_old_outputs = manager->n_outputs;
old_crtcs = manager->crtcs;
n_old_crtcs = manager->n_crtcs;
old_modes = manager->modes;
n_old_modes = manager->n_modes;
old_crtcs = manager->crtcs;
manager->serial++;
META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager);
meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
g_free (old_crtcs);
meta_monitor_manager_free_crtc_array (old_crtcs, n_old_crtcs);
}
void
meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager)
{
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (manager);
MetaMonitorInfo *old_monitor_infos;
unsigned old_n_monitor_infos;
unsigned i, j;
old_monitor_infos = manager->monitor_infos;
old_n_monitor_infos = manager->n_monitor_infos;
if (manager->in_init)
return;
make_logical_config (manager);
if (manager_class->delete_monitor)
{
for (i = 0; i < old_n_monitor_infos; i++)
{
gboolean delete_mon = TRUE;
for (j = 0; j < manager->n_monitor_infos; j++)
{
if (manager->monitor_infos[j].monitor_winsys_xid == old_monitor_infos[i].monitor_winsys_xid)
{
delete_mon = FALSE;
break;
}
}
if (delete_mon)
manager_class->delete_monitor (manager, old_monitor_infos[i].monitor_winsys_xid);
}
}
g_signal_emit_by_name (manager, "monitors-changed");
g_free (old_monitor_infos);
@@ -1245,25 +1416,35 @@ meta_output_parse_edid (MetaOutput *meta_output,
if (parsed_edid)
{
meta_output->vendor = g_strndup (parsed_edid->manufacturer_code, 4);
if (parsed_edid->dsc_product_name[0])
meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14);
else
meta_output->product = g_strdup_printf ("0x%04x", (unsigned) parsed_edid->product_code);
if (parsed_edid->dsc_serial_number[0])
meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14);
else
meta_output->serial = g_strdup_printf ("0x%08x", parsed_edid->serial_number);
if (!g_utf8_validate (meta_output->vendor, -1, NULL))
g_clear_pointer (&meta_output->vendor, g_free);
meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14);
if (!g_utf8_validate (meta_output->product, -1, NULL) ||
meta_output->product[0] == '\0')
{
g_clear_pointer (&meta_output->product, g_free);
meta_output->product = g_strdup_printf ("0x%04x", (unsigned) parsed_edid->product_code);
}
meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14);
if (!g_utf8_validate (meta_output->serial, -1, NULL) ||
meta_output->serial[0] == '\0')
{
g_clear_pointer (&meta_output->serial, g_free);
meta_output->serial = g_strdup_printf ("0x%08x", parsed_edid->serial_number);
}
g_free (parsed_edid);
}
out:
if (!meta_output->vendor)
{
meta_output->vendor = g_strdup ("unknown");
meta_output->product = g_strdup ("unknown");
meta_output->serial = g_strdup ("unknown");
}
meta_output->vendor = g_strdup ("unknown");
if (!meta_output->product)
meta_output->product = g_strdup ("unknown");
if (!meta_output->serial)
meta_output->serial = g_strdup ("unknown");
}
void
@@ -1368,3 +1549,27 @@ meta_monitor_manager_get_monitor_for_output (MetaMonitorManager *manager,
return -1;
}
gint
meta_monitor_manager_get_monitor_at_point (MetaMonitorManager *manager,
gfloat x,
gfloat y)
{
unsigned int i;
for (i = 0; i < manager->n_monitor_infos; i++)
{
MetaMonitorInfo *monitor = &manager->monitor_infos[i];
int left, right, top, bottom;
left = monitor->rect.x;
right = left + monitor->rect.width;
top = monitor->rect.y;
bottom = top + monitor->rect.height;
if ((x >= left) && (x < right) && (y >= top) && (y < bottom))
return i;
}
return -1;
}

View File

@@ -41,6 +41,7 @@ typedef struct {
struct _MetaStagePrivate {
MetaOverlay cursor_overlay;
gboolean is_active;
};
typedef struct _MetaStagePrivate MetaStagePrivate;
@@ -126,15 +127,41 @@ meta_stage_paint (ClutterActor *actor)
meta_overlay_paint (&priv->cursor_overlay);
}
static void
meta_stage_activate (ClutterStage *actor)
{
MetaStage *stage = META_STAGE (actor);
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
CLUTTER_STAGE_CLASS (meta_stage_parent_class)->activate (actor);
priv->is_active = TRUE;
}
static void
meta_stage_deactivate (ClutterStage *actor)
{
MetaStage *stage = META_STAGE (actor);
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
CLUTTER_STAGE_CLASS (meta_stage_parent_class)->deactivate (actor);
priv->is_active = FALSE;
}
static void
meta_stage_class_init (MetaStageClass *klass)
{
ClutterStageClass *stage_class = (ClutterStageClass *) klass;
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
GObjectClass *object_class = (GObjectClass *) klass;
object_class->finalize = meta_stage_finalize;
actor_class->paint = meta_stage_paint;
stage_class->activate = meta_stage_activate;
stage_class->deactivate = meta_stage_deactivate;
}
static void
@@ -195,3 +222,43 @@ meta_stage_set_cursor (MetaStage *stage,
meta_overlay_set (&priv->cursor_overlay, texture, rect);
queue_redraw_for_overlay (stage, &priv->cursor_overlay);
}
void
meta_stage_set_active (MetaStage *stage,
gboolean is_active)
{
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
ClutterEvent event = { 0 };
/* Used by the native backend to inform accessibility technologies
* about when the stage loses and gains input focus.
*
* For the X11 backend, clutter transparently takes care of this
* for us.
*/
if (priv->is_active == is_active)
return;
event.type = CLUTTER_STAGE_STATE;
clutter_event_set_stage (&event, CLUTTER_STAGE (stage));
event.stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED;
if (is_active)
event.stage_state.new_state = CLUTTER_STAGE_STATE_ACTIVATED;
/* Emitting this StageState event will result in the stage getting
* activated or deactivated (with the activated or deactivated signal
* getting emitted from the stage)
*
* FIXME: This won't update ClutterStage's own notion of its
* activeness. For that we would need to somehow trigger a
* _clutter_stage_update_state call, which will probably
* require new API in clutter. In practice, nothing relies
* on the ClutterStage's own notion of activeness when using
* the EGL backend.
*
* See http://bugzilla.gnome.org/746670
*/
clutter_stage_event (CLUTTER_STAGE (stage), &event);
}

View File

@@ -54,6 +54,9 @@ ClutterActor *meta_stage_new (void);
void meta_stage_set_cursor (MetaStage *stage,
CoglTexture *texture,
MetaRectangle *rect);
void meta_stage_set_active (MetaStage *stage,
gboolean is_active);
G_END_DECLS
#endif /* META_STAGE_H */

View File

@@ -29,6 +29,7 @@
#include <meta/main.h>
#include <clutter/evdev/clutter-evdev.h>
#include <libupower-glib/upower.h>
#include "meta-barrier-native.h"
#include "meta-idle-monitor-native.h"
@@ -39,10 +40,11 @@
struct _MetaBackendNativePrivate
{
MetaLauncher *launcher;
MetaBarrierManagerNative *barrier_manager;
GSettings *keyboard_settings;
UpClient *up_client;
guint sleep_signal_id;
GCancellable *cancellable;
GDBusConnection *system_bus;
};
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
@@ -56,9 +58,69 @@ meta_backend_native_finalize (GObject *object)
meta_launcher_free (priv->launcher);
g_object_unref (priv->up_client);
if (priv->sleep_signal_id)
g_dbus_connection_signal_unsubscribe (priv->system_bus, priv->sleep_signal_id);
g_cancellable_cancel (priv->cancellable);
g_clear_object (&priv->cancellable);
g_clear_object (&priv->system_bus);
G_OBJECT_CLASS (meta_backend_native_parent_class)->finalize (object);
}
static void
prepare_for_sleep_cb (GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
const gchar *interface_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
gboolean suspending;
g_variant_get (parameters, "(b)", &suspending);
if (suspending)
return;
meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ());
}
static void
system_bus_gotten_cb (GObject *object,
GAsyncResult *res,
gpointer user_data)
{
MetaBackendNativePrivate *priv;
GDBusConnection *bus;
bus = g_bus_get_finish (res, NULL);
if (!bus)
return;
priv = meta_backend_native_get_instance_private (META_BACKEND_NATIVE (user_data));
priv->system_bus = bus;
priv->sleep_signal_id = g_dbus_connection_signal_subscribe (priv->system_bus,
"org.freedesktop.login1",
"org.freedesktop.login1.Manager",
"PrepareForSleep",
"/org/freedesktop/login1",
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
prepare_for_sleep_cb,
NULL,
NULL);
}
static void
lid_is_closed_changed_cb (UpClient *client,
GParamSpec *pspec,
gpointer user_data)
{
if (up_client_get_lid_is_closed (client))
return;
meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ());
}
static void
constrain_to_barriers (ClutterInputDevice *device,
guint32 time,
@@ -84,31 +146,6 @@ constrain_to_barriers (ClutterInputDevice *device,
*
*/
static gboolean
check_all_screen_monitors(MetaMonitorInfo *monitors,
unsigned n_monitors,
float x,
float y)
{
unsigned int i;
for (i = 0; i < n_monitors; i++)
{
MetaMonitorInfo *monitor = &monitors[i];
int left, right, top, bottom;
left = monitor->rect.x;
right = left + monitor->rect.width;
top = monitor->rect.y;
bottom = top + monitor->rect.height;
if ((x >= left) && (x < right) && (y >= top) && (y < bottom))
return TRUE;
}
return FALSE;
}
static void
constrain_all_screen_monitors (ClutterInputDevice *device,
MetaMonitorInfo *monitors,
@@ -162,7 +199,6 @@ pointer_constrain_callback (ClutterInputDevice *device,
MetaMonitorManager *monitor_manager;
MetaMonitorInfo *monitors;
unsigned int n_monitors;
gboolean ret;
/* Constrain to barriers */
constrain_to_barriers (device, time, new_x, new_y);
@@ -171,57 +207,22 @@ pointer_constrain_callback (ClutterInputDevice *device,
monitors = meta_monitor_manager_get_monitor_infos (monitor_manager, &n_monitors);
/* if we're moving inside a monitor, we're fine */
ret = check_all_screen_monitors(monitors, n_monitors, *new_x, *new_y);
if (ret == TRUE)
if (meta_monitor_manager_get_monitor_at_point (monitor_manager, *new_x, *new_y) >= 0)
return;
/* if we're trying to escape, clamp to the CRTC we're coming from */
constrain_all_screen_monitors(device, monitors, n_monitors, new_x, new_y);
}
static void
on_monitors_changed (MetaMonitorManager *monitor_manager,
MetaBackend *backend)
{
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
ClutterInputDevice *device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE);
MetaMonitorInfo *monitors, *primary;
unsigned int n_monitors;
ClutterPoint point;
if (!clutter_input_device_get_coords (device, NULL, &point))
return;
monitors = meta_monitor_manager_get_monitor_infos (monitor_manager, &n_monitors);
/* if we're inside a monitor, we're fine */
if (check_all_screen_monitors (monitors, n_monitors, point.x, point.y))
return;
/* warp the pointer to the primary monitor so it isn't lost */
primary = &monitors[meta_monitor_manager_get_primary_index (monitor_manager)];
meta_backend_warp_pointer (backend,
primary->rect.x + primary->rect.width / 2,
primary->rect.y + primary->rect.height / 2);
}
static void
meta_backend_native_post_init (MetaBackend *backend)
{
MetaMonitorManager *monitor_manager;
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
META_BACKEND_CLASS (meta_backend_native_parent_class)->post_init (backend);
clutter_evdev_set_pointer_constrain_callback (manager, pointer_constrain_callback,
NULL, NULL);
monitor_manager = meta_backend_get_monitor_manager (backend);
g_signal_connect_object (monitor_manager, "monitors-changed",
G_CALLBACK (on_monitors_changed), backend, G_CONNECT_AFTER);
/* make sure the pointer is in the visible area after init */
on_monitors_changed (monitor_manager, backend);
}
static MetaIdleMonitor *
@@ -331,6 +332,16 @@ meta_backend_native_init (MetaBackendNative *native)
priv->launcher = meta_launcher_new ();
priv->barrier_manager = meta_barrier_manager_native_new ();
priv->up_client = up_client_new ();
g_signal_connect (priv->up_client, "notify::lid-is-closed",
G_CALLBACK (lid_is_closed_changed_cb), NULL);
priv->cancellable = g_cancellable_new ();
g_bus_get (G_BUS_TYPE_SYSTEM,
priv->cancellable,
system_bus_gotten_cb,
native);
}
gboolean

View File

@@ -43,6 +43,9 @@ struct _MetaCursorRendererNativePrivate
{
gboolean has_hw_cursor;
MetaCursorReference *last_cursor;
guint animation_timeout_id;
int drm_fd;
struct gbm_device *gbm;
@@ -59,6 +62,9 @@ meta_cursor_renderer_native_finalize (GObject *object)
MetaCursorRendererNative *renderer = META_CURSOR_RENDERER_NATIVE (object);
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (renderer);
if (priv->animation_timeout_id)
g_source_remove (priv->animation_timeout_id);
if (priv->gbm)
gbm_device_destroy (priv->gbm);
@@ -147,12 +153,66 @@ should_have_hw_cursor (MetaCursorRenderer *renderer)
return FALSE;
}
static gboolean
meta_cursor_renderer_native_update_animation (MetaCursorRendererNative *native)
{
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
MetaCursorReference *cursor;
priv->animation_timeout_id = 0;
cursor = meta_cursor_renderer_get_cursor (META_CURSOR_RENDERER (native));
meta_cursor_reference_tick_frame (cursor);
meta_cursor_renderer_force_update (META_CURSOR_RENDERER (native));
meta_cursor_renderer_native_force_update (native);
return G_SOURCE_REMOVE;
}
static void
meta_cursor_renderer_native_trigger_frame (MetaCursorRendererNative *native)
{
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
MetaCursorReference *cursor;
gboolean cursor_change;
guint delay;
cursor = meta_cursor_renderer_get_cursor (META_CURSOR_RENDERER (native));
cursor_change = cursor != priv->last_cursor;
priv->last_cursor = cursor;
if (!cursor_change && priv->animation_timeout_id)
return;
if (priv->animation_timeout_id)
{
g_source_remove (priv->animation_timeout_id);
priv->animation_timeout_id = 0;
}
if (cursor && meta_cursor_reference_is_animated (cursor))
{
delay = meta_cursor_reference_get_current_frame_time (cursor);
if (delay == 0)
return;
priv->animation_timeout_id =
g_timeout_add (delay,
(GSourceFunc) meta_cursor_renderer_native_update_animation,
native);
g_source_set_name_by_id (priv->animation_timeout_id,
"[mutter] meta_cursor_renderer_native_update_animation");
}
}
static gboolean
meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer)
{
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
meta_cursor_renderer_native_trigger_frame (native);
priv->has_hw_cursor = should_have_hw_cursor (renderer);
update_hw_cursor (native, FALSE);
return priv->has_hw_cursor;

View File

@@ -169,10 +169,10 @@ meta_input_settings_native_set_scroll_method (MetaInputSettings *sett
scroll_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
break;
case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_EDGE_SCROLLING:
scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
scroll_method = LIBINPUT_CONFIG_SCROLL_EDGE;
break;
case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING:
scroll_method = LIBINPUT_CONFIG_SCROLL_EDGE;
scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
break;
default:
g_assert_not_reached ();

View File

@@ -43,6 +43,7 @@
#include "backends/meta-backend-private.h"
#include "meta-cursor-renderer-native.h"
#include "meta-idle-monitor-native.h"
struct _MetaLauncher
{
@@ -110,6 +111,7 @@ session_unpause (void)
clutter_actor_queue_redraw (stage);
meta_cursor_renderer_native_force_update (META_CURSOR_RENDERER_NATIVE (renderer));
meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ());
}
}
@@ -128,9 +130,8 @@ take_device (Login1Session *session_proxy,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
GVariant *fd_variant = NULL;
GUnixFDList *fd_list = NULL;
g_autoptr (GVariant) fd_variant = NULL;
g_autoptr (GUnixFDList) fd_list = NULL;
int fd = -1;
if (!login1_session_call_take_device_sync (session_proxy,
@@ -142,21 +143,14 @@ take_device (Login1Session *session_proxy,
&fd_list,
cancellable,
error))
goto out;
return FALSE;
fd = g_unix_fd_list_get (fd_list, g_variant_get_handle (fd_variant), error);
if (fd == -1)
goto out;
return FALSE;
*out_fd = fd;
ret = TRUE;
out:
if (fd_variant)
g_variant_unref (fd_variant);
if (fd_list)
g_object_unref (fd_list);
return ret;
return TRUE;
}
static gboolean
@@ -164,22 +158,16 @@ get_device_info_from_path (const char *path,
int *out_major,
int *out_minor)
{
gboolean ret = FALSE;
int r;
struct stat st;
r = stat (path, &st);
if (r < 0)
goto out;
if (!S_ISCHR (st.st_mode))
goto out;
if (r < 0 || !S_ISCHR (st.st_mode))
return FALSE;
*out_major = major (st.st_rdev);
*out_minor = minor (st.st_rdev);
ret = TRUE;
out:
return ret;
return TRUE;
}
static gboolean
@@ -187,22 +175,16 @@ get_device_info_from_fd (int fd,
int *out_major,
int *out_minor)
{
gboolean ret = FALSE;
int r;
struct stat st;
r = fstat (fd, &st);
if (r < 0)
goto out;
if (!S_ISCHR (st.st_mode))
goto out;
if (r < 0 || !S_ISCHR (st.st_mode))
return FALSE;
*out_major = major (st.st_rdev);
*out_minor = minor (st.st_rdev);
ret = TRUE;
out:
return ret;
return TRUE;
}
static int

View File

@@ -55,8 +55,19 @@ typedef struct {
uint32_t dpms_prop_id;
uint32_t edid_blob_id;
uint32_t tile_blob_id;
int suggested_x;
int suggested_y;
uint32_t hotplug_mode_update;
} MetaOutputKms;
typedef struct {
uint32_t underscan_prop_id;
uint32_t underscan_hborder_prop_id;
uint32_t underscan_vborder_prop_id;
} MetaCRTCKms;
struct _MetaMonitorManagerKms
{
MetaMonitorManager parent_instance;
@@ -104,7 +115,7 @@ make_output_name (drmModeConnector *connector)
static const char * const connector_type_names[] = {
"unknown", "VGA", "DVII", "DVID", "DVID", "Composite",
"SVIDEO", "LVDS", "Component", "9PinDIN", "DisplayPort",
"HDMIA", "HDMIB", "TV", "eDP"
"HDMIA", "HDMIB", "TV", "eDP", "Virtual", "DSI"
};
const char *connector_type_name;
@@ -137,6 +148,12 @@ meta_monitor_mode_destroy_notify (MetaMonitorMode *output)
g_slice_free (drmModeModeInfo, output->driver_private);
}
static void
meta_crtc_destroy_notify (MetaCRTC *crtc)
{
g_free (crtc->driver_private);
}
static gboolean
drm_mode_equal (gconstpointer one,
gconstpointer two)
@@ -181,24 +198,67 @@ drm_mode_hash (gconstpointer ptr)
}
static void
find_properties (MetaMonitorManagerKms *manager_kms,
MetaOutputKms *output_kms)
find_connector_properties (MetaMonitorManagerKms *manager_kms,
MetaOutputKms *output_kms)
{
drmModePropertyPtr prop;
int i;
output_kms->hotplug_mode_update = 0;
output_kms->suggested_x = -1;
output_kms->suggested_y = -1;
for (i = 0; i < output_kms->connector->count_props; i++)
{
prop = drmModeGetProperty (manager_kms->fd, output_kms->connector->props[i]);
drmModePropertyPtr prop = drmModeGetProperty (manager_kms->fd, output_kms->connector->props[i]);
if (!prop)
continue;
if ((prop->flags & DRM_MODE_PROP_ENUM) &&
strcmp(prop->name, "DPMS") == 0)
if ((prop->flags & DRM_MODE_PROP_ENUM) && strcmp (prop->name, "DPMS") == 0)
output_kms->dpms_prop_id = prop->prop_id;
else if ((prop->flags & DRM_MODE_PROP_BLOB) &&
strcmp (prop->name, "EDID") == 0)
else if ((prop->flags & DRM_MODE_PROP_BLOB) && strcmp (prop->name, "EDID") == 0)
output_kms->edid_blob_id = output_kms->connector->prop_values[i];
else if ((prop->flags & DRM_MODE_PROP_BLOB) &&
strcmp (prop->name, "TILE") == 0)
output_kms->tile_blob_id = output_kms->connector->prop_values[i];
else if ((prop->flags & DRM_MODE_PROP_RANGE) &&
strcmp (prop->name, "suggested X") == 0)
output_kms->suggested_x = output_kms->connector->prop_values[i];
else if ((prop->flags & DRM_MODE_PROP_RANGE) &&
strcmp (prop->name, "suggested Y") == 0)
output_kms->suggested_y = output_kms->connector->prop_values[i];
else if ((prop->flags & DRM_MODE_PROP_RANGE) &&
strcmp (prop->name, "hotplug_mode_update") == 0)
output_kms->hotplug_mode_update = output_kms->connector->prop_values[i];
drmModeFreeProperty (prop);
}
}
static void
find_crtc_properties (MetaMonitorManagerKms *manager_kms,
MetaCRTC *meta_crtc)
{
MetaCRTCKms *crtc_kms;
drmModeObjectPropertiesPtr props;
size_t i;
crtc_kms = meta_crtc->driver_private;
props = drmModeObjectGetProperties (manager_kms->fd, meta_crtc->crtc_id, DRM_MODE_OBJECT_CRTC);
if (!props)
return;
for (i = 0; i < props->count_props; i++)
{
drmModePropertyPtr prop = drmModeGetProperty (manager_kms->fd, props->props[i]);
if (!prop)
continue;
if ((prop->flags & DRM_MODE_PROP_ENUM) && strcmp (prop->name, "underscan") == 0)
crtc_kms->underscan_prop_id = prop->prop_id;
else if ((prop->flags & DRM_MODE_PROP_RANGE) && strcmp (prop->name, "underscan hborder") == 0)
crtc_kms->underscan_hborder_prop_id = prop->prop_id;
else if ((prop->flags & DRM_MODE_PROP_RANGE) && strcmp (prop->name, "underscan vborder") == 0)
crtc_kms->underscan_vborder_prop_id = prop->prop_id;
drmModeFreeProperty (prop);
}
@@ -233,6 +293,47 @@ read_output_edid (MetaMonitorManagerKms *manager_kms,
}
}
static gboolean
output_get_tile_info (MetaMonitorManagerKms *manager_kms,
MetaOutput *output)
{
MetaOutputKms *output_kms = output->driver_private;
drmModePropertyBlobPtr tile_blob = NULL;
int ret;
if (output_kms->tile_blob_id == 0)
return FALSE;
tile_blob = drmModeGetPropertyBlob (manager_kms->fd, output_kms->tile_blob_id);
if (!tile_blob)
{
meta_warning ("Failed to read TILE of output %s: %s\n", output->name, strerror(errno));
return FALSE;
}
if (tile_blob->length > 0)
{
ret = sscanf ((char *)tile_blob->data, "%d:%d:%d:%d:%d:%d:%d:%d",
&output->tile_info.group_id,
&output->tile_info.flags,
&output->tile_info.max_h_tiles,
&output->tile_info.max_v_tiles,
&output->tile_info.loc_h_tile,
&output->tile_info.loc_v_tile,
&output->tile_info.tile_w,
&output->tile_info.tile_h);
if (ret != 8)
return FALSE;
return TRUE;
}
else
{
drmModeFreePropertyBlob (tile_blob);
return FALSE;
}
}
static MetaMonitorMode *
find_meta_mode (MetaMonitorManager *manager,
const drmModeModeInfo *drm_mode)
@@ -442,6 +543,10 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
height = MAX (height, meta_crtc->rect.y + meta_crtc->rect.height);
}
meta_crtc->driver_private = g_new0 (MetaCRTCKms, 1);
meta_crtc->driver_notify = (GDestroyNotify) meta_crtc_destroy_notify;
find_crtc_properties (manager_kms, meta_crtc);
drmModeFreeCrtc (crtc);
}
@@ -472,8 +577,6 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_output->name = make_output_name (connector);
meta_output->width_mm = connector->mmWidth;
meta_output->height_mm = connector->mmHeight;
meta_output->suggested_x = -1;
meta_output->suggested_y = -1;
switch (connector->subpixel)
{
@@ -498,11 +601,17 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
break;
}
meta_output->preferred_mode = NULL;
meta_output->n_modes = connector->count_modes;
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
for (j = 0; j < meta_output->n_modes; j++)
for (j = 0; j < meta_output->n_modes; j++) {
meta_output->modes[j] = find_meta_mode (manager, &connector->modes[j]);
meta_output->preferred_mode = meta_output->modes[0];
if (connector->modes[j].type & DRM_MODE_TYPE_PREFERRED)
meta_output->preferred_mode = meta_output->modes[j];
}
if (!meta_output->preferred_mode)
meta_output->preferred_mode = meta_output->modes[0];
output_kms->connector = connector;
output_kms->n_encoders = connector->count_encoders;
@@ -567,8 +676,11 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_output->is_presentation = FALSE;
}
find_properties (manager_kms, output_kms);
find_connector_properties (manager_kms, output_kms);
meta_output->suggested_x = output_kms->suggested_x;
meta_output->suggested_y = output_kms->suggested_y;
meta_output->hotplug_mode_update = output_kms->hotplug_mode_update;
edid = read_output_edid (manager_kms, meta_output);
meta_output_parse_edid (meta_output, edid);
g_bytes_unref (edid);
@@ -578,6 +690,8 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_output->scale = get_output_scale (manager, meta_output);
output_get_tile_info (manager_kms, meta_output);
/* FIXME: backlight is a very driver specific thing unfortunately,
every DDX does its own thing, and the dumb KMS API does not include it.
@@ -723,8 +837,9 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
if (output_kms->dpms_prop_id != 0)
{
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->winsys_id,
output_kms->dpms_prop_id, state);
int ok = drmModeObjectSetProperty (manager_kms->fd, meta_output->winsys_id,
DRM_MODE_OBJECT_CONNECTOR,
output_kms->dpms_prop_id, state);
if (ok < 0)
meta_warning ("Failed to set power save mode for output %s: %s\n",
@@ -748,6 +863,48 @@ crtc_free (CoglKmsCrtc *crtc)
g_slice_free (CoglKmsCrtc, crtc);
}
static void
set_underscan (MetaMonitorManagerKms *manager_kms,
MetaOutput *output)
{
if (!output->crtc)
return;
MetaCRTC *crtc = output->crtc;
MetaCRTCKms *crtc_kms = crtc->driver_private;
if (!crtc_kms->underscan_prop_id)
return;
if (output->is_underscanning)
{
drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id,
DRM_MODE_OBJECT_CRTC,
crtc_kms->underscan_prop_id, (uint64_t) 1);
if (crtc_kms->underscan_hborder_prop_id)
{
uint64_t value = crtc->current_mode->width * 0.05;
drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id,
DRM_MODE_OBJECT_CRTC,
crtc_kms->underscan_hborder_prop_id, value);
}
if (crtc_kms->underscan_vborder_prop_id)
{
uint64_t value = crtc->current_mode->height * 0.05;
drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id,
DRM_MODE_OBJECT_CRTC,
crtc_kms->underscan_vborder_prop_id, value);
}
}
else
{
drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id,
DRM_MODE_OBJECT_CRTC,
crtc_kms->underscan_prop_id, (uint64_t) 0);
}
}
static void
meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
MetaCRTCInfo **crtcs,
@@ -755,6 +912,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
MetaOutputInfo **outputs,
unsigned int n_outputs)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
ClutterBackend *backend;
CoglContext *cogl_context;
CoglDisplay *cogl_display;
@@ -900,6 +1058,9 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
output->is_primary = output_info->is_primary;
output->is_presentation = output_info->is_presentation;
output->is_underscanning = output_info->is_underscanning;
set_underscan (manager_kms, output);
}
/* Disable outputs not mentioned in the list */

View File

@@ -46,6 +46,14 @@
#include "display-private.h"
#include "compositor/compositor-private.h"
typedef enum {
/* We're a traditional CM running under the host. */
META_BACKEND_X11_MODE_COMPOSITOR,
/* We're a nested X11 client */
META_BACKEND_X11_MODE_NESTED,
} MetaBackendX11Mode;
struct _MetaBackendX11Private
{
/* The host X11 display */
@@ -53,6 +61,8 @@ struct _MetaBackendX11Private
xcb_connection_t *xcb;
GSource *source;
MetaBackendX11Mode mode;
int xsync_event_base;
int xsync_error_base;
@@ -102,7 +112,7 @@ translate_device_event (MetaBackendX11 *x11,
/* This codepath should only ever trigger as an X11 compositor,
* and never under nested, as under nested all backend events
* should be reported with respect to the stage window. */
g_assert (!meta_is_wayland_compositor ());
g_assert (priv->mode == META_BACKEND_X11_MODE_COMPOSITOR);
device_event->event = stage_window;
@@ -133,6 +143,8 @@ static void
translate_crossing_event (MetaBackendX11 *x11,
XIEnterEvent *enter_event)
{
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
/* Throw out weird events generated by grabs. */
if (enter_event->mode == XINotifyGrab ||
enter_event->mode == XINotifyUngrab)
@@ -141,7 +153,15 @@ translate_crossing_event (MetaBackendX11 *x11,
return;
}
enter_event->event = meta_backend_x11_get_xwindow (x11);
Window stage_window = meta_backend_x11_get_xwindow (x11);
if (enter_event->event != stage_window)
{
/* See above for the rationale for this... */
g_assert (priv->mode == META_BACKEND_X11_MODE_COMPOSITOR);
enter_event->event = meta_backend_x11_get_xwindow (x11);
enter_event->event_x = enter_event->root_x;
enter_event->event_y = enter_event->root_y;
}
}
static void
@@ -430,7 +450,9 @@ meta_backend_x11_post_init (MetaBackend *backend)
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
}
take_touch_grab (backend);
/* We only take the passive touch grab if we are a X11 compositor */
if (priv->mode == META_BACKEND_X11_MODE_COMPOSITOR)
take_touch_grab (backend);
priv->xcb = XGetXCBConnection (priv->xdisplay);
if (!xkb_x11_setup_xkb_extension (priv->xcb,
@@ -461,13 +483,18 @@ meta_backend_x11_create_idle_monitor (MetaBackend *backend,
static MetaMonitorManager *
meta_backend_x11_create_monitor_manager (MetaBackend *backend)
{
/* If we're a Wayland compositor using the X11 backend,
* we're a nested configuration, so return the dummy
* monitor setup. */
if (meta_is_wayland_compositor ())
return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL);
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, NULL);
switch (priv->mode)
{
case META_BACKEND_X11_MODE_COMPOSITOR:
return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, NULL);
case META_BACKEND_X11_MODE_NESTED:
return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL);
default:
g_assert_not_reached ();
}
}
static MetaCursorRenderer *
@@ -721,7 +748,10 @@ static void
meta_backend_x11_update_screen_size (MetaBackend *backend,
int width, int height)
{
if (meta_is_wayland_compositor ())
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
if (priv->mode == META_BACKEND_X11_MODE_NESTED)
{
/* For a nested wayland session, we want to go through Clutter to update the
* toplevel window size, rather than doing it directly.
@@ -755,9 +785,21 @@ meta_backend_x11_select_stage_events (MetaBackend *backend)
XISetMask (mask.mask, XI_FocusIn);
XISetMask (mask.mask, XI_FocusOut);
XISetMask (mask.mask, XI_Motion);
XIClearMask (mask.mask, XI_TouchBegin);
XIClearMask (mask.mask, XI_TouchEnd);
XIClearMask (mask.mask, XI_TouchUpdate);
if (priv->mode == META_BACKEND_X11_MODE_NESTED)
{
/* When we're an X11 compositor, we can't take these events or else
* replaying events from our passive root window grab will cause
* them to come back to us.
*
* When we're a nested application, we want to behave like any other
* application, so select these events like normal apps do.
*/
XISetMask (mask.mask, XI_TouchBegin);
XISetMask (mask.mask, XI_TouchEnd);
XISetMask (mask.mask, XI_TouchUpdate);
}
XISelectEvents (priv->xdisplay, xwin, &mask, 1);
}
@@ -783,8 +825,15 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
static void
meta_backend_x11_init (MetaBackendX11 *x11)
{
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
/* We do X11 event retrieval ourselves */
clutter_x11_disable_event_retrieval ();
if (meta_is_wayland_compositor ())
priv->mode = META_BACKEND_X11_MODE_NESTED;
else
priv->mode = META_BACKEND_X11_MODE_COMPOSITOR;
}
Display *

View File

@@ -26,6 +26,7 @@
#include "meta-backend-x11.h"
#include "meta-input-settings-x11.h"
#include <string.h>
#include <gdk/gdkx.h>
#include <X11/Xatom.h>
#include <X11/extensions/XInput2.h>
@@ -35,6 +36,41 @@
G_DEFINE_TYPE (MetaInputSettingsX11, meta_input_settings_x11, META_TYPE_INPUT_SETTINGS)
static void *
get_property (ClutterInputDevice *device,
const gchar *property,
Atom type,
int format,
gulong nitems)
{
MetaBackend *backend = meta_get_backend ();
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
gulong nitems_ret, bytes_after_ret;
int rc, device_id, format_ret;
Atom property_atom, type_ret;
guchar *data_ret = NULL;
property_atom = XInternAtom (xdisplay, property, True);
if (!property_atom)
return NULL;
device_id = clutter_input_device_get_device_id (device);
rc = XIGetProperty (xdisplay, device_id, property_atom,
0, 10, False, type, &type_ret, &format_ret,
&nitems_ret, &bytes_after_ret, &data_ret);
if (rc == Success && type_ret == type && format_ret == format && nitems_ret >= nitems)
{
if (nitems_ret > nitems)
g_warning ("Property '%s' for device '%s' returned %lu items, expected %lu",
property, clutter_input_device_get_device_name (device), nitems_ret, nitems);
return data_ret;
}
meta_XFree (data_ret);
return NULL;
}
static void
change_property (ClutterInputDevice *device,
const gchar *property,
@@ -45,23 +81,23 @@ change_property (ClutterInputDevice *device,
{
MetaBackend *backend = meta_get_backend ();
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
gulong nitems_ret, bytes_after_ret;
int rc, device_id, format_ret;
Atom property_atom, type_ret;
int device_id;
Atom property_atom;
guchar *data_ret;
property_atom = XInternAtom (xdisplay, property, False);
property_atom = XInternAtom (xdisplay, property, True);
if (!property_atom)
return;
device_id = clutter_input_device_get_device_id (device);
rc = XIGetProperty (xdisplay, device_id, property_atom,
0, 0, False, type, &type_ret, &format_ret,
&nitems_ret, &bytes_after_ret, &data_ret);
data_ret = get_property (device, property, type, format, nitems);
if (!data_ret)
return;
XIChangeProperty (xdisplay, device_id, property_atom, type,
format, XIPropModeReplace, data, nitems);
meta_XFree (data_ret);
if (rc == Success && type_ret == type && format_ret == format)
XIChangeProperty (xdisplay, device_id, property_atom, type,
format, XIPropModeReplace, data, nitems);
}
static void
@@ -70,6 +106,12 @@ meta_input_settings_x11_set_send_events (MetaInputSettings *settings,
GDesktopDeviceSendEvents mode)
{
guchar values[2] = { 0 }; /* disabled, disabled-on-external-mouse */
guchar *available;
available = get_property (device, "libinput Send Events Modes Available",
XA_INTEGER, 8, 2);
if (!available)
return;
switch (mode)
{
@@ -83,8 +125,14 @@ meta_input_settings_x11_set_send_events (MetaInputSettings *settings,
break;
}
change_property (device, "libinput Send Events Mode Enabled",
XA_INTEGER, 8, &values, 2);
if ((values[0] && !available[0]) || (values[1] && !available[1]))
g_warning ("Device '%s' does not support sendevents mode %d\n",
clutter_input_device_get_device_name (device), mode);
else
change_property (device, "libinput Send Events Mode Enabled",
XA_INTEGER, 8, &values, 2);
meta_XFree (available);
}
static void
@@ -156,6 +204,12 @@ meta_input_settings_x11_set_scroll_method (MetaInputSettings *setting
GDesktopTouchpadScrollMethod mode)
{
guchar values[3] = { 0 }; /* 2fg, edge, button. The last value is unused */
guchar *available;
available = get_property (device, "libinput Scroll Methods Available",
XA_INTEGER, 8, 3);
if (!available)
return;
switch (mode)
{
@@ -171,8 +225,14 @@ meta_input_settings_x11_set_scroll_method (MetaInputSettings *setting
g_assert_not_reached ();
}
change_property (device, "libinput Scroll Method Enabled",
XA_INTEGER, 8, &values, 3);
if ((values[0] && !available[0]) || (values[1] && !available[1]))
g_warning ("Device '%s' does not support scroll mode %d\n",
clutter_input_device_get_device_name (device), mode);
else
change_property (device, "libinput Scroll Method Enabled",
XA_INTEGER, 8, &values, 3);
meta_XFree (available);
}
static void
@@ -180,7 +240,7 @@ meta_input_settings_x11_set_scroll_button (MetaInputSettings *settings,
ClutterInputDevice *device,
guint button)
{
change_property (device, "libinput Scroll Method Enabled",
change_property (device, "libinput Button Scrolling Button",
XA_INTEGER, 32, &button, 1);
}
@@ -190,16 +250,28 @@ meta_input_settings_x11_set_click_method (MetaInputSettings *settings,
GDesktopTouchpadClickMethod mode)
{
guchar values[2] = { 0 }; /* buttonareas, clickfinger */
guchar *defaults, *available;
available = get_property (device, "libinput Click Methods Available",
XA_INTEGER, 8, 2);
if (!available)
return;
switch (mode)
{
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_DEFAULT:
defaults = get_property (device, "libinput Click Method Enabled Default",
XA_INTEGER, 8, 2);
if (!defaults)
break;
memcpy (values, defaults, 2);
meta_XFree (defaults);
break;
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_NONE:
break;
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_AREAS:
values[0] = 1;
break;
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_DEFAULT:
/* XXX: We can't be much smarter yet, x11 doesn't expose default settings */
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_FINGERS:
values[1] = 1;
break;
@@ -208,8 +280,14 @@ meta_input_settings_x11_set_click_method (MetaInputSettings *settings,
return;
}
change_property (device, "libinput Click Method Enabled",
XA_INTEGER, 8, &values, 2);
if ((values[0] && !available[0]) || (values[1] && !available[1]))
g_warning ("Device '%s' does not support click method %d\n",
clutter_input_device_get_device_name (device), mode);
else
change_property (device, "libinput Click Method Enabled",
XA_INTEGER, 8, &values, 2);
meta_XFree(available);
}
static void

View File

@@ -58,6 +58,7 @@ struct _MetaMonitorManagerXrandr
XRRScreenResources *resources;
int rr_event_base;
int rr_error_base;
gboolean has_randr15;
};
struct _MetaMonitorManagerXrandrClass
@@ -194,11 +195,10 @@ static gboolean
output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output, const char *propname)
{
gboolean value = FALSE;
Atom atom, actual_type;
int actual_format;
unsigned long nitems, bytes_after;
unsigned char *buffer;
g_autofree unsigned char *buffer = NULL;
atom = XInternAtom (manager_xrandr->xdisplay, propname, False);
XRRGetOutputProperty (manager_xrandr->xdisplay,
@@ -209,13 +209,9 @@ output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
&nitems, &bytes_after, &buffer);
if (actual_type != XA_CARDINAL || actual_format != 32 || nitems < 1)
goto out;
return FALSE;
value = ((int*)buffer)[0];
out:
XFree (buffer);
return value;
return ((int*)buffer)[0];
}
static gboolean
@@ -225,6 +221,76 @@ output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
return output_get_boolean_property (manager_xrandr, output, "_MUTTER_PRESENTATION_OUTPUT");
}
static gboolean
output_get_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
{
Atom atom, actual_type;
int actual_format;
unsigned long nitems, bytes_after;
g_autofree unsigned char *buffer = NULL;
g_autofree char *str = NULL;
atom = XInternAtom (manager_xrandr->xdisplay, "underscan", False);
XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
atom,
0, G_MAXLONG, False, False, XA_ATOM,
&actual_type, &actual_format,
&nitems, &bytes_after, &buffer);
if (actual_type != XA_ATOM || actual_format != 32 || nitems < 1)
return FALSE;
str = XGetAtomName (manager_xrandr->xdisplay, *(Atom *)buffer);
return (strcmp (str, "on") == 0);
}
static gboolean
output_get_supports_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
{
Atom atom, actual_type;
int actual_format, i;
unsigned long nitems, bytes_after;
g_autofree unsigned char *buffer = NULL;
XRRPropertyInfo *property_info;
Atom *values;
gboolean supports_underscanning = FALSE;
atom = XInternAtom (manager_xrandr->xdisplay, "underscan", False);
XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
atom,
0, G_MAXLONG, False, False, XA_ATOM,
&actual_type, &actual_format,
&nitems, &bytes_after, &buffer);
if (actual_type != XA_ATOM || actual_format != 32 || nitems < 1)
return FALSE;
property_info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
(XID) output->winsys_id,
atom);
values = (Atom *) property_info->values;
for (i = 0; i < property_info->num_values; i++)
{
/* The output supports underscanning if "on" is a valid value
* for the underscan property.
*/
char *name = XGetAtomName (manager_xrandr->xdisplay, values[i]);
if (strcmp (name, "on") == 0)
supports_underscanning = TRUE;
XFree (name);
}
XFree (property_info);
return supports_underscanning;
}
static int
normalize_backlight (MetaOutput *output,
int hw_value)
@@ -241,7 +307,7 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
Atom atom, actual_type;
int actual_format;
unsigned long nitems, bytes_after;
unsigned char *buffer;
g_autofree unsigned char *buffer = NULL;
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
XRRGetOutputProperty (manager_xrandr->xdisplay,
@@ -252,12 +318,9 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
&nitems, &bytes_after, &buffer);
if (actual_type != XA_INTEGER || actual_format != 32 || nitems < 1)
goto out;
return FALSE;
value = ((int*)buffer)[0];
out:
XFree (buffer);
if (value > 0)
return normalize_backlight (output, value);
else
@@ -270,7 +333,7 @@ output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
{
Atom atom;
xcb_connection_t *xcb_conn;
xcb_randr_query_output_property_reply_t *reply;
g_autofree xcb_randr_query_output_property_reply_t *reply;
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
@@ -288,15 +351,12 @@ output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
if (!reply->range || reply->length != 2)
{
meta_verbose ("backlight %s was not range\n", output->name);
goto out;
return;
}
int32_t *values = xcb_randr_query_output_property_valid_values (reply);
output->backlight_min = values[0];
output->backlight_max = values[1];
out:
free (reply);
}
static int
@@ -376,6 +436,42 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
return NULL;
}
static void
output_get_tile_info (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
{
Atom tile_atom;
unsigned char *prop;
unsigned long nitems, bytes_after;
int actual_format;
Atom actual_type;
if (manager_xrandr->has_randr15 == FALSE)
return;
tile_atom = XInternAtom (manager_xrandr->xdisplay, "TILE", FALSE);
XRRGetOutputProperty (manager_xrandr->xdisplay,
output->winsys_id,
tile_atom, 0, 100, False,
False, AnyPropertyType,
&actual_type, &actual_format,
&nitems, &bytes_after, &prop);
if (actual_type == XA_INTEGER && actual_format == 32 && nitems == 8)
{
long *values = (long *)prop;
output->tile_info.group_id = values[0];
output->tile_info.flags = values[1];
output->tile_info.max_h_tiles = values[2];
output->tile_info.max_v_tiles = values[3];
output->tile_info.loc_h_tile = values[4];
output->tile_info.loc_v_tile = values[5];
output->tile_info.tile_w = values[6];
output->tile_info.tile_h = values[7];
}
XFree (prop);
}
static gboolean
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
@@ -447,11 +543,10 @@ static MetaConnectorType
output_get_connector_type_from_prop (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
{
MetaConnectorType ret = META_CONNECTOR_TYPE_Unknown;
Atom atom, actual_type, connector_type_atom;
int actual_format;
unsigned long nitems, bytes_after;
unsigned char *buffer;
g_autofree unsigned char *buffer = NULL;
atom = XInternAtom (manager_xrandr->xdisplay, "ConnectorType", False);
XRRGetOutputProperty (manager_xrandr->xdisplay,
@@ -462,14 +557,10 @@ output_get_connector_type_from_prop (MetaMonitorManagerXrandr *manager_xrandr,
&nitems, &bytes_after, &buffer);
if (actual_type != XA_ATOM || actual_format != 32 || nitems < 1)
goto out;
return META_CONNECTOR_TYPE_Unknown;
connector_type_atom = ((Atom *) buffer)[0];
ret = connector_type_from_atom (manager_xrandr, connector_type_atom);
out:
meta_XFree (buffer);
return ret;
return connector_type_from_atom (manager_xrandr, connector_type_atom);
}
static MetaConnectorType
@@ -506,7 +597,7 @@ output_get_connector_type_from_name (MetaMonitorManagerXrandr *manager_xrandr,
if (g_str_has_prefix (name, "Virtual"))
return META_CONNECTOR_TYPE_VIRTUAL;
if (g_str_has_prefix (name, "Composite"))
return META_CONNECTOR_TYPE_VGA;
return META_CONNECTOR_TYPE_Composite;
if (g_str_has_prefix (name, "S-video"))
return META_CONNECTOR_TYPE_SVIDEO;
if (g_str_has_prefix (name, "TV"))
@@ -704,6 +795,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_output->suggested_y = output_get_suggested_y (manager_xrandr, meta_output);
meta_output->connector_type = output_get_connector_type (manager_xrandr, meta_output);
output_get_tile_info (manager_xrandr, meta_output);
meta_output->n_modes = output->nmode;
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
for (j = 0; j < meta_output->n_modes; j++)
@@ -756,6 +848,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_output->is_primary = ((XID)meta_output->winsys_id == primary_output);
meta_output->is_presentation = output_get_presentation_xrandr (manager_xrandr, meta_output);
meta_output->is_underscanning = output_get_underscanning_xrandr (manager_xrandr, meta_output);
meta_output->supports_underscanning = output_get_supports_underscanning_xrandr (manager_xrandr, meta_output);
output_get_backlight_limits_xrandr (manager_xrandr, meta_output);
if (!(meta_output->backlight_min == 0 && meta_output->backlight_max == 0))
@@ -869,11 +963,58 @@ output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
int value = presentation;
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
atom,
XA_CARDINAL, 32, PropModeReplace,
(unsigned char*) &value, 1);
xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
(XID)output->winsys_id,
atom, XCB_ATOM_CARDINAL, 32,
XCB_PROP_MODE_REPLACE,
1, &value);
}
static void
output_set_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output,
gboolean underscanning)
{
Atom prop, valueatom;
const char *value;
prop = XInternAtom (manager_xrandr->xdisplay, "underscan", False);
value = underscanning ? "on" : "off";
valueatom = XInternAtom (manager_xrandr->xdisplay, value, False);
xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
(XID)output->winsys_id,
prop, XCB_ATOM_ATOM, 32,
XCB_PROP_MODE_REPLACE,
1, &valueatom);
/* Configure the border at the same time. Currently, we use a
* 5% of the width/height of the mode. In the future, we should
* make the border configurable. */
if (underscanning)
{
uint32_t border_value;
prop = XInternAtom (manager_xrandr->xdisplay, "underscan hborder", False);
border_value = output->crtc->current_mode->width * 0.05;
xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
(XID)output->winsys_id,
prop, XCB_ATOM_INTEGER, 32,
XCB_PROP_MODE_REPLACE,
1, &border_value);
prop = XInternAtom (manager_xrandr->xdisplay, "underscan vborder", False);
border_value = output->crtc->current_mode->height * 0.05;
xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
(XID)output->winsys_id,
prop, XCB_ATOM_INTEGER, 32,
XCB_PROP_MODE_REPLACE,
1, &border_value);
}
}
static void
@@ -992,7 +1133,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
if (crtc_info->mode != NULL)
{
MetaMonitorMode *mode;
XID *outputs;
g_autofree XID *outputs = NULL;
unsigned int j, n_outputs;
int width, height;
Status ok;
@@ -1029,7 +1170,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
(unsigned)(crtc->crtc_id), (unsigned)(mode->mode_id),
mode->width, mode->height, (float)mode->refresh_rate,
crtc_info->x, crtc_info->y, crtc_info->transform);
goto next;
continue;
}
if (meta_monitor_transform_is_rotated (crtc_info->transform))
@@ -1049,9 +1190,6 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
crtc->rect.height = height;
crtc->current_mode = mode;
crtc->transform = crtc_info->transform;
next:
g_free (outputs);
}
}
@@ -1071,8 +1209,14 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
output_info->output,
output_info->is_presentation);
if (output_get_supports_underscanning_xrandr (manager_xrandr, output_info->output))
output_set_underscanning_xrandr (manager_xrandr,
output_info->output,
output_info->is_underscanning);
output->is_primary = output_info->is_primary;
output->is_presentation = output_info->is_presentation;
output->is_underscanning = output_info->is_underscanning;
}
/* Disable outputs not mentioned in the list */
@@ -1106,11 +1250,12 @@ meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
hw_value = round ((double)value / 100.0 * output->backlight_max + output->backlight_min);
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
atom,
XA_INTEGER, 32, PropModeReplace,
(unsigned char *) &hw_value, 1);
xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
(XID)output->winsys_id,
atom, XCB_ATOM_INTEGER, 32,
XCB_PROP_MODE_REPLACE,
1, &hw_value);
/* We're not selecting for property notifies, so update the value immediately */
output->backlight = normalize_backlight (output, hw_value);
@@ -1158,6 +1303,88 @@ meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager,
XRRFreeGamma (gamma);
}
#ifdef HAVE_XRANDR15
static void
meta_monitor_manager_xrandr_add_monitor(MetaMonitorManager *manager,
MetaMonitorInfo *monitor)
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
XRRMonitorInfo *m;
int o;
Atom name;
char name_buf[40];
if (manager_xrandr->has_randr15 == FALSE)
return;
if (monitor->n_outputs <= 1)
return;
if (monitor->outputs[0]->product)
snprintf (name_buf, 40, "%s-%d", monitor->outputs[0]->product, monitor->outputs[0]->tile_info.group_id);
else
snprintf (name_buf, 40, "Tiled-%d", monitor->outputs[0]->tile_info.group_id);
name = XInternAtom (manager_xrandr->xdisplay, name_buf, False);
monitor->monitor_winsys_xid = name;
m = XRRAllocateMonitor (manager_xrandr->xdisplay, monitor->n_outputs);
if (!m)
return;
m->name = name;
m->primary = monitor->is_primary;
m->automatic = True;
for (o = 0; o < monitor->n_outputs; o++) {
MetaOutput *output = monitor->outputs[o];
m->outputs[o] = output->winsys_id;
}
XRRSetMonitor (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay),
m);
XRRFreeMonitors (m);
}
static void
meta_monitor_manager_xrandr_delete_monitor(MetaMonitorManager *manager,
int monitor_winsys_xid)
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
if (manager_xrandr->has_randr15 == FALSE)
return;
XRRDeleteMonitor (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay),
monitor_winsys_xid);
}
static void
meta_monitor_manager_xrandr_init_monitors(MetaMonitorManagerXrandr *manager_xrandr)
{
XRRMonitorInfo *m;
int n, i;
if (manager_xrandr->has_randr15 == FALSE)
return;
/* delete any tiled monitors setup, as mutter will want to recreate
things in its image */
m = XRRGetMonitors (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay),
FALSE, &n);
if (n == -1)
return;
for (i = 0; i < n; i++)
{
if (m[i].noutput > 1)
XRRDeleteMonitor (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay),
m[i].name);
}
XRRFreeMonitors (m);
}
#endif
static void
meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
{
@@ -1173,6 +1400,7 @@ meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
}
else
{
int major_version, minor_version;
/* We only use ScreenChangeNotify, but GDK uses the others,
and we don't want to step on its toes */
XRRSelectInput (manager_xrandr->xdisplay,
@@ -1180,6 +1408,17 @@ meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
RRScreenChangeNotifyMask
| RRCrtcChangeNotifyMask
| RROutputPropertyNotifyMask);
manager_xrandr->has_randr15 = FALSE;
XRRQueryVersion (manager_xrandr->xdisplay, &major_version,
&minor_version);
#ifdef HAVE_XRANDR15
if (major_version > 1 ||
(major_version == 1 &&
minor_version >= 5))
manager_xrandr->has_randr15 = TRUE;
meta_monitor_manager_xrandr_init_monitors (manager_xrandr);
#endif
}
}
@@ -1210,6 +1449,10 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma;
manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma;
#ifdef HAVE_XRANDR15
manager_class->add_monitor = meta_monitor_manager_xrandr_add_monitor;
manager_class->delete_monitor = meta_monitor_manager_xrandr_delete_monitor;
#endif
}
gboolean

View File

@@ -37,11 +37,6 @@
* compositor needs to delay hiding the windows until the switch
* workspace animation completes.
*
* meta_compositor_maximize_window() and meta_compositor_unmaximize_window()
* are transitions within the visible state. The window is resized __before__
* the call, so it may be necessary to readjust the display based on the
* old_rect to start the animation.
*
* # Containers #
*
* There's two containers in the stage that are used to place window actors, here
@@ -769,23 +764,14 @@ meta_compositor_hide_window (MetaCompositor *compositor,
}
void
meta_compositor_maximize_window (MetaCompositor *compositor,
MetaWindow *window,
MetaRectangle *old_rect,
MetaRectangle *new_rect)
meta_compositor_size_change_window (MetaCompositor *compositor,
MetaWindow *window,
MetaSizeChange which_change,
MetaRectangle *old_frame_rect,
MetaRectangle *old_buffer_rect)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
meta_window_actor_maximize (window_actor, old_rect, new_rect);
}
void
meta_compositor_unmaximize_window (MetaCompositor *compositor,
MetaWindow *window,
MetaRectangle *old_rect,
MetaRectangle *new_rect)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
meta_window_actor_unmaximize (window_actor, old_rect, new_rect);
meta_window_actor_size_change (window_actor, META_SIZE_CHANGE_MAXIMIZE, old_frame_rect, old_buffer_rect);
}
void

View File

@@ -71,6 +71,8 @@ enum
G_DEFINE_TYPE (MetaBackground, meta_background, G_TYPE_OBJECT)
static GSList *all_backgrounds = NULL;
static void
free_fbos (MetaBackground *self)
{
@@ -305,6 +307,8 @@ meta_background_dispose (GObject *object)
static void
meta_background_finalize (GObject *object)
{
all_backgrounds = g_slist_remove (all_backgrounds, object);
G_OBJECT_CLASS (meta_background_parent_class)->finalize (object);
}
@@ -347,6 +351,7 @@ meta_background_init (MetaBackground *self)
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
META_TYPE_BACKGROUND,
MetaBackgroundPrivate);
all_backgrounds = g_slist_prepend (all_backgrounds, self);
}
static void
@@ -913,3 +918,12 @@ meta_background_set_blend (MetaBackground *self,
free_wallpaper_texture (self);
mark_changed (self);
}
void
meta_background_refresh_all (void)
{
GSList *l;
for (l = all_backgrounds; l; l = l->next)
mark_changed (l->data);
}

View File

@@ -187,7 +187,7 @@ meta_feedback_actor_set_anchor (MetaFeedbackActor *self,
if (priv->anchor_x == anchor_x && priv->anchor_y == anchor_y)
return;
if (priv->anchor_x != anchor_y)
if (priv->anchor_x != anchor_x)
{
priv->anchor_x = anchor_x;
g_object_notify (G_OBJECT (self), "anchor-x");

View File

@@ -149,7 +149,7 @@ meta_plugin_manager_kill_switch_workspace (MetaPluginManager *plugin_mgr)
gboolean
meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
MetaWindowActor *actor,
unsigned long event)
MetaPluginEffect event)
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
@@ -196,67 +196,32 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
}
break;
default:
g_warning ("Incorrect handler called for event %lu", event);
g_warning ("Incorrect handler called for event %d", event);
}
return retval;
}
/*
* The public method that the compositor hooks into for maximize and unmaximize
* events.
*
* Returns TRUE if the plugin handled the event type (i.e.,
* if the return value is FALSE, there will be no subsequent call to the
* manager completed() callback, and the compositor must ensure that any
* appropriate post-effect cleanup is carried out.
*/
gboolean
meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
MetaWindowActor *actor,
unsigned long event,
gint target_x,
gint target_y,
gint target_width,
gint target_height)
meta_plugin_manager_event_size_change (MetaPluginManager *plugin_mgr,
MetaWindowActor *actor,
MetaSizeChange which_change,
MetaRectangle *old_frame_rect,
MetaRectangle *old_buffer_rect)
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
MetaDisplay *display = plugin_mgr->compositor->display;
gboolean retval = FALSE;
if (display->display_opening)
return FALSE;
switch (event)
{
case META_PLUGIN_MAXIMIZE:
if (klass->maximize)
{
retval = TRUE;
meta_plugin_manager_kill_window_effects (plugin_mgr,
actor);
klass->maximize (plugin, actor,
target_x, target_y,
target_width, target_height);
}
break;
case META_PLUGIN_UNMAXIMIZE:
if (klass->unmaximize)
{
retval = TRUE;
meta_plugin_manager_kill_window_effects (plugin_mgr,
actor);
klass->unmaximize (plugin, actor,
target_x, target_y,
target_width, target_height);
}
break;
default:
g_warning ("Incorrect handler called for event %lu", event);
}
if (!klass->size_change)
return FALSE;
return retval;
meta_plugin_manager_kill_window_effects (plugin_mgr, actor);
klass->size_change (plugin, actor, which_change, old_frame_rect, old_buffer_rect);
return TRUE;
}
/*

View File

@@ -24,20 +24,17 @@
#include <meta/types.h>
#include <meta/screen.h>
#define META_PLUGIN_FROM_MANAGER_
#include <meta/meta-plugin.h>
#undef META_PLUGIN_FROM_MANAGER_
#define META_PLUGIN_MINIMIZE (1<<0)
#define META_PLUGIN_MAXIMIZE (1<<1)
#define META_PLUGIN_UNMAXIMIZE (1<<2)
#define META_PLUGIN_MAP (1<<3)
#define META_PLUGIN_DESTROY (1<<4)
#define META_PLUGIN_SWITCH_WORKSPACE (1<<5)
#define META_PLUGIN_UNMINIMIZE (1<<6)
#define META_PLUGIN_ALL_EFFECTS (~0)
typedef enum {
META_PLUGIN_NONE,
META_PLUGIN_MINIMIZE,
META_PLUGIN_MAP,
META_PLUGIN_DESTROY,
META_PLUGIN_SWITCH_WORKSPACE,
META_PLUGIN_UNMINIMIZE,
META_PLUGIN_SIZE_CHANGE,
} MetaPluginEffect;
/**
* MetaPluginManager: (skip)
@@ -51,15 +48,13 @@ void meta_plugin_manager_load (const gchar *plugin_name);
gboolean meta_plugin_manager_event_simple (MetaPluginManager *mgr,
MetaWindowActor *actor,
unsigned long event);
MetaPluginEffect event);
gboolean meta_plugin_manager_event_maximize (MetaPluginManager *mgr,
MetaWindowActor *actor,
unsigned long event,
gint target_x,
gint target_y,
gint target_width,
gint target_height);
gboolean meta_plugin_manager_event_size_change (MetaPluginManager *mgr,
MetaWindowActor *actor,
MetaSizeChange which_change,
MetaRectangle *old_frame_rect,
MetaRectangle *old_buffer_rect);
gboolean meta_plugin_manager_switch_workspace (MetaPluginManager *mgr,
gint from,

View File

@@ -118,17 +118,10 @@ meta_plugin_unminimize_completed (MetaPlugin *plugin,
}
void
meta_plugin_maximize_completed (MetaPlugin *plugin,
MetaWindowActor *actor)
meta_plugin_size_change_completed (MetaPlugin *plugin,
MetaWindowActor *actor)
{
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MAXIMIZE);
}
void
meta_plugin_unmaximize_completed (MetaPlugin *plugin,
MetaWindowActor *actor)
{
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_UNMAXIMIZE);
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_SIZE_CHANGE);
}
void

View File

@@ -1,66 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* MetaShadowFactory:
*
* Create and cache shadow textures for arbitrary window shapes
*
* Copyright (C) 2010 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __META_SHADOW_FACTORY_PRIVATE_H__
#define __META_SHADOW_FACTORY_PRIVATE_H__
#include <cairo.h>
#include <clutter/clutter.h>
#include "meta-window-shape.h"
#include <meta/meta-shadow-factory.h>
/**
* MetaShadow:
* #MetaShadow holds a shadow texture along with information about how to
* apply that texture to draw a window texture. (E.g., it knows how big the
* unscaled borders are on each side of the shadow texture.)
*/
typedef struct _MetaShadow MetaShadow;
MetaShadow *meta_shadow_ref (MetaShadow *shadow);
void meta_shadow_unref (MetaShadow *shadow);
CoglTexture*meta_shadow_get_texture (MetaShadow *shadow);
void meta_shadow_paint (MetaShadow *shadow,
int window_x,
int window_y,
int window_width,
int window_height,
guint8 opacity,
cairo_region_t *clip,
gboolean clip_strictly);
void meta_shadow_get_bounds (MetaShadow *shadow,
int window_x,
int window_y,
int window_width,
int window_height,
cairo_rectangle_int_t *bounds);
MetaShadowFactory *meta_shadow_factory_new (void);
MetaShadow *meta_shadow_factory_get_shadow (MetaShadowFactory *factory,
MetaWindowShape *shape,
int width,
int height,
const char *class_name,
gboolean focused);
#endif /* __META_SHADOW_FACTORY_PRIVATE_H__ */

View File

@@ -26,8 +26,9 @@
#include <math.h>
#include <string.h>
#include <meta/meta-shadow-factory.h>
#include "cogl-utils.h"
#include "meta-shadow-factory-private.h"
#include "region-utils.h"
/* This file implements blurring the shape of a window to produce a
@@ -1048,3 +1049,6 @@ meta_shadow_factory_get_params (MetaShadowFactory *factory,
if (params)
*params = *stored_params;
}
G_DEFINE_BOXED_TYPE (MetaShadow, meta_shadow,
meta_shadow_ref, meta_shadow_unref)

View File

@@ -32,6 +32,9 @@
ClutterActor *meta_shaped_texture_new (void);
void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
CoglTexture *texture);
void meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex,
guint fallback_width,
guint fallback_height);
gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self);
#endif

View File

@@ -86,6 +86,7 @@ struct _MetaShapedTexturePrivate
cairo_region_t *unobscured_region;
guint tex_width, tex_height;
guint fallback_width, fallback_height;
guint create_mipmaps : 1;
};
@@ -136,7 +137,20 @@ set_unobscured_region (MetaShapedTexture *self,
g_clear_pointer (&priv->unobscured_region, (GDestroyNotify) cairo_region_destroy);
if (unobscured_region)
{
cairo_rectangle_int_t bounds = { 0, 0, priv->tex_width, priv->tex_height };
guint width, height;
if (priv->texture)
{
width = priv->tex_width;
height = priv->tex_height;
}
else
{
width = priv->fallback_width;
height = priv->fallback_height;
}
cairo_rectangle_int_t bounds = { 0, 0, width, height };
priv->unobscured_region = cairo_region_copy (unobscured_region);
cairo_region_intersect_rectangle (priv->unobscured_region, &bounds);
}
@@ -173,10 +187,25 @@ meta_shaped_texture_dispose (GObject *object)
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
}
static CoglPipeline *
get_base_pipeline (CoglContext *ctx)
{
static CoglPipeline *template = NULL;
if (G_UNLIKELY (template == NULL))
{
template = cogl_pipeline_new (ctx);
cogl_pipeline_set_layer_wrap_mode_s (template, 0, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
cogl_pipeline_set_layer_wrap_mode_t (template, 0, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
cogl_pipeline_set_layer_wrap_mode_s (template, 1, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
cogl_pipeline_set_layer_wrap_mode_t (template, 1, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
}
return template;
}
static CoglPipeline *
get_unmasked_pipeline (CoglContext *ctx)
{
return cogl_pipeline_new (ctx);
return get_base_pipeline (ctx);
}
static CoglPipeline *
@@ -185,13 +214,13 @@ get_masked_pipeline (CoglContext *ctx)
static CoglPipeline *template = NULL;
if (G_UNLIKELY (template == NULL))
{
template = cogl_pipeline_new (ctx);
template = cogl_pipeline_copy (get_base_pipeline (ctx));
cogl_pipeline_set_layer_combine (template, 1,
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
NULL);
}
return cogl_pipeline_copy (template);
return template;
}
static CoglPipeline *
@@ -201,7 +230,7 @@ get_unblended_pipeline (CoglContext *ctx)
if (G_UNLIKELY (template == NULL))
{
CoglColor color;
template = cogl_pipeline_new (ctx);
template = cogl_pipeline_copy (get_base_pipeline (ctx));
cogl_color_init_from_4ub (&color, 255, 255, 255, 255);
cogl_pipeline_set_blend (template,
"RGBA = ADD (SRC_COLOR, 0)",
@@ -209,7 +238,7 @@ get_unblended_pipeline (CoglContext *ctx)
cogl_pipeline_set_color (template, &color);
}
return cogl_pipeline_copy (template);
return template;
}
static void
@@ -420,8 +449,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
cairo_region_get_rectangle (region, i, &rect);
paint_clipped_rectangle (fb, opaque_pipeline, &rect, &alloc);
}
cogl_object_unref (opaque_pipeline);
}
cairo_region_destroy (region);
@@ -484,8 +511,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
alloc.x2 - alloc.x1,
alloc.y2 - alloc.y1);
}
cogl_object_unref (blended_pipeline);
}
if (blended_region != NULL)
@@ -498,17 +523,18 @@ meta_shaped_texture_get_preferred_width (ClutterActor *self,
gfloat *min_width_p,
gfloat *natural_width_p)
{
MetaShapedTexturePrivate *priv;
MetaShapedTexturePrivate *priv = META_SHAPED_TEXTURE (self)->priv;
guint width;
g_return_if_fail (META_IS_SHAPED_TEXTURE (self));
priv = META_SHAPED_TEXTURE (self)->priv;
if (priv->texture)
width = priv->tex_width;
else
width = priv->fallback_width;
if (min_width_p)
*min_width_p = priv->tex_width;
*min_width_p = width;
if (natural_width_p)
*natural_width_p = priv->tex_width;
*natural_width_p = width;
}
static void
@@ -517,17 +543,18 @@ meta_shaped_texture_get_preferred_height (ClutterActor *self,
gfloat *min_height_p,
gfloat *natural_height_p)
{
MetaShapedTexturePrivate *priv;
MetaShapedTexturePrivate *priv = META_SHAPED_TEXTURE (self)->priv;
guint height;
g_return_if_fail (META_IS_SHAPED_TEXTURE (self));
priv = META_SHAPED_TEXTURE (self)->priv;
if (priv->texture)
height = priv->tex_height;
else
height = priv->fallback_height;
if (min_height_p)
*min_height_p = priv->tex_height;
*min_height_p = height;
if (natural_height_p)
*natural_height_p = priv->tex_height;
*natural_height_p = height;
}
static cairo_region_t *
@@ -860,6 +887,17 @@ meta_shaped_texture_get_image (MetaShapedTexture *stex,
return surface;
}
void
meta_shaped_texture_set_fallback_size (MetaShapedTexture *self,
guint fallback_width,
guint fallback_height)
{
MetaShapedTexturePrivate *priv = self->priv;
priv->fallback_width = fallback_width;
priv->fallback_height = fallback_height;
}
static void
meta_shaped_texture_cull_out (MetaCullable *cullable,
cairo_region_t *unobscured_region,

View File

@@ -26,10 +26,13 @@
#include "meta-surface-actor-wayland.h"
#include <math.h>
#include <cogl/cogl-wayland-server.h>
#include "meta-shaped-texture-private.h"
#include "wayland/meta-wayland-buffer.h"
#include "wayland/meta-wayland-private.h"
#include "wayland/meta-window-wayland.h"
#include "compositor/region-utils.h"
@@ -80,53 +83,89 @@ meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
return FALSE;
}
static int
get_output_scale (int winsys_id)
{
MetaMonitorManager *monitor_manager = meta_monitor_manager_get ();
MetaOutput *outputs;
guint n_outputs, i;
int output_scale = 1;
outputs = meta_monitor_manager_get_outputs (monitor_manager, &n_outputs);
for (i = 0; i < n_outputs; i++)
{
if (outputs[i].winsys_id == winsys_id)
{
output_scale = outputs[i].scale;
break;
}
}
return output_scale;
}
double
meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor)
{
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (actor);
MetaWaylandSurface *surface = priv->surface;
MetaWindow *window = surface->window;
MetaWindow *window;
int output_scale = 1;
while (surface)
{
if (surface->window)
{
window = surface->window;
break;
}
surface = surface->sub.parent;
}
if (!surface)
return 1;
window = meta_wayland_surface_get_toplevel_window (surface);
/* XXX: We do not handle x11 clients yet */
if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11)
output_scale = get_output_scale (window->monitor->winsys_id);
output_scale = meta_window_wayland_get_main_monitor_scale (window);
return (double)output_scale / (double)priv->surface->scale;
}
static void
logical_to_actor_position (MetaSurfaceActorWayland *self,
int *x,
int *y)
{
MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
MetaWindow *toplevel_window;
int monitor_scale = 1;
toplevel_window = meta_wayland_surface_get_toplevel_window (surface);
if (toplevel_window)
monitor_scale = meta_window_wayland_get_main_monitor_scale (toplevel_window);
*x = *x * monitor_scale;
*y = *y * monitor_scale;
}
/* Convert the current actor state to the corresponding subsurface rectangle
* in logical pixel coordinate space. */
void
meta_surface_actor_wayland_get_subsurface_rect (MetaSurfaceActorWayland *self,
MetaRectangle *rect)
{
MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
CoglTexture *texture = surface->buffer->texture;
MetaWindow *toplevel_window;
int monitor_scale;
float x, y;
toplevel_window = meta_wayland_surface_get_toplevel_window (surface);
monitor_scale = meta_window_wayland_get_main_monitor_scale (toplevel_window);
clutter_actor_get_position (CLUTTER_ACTOR (self), &x, &y);
*rect = (MetaRectangle) {
.x = x / monitor_scale,
.y = y / monitor_scale,
.width = cogl_texture_get_width (texture) / surface->scale,
.height = cogl_texture_get_height (texture) / surface->scale,
};
}
void
meta_surface_actor_wayland_sync_subsurface_state (MetaSurfaceActorWayland *self)
{
MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
MetaWindow *window;
int x = surface->offset_x + surface->sub.x;
int y = surface->offset_y + surface->sub.y;
window = meta_wayland_surface_get_toplevel_window (surface);
if (window && window->client_type == META_WINDOW_CLIENT_TYPE_X11)
{
/* Bail directly if this is part of a Xwayland window and warn
* if there happen to be offsets anyway since that is not supposed
* to happen. */
g_warn_if_fail (x == 0 && y == 0);
return;
}
logical_to_actor_position (self, &x, &y);
clutter_actor_set_position (CLUTTER_ACTOR (self), x, y);
}
void
meta_surface_actor_wayland_sync_state (MetaSurfaceActorWayland *self)
{
@@ -173,25 +212,65 @@ meta_surface_actor_wayland_sync_state (MetaSurfaceActorWayland *self)
scaled_opaque_region);
cairo_region_destroy (scaled_opaque_region);
}
meta_surface_actor_wayland_sync_subsurface_state (self);
}
void
meta_surface_actor_wayland_sync_state_recursive (MetaSurfaceActorWayland *self)
{
MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
MetaWindow *window = meta_wayland_surface_get_toplevel_window (surface);
GList *iter;
meta_surface_actor_wayland_sync_state (self);
for (iter = surface->subsurfaces; iter != NULL; iter = iter->next)
if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11)
{
MetaWaylandSurface *subsurf = iter->data;
for (iter = surface->subsurfaces; iter != NULL; iter = iter->next)
{
MetaWaylandSurface *subsurf = iter->data;
meta_surface_actor_wayland_sync_state_recursive (
META_SURFACE_ACTOR_WAYLAND (subsurf->surface_actor));
meta_surface_actor_wayland_sync_state_recursive (
META_SURFACE_ACTOR_WAYLAND (subsurf->surface_actor));
}
}
}
gboolean
meta_surface_actor_wayland_is_on_monitor (MetaSurfaceActorWayland *self,
MetaMonitorInfo *monitor)
{
float x, y, width, height;
cairo_rectangle_int_t actor_rect;
cairo_region_t *region;
gboolean is_on_monitor;
clutter_actor_get_transformed_position (CLUTTER_ACTOR (self), &x, &y);
clutter_actor_get_transformed_size (CLUTTER_ACTOR (self), &width, &height);
actor_rect.x = (int)roundf (x);
actor_rect.y = (int)roundf (y);
actor_rect.width = (int)roundf (x + width) - actor_rect.x;
actor_rect.height = (int)roundf (y + height) - actor_rect.y;
/* Calculate the scaled surface actor region. */
region = cairo_region_create_rectangle (&actor_rect);
cairo_region_intersect_rectangle (region,
&((cairo_rectangle_int_t) {
.x = monitor->rect.x,
.y = monitor->rect.y,
.width = monitor->rect.width,
.height = monitor->rect.height,
}));
is_on_monitor = !cairo_region_is_empty (region);
cairo_region_destroy (region);
return is_on_monitor;
}
static MetaWindow *
meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
{
@@ -236,6 +315,19 @@ meta_surface_actor_wayland_get_preferred_height (ClutterActor *self,
*natural_height_p *= scale;
}
static void
meta_surface_actor_wayland_paint (ClutterActor *actor)
{
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
MetaSurfaceActorWaylandPrivate *priv =
meta_surface_actor_wayland_get_instance_private (self);
if (priv->surface)
meta_wayland_surface_update_outputs (priv->surface);
CLUTTER_ACTOR_CLASS (meta_surface_actor_wayland_parent_class)->paint (actor);
}
static void
meta_surface_actor_wayland_dispose (GObject *object)
{
@@ -255,6 +347,7 @@ meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
actor_class->get_preferred_width = meta_surface_actor_wayland_get_preferred_width;
actor_class->get_preferred_height = meta_surface_actor_wayland_get_preferred_height;
actor_class->paint = meta_surface_actor_wayland_paint;
surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint;
@@ -301,3 +394,12 @@ meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self)
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
return priv->surface;
}
void
meta_surface_actor_wayland_surface_destroyed (MetaSurfaceActorWayland *self)
{
MetaSurfaceActorWaylandPrivate *priv =
meta_surface_actor_wayland_get_instance_private (self);
priv->surface = NULL;
}

View File

@@ -31,6 +31,8 @@
#include "wayland/meta-wayland.h"
#include "backends/meta-monitor-manager-private.h"
G_BEGIN_DECLS
#define META_TYPE_SURFACE_ACTOR_WAYLAND (meta_surface_actor_wayland_get_type ())
@@ -57,16 +59,25 @@ GType meta_surface_actor_wayland_get_type (void);
MetaSurfaceActor * meta_surface_actor_wayland_new (MetaWaylandSurface *surface);
MetaWaylandSurface * meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self);
void meta_surface_actor_wayland_surface_destroyed (MetaSurfaceActorWayland *self);
void meta_surface_actor_wayland_set_texture (MetaSurfaceActorWayland *self,
CoglTexture *texture);
double meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor);
void meta_surface_actor_wayland_get_subsurface_rect (MetaSurfaceActorWayland *self,
MetaRectangle *rect);
void meta_surface_actor_wayland_sync_state (MetaSurfaceActorWayland *self);
void meta_surface_actor_wayland_sync_state_recursive (MetaSurfaceActorWayland *self);
void meta_surface_actor_wayland_sync_subsurface_state (MetaSurfaceActorWayland *self);
gboolean meta_surface_actor_wayland_is_on_monitor (MetaSurfaceActorWayland *self,
MetaMonitorInfo *monitor);
G_END_DECLS
#endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */

View File

@@ -416,6 +416,7 @@ meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
int width, int height)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
if (priv->last_width == width &&
priv->last_height == height)
@@ -424,4 +425,5 @@ meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
priv->size_changed = TRUE;
priv->last_width = width;
priv->last_height = height;
meta_shaped_texture_set_fallback_size (stex, width, height);
}

View File

@@ -8,6 +8,7 @@
#include <X11/extensions/Xdamage.h>
#include <meta/compositor-mutter.h>
#include "meta-surface-actor.h"
#include "meta-plugin-manager.h"
MetaWindowActor *meta_window_actor_new (MetaWindow *window);
@@ -18,12 +19,10 @@ void meta_window_actor_show (MetaWindowActor *self,
void meta_window_actor_hide (MetaWindowActor *self,
MetaCompEffect effect);
void meta_window_actor_maximize (MetaWindowActor *self,
MetaRectangle *old_rect,
MetaRectangle *new_rect);
void meta_window_actor_unmaximize (MetaWindowActor *self,
MetaRectangle *old_rect,
MetaRectangle *new_rect);
void meta_window_actor_size_change (MetaWindowActor *self,
MetaSizeChange which_change,
MetaRectangle *old_frame_rect,
MetaRectangle *old_buffer_rect);
void meta_window_actor_process_x11_damage (MetaWindowActor *self,
XDamageNotifyEvent *event);
@@ -55,8 +54,8 @@ void meta_window_actor_sync_updates_frozen (MetaWindowActor *self);
void meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
gboolean no_delay_frame);
void meta_window_actor_effect_completed (MetaWindowActor *actor,
gulong event);
void meta_window_actor_effect_completed (MetaWindowActor *actor,
MetaPluginEffect event);
MetaSurfaceActor *meta_window_actor_get_surface (MetaWindowActor *self);
void meta_window_actor_update_surface (MetaWindowActor *self);

View File

@@ -20,10 +20,11 @@
#include "frame.h"
#include <meta/window.h>
#include <meta/meta-shaped-texture.h>
#include <meta/meta-enum-types.h>
#include <meta/meta-shadow-factory.h>
#include "compositor-private.h"
#include "meta-shaped-texture-private.h"
#include "meta-shadow-factory-private.h"
#include "meta-window-actor-private.h"
#include "meta-texture-rectangle.h"
#include "region-utils.h"
@@ -74,6 +75,8 @@ struct _MetaWindowActorPrivate
MetaWindowShape *shadow_shape;
char * shadow_class;
MetaShadowMode shadow_mode;
guint send_frame_messages_timer;
gint64 frame_drawn_time;
@@ -87,8 +90,7 @@ struct _MetaWindowActorPrivate
*/
gint minimize_in_progress;
gint unminimize_in_progress;
gint maximize_in_progress;
gint unmaximize_in_progress;
gint size_change_in_progress;
gint map_in_progress;
gint destroy_in_progress;
@@ -110,8 +112,6 @@ struct _MetaWindowActorPrivate
guint needs_destroy : 1;
guint no_shadow : 1;
guint updates_frozen : 1;
guint first_frame_state : 2; /* FirstFrameState */
};
@@ -147,7 +147,7 @@ static guint signals[LAST_SIGNAL] = { 0 };
enum
{
PROP_META_WINDOW = 1,
PROP_NO_SHADOW,
PROP_SHADOW_MODE,
PROP_SHADOW_CLASS
};
@@ -245,14 +245,15 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
PROP_META_WINDOW,
pspec);
pspec = g_param_spec_boolean ("no-shadow",
"No shadow",
"Do not add shaddow to this window",
FALSE,
G_PARAM_READWRITE);
pspec = g_param_spec_enum ("shadow-mode",
"Shadow mode",
"Decides when to paint shadows",
META_TYPE_SHADOW_MODE,
META_SHADOW_MODE_AUTO,
G_PARAM_READWRITE);
g_object_class_install_property (object_class,
PROP_NO_SHADOW,
PROP_SHADOW_MODE,
pspec);
pspec = g_param_spec_string ("shadow-class",
@@ -510,14 +511,14 @@ meta_window_actor_set_property (GObject *object,
g_signal_connect_object (priv->window, "notify::appears-focused",
G_CALLBACK (window_appears_focused_notify), self, 0);
break;
case PROP_NO_SHADOW:
case PROP_SHADOW_MODE:
{
gboolean newv = g_value_get_boolean (value);
MetaShadowMode newv = g_value_get_enum (value);
if (newv == priv->no_shadow)
if (newv == priv->shadow_mode)
return;
priv->no_shadow = newv;
priv->shadow_mode = newv;
meta_window_actor_invalidate_shadow (self);
}
@@ -554,8 +555,8 @@ meta_window_actor_get_property (GObject *object,
case PROP_META_WINDOW:
g_value_set_object (value, priv->window);
break;
case PROP_NO_SHADOW:
g_value_set_boolean (value, priv->no_shadow);
case PROP_SHADOW_MODE:
g_value_set_enum (value, priv->shadow_mode);
break;
case PROP_SHADOW_CLASS:
g_value_set_string (value, priv->shadow_class);
@@ -615,8 +616,10 @@ meta_window_actor_get_shape_bounds (MetaWindowActor *self,
#ifdef HAVE_WAYLAND
if (META_IS_SURFACE_ACTOR_WAYLAND (priv->surface))
{
double scale = priv->surface ?
meta_surface_actor_wayland_get_scale (META_SURFACE_ACTOR_WAYLAND (priv->surface)) : 1.;
MetaSurfaceActorWayland *surface_actor =
META_SURFACE_ACTOR_WAYLAND (priv->surface);
double scale = meta_surface_actor_wayland_get_scale (surface_actor);
bounds->x *= scale;
bounds->y *= scale;
bounds->width *= scale;
@@ -802,8 +805,10 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
if (priv->no_shadow)
if (priv->shadow_mode == META_SHADOW_MODE_FORCED_OFF)
return FALSE;
if (priv->shadow_mode == META_SHADOW_MODE_FORCED_ON)
return TRUE;
/* Leaving out shadows for maximized and fullscreen windows is an effeciency
* win and also prevents the unsightly effect of the shadow of maximized
@@ -1036,20 +1041,18 @@ gboolean
meta_window_actor_effect_in_progress (MetaWindowActor *self)
{
return (self->priv->minimize_in_progress ||
self->priv->maximize_in_progress ||
self->priv->unmaximize_in_progress ||
self->priv->size_change_in_progress ||
self->priv->map_in_progress ||
self->priv->destroy_in_progress);
}
static gboolean
is_freeze_thaw_effect (gulong event)
is_freeze_thaw_effect (MetaPluginEffect event)
{
switch (event)
{
case META_PLUGIN_DESTROY:
case META_PLUGIN_MAXIMIZE:
case META_PLUGIN_UNMAXIMIZE:
case META_PLUGIN_SIZE_CHANGE:
return TRUE;
break;
default:
@@ -1058,8 +1061,8 @@ is_freeze_thaw_effect (gulong event)
}
static gboolean
start_simple_effect (MetaWindowActor *self,
gulong event)
start_simple_effect (MetaWindowActor *self,
MetaPluginEffect event)
{
MetaWindowActorPrivate *priv = self->priv;
MetaCompositor *compositor = priv->compositor;
@@ -1068,6 +1071,8 @@ start_simple_effect (MetaWindowActor *self,
switch (event)
{
case META_PLUGIN_NONE:
return FALSE;
case META_PLUGIN_MINIMIZE:
counter = &priv->minimize_in_progress;
break;
@@ -1080,8 +1085,7 @@ start_simple_effect (MetaWindowActor *self,
case META_PLUGIN_DESTROY:
counter = &priv->destroy_in_progress;
break;
case META_PLUGIN_UNMAXIMIZE:
case META_PLUGIN_MAXIMIZE:
case META_PLUGIN_SIZE_CHANGE:
case META_PLUGIN_SWITCH_WORKSPACE:
g_assert_not_reached ();
break;
@@ -1123,8 +1127,8 @@ meta_window_actor_after_effects (MetaWindowActor *self)
}
void
meta_window_actor_effect_completed (MetaWindowActor *self,
gulong event)
meta_window_actor_effect_completed (MetaWindowActor *self,
MetaPluginEffect event)
{
MetaWindowActorPrivate *priv = self->priv;
@@ -1134,6 +1138,8 @@ meta_window_actor_effect_completed (MetaWindowActor *self,
switch (event)
{
case META_PLUGIN_NONE:
break;
case META_PLUGIN_MINIMIZE:
{
priv->minimize_in_progress--;
@@ -1176,20 +1182,12 @@ meta_window_actor_effect_completed (MetaWindowActor *self,
priv->destroy_in_progress = 0;
}
break;
case META_PLUGIN_UNMAXIMIZE:
priv->unmaximize_in_progress--;
if (priv->unmaximize_in_progress < 0)
case META_PLUGIN_SIZE_CHANGE:
priv->size_change_in_progress--;
if (priv->size_change_in_progress < 0)
{
g_warning ("Error in unmaximize accounting.");
priv->unmaximize_in_progress = 0;
}
break;
case META_PLUGIN_MAXIMIZE:
priv->maximize_in_progress--;
if (priv->maximize_in_progress < 0)
{
g_warning ("Error in maximize accounting.");
priv->maximize_in_progress = 0;
g_warning ("Error in size change accounting.");
priv->size_change_in_progress = 0;
}
break;
case META_PLUGIN_SWITCH_WORKSPACE:
@@ -1300,7 +1298,7 @@ meta_window_actor_show (MetaWindowActor *self,
{
MetaWindowActorPrivate *priv = self->priv;
MetaCompositor *compositor = priv->compositor;
gulong event = 0;
MetaPluginEffect event;
g_return_if_fail (!priv->visible);
@@ -1315,14 +1313,13 @@ meta_window_actor_show (MetaWindowActor *self,
event = META_PLUGIN_UNMINIMIZE;
break;
case META_COMP_EFFECT_NONE:
event = META_PLUGIN_NONE;
break;
case META_COMP_EFFECT_DESTROY:
case META_COMP_EFFECT_MINIMIZE:
default:
g_assert_not_reached();
}
if (compositor->switch_workspace_in_progress ||
event == 0 ||
!start_simple_effect (self, event))
{
clutter_actor_show (CLUTTER_ACTOR (self));
@@ -1335,7 +1332,7 @@ meta_window_actor_hide (MetaWindowActor *self,
{
MetaWindowActorPrivate *priv = self->priv;
MetaCompositor *compositor = priv->compositor;
gulong event = 0;
MetaPluginEffect event;
g_return_if_fail (priv->visible);
@@ -1357,70 +1354,32 @@ meta_window_actor_hide (MetaWindowActor *self,
event = META_PLUGIN_MINIMIZE;
break;
case META_COMP_EFFECT_NONE:
event = META_PLUGIN_NONE;
break;
case META_COMP_EFFECT_UNMINIMIZE:
case META_COMP_EFFECT_CREATE:
default:
g_assert_not_reached();
}
if (event == 0 ||
!start_simple_effect (self, event))
if (!start_simple_effect (self, event))
clutter_actor_hide (CLUTTER_ACTOR (self));
}
void
meta_window_actor_maximize (MetaWindowActor *self,
MetaRectangle *old_rect,
MetaRectangle *new_rect)
meta_window_actor_size_change (MetaWindowActor *self,
MetaSizeChange which_change,
MetaRectangle *old_frame_rect,
MetaRectangle *old_buffer_rect)
{
MetaWindowActorPrivate *priv = self->priv;
MetaCompositor *compositor = priv->compositor;
/* The window has already been resized (in order to compute new_rect),
* which by side effect caused the actor to be resized. Restore it to the
* old size and position */
clutter_actor_set_position (CLUTTER_ACTOR (self), old_rect->x, old_rect->y);
clutter_actor_set_size (CLUTTER_ACTOR (self), old_rect->width, old_rect->height);
self->priv->maximize_in_progress++;
self->priv->size_change_in_progress++;
meta_window_actor_freeze (self);
if (!meta_plugin_manager_event_maximize (compositor->plugin_mgr,
self,
META_PLUGIN_MAXIMIZE,
new_rect->x, new_rect->y,
new_rect->width, new_rect->height))
if (!meta_plugin_manager_event_size_change (compositor->plugin_mgr, self,
which_change, old_frame_rect, old_buffer_rect))
{
self->priv->maximize_in_progress--;
meta_window_actor_thaw (self);
}
}
void
meta_window_actor_unmaximize (MetaWindowActor *self,
MetaRectangle *old_rect,
MetaRectangle *new_rect)
{
MetaWindowActorPrivate *priv = self->priv;
MetaCompositor *compositor = priv->compositor;
/* The window has already been resized (in order to compute new_rect),
* which by side effect caused the actor to be resized. Restore it to the
* old size and position */
clutter_actor_set_position (CLUTTER_ACTOR (self), old_rect->x, old_rect->y);
clutter_actor_set_size (CLUTTER_ACTOR (self), old_rect->width, old_rect->height);
self->priv->unmaximize_in_progress++;
meta_window_actor_freeze (self);
if (!meta_plugin_manager_event_maximize (compositor->plugin_mgr,
self,
META_PLUGIN_UNMAXIMIZE,
new_rect->x, new_rect->y,
new_rect->width, new_rect->height))
{
self->priv->unmaximize_in_progress--;
self->priv->size_change_in_progress--;
meta_window_actor_thaw (self);
}
}

View File

@@ -58,9 +58,7 @@ meta_window_group_paint (ClutterActor *actor)
cairo_region_t *clip_region;
cairo_region_t *unobscured_region;
cairo_rectangle_int_t visible_rect, clip_rect;
int paint_x_offset, paint_y_offset;
int paint_x_origin, paint_y_origin;
int actor_x_origin, actor_y_origin;
int screen_width, screen_height;
MetaWindowGroup *window_group = META_WINDOW_GROUP (actor);
@@ -82,7 +80,7 @@ meta_window_group_paint (ClutterActor *actor)
* on the stage.
*/
if (!meta_actor_painting_untransformed (screen_width, screen_height, &paint_x_origin, &paint_y_origin) ||
!meta_actor_is_untransformed (actor, &actor_x_origin, &actor_y_origin))
!meta_actor_is_untransformed (actor, NULL, NULL))
{
CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor);
return;
@@ -105,9 +103,7 @@ meta_window_group_paint (ClutterActor *actor)
clip_region = cairo_region_create_rectangle (&clip_rect);
paint_x_offset = paint_x_origin - actor_x_origin;
paint_y_offset = paint_y_origin - actor_y_origin;
cairo_region_translate (clip_region, -paint_x_offset, -paint_y_offset);
cairo_region_translate (clip_region, -paint_x_origin, -paint_y_origin);
meta_cullable_cull_out (META_CULLABLE (window_group), unobscured_region, clip_region);
@@ -145,6 +141,36 @@ meta_window_group_get_paint_volume (ClutterActor *self,
return TRUE;
}
/* This is a workaround for Clutter's awful allocation tracking.
* Without this, any time the window group changed size, which is
* any time windows are dragged around, we'll do a full repaint
* of the window group, which includes the background actor, meaning
* a full-stage repaint.
*
* Since actors are allowed to paint outside their allocation, and
* since child actors are allowed to be outside their parents, this
* doesn't affect anything, but it means that we'll get much more
* sane and consistent clipped repaints from Clutter. */
static void
meta_window_group_get_preferred_width (ClutterActor *actor,
gfloat for_height,
gfloat *min_width,
gfloat *nat_width)
{
*min_width = 0;
*nat_width = 0;
}
static void
meta_window_group_get_preferred_height (ClutterActor *actor,
gfloat for_width,
gfloat *min_height,
gfloat *nat_height)
{
*min_height = 0;
*nat_height = 0;
}
static void
meta_window_group_class_init (MetaWindowGroupClass *klass)
{
@@ -152,6 +178,8 @@ meta_window_group_class_init (MetaWindowGroupClass *klass)
actor_class->paint = meta_window_group_paint;
actor_class->get_paint_volume = meta_window_group_get_paint_volume;
actor_class->get_preferred_width = meta_window_group_get_preferred_width;
actor_class->get_preferred_height = meta_window_group_get_preferred_height;
}
static void

View File

@@ -1,4 +1,5 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* MetaWindowShape
*
@@ -19,9 +20,12 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "meta-window-shape.h"
#include "config.h"
#include <meta/meta-window-shape.h>
#include <string.h>
#include "region-utils.h"
struct _MetaWindowShape
@@ -250,3 +254,5 @@ meta_window_shape_to_region (MetaWindowShape *shape,
return region;
}
G_DEFINE_BOXED_TYPE (MetaWindowShape, meta_window_shape,
meta_window_shape_ref, meta_window_shape_unref)

View File

@@ -689,7 +689,7 @@ show_tile_preview (MetaPlugin *plugin,
ScreenTilePreview *preview = get_screen_tile_preview (screen);
ClutterActor *window_actor;
if (CLUTTER_ACTOR_IS_VISIBLE (preview->actor)
if (clutter_actor_is_visible (preview->actor)
&& preview->tile_rect.x == tile_rect->x
&& preview->tile_rect.y == tile_rect->y
&& preview->tile_rect.width == tile_rect->width

View File

@@ -172,18 +172,6 @@ meta_core_toggle_maximize (Display *xdisplay,
meta_window_maximize (window, META_MAXIMIZE_BOTH);
}
void
meta_core_change_workspace (Display *xdisplay,
Window frame_xwindow,
int new_workspace)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
meta_window_change_workspace (window,
meta_screen_get_workspace_by_index (window->screen,
new_workspace));
}
void
meta_core_show_window_menu (Display *xdisplay,
Window frame_xwindow,
@@ -217,19 +205,6 @@ meta_core_show_window_menu_for_rect (Display *xdisplay,
meta_window_show_menu_for_rect (window, menu, rect);
}
const char*
meta_core_get_workspace_name_with_index (Display *xdisplay,
Window xroot,
int index)
{
MetaDisplay *display;
MetaWorkspace *workspace;
display = meta_display_for_x_display (xdisplay);
workspace = meta_screen_get_workspace_by_index (display->screen, index);
return workspace ? meta_workspace_get_name (workspace) : NULL;
}
gboolean
meta_core_begin_grab_op (Display *xdisplay,
Window frame_xwindow,

View File

@@ -41,15 +41,6 @@ void meta_core_toggle_maximize_horizontally (Display *xdisplay,
Window frame_xwindow);
void meta_core_toggle_maximize_vertically (Display *xdisplay,
Window frame_xwindow);
void meta_core_change_workspace (Display *xdisplay,
Window frame_xwindow,
int new_workspace);
int meta_core_get_frame_workspace (Display *xdisplay,
Window frame_xwindow);
const char* meta_core_get_workspace_name_with_index (Display *xdisplay,
Window xroot,
int index);
void meta_core_show_window_menu (Display *xdisplay,
Window frame_xwindow,

View File

@@ -160,12 +160,7 @@ void
meta_window_set_alive (MetaWindow *window,
gboolean is_alive)
{
if (window->is_alive == is_alive)
return;
window->is_alive = is_alive;
if (window->is_alive)
if (is_alive)
kill_delete_dialog (window);
else
show_delete_dialog (window, CurrentTime);
@@ -185,34 +180,6 @@ meta_window_delete (MetaWindow *window,
META_WINDOW_GET_CLASS (window)->delete (window, timestamp);
meta_window_check_alive (window, timestamp);
if (window->has_focus)
{
/* FIXME Clean this up someday
* http://bugzilla.gnome.org/show_bug.cgi?id=108706
*/
#if 0
/* This is unfortunately going to result in weirdness
* if the window doesn't respond to the delete event.
* I don't know how to avoid that though.
*/
meta_topic (META_DEBUG_FOCUS,
"Focusing default window because focus window %s was deleted/killed\n",
window->desc);
meta_workspace_focus_default_window (window->screen->active_workspace,
window);
#else
meta_topic (META_DEBUG_FOCUS,
"Not unfocusing %s on delete/kill\n",
window->desc);
#endif
}
else
{
meta_topic (META_DEBUG_FOCUS,
"Window %s was deleted/killed but didn't have focus\n",
window->desc);
}
}
void

View File

@@ -121,7 +121,7 @@ struct _MetaDisplay
* class is constructed.
*/
#define item(x) Atom atom_##x;
#include <meta/atomnames.h>
#include <x11/atomnames.h>
#undef item
/* The window and serial of the most recent FocusIn event. */
@@ -217,9 +217,6 @@ struct _MetaDisplay
guint grab_have_pointer : 1;
guint grab_have_keyboard : 1;
guint grab_frame_action : 1;
/* During a resize operation, the directions in which we've broken
* out of the initial maximization state */
guint grab_resize_unmaximize : 2; /* MetaMaximizeFlags */
MetaRectangle grab_initial_window_pos;
int grab_initial_x, grab_initial_y; /* These are only relevant for */
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */

View File

@@ -46,12 +46,13 @@
#include <meta/compositor.h>
#include <meta/compositor-mutter.h>
#include <X11/Xatom.h>
#include "mutter-enum-types.h"
#include <meta/meta-enum-types.h>
#include "meta-idle-monitor-dbus.h"
#include "meta-cursor-tracker-private.h"
#include <meta/meta-backend.h>
#include "backends/native/meta-backend-native.h"
#include "backends/x11/meta-backend-x11.h"
#include "backends/meta-stage.h"
#include <clutter/x11/clutter-x11.h>
#ifdef HAVE_RANDR
@@ -548,7 +549,7 @@ meta_display_open (void)
/* A list of all atom names, so that we can intern them in one go. */
char *atom_names[] = {
#define item(x) #x,
#include <meta/atomnames.h>
#include <x11/atomnames.h>
#undef item
};
Atom atoms[G_N_ELEMENTS(atom_names)];
@@ -609,7 +610,7 @@ meta_display_open (void)
{
int i = 0;
#define item(x) display->atom_##x = atoms[i++];
#include <meta/atomnames.h>
#include <x11/atomnames.h>
#undef item
}
@@ -1411,6 +1412,8 @@ meta_display_sync_wayland_input_focus (MetaDisplay *display)
#ifdef HAVE_WAYLAND
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaWindow *focus_window = NULL;
MetaBackend *backend = meta_get_backend ();
MetaStage *stage = META_STAGE (meta_backend_get_stage (backend));
if (!meta_display_windows_are_interactable (display))
focus_window = NULL;
@@ -1421,6 +1424,7 @@ meta_display_sync_wayland_input_focus (MetaDisplay *display)
else
meta_topic (META_DEBUG_FOCUS, "Focus change has no effect, because there is no matching wayland surface");
meta_stage_set_active (stage, focus_window == NULL);
meta_wayland_compositor_set_input_focus (compositor, focus_window);
meta_wayland_seat_repick (compositor->seat);
@@ -1918,7 +1922,6 @@ meta_display_begin_grab_op (MetaDisplay *display,
display->grab_last_moveresize_time.tv_usec = 0;
display->grab_last_user_action_was_snap = FALSE;
display->grab_frame_action = frame_action;
display->grab_resize_unmaximize = 0;
meta_display_update_cursor (display);

View File

@@ -40,6 +40,13 @@
#endif
#include "meta-surface-actor.h"
#define IS_GESTURE_EVENT(e) ((e)->type == CLUTTER_TOUCHPAD_SWIPE || \
(e)->type == CLUTTER_TOUCHPAD_PINCH || \
(e)->type == CLUTTER_TOUCH_BEGIN || \
(e)->type == CLUTTER_TOUCH_UPDATE || \
(e)->type == CLUTTER_TOUCH_END || \
(e)->type == CLUTTER_TOUCH_CANCEL)
static MetaWindow *
get_window_for_event (MetaDisplay *display,
const ClutterEvent *event)
@@ -93,6 +100,15 @@ handle_idletime_for_event (const ClutterEvent *event)
if (device == NULL)
return;
if (event->any.flags & CLUTTER_EVENT_FLAG_SYNTHETIC ||
event->type == CLUTTER_ENTER ||
event->type == CLUTTER_LEAVE ||
event->type == CLUTTER_STAGE_STATE ||
event->type == CLUTTER_DESTROY_NOTIFY ||
event->type == CLUTTER_CLIENT_MESSAGE ||
event->type == CLUTTER_DELETE)
return;
device_id = clutter_input_device_get_device_id (device);
core_monitor = meta_idle_monitor_get_core ();
@@ -192,6 +208,7 @@ meta_display_handle_event (MetaDisplay *display,
{
MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (NULL);
meta_cursor_tracker_update_position (tracker, event->motion.x, event->motion.y);
display->monitor_cache_invalidated = TRUE;
}
handle_idletime_for_event (event);
@@ -255,15 +272,18 @@ meta_display_handle_event (MetaDisplay *display,
if (window)
{
if (!clutter_event_get_event_sequence (event))
{
/* Swallow all non-touch events on windows that come our way.
* Touch events that reach here aren't yet in an accepted state,
* so Clutter must see them to maybe trigger gestures into
* recognition.
*/
bypass_clutter = TRUE;
}
/* Events that are likely to trigger compositor gestures should
* be known to clutter so they can propagate along the hierarchy.
* Gesture-wise, there's two groups of events we should be getting
* here:
* - CLUTTER_TOUCH_* with a touch sequence that's not yet accepted
* by the gesture tracker, these might trigger gesture actions
* into recognition. Already accepted touch sequences are handled
* directly by meta_gesture_tracker_handle_event().
* - CLUTTER_TOUCHPAD_* events over windows. These can likewise
* trigger ::captured-event handlers along the way.
*/
bypass_clutter = !IS_GESTURE_EVENT (event);
meta_window_handle_ungrabbed_event (window, event);

View File

@@ -37,7 +37,6 @@ meta_window_ensure_frame (MetaWindow *window)
{
MetaFrame *frame;
XSetWindowAttributes attrs;
Visual *visual;
gulong create_serial;
if (window->frame)
@@ -58,37 +57,14 @@ meta_window_ensure_frame (MetaWindow *window)
frame->is_flashing = FALSE;
frame->borders_cached = FALSE;
meta_verbose ("Framing window %s: visual %s default, depth %d default depth %d\n",
window->desc,
XVisualIDFromVisual (window->xvisual) ==
XVisualIDFromVisual (window->screen->default_xvisual) ?
"is" : "is not",
window->depth, window->screen->default_depth);
meta_verbose ("Frame geometry %d,%d %dx%d\n",
frame->rect.x, frame->rect.y,
frame->rect.width, frame->rect.height);
/* Default depth/visual handles clients with weird visuals; they can
* always be children of the root depth/visual obviously, but
* e.g. DRI games can't be children of a parent that has the same
* visual as the client. NULL means default visual.
*
* We look for an ARGB visual if we can find one, otherwise use
* the default of NULL.
*/
/* Special case for depth 32 windows (assumed to be ARGB),
* we use the window's visual. Otherwise we just use the system visual.
*/
if (window->depth == 32)
visual = window->xvisual;
else
visual = NULL;
frame->ui_frame = meta_ui_create_frame (window->screen->ui,
window->display->xdisplay,
frame->window,
visual,
window->xvisual,
frame->rect.x,
frame->rect.y,
frame->rect.width,

View File

@@ -30,6 +30,7 @@
#include <gio/gio.h>
#include <meta/keybindings.h>
#include <xkbcommon/xkbcommon.h>
#include "meta-accel-parse.h"
typedef struct _MetaKeyHandler MetaKeyHandler;
struct _MetaKeyHandler
@@ -53,7 +54,6 @@ typedef struct _MetaResolvedKeyCombo {
* @keycode: keycode
* @modifiers: modifiers
*/
typedef struct _MetaKeyCombo MetaKeyCombo;
struct _MetaKeyCombo
{
unsigned int keysym;

View File

@@ -3186,7 +3186,7 @@ handle_move_to_monitor (MetaDisplay *display,
gint which = binding->handler->data;
const MetaMonitorInfo *current, *new;
current = meta_screen_get_monitor_for_window (screen, window);
current = window->monitor;
new = meta_screen_get_monitor_neighbor (screen, current->number, which);
if (new == NULL)

View File

@@ -176,7 +176,6 @@ static gboolean
accelerator_parse (const gchar *accelerator,
MetaKeyCombo *combo)
{
gboolean error = FALSE;
guint keyval, keycode;
MetaVirtualModifier mods;
gint len;
@@ -186,10 +185,7 @@ accelerator_parse (const gchar *accelerator,
combo->modifiers = 0;
if (accelerator == NULL)
{
error = TRUE;
goto out;
}
return FALSE;
keyval = 0;
keycode = 0;
@@ -310,10 +306,7 @@ accelerator_parse (const gchar *accelerator,
g_free (with_xf86);
if (keyval == XKB_KEY_NoSymbol)
{
error = TRUE;
goto out;
}
return FALSE;
}
}
@@ -322,14 +315,10 @@ accelerator_parse (const gchar *accelerator,
}
}
out:
if (error)
return FALSE;
out:
combo->keysym = keyval;
combo->keycode = keycode;
combo->modifiers = mods;
return TRUE;
}

View File

@@ -2113,12 +2113,6 @@ meta_prefs_add_keybinding (const char *name,
pref->combos = NULL;
pref->builtin = (flags & META_KEY_BINDING_BUILTIN) != 0;
strokes = g_settings_get_strv (settings, name);
update_binding (pref, strokes);
g_strfreev (strokes);
g_hash_table_insert (key_bindings, g_strdup (name), pref);
if (pref->builtin)
{
if (g_object_get_data (G_OBJECT (settings), "changed-signal") == NULL)
@@ -2140,6 +2134,12 @@ meta_prefs_add_keybinding (const char *name,
queue_changed (META_PREF_KEYBINDINGS);
}
strokes = g_settings_get_strv (settings, name);
update_binding (pref, strokes);
g_strfreev (strokes);
g_hash_table_insert (key_bindings, g_strdup (name), pref);
return TRUE;
}

View File

@@ -41,14 +41,6 @@
typedef void (* MetaScreenWindowFunc) (MetaWindow *window,
gpointer user_data);
typedef enum
{
META_SCREEN_UP,
META_SCREEN_DOWN,
META_SCREEN_LEFT,
META_SCREEN_RIGHT
} MetaScreenDirection;
#define META_WIREFRAME_XOR_LINE_WIDTH 2
struct _MetaScreen
@@ -157,8 +149,8 @@ const MetaMonitorInfo* meta_screen_get_current_monitor_info_for_pos (MetaScree
int y);
const MetaMonitorInfo* meta_screen_get_monitor_for_rect (MetaScreen *screen,
MetaRectangle *rect);
const MetaMonitorInfo* meta_screen_get_monitor_for_window (MetaScreen *screen,
MetaWindow *window);
const MetaMonitorInfo* meta_screen_calculate_monitor_for_window (MetaScreen *screen,
MetaWindow *window);
const MetaMonitorInfo* meta_screen_get_monitor_neighbor (MetaScreen *screen,

View File

@@ -40,7 +40,7 @@
#include "keybindings-private.h"
#include "stack.h"
#include <meta/compositor.h>
#include "mutter-enum-types.h"
#include <meta/meta-enum-types.h>
#include "core.h"
#include "meta-cursor-tracker-private.h"
@@ -294,7 +294,7 @@ set_supported_hint (MetaScreen *screen)
Atom atoms[] = {
#define EWMH_ATOMS_ONLY
#define item(x) screen->display->atom_##x,
#include <meta/atomnames.h>
#include <x11/atomnames.h>
#undef item
#undef EWMH_ATOMS_ONLY
@@ -750,7 +750,7 @@ void
meta_screen_init_workspaces (MetaScreen *screen)
{
MetaWorkspace *current_workspace;
gulong current_workspace_index = 0;
uint32_t current_workspace_index = 0;
guint32 timestamp;
g_return_if_fail (META_IS_SCREEN (screen));
@@ -1166,7 +1166,7 @@ update_num_workspaces (MetaScreen *screen,
if (meta_prefs_get_dynamic_workspaces ())
{
int n_items;
gulong *list;
uint32_t *list;
n_items = 0;
list = NULL;
@@ -1439,8 +1439,8 @@ meta_screen_get_monitor_for_rect (MetaScreen *screen,
}
const MetaMonitorInfo*
meta_screen_get_monitor_for_window (MetaScreen *screen,
MetaWindow *window)
meta_screen_calculate_monitor_for_window (MetaScreen *screen,
MetaWindow *window)
{
MetaRectangle window_rect;
@@ -1490,6 +1490,16 @@ meta_screen_get_monitor_neighbor (MetaScreen *screen,
return NULL;
}
int
meta_screen_get_monitor_neighbor_index (MetaScreen *screen,
int which_monitor,
MetaScreenDirection direction)
{
const MetaMonitorInfo *monitor;
monitor = meta_screen_get_monitor_neighbor (screen, which_monitor, direction);
return monitor ? monitor->number : -1;
}
void
meta_screen_get_natural_monitor_list (MetaScreen *screen,
int** monitors_list,
@@ -1745,7 +1755,7 @@ meta_screen_get_monitor_geometry (MetaScreen *screen,
void
meta_screen_update_workspace_layout (MetaScreen *screen)
{
gulong *list;
uint32_t *list;
int n_items;
if (screen->workspace_layout_overridden)
@@ -2378,12 +2388,12 @@ on_monitors_changed (MetaMonitorManager *manager,
&changes);
}
/* Queue a resize on all the windows */
meta_screen_foreach_window (screen, META_LIST_DEFAULT, meta_screen_resize_func, 0);
/* Fix up monitor for all windows on this screen */
meta_screen_foreach_window (screen, META_LIST_INCLUDE_OVERRIDE_REDIRECT, (MetaScreenWindowFunc) meta_window_update_for_monitors_changed, 0);
/* Queue a resize on all the windows */
meta_screen_foreach_window (screen, META_LIST_DEFAULT, meta_screen_resize_func, 0);
meta_screen_queue_check_fullscreen (screen);
g_signal_emit (screen, screen_signals[MONITORS_CHANGED], 0);

View File

@@ -288,8 +288,7 @@ windows_on_different_monitor (MetaWindow *a,
if (a->screen != b->screen)
return TRUE;
return meta_screen_get_monitor_for_window (a->screen, a) !=
meta_screen_get_monitor_for_window (b->screen, b);
return a->monitor != b->monitor;
}
/* Get layer ignoring any transient or group relationships */
@@ -1239,24 +1238,10 @@ get_default_focus_window (MetaStack *stack,
{
/* Find the topmost, focusable, mapped, window.
* not_this_one is being unfocused or going away, so exclude it.
* Also, prefer to focus transient parent of not_this_one,
* or top window in same group as not_this_one.
*/
MetaWindow *transient_parent;
MetaWindow *topmost_in_group;
MetaWindow *topmost_overall;
MetaGroup *not_this_one_group;
GList *l;
transient_parent = NULL;
topmost_in_group = NULL;
topmost_overall = NULL;
if (not_this_one)
not_this_one_group = meta_window_get_group (not_this_one);
else
not_this_one_group = NULL;
stack_ensure_sorted (stack);
/* top of this layer is at the front of the list */
@@ -1273,49 +1258,25 @@ get_default_focus_window (MetaStack *stack,
if (window->unmaps_pending > 0)
continue;
if (window->minimized)
continue;
if (window->unmanaging)
continue;
if (!(window->input || window->take_focus))
continue;
if (workspace != NULL && !meta_window_located_on_workspace (window, workspace))
if (!meta_window_should_be_showing (window))
continue;
if (must_be_at_point && !window_contains_point (window, root_x, root_y))
continue;
if (not_this_one != NULL)
{
if (transient_parent == NULL &&
meta_window_get_transient_for (not_this_one) == window)
transient_parent = window;
if (window->type == META_WINDOW_DOCK)
continue;
if (topmost_in_group == NULL &&
not_this_one_group != NULL &&
not_this_one_group == meta_window_get_group (window))
topmost_in_group = window;
}
if (topmost_overall == NULL && window->type != META_WINDOW_DOCK)
topmost_overall = window;
/* We could try to bail out early here for efficiency in
* some cases, but it's just not worth the code.
*/
return window;
}
if (transient_parent)
return transient_parent;
else if (topmost_in_group)
return topmost_in_group;
else if (topmost_overall)
return topmost_overall;
else
return NULL;
return NULL;
}
MetaWindow*

View File

@@ -78,6 +78,7 @@ typedef enum
META_MOVE_RESIZE_RESIZE_ACTION = 1 << 3,
META_MOVE_RESIZE_WAYLAND_RESIZE = 1 << 4,
META_MOVE_RESIZE_STATE_CHANGED = 1 << 5,
META_MOVE_RESIZE_DONT_SYNC_COMPOSITOR = 1 << 6,
} MetaMoveResizeFlags;
typedef enum
@@ -434,7 +435,6 @@ struct _MetaWindow
/* Managed by delete.c */
int dialog_pid;
guint is_alive : 1;
/* maintained by group.c */
MetaGroup *group;
@@ -482,6 +482,7 @@ struct _MetaWindowClass
gboolean (*update_icon) (MetaWindow *window,
cairo_surface_t **icon,
cairo_surface_t **mini_icon);
void (*update_main_monitor) (MetaWindow *window);
void (*main_monitor_changed) (MetaWindow *window,
const MetaMonitorInfo *old);
};
@@ -695,4 +696,6 @@ void meta_window_set_alive (MetaWindow *window, gboolean is_alive);
gboolean meta_window_has_pointer (MetaWindow *window);
void meta_window_emit_size_changed (MetaWindow *window);
#endif

View File

@@ -41,7 +41,7 @@
#include <meta/prefs.h>
#include <meta/group.h>
#include "constraints.h"
#include "mutter-enum-types.h"
#include <meta/meta-enum-types.h>
#include "core.h"
#include <X11/Xatom.h>
@@ -57,7 +57,8 @@
#include "x11/xprops.h"
#ifdef HAVE_WAYLAND
#include "wayland/window-wayland.h"
#include "wayland/meta-window-wayland.h"
#include "wayland/meta-wayland-surface.h"
#include "wayland/meta-wayland-private.h"
#endif
@@ -723,6 +724,12 @@ meta_window_should_attach_to_parent (MetaWindow *window)
static gboolean
client_window_should_be_mapped (MetaWindow *window)
{
#ifdef HAVE_WAYLAND
if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND &&
!window->surface->buffer)
return FALSE;
#endif
return !window->shaded;
}
@@ -974,7 +981,8 @@ _meta_window_shared_new (MetaDisplay *display,
window->compositor_private = NULL;
window->monitor = meta_screen_get_monitor_for_window (window->screen, window);
window->monitor = meta_screen_calculate_monitor_for_window (window->screen,
window);
window->preferred_output_winsys_id = window->monitor->winsys_id;
window->tile_match = NULL;
@@ -1533,6 +1541,12 @@ meta_window_showing_on_its_workspace (MetaWindow *window)
gboolean
meta_window_should_be_showing (MetaWindow *window)
{
#ifdef HAVE_WAYLAND
if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND &&
!window->surface->buffer)
return FALSE;
#endif
/* Windows should be showing if they're located on the
* active workspace and they're showing on their own workspace. */
return (meta_window_located_on_workspace (window, window->screen->active_workspace) &&
@@ -2651,8 +2665,6 @@ meta_window_maximize (MetaWindow *window,
{
MetaRectangle *saved_rect = NULL;
gboolean maximize_horizontally, maximize_vertically;
MetaRectangle old_rect;
MetaRectangle new_rect;
g_return_if_fail (!window->override_redirect);
@@ -2702,18 +2714,23 @@ meta_window_maximize (MetaWindow *window,
directions,
saved_rect);
meta_window_get_frame_rect (window, &old_rect);
MetaRectangle old_frame_rect, old_buffer_rect, new_rect;
meta_window_get_frame_rect (window, &old_frame_rect);
meta_window_get_buffer_rect (window, &old_buffer_rect);
meta_window_move_resize_internal (window,
META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION | META_MOVE_RESIZE_STATE_CHANGED,
(META_MOVE_RESIZE_MOVE_ACTION |
META_MOVE_RESIZE_RESIZE_ACTION |
META_MOVE_RESIZE_STATE_CHANGED |
META_MOVE_RESIZE_DONT_SYNC_COMPOSITOR),
NorthWestGravity,
window->unconstrained_rect);
meta_window_get_frame_rect (window, &new_rect);
meta_compositor_maximize_window (window->display->compositor,
window,
&old_rect,
&new_rect);
meta_compositor_size_change_window (window->display->compositor, window,
META_SIZE_CHANGE_MAXIMIZE,
&old_frame_rect, &old_buffer_rect);
}
}
@@ -2873,8 +2890,6 @@ void
meta_window_tile (MetaWindow *window)
{
MetaMaximizeFlags directions;
MetaRectangle old_rect;
MetaRectangle new_rect;
/* Don't do anything if no tiling is requested */
if (window->tile_mode == META_TILE_NONE)
@@ -2888,16 +2903,8 @@ meta_window_tile (MetaWindow *window)
meta_window_maximize_internal (window, directions, NULL);
meta_screen_update_tile_preview (window->screen, FALSE);
meta_window_get_frame_rect (window, &old_rect);
meta_window_move_resize_now (window);
meta_window_get_frame_rect (window, &new_rect);
meta_compositor_maximize_window (window->display->compositor,
window,
&old_rect,
&new_rect);
if (window->frame)
meta_frame_queue_draw (window->frame);
}
@@ -2965,11 +2972,9 @@ unmaximize_window_before_freeing (MetaWindow *window)
}
}
static void
meta_window_unmaximize_internal (MetaWindow *window,
MetaMaximizeFlags directions,
MetaRectangle *desired_rect,
int gravity)
void
meta_window_unmaximize (MetaWindow *window,
MetaMaximizeFlags directions)
{
gboolean unmaximize_horizontally, unmaximize_vertically;
MetaRectangle new_rect;
@@ -2990,12 +2995,14 @@ meta_window_unmaximize_internal (MetaWindow *window,
if ((unmaximize_horizontally && window->maximized_horizontally) ||
(unmaximize_vertically && window->maximized_vertically))
{
MetaRectangle *desired_rect;
MetaRectangle target_rect;
MetaRectangle work_area;
MetaRectangle old_rect;
MetaRectangle old_frame_rect, old_buffer_rect;
meta_window_get_work_area_for_monitor (window, window->monitor->number, &work_area);
meta_window_get_frame_rect (window, &old_rect);
meta_window_get_frame_rect (window, &old_frame_rect);
meta_window_get_buffer_rect (window, &old_buffer_rect);
meta_topic (META_DEBUG_WINDOW_OPS,
"Unmaximizing %s%s\n",
@@ -3015,10 +3022,12 @@ meta_window_unmaximize_internal (MetaWindow *window,
*/
meta_window_frame_size_changed (window);
desired_rect = &window->saved_rect;
/* Unmaximize to the saved_rect position in the direction(s)
* being unmaximized.
*/
target_rect = old_rect;
target_rect = old_frame_rect;
/* Avoid unmaximizing to "almost maximized" size when the previous size
* is greater then 80% of the work area use MAX_UNMAXIMIZED_WINDOW_AREA of the work area as upper limit
@@ -3060,15 +3069,17 @@ meta_window_unmaximize_internal (MetaWindow *window,
meta_window_client_rect_to_frame_rect (window, &target_rect, &target_rect);
meta_window_move_resize_internal (window,
META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION | META_MOVE_RESIZE_STATE_CHANGED,
gravity,
(META_MOVE_RESIZE_MOVE_ACTION |
META_MOVE_RESIZE_RESIZE_ACTION |
META_MOVE_RESIZE_STATE_CHANGED |
META_MOVE_RESIZE_DONT_SYNC_COMPOSITOR),
NorthWestGravity,
target_rect);
meta_window_get_frame_rect (window, &new_rect);
meta_compositor_unmaximize_window (window->display->compositor,
window,
&old_rect,
&new_rect);
meta_compositor_size_change_window (window->display->compositor, window,
META_SIZE_CHANGE_UNMAXIMIZE,
&old_frame_rect, &old_buffer_rect);
/* When we unmaximize, if we're doing a mouse move also we could
* get the window suddenly jumping to the upper left corner of
@@ -3095,37 +3106,6 @@ meta_window_unmaximize_internal (MetaWindow *window,
g_object_thaw_notify (G_OBJECT (window));
}
void
meta_window_unmaximize (MetaWindow *window,
MetaMaximizeFlags directions)
{
meta_window_unmaximize_internal (window, directions, &window->saved_rect,
NorthWestGravity);
}
/* Like meta_window_unmaximize(), but instead of unmaximizing to the
* saved position, we give the new desired size, and the gravity that
* determines the positioning relationship between the area occupied
* maximized and the new are. The arguments are similar to
* meta_window_resize_with_gravity().
* Unlike meta_window_unmaximize(), tiling is not restored for windows
* with a tile mode other than META_TILE_NONE.
*/
static void
meta_window_unmaximize_with_gravity (MetaWindow *window,
MetaMaximizeFlags directions,
int new_width,
int new_height,
int gravity)
{
MetaRectangle desired_rect;
desired_rect.width = new_width;
desired_rect.height = new_height;
meta_window_unmaximize_internal (window, directions, &desired_rect, gravity);
}
void
meta_window_make_above (MetaWindow *window)
{
@@ -3228,6 +3208,8 @@ meta_window_unmake_fullscreen (MetaWindow *window)
window->fullscreen = FALSE;
target_rect = window->saved_rect;
meta_window_frame_size_changed (window);
/* Window's size hints may have changed while maximized, making
* saved_rect invalid. #329152
*/
@@ -3565,7 +3547,7 @@ meta_window_update_monitor (MetaWindow *window,
const MetaMonitorInfo *old;
old = window->monitor;
window->monitor = meta_screen_get_monitor_for_window (window->screen, window);
META_WINDOW_GET_CLASS (window)->update_main_monitor (window);
if (old != window->monitor)
{
meta_window_on_all_workspaces_changed (window);
@@ -3706,7 +3688,7 @@ meta_window_move_resize_internal (MetaWindow *window,
{
window->unconstrained_rect = unconstrained_rect;
if (window->known_to_compositor)
if (window->known_to_compositor && !(flags & META_MOVE_RESIZE_DONT_SYNC_COMPOSITOR))
meta_compositor_sync_window_geometry (window->display->compositor,
window,
did_placement);
@@ -4038,9 +4020,8 @@ meta_window_get_buffer_rect (const MetaWindow *window,
* @client_rect: client rectangle in root coordinates
* @frame_rect: (out): location to store the computed corresponding frame bounds.
*
* Converts a desired bounds of the client window - what is passed to meta_window_move_resize() -
* into the corresponding bounds of the window frame (excluding invisible borders
* and client side shadows.)
* Converts a desired bounds of the client window into the corresponding bounds
* of the window frame (excluding invisible borders and client side shadows.)
*/
void
meta_window_client_rect_to_frame_rect (MetaWindow *window,
@@ -4087,7 +4068,7 @@ meta_window_client_rect_to_frame_rect (MetaWindow *window,
* @client_rect: (out): location to store the computed corresponding client rectangle.
*
* Converts a desired frame bounds for a window into the bounds of the client
* window - what is passed to meta_window_move_resize().
* window.
*/
void
meta_window_frame_rect_to_client_rect (MetaWindow *window,
@@ -4634,12 +4615,7 @@ meta_window_change_workspace_by_index (MetaWindow *window,
workspace = meta_screen_append_new_workspace (screen, FALSE, CurrentTime);
if (workspace)
{
if (window->on_all_workspaces_requested)
meta_window_unstick (window);
meta_window_change_workspace (window, workspace);
}
meta_window_change_workspace (window, workspace);
}
static void
@@ -5658,7 +5634,7 @@ update_move (MetaWindow *window,
int monitor;
window->tile_mode = META_TILE_NONE;
wmonitor = meta_screen_get_monitor_for_window (window->screen, window);
wmonitor = window->monitor;
for (monitor = 0; monitor < window->screen->n_monitor_infos; monitor++)
{
@@ -5728,81 +5704,6 @@ update_move (MetaWindow *window,
meta_window_move_frame (window, TRUE, new_x, new_y);
}
/* When resizing a maximized window by using alt-middle-drag (resizing
* with the grips or the menu for a maximized window is not enabled),
* the user can "break" out of the maximized state. This checks for
* that possibility. During such a break-out resize the user can also
* return to the previous maximization state by resizing back to near
* the original size.
*/
static MetaMaximizeFlags
check_resize_unmaximize(MetaWindow *window,
int dx,
int dy)
{
int threshold;
MetaMaximizeFlags new_unmaximize;
#define DRAG_THRESHOLD_TO_RESIZE_THRESHOLD_FACTOR 3
threshold = meta_prefs_get_drag_threshold () *
DRAG_THRESHOLD_TO_RESIZE_THRESHOLD_FACTOR;
new_unmaximize = 0;
if (window->maximized_horizontally ||
window->tile_mode != META_TILE_NONE ||
(window->display->grab_resize_unmaximize & META_MAXIMIZE_HORIZONTAL) != 0)
{
int x_amount;
/* We allow breaking out of maximization in either direction, to make
* the window larger than the monitor as well as smaller than the
* monitor. If we wanted to only allow resizing smaller than the
* monitor, we'd use - dx for NE/E/SE and dx for SW/W/NW.
*/
if ((window->display->grab_op & (META_GRAB_OP_WINDOW_DIR_WEST | META_GRAB_OP_WINDOW_DIR_EAST)) != 0)
x_amount = dx < 0 ? - dx : dx;
else
x_amount = 0;
if (x_amount > threshold)
new_unmaximize |= META_MAXIMIZE_HORIZONTAL;
}
if (window->maximized_vertically ||
(window->display->grab_resize_unmaximize & META_MAXIMIZE_VERTICAL) != 0)
{
int y_amount;
if ((window->display->grab_op & (META_GRAB_OP_WINDOW_DIR_NORTH | META_GRAB_OP_WINDOW_DIR_SOUTH)) != 0)
y_amount = dy < 0 ? - dy : dy;
else
y_amount = 0;
if (y_amount > threshold)
new_unmaximize |= META_MAXIMIZE_VERTICAL;
}
/* Metacity doesn't have a full user interface for only horizontally or
* vertically maximized, so while only unmaximizing in the direction drags
* has some advantages, it will also confuse the user. So, we always
* unmaximize both ways if possible.
*/
if (new_unmaximize != 0)
{
new_unmaximize = 0;
if (window->maximized_horizontally ||
(window->display->grab_resize_unmaximize & META_MAXIMIZE_HORIZONTAL) != 0)
new_unmaximize |= META_MAXIMIZE_HORIZONTAL;
if (window->maximized_vertically ||
(window->display->grab_resize_unmaximize & META_MAXIMIZE_VERTICAL) != 0)
new_unmaximize |= META_MAXIMIZE_VERTICAL;
}
return new_unmaximize;
}
static gboolean
update_resize_timeout (gpointer data)
{
@@ -5827,7 +5728,6 @@ update_resize (MetaWindow *window,
int gravity;
MetaRectangle old;
double remaining = 0;
MetaMaximizeFlags new_unmaximize;
window->display->grab_latest_motion_x = x;
window->display->grab_latest_motion_y = y;
@@ -5874,8 +5774,6 @@ update_resize (MetaWindow *window,
meta_window_update_keyboard_resize (window, TRUE);
}
new_unmaximize = check_resize_unmaximize (window, dx, dy);
if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_EAST)
new_w += dx;
else if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_WEST)
@@ -5944,29 +5842,7 @@ update_resize (MetaWindow *window,
snap,
FALSE);
if (new_unmaximize == window->display->grab_resize_unmaximize)
{
meta_window_resize_frame_with_gravity (window, TRUE, new_w, new_h, gravity);
}
else
{
if ((new_unmaximize & ~window->display->grab_resize_unmaximize) != 0)
{
meta_window_unmaximize_with_gravity (window,
(new_unmaximize & ~window->display->grab_resize_unmaximize),
new_w, new_h, gravity);
}
if ((window->display->grab_resize_unmaximize & ~new_unmaximize))
{
MetaRectangle saved_rect = window->saved_rect;
meta_window_maximize (window,
(window->display->grab_resize_unmaximize & ~new_unmaximize));
window->saved_rect = saved_rect;
}
}
window->display->grab_resize_unmaximize = new_unmaximize;
meta_window_resize_frame_with_gravity (window, TRUE, new_w, new_h, gravity);
/* Store the latest resize time, if we actually resized. */
if (window->rect.width != old.width || window->rect.height != old.height)
@@ -6167,12 +6043,8 @@ void
meta_window_get_work_area_current_monitor (MetaWindow *window,
MetaRectangle *area)
{
const MetaMonitorInfo *monitor = NULL;
monitor = meta_screen_get_monitor_for_window (window->screen,
window);
meta_window_get_work_area_for_monitor (window,
monitor->number,
window->monitor->number,
area);
}
@@ -7977,3 +7849,9 @@ meta_window_grab_op_ended (MetaWindow *window,
{
META_WINDOW_GET_CLASS (window)->grab_op_ended (window, op);
}
void
meta_window_emit_size_changed (MetaWindow *window)
{
g_signal_emit (window, window_signals[SIZE_CHANGED], 0);
}

View File

@@ -1,5 +1,5 @@
/*** BEGIN file-header ***/
#include "mutter-enum-types.h"
#include <meta/meta-enum-types.h>
/*** END file-header ***/
/*** BEGIN file-production ***/

View File

@@ -1,6 +1,6 @@
/*** BEGIN file-header ***/
#ifndef __MUTTER_ENUM_TYPES_H__
#define __MUTTER_ENUM_TYPES_H__
#ifndef __META_ENUM_TYPES_H__
#define __META_ENUM_TYPES_H__
#include <glib-object.h>

View File

@@ -54,6 +54,11 @@ typedef enum
META_COMP_EFFECT_NONE
} MetaCompEffect;
typedef enum {
META_SIZE_CHANGE_MAXIMIZE,
META_SIZE_CHANGE_UNMAXIMIZE,
} MetaSizeChange;
MetaCompositor *meta_compositor_new (MetaDisplay *display);
void meta_compositor_destroy (MetaCompositor *compositor);
@@ -89,14 +94,11 @@ void meta_compositor_switch_workspace (MetaCompositor *compositor,
MetaWorkspace *to,
MetaMotionDirection direction);
void meta_compositor_maximize_window (MetaCompositor *compositor,
MetaWindow *window,
MetaRectangle *old_rect,
MetaRectangle *new_rect);
void meta_compositor_unmaximize_window (MetaCompositor *compositor,
MetaWindow *window,
MetaRectangle *old_rect,
MetaRectangle *new_rect);
void meta_compositor_size_change_window (MetaCompositor *compositor,
MetaWindow *window,
MetaSizeChange which_change,
MetaRectangle *old_frame_rect,
MetaRectangle *old_buffer_rect);
void meta_compositor_sync_window_geometry (MetaCompositor *compositor,
MetaWindow *window,

View File

@@ -57,6 +57,8 @@ struct _MetaBackground
MetaBackgroundPrivate *priv;
};
void meta_background_refresh_all (void);
GType meta_background_get_type (void);
MetaBackground *meta_background_new (MetaScreen *screen);

View File

@@ -55,8 +55,7 @@ struct _MetaPlugin
* MetaPluginClass:
* @start: virtual function called when the compositor starts managing a screen
* @minimize: virtual function called when a window is minimized
* @maximize: virtual function called when a window is maximized
* @unmaximize: virtual function called when a window is unmaximized
* @size_change: virtual function called when a window changes size to/from constraints
* @map: virtual function called when a window is mapped
* @destroy: virtual function called when a window is destroyed
* @switch_workspace: virtual function called when the user switches to another
@@ -103,39 +102,11 @@ struct _MetaPluginClass
void (*unminimize) (MetaPlugin *plugin,
MetaWindowActor *actor);
/**
* MetaPluginClass::maximize:
* @actor: a #MetaWindowActor
* @x: target X coordinate
* @y: target Y coordinate
* @width: target width
* @height: target height
*
* Virtual function called when the window represented by @actor is maximized.
*/
void (*maximize) (MetaPlugin *plugin,
void (*size_change) (MetaPlugin *plugin,
MetaWindowActor *actor,
gint x,
gint y,
gint width,
gint height);
/**
* MetaPluginClass::unmaximize:
* @actor: a #MetaWindowActor
* @x: target X coordinate
* @y: target Y coordinate
* @width: target width
* @height: target height
*
* Virtual function called when the window represented by @actor is unmaximized.
*/
void (*unmaximize) (MetaPlugin *plugin,
MetaWindowActor *actor,
gint x,
gint y,
gint width,
gint height);
MetaSizeChange which_change,
MetaRectangle *old_frame_rect,
MetaRectangle *old_buffer_rect);
/**
* MetaPluginClass::map:
@@ -386,12 +357,8 @@ meta_plugin_unminimize_completed (MetaPlugin *plugin,
MetaWindowActor *actor);
void
meta_plugin_maximize_completed (MetaPlugin *plugin,
MetaWindowActor *actor);
void
meta_plugin_unmaximize_completed (MetaPlugin *plugin,
MetaWindowActor *actor);
meta_plugin_size_change_completed (MetaPlugin *plugin,
MetaWindowActor *actor);
void
meta_plugin_map_completed (MetaPlugin *plugin,

View File

@@ -23,7 +23,11 @@
#ifndef __META_SHADOW_FACTORY_H__
#define __META_SHADOW_FACTORY_H__
#include <glib-object.h>
#include <cairo.h>
#include <clutter/clutter.h>
#include <meta/meta-window-shape.h>
GType meta_shadow_get_type (void) G_GNUC_CONST;
/**
* MetaShadowParams:
@@ -81,4 +85,38 @@ void meta_shadow_factory_get_params (MetaShadowFactory *factory,
gboolean focused,
MetaShadowParams *params);
/**
* MetaShadow:
* #MetaShadow holds a shadow texture along with information about how to
* apply that texture to draw a window texture. (E.g., it knows how big the
* unscaled borders are on each side of the shadow texture.)
*/
typedef struct _MetaShadow MetaShadow;
MetaShadow *meta_shadow_ref (MetaShadow *shadow);
void meta_shadow_unref (MetaShadow *shadow);
void meta_shadow_paint (MetaShadow *shadow,
int window_x,
int window_y,
int window_width,
int window_height,
guint8 opacity,
cairo_region_t *clip,
gboolean clip_strictly);
void meta_shadow_get_bounds (MetaShadow *shadow,
int window_x,
int window_y,
int window_width,
int window_height,
cairo_rectangle_int_t *bounds);
MetaShadowFactory *meta_shadow_factory_new (void);
MetaShadow *meta_shadow_factory_get_shadow (MetaShadowFactory *factory,
MetaWindowShape *shape,
int width,
int height,
const char *class_name,
gboolean focused);
#endif /* __META_SHADOW_FACTORY_H__ */

View File

@@ -62,4 +62,10 @@ MetaWindow * meta_window_actor_get_meta_window (MetaWindowActor *self
ClutterActor * meta_window_actor_get_texture (MetaWindowActor *self);
gboolean meta_window_actor_is_destroyed (MetaWindowActor *self);
typedef enum {
META_SHADOW_MODE_AUTO,
META_SHADOW_MODE_FORCED_OFF,
META_SHADOW_MODE_FORCED_ON,
} MetaShadowMode;
#endif /* META_WINDOW_ACTOR_H */

View File

@@ -24,7 +24,9 @@
#define __META_WINDOW_SHAPE_H__
#include <cairo.h>
#include <glib.h>
#include <glib-object.h>
GType meta_window_shape_get_type (void) G_GNUC_CONST;
/**
* MetaWindowShape:

View File

@@ -66,6 +66,21 @@ int meta_screen_get_active_workspace_index (MetaScreen *screen);
MetaWorkspace * meta_screen_get_active_workspace (MetaScreen *screen);
/**
* MetaScreenDirection:
* @META_SCREEN_UP: up
* @META_SCREEN_DOWN: down
* @META_SCREEN_LEFT: left
* @META_SCREEN_RIGHT: right
*/
typedef enum
{
META_SCREEN_UP,
META_SCREEN_DOWN,
META_SCREEN_LEFT,
META_SCREEN_RIGHT
} MetaScreenDirection;
int meta_screen_get_n_monitors (MetaScreen *screen);
int meta_screen_get_primary_monitor (MetaScreen *screen);
int meta_screen_get_current_monitor (MetaScreen *screen);
@@ -82,6 +97,10 @@ gboolean meta_screen_get_monitor_in_fullscreen (MetaScreen *screen,
int meta_screen_get_monitor_index_for_rect (MetaScreen *screen,
MetaRectangle *rect);
int meta_screen_get_monitor_neighbor_index (MetaScreen *screen,
int which_monitor,
MetaScreenDirection dir);
void meta_screen_focus_default_window (MetaScreen *screen,
guint32 timestamp);

View File

@@ -0,0 +1 @@
timestamp

View File

@@ -1053,6 +1053,11 @@ meta_frame_left_click_event (MetaUIFrame *frame,
}
return TRUE;
case META_FRAME_CONTROL_NONE:
/* We can get this for example when trying to resize window
* that cannot be resized (e. g. it is maximized and the theme
* currently used has borders for maximized windows), see #751884 */
return FALSE;
default:
g_assert_not_reached ();
}

View File

@@ -27,6 +27,7 @@
#include <meta/common.h>
#include <meta/types.h>
#include "theme-private.h"
#include "ui.h"
typedef enum
{
@@ -69,8 +70,6 @@ typedef enum
typedef struct _MetaFrames MetaFrames;
typedef struct _MetaFramesClass MetaFramesClass;
typedef struct _MetaUIFrame MetaUIFrame;
struct _MetaUIFrame
{
MetaFrames *frames;

View File

@@ -115,7 +115,7 @@ struct _MetaFrameGeometry
/* used for a memset hack */
#define ADDRESS_OF_BUTTON_RECTS(fgeom) (((char*)(fgeom)) + G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
#define LENGTH_OF_BUTTON_RECTS (G_STRUCT_OFFSET (MetaFrameGeometry, unstick_rect) + sizeof (GdkRectangle) - G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
#define LENGTH_OF_BUTTON_RECTS (G_STRUCT_OFFSET (MetaFrameGeometry, unstick_rect) + sizeof (MetaButtonSpace) - G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
/* The button rects (if changed adjust memset hack) */
MetaButtonSpace close_rect;

View File

@@ -121,7 +121,7 @@ meta_frame_layout_get_borders (const MetaFrameLayout *layout,
}
int
meta_theme_get_window_scaling_factor ()
meta_theme_get_window_scaling_factor (void)
{
GdkScreen *screen;
GValue value = G_VALUE_INIT;

View File

@@ -0,0 +1,34 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2015 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jonas Ådahl <jadahl@gmail.com>
*/
#ifndef META_WAYLAND_DATA_DEVICE_PRIVATE_H
#define META_WAYLAND_DATA_DEVICE_PRIVATE_H
#define META_TYPE_WAYLAND_DATA_SOURCE_WAYLAND (meta_wayland_data_source_wayland_get_type ())
G_DECLARE_FINAL_TYPE (MetaWaylandDataSourceWayland,
meta_wayland_data_source_wayland,
META, WAYLAND_DATA_SOURCE_WAYLAND,
MetaWaylandDataSource);
#endif /* META_WAYLAND_DATA_DEVICE_PRIVATE_H */

View File

@@ -31,24 +31,44 @@
#include <glib.h>
#include "meta-wayland-data-device.h"
#include "meta-wayland-data-device-private.h"
#include "meta-wayland-seat.h"
#include "meta-wayland-pointer.h"
#include "meta-wayland-private.h"
#include "meta-dnd-actor-private.h"
typedef struct
struct _MetaWaylandDataOffer
{
struct wl_resource *resource;
MetaWaylandDataSource *source;
struct wl_listener source_destroy_listener;
} MetaWaylandDataOffer;
};
struct _MetaWaylandDataSource
typedef struct _MetaWaylandDataSourcePrivate
{
struct wl_resource *resource;
struct wl_array mime_types;
gboolean has_target;
};
} MetaWaylandDataSourcePrivate;
typedef struct _MetaWaylandDataSourceWayland
{
MetaWaylandDataSource parent;
struct wl_resource *resource;
} MetaWaylandDataSourceWayland;
GType meta_wayland_data_source_wayland_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandDataSource, meta_wayland_data_source,
G_TYPE_OBJECT);
G_DEFINE_TYPE (MetaWaylandDataSourceWayland, meta_wayland_data_source_wayland,
META_TYPE_WAYLAND_DATA_SOURCE);
static MetaWaylandDataSource *
meta_wayland_data_source_wayland_new (struct wl_resource *resource);
static void
drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was);
static void
unbind_resource (struct wl_resource *resource)
@@ -56,6 +76,55 @@ unbind_resource (struct wl_resource *resource)
wl_list_remove (wl_resource_get_link (resource));
}
static void
meta_wayland_data_source_target (MetaWaylandDataSource *source,
const char *mime_type)
{
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->target (source, mime_type);
}
void
meta_wayland_data_source_send (MetaWaylandDataSource *source,
const char *mime_type,
int fd)
{
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->send (source, mime_type, fd);
}
gboolean
meta_wayland_data_source_has_target (MetaWaylandDataSource *source)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
return priv->has_target;
}
void
meta_wayland_data_source_set_has_target (MetaWaylandDataSource *source,
gboolean has_target)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
priv->has_target = has_target;
}
struct wl_array *
meta_wayland_data_source_get_mime_types (const MetaWaylandDataSource *source)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
return &priv->mime_types;
}
static void
meta_wayland_data_source_cancel (MetaWaylandDataSource *source)
{
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->cancel (source);
}
static void
data_offer_accept (struct wl_client *client,
struct wl_resource *resource,
@@ -70,8 +139,9 @@ data_offer_accept (struct wl_client *client,
if (offer->source)
{
wl_data_source_send_target (offer->source->resource, mime_type);
offer->source->has_target = mime_type != NULL;
meta_wayland_data_source_target (offer->source, mime_type);
meta_wayland_data_source_set_has_target (offer->source,
mime_type != NULL);
}
}
@@ -82,9 +152,9 @@ data_offer_receive (struct wl_client *client, struct wl_resource *resource,
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
if (offer->source)
wl_data_source_send_send (offer->source->resource, mime_type, fd);
close (fd);
meta_wayland_data_source_send (offer->source, mime_type, fd);
else
close (fd);
}
static void
@@ -105,38 +175,34 @@ destroy_data_offer (struct wl_resource *resource)
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
if (offer->source)
wl_list_remove (&offer->source_destroy_listener.link);
g_object_remove_weak_pointer (G_OBJECT (offer->source),
(gpointer *)&offer->source);
g_slice_free (MetaWaylandDataOffer, offer);
}
static void
destroy_offer_data_source (struct wl_listener *listener, void *data)
{
MetaWaylandDataOffer *offer;
offer = wl_container_of (listener, offer, source_destroy_listener);
offer->source = NULL;
}
static struct wl_resource *
meta_wayland_data_source_send_offer (MetaWaylandDataSource *source,
struct wl_resource *target)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
MetaWaylandDataOffer *offer = g_slice_new0 (MetaWaylandDataOffer);
char **p;
offer->source = source;
offer->source_destroy_listener.notify = destroy_offer_data_source;
offer->resource = wl_resource_create (wl_resource_get_client (target), &wl_data_offer_interface, wl_resource_get_version (target), 0);
wl_resource_set_implementation (offer->resource, &data_offer_interface, offer, destroy_data_offer);
wl_resource_add_destroy_listener (source->resource, &offer->source_destroy_listener);
g_object_add_weak_pointer (G_OBJECT (source), (gpointer *)&offer->source);
offer->resource = wl_resource_create (wl_resource_get_client (target),
&wl_data_offer_interface,
wl_resource_get_version (target), 0);
wl_resource_set_implementation (offer->resource,
&data_offer_interface,
offer,
destroy_data_offer);
wl_data_device_send_data_offer (target, offer->resource);
wl_array_for_each (p, &source->mime_types)
wl_array_for_each (p, &priv->mime_types)
wl_data_offer_send_offer (offer->resource, *p);
return offer->resource;
@@ -147,12 +213,8 @@ data_source_offer (struct wl_client *client,
struct wl_resource *resource, const char *type)
{
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
char **p;
p = wl_array_add (&source->mime_types, sizeof *p);
if (p)
*p = strdup (type);
if (!p || !*p)
if (!meta_wayland_data_source_add_mime_type (source, type))
wl_resource_post_no_memory (resource);
}
@@ -181,7 +243,6 @@ struct _MetaWaylandDragGrab {
struct wl_listener drag_icon_listener;
MetaWaylandDataSource *drag_data_source;
struct wl_listener drag_data_source_listener;
ClutterActor *feedback_actor;
@@ -199,26 +260,20 @@ destroy_drag_focus (struct wl_listener *listener, void *data)
grab->drag_focus_data_device = NULL;
}
static void
drag_grab_focus (MetaWaylandPointerGrab *grab,
MetaWaylandSurface *surface)
void
meta_wayland_drag_grab_set_focus (MetaWaylandDragGrab *drag_grab,
MetaWaylandSurface *surface)
{
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
MetaWaylandSeat *seat = drag_grab->seat;
struct wl_client *client;
struct wl_resource *data_device_resource, *offer = NULL;
struct wl_display *display;
guint32 serial;
wl_fixed_t sx, sy;
if (drag_grab->drag_focus == surface)
return;
if (drag_grab->drag_focus_data_device)
if (drag_grab->drag_focus)
{
wl_data_device_send_leave (drag_grab->drag_focus_data_device);
wl_list_remove (&drag_grab->drag_focus_listener.link);
drag_grab->drag_focus_data_device = NULL;
meta_wayland_surface_drag_dest_focus_out (drag_grab->drag_focus);
drag_grab->drag_focus = NULL;
}
@@ -232,25 +287,31 @@ drag_grab_focus (MetaWaylandPointerGrab *grab,
client = wl_resource_get_client (surface->resource);
data_device_resource = wl_resource_find_for_client (&seat->data_device.resource_list, client);
if (!data_device_resource)
return;
display = wl_client_get_display (client);
serial = wl_display_next_serial (display);
if (drag_grab->drag_data_source)
if (drag_grab->drag_data_source && data_device_resource)
offer = meta_wayland_data_source_send_offer (drag_grab->drag_data_source,
data_device_resource);
meta_wayland_pointer_get_relative_coordinates (grab->pointer, surface, &sx, &sy);
wl_data_device_send_enter (data_device_resource, serial, surface->resource,
sx, sy, offer);
drag_grab->drag_focus = surface;
drag_grab->drag_focus_data_device = data_device_resource;
drag_grab->drag_focus_listener.notify = destroy_drag_focus;
wl_resource_add_destroy_listener (data_device_resource, &drag_grab->drag_focus_listener);
meta_wayland_surface_drag_dest_focus_in (drag_grab->drag_focus,
offer ? wl_resource_get_user_data (offer) : NULL);
}
MetaWaylandSurface *
meta_wayland_drag_grab_get_focus (MetaWaylandDragGrab *drag_grab)
{
return drag_grab->drag_focus;
}
static void
drag_grab_focus (MetaWaylandPointerGrab *grab,
MetaWaylandSurface *surface)
{
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
meta_wayland_drag_grab_set_focus (drag_grab, surface);
}
static void
@@ -258,17 +319,9 @@ drag_grab_motion (MetaWaylandPointerGrab *grab,
const ClutterEvent *event)
{
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
wl_fixed_t sx, sy;
if (drag_grab->drag_focus_data_device)
{
meta_wayland_pointer_get_relative_coordinates (grab->pointer,
drag_grab->drag_focus,
&sx, &sy);
wl_data_device_send_motion (drag_grab->drag_focus_data_device,
clutter_event_get_time (event),
sx, sy);
}
if (drag_grab->drag_focus)
meta_wayland_surface_drag_dest_motion (drag_grab->drag_focus, event);
if (drag_grab->drag_surface)
meta_feedback_actor_update (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
@@ -278,6 +331,8 @@ drag_grab_motion (MetaWaylandPointerGrab *grab,
static void
data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
{
meta_wayland_drag_grab_set_focus (drag_grab, NULL);
if (drag_grab->drag_origin)
{
drag_grab->drag_origin = NULL;
@@ -291,10 +346,9 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
}
if (drag_grab->drag_data_source)
{
drag_grab->drag_data_source->has_target = FALSE;
wl_list_remove (&drag_grab->drag_data_source_listener.link);
}
g_object_weak_unref (G_OBJECT (drag_grab->drag_data_source),
drag_grab_data_source_destroyed,
drag_grab);
if (drag_grab->feedback_actor)
{
@@ -304,8 +358,6 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
drag_grab->seat->data_device.current_grab = NULL;
drag_grab_focus (&drag_grab->generic, NULL);
meta_wayland_pointer_end_grab (drag_grab->generic.pointer);
g_slice_free (MetaWaylandDragGrab, drag_grab);
}
@@ -323,10 +375,9 @@ drag_grab_button (MetaWaylandPointerGrab *grab,
{
gboolean success = FALSE;
if (drag_grab->drag_focus_data_device &&
drag_grab->drag_data_source->has_target)
if (meta_wayland_data_source_has_target (drag_grab->drag_data_source))
{
wl_data_device_send_drop (drag_grab->drag_focus_data_device);
meta_wayland_surface_drag_dest_drop (drag_grab->drag_focus);
success = TRUE;
}
@@ -355,23 +406,24 @@ destroy_data_device_origin (struct wl_listener *listener, void *data)
drag_grab->drag_origin = NULL;
data_device_end_drag_grab (drag_grab);
meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device, NULL);
}
static void
destroy_data_device_source (struct wl_listener *listener, void *data)
drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was)
{
MetaWaylandDragGrab *drag_grab =
wl_container_of (listener, drag_grab, drag_data_source_listener);
MetaWaylandDragGrab *drag_grab = data;
drag_grab->drag_data_source = NULL;
data_device_end_drag_grab (drag_grab);
meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device, NULL);
}
static void
destroy_data_device_icon (struct wl_listener *listener, void *data)
{
MetaWaylandDragGrab *drag_grab =
wl_container_of (listener, drag_grab, drag_data_source_listener);
wl_container_of (listener, drag_grab, drag_icon_listener);
drag_grab->drag_surface = NULL;
@@ -379,6 +431,76 @@ destroy_data_device_icon (struct wl_listener *listener, void *data)
clutter_actor_remove_all_children (drag_grab->feedback_actor);
}
void
meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data_device,
struct wl_client *client,
const MetaWaylandPointerGrabInterface *funcs,
MetaWaylandSurface *surface,
MetaWaylandDataSource *source,
MetaWaylandSurface *icon_surface)
{
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
MetaWaylandDragGrab *drag_grab;
ClutterPoint pos, stage_pos;
data_device->current_grab = drag_grab = g_slice_new0 (MetaWaylandDragGrab);
drag_grab->generic.interface = funcs;
drag_grab->generic.pointer = &seat->pointer;
drag_grab->drag_client = client;
drag_grab->seat = seat;
drag_grab->drag_origin = surface;
drag_grab->drag_origin_listener.notify = destroy_data_device_origin;
wl_resource_add_destroy_listener (surface->resource,
&drag_grab->drag_origin_listener);
clutter_input_device_get_coords (seat->pointer.device, NULL, &pos);
clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface->surface_actor)),
pos.x, pos.y, &stage_pos.x, &stage_pos.y);
drag_grab->drag_start_x = stage_pos.x;
drag_grab->drag_start_y = stage_pos.y;
g_object_weak_ref (G_OBJECT (source),
drag_grab_data_source_destroyed,
drag_grab);
drag_grab->drag_data_source = source;
meta_wayland_data_device_set_dnd_source (data_device,
drag_grab->drag_data_source);
if (icon_surface)
{
drag_grab->drag_surface = icon_surface;
drag_grab->drag_icon_listener.notify = destroy_data_device_icon;
wl_resource_add_destroy_listener (icon_surface->resource,
&drag_grab->drag_icon_listener);
drag_grab->feedback_actor = meta_dnd_actor_new (CLUTTER_ACTOR (drag_grab->drag_origin->surface_actor),
drag_grab->drag_start_x,
drag_grab->drag_start_y);
meta_feedback_actor_set_anchor (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
-drag_grab->drag_surface->offset_x,
-drag_grab->drag_surface->offset_y);
clutter_actor_add_child (drag_grab->feedback_actor,
CLUTTER_ACTOR (drag_grab->drag_surface->surface_actor));
meta_feedback_actor_set_position (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
pos.x, pos.y);
}
meta_wayland_pointer_start_grab (&seat->pointer, (MetaWaylandPointerGrab*) drag_grab);
}
void
meta_wayland_data_device_end_drag (MetaWaylandDataDevice *data_device)
{
if (data_device->current_grab)
data_device_end_drag_grab (data_device->current_grab);
}
static void
data_device_start_drag (struct wl_client *client,
struct wl_resource *resource,
@@ -388,9 +510,8 @@ data_device_start_drag (struct wl_client *client,
{
MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
MetaWaylandSurface *surface = NULL;
MetaWaylandDragGrab *drag_grab;
ClutterPoint pos;
MetaWaylandSurface *surface = NULL, *icon_surface = NULL;
MetaWaylandDataSource *drag_source = NULL;
if (origin_resource)
surface = wl_resource_get_user_data (origin_resource);
@@ -410,69 +531,28 @@ data_device_start_drag (struct wl_client *client,
seat->pointer.grab != &seat->pointer.default_grab)
return;
if (icon_resource)
icon_surface = wl_resource_get_user_data (icon_resource);
if (source_resource)
drag_source = wl_resource_get_user_data (source_resource);
if (icon_resource &&
meta_wayland_surface_set_role (wl_resource_get_user_data (icon_resource),
meta_wayland_surface_set_role (icon_surface,
META_WAYLAND_SURFACE_ROLE_DND,
resource,
WL_DATA_DEVICE_ERROR_ROLE) != 0)
return;
data_device->current_grab = drag_grab = g_slice_new0 (MetaWaylandDragGrab);
drag_grab->generic.interface = &drag_grab_interface;
drag_grab->generic.pointer = &seat->pointer;
drag_grab->drag_client = client;
drag_grab->seat = seat;
drag_grab->drag_origin = surface;
drag_grab->drag_origin_listener.notify = destroy_data_device_origin;
wl_resource_add_destroy_listener (origin_resource,
&drag_grab->drag_origin_listener);
clutter_input_device_get_coords (seat->pointer.device, NULL, &pos);
clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface->surface_actor)),
pos.x, pos.y, &pos.x, &pos.y);
drag_grab->drag_start_x = pos.x;
drag_grab->drag_start_y = pos.y;
if (source_resource)
{
drag_grab->drag_data_source = wl_resource_get_user_data (source_resource);
drag_grab->drag_data_source_listener.notify = destroy_data_device_source;
wl_resource_add_destroy_listener (source_resource,
&drag_grab->drag_data_source_listener);
}
if (icon_resource)
{
drag_grab->drag_surface = wl_resource_get_user_data (icon_resource);
drag_grab->drag_icon_listener.notify = destroy_data_device_icon;
wl_resource_add_destroy_listener (icon_resource,
&drag_grab->drag_icon_listener);
drag_grab->feedback_actor = meta_dnd_actor_new (CLUTTER_ACTOR (drag_grab->drag_origin->surface_actor),
drag_grab->drag_start_x,
drag_grab->drag_start_y);
meta_feedback_actor_set_anchor (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
-drag_grab->drag_surface->offset_x,
-drag_grab->drag_surface->offset_y);
clutter_actor_add_child (drag_grab->feedback_actor,
CLUTTER_ACTOR (drag_grab->drag_surface->surface_actor));
clutter_input_device_get_coords (seat->pointer.device, NULL, &pos);
meta_feedback_actor_set_position (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
pos.x, pos.y);
}
meta_wayland_pointer_set_focus (&seat->pointer, NULL);
meta_wayland_pointer_start_grab (&seat->pointer, (MetaWaylandPointerGrab*)drag_grab);
meta_wayland_data_device_start_drag (data_device, client,
&drag_grab_interface,
surface, drag_source, icon_surface);
}
static void
destroy_selection_data_source (struct wl_listener *listener, void *data)
selection_data_source_destroyed (gpointer data, GObject *object_was_here)
{
MetaWaylandDataDevice *data_device = wl_container_of (listener, data_device, selection_data_source_listener);
MetaWaylandDataDevice *data_device = data;
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
struct wl_resource *data_device_resource;
struct wl_client *focus_client = NULL;
@@ -489,6 +569,190 @@ destroy_selection_data_source (struct wl_listener *listener, void *data)
}
static void
meta_wayland_source_send (MetaWaylandDataSource *source,
const gchar *mime_type,
gint fd)
{
MetaWaylandDataSourceWayland *source_wayland =
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
wl_data_source_send_send (source_wayland->resource, mime_type, fd);
close (fd);
}
static void
meta_wayland_source_target (MetaWaylandDataSource *source,
const gchar *mime_type)
{
MetaWaylandDataSourceWayland *source_wayland =
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
wl_data_source_send_target (source_wayland->resource, mime_type);
}
static void
meta_wayland_source_cancel (MetaWaylandDataSource *source)
{
MetaWaylandDataSourceWayland *source_wayland =
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
wl_data_source_send_cancelled (source_wayland->resource);
}
static void
meta_wayland_source_finalize (GObject *object)
{
G_OBJECT_CLASS (meta_wayland_data_source_parent_class)->finalize (object);
}
static void
meta_wayland_data_source_wayland_init (MetaWaylandDataSourceWayland *source_wayland)
{
}
static void
meta_wayland_data_source_wayland_class_init (MetaWaylandDataSourceWaylandClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
MetaWaylandDataSourceClass *data_source_class =
META_WAYLAND_DATA_SOURCE_CLASS (klass);
object_class->finalize = meta_wayland_source_finalize;
data_source_class->send = meta_wayland_source_send;
data_source_class->target = meta_wayland_source_target;
data_source_class->cancel = meta_wayland_source_cancel;
}
static void
meta_wayland_data_source_finalize (GObject *object)
{
MetaWaylandDataSource *source = META_WAYLAND_DATA_SOURCE (object);
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
char **pos;
wl_array_for_each (pos, &priv->mime_types)
g_free (*pos);
wl_array_release (&priv->mime_types);
G_OBJECT_CLASS (meta_wayland_data_source_parent_class)->finalize (object);
}
static void
meta_wayland_data_source_init (MetaWaylandDataSource *source)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
wl_array_init (&priv->mime_types);
}
static void
meta_wayland_data_source_class_init (MetaWaylandDataSourceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_wayland_data_source_finalize;
}
static void
meta_wayland_drag_dest_focus_in (MetaWaylandDataDevice *data_device,
MetaWaylandSurface *surface,
MetaWaylandDataOffer *offer)
{
MetaWaylandDragGrab *grab = data_device->current_grab;
struct wl_display *display;
struct wl_client *client;
wl_fixed_t sx, sy;
if (!grab->drag_focus_data_device)
return;
client = wl_resource_get_client (surface->resource);
display = wl_client_get_display (client);
grab->drag_focus_listener.notify = destroy_drag_focus;
wl_resource_add_destroy_listener (grab->drag_focus_data_device,
&grab->drag_focus_listener);
meta_wayland_pointer_get_relative_coordinates (grab->generic.pointer,
surface, &sx, &sy);
wl_data_device_send_enter (grab->drag_focus_data_device,
wl_display_next_serial (display),
surface->resource, sx, sy, offer->resource);
}
static void
meta_wayland_drag_dest_focus_out (MetaWaylandDataDevice *data_device,
MetaWaylandSurface *surface)
{
MetaWaylandDragGrab *grab = data_device->current_grab;
if (grab->drag_focus_data_device)
wl_data_device_send_leave (grab->drag_focus_data_device);
wl_list_remove (&grab->drag_focus_listener.link);
grab->drag_focus_data_device = NULL;
}
static void
meta_wayland_drag_dest_motion (MetaWaylandDataDevice *data_device,
MetaWaylandSurface *surface,
const ClutterEvent *event)
{
MetaWaylandDragGrab *grab = data_device->current_grab;
wl_fixed_t sx, sy;
meta_wayland_pointer_get_relative_coordinates (grab->generic.pointer,
grab->drag_focus,
&sx, &sy);
wl_data_device_send_motion (grab->drag_focus_data_device,
clutter_event_get_time (event),
sx, sy);
}
static void
meta_wayland_drag_dest_drop (MetaWaylandDataDevice *data_device,
MetaWaylandSurface *surface)
{
MetaWaylandDragGrab *grab = data_device->current_grab;
wl_data_device_send_drop (grab->drag_focus_data_device);
}
static const MetaWaylandDragDestFuncs meta_wayland_drag_dest_funcs = {
meta_wayland_drag_dest_focus_in,
meta_wayland_drag_dest_focus_out,
meta_wayland_drag_dest_motion,
meta_wayland_drag_dest_drop
};
const MetaWaylandDragDestFuncs *
meta_wayland_data_device_get_drag_dest_funcs (void)
{
return &meta_wayland_drag_dest_funcs;
}
void
meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_device,
MetaWaylandDataSource *source)
{
if (data_device->dnd_data_source == source)
return;
if (data_device->dnd_data_source)
g_object_remove_weak_pointer (G_OBJECT (source),
(gpointer *)&data_device->dnd_data_source);
data_device->dnd_data_source = source;
g_object_add_weak_pointer (G_OBJECT (source),
(gpointer *)&data_device->dnd_data_source);
wl_signal_emit (&data_device->dnd_ownership_signal, source);
}
void
meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
MetaWaylandDataSource *source,
guint32 serial)
@@ -503,8 +767,10 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
if (data_device->selection_data_source)
{
wl_data_source_send_cancelled (data_device->selection_data_source->resource);
wl_list_remove (&data_device->selection_data_source_listener.link);
meta_wayland_data_source_cancel (data_device->selection_data_source);
g_object_weak_unref (G_OBJECT (data_device->selection_data_source),
selection_data_source_destroyed,
data_device);
data_device->selection_data_source = NULL;
}
@@ -531,9 +797,12 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
if (source)
{
data_device->selection_data_source_listener.notify = destroy_selection_data_source;
wl_resource_add_destroy_listener (source->resource, &data_device->selection_data_source_listener);
g_object_weak_ref (G_OBJECT (source),
selection_data_source_destroyed,
data_device);
}
wl_signal_emit (&data_device->selection_ownership_signal, source);
}
static void
@@ -545,10 +814,10 @@ data_device_set_selection (struct wl_client *client,
MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
MetaWaylandDataSource *source;
if (!source_resource)
return;
source = wl_resource_get_user_data (source_resource);
if (source_resource)
source = wl_resource_get_user_data (source_resource);
else
source = NULL;
/* FIXME: Store serial and check against incoming serial here. */
meta_wayland_data_device_set_selection (data_device, source, serial);
@@ -569,26 +838,21 @@ static const struct wl_data_device_interface data_device_interface = {
static void
destroy_data_source (struct wl_resource *resource)
{
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
char **p;
MetaWaylandDataSourceWayland *source = wl_resource_get_user_data (resource);
wl_array_for_each (p, &source->mime_types) free (*p);
wl_array_release (&source->mime_types);
g_slice_free (MetaWaylandDataSource, source);
source->resource = NULL;
g_object_unref (source);
}
static void
create_data_source (struct wl_client *client,
struct wl_resource *resource, guint32 id)
{
MetaWaylandDataSource *source = g_slice_new0 (MetaWaylandDataSource);
struct wl_resource *source_resource;
source->resource = wl_resource_create (client, &wl_data_source_interface, wl_resource_get_version (resource), id);
wl_resource_set_implementation (source->resource, &data_source_interface, source, destroy_data_source);
wl_array_init (&source->mime_types);
source_resource = wl_resource_create (client, &wl_data_source_interface,
wl_resource_get_version (resource), id);
meta_wayland_data_source_wayland_new (source_resource);
}
static void
@@ -632,6 +896,8 @@ void
meta_wayland_data_device_init (MetaWaylandDataDevice *data_device)
{
wl_list_init (&data_device->resource_list);
wl_signal_init (&data_device->selection_ownership_signal);
wl_signal_init (&data_device->dnd_ownership_signal);
}
void
@@ -656,6 +922,8 @@ meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device)
offer = meta_wayland_data_source_send_offer (source, data_device_resource);
wl_data_device_send_selection (data_device_resource, offer);
}
else
wl_data_device_send_selection (data_device_resource, NULL);
}
gboolean
@@ -683,3 +951,52 @@ meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device)
-drag_grab->drag_surface->offset_x,
-drag_grab->drag_surface->offset_y);
}
gboolean
meta_wayland_data_source_has_mime_type (const MetaWaylandDataSource *source,
const gchar *mime_type)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
gchar **p;
wl_array_for_each (p, &priv->mime_types)
{
if (g_strcmp0 (mime_type, *p) == 0)
return TRUE;
}
return FALSE;
}
static MetaWaylandDataSource *
meta_wayland_data_source_wayland_new (struct wl_resource *resource)
{
MetaWaylandDataSourceWayland *source_wayland =
g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_WAYLAND, NULL);
source_wayland->resource = resource;
wl_resource_set_implementation (resource, &data_source_interface,
source_wayland, destroy_data_source);
return META_WAYLAND_DATA_SOURCE (source_wayland);
}
gboolean
meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source,
const gchar *mime_type)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
gchar **pos;
pos = wl_array_add (&priv->mime_types, sizeof (*pos));
if (pos)
{
*pos = g_strdup (mime_type);
return *pos != NULL;
}
return FALSE;
}

View File

@@ -24,20 +24,44 @@
#define META_WAYLAND_DATA_DEVICE_H
#include <wayland-server.h>
#include <glib-object.h>
#include "meta-wayland-types.h"
typedef struct _MetaWaylandDragGrab MetaWaylandDragGrab;
typedef struct _MetaWaylandDataSourceFuncs MetaWaylandDataSourceFuncs;
#define META_TYPE_WAYLAND_DATA_SOURCE (meta_wayland_data_source_get_type ())
G_DECLARE_DERIVABLE_TYPE (MetaWaylandDataSource, meta_wayland_data_source,
META, WAYLAND_DATA_SOURCE, GObject);
struct _MetaWaylandDataSourceClass
{
GObjectClass parent_class;
void (* send) (MetaWaylandDataSource *source,
const gchar *mime_type,
gint fd);
void (* target) (MetaWaylandDataSource *source,
const gchar *mime_type);
void (* cancel) (MetaWaylandDataSource *source);
};
struct _MetaWaylandDataDevice
{
uint32_t selection_serial;
MetaWaylandDataSource *selection_data_source;
MetaWaylandDataSource *dnd_data_source;
struct wl_listener selection_data_source_listener;
struct wl_list resource_list;
MetaWaylandDragGrab *current_grab;
struct wl_signal selection_ownership_signal;
struct wl_signal dnd_ownership_signal;
};
GType meta_wayland_data_source_get_type (void) G_GNUC_CONST;
void meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor);
void meta_wayland_data_device_init (MetaWaylandDataDevice *data_device);
@@ -48,4 +72,45 @@ gboolean meta_wayland_data_device_is_dnd_surface (MetaWaylandDataDevice *data_de
MetaWaylandSurface *surface);
void meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device);
void meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_device,
MetaWaylandDataSource *source);
void meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
MetaWaylandDataSource *source,
guint32 serial);
gboolean meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source,
const gchar *mime_type);
gboolean meta_wayland_data_source_has_mime_type (const MetaWaylandDataSource *source,
const gchar *mime_type);
struct wl_array *
meta_wayland_data_source_get_mime_types (const MetaWaylandDataSource *source);
gboolean meta_wayland_data_source_has_target (MetaWaylandDataSource *source);
void meta_wayland_data_source_set_has_target (MetaWaylandDataSource *source,
gboolean has_target);
void meta_wayland_data_source_send (MetaWaylandDataSource *source,
const gchar *mime_type,
gint fd);
const MetaWaylandDragDestFuncs *
meta_wayland_data_device_get_drag_dest_funcs (void);
void meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data_device,
struct wl_client *client,
const MetaWaylandPointerGrabInterface *funcs,
MetaWaylandSurface *surface,
MetaWaylandDataSource *source,
MetaWaylandSurface *icon_surface);
void meta_wayland_data_device_end_drag (MetaWaylandDataDevice *data_device);
void meta_wayland_drag_grab_set_focus (MetaWaylandDragGrab *drag_grab,
MetaWaylandSurface *surface);
MetaWaylandSurface *
meta_wayland_drag_grab_get_focus (MetaWaylandDragGrab *drag_grab);
#endif /* META_WAYLAND_DATA_DEVICE_H */

View File

@@ -411,6 +411,11 @@ meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
void
meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
{
MetaBackend *backend = meta_get_backend ();
g_signal_handlers_disconnect_by_func (backend, on_keymap_changed, keyboard);
g_signal_handlers_disconnect_by_func (backend, on_keymap_layout_group_changed, keyboard);
meta_wayland_keyboard_set_focus (keyboard, NULL);
meta_wayland_xkb_info_destroy (&keyboard->xkb_info);

View File

@@ -31,14 +31,15 @@
#include <string.h>
typedef struct {
MetaOutput *output;
struct wl_global *global;
int x, y;
enum wl_output_transform transform;
enum {
OUTPUT_DESTROYED,
GList *resources;
} MetaWaylandOutput;
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE (MetaWaylandOutput, meta_wayland_output, G_TYPE_OBJECT)
static void
output_resource_destroy (struct wl_resource *res)
@@ -46,6 +47,9 @@ output_resource_destroy (struct wl_resource *res)
MetaWaylandOutput *wayland_output;
wayland_output = wl_resource_get_user_data (res);
if (!wayland_output)
return;
wayland_output->resources = g_list_remove (wayland_output->resources, res);
}
@@ -56,9 +60,10 @@ bind_output (struct wl_client *client,
guint32 id)
{
MetaWaylandOutput *wayland_output = data;
MetaOutput *output = wayland_output->output;
MetaMonitorInfo *monitor_info = wayland_output->monitor_info;
struct wl_resource *resource;
guint mode_flags;
MetaOutput *output = monitor_info->outputs[0];
resource = wl_resource_create (client, &wl_output_interface, version, id);
wayland_output->resources = g_list_prepend (wayland_output->resources, resource);
@@ -66,17 +71,17 @@ bind_output (struct wl_client *client,
wl_resource_set_user_data (resource, wayland_output);
wl_resource_set_destructor (resource, output_resource_destroy);
meta_verbose ("Binding output %p/%s (%u, %u, %u, %u) x %f\n",
output, output->name,
output->crtc->rect.x, output->crtc->rect.y,
output->crtc->rect.width, output->crtc->rect.height,
output->crtc->current_mode->refresh_rate);
meta_verbose ("Binding monitor %p/%s (%u, %u, %u, %u) x %f\n",
monitor_info, output->name,
monitor_info->rect.x, monitor_info->rect.y,
monitor_info->rect.width, monitor_info->rect.height,
monitor_info->refresh_rate);
wl_output_send_geometry (resource,
(int)output->crtc->rect.x,
(int)output->crtc->rect.y,
output->width_mm,
output->height_mm,
(int)monitor_info->rect.x,
(int)monitor_info->rect.y,
monitor_info->width_mm,
monitor_info->height_mm,
/* Cogl values reflect XRandR values,
and so does wayland */
output->subpixel_order,
@@ -92,9 +97,9 @@ bind_output (struct wl_client *client,
wl_output_send_mode (resource,
mode_flags,
(int)output->crtc->current_mode->width,
(int)output->crtc->current_mode->height,
(int)output->crtc->current_mode->refresh_rate);
(int)monitor_info->rect.width,
(int)monitor_info->rect.height,
(int)monitor_info->refresh_rate);
if (version >= WL_OUTPUT_SCALE_SINCE_VERSION)
wl_output_send_scale (resource, output->scale);
@@ -107,16 +112,9 @@ static void
wayland_output_destroy_notify (gpointer data)
{
MetaWaylandOutput *wayland_output = data;
GList *resources;
/* Make sure the destructors don't mess with the list */
resources = wayland_output->resources;
wayland_output->resources = NULL;
wl_global_destroy (wayland_output->global);
g_list_free (resources);
g_slice_free (MetaWaylandOutput, wayland_output);
g_signal_emit (wayland_output, signals[OUTPUT_DESTROYED], 0);
g_object_unref (wayland_output);
}
static inline enum wl_output_transform
@@ -128,14 +126,13 @@ wl_output_transform_from_meta_monitor_transform (MetaMonitorTransform transform)
static void
wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
MetaOutput *output)
MetaMonitorInfo *monitor_info)
{
GList *iter;
guint mode_flags;
MetaOutput *output = monitor_info->outputs[0];
enum wl_output_transform wl_transform = wl_output_transform_from_meta_monitor_transform (output->crtc->transform);
g_assert (output->crtc->current_mode != NULL);
mode_flags = WL_OUTPUT_MODE_CURRENT;
if (output->crtc->current_mode == output->preferred_mode)
mode_flags |= WL_OUTPUT_MODE_PREFERRED;
@@ -144,15 +141,15 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
{
struct wl_resource *resource = iter->data;
if (wayland_output->x != output->crtc->rect.x ||
wayland_output->y != output->crtc->rect.y ||
if (wayland_output->x != monitor_info->rect.x ||
wayland_output->y != monitor_info->rect.y ||
wayland_output->transform != wl_transform)
{
wl_output_send_geometry (resource,
(int)output->crtc->rect.x,
(int)output->crtc->rect.y,
output->width_mm,
output->height_mm,
(int)monitor_info->rect.x,
(int)monitor_info->rect.y,
monitor_info->width_mm,
monitor_info->height_mm,
output->subpixel_order,
output->vendor,
output->product,
@@ -161,59 +158,63 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
wl_output_send_mode (resource,
mode_flags,
(int)output->crtc->current_mode->width,
(int)output->crtc->current_mode->height,
(int)output->crtc->current_mode->refresh_rate);
(int)monitor_info->rect.width,
(int)monitor_info->rect.height,
(int)monitor_info->refresh_rate);
}
/* It's very important that we change the output pointer here, as
the old structure is about to be freed by MetaMonitorManager */
wayland_output->output = output;
wayland_output->x = output->crtc->rect.x;
wayland_output->y = output->crtc->rect.y;
wayland_output->monitor_info = monitor_info;
wayland_output->x = monitor_info->rect.x;
wayland_output->y = monitor_info->rect.y;
wayland_output->transform = wl_transform;
}
static MetaWaylandOutput *
meta_wayland_output_new (MetaWaylandCompositor *compositor)
{
MetaWaylandOutput *wayland_output;
wayland_output = g_object_new (META_TYPE_WAYLAND_OUTPUT, NULL);
wayland_output->global = wl_global_create (compositor->wayland_display,
&wl_output_interface,
META_WL_OUTPUT_VERSION,
wayland_output, bind_output);
return wayland_output;
}
static GHashTable *
meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
MetaMonitorManager *monitors)
{
MetaOutput *outputs;
unsigned int i, n_outputs;
unsigned int i;
GHashTable *new_table;
MetaMonitorInfo *monitor_infos;
unsigned int n_monitor_infos;
outputs = meta_monitor_manager_get_outputs (monitors, &n_outputs);
monitor_infos = meta_monitor_manager_get_monitor_infos (monitors, &n_monitor_infos);
new_table = g_hash_table_new_full (NULL, NULL, NULL, wayland_output_destroy_notify);
for (i = 0; i < n_outputs; i++)
for (i = 0; i < n_monitor_infos; i++)
{
MetaOutput *output = &outputs[i];
MetaMonitorInfo *info = &monitor_infos[i];
MetaWaylandOutput *wayland_output;
/* wayland does not expose disabled outputs */
if (output->crtc == NULL)
{
g_hash_table_remove (compositor->outputs, GSIZE_TO_POINTER (output->winsys_id));
continue;
}
wayland_output = g_hash_table_lookup (compositor->outputs, GSIZE_TO_POINTER (output->winsys_id));
if (info->winsys_id == 0)
continue;
wayland_output = g_hash_table_lookup (compositor->outputs, GSIZE_TO_POINTER (info->winsys_id));
if (wayland_output)
{
g_hash_table_steal (compositor->outputs, GSIZE_TO_POINTER (output->winsys_id));
g_hash_table_steal (compositor->outputs, GSIZE_TO_POINTER (info->winsys_id));
}
else
{
wayland_output = g_slice_new0 (MetaWaylandOutput);
wayland_output->global = wl_global_create (compositor->wayland_display,
&wl_output_interface,
META_WL_OUTPUT_VERSION,
wayland_output, bind_output);
}
wayland_output = meta_wayland_output_new (compositor);
wayland_output_update_for_output (wayland_output, output);
g_hash_table_insert (new_table, GSIZE_TO_POINTER (output->winsys_id), wayland_output);
wayland_output_update_for_output (wayland_output, info);
g_hash_table_insert (new_table, GSIZE_TO_POINTER (info->winsys_id), wayland_output);
}
g_hash_table_destroy (compositor->outputs);
@@ -227,6 +228,49 @@ on_monitors_changed (MetaMonitorManager *monitors,
compositor->outputs = meta_wayland_compositor_update_outputs (compositor, monitors);
}
static void
meta_wayland_output_init (MetaWaylandOutput *wayland_output)
{
}
static void
meta_wayland_output_finalize (GObject *object)
{
MetaWaylandOutput *wayland_output = META_WAYLAND_OUTPUT (object);
GList *l;
wl_global_destroy (wayland_output->global);
/* Make sure the wl_output destructor doesn't try to access MetaWaylandOutput
* after we have freed it.
*/
for (l = wayland_output->resources; l; l = l->next)
{
struct wl_resource *output_resource = l->data;
wl_resource_set_user_data (output_resource, NULL);
}
g_list_free (wayland_output->resources);
G_OBJECT_CLASS (meta_wayland_output_parent_class)->finalize (object);
}
static void
meta_wayland_output_class_init (MetaWaylandOutputClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_wayland_output_finalize;
signals[OUTPUT_DESTROYED] = g_signal_new ("output-destroyed",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
}
void
meta_wayland_outputs_init (MetaWaylandCompositor *compositor)
{

View File

@@ -25,8 +25,37 @@
#ifndef META_WAYLAND_OUTPUTS_H
#define META_WAYLAND_OUTPUTS_H
#include "backends/meta-monitor-manager-private.h"
#include "meta-wayland-private.h"
#define META_TYPE_WAYLAND_OUTPUT (meta_wayland_output_get_type ())
#define META_WAYLAND_OUTPUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WAYLAND_OUTPUT, MetaWaylandOutput))
#define META_WAYLAND_OUTPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WAYLAND_OUTPUT, MetaWaylandOutputClass))
#define META_IS_WAYLAND_OUTPUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_WAYLAND_OUTPUT))
#define META_IS_WAYLAND_OUTPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WAYLAND_OUTPUT))
#define META_WAYLAND_OUTPUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WAYLAND_OUTPUT, MetaWaylandOutputClass))
typedef struct _MetaWaylandOutputClass MetaWaylandOutputClass;
struct _MetaWaylandOutput
{
GObject parent;
MetaMonitorInfo *monitor_info;
struct wl_global *global;
int x, y;
enum wl_output_transform transform;
GList *resources;
};
struct _MetaWaylandOutputClass
{
GObjectClass parent_class;
};
GType meta_wayland_output_get_type (void) G_GNUC_CONST;
void meta_wayland_outputs_init (MetaWaylandCompositor *compositor);
#endif /* META_WAYLAND_OUTPUTS_H */

View File

@@ -339,8 +339,6 @@ handle_button_event (MetaWaylandPointer *pointer,
{
gboolean implicit_grab;
notify_motion (pointer, event);
implicit_grab = (event->type == CLUTTER_BUTTON_PRESS) && (pointer->button_count == 1);
if (implicit_grab)
{
@@ -363,8 +361,6 @@ handle_scroll_event (MetaWaylandPointer *pointer,
struct wl_list *l;
wl_fixed_t x_value = 0, y_value = 0;
notify_motion (pointer, event);
if (clutter_event_is_pointer_emulated (event))
return;

View File

@@ -33,6 +33,8 @@
#include "meta-wayland-surface.h"
#include "meta-wayland-seat.h"
typedef struct _MetaXWaylandSelection MetaXWaylandSelection;
typedef struct
{
struct wl_list link;
@@ -43,7 +45,7 @@ typedef struct
typedef struct
{
int display_index;
char *lockfile;
char *lock_file;
int abstract_fd;
int unix_fd;
pid_t pid;
@@ -52,6 +54,8 @@ typedef struct
char *display_name;
GMainLoop *init_loop;
MetaXWaylandSelection *selection_data;
} MetaXWaylandManager;
struct _MetaWaylandCompositor

View File

@@ -42,16 +42,18 @@
#include "meta-wayland-pointer.h"
#include "meta-wayland-popup.h"
#include "meta-wayland-data-device.h"
#include "meta-wayland-outputs.h"
#include "meta-cursor-tracker-private.h"
#include "display-private.h"
#include "window-private.h"
#include "window-wayland.h"
#include "meta-window-wayland.h"
#include "compositor/region-utils.h"
#include "meta-surface-actor.h"
#include "meta-surface-actor-wayland.h"
#include "meta-xwayland-private.h"
typedef enum
{
@@ -121,24 +123,30 @@ static void
surface_process_damage (MetaWaylandSurface *surface,
cairo_region_t *region)
{
unsigned int buffer_width;
unsigned int buffer_height;
cairo_rectangle_int_t surface_rect;
cairo_region_t *scaled_region;
cairo_rectangle_int_t buffer_rect;
int i, n_rectangles;
if (!surface->buffer)
return;
buffer_rect.x = 0;
buffer_rect.y = 0;
buffer_rect.width = cogl_texture_get_width (surface->buffer->texture);
buffer_rect.height = cogl_texture_get_height (surface->buffer->texture);
/* Intersect the damage region with the surface region before scaling in
* order to avoid integer overflow when scaling a damage region is too large
* (for example INT32_MAX which mesa passes). */
buffer_width = cogl_texture_get_width (surface->buffer->texture);
buffer_height = cogl_texture_get_height (surface->buffer->texture);
surface_rect = (cairo_rectangle_int_t) {
.width = buffer_width / surface->scale,
.height = buffer_height / surface->scale,
};
cairo_region_intersect_rectangle (region, &surface_rect);
/* The damage region must be in the same coordinate space as the buffer,
* i.e. scaled with surface->scale. */
scaled_region = meta_region_scale (region, surface->scale);
cairo_region_intersect_rectangle (scaled_region, &buffer_rect);
/* First update the buffer. */
meta_wayland_buffer_process_damage (surface->buffer, scaled_region);
@@ -180,48 +188,84 @@ calculate_surface_window_geometry (MetaWaylandSurface *surface,
float parent_x,
float parent_y)
{
ClutterActor *surface_actor = CLUTTER_ACTOR (surface->surface_actor);
MetaSurfaceActorWayland *surface_actor =
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
MetaRectangle subsurface_rect;
MetaRectangle geom;
float x, y;
GList *l;
/* Unmapped surfaces don't count. */
if (!CLUTTER_ACTOR_IS_VISIBLE (surface_actor))
if (!CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR (surface_actor)))
return;
if (!surface->buffer)
return;
/* XXX: Is there a better way to do this using Clutter APIs? */
clutter_actor_get_position (surface_actor, &x, &y);
meta_surface_actor_wayland_get_subsurface_rect (surface_actor,
&subsurface_rect);
geom.x = parent_x + x;
geom.y = parent_x + y;
geom.width = cogl_texture_get_width (surface->buffer->texture);
geom.height = cogl_texture_get_height (surface->buffer->texture);
geom.x = parent_x + subsurface_rect.x;
geom.y = parent_x + subsurface_rect.y;
geom.width = subsurface_rect.width;
geom.height = subsurface_rect.height;
meta_rectangle_union (total_geometry, &geom, total_geometry);
for (l = surface->subsurfaces; l != NULL; l = l->next)
{
MetaWaylandSurface *subsurface = l->data;
calculate_surface_window_geometry (subsurface, total_geometry, x, y);
calculate_surface_window_geometry (subsurface, total_geometry,
subsurface_rect.x,
subsurface_rect.y);
}
}
static void
destroy_window (MetaWaylandSurface *surface)
{
if (surface->window)
{
MetaDisplay *display = meta_get_display ();
guint32 timestamp = meta_display_get_current_time_roundtrip (display);
meta_window_unmanage (surface->window, timestamp);
}
g_assert (surface->window == NULL);
}
static void
toplevel_surface_commit (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending)
{
MetaWindow *window = surface->window;
/* Sanity check. */
if (surface->buffer == NULL)
if (surface->role == META_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE)
{
wl_resource_post_error (surface->resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"Cannot commit a NULL buffer to an xdg_surface");
return;
/* For wl_shell, it's equivalent to an unmap. Semantics
* are poorly defined, so we can choose some that are
* convenient for us. */
if (surface->buffer && !window)
{
window = meta_window_wayland_new (meta_get_display (), surface);
meta_wayland_surface_set_window (surface, window);
}
else if (surface->buffer == NULL && window)
{
destroy_window (surface);
return;
}
}
else
{
if (surface->buffer == NULL)
{
/* XDG surfaces can't commit NULL buffers */
wl_resource_post_error (surface->resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"Cannot commit a NULL buffer to an xdg_surface");
return;
}
}
/* We resize X based surfaces according to X events */
@@ -341,49 +385,113 @@ static void
subsurface_surface_commit (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending)
{
MetaSurfaceActor *surface_actor = surface->surface_actor;
float x, y;
MetaSurfaceActorWayland *surface_actor =
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
if (surface->buffer != NULL)
clutter_actor_show (CLUTTER_ACTOR (surface_actor));
else
clutter_actor_hide (CLUTTER_ACTOR (surface_actor));
clutter_actor_get_position (CLUTTER_ACTOR (surface_actor), &x, &y);
x += pending->dx;
y += pending->dy;
clutter_actor_set_position (CLUTTER_ACTOR (surface_actor), x, y);
}
static void
subsurface_parent_surface_committed (MetaWaylandSurface *surface);
static void
parent_surface_committed (gpointer data, gpointer user_data)
/* A non-subsurface is always desynchronized.
*
* A subsurface is effectively synchronized if either its parent is
* synchronized or itself is in synchronized mode. */
static gboolean
is_surface_effectively_synchronized (MetaWaylandSurface *surface)
{
subsurface_parent_surface_committed (data);
if (surface->wl_subsurface == NULL)
{
return FALSE;
}
else
{
if (surface->sub.synchronous)
return TRUE;
else
return is_surface_effectively_synchronized (surface->sub.parent);
}
}
static void
commit_pending_state (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending)
apply_pending_state (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending);
static void
parent_surface_state_applied (gpointer data, gpointer user_data)
{
MetaWaylandSurface *surface = data;
if (surface->sub.pending_pos)
{
surface->sub.x = surface->sub.pending_x;
surface->sub.y = surface->sub.pending_y;
surface->sub.pending_pos = FALSE;
}
if (surface->sub.pending_placement_ops)
{
GSList *it;
MetaWaylandSurface *parent = surface->sub.parent;
ClutterActor *parent_actor =
clutter_actor_get_parent (CLUTTER_ACTOR (parent->surface_actor));
ClutterActor *surface_actor =
surface_actor = CLUTTER_ACTOR (surface->surface_actor);
for (it = surface->sub.pending_placement_ops; it; it = it->next)
{
MetaWaylandSubsurfacePlacementOp *op = it->data;
ClutterActor *sibling_actor;
if (!op->sibling)
{
g_slice_free (MetaWaylandSubsurfacePlacementOp, op);
continue;
}
sibling_actor = CLUTTER_ACTOR (op->sibling->surface_actor);
switch (op->placement)
{
case META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE:
clutter_actor_set_child_above_sibling (parent_actor,
surface_actor,
sibling_actor);
break;
case META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW:
clutter_actor_set_child_below_sibling (parent_actor,
surface_actor,
sibling_actor);
break;
}
wl_list_remove (&op->sibling_destroy_listener.link);
g_slice_free (MetaWaylandSubsurfacePlacementOp, op);
}
g_slist_free (surface->sub.pending_placement_ops);
surface->sub.pending_placement_ops = NULL;
}
if (is_surface_effectively_synchronized (surface))
apply_pending_state (surface, &surface->sub.pending);
meta_surface_actor_wayland_sync_subsurface_state (
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor));
}
static void
apply_pending_state (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending)
{
MetaWaylandCompositor *compositor = surface->compositor;
/* If this surface is a subsurface in in synchronous mode, commit
* has a special-case and should not apply the pending state immediately.
*
* Instead, we move it to another pending state, which will be
* actually committed when the parent commits.
*/
if (surface->sub.synchronous)
{
move_pending_state (pending, &surface->sub.pending);
return;
}
if (pending->newly_attached)
{
if (!surface->buffer && surface->window)
meta_window_queue (surface->window, META_QUEUE_CALC_SHOWING);
surface_set_buffer (surface, pending->buffer);
if (pending->buffer)
@@ -416,31 +524,53 @@ commit_pending_state (MetaWaylandSurface *surface,
surface->input_region = cairo_region_reference (pending->input_region);
}
meta_surface_actor_wayland_sync_state (
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor));
/* wl_surface.frame */
wl_list_insert_list (&compositor->frame_callbacks, &pending->frame_callback_list);
wl_list_init (&pending->frame_callback_list);
if (surface == compositor->seat->pointer.cursor_surface)
cursor_surface_commit (surface, pending);
else if (meta_wayland_data_device_is_dnd_surface (&compositor->seat->data_device, surface))
dnd_surface_commit (surface, pending);
else if (surface->window)
toplevel_surface_commit (surface, pending);
else if (surface->wl_subsurface)
subsurface_surface_commit (surface, pending);
switch (surface->role)
{
case META_WAYLAND_SURFACE_ROLE_NONE:
break;
case META_WAYLAND_SURFACE_ROLE_CURSOR:
cursor_surface_commit (surface, pending);
break;
case META_WAYLAND_SURFACE_ROLE_DND:
dnd_surface_commit (surface, pending);
break;
case META_WAYLAND_SURFACE_ROLE_XDG_SURFACE:
case META_WAYLAND_SURFACE_ROLE_XDG_POPUP:
case META_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE:
toplevel_surface_commit (surface, pending);
break;
case META_WAYLAND_SURFACE_ROLE_SUBSURFACE:
subsurface_surface_commit (surface, pending);
break;
}
g_list_foreach (surface->subsurfaces, parent_surface_committed, NULL);
meta_surface_actor_wayland_sync_state (
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor));
pending_state_reset (pending);
g_list_foreach (surface->subsurfaces, parent_surface_state_applied, NULL);
}
static void
meta_wayland_surface_commit (MetaWaylandSurface *surface)
{
commit_pending_state (surface, &surface->pending);
/*
* If this is a sub-surface and it is in effective synchronous mode, only
* cache the pending surface state until either one of the following two
* scenarios happens:
* 1) Its parent surface gets its state applied.
* 2) Its mode changes from synchronized to desynchronized and its parent
* surface is in effective desynchronized mode.
*/
if (is_surface_effectively_synchronized (surface))
move_pending_state (&surface->pending, &surface->sub.pending);
else
apply_pending_state (surface, &surface->pending);
}
static void
@@ -636,26 +766,131 @@ sync_reactive (MetaWaylandSurface *surface)
surface_should_be_reactive (surface));
}
static void
sync_drag_dest_funcs (MetaWaylandSurface *surface)
{
if (surface->window &&
surface->window->client_type == META_WINDOW_CLIENT_TYPE_X11)
surface->dnd.funcs = meta_xwayland_selection_get_drag_dest_funcs ();
else
surface->dnd.funcs = meta_wayland_data_device_get_drag_dest_funcs ();
}
static void
surface_entered_output (MetaWaylandSurface *surface,
MetaWaylandOutput *wayland_output)
{
GList *iter;
struct wl_resource *resource;
for (iter = wayland_output->resources; iter != NULL; iter = iter->next)
{
resource = iter->data;
if (wl_resource_get_client (resource) !=
wl_resource_get_client (surface->resource))
continue;
wl_surface_send_enter (surface->resource, resource);
}
}
static void
surface_left_output (MetaWaylandSurface *surface,
MetaWaylandOutput *wayland_output)
{
GList *iter;
struct wl_resource *resource;
for (iter = wayland_output->resources; iter != NULL; iter = iter->next)
{
resource = iter->data;
if (wl_resource_get_client (resource) !=
wl_resource_get_client (surface->resource))
continue;
wl_surface_send_leave (surface->resource, resource);
}
}
static void
set_surface_is_on_output (MetaWaylandSurface *surface,
MetaWaylandOutput *wayland_output,
gboolean is_on_output);
static void
surface_handle_output_destroy (MetaWaylandOutput *wayland_output,
GParamSpec *pspec,
MetaWaylandSurface *surface)
{
set_surface_is_on_output (surface, wayland_output, FALSE);
}
static void
set_surface_is_on_output (MetaWaylandSurface *surface,
MetaWaylandOutput *wayland_output,
gboolean is_on_output)
{
gboolean was_on_output = g_hash_table_contains (surface->outputs,
wayland_output);
if (!was_on_output && is_on_output)
{
g_signal_connect (wayland_output, "output-destroyed",
G_CALLBACK (surface_handle_output_destroy),
surface);
g_hash_table_add (surface->outputs, wayland_output);
surface_entered_output (surface, wayland_output);
}
else if (was_on_output && !is_on_output)
{
g_hash_table_remove (surface->outputs, wayland_output);
g_signal_handlers_disconnect_by_func (
wayland_output, (gpointer)surface_handle_output_destroy, surface);
surface_left_output (surface, wayland_output);
}
}
static void
update_surface_output_state (gpointer key, gpointer value, gpointer user_data)
{
MetaWaylandOutput *wayland_output = value;
MetaWaylandSurface *surface = user_data;
MetaSurfaceActorWayland *actor =
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
MetaMonitorInfo *monitor;
gboolean is_on_output;
monitor = wayland_output->monitor_info;
if (!monitor)
{
set_surface_is_on_output (surface, wayland_output, FALSE);
return;
}
is_on_output = meta_surface_actor_wayland_is_on_monitor (actor, monitor);
set_surface_is_on_output (surface, wayland_output, is_on_output);
}
void
meta_wayland_surface_update_outputs (MetaWaylandSurface *surface)
{
if (!surface->compositor)
return;
g_hash_table_foreach (surface->compositor->outputs,
update_surface_output_state,
surface);
}
void
meta_wayland_surface_set_window (MetaWaylandSurface *surface,
MetaWindow *window)
{
surface->window = window;
sync_reactive (surface);
}
static void
destroy_window (MetaWaylandSurface *surface)
{
if (surface->window)
{
MetaDisplay *display = meta_get_display ();
guint32 timestamp = meta_display_get_current_time_roundtrip (display);
meta_window_unmanage (surface->window, timestamp);
}
g_assert (surface->window == NULL);
sync_drag_dest_funcs (surface);
}
static void
@@ -678,10 +913,15 @@ wl_surface_destructor (struct wl_resource *resource)
if (surface->input_region)
cairo_region_destroy (surface->input_region);
meta_surface_actor_wayland_surface_destroyed (
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor));
g_object_unref (surface->surface_actor);
meta_wayland_compositor_destroy_frame_callbacks (compositor, surface);
g_hash_table_unref (surface->outputs);
if (surface->resource)
wl_resource_set_user_data (surface->resource, NULL);
@@ -718,6 +958,10 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
surface->buffer_destroy_listener.notify = surface_handle_buffer_destroy;
surface->surface_actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface));
sync_drag_dest_funcs (surface);
surface->outputs = g_hash_table_new (NULL, NULL);
pending_state_init (&surface->pending);
return surface;
}
@@ -1160,11 +1404,8 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
&surface->popup.parent_destroy_listener);
window = meta_window_wayland_new (display, surface);
meta_window_move_frame (window, FALSE,
parent_surf->window->rect.x + x,
parent_surf->window->rect.y + y);
meta_window_wayland_place_relative_to (window, parent_surf->window, x, y);
window->showing_for_first_time = FALSE;
window->placed = TRUE;
meta_wayland_surface_set_window (surface, window);
@@ -1328,10 +1569,9 @@ wl_shell_surface_set_transient (struct wl_client *client,
wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL);
meta_window_set_transient_for (surface->window, parent_surf->window);
meta_window_move_frame (surface->window, FALSE,
parent_surf->window->rect.x + x,
parent_surf->window->rect.y + y);
surface->window->placed = TRUE;
meta_window_wayland_place_relative_to (surface->window,
parent_surf->window,
x, y);
}
static void
@@ -1346,6 +1586,17 @@ wl_shell_surface_set_fullscreen (struct wl_client *client,
wl_shell_surface_set_state (surface, SURFACE_STATE_FULLSCREEN);
}
static void
handle_wl_shell_popup_parent_destroyed (struct wl_listener *listener,
void *data)
{
MetaWaylandSurface *surface =
wl_container_of (listener, surface, popup.parent_destroy_listener);
wl_list_remove (&surface->popup.parent_destroy_listener.link);
surface->popup.parent = NULL;
}
static void
wl_shell_surface_set_popup (struct wl_client *client,
struct wl_resource *resource,
@@ -1369,10 +1620,18 @@ wl_shell_surface_set_popup (struct wl_client *client,
}
meta_window_set_transient_for (surface->window, parent_surf->window);
meta_window_move_frame (surface->window, FALSE,
parent_surf->window->rect.x + x,
parent_surf->window->rect.y + y);
surface->window->placed = TRUE;
meta_window_wayland_place_relative_to (surface->window,
parent_surf->window,
x, y);
if (!surface->popup.parent)
{
surface->popup.parent = parent_surf;
surface->popup.parent_destroy_listener.notify =
handle_wl_shell_popup_parent_destroyed;
wl_resource_add_destroy_listener (parent_surf->resource,
&surface->popup.parent_destroy_listener);
}
meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
}
@@ -1475,14 +1734,14 @@ gtk_surface_destructor (struct wl_resource *resource)
}
static void
set_dbus_properties (struct wl_client *client,
struct wl_resource *resource,
const char *application_id,
const char *app_menu_path,
const char *menubar_path,
const char *window_object_path,
const char *application_object_path,
const char *unique_bus_name)
gtk_surface_set_dbus_properties (struct wl_client *client,
struct wl_resource *resource,
const char *application_id,
const char *app_menu_path,
const char *menubar_path,
const char *window_object_path,
const char *application_object_path,
const char *unique_bus_name)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
@@ -1502,8 +1761,36 @@ set_dbus_properties (struct wl_client *client,
window_object_path);
}
static void
gtk_surface_set_modal (struct wl_client *client,
struct wl_resource *resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
if (surface->is_modal)
return;
surface->is_modal = TRUE;
meta_window_set_type (surface->window, META_WINDOW_MODAL_DIALOG);
}
static void
gtk_surface_unset_modal (struct wl_client *client,
struct wl_resource *resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
if (!surface->is_modal)
return;
surface->is_modal = FALSE;
meta_window_set_type (surface->window, META_WINDOW_NORMAL);
}
static const struct gtk_surface_interface meta_wayland_gtk_surface_interface = {
set_dbus_properties
gtk_surface_set_dbus_properties,
gtk_surface_set_modal,
gtk_surface_unset_modal,
};
static void
@@ -1540,6 +1827,17 @@ bind_gtk_shell (struct wl_client *client,
uint32_t capabilities = 0;
resource = wl_resource_create (client, &gtk_shell_interface, version, id);
if (version != META_GTK_SHELL_VERSION)
{
wl_resource_post_error (resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"Incompatible gtk-shell version "
"(supported version: %d)",
META_GTK_SHELL_VERSION);
return;
}
wl_resource_set_implementation (resource, &meta_wayland_gtk_shell_interface, data, NULL);
if (!meta_prefs_get_show_fallback_app_menu ())
@@ -1548,59 +1846,6 @@ bind_gtk_shell (struct wl_client *client,
gtk_shell_send_capabilities (resource, capabilities);
}
static void
subsurface_parent_surface_committed (MetaWaylandSurface *surface)
{
if (surface->sub.pending_pos)
{
clutter_actor_set_position (CLUTTER_ACTOR (surface->surface_actor),
surface->sub.pending_x,
surface->sub.pending_y);
surface->sub.pending_pos = FALSE;
}
if (surface->sub.pending_placement_ops)
{
GSList *it;
for (it = surface->sub.pending_placement_ops; it; it = it->next)
{
MetaWaylandSubsurfacePlacementOp *op = it->data;
ClutterActor *surface_actor;
ClutterActor *parent_actor;
ClutterActor *sibling_actor;
if (!op->sibling)
{
g_slice_free (MetaWaylandSubsurfacePlacementOp, op);
continue;
}
surface_actor = CLUTTER_ACTOR (surface->surface_actor);
parent_actor = clutter_actor_get_parent (CLUTTER_ACTOR (surface->sub.parent));
sibling_actor = CLUTTER_ACTOR (op->sibling->surface_actor);
switch (op->placement)
{
case META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE:
clutter_actor_set_child_above_sibling (parent_actor, surface_actor, sibling_actor);
break;
case META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW:
clutter_actor_set_child_below_sibling (parent_actor, surface_actor, sibling_actor);
break;
}
wl_list_remove (&op->sibling_destroy_listener.link);
g_slice_free (MetaWaylandSubsurfacePlacementOp, op);
}
g_slist_free (surface->sub.pending_placement_ops);
surface->sub.pending_placement_ops = NULL;
}
if (surface->sub.synchronous)
commit_pending_state (surface, &surface->sub.pending);
}
static void
unparent_actor (MetaWaylandSurface *surface)
{
@@ -1745,11 +1990,13 @@ wl_subsurface_set_desync (struct wl_client *client,
struct wl_resource *resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
gboolean was_effectively_synchronized;
if (surface->sub.synchronous)
subsurface_parent_surface_committed (surface);
was_effectively_synchronized = is_surface_effectively_synchronized (surface);
surface->sub.synchronous = FALSE;
if (was_effectively_synchronized &&
!is_surface_effectively_synchronized (surface))
apply_pending_state (surface, &surface->sub.pending);
}
static const struct wl_subsurface_interface meta_wayland_wl_subsurface_interface = {
@@ -1908,12 +2155,6 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
wl_array_init (&states);
fill_states (&states, surface->window);
/* new_width and new_height comes from window->rect, which is based on
* the buffer size, not the surface size. The configure event requires
* surface size. */
new_width /= surface->scale;
new_height /= surface->scale;
xdg_surface_send_configure (surface->xdg_surface, new_width, new_height, &states, serial);
wl_array_release (&states);
@@ -1961,3 +2202,60 @@ meta_wayland_surface_popup_done (MetaWaylandSurface *surface)
else if (surface->wl_shell_surface)
wl_shell_surface_send_popup_done (surface->wl_shell_surface);
}
void
meta_wayland_surface_drag_dest_focus_in (MetaWaylandSurface *surface,
MetaWaylandDataOffer *offer)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
surface->dnd.funcs->focus_in (data_device, surface, offer);
}
void
meta_wayland_surface_drag_dest_motion (MetaWaylandSurface *surface,
const ClutterEvent *event)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
surface->dnd.funcs->motion (data_device, surface, event);
}
void
meta_wayland_surface_drag_dest_focus_out (MetaWaylandSurface *surface)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
surface->dnd.funcs->focus_out (data_device, surface);
}
void
meta_wayland_surface_drag_dest_drop (MetaWaylandSurface *surface)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
surface->dnd.funcs->drop (data_device, surface);
}
MetaWindow *
meta_wayland_surface_get_toplevel_window (MetaWaylandSurface *surface)
{
while (surface)
{
if (surface->window)
{
if (surface->popup.parent)
surface = surface->popup.parent;
else
return surface->window;
}
else
surface = surface->sub.parent;
}
return NULL;
}

View File

@@ -71,6 +71,20 @@ typedef struct
gboolean has_new_geometry;
} MetaWaylandPendingState;
struct _MetaWaylandDragDestFuncs
{
void (* focus_in) (MetaWaylandDataDevice *data_device,
MetaWaylandSurface *surface,
MetaWaylandDataOffer *offer);
void (* focus_out) (MetaWaylandDataDevice *data_device,
MetaWaylandSurface *surface);
void (* motion) (MetaWaylandDataDevice *data_device,
MetaWaylandSurface *surface,
const ClutterEvent *event);
void (* drop) (MetaWaylandDataDevice *data_device,
MetaWaylandSurface *surface);
};
struct _MetaWaylandSurface
{
/* Generic stuff */
@@ -86,6 +100,11 @@ struct _MetaWaylandSurface
int scale;
int32_t offset_x, offset_y;
GList *subsurfaces;
GHashTable *outputs;
struct {
const MetaWaylandDragDestFuncs *funcs;
} dnd;
/* All the pending state that wl_surface.commit will apply. */
MetaWaylandPendingState pending;
@@ -101,6 +120,7 @@ struct _MetaWaylandSurface
struct wl_resource *xdg_shell_resource;
MetaWaylandSerial acked_configure_serial;
gboolean has_set_geometry;
gboolean is_modal;
/* xdg_popup */
struct {
@@ -116,6 +136,9 @@ struct _MetaWaylandSurface
MetaWaylandSurface *parent;
struct wl_listener parent_destroy_listener;
int x;
int y;
/* When the surface is synchronous, its state will be applied
* when the parent is committed. This is done by moving the
* "real" pending state below to here when this surface is
@@ -160,4 +183,16 @@ void meta_wayland_surface_delete (MetaWaylandSurface *surface);
void meta_wayland_surface_popup_done (MetaWaylandSurface *surface);
/* Drag dest functions */
void meta_wayland_surface_drag_dest_focus_in (MetaWaylandSurface *surface,
MetaWaylandDataOffer *offer);
void meta_wayland_surface_drag_dest_motion (MetaWaylandSurface *surface,
const ClutterEvent *event);
void meta_wayland_surface_drag_dest_focus_out (MetaWaylandSurface *surface);
void meta_wayland_surface_drag_dest_drop (MetaWaylandSurface *surface);
void meta_wayland_surface_update_outputs (MetaWaylandSurface *surface);
MetaWindow * meta_wayland_surface_get_toplevel_window (MetaWaylandSurface *surface);
#endif

View File

@@ -30,7 +30,8 @@ typedef struct _MetaWaylandPopupGrab MetaWaylandPopupGrab;
typedef struct _MetaWaylandPopup MetaWaylandPopup;
typedef struct _MetaWaylandKeyboard MetaWaylandKeyboard;
typedef struct _MetaWaylandTouch MetaWaylandTouch;
typedef struct _MetaWaylandDataSource MetaWaylandDataSource;
typedef struct _MetaWaylandDragDestFuncs MetaWaylandDragDestFuncs;
typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer;
typedef struct _MetaWaylandDataDevice MetaWaylandDataDevice;
typedef struct _MetaWaylandBuffer MetaWaylandBuffer;
@@ -38,6 +39,8 @@ typedef struct _MetaWaylandRegion MetaWaylandRegion;
typedef struct _MetaWaylandSurface MetaWaylandSurface;
typedef struct _MetaWaylandOutput MetaWaylandOutput;
typedef struct _MetaWaylandSerial MetaWaylandSerial;
#endif

View File

@@ -42,7 +42,7 @@
#define META_WL_SEAT_VERSION 4
#define META_WL_OUTPUT_VERSION 2
#define META_XSERVER_VERSION 1
#define META_GTK_SHELL_VERSION 1
#define META_GTK_SHELL_VERSION 2
#define META_WL_SUBCOMPOSITOR_VERSION 1
#endif

View File

@@ -24,7 +24,7 @@
#include "config.h"
#include "window-wayland.h"
#include "meta-window-wayland.h"
#include <meta/errors.h>
#include "window-private.h"
@@ -166,9 +166,20 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
{
MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window);
gboolean can_move_now;
int configured_width;
int configured_height;
int monitor_scale;
g_assert (window->frame == NULL);
/* The scale the window is drawn in might change depending on what monitor it
* is mainly on. Scale the configured rectangle to be in logical pixel
* coordinate space so that we can have a scale independent size to pass
* to the Wayland surface. */
monitor_scale = meta_window_wayland_get_main_monitor_scale (window);
configured_width = constrained_rect.width / monitor_scale;
configured_height = constrained_rect.height / monitor_scale;
/* For wayland clients, the size is completely determined by the client,
* and while this allows to avoid some trickery with frames and the resulting
* lagging, we also need to insist a bit when the constraints would apply
@@ -223,8 +234,8 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
return;
meta_wayland_surface_configure_notify (window->surface,
constrained_rect.width,
constrained_rect.height,
configured_width,
configured_height,
&wl_window->pending_configure_serial);
/* We need to wait until the resize completes before we can move */
@@ -238,8 +249,8 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
}
}
wl_window->last_sent_width = constrained_rect.width;
wl_window->last_sent_height = constrained_rect.height;
wl_window->last_sent_width = configured_width;
wl_window->last_sent_height = configured_height;
if (can_move_now)
{
@@ -277,12 +288,101 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
}
}
static void
scale_rect_size (MetaRectangle *rect, float scale)
{
rect->width = (int)(rect->width * scale);
rect->height = (int)(rect->height * scale);
}
static void
meta_window_wayland_update_main_monitor (MetaWindow *window)
{
const MetaMonitorInfo *from;
const MetaMonitorInfo *to;
const MetaMonitorInfo *scaled_new;
float scale;
MetaRectangle rect;
/* Require both the current and the new monitor would be the new main monitor,
* even given the resulting scale the window would end up having. This is
* needed to avoid jumping back and forth between the new and the old, since
* changing main monitor may cause the window to be resized so that it no
* longer have that same new main monitor. */
from = window->monitor;
to = meta_screen_calculate_monitor_for_window (window->screen, window);
if (from == to)
return;
/* If we are setting the first output, unsetting the output, or the new has
* the same scale as the old no need to do any further checking. */
if (from == NULL || to == NULL || from->scale == to->scale)
{
window->monitor = to;
return;
}
/* To avoid a window alternating between two main monitors because scaling
* changes the main monitor, wait until both the current and the new scale
* will result in the same main monitor. */
scale = (float)to->scale / from->scale;
rect = window->rect;
scale_rect_size (&rect, scale);
scaled_new = meta_screen_get_monitor_for_rect (window->screen, &rect);
if (to != scaled_new)
return;
window->monitor = to;
}
static void
meta_window_wayland_main_monitor_changed (MetaWindow *window,
const MetaMonitorInfo *old)
{
MetaWaylandSurface *surface = window->surface;
float scale_factor;
MetaWaylandSurface *surface;
/* This function makes sure that window geometry, window actor geometry and
* surface actor geometry gets set according the old and current main monitor
* scale. If there either is no past or current main monitor, or if the scale
* didn't change, there is nothing to do. */
if (old == NULL ||
window->monitor == NULL ||
old->scale == window->monitor->scale)
return;
/* MetaWindow keeps its rectangles in the physical pixel coordinate space.
* When the main monitor of a window changes, it can cause the corresponding
* window surfaces to be scaled given the monitor scale, so we need to scale
* the rectangles in MetaWindow accordingly. */
scale_factor = (float)window->monitor->scale / old->scale;
/* Window size. */
scale_rect_size (&window->rect, scale_factor);
/* Window geometry offset (XXX: Need a better place, see
* meta_window_wayland_move_resize). */
window->custom_frame_extents.left =
(int)(scale_factor * window->custom_frame_extents.left);
window->custom_frame_extents.top =
(int)(scale_factor * window->custom_frame_extents.top);
/* Buffer rect. */
scale_rect_size (&window->buffer_rect, scale_factor);
window->buffer_rect.x =
window->rect.x - window->custom_frame_extents.left;
window->buffer_rect.y =
window->rect.y - window->custom_frame_extents.top;
meta_compositor_sync_window_geometry (window->display->compositor,
window,
TRUE);
/* The surface actor needs to update the scale recursively for itself and all
* its subsurfaces */
surface = window->surface;
if (surface)
{
MetaSurfaceActorWayland *actor =
@@ -290,6 +390,8 @@ meta_window_wayland_main_monitor_changed (MetaWindow *window,
meta_surface_actor_wayland_sync_state_recursive (actor);
}
meta_window_emit_size_changed (window);
}
static void
@@ -330,6 +432,7 @@ meta_window_wayland_class_init (MetaWindowWaylandClass *klass)
window_class->grab_op_began = meta_window_wayland_grab_op_began;
window_class->grab_op_ended = meta_window_wayland_grab_op_ended;
window_class->move_resize_internal = meta_window_wayland_move_resize_internal;
window_class->update_main_monitor = meta_window_wayland_update_main_monitor;
window_class->main_monitor_changed = meta_window_wayland_main_monitor_changed;
}
@@ -412,6 +515,12 @@ should_do_pending_move (MetaWindowWayland *wl_window,
return TRUE;
}
int
meta_window_wayland_get_main_monitor_scale (MetaWindow *window)
{
return window->monitor->scale;
}
/**
* meta_window_move_resize_wayland:
*
@@ -428,6 +537,22 @@ meta_window_wayland_move_resize (MetaWindow *window,
int gravity;
MetaRectangle rect;
MetaMoveResizeFlags flags;
int monitor_scale;
/* new_geom is in the logical pixel coordinate space, but MetaWindow wants its
* rects to represent what in turn will end up on the stage, i.e. we need to
* scale new_geom to physical pixels given what buffer scale and texture scale
* is in use. */
monitor_scale = meta_window_wayland_get_main_monitor_scale (window);
new_geom.x *= monitor_scale;
new_geom.y *= monitor_scale;
new_geom.width *= monitor_scale;
new_geom.height *= monitor_scale;
/* The (dx, dy) offset is also in logical pixel coordinate space and needs
* to be scaled in the same way as new_geom. */
dx *= monitor_scale;
dy *= monitor_scale;
/* XXX: Find a better place to store the window geometry offsets. */
window->custom_frame_extents.left = new_geom.x;
@@ -470,3 +595,24 @@ meta_window_wayland_move_resize (MetaWindow *window,
gravity = meta_resize_gravity_from_grab_op (window->display->grab_op);
meta_window_move_resize_internal (window, flags, gravity, rect);
}
void
meta_window_wayland_place_relative_to (MetaWindow *window,
MetaWindow *other,
int x,
int y)
{
int monitor_scale;
/* If there is no monitor, we can't position the window reliably. */
if (!other->monitor)
return;
/* Scale the relative coordinate (x, y) from logical pixels to physical
* pixels. */
monitor_scale = other->monitor->scale;
meta_window_move_frame (window, FALSE,
other->buffer_rect.x + (x * monitor_scale),
other->buffer_rect.y + (y * monitor_scale));
window->placed = TRUE;
}

View File

@@ -50,5 +50,11 @@ void meta_window_wayland_move_resize (MetaWindow *window,
MetaRectangle new_geom,
int dx,
int dy);
int meta_window_wayland_get_main_monitor_scale (MetaWindow *window);
void meta_window_wayland_place_relative_to (MetaWindow *window,
MetaWindow *other,
int x,
int y);
#endif

Some files were not shown because too many files have changed in this diff Show More