Compare commits

...

78 Commits

Author SHA1 Message Date
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
54 changed files with 5124 additions and 4484 deletions

25
NEWS
View File

@@ -1,3 +1,28 @@
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]

View File

@@ -2,7 +2,7 @@ AC_PREREQ(2.62)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [17])
m4_define([mutter_micro_version], [1])
m4_define([mutter_micro_version], [3])
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
@@ -284,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"

View File

@@ -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"

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

@@ -210,8 +210,6 @@ libmutter_la_SOURCES = \
meta/theme.h \
ui/theme-private.h \
ui/ui.c \
x11/async-getprop.c \
x11/async-getprop.h \
x11/atomnames.h \
x11/events.c \
x11/events.h \
@@ -243,6 +241,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 \
@@ -250,6 +250,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 \

View File

@@ -886,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,
@@ -905,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
@@ -1079,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);
@@ -1092,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;
}
@@ -1146,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);
@@ -1154,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;
@@ -1181,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,
@@ -1189,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;
}
}
}
@@ -1337,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 */
@@ -1355,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)
{
@@ -1840,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;
@@ -1857,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];
@@ -1905,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);
}
@@ -1917,8 +1991,7 @@ real_assign_crtcs (CrtcAssignment *assignment,
}
}
out:
return success;
return FALSE;
}
static gboolean

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 */
@@ -133,6 +145,7 @@ struct _MetaOutput
gboolean is_primary;
gboolean is_presentation;
gboolean is_underscanning;
gboolean supports_underscanning;
gpointer driver_private;
GDestroyNotify driver_notify;
@@ -141,6 +154,8 @@ struct _MetaOutput
gboolean hotplug_mode_update;
gint suggested_x;
gint suggested_y;
MetaTileInfo tile_info;
};
struct _MetaCRTC
@@ -179,6 +194,7 @@ struct _MetaMonitorMode
GDestroyNotify driver_notify;
};
#define META_MAX_OUTPUTS_PER_MONITOR 4
/**
* MetaMonitorInfo:
*
@@ -194,6 +210,10 @@ 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;
@@ -207,6 +227,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];
};
/*
@@ -324,6 +350,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);

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,9 @@ 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.is_primary = FALSE;
/* This starts true because we want
is_presentation only if all outputs are
@@ -125,7 +229,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 +252,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,6 +263,12 @@ 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;
@@ -164,6 +278,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
@@ -368,16 +486,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;
}
@@ -413,18 +529,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 *
@@ -537,6 +647,8 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
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)
@@ -557,6 +669,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,
@@ -1237,15 +1363,35 @@ meta_monitor_manager_read_current_config (MetaMonitorManager *manager)
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);

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,
@@ -270,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,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,6 +55,11 @@ 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 {
@@ -110,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;
@@ -198,6 +203,9 @@ find_connector_properties (MetaMonitorManagerKms *manager_kms,
{
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++)
{
drmModePropertyPtr prop = drmModeGetProperty (manager_kms->fd, output_kms->connector->props[i]);
@@ -208,7 +216,19 @@ find_connector_properties (MetaMonitorManagerKms *manager_kms,
output_kms->dpms_prop_id = prop->prop_id;
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);
}
}
@@ -273,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)
@@ -516,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)
{
@@ -542,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;
@@ -612,7 +677,10 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
}
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);
@@ -622,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.

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
@@ -190,16 +226,23 @@ meta_input_settings_x11_set_click_method (MetaInputSettings *settings,
GDesktopTouchpadClickMethod mode)
{
guchar values[2] = { 0 }; /* buttonareas, clickfinger */
guchar *defaults;
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;

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
@@ -229,12 +225,11 @@ static gboolean
output_get_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
{
gboolean value = FALSE;
Atom atom, actual_type;
int actual_format;
unsigned long nitems, bytes_after;
unsigned char *buffer;
char *str;
g_autofree unsigned char *buffer = NULL;
g_autofree char *str = NULL;
atom = XInternAtom (manager_xrandr->xdisplay, "underscan", False);
XRRGetOutputProperty (manager_xrandr->xdisplay,
@@ -244,17 +239,56 @@ output_get_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
&actual_type, &actual_format,
&nitems, &bytes_after, &buffer);
if (actual_type != XA_ATOM || actual_format != 32 ||
nitems < 1)
goto out;
if (actual_type != XA_ATOM || actual_format != 32 || nitems < 1)
return FALSE;
str = XGetAtomName (manager_xrandr->xdisplay, *(Atom *)buffer);
value = !strcmp(str, "on");
XFree (str);
return (strcmp (str, "on") == 0);
}
out:
XFree (buffer);
return value;
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
@@ -273,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,
@@ -284,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
@@ -302,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);
@@ -320,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
@@ -408,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)
@@ -479,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,
@@ -494,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
@@ -538,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"))
@@ -736,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++)
@@ -789,6 +849,7 @@ 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))
@@ -902,11 +963,12 @@ 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
@@ -921,11 +983,12 @@ output_set_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
value = underscanning ? "on" : "off";
valueatom = XInternAtom (manager_xrandr->xdisplay, value, False);
XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
prop,
XA_ATOM, 32, PropModeReplace,
(unsigned char*) &valueatom, 1);
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
@@ -936,19 +999,21 @@ output_set_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
prop = XInternAtom (manager_xrandr->xdisplay, "underscan hborder", False);
border_value = output->crtc->current_mode->width * 0.05;
XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
prop,
XA_INTEGER, 32, PropModeReplace,
(unsigned char *) &border_value, 1);
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;
XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
prop,
XA_INTEGER, 32, PropModeReplace,
(unsigned char *) &border_value, 1);
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);
}
}
@@ -1068,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;
@@ -1105,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))
@@ -1125,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);
}
}
@@ -1147,9 +1209,10 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
output_info->output,
output_info->is_presentation);
output_set_underscanning_xrandr (manager_xrandr,
output_info->output,
output_info->is_underscanning);
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;
@@ -1187,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);
@@ -1239,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)
{
@@ -1254,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,
@@ -1261,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
}
}
@@ -1291,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

@@ -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);
}
@@ -498,17 +512,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 +532,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 +876,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

@@ -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

@@ -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);

View File

@@ -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

@@ -1922,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

@@ -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

@@ -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

@@ -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;
@@ -1755,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)

View File

@@ -1273,16 +1273,13 @@ 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))

View File

@@ -434,7 +434,6 @@ struct _MetaWindow
/* Managed by delete.c */
int dialog_pid;
guint is_alive : 1;
/* maintained by group.c */
MetaGroup *group;

View File

@@ -58,6 +58,7 @@
#ifdef HAVE_WAYLAND
#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;
}
@@ -1533,6 +1540,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) &&
@@ -2965,11 +2978,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,6 +3001,7 @@ 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;
@@ -3015,6 +3027,8 @@ 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.
*/
@@ -3061,7 +3075,7 @@ meta_window_unmaximize_internal (MetaWindow *window,
meta_window_move_resize_internal (window,
META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION | META_MOVE_RESIZE_STATE_CHANGED,
gravity,
NorthWestGravity,
target_rect);
meta_window_get_frame_rect (window, &new_rect);
@@ -3095,37 +3109,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 +3211,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
*/
@@ -5728,81 +5713,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 +5737,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 +5783,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 +5851,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)

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

@@ -32,7 +32,7 @@
#include <string.h>
typedef struct {
MetaOutput *output;
MetaMonitorInfo *monitor_info;
struct wl_global *global;
int x, y;
enum wl_output_transform transform;
@@ -56,9 +56,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 +67,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 +93,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);
@@ -128,14 +129,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 +144,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,16 +161,16 @@ 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;
}
@@ -178,30 +178,26 @@ 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
{
@@ -212,8 +208,8 @@ meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
wayland_output, bind_output);
}
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);

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;
@@ -52,6 +54,8 @@ typedef struct
char *display_name;
GMainLoop *init_loop;
MetaXWaylandSelection *selection_data;
} MetaXWaylandManager;
struct _MetaWaylandCompositor

View File

@@ -52,6 +52,7 @@
#include "meta-surface-actor.h"
#include "meta-surface-actor-wayland.h"
#include "meta-xwayland-private.h"
typedef enum
{
@@ -485,6 +486,9 @@ apply_pending_state (MetaWaylandSurface *surface,
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)
@@ -748,12 +752,23 @@ 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 ();
}
void
meta_wayland_surface_set_window (MetaWaylandSurface *surface,
MetaWindow *window)
{
surface->window = window;
sync_reactive (surface);
sync_drag_dest_funcs (surface);
}
static void
@@ -816,6 +831,8 @@ 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);
pending_state_init (&surface->pending);
return surface;
}
@@ -1259,8 +1276,8 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
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);
parent_surf->window->buffer_rect.x + x,
parent_surf->window->buffer_rect.y + y);
window->showing_for_first_time = FALSE;
window->placed = TRUE;
@@ -1525,6 +1542,7 @@ wl_shell_get_shell_surface (struct wl_client *client,
struct wl_resource *surface_resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWindow *window;
if (surface->wl_shell_surface != NULL)
{
@@ -1542,6 +1560,9 @@ wl_shell_get_shell_surface (struct wl_client *client,
surface->wl_shell_surface = wl_resource_create (client, &wl_shell_surface_interface, wl_resource_get_version (resource), id);
wl_resource_set_implementation (surface->wl_shell_surface, &meta_wayland_wl_shell_surface_interface, surface, wl_shell_surface_destructor);
window = meta_window_wayland_new (meta_get_display (), surface);
meta_wayland_surface_set_window (surface, window);
}
static const struct wl_shell_interface meta_wayland_wl_shell_interface = {
@@ -2043,3 +2064,41 @@ 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);
}

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 */
@@ -87,6 +101,10 @@ struct _MetaWaylandSurface
int32_t offset_x, offset_y;
GList *subsurfaces;
struct {
const MetaWaylandDragDestFuncs *funcs;
} dnd;
/* All the pending state that wl_surface.commit will apply. */
MetaWaylandPendingState pending;
@@ -161,4 +179,12 @@ 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);
#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;

View File

@@ -34,4 +34,11 @@ meta_xwayland_complete_init (void);
void
meta_xwayland_stop (MetaXWaylandManager *manager);
/* wl_data_device/X11 selection interoperation */
void meta_xwayland_init_selection (void);
void meta_xwayland_shutdown_selection (void);
gboolean meta_xwayland_selection_handle_event (XEvent *xevent);
const MetaWaylandDragDestFuncs * meta_xwayland_selection_get_drag_dest_funcs (void);
#endif /* META_XWAYLAND_PRIVATE_H */

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_XWAYLAND_SELECTION_PRIVATE_H
#define META_XWAYLAND_SELECTION_PRIVATE_H
#define META_TYPE_WAYLAND_DATA_SOURCE_XWAYLAND (meta_wayland_data_source_xwayland_get_type ())
G_DECLARE_FINAL_TYPE (MetaWaylandDataSourceXWayland,
meta_wayland_data_source_xwayland,
META, WAYLAND_DATA_SOURCE_XWAYLAND,
MetaWaylandDataSource);
#endif /* META_XWAYLAND_SELECTION_PRIVATE_H */

File diff suppressed because it is too large Load Diff

View File

@@ -522,6 +522,8 @@ meta_xwayland_complete_init (void)
we won't reset the tty).
*/
XSetIOErrorHandler (x_io_error);
meta_xwayland_init_selection ();
}
void
@@ -529,6 +531,8 @@ meta_xwayland_stop (MetaXWaylandManager *manager)
{
char path[256];
meta_xwayland_shutdown_selection ();
snprintf (path, sizeof path, "/tmp/.X11-unix/X%d", manager->display_index);
unlink (path);

View File

@@ -1,680 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Asynchronous X property getting hack */
/*
* Copyright (C) 2002 Havoc Pennington
* Copyright (C) 1986, 1998 The Open Group
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation.
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of The Open Group shall not be
* used in advertising or otherwise to promote the sale, use or other dealings
* in this Software without prior written authorization from The Open Group.
*/
#include <assert.h>
#undef DEBUG_SPEW
#ifdef DEBUG_SPEW
#include <stdio.h>
#endif
#include "async-getprop.h"
#define NEED_REPLIES
#include <X11/Xlibint.h>
#ifndef NULL
#define NULL ((void*)0)
#endif
typedef struct _ListNode ListNode;
typedef struct _AgPerDisplayData AgPerDisplayData;
struct _ListNode
{
ListNode *next;
};
struct _AgGetPropertyTask
{
ListNode node;
AgPerDisplayData *dd;
Window window;
Atom property;
unsigned long request_seq;
int error;
Atom actual_type;
int actual_format;
unsigned long n_items;
unsigned long bytes_after;
char *data;
Bool have_reply;
};
struct _AgPerDisplayData
{
ListNode node;
_XAsyncHandler async;
Display *display;
ListNode *pending_tasks;
ListNode *pending_tasks_tail;
ListNode *completed_tasks;
ListNode *completed_tasks_tail;
int n_tasks_pending;
int n_tasks_completed;
};
static ListNode *display_datas = NULL;
static ListNode *display_datas_tail = NULL;
static void
append_to_list (ListNode **head,
ListNode **tail,
ListNode *task)
{
task->next = NULL;
if (*tail == NULL)
{
assert (*head == NULL);
*head = task;
*tail = task;
}
else
{
(*tail)->next = task;
*tail = task;
}
}
static void
remove_from_list (ListNode **head,
ListNode **tail,
ListNode *task)
{
ListNode *prev;
ListNode *node;
prev = NULL;
node = *head;
while (node != NULL)
{
if (node == task)
{
if (prev)
prev->next = node->next;
else
*head = node->next;
if (node == *tail)
*tail = prev;
break;
}
prev = node;
node = node->next;
}
/* can't remove what's not there */
assert (node != NULL);
node->next = NULL;
}
static void
move_to_completed (AgPerDisplayData *dd,
AgGetPropertyTask *task)
{
remove_from_list (&dd->pending_tasks,
&dd->pending_tasks_tail,
&task->node);
append_to_list (&dd->completed_tasks,
&dd->completed_tasks_tail,
&task->node);
dd->n_tasks_pending -= 1;
dd->n_tasks_completed += 1;
}
static AgGetPropertyTask*
find_pending_by_request_sequence (AgPerDisplayData *dd,
unsigned long request_seq)
{
ListNode *node;
/* if the sequence is after our last pending task, we
* aren't going to find a match
*/
{
AgGetPropertyTask *task = (AgGetPropertyTask*) dd->pending_tasks_tail;
if (task != NULL)
{
if (task->request_seq < request_seq)
return NULL;
else if (task->request_seq == request_seq)
return task; /* why not check this */
}
}
/* Generally we should get replies in the order we sent
* requests, so we should usually be using the task
* at the head of the list, if we use any task at all.
* I'm not sure this is 100% guaranteed, if it is,
* it would be a big speedup.
*/
node = dd->pending_tasks;
while (node != NULL)
{
AgGetPropertyTask *task = (AgGetPropertyTask*) node;
if (task->request_seq == request_seq)
return task;
node = node->next;
}
return NULL;
}
static Bool
async_get_property_handler (Display *dpy,
xReply *rep,
char *buf,
int len,
XPointer data)
{
xGetPropertyReply replbuf;
xGetPropertyReply *reply;
AgGetPropertyTask *task;
AgPerDisplayData *dd;
int bytes_read;
dd = (AgPerDisplayData*) data;
#if 0
printf ("%s: seeing request seq %ld buflen %d\n", __FUNCTION__,
dpy->last_request_read, len);
#endif
task = find_pending_by_request_sequence (dd, dpy->last_request_read);
if (task == NULL)
return False;
assert (dpy->last_request_read == task->request_seq);
task->have_reply = True;
move_to_completed (dd, task);
/* read bytes so far */
bytes_read = SIZEOF (xReply);
if (rep->generic.type == X_Error)
{
xError errbuf;
task->error = rep->error.errorCode;
#ifdef DEBUG_SPEW
printf ("%s: error code = %d (ignoring error, eating %d bytes, generic.length = %ld)\n",
__FUNCTION__, task->error, (SIZEOF (xError) - bytes_read),
rep->generic.length);
#endif
/* We return True (meaning we consumed the reply)
* because otherwise it would invoke the X error handler,
* and an async API is useless if you have to synchronously
* trap X errors. Also GetProperty can always fail, pretty
* much, so trapping errors is always what you want.
*
* We have to eat all the error reply data here.
* (kind of a charade as we know sizeof(xError) == sizeof(xReply))
*
* Passing discard = True seems to break things; I don't understand
* why, because there should be no extra data in an error reply,
* right?
*/
_XGetAsyncReply (dpy, (char *)&errbuf, rep, buf, len,
(SIZEOF (xError) - bytes_read) >> 2, /* in 32-bit words */
False); /* really seems like it should be True */
return True;
}
#ifdef DEBUG_SPEW
printf ("%s: already read %d bytes reading %d more for total of %d; generic.length = %ld\n",
__FUNCTION__, bytes_read, (SIZEOF (xGetPropertyReply) - bytes_read) >> 2,
SIZEOF (xGetPropertyReply), rep->generic.length);
#endif
/* (kind of a silly as we know sizeof(xGetPropertyReply) == sizeof(xReply)) */
reply = (xGetPropertyReply *)
_XGetAsyncReply (dpy, (char *)&replbuf, rep, buf, len,
(SIZEOF (xGetPropertyReply) - bytes_read) >> 2, /* in 32-bit words */
False); /* False means expecting more data to follow,
* don't eat the rest of the reply
*/
bytes_read = SIZEOF (xGetPropertyReply);
#ifdef DEBUG_SPEW
printf ("%s: have reply propertyType = %ld format = %d n_items = %ld\n",
__FUNCTION__, reply->propertyType, reply->format, reply->nItems);
#endif
assert (task->data == NULL);
/* This is all copied from XGetWindowProperty(). Not sure we should
* LockDisplay(). Not sure I'm passing the right args to
* XGetAsyncData(). Not sure about a lot of things.
*/
/* LockDisplay (dpy); */
if (reply->propertyType != None)
{
long nbytes, netbytes;
/* this alignment macro from orbit2 */
#define ALIGN_VALUE(this, boundary) \
(( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
switch (reply->format)
{
/*
* One extra byte is malloced than is needed to contain the property
* data, but this last byte is null terminated and convenient for
* returning string properties, so the client doesn't then have to
* recopy the string to make it null terminated.
*/
case 8:
nbytes = reply->nItems;
/* there's padding to word boundary */
netbytes = ALIGN_VALUE (nbytes, 4);
if (nbytes + 1 > 0 &&
(task->data = (char *) Xmalloc ((unsigned)nbytes + 1)))
{
#ifdef DEBUG_SPEW
printf ("%s: already read %d bytes using %ld, more eating %ld more\n",
__FUNCTION__, bytes_read, nbytes, netbytes);
#endif
/* _XReadPad (dpy, (char *) task->data, netbytes); */
_XGetAsyncData (dpy, task->data, buf, len,
bytes_read, nbytes,
netbytes);
}
break;
case 16:
nbytes = reply->nItems * sizeof (short);
netbytes = reply->nItems << 1;
netbytes = ALIGN_VALUE (netbytes, 4); /* align to word boundary */
if (nbytes + 1 > 0 &&
(task->data = (char *) Xmalloc ((unsigned)nbytes + 1)))
{
#ifdef DEBUG_SPEW
printf ("%s: already read %d bytes using %ld more, eating %ld more\n",
__FUNCTION__, bytes_read, nbytes, netbytes);
#endif
/* _XRead16Pad (dpy, (short *) task->data, netbytes); */
_XGetAsyncData (dpy, task->data, buf, len,
bytes_read, nbytes, netbytes);
}
break;
case 32:
/* NOTE buffer is in longs to match XGetWindowProperty() */
nbytes = reply->nItems * sizeof (long);
netbytes = reply->nItems << 2; /* wire size is always 32 bits though */
if (nbytes + 1 > 0 &&
(task->data = (char *) Xmalloc ((unsigned)nbytes + 1)))
{
#ifdef DEBUG_SPEW
printf ("%s: already read %d bytes using %ld more, eating %ld more\n",
__FUNCTION__, bytes_read, nbytes, netbytes);
#endif
/* We have to copy the XGetWindowProperty() crackrock
* and get format 32 as long even on 64-bit platforms.
*/
if (sizeof (long) == 8)
{
char *netdata;
char *lptr;
char *end_lptr;
/* Store the 32-bit values in the end of the array */
netdata = task->data + nbytes / 2;
_XGetAsyncData (dpy, netdata, buf, len,
bytes_read, netbytes,
netbytes);
/* Now move the 32-bit values to the front */
lptr = task->data;
end_lptr = task->data + nbytes;
while (lptr != end_lptr)
{
*(long*) lptr = *(CARD32*) netdata;
lptr += sizeof (long);
netdata += sizeof (CARD32);
}
}
else
{
/* Here the wire format matches our actual format */
_XGetAsyncData (dpy, task->data, buf, len,
bytes_read, netbytes,
netbytes);
}
}
break;
default:
/*
* This part of the code should never be reached. If it is,
* the server sent back a property with an invalid format.
* This is a BadImplementation error.
*
* However this async GetProperty API doesn't report errors
* via the standard X mechanism, so don't do anything about
* it, other than store it in task->error.
*/
{
#if 0
xError error;
#endif
task->error = BadImplementation;
#if 0
error.sequenceNumber = task->request_seq;
error.type = X_Error;
error.majorCode = X_GetProperty;
error.minorCode = 0;
error.errorCode = BadImplementation;
_XError (dpy, &error);
#endif
}
nbytes = netbytes = 0L;
break;
}
if (task->data == NULL)
{
task->error = BadAlloc;
#ifdef DEBUG_SPEW
printf ("%s: already read %d bytes eating %ld\n",
__FUNCTION__, bytes_read, netbytes);
#endif
/* _XEatData (dpy, (unsigned long) netbytes); */
_XGetAsyncData (dpy, NULL, buf, len,
bytes_read, 0, netbytes);
/* UnlockDisplay (dpy); */
return BadAlloc; /* not Success */
}
(task->data)[nbytes] = '\0';
}
#ifdef DEBUG_SPEW
printf ("%s: have data\n", __FUNCTION__);
#endif
task->actual_type = reply->propertyType;
task->actual_format = reply->format;
task->n_items = reply->nItems;
task->bytes_after = reply->bytesAfter;
/* UnlockDisplay (dpy); */
return True;
}
static AgPerDisplayData*
get_display_data (Display *display,
Bool create)
{
ListNode *node;
AgPerDisplayData *dd;
node = display_datas;
while (node != NULL)
{
dd = (AgPerDisplayData*) node;
if (dd->display == display)
return dd;
node = node->next;
}
if (!create)
return NULL;
dd = Xcalloc (1, sizeof (AgPerDisplayData));
if (dd == NULL)
return NULL;
dd->display = display;
dd->async.next = display->async_handlers;
dd->async.handler = async_get_property_handler;
dd->async.data = (XPointer) dd;
dd->display->async_handlers = &dd->async;
append_to_list (&display_datas,
&display_datas_tail,
&dd->node);
return dd;
}
static void
maybe_free_display_data (AgPerDisplayData *dd)
{
if (dd->pending_tasks == NULL &&
dd->completed_tasks == NULL)
{
DeqAsyncHandler (dd->display, &dd->async);
remove_from_list (&display_datas, &display_datas_tail,
&dd->node);
XFree (dd);
}
}
AgGetPropertyTask*
ag_task_create (Display *dpy,
Window window,
Atom property,
long offset,
long length,
Bool delete,
Atom req_type)
{
AgGetPropertyTask *task;
xGetPropertyReq *req;
AgPerDisplayData *dd;
/* Fire up our request */
LockDisplay (dpy);
dd = get_display_data (dpy, True);
if (dd == NULL)
{
UnlockDisplay (dpy);
return NULL;
}
GetReq (GetProperty, req);
req->window = window;
req->property = property;
req->type = req_type;
req->delete = delete;
req->longOffset = offset;
req->longLength = length;
/* Queue up our async task */
task = Xcalloc (1, sizeof (AgGetPropertyTask));
if (task == NULL)
{
UnlockDisplay (dpy);
return NULL;
}
task->dd = dd;
task->window = window;
task->property = property;
task->request_seq = dpy->request;
append_to_list (&dd->pending_tasks,
&dd->pending_tasks_tail,
&task->node);
dd->n_tasks_pending += 1;
UnlockDisplay (dpy);
SyncHandle ();
return task;
}
static void
free_task (AgGetPropertyTask *task)
{
remove_from_list (&task->dd->completed_tasks,
&task->dd->completed_tasks_tail,
&task->node);
task->dd->n_tasks_completed -= 1;
maybe_free_display_data (task->dd);
XFree (task);
}
Status
ag_task_get_reply_and_free (AgGetPropertyTask *task,
Atom *actual_type,
int *actual_format,
unsigned long *nitems,
unsigned long *bytesafter,
unsigned char **prop)
{
Display *dpy;
*prop = NULL;
dpy = task->dd->display; /* Xlib macros require a variable named "dpy" */
if (task->error != Success)
{
Status s = task->error;
free_task (task);
return s;
}
if (!task->have_reply)
{
free_task (task);
return BadAlloc; /* not Success */
}
*actual_type = task->actual_type;
*actual_format = task->actual_format;
*nitems = task->n_items;
*bytesafter = task->bytes_after;
*prop = (unsigned char*) task->data; /* pass out ownership of task->data */
SyncHandle ();
free_task (task);
return Success;
}
Bool
ag_task_have_reply (AgGetPropertyTask *task)
{
return task->have_reply;
}
Atom
ag_task_get_property (AgGetPropertyTask *task)
{
return task->property;
}
Window
ag_task_get_window (AgGetPropertyTask *task)
{
return task->window;
}
Display*
ag_task_get_display (AgGetPropertyTask *task)
{
return task->dd->display;
}
AgGetPropertyTask*
ag_get_next_completed_task (Display *display)
{
AgPerDisplayData *dd;
dd = get_display_data (display, False);
if (dd == NULL)
return NULL;
#ifdef DEBUG_SPEW
printf ("%d pending %d completed\n",
dd->n_tasks_pending,
dd->n_tasks_completed);
#endif
return (AgGetPropertyTask*) dd->completed_tasks;
}
void*
ag_Xmalloc (unsigned long bytes)
{
return (void*) Xmalloc (bytes);
}
void*
ag_Xmalloc0 (unsigned long bytes)
{
return (void*) Xcalloc (bytes, 1);
}

View File

@@ -1,67 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Asynchronous X property getting hack */
/*
* Copyright (C) 2002 Havoc Pennington
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation.
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of The Open Group shall not be
* used in advertising or otherwise to promote the sale, use or other dealings
* in this Software without prior written authorization from The Open Group.
*/
#ifndef ASYNC_GETPROP_H
#define ASYNC_GETPROP_H
#include <X11/Xlib.h>
#include <X11/Xutil.h>
typedef struct _AgGetPropertyTask AgGetPropertyTask;
AgGetPropertyTask* ag_task_create (Display *display,
Window window,
Atom property,
long offset,
long length,
Bool delete,
Atom req_type);
Status ag_task_get_reply_and_free (AgGetPropertyTask *task,
Atom *actual_type,
int *actual_format,
unsigned long *nitems,
unsigned long *bytesafter,
unsigned char **prop);
Bool ag_task_have_reply (AgGetPropertyTask *task);
Atom ag_task_get_property (AgGetPropertyTask *task);
Window ag_task_get_window (AgGetPropertyTask *task);
Display* ag_task_get_display (AgGetPropertyTask *task);
AgGetPropertyTask* ag_get_next_completed_task (Display *display);
/* so other headers don't have to include internal Xlib goo */
void* ag_Xmalloc (unsigned long bytes);
void* ag_Xmalloc0 (unsigned long bytes);
#endif

View File

@@ -39,6 +39,7 @@
#ifdef HAVE_WAYLAND
#include "wayland/meta-xwayland.h"
#include "wayland/meta-wayland-private.h"
#include "wayland/meta-xwayland-private.h"
#endif
static XIEvent *
@@ -1676,6 +1677,15 @@ meta_display_handle_xevent (MetaDisplay *display,
}
#endif
#ifdef HAVE_WAYLAND
if (meta_is_wayland_compositor () &&
meta_xwayland_selection_handle_event (event))
{
bypass_gtk = bypass_compositor = TRUE;
goto out;
}
#endif
display->current_time = event_get_time (display, event);
display->monitor_cache_invalidated = TRUE;

View File

@@ -50,6 +50,11 @@ meta_group_new (MetaDisplay *display,
group->group_leader = group_leader;
group->refcount = 1; /* owned by caller, hash table has only weak ref */
XWindowAttributes attrs;
XGetWindowAttributes (display->xdisplay, group_leader, &attrs);
XSelectInput (display->xdisplay, group_leader,
attrs.your_event_mask | PropertyChangeMask);
if (display->groups_by_leader == NULL)
display->groups_by_leader = g_hash_table_new (meta_unsigned_long_hash,
meta_unsigned_long_equal);

View File

@@ -60,10 +60,10 @@ SOFTWARE.
#ifndef _XATOMTYPE_H_
#define _XATOMTYPE_H_
#define BOOL long
#define SIGNEDINT long
#define UNSIGNEDINT unsigned long
#define RESOURCEID unsigned long
#define BOOL int32_t
#define SIGNEDINT int32_t
#define UNSIGNEDINT uint32_t
#define RESOURCEID uint32_t
/* this structure may be extended, but do not change the order */

View File

@@ -1,496 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2002 Havoc Pennington
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation.
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of The Open Group shall not be
* used in advertising or otherwise to promote the sale, use or other dealings
* in this Software without prior written authorization from The Open Group.
*/
#include "async-getprop.h"
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <assert.h>
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef NULL
#define NULL ((void*) 0)
#endif
#ifdef HAVE_BACKTRACE
#include <execinfo.h>
static void
print_backtrace (void)
{
void *bt[500];
int bt_size;
int i;
char **syms;
bt_size = backtrace (bt, 500);
syms = backtrace_symbols (bt, bt_size);
i = 0;
while (i < bt_size)
{
fprintf (stderr, " %s\n", syms[i]);
++i;
}
free (syms);
}
#else
static void
print_backtrace (void)
{
fprintf (stderr, "Not compiled with backtrace support\n");
}
#endif
static int error_trap_depth = 0;
static int
x_error_handler (Display *xdisplay,
XErrorEvent *error)
{
char buf[64];
XGetErrorText (xdisplay, error->error_code, buf, 63);
if (error_trap_depth == 0)
{
print_backtrace ();
fprintf (stderr, "Unexpected X error: %s serial %ld error_code %d request_code %d minor_code %d)\n",
buf,
error->serial,
error->error_code,
error->request_code,
error->minor_code);
exit (1);
}
return 1; /* return value is meaningless */
}
static void
error_trap_push (Display *xdisplay)
{
++error_trap_depth;
}
static void
error_trap_pop (Display *xdisplay)
{
if (error_trap_depth == 0)
{
fprintf (stderr, "Error trap underflow!\n");
exit (1);
}
XSync (xdisplay, False); /* get all errors out of the queue */
--error_trap_depth;
}
static char*
my_strdup (const char *str)
{
char *s;
s = malloc (strlen (str) + 1);
if (s == NULL)
{
fprintf (stderr, "malloc failed\n");
exit (1);
}
strcpy (s, str);
return s;
}
static char*
atom_name (Display *display,
Atom atom)
{
if (atom == None)
{
return my_strdup ("None");
}
else
{
char *xname;
char *ret;
error_trap_push (display);
xname = XGetAtomName (display, atom);
error_trap_pop (display);
if (xname == NULL)
return my_strdup ("[unknown atom]");
ret = my_strdup (xname);
XFree (xname);
return ret;
}
}
#define ELAPSED(start_time, current_time) \
(((((double)current_time.tv_sec - start_time.tv_sec) * 1000000 + \
(current_time.tv_usec - start_time.tv_usec))) / 1000.0)
static struct timeval program_start_time;
static Bool
try_get_reply (Display *xdisplay,
AgGetPropertyTask *task)
{
if (ag_task_have_reply (task))
{
int result;
Atom actual_type;
int actual_format;
unsigned long n_items;
unsigned long bytes_after;
unsigned char *data;
char *name;
struct timeval current_time;
gettimeofday (&current_time, NULL);
printf (" %gms (we have a reply for property %ld)\n",
ELAPSED (program_start_time, current_time),
ag_task_get_property (task));
data = NULL;
name = atom_name (xdisplay,
ag_task_get_property (task));
printf (" %s on 0x%lx:\n", name,
ag_task_get_window (task));
free (name);
result = ag_task_get_reply_and_free (task,
&actual_type,
&actual_format,
&n_items,
&bytes_after,
&data);
task = NULL;
if (result != Success)
{
fprintf (stderr, " error code %d getting reply\n", result);
}
else
{
name = atom_name (xdisplay, actual_type);
printf (" actual_type = %s\n", name);
free (name);
printf (" actual_format = %d\n", actual_format);
printf (" n_items = %lu\n", n_items);
printf (" bytes_after = %lu\n", bytes_after);
printf (" data = \"%s\"\n", data ? (char*) data : "NULL");
}
return True;
}
return False;
}
static void run_speed_comparison (Display *xdisplay,
Window window);
int
main (int argc, char **argv)
{
Display *xdisplay;
int i;
int n_left;
int n_props;
Window window;
const char *window_str;
char *end;
Atom *props;
struct timeval current_time;
if (argc < 2)
{
fprintf (stderr, "specify window ID\n");
return 1;
}
window_str = argv[1];
end = NULL;
window = strtoul (window_str, &end, 0);
if (end == NULL || *end != '\0')
{
fprintf (stderr, "\"%s\" does not parse as a window ID\n", window_str);
return 1;
}
xdisplay = XOpenDisplay (NULL);
if (xdisplay == NULL)
{
fprintf (stderr, "Could not open display\n");
return 1;
}
if (getenv ("MUTTER_SYNC") != NULL)
XSynchronize (xdisplay, True);
XSetErrorHandler (x_error_handler);
n_props = 0;
props = XListProperties (xdisplay, window, &n_props);
if (n_props == 0 || props == NULL)
{
fprintf (stderr, "Window has no properties\n");
return 1;
}
gettimeofday (&program_start_time, NULL);
i = 0;
while (i < n_props)
{
gettimeofday (&current_time, NULL);
printf (" %gms (sending request for property %ld)\n",
ELAPSED (program_start_time, current_time),
props[i]);
if (ag_task_create (xdisplay,
window, props[i],
0, 0xffffffff,
False,
AnyPropertyType) == NULL)
{
fprintf (stderr, "Failed to send request\n");
return 1;
}
++i;
}
XFree (props);
props = NULL;
n_left = n_props;
while (TRUE)
{
XEvent xevent;
int connection;
fd_set set;
AgGetPropertyTask *task;
/* Mop up event queue */
while (XPending (xdisplay) > 0)
{
XNextEvent (xdisplay, &xevent);
gettimeofday (&current_time, NULL);
printf (" %gms (processing event type %d)\n",
ELAPSED (program_start_time, current_time),
xevent.xany.type);
}
while ((task = ag_get_next_completed_task (xdisplay)))
{
try_get_reply (xdisplay, task);
n_left -= 1;
}
if (n_left == 0)
{
printf ("All %d replies received.\n", n_props);
break;
}
/* Wake up if we may have a reply */
connection = ConnectionNumber (xdisplay);
FD_ZERO (&set);
FD_SET (connection, &set);
gettimeofday (&current_time, NULL);
printf (" %gms (blocking for data %d left)\n",
ELAPSED (program_start_time, current_time), n_left);
select (connection + 1, &set, NULL, NULL, NULL);
}
run_speed_comparison (xdisplay, window);
return 0;
}
/* This function doesn't have all the printf's
* and other noise, it just compares async to sync
*/
static void
run_speed_comparison (Display *xdisplay,
Window window)
{
int i;
int n_props;
struct timeval start, end;
int n_left;
/* We just use atom values (0 to n_props) % 200, many are probably
* BadAtom, that's fine, but the %200 keeps most of them valid. The
* async case is about twice as advantageous when using valid atoms
* (or the issue may be that it's more advantageous when the
* properties are present and data is transmitted).
*/
n_props = 4000;
printf ("Timing with %d property requests\n", n_props);
gettimeofday (&start, NULL);
i = 0;
while (i < n_props)
{
if (ag_task_create (xdisplay,
window, (Atom) i % 200,
0, 0xffffffff,
False,
AnyPropertyType) == NULL)
{
fprintf (stderr, "Failed to send request\n");
exit (1);
}
++i;
}
n_left = n_props;
while (TRUE)
{
int connection;
fd_set set;
XEvent xevent;
AgGetPropertyTask *task;
/* Mop up event queue */
while (XPending (xdisplay) > 0)
XNextEvent (xdisplay, &xevent);
while ((task = ag_get_next_completed_task (xdisplay)))
{
Atom actual_type;
int actual_format;
unsigned long n_items;
unsigned long bytes_after;
unsigned char *data;
assert (ag_task_have_reply (task));
data = NULL;
ag_task_get_reply_and_free (task,
&actual_type,
&actual_format,
&n_items,
&bytes_after,
&data);
if (data)
XFree (data);
n_left -= 1;
}
if (n_left == 0)
break;
/* Wake up if we may have a reply */
connection = ConnectionNumber (xdisplay);
FD_ZERO (&set);
FD_SET (connection, &set);
select (connection + 1, &set, NULL, NULL, NULL);
}
gettimeofday (&end, NULL);
printf ("Async time: %gms\n",
ELAPSED (start, end));
gettimeofday (&start, NULL);
error_trap_push (xdisplay);
i = 0;
while (i < n_props)
{
Atom actual_type;
int actual_format;
unsigned long n_items;
unsigned long bytes_after;
unsigned char *data;
data = NULL;
if (XGetWindowProperty (xdisplay, window,
(Atom) i % 200,
0, 0xffffffff,
False,
AnyPropertyType,
&actual_type,
&actual_format,
&n_items,
&bytes_after,
&data) == Success)
{
if (data)
XFree (data);
}
++i;
}
error_trap_pop (xdisplay);
gettimeofday (&end, NULL);
printf ("Sync time: %gms\n",
ELAPSED (start, end));
}

View File

@@ -428,10 +428,10 @@ reload_net_wm_pid (MetaWindow *window,
{
if (value->type != META_PROP_VALUE_INVALID)
{
gulong cardinal = (int) value->v.cardinal;
uint32_t cardinal = (int) value->v.cardinal;
if (cardinal <= 0)
meta_warning ("Application set a bogus _NET_WM_PID %lu\n",
meta_warning ("Application set a bogus _NET_WM_PID %u\n",
cardinal);
else
{
@@ -449,7 +449,7 @@ reload_net_wm_user_time (MetaWindow *window,
{
if (value->type != META_PROP_VALUE_INVALID)
{
gulong cardinal = value->v.cardinal;
uint32_t cardinal = value->v.cardinal;
meta_window_set_user_time (window, cardinal);
}
}
@@ -670,7 +670,7 @@ reload_opaque_region (MetaWindow *window,
if (value->type != META_PROP_VALUE_INVALID)
{
gulong *region = value->v.cardinal_list.cardinals;
uint32_t *region = value->v.cardinal_list.cardinals;
int nitems = value->v.cardinal_list.n_cardinals;
cairo_rectangle_int_t *rects;
@@ -862,7 +862,7 @@ reload_mwm_hints (MetaWindow *window,
if (hints->flags & MWM_HINTS_DECORATIONS)
{
meta_verbose ("Window %s sets MWM_HINTS_DECORATIONS 0x%lx\n",
meta_verbose ("Window %s sets MWM_HINTS_DECORATIONS 0x%x\n",
window->desc, hints->decorations);
if (hints->decorations == 0)
@@ -878,7 +878,7 @@ reload_mwm_hints (MetaWindow *window,
{
gboolean toggle_value;
meta_verbose ("Window %s sets MWM_HINTS_FUNCTIONS 0x%lx\n",
meta_verbose ("Window %s sets MWM_HINTS_FUNCTIONS 0x%x\n",
window->desc, hints->functions);
/* If _ALL is specified, then other flags indicate what to turn off;

View File

@@ -1283,7 +1283,7 @@ meta_window_x11_update_struts (MetaWindow *window)
GSList *old_struts;
GSList *new_struts;
GSList *old_iter, *new_iter;
gulong *struts = NULL;
uint32_t *struts = NULL;
int nitems;
gboolean changed;
@@ -1346,7 +1346,7 @@ meta_window_x11_update_struts (MetaWindow *window)
new_struts = g_slist_prepend (new_struts, temp);
}
meta_verbose ("_NET_WM_STRUT_PARTIAL struts %lu %lu %lu %lu for "
meta_verbose ("_NET_WM_STRUT_PARTIAL struts %u %u %u %u for "
"window %s\n",
struts[0], struts[1], struts[2], struts[3],
window->desc);
@@ -1405,7 +1405,7 @@ meta_window_x11_update_struts (MetaWindow *window)
new_struts = g_slist_prepend (new_struts, temp);
}
meta_verbose ("_NET_WM_STRUT struts %lu %lu %lu %lu for window %s\n",
meta_verbose ("_NET_WM_STRUT struts %u %u %u %u for window %s\n",
struts[0], struts[1], struts[2], struts[3],
window->desc);
}
@@ -2774,7 +2774,7 @@ maybe_filter_xwindow (MetaDisplay *display,
*/
if (!must_be_viewable || attrs->map_state == IsViewable)
{
gulong old_state;
uint32_t old_state;
if (!meta_prop_get_cardinal_with_atom_type (display, xwindow,
display->atom_WM_STATE,
@@ -2910,7 +2910,7 @@ meta_window_x11_new (MetaDisplay *display,
if (must_be_viewable && attrs.map_state != IsViewable)
{
/* Only manage if WM_STATE is IconicState or NormalState */
gulong state;
uint32_t state;
/* WM_STATE isn't a cardinal, it's type WM_STATE, but is an int */
if (!(meta_prop_get_cardinal_with_atom_type (display, xwindow,

View File

@@ -78,17 +78,21 @@ from The Open Group.
*/
#include <config.h>
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include "xprops.h"
#include <meta/errors.h>
#include "util-private.h"
#include "async-getprop.h"
#include "ui.h"
#include "mutter-Xatomtype.h"
#include <X11/Xatom.h>
#include <string.h>
#include "window-private.h"
#include <X11/Xatom.h>
#include <X11/Xlib-xcb.h>
typedef struct
{
MetaDisplay *display;
@@ -168,13 +172,50 @@ validate_or_free_results (GetPropertyResults *results,
if (results->prop)
{
XFree (results->prop);
g_free (results->prop);
results->prop = NULL;
}
return FALSE;
}
static xcb_get_property_cookie_t
async_get_property (xcb_connection_t *xcb_conn, Window xwindow,
Atom xatom, Atom required_type)
{
return xcb_get_property (xcb_conn, False, xwindow,
xatom, required_type, 0, G_MAXUINT32);
}
static gboolean
async_get_property_finish (xcb_connection_t *xcb_conn,
xcb_get_property_cookie_t cookie,
GetPropertyResults *results)
{
xcb_get_property_reply_t *reply;
xcb_generic_error_t *error;
reply = xcb_get_property_reply (xcb_conn, cookie, &error);
if (error)
{
free (error);
return FALSE;
}
results->n_items = reply->value_len;
results->type = reply->type;
results->bytes_after = reply->bytes_after;
results->format = reply->format;
results->prop = NULL;
if (results->type != None)
results->prop = g_memdup (xcb_get_property_value (reply),
xcb_get_property_value_length (reply));
free (reply);
return (results->prop != NULL);
}
static gboolean
get_property (MetaDisplay *display,
Window xwindow,
@@ -182,6 +223,9 @@ get_property (MetaDisplay *display,
Atom req_type,
GetPropertyResults *results)
{
xcb_get_property_cookie_t cookie;
xcb_connection_t *xcb_conn = XGetXCBConnection (display->xdisplay);
results->display = display;
results->xwindow = xwindow;
results->xatom = xatom;
@@ -191,87 +235,37 @@ get_property (MetaDisplay *display,
results->bytes_after = 0;
results->format = 0;
meta_error_trap_push (display);
if (XGetWindowProperty (display->xdisplay, xwindow, xatom,
0, G_MAXLONG,
False, req_type, &results->type, &results->format,
&results->n_items,
&results->bytes_after,
&results->prop) != Success ||
results->type == None)
{
if (results->prop)
XFree (results->prop);
meta_error_trap_pop_with_return (display);
return FALSE;
}
if (meta_error_trap_pop_with_return (display) != Success)
{
if (results->prop)
XFree (results->prop);
return FALSE;
}
return TRUE;
cookie = async_get_property (xcb_conn, xwindow, xatom, req_type);
return async_get_property_finish (xcb_conn, cookie, results);
}
static gboolean
atom_list_from_results (GetPropertyResults *results,
Atom **atoms_p,
uint32_t **atoms_p,
int *n_atoms_p)
{
if (!validate_or_free_results (results, 32, XA_ATOM, FALSE))
return FALSE;
*atoms_p = (Atom*) results->prop;
*atoms_p = (uint32_t*) results->prop;
*n_atoms_p = results->n_items;
results->prop = NULL;
return TRUE;
}
gboolean
meta_prop_get_atom_list (MetaDisplay *display,
Window xwindow,
Atom xatom,
Atom **atoms_p,
int *n_atoms_p)
{
GetPropertyResults results;
*atoms_p = NULL;
*n_atoms_p = 0;
if (!get_property (display, xwindow, xatom, XA_ATOM,
&results))
return FALSE;
return atom_list_from_results (&results, atoms_p, n_atoms_p);
}
static gboolean
cardinal_list_from_results (GetPropertyResults *results,
gulong **cardinals_p,
uint32_t **cardinals_p,
int *n_cardinals_p)
{
if (!validate_or_free_results (results, 32, XA_CARDINAL, FALSE))
return FALSE;
*cardinals_p = (gulong*) results->prop;
*cardinals_p = (uint32_t *) results->prop;
*n_cardinals_p = results->n_items;
results->prop = NULL;
#if GLIB_SIZEOF_LONG == 8
/* Xlib sign-extends format=32 items, but we want them unsigned */
{
int i;
for (i = 0; i < *n_cardinals_p; i++)
(*cardinals_p)[i] = (*cardinals_p)[i] & 0xffffffff;
}
#endif
return TRUE;
}
@@ -279,7 +273,7 @@ gboolean
meta_prop_get_cardinal_list (MetaDisplay *display,
Window xwindow,
Atom xatom,
gulong **cardinals_p,
uint32_t **cardinals_p,
int *n_cardinals_p)
{
GetPropertyResults results;
@@ -298,19 +292,11 @@ static gboolean
motif_hints_from_results (GetPropertyResults *results,
MotifWmHints **hints_p)
{
int real_size, max_size;
#define MAX_ITEMS sizeof (MotifWmHints)/sizeof (gulong)
*hints_p = NULL;
if (results->type == None || results->n_items <= 0)
{
meta_verbose ("Motif hints had unexpected type or n_items\n");
if (results->prop)
{
XFree (results->prop);
results->prop = NULL;
}
return FALSE;
}
@@ -318,26 +304,12 @@ motif_hints_from_results (GetPropertyResults *results,
* MotifWmHints than the one we expect, apparently. I'm not sure of
* the history behind it. See bug #89841 for example.
*/
*hints_p = ag_Xmalloc (sizeof (MotifWmHints));
*hints_p = calloc (1, sizeof (MotifWmHints));
if (*hints_p == NULL)
{
if (results->prop)
{
XFree (results->prop);
results->prop = NULL;
}
return FALSE;
}
real_size = results->n_items * sizeof (gulong);
max_size = MAX_ITEMS * sizeof (gulong);
memcpy (*hints_p, results->prop, MIN (real_size, max_size));
if (results->prop)
{
XFree (results->prop);
results->prop = NULL;
}
return FALSE;
memcpy(*hints_p, results->prop, MIN (sizeof (MotifWmHints),
results->n_items * sizeof (uint32_t)));
return TRUE;
}
@@ -367,8 +339,7 @@ latin1_string_from_results (GetPropertyResults *results,
if (!validate_or_free_results (results, 8, XA_STRING, FALSE))
return FALSE;
*str_p = (char*) results->prop;
results->prop = NULL;
*str_p = g_strndup ((char *) results->prop, results->n_items);
return TRUE;
}
@@ -409,36 +380,17 @@ utf8_string_from_results (GetPropertyResults *results,
meta_warning ("Property %s on window 0x%lx contained invalid UTF-8\n",
name, results->xwindow);
meta_XFree (name);
XFree (results->prop);
g_free (results->prop);
results->prop = NULL;
return FALSE;
}
*str_p = (char*) results->prop;
results->prop = NULL;
*str_p = g_strndup ((char *) results->prop, results->n_items);
return TRUE;
}
gboolean
meta_prop_get_utf8_string (MetaDisplay *display,
Window xwindow,
Atom xatom,
char **str_p)
{
GetPropertyResults results;
*str_p = NULL;
if (!get_property (display, xwindow, xatom,
display->atom_UTF8_STRING,
&results))
return FALSE;
return utf8_string_from_results (&results, str_p);
}
/* this one freakishly returns g_malloc memory */
static gboolean
utf8_list_from_results (GetPropertyResults *results,
@@ -492,7 +444,7 @@ utf8_list_from_results (GetPropertyResults *results,
meta_warning ("Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n",
name, results->xwindow, i);
meta_XFree (name);
meta_XFree (results->prop);
g_free (results->prop);
results->prop = NULL;
g_strfreev (retval);
@@ -508,7 +460,7 @@ utf8_list_from_results (GetPropertyResults *results,
*str_p = retval;
*n_str_p = i;
meta_XFree (results->prop);
g_free (results->prop);
results->prop = NULL;
return TRUE;
@@ -534,81 +486,6 @@ meta_prop_get_utf8_list (MetaDisplay *display,
return utf8_list_from_results (&results, str_p, n_str_p);
}
/* this one freakishly returns g_malloc memory */
static gboolean
latin1_list_from_results (GetPropertyResults *results,
char ***str_p,
int *n_str_p)
{
int i;
int n_strings;
char **retval;
const char *p;
*str_p = NULL;
*n_str_p = 0;
if (!validate_or_free_results (results, 8, XA_STRING, FALSE))
return FALSE;
/* I'm not sure this is right, but I'm guessing the
* property is nul-separated
*/
i = 0;
n_strings = 0;
while (i < (int) results->n_items)
{
if (results->prop[i] == '\0')
++n_strings;
++i;
}
if (results->prop[results->n_items - 1] != '\0')
++n_strings;
/* we're guaranteed that results->prop has a nul on the end
* by XGetWindowProperty
*/
retval = g_new0 (char*, n_strings + 1);
p = (char *)results->prop;
i = 0;
while (i < n_strings)
{
retval[i] = g_strdup (p);
p = p + strlen (p) + 1;
++i;
}
*str_p = retval;
*n_str_p = i;
meta_XFree (results->prop);
results->prop = NULL;
return TRUE;
}
gboolean
meta_prop_get_latin1_list (MetaDisplay *display,
Window xwindow,
Atom xatom,
char ***str_p,
int *n_str_p)
{
GetPropertyResults results;
*str_p = NULL;
if (!get_property (display, xwindow, xatom,
XA_STRING, &results))
return FALSE;
return latin1_list_from_results (&results, str_p, n_str_p);
}
void
meta_prop_set_utf8_string_hint (MetaDisplay *display,
Window xwindow,
@@ -631,7 +508,7 @@ window_from_results (GetPropertyResults *results,
return FALSE;
*window_p = *(Window*) results->prop;
XFree (results->prop);
g_free (results->prop);
results->prop = NULL;
return TRUE;
@@ -647,7 +524,7 @@ counter_from_results (GetPropertyResults *results,
return FALSE;
*counter_p = *(XSyncCounter*) results->prop;
XFree (results->prop);
g_free (results->prop);
results->prop = NULL;
return TRUE;
@@ -655,7 +532,7 @@ counter_from_results (GetPropertyResults *results,
static gboolean
counter_list_from_results (GetPropertyResults *results,
XSyncCounter **counters_p,
uint32_t **counters_p,
int *n_counters_p)
{
if (!validate_or_free_results (results, 32,
@@ -663,7 +540,7 @@ counter_list_from_results (GetPropertyResults *results,
FALSE))
return FALSE;
*counters_p = (XSyncCounter*) results->prop;
*counters_p = (uint32_t *) results->prop;
*n_counters_p = results->n_items;
results->prop = NULL;
@@ -691,7 +568,7 @@ gboolean
meta_prop_get_cardinal (MetaDisplay *display,
Window xwindow,
Atom xatom,
gulong *cardinal_p)
uint32_t *cardinal_p)
{
return meta_prop_get_cardinal_with_atom_type (display, xwindow, xatom,
XA_CARDINAL, cardinal_p);
@@ -700,17 +577,13 @@ meta_prop_get_cardinal (MetaDisplay *display,
static gboolean
cardinal_with_atom_type_from_results (GetPropertyResults *results,
Atom prop_type,
gulong *cardinal_p)
uint32_t *cardinal_p)
{
if (!validate_or_free_results (results, 32, prop_type, TRUE))
return FALSE;
*cardinal_p = *(gulong*) results->prop;
#if GLIB_SIZEOF_LONG == 8
/* Xlib sign-extends format=32 items, but we want them unsigned */
*cardinal_p &= 0xffffffff;
#endif
XFree (results->prop);
*cardinal_p = *((uint32_t *) results->prop);
g_free (results->prop);
results->prop = NULL;
return TRUE;
@@ -721,7 +594,7 @@ meta_prop_get_cardinal_with_atom_type (MetaDisplay *display,
Window xwindow,
Atom xatom,
Atom prop_type,
gulong *cardinal_p)
uint32_t *cardinal_p)
{
GetPropertyResults results;
@@ -779,46 +652,6 @@ text_property_from_results (GetPropertyResults *results,
return *utf8_str_p != NULL;
}
gboolean
meta_prop_get_text_property (MetaDisplay *display,
Window xwindow,
Atom xatom,
char **utf8_str_p)
{
GetPropertyResults results;
if (!get_property (display, xwindow, xatom, AnyPropertyType,
&results))
return FALSE;
return text_property_from_results (&results, utf8_str_p);
}
/* From Xmd.h */
#ifndef cvtINT32toInt
#if SIZEOF_VOID_P == 8
#define cvtINT8toInt(val) ((((unsigned int)val) & 0x00000080) ? (((unsigned int)val) | 0xffffffffffffff00) : ((unsigned int)val))
#define cvtINT16toInt(val) ((((unsigned int)val) & 0x00008000) ? (((unsigned int)val) | 0xffffffffffff0000) : ((unsigned int)val))
#define cvtINT32toInt(val) ((((unsigned int)val) & 0x80000000) ? (((unsigned int)val) | 0xffffffff00000000) : ((unsigned int)val))
#define cvtINT8toShort(val) cvtINT8toInt(val)
#define cvtINT16toShort(val) cvtINT16toInt(val)
#define cvtINT32toShort(val) cvtINT32toInt(val)
#define cvtINT8toLong(val) cvtINT8toInt(val)
#define cvtINT16toLong(val) cvtINT16toInt(val)
#define cvtINT32toLong(val) cvtINT32toInt(val)
#else
#define cvtINT8toInt(val) (val)
#define cvtINT16toInt(val) (val)
#define cvtINT32toInt(val) (val)
#define cvtINT8toShort(val) (val)
#define cvtINT16toShort(val) (val)
#define cvtINT32toShort(val) (val)
#define cvtINT8toLong(val) (val)
#define cvtINT16toLong(val) (val)
#define cvtINT32toLong(val) (val)
#endif /* SIZEOF_VOID_P == 8 */
#endif /* cvtINT32toInt() */
static gboolean
wm_hints_from_results (GetPropertyResults *results,
XWMHints **hints_p)
@@ -838,23 +671,23 @@ wm_hints_from_results (GetPropertyResults *results,
(int) results->n_items, NumPropWMHintsElements - 1);
if (results->prop)
{
XFree (results->prop);
g_free (results->prop);
results->prop = NULL;
}
return FALSE;
}
hints = ag_Xmalloc0 (sizeof (XWMHints));
hints = calloc (1, sizeof (XWMHints));
raw = (xPropWMHints*) results->prop;
hints->flags = raw->flags;
hints->input = (raw->input ? True : False);
hints->initial_state = cvtINT32toInt (raw->initialState);
hints->initial_state = raw->initialState;
hints->icon_pixmap = raw->iconPixmap;
hints->icon_window = raw->iconWindow;
hints->icon_x = cvtINT32toInt (raw->iconX);
hints->icon_y = cvtINT32toInt (raw->iconY);
hints->icon_x = raw->iconX;
hints->icon_y = raw->iconY;
hints->icon_mask = raw->iconMask;
if (results->n_items >= NumPropWMHintsElements)
hints->window_group = raw->windowGroup;
@@ -863,7 +696,7 @@ wm_hints_from_results (GetPropertyResults *results,
if (results->prop)
{
XFree (results->prop);
g_free (results->prop);
results->prop = NULL;
}
@@ -872,23 +705,6 @@ wm_hints_from_results (GetPropertyResults *results,
return TRUE;
}
gboolean
meta_prop_get_wm_hints (MetaDisplay *display,
Window xwindow,
Atom xatom,
XWMHints **hints_p)
{
GetPropertyResults results;
*hints_p = NULL;
if (!get_property (display, xwindow, xatom, XA_WM_HINTS,
&results))
return FALSE;
return wm_hints_from_results (&results, hints_p);
}
static gboolean
class_hint_from_results (GetPropertyResults *results,
XClassHint *class_hint)
@@ -902,9 +718,9 @@ class_hint_from_results (GetPropertyResults *results,
return FALSE;
len_name = strlen ((char *) results->prop);
if (! (class_hint->res_name = ag_Xmalloc (len_name+1)))
if (! (class_hint->res_name = malloc (len_name+1)))
{
XFree (results->prop);
g_free (results->prop);
results->prop = NULL;
return FALSE;
}
@@ -916,41 +732,23 @@ class_hint_from_results (GetPropertyResults *results,
len_class = strlen ((char *)results->prop + len_name + 1);
if (! (class_hint->res_class = ag_Xmalloc(len_class+1)))
if (! (class_hint->res_class = malloc(len_class+1)))
{
XFree(class_hint->res_name);
class_hint->res_name = NULL;
XFree (results->prop);
g_free (results->prop);
results->prop = NULL;
return FALSE;
}
strcpy (class_hint->res_class, (char *)results->prop + len_name + 1);
XFree (results->prop);
g_free (results->prop);
results->prop = NULL;
return TRUE;
}
gboolean
meta_prop_get_class_hint (MetaDisplay *display,
Window xwindow,
Atom xatom,
XClassHint *class_hint)
{
GetPropertyResults results;
class_hint->res_class = NULL;
class_hint->res_name = NULL;
if (!get_property (display, xwindow, xatom, XA_STRING,
&results))
return FALSE;
return class_hint_from_results (&results, class_hint);
}
static gboolean
size_hints_from_results (GetPropertyResults *results,
XSizeHints **hints_p,
@@ -970,37 +768,36 @@ size_hints_from_results (GetPropertyResults *results,
raw = (xPropSizeHints*) results->prop;
hints = ag_Xmalloc (sizeof (XSizeHints));
hints = malloc (sizeof (XSizeHints));
/* XSizeHints misdeclares these as int instead of long */
hints->flags = raw->flags;
hints->x = cvtINT32toInt (raw->x);
hints->y = cvtINT32toInt (raw->y);
hints->width = cvtINT32toInt (raw->width);
hints->height = cvtINT32toInt (raw->height);
hints->min_width = cvtINT32toInt (raw->minWidth);
hints->min_height = cvtINT32toInt (raw->minHeight);
hints->max_width = cvtINT32toInt (raw->maxWidth);
hints->max_height = cvtINT32toInt (raw->maxHeight);
hints->width_inc = cvtINT32toInt (raw->widthInc);
hints->height_inc = cvtINT32toInt (raw->heightInc);
hints->min_aspect.x = cvtINT32toInt (raw->minAspectX);
hints->min_aspect.y = cvtINT32toInt (raw->minAspectY);
hints->max_aspect.x = cvtINT32toInt (raw->maxAspectX);
hints->max_aspect.y = cvtINT32toInt (raw->maxAspectY);
hints->x = raw->x;
hints->y = raw->y;
hints->width = raw->width;
hints->height = raw->height;
hints->min_width = raw->minWidth;
hints->min_height = raw->minHeight;
hints->max_width = raw->maxWidth;
hints->max_height = raw->maxHeight;
hints->width_inc = raw->widthInc;
hints->height_inc = raw->heightInc;
hints->min_aspect.x = raw->minAspectX;
hints->min_aspect.y = raw->minAspectY;
hints->max_aspect.x = raw->maxAspectX;
hints->max_aspect.y = raw->maxAspectY;
*flags_p = (USPosition | USSize | PAllHints);
if (results->n_items >= NumPropSizeElements)
{
hints->base_width= cvtINT32toInt (raw->baseWidth);
hints->base_height= cvtINT32toInt (raw->baseHeight);
hints->win_gravity= cvtINT32toInt (raw->winGravity);
hints->base_width = raw->baseWidth;
hints->base_height = raw->baseHeight;
hints->win_gravity = raw->winGravity;
*flags_p |= (PBaseSize | PWinGravity);
}
hints->flags &= (*flags_p); /* get rid of unwanted bits */
XFree (results->prop);
g_free (results->prop);
results->prop = NULL;
*hints_p = hints;
@@ -1008,37 +805,6 @@ size_hints_from_results (GetPropertyResults *results,
return TRUE;
}
gboolean
meta_prop_get_size_hints (MetaDisplay *display,
Window xwindow,
Atom xatom,
XSizeHints **hints_p,
gulong *flags_p)
{
GetPropertyResults results;
*hints_p = NULL;
*flags_p = 0;
if (!get_property (display, xwindow, xatom, XA_WM_SIZE_HINTS,
&results))
return FALSE;
return size_hints_from_results (&results, hints_p, flags_p);
}
static AgGetPropertyTask*
get_task (MetaDisplay *display,
Window xwindow,
Atom xatom,
Atom req_type)
{
return ag_task_create (display->xdisplay,
xwindow,
xatom, 0, G_MAXLONG,
False, req_type);
}
static char*
latin1_to_utf8 (const char *text)
{
@@ -1064,7 +830,8 @@ meta_prop_get_values (MetaDisplay *display,
int n_values)
{
int i;
AgGetPropertyTask **tasks;
xcb_get_property_cookie_t *tasks;
xcb_connection_t *xcb_conn = XGetXCBConnection (display->xdisplay);
meta_verbose ("Requesting %d properties of 0x%lx at once\n",
n_values, xwindow);
@@ -1072,7 +839,7 @@ meta_prop_get_values (MetaDisplay *display,
if (n_values == 0)
return;
tasks = g_new0 (AgGetPropertyTask*, n_values);
tasks = g_new0 (xcb_get_property_cookie_t, n_values);
/* Start up tasks. The "values" array can have values
* with atom == None, which means to ignore that element.
@@ -1132,9 +899,7 @@ meta_prop_get_values (MetaDisplay *display,
}
if (values[i].atom != None)
tasks[i] = get_task (display, xwindow,
values[i].atom, values[i].required_type);
tasks[i] = async_get_property (xcb_conn, xwindow, values[i].atom, values[i].required_type);
++i;
}
@@ -1147,10 +912,11 @@ meta_prop_get_values (MetaDisplay *display,
i = 0;
while (i < n_values)
{
AgGetPropertyTask *task;
GetPropertyResults results;
if (tasks[i] == NULL)
/* We're relying on the fact that sequence numbers can never be zero
* in Xorg. This is a bit disgusting... */
if (tasks[i].sequence == 0)
{
/* Probably values[i].type was None, or ag_task_create()
* returned NULL.
@@ -1159,10 +925,6 @@ meta_prop_get_values (MetaDisplay *display,
goto next;
}
task = ag_get_next_completed_task (display->xdisplay);
g_assert (task != NULL);
g_assert (ag_task_have_reply (task));
results.display = display;
results.xwindow = xwindow;
results.xatom = values[i].atom;
@@ -1172,19 +934,9 @@ meta_prop_get_values (MetaDisplay *display,
results.bytes_after = 0;
results.format = 0;
if (ag_task_get_reply_and_free (task,
&results.type, &results.format,
&results.n_items,
&results.bytes_after,
&results.prop) != Success ||
results.type == None)
if (!async_get_property_finish (xcb_conn, tasks[i], &results))
{
values[i].type = META_PROP_VALUE_INVALID;
if (results.prop)
{
XFree (results.prop);
results.prop = NULL;
}
goto next;
}
@@ -1216,18 +968,9 @@ meta_prop_get_values (MetaDisplay *display,
else
{
char *new_str;
char *xmalloc_new_str;
new_str = latin1_to_utf8 (values[i].v.str);
xmalloc_new_str = ag_Xmalloc (strlen (new_str) + 1);
if (xmalloc_new_str != NULL)
{
strcpy (xmalloc_new_str, new_str);
meta_XFree (values[i].v.str);
values[i].v.str = xmalloc_new_str;
}
g_free (new_str);
free (values[i].v.str);
values[i].v.str = new_str;
}
break;
case META_PROP_VALUE_MOTIF_HINTS:
@@ -1305,42 +1048,44 @@ free_value (MetaPropValue *value)
break;
case META_PROP_VALUE_UTF8:
case META_PROP_VALUE_STRING:
free (value->v.str);
break;
case META_PROP_VALUE_STRING_AS_UTF8:
meta_XFree (value->v.str);
g_free (value->v.str);
break;
case META_PROP_VALUE_MOTIF_HINTS:
meta_XFree (value->v.motif_hints);
free (value->v.motif_hints);
break;
case META_PROP_VALUE_CARDINAL:
break;
case META_PROP_VALUE_WINDOW:
break;
case META_PROP_VALUE_ATOM_LIST:
meta_XFree (value->v.atom_list.atoms);
free (value->v.atom_list.atoms);
break;
case META_PROP_VALUE_TEXT_PROPERTY:
meta_XFree (value->v.str);
free (value->v.str);
break;
case META_PROP_VALUE_WM_HINTS:
meta_XFree (value->v.wm_hints);
free (value->v.wm_hints);
break;
case META_PROP_VALUE_CLASS_HINT:
meta_XFree (value->v.class_hint.res_class);
meta_XFree (value->v.class_hint.res_name);
free (value->v.class_hint.res_class);
free (value->v.class_hint.res_name);
break;
case META_PROP_VALUE_SIZE_HINTS:
meta_XFree (value->v.size_hints.hints);
free (value->v.size_hints.hints);
break;
case META_PROP_VALUE_UTF8_LIST:
g_strfreev (value->v.string_list.strings);
break;
case META_PROP_VALUE_CARDINAL_LIST:
meta_XFree (value->v.cardinal_list.cardinals);
free (value->v.cardinal_list.cardinals);
break;
case META_PROP_VALUE_SYNC_COUNTER:
break;
case META_PROP_VALUE_SYNC_COUNTER_LIST:
meta_XFree (value->v.xcounter_list.counters);
free (value->v.xcounter_list.counters);
break;
}
}

View File

@@ -33,11 +33,11 @@
* found in some Motif reference guides online.
*/
typedef struct {
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long input_mode;
unsigned long status;
uint32_t flags;
uint32_t functions;
uint32_t decorations;
uint32_t input_mode;
uint32_t status;
} MotifWmHints, MwmHints;
#define MWM_HINTS_FUNCTIONS (1L << 0)
@@ -71,11 +71,6 @@ typedef struct {
/* These all return the memory from Xlib, so require an XFree()
* when they return TRUE. They return TRUE on success.
*/
gboolean meta_prop_get_atom_list (MetaDisplay *display,
Window xwindow,
Atom xatom,
Atom **atoms_p,
int *n_atoms_p);
gboolean meta_prop_get_motif_hints (MetaDisplay *display,
Window xwindow,
Atom xatom,
@@ -83,26 +78,17 @@ gboolean meta_prop_get_motif_hints (MetaDisplay *display,
gboolean meta_prop_get_cardinal_list (MetaDisplay *display,
Window xwindow,
Atom xatom,
gulong **cardinals_p,
uint32_t **cardinals_p,
int *n_cardinals_p);
gboolean meta_prop_get_latin1_string (MetaDisplay *display,
Window xwindow,
Atom xatom,
char **str_p);
gboolean meta_prop_get_utf8_string (MetaDisplay *display,
Window xwindow,
Atom xatom,
char **str_p);
gboolean meta_prop_get_utf8_list (MetaDisplay *display,
Window xwindow,
Atom xatom,
char ***str_p,
int *n_str_p);
gboolean meta_prop_get_latin1_list (MetaDisplay *display,
Window xwindow,
Atom xatom,
char ***str_p,
int *n_str_p);
void meta_prop_set_utf8_string_hint
(MetaDisplay *display,
Window xwindow,
@@ -115,32 +101,12 @@ gboolean meta_prop_get_window (MetaDisplay *display,
gboolean meta_prop_get_cardinal (MetaDisplay *display,
Window xwindow,
Atom xatom,
gulong *cardinal_p);
uint32_t *cardinal_p);
gboolean meta_prop_get_cardinal_with_atom_type (MetaDisplay *display,
Window xwindow,
Atom xatom,
Atom prop_type,
gulong *cardinal_p);
gboolean meta_prop_get_text_property (MetaDisplay *display,
Window xwindow,
Atom xatom,
char **utf8_str_p);
gboolean meta_prop_get_wm_hints (MetaDisplay *display,
Window xwindow,
Atom xatom,
XWMHints **hints_p);
gboolean meta_prop_get_class_hint (MetaDisplay *display,
Window xwindow,
Atom xatom,
XClassHint *class_hint);
gboolean meta_prop_get_size_hints (MetaDisplay *display,
Window xwindow,
Atom xatom,
XSizeHints **hints_p,
gulong *flags_p);
uint32_t *cardinal_p);
typedef enum
{
@@ -174,14 +140,14 @@ typedef struct
char *str;
MotifWmHints *motif_hints;
Window xwindow;
gulong cardinal;
uint32_t cardinal;
XWMHints *wm_hints;
XClassHint class_hint;
XSyncCounter xcounter;
struct
{
gulong *counters;
int n_counters;
uint32_t *counters;
int n_counters;
} xcounter_list;
struct
@@ -192,8 +158,8 @@ typedef struct
struct
{
gulong *cardinals;
int n_cardinals;
uint32_t *cardinals;
int n_cardinals;
} cardinal_list;
struct
@@ -204,8 +170,8 @@ typedef struct
struct
{
Atom *atoms;
int n_atoms;
uint32_t *atoms;
int n_atoms;
} atom_list;
} v;