Compare commits

..

39 Commits

Author SHA1 Message Date
Cédric Valmary
049b277ca5 Update Occitan translation 2016-10-11 17:53:17 +00:00
Pedro Albuquerque
9f23f466de Updated Portuguese translation 2015-11-24 08:06:28 +00:00
Rui Matos
461f193c00 compositor: Handle fences in the frontend X connection
Since mutter has two X connections and does damage handling on the
frontend while fence triggering is done on the backend, we have a race
between XDamageSubtract() and XSyncFenceTrigger() causing missed
redraws in the GL_EXT_X11_sync_object path.

If the fence trigger gets processed first by the server, any client
drawing that happens between that and the damage subtract being
processed and is completely contained in the last damage event box
that mutter got, won't be included in the current frame nor will it
cause a new damage event.

A simple fix for this would be XSync()ing on the frontend connection
after doing all the damage subtracts but that would add a round trip
on every frame again which defeats the asynchronous design of X
fences.

Instead, if we move fence handling to the frontend we automatically
get the right ordering between damage subtracts and fence triggers.

https://bugzilla.gnome.org/show_bug.cgi?id=728464
2015-08-13 14:50:22 +02:00
Ting-Wei Lan
9b1d436854 build: Fix return value in meta-sync-ring.c
https://bugzilla.gnome.org/show_bug.cgi?id=753380
2015-08-13 14:50:22 +02:00
Aaron Plattner
662d50460b compositor: Fix GL_EXT_x11_sync_object race condition
The compositor maintains a ring of shared fences with the X server in order to
properly synchronize rendering between the X server and the compositor's GPU
channel.  When all of the fences have been used, the compositor needs to reset
one so that it can be reused.  It does this by first waiting on the CPU for the
fence to become triggered, and then sending a request to the X server to reset
the fence.

If the compositor's GPU channel is busy processing other work (e.g. the desktop
switcher animation), then the X server may process the reset request before the
GPU has consumed the fence.  This causes the GPU channel to hang.

Fix the problem by having the compositor's GPU channel trigger its own fence
after waiting for the X server's fence.  Wait for that fence on the CPU before
sending the reset request to the X server.  This ensures that the GPU has
consumed the X11 fence before the server resets it.

Signed-off-by: Aaron Plattner <aplattner@nvidia.com>

https://bugzilla.gnome.org/show_bug.cgi?id=728464
2015-08-13 14:50:22 +02:00
Rui Matos
47cb21b36c compositor: Add support for GL_EXT_x11_sync_object
If GL advertises this extension we'll use it to synchronize X with GL
rendering instead of relying on the XSync() behavior with open source
drivers.

Some driver bugs were uncovered while working on this so if we have
had to reboot the ring a few times, something is probably wrong and
we're likely to just make things worse by continuing to try.  Let's
err on the side of caution, disable ourselves and fallback to the
XSync() path in the compositor.

https://bugzilla.gnome.org/show_bug.cgi?id=728464
2015-08-13 14:50:22 +02:00
Calvin Walton
8b75b41c4d Include libXrender as a dependency, link it to libmutter
Mutter uses a function from libXrender (XRenderFindStandardFormat in
src/x11/iconcache.c), but doesn't link to libXrender. This causes
link issues on systems using the gold linker, particularly with
-Wl,--as-needed.

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

https://bugzilla.gnome.org/show_bug.cgi?id=746692
2015-03-28 13:44:09 +01:00
Jasper St. Pierre
c45c39bff3 launcher: Fix a crash that happens when TakeDevice has an error 2015-03-27 23:46:00 +01:00
Florian Müllner
8b80a70efc Bump version to 3.14.4
Update NEWS.
2015-03-23 18:41:32 +01:00
Florian Müllner
63ad42e1f6 window-x11: Fix height computation of shaded windows
Since commit 6e06648f7, we start out with the invisible frame parts
only, and then add the unconstrained rect's height (which consists of
the visible parts of both frame and client window) *unless* the window
is shaded. While we indeed don't want to add the client height in that
case, we need to explicitly include the visible frame parts now.

https://bugzilla.gnome.org/show_bug.cgi?id=746145
2015-03-23 18:40:19 +01:00
Rui Matos
6b3be51ca8 meta-background: Add a function to refresh all background instances
We need to reload the FBOs under some circumstances, this adds a way
to easily do so.

https://bugzilla.gnome.org/show_bug.cgi?id=739178
2015-03-20 17:11:30 +01:00
Samir Ribic
46d57bf0ac Updated Bosnian translation 2015-03-14 23:06:25 +00:00
Alban Browaeys
8dd7102909 MetaBackgroundActor: glsl: do not mix int and float.
Implicit conversion from int to float is not supported by
GLSL ES.

Fixes:
(gnome-shell:8954): Cogl-WARNING **: Shader compilation failed:
1:2: P0004: High precision not supported, instead compiling high precision as medium precision
4:17: S0001: Type mismatch in arithmetic operation between 'int' and 'float'
when one trigger the overview mode on Mali 400 r1p1 GPU.

https://bugzilla.gnome.org/show_bug.cgi?id=745442
2015-03-03 22:10:43 +01:00
Chris Wilson
7a57e59fcc compositor: Update composite overlay window before unredirecting
The current ordering updates the clip shape of the composite overlay
window after unredirecting the target window. This has the effect of
forcing X to clear the target window and sending an expose to the
application to repaint - causing an unsightly flash. If we update the
shape first, then unredirect, X restores the background of the root
window (sending no expose events as no one is interested) and the
background is typically NONE for the root window. Then the unredirect
paints the contents of the composite backing pixmap over top without
requiring a round trip and waiting for the client to repaint - thus no
flashing.

Fixes regression from

commit d6282716b2
Author: Jasper St. Pierre <jstpierre@mecheye.net>
Date:   Fri Dec 6 17:10:44 2013 -0500

    compositor: Simplify the unredirected window management code

Cc: Jasper St. Pierre <jstpierre@mecheye.net>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

https://bugzilla.gnome.org/show_bug.cgi?id=743858
2015-02-02 15:43:01 +01:00
Rui Matos
6772758a64 display: Fix moving grab op check
We were regarding META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN as a move.

https://bugzilla.gnome.org/show_bug.cgi?id=743254
2015-01-20 17:52:54 +01:00
Florian Müllner
08ba9c689e place: Fix workspace check when collecting relevant windows
When looking for space to place a new window, other non-minimized
windows on the same workspace should be taken into account. However
the current check does not work correctly when the placed window is
located on all workspaces, so handle that case explicitly.

https://bugzilla.gnome.org/show_bug.cgi?id=743217
2015-01-20 00:43:05 +01:00
Muhammet Kara
bdb2dac244 Updated Turkish translation 2015-01-03 08:30:58 +00:00
Florian Müllner
dd9b1ce440 Bump GLib requirement
We have depended on GTask for a while now, bump the GLib requirement
to a new enough version to include that.

https://bugzilla.gnome.org/show_bug.cgi?id=698995
2014-12-29 17:53:52 +01:00
Matej Urbančič
878f0e6443 Updated Slovenian translation 2014-12-26 19:37:02 +01:00
Florian Müllner
fc1f78e8cc Bump version to 3.14.3
Update NEWS.
2014-12-19 12:04:48 +01:00
Rui Matos
25aa942a0e monitor-manager-xrandr: Set CRTC config even if it might be redundant
This optimization breaks our use of XRRScreenResources' timestamps to
detect hotplugs in case one of the outputs is disconnected and the
remaining ones don't need any mode, position or transform adjustments.

In that scenario, when applying the new configuration, we resize the X
screen but never call XRRSetCrtcConfig() and since XRRSetScreenSize()
doesn't take a timestamp and the X server doesn't update its last set
timestamp, when we next get a RRScreenChangeNotify and update
ourselves, XRRScreenResources.timestamp will still be smaller than
XRRScreenResources.configTimestamp which makes us think we're seeing a
new hotplug. We just don't enter an endless loop because the screen
size that we keep applying is always the same and the X server
short-circuits and stops sending us RRScreenChangeNotifys.

Always calling XRRSetCrtcConfig() ensures that the last set timestamp
will be bigger than configTimestamp in the next event and thus making
us trigger the monitors-changed signal properly.

Note that the X server already does basically the same checks that
we're removing here, so doing this shouldn't be a significant
efficiency loss. See

http://cgit.freedesktop.org/xorg/xserver/tree/randr/rrcrtc.c?h=server-1.16-branch#n539

https://bugzilla.gnome.org/show_bug.cgi?id=740838
2014-12-10 19:14:58 +01:00
Owen W. Taylor
56e74b1ea8 MetaWindowActor: don't overwrite send_frame_messages_timer
If the app finished multiple frames before we sent _NET_WM_FRAME_DRAWN,
we could add the send_frame_messages_timer multiple times. In the rare
case that the app immediately closed the window, the older timeout
could potentially then run on the freed actor.

https://bugzilla.gnome.org/show_bug.cgi?id=738686
2014-12-02 11:49:06 -05:00
Owen W. Taylor
7d3204b196 Fix problems resulting in left-over queued frames
* Use -1 rather than 0 as a flag for pending queue entries; 0 is
  a valid frame_counter value from Cogl.
* Consistently handle the fact we can have more than one pending
  entry. It's app misbehavior to submit a new frame before
  _NET_WM_FRAME_DRAWN is received; but we accept such frame messages,
  so we can't just leak them.
* If we remove send_frame_message_timer, assign the current frame counter
  to pending entries.
* To try to avoid regressing on this, when sending _NET_WM_FRAME_TIMINGS
  messages, if we have stale messages, or messages with no frame drawn
  time, warn and remove them from the queue rather than just accumulating.
* Improve commenting.

https://bugzilla.gnome.org/show_bug.cgi?id=738686
2014-12-02 11:49:01 -05:00
Jasper St. Pierre
d7ff632c67 window-x11: Fix windows that set empty input shapes
Windows that set empty input shapes get n_rects of 0 when querying them
later, which makes sense, but the code that interpreted the result
translated it into a NULL input shape, which meant it was the same as
the bounding region. As such, an empty input shape would actually get
interpreted as a full input shape!

We, ourselves, set an empty input shape on tray icon windows in
gnome-shell since we would handle the picking ourselves. This meant that
we'd actually get the MetaSurfaceActorX11 when hovering over the tray
icon, instead of the ShellGTKEmbed that we capture events on and react
to.

This fixes weird tray icon behavior in gnome-shell.
2014-11-26 22:46:59 +01:00
Ray Strode
6d3e64226d Revert "screen: Set a black background for testing purposes"
This reverts commit ec8ed1dbb0.

1) It turns out to add a momentary flicker from the transition
between the login screen and user session
2) It actually isn't needed anymore since bug 733026

https://bugzilla.gnome.org/show_bug.cgi?id=740377
2014-11-20 16:22:55 -05:00
Florian Müllner
2e7b9e0dfe window-actor: Do not request unredirection when destroyed
WindowActors can outlive their corresponding window to animate unmap.
Unredirecting the actor does not make sense in that case, so make
sure to not request it.

https://bugzilla.gnome.org/show_bug.cgi?id=740133
2014-11-14 18:31:02 +01:00
Florian Müllner
08d81b6f7f Bump version to 3.14.2
Update NEWS.
2014-11-12 19:00:56 +01:00
Jasper St. Pierre
e01077914d configure: Actually make gbm optional
Whoops, I made the code work without it, but forgot to strip it from the
actual list of requires packages.

Spotted-by: Rico Tzschichholz <ricotz@ubuntu.com>
2014-11-10 14:54:31 +01:00
Jasper St. Pierre
d7cf6bed63 Make gbm optional
Now it's only required by the native backend. The cursor code is getting
quite messy, but it was already considerable messy to start with.
2014-11-10 14:54:11 +01:00
Jasper St. Pierre
d071ba8446 cursor: Clean up code flow slightly
Reverse the set of expressions so testing for gbm is at the top.
2014-11-10 14:53:19 +01:00
Jonathon Jongsma
4d08e89c16 xrandr: ignore hotplug_mode_update value
The important thing is whether this property exists or not, but the value
doesn't matter.
2014-11-05 16:36:24 -06:00
Rui Matos
21d8c4b032 monitor-manager: Don't try to match the outputs on hotplug
meta_monitor_config_match_current() only matches the number of outputs
and if the output connector, vendor, product and serial match.

This means that we can't use it to bypass doing any
work because it won't detect cases where we actually want to update
ourselves like e.g. an output being turned off either by us or by
another X client (e.g. xrandr).

https://bugzilla.gnome.org/show_bug.cgi?id=738630
2014-11-05 15:51:26 +01:00
Rui Matos
c98686da92 monitor-config: Prevent a crash applying config for a closed lid
When a laptop's lid is closed we try to build and apply a temporary
configuration that disables the laptop's display if we have other
outputs.

This isn't enough though, we must also check if at least one of these
other outputs is enabled otherwise we'll try to resize the screen to
0x0 which (rightfully) hits an assertion.

https://bugzilla.gnome.org/show_bug.cgi?id=739450
2014-10-31 17:38:29 +01:00
Florian Müllner
a19eda5ae7 Bump version to 3.14.1.5
Update NEWS.
2014-10-30 11:01:04 +00:00
Adel Gadllah
0a9bbe0109 meta-wayland-surface: Correcly scale the input region
The input region currently only gets scaled by the surface
scale while ignoring the output scale, which causes input events to not get
delivered correctly for clients on hidpi screens. So take the output scale
into account when doing so.

https://bugzilla.gnome.org/show_bug.cgi?id=739161
2014-10-27 18:13:00 +01:00
Adel Gadllah
a8eb42e43c Revert "wayland-surface: Apply the surface scale only if needed"
This commit is wrong, it assumes that the scale only applies to the one
set by the client but its not. meta_surface_actor_wayland_scale_texture
also handles the output scale. Revert the commit to fix hidpi for wayland
clients like weston-terminal.

This reverts commit 0364ea9140.

https://bugzilla.gnome.org/show_bug.cgi?id=739161
2014-10-27 18:12:52 +01:00
Dušan Kazik
9d0c9f1f42 Updated Slovak translation 2014-10-19 17:43:23 +00:00
Florian Müllner
9fa0743394 Remove unused variable 2014-10-16 11:00:51 +02:00
Jasper St. Pierre
bb79a20fac display: Fix accidental inversion from 2f9c601
Commit 2f9c601 accidentally changed the logic here, changing the grab
behavior when not using raise-on-click. Fix this.

Spotted-by: Adam Goode <adam@spicenitz.org>
2014-10-15 23:54:20 +02:00
146 changed files with 38340 additions and 23205 deletions

98
NEWS
View File

@@ -1,96 +1,44 @@
3.15.91
=======
* wayland: Fix nested compositor mode [Jonas; #745401]
* wayland: Fix pointer constraining [Marek; #727337]
* wayland: Fix input region on HiDPI [Jonas; #744933]
* Allow themes to style buttons differently based on function [Horst; #745108]
* Misc. bug fixes and cleanups [Ray, Rui, Alban; #745141, #745118, #745476,
#745442]
Contributors:
Jonas Ådahl, Alban Browaeys, Marek Chalupa, Horst, Rui Matos,
Jasper St. Pierre, Ray Strode
Translations:
Chao-Hsiung Liao [zh_TW], Efstathios Iosifidis [el], Dušan Kazik [sk],
Balázs Úr [hu], Daniel Mustieles [es], Claude Paroz [fr], Stas Solovey [ru],
Yosef Or Boczko [he], Rafael Ferreira [pt_BR], Aurimas Černius [lt],
Fran Dieguez [gl], Anders Jonsson [sv], Мирослав Николић [sr, sr@latin]
3.15.90
=======
* Initialize MetaOutput even when we can't get the EDID [Rui; #743412]
* Expose MetaMonitorManager to introspection [Rui; #743745]
3.14.4
======
* Fix flash on unredirection [Chris; #743858]
* Update xdg-shell implementation to v5 [Jonas; #744452]
* Do not try to use seat devices that aren't (yet) present [Ray; #744640]
* Add keybindings for switching to VT8-VT12 [Ray; #744800]
* Misc bug fixes [Jonas, Cosimo; #743678, #744500]
* Fix incompatibility with GLES2 GLSL [Alban; #745442]
* Add function to refresh all background instances [Rui; #739178]
* Fix geometry of shaded windows [Florian; #746145]
* Misc. bug fixes [Florian, Rui; #698995, #743217, #743254]
Contributors:
Jonas Ådahl, Cosimo Cecchi, Carlos Garnacho, Rui Matos, Jasper St. Pierre,
Ray Strode, Chris Wilson
Alban Browaeys, Rui Matos, Florian Müllner, Chris Wilson
Translations:
Yosef Or Boczko [he], Yuri Myasoedov [ru], Kristjan SCHMIDT [eo],
Matej Urbančič [sl], Dušan Kazik [sk]
Matej Urbančič [sl], Muhammet Kara [tr], Samir Ribic [bs]
3.15.4
======
* Use GTK+ theme for window decorations instead of metacity [Florian; #741917]
* Export the same EDID information on X11 and wayland [Carlos; #742882]
* Apply input device configuration on wayland [Carlos; #739397]
* Implement pointer barriers on wayland [Jonas; #706655]
* Misc. bug fixes (Ting-Wei, Rui, Ikey, Florian, Marek, Jonas; #741829,
#738630, #737463, #698995, #727893, #742825, #742824, #742841, #743173,
#743189, #743217, #743254]
Contributors:
Jonas Ådahl, Giovanni Campagna, Marek Chalupa, Ikey Doherty, Adel Gadllah,
Carlos Garnacho, Ting-Wei Lan, Rui Matos, Florian Müllner, Jasper St. Pierre,
Rico Tzschichholz
Translations:
Matej Urbančič [sl], Balázs Úr [hu], Marek Černocký [cs],
Inaki Larranaga Murgoitio [eu], Rafael Ferreira [pt_BR],
Daniel Mustieles [es], Fran Dieguez [gl]
3.15.3
3.14.3
======
* Fix crash when trying to unredirect a destroyed window [Florian; #740133]
* Fix "flicker" during startup transition [Ray; #740377]
* Don't leave left-over frames queued [Owen; #738686]
* Set CRTC configuration even if it might be redundant [Rui; #740838]
Contributors:
Rui Matos, Jasper St. Pierre, Rico Tzschichholz, Owen W. Taylor
Rui Matos, Florian Müllner, Jasper St. Pierre, Ray Strode, Owen W. Taylor
Translations:
Trần Ngọc Quân [vi], Muhammet Kara [tr]
3.15.2
3.14.2
======
* Don't enable hiDPI on monitors with broken EDID [Bastien; #734839]
* Prevent crash applying monitor config for a closed lid [Rui; #739450]
* Fix "flicker" during startup transition [Ray; #740377]
* Misc. bug fixes [Lan, Florian, Carlos; #731521, #740133, #738890]
* Misc. fixes [Rui, Jonathon, Jasper; #738630]
Contributors:
Emmanuele Bassi, Carlos Garnacho, Jonathon Jongsma, Ting-Wei Lan, Rui Matos,
Florian Müllner, Bastien Nocera, Jasper St. Pierre, Ray Strode
Jonathon Jongsma, Rui Matos, Jasper St. Pierre
3.14.1.5
========
* Fix wayland hiDPI regressions [Adel; #739161]
Contributors:
Adel Gadllah, Florian Müllner, Jasper St. Pierre
Translations:
Kjartan Maraas [nb]
3.15.1
======
* Use GResources for theme loading [Cosimo; #736936]
* Fix headerbar drag getting stuck on xwayland [Carlos; #738411]
* Fix wayland hiDPI regressions [Adel; #739161]
* Misc bug fixes and cleanups [Jasper, Rui, Carlos; #662962, #738630, #738888,
#738890]
Contributors:
Cosimo Cecchi, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
Jasper St. Pierre
Dušan Kazik [sk]
3.14.1
======

View File

@@ -4,6 +4,7 @@
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
PKG_NAME="mutter"
REQUIRED_AUTOMAKE_VERSION=1.11
(test -f $srcdir/configure.ac \
@@ -18,4 +19,4 @@ which gnome-autogen.sh || {
echo "your distribution's package manager)."
exit 1
}
. gnome-autogen.sh
USE_GNOME2_MACROS=1 USE_COMMON_DOC_BUILD=yes . gnome-autogen.sh

View File

@@ -1,8 +1,8 @@
AC_PREREQ(2.62)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [15])
m4_define([mutter_micro_version], [91])
m4_define([mutter_minor_version], [14])
m4_define([mutter_micro_version], [4])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@@ -75,8 +75,8 @@ MUTTER_PC_MODULES="
gio-unix-2.0 >= 2.35.1
pango >= 1.2.0
cairo >= 1.10.0
gsettings-desktop-schemas >= 3.15.4
$CLUTTER_PACKAGE >= 1.21.3
gsettings-desktop-schemas >= 3.7.3
$CLUTTER_PACKAGE >= 1.19.5
cogl-1.0 >= 1.17.1
upower-glib >= 0.99.0
gnome-desktop-3.0
@@ -90,6 +90,7 @@ MUTTER_PC_MODULES="
xkeyboard-config
xkbcommon >= 0.4.3
xkbcommon-x11
xrender
x11-xcb
xcb-randr
"
@@ -200,39 +201,22 @@ AC_SUBST(XWAYLAND_PATH)
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
MUTTER_NATIVE_BACKEND_MODULES="clutter-egl-1.0 libdrm libsystemd libinput gudev-1.0 gbm >= 10.3"
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [clutter-egl-1.0 libdrm libsystemd libinput gbm >= 10.3], [have_native_backend=yes], [have_native_backend=no])
if test $have_native_backend = yes; then
AC_DEFINE([HAVE_NATIVE_BACKEND],[1],[Define if you want to enable the native (KMS) backend based on systemd])
fi
AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test $have_native_backend = yes])
AC_ARG_ENABLE(native-backend,
AS_HELP_STRING([--disable-native-backend], [disable mutter native (KMS) backend]),,
enable_native_backend=auto
)
AS_IF([test "$enable_native_backend" = "yes"], [have_native_backend=yes],
[test "$enable_native_backend" = "auto"], PKG_CHECK_EXISTS([$MUTTER_NATIVE_BACKEND_MODULES], [have_native_backend=yes]))
PKG_CHECK_MODULES(MUTTER_WAYLAND, [clutter-wayland-1.0 clutter-wayland-compositor-1.0 wayland-server >= 1.5.90], [have_wayland=yes], [have_wayland=no])
if test $have_wayland = yes; then
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
AS_IF([test $WAYLAND_SCANNER = "no"],
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
AC_SUBST([WAYLAND_SCANNER])
AS_IF([test "$have_native_backend" = "yes"], [
PKG_CHECK_MODULES([MUTTER_NATIVE_BACKEND], [$MUTTER_NATIVE_BACKEND_MODULES])
AC_DEFINE([HAVE_NATIVE_BACKEND],[1], [Define if you want to enable the native (KMS) backend based on systemd])
])
AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test "$have_native_backend" = "yes"])
MUTTER_WAYLAND_MODULES="clutter-wayland-1.0 clutter-wayland-compositor-1.0 wayland-server >= 1.6.90"
AC_ARG_ENABLE(wayland,
AS_HELP_STRING([--disable-wayland], [disable mutter on wayland support]),,
enable_wayland=auto
)
AS_IF([test "$enable_wayland" = "yes"], [have_wayland=yes],
[test "$enable_wayland" = "auto"], PKG_CHECK_EXISTS([$MUTTER_WAYLAND_MODULES], [have_wayland=yes]))
AS_IF([test "$have_wayland" = "yes"], [
PKG_CHECK_MODULES([MUTTER_WAYLAND], [$MUTTER_WAYLAND_MODULES])
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
AS_IF([test $WAYLAND_SCANNER = "no"],
[AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols])])
AC_SUBST([WAYLAND_SCANNER])
AC_DEFINE([HAVE_WAYLAND],[1],[Define if you want to enable Wayland support])
])
AM_CONDITIONAL([HAVE_WAYLAND],[test "$have_wayland" = "yes"])
AC_DEFINE([HAVE_WAYLAND],[1],[Define if you want to enable Wayland support])
fi
AM_CONDITIONAL([HAVE_WAYLAND],[test $have_wayland = yes])
PKG_CHECK_EXISTS([xi >= 1.6.99.1],
AC_DEFINE([HAVE_XI23],[1],[Define if you have support for XInput 2.3 or greater]))
@@ -331,6 +315,11 @@ fi
GTK_DOC_CHECK([1.15], [--flavour no-tmpl])
AC_CHECK_DECL([GL_EXT_x11_sync_object],
[],
[AC_MSG_ERROR([GL_EXT_x11_sync_object definition not found, please update your GL headers])],
[#include <GL/glx.h>])
#### Warnings (last since -Werror can disturb other tests)
# Stay command-line compatible with the gnome-common configure option. Here
@@ -433,8 +422,6 @@ mutter-$VERSION
libcanberra: ${have_libcanberra}
Introspection: ${found_introspection}
Session management: ${found_sm}
Wayland: ${have_wayland}
Native (KMS) backend: ${have_native_backend}
"

View File

@@ -29,25 +29,5 @@
<default><![CDATA[['<Primary><Alt>F7']]]></default>
<_summary>Switch to VT 7</_summary>
</key>
<key name="switch-to-session-8" type="as">
<default><![CDATA[['<Primary><Alt>F8']]]></default>
<_summary>Switch to VT 8</_summary>
</key>
<key name="switch-to-session-9" type="as">
<default><![CDATA[['<Primary><Alt>F9']]]></default>
<_summary>Switch to VT 9</_summary>
</key>
<key name="switch-to-session-10" type="as">
<default><![CDATA[['<Primary><Alt>F10']]]></default>
<_summary>Switch to VT 10</_summary>
</key>
<key name="switch-to-session-11" type="as">
<default><![CDATA[['<Primary><Alt>F11']]]></default>
<_summary>Switch to VT 11</_summary>
</key>
<key name="switch-to-session-12" type="as">
<default><![CDATA[['<Primary><Alt>F12']]]></default>
<_summary>Switch to VT 12</_summary>
</key>
</schema>
</schemalist>

View File

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

View File

@@ -81,7 +81,6 @@ IGNORE_HFILES= \
keybindings-private.h \
meta-background-actor-private.h \
meta-background-group-private.h \
meta-dbus-login1.h \
meta-module.h \
meta-plugin-manager.h \
meta-shadow-factory-private.h \
@@ -112,17 +111,6 @@ IGNORE_HFILES= \
xprops.h \
$(NULL)
if !HAVE_NATIVE_BACKEND
IGNORE_HFILES+= \
meta-backend-native.h \
meta-barrier-native.h \
meta-cursor-renderer-native.h \
meta-idle-monitor-native.h \
meta-input-settings-native.h \
meta-monitor-manager-kms.h \
$(NULL)
endif
if !HAVE_WAYLAND
IGNORE_HFILES += \
meta-surface-actor-wayland.h \

View File

@@ -22,6 +22,7 @@
<title>Mutter Core Reference</title>
<xi:include href="xml/main.xml"/>
<xi:include href="xml/common.xml"/>
<xi:include href="xml/gradient.xml"/>
<xi:include href="xml/prefs.xml"/>
<xi:include href="xml/util.xml"/>
<xi:include href="xml/errors.xml"/>

View File

@@ -172,6 +172,15 @@ meta_error_trap_push_with_return
meta_error_trap_pop_with_return
</SECTION>
<SECTION>
<FILE>gradient</FILE>
MetaGradientType
meta_gradient_create_simple
meta_gradient_create_multi
meta_gradient_create_interwoven
meta_gradient_add_alpha
</SECTION>
<SECTION>
<FILE>group</FILE>
MetaGroup

396
doc/theme-format.txt Normal file
View File

@@ -0,0 +1,396 @@
Themes are in a simple XML-subset format. There are multiple versions
of the theme format, and a given theme can support more than one format.
Version 1: THEMEDIR/metacity-1/metacity-theme-1.xml
(original metacity format)
Version 2: THEMEDIR/metacity-1/metacity-theme-2.xml
Version 3: THEMEDIR/metacity-1/metacity-theme-3.xml
The subdirectory name is "metacity-1" in all versions.
As you might expect, older versions of metacity will not understand
newer theme formats. However, newer versions will use old themes.
Metacity will always use the newest theme format it understands that
the X server supports. Some format versions are only supported if you
have the right X server features.
Each format *requires* the corresponding filename. If you put version
2 format features in the metacity-1/metacity-theme-1.xml file, then
metacity will get angry.
This document has separate sections for each format version. You may
want to read the document in reverse order, since the base features
are discussed under version 1.
New Features in Theme Format Version 3.4
========================================
An additional color type is added to pick up custom colors defined
in the GTK+ theme's CSS:
gtk:custom(name,fallback)
where <name> refers to a custom color defined with @define-color in
the GTK+ theme, and <fallback> provides an alternative color definition
in case the color referenced by <name> is not found.
New Features in Theme Format Version 3.3
========================================
Add two additional button background functions - left_single_background and
right_single_background - for button groups with just a single button.
There are now additional frame states to style left/right tiled windows
differently ("tiled_left", "tiled_right", "tiled_left_and_shaded",
"tiled_right_and_shaded").
New Features in Theme Format Version 3.2
========================================
A new window type 'attached' is added for modal dialogs which are
attached to their parent window. (When the attach_modal_dialogs preference
is turned on.) If no style is defined for the 'attached' window type,
the 'border' window type will be used instead.
New Features in Theme Format Version 3.1
========================================
Additional predefined variables are added for positioning expressions:
frame_x_center: the X center of the entire frame, with respect to the
piece currently being drawn.
frame_y_center: the Y center of the entire frame, with respect to the
piece currently being drawn.
The <title/> element now supports an "ellipsize_width" attribute. When
specified, this gives a width at which to ellipsize the title. If not
specified, the title will simply be clipped to the title area.
New Features in Theme Format Version 3
======================================
Format version 3 has exactly one new feature; any element in the file
can now have a version attribute:
version="[<|<=|=>|>] MAJOR.MINOR"
(< and > should be to be entity escaped as &lt; and &gt;). If this
version check is not met, then the element and its children will be
ignored. This allows having alternate sections of the theme file for
older and newer version of the Metacity theme format.
When placed on the toplevel <metacity_theme> element, an unsatisfied
version check will not just cause the contents of the file to be
ignored, it will also cause the lookup of a theme file to proceed on
and look for an older format 2 or format 1 file. This allows making a
metacity-theme-3.xml file that is only used the format version 3.2 or
newer is supported, and using metacity-theme-1.xml for older window
managers.
New Features in Theme Format Version 2
======================================
The optional attributes rounded_top_left, rounded_top_right,
rounded_bottom_left and rounded_bottom_right on <frame_geometry>
should now be the radius of the corner in pixels. You may still use
the values "false" for 0 and "true" for 5, which means v1 values will
still work just fine.
<frame_geometry> has a new optional attribute, hide_buttons. If this
is true, no buttons will be displayed on the titlebar.
Anywhere you can use a positive integer, you can use an integer constant.
As well as constant integers and reals, you may define constant colours,
thus:
<constant name="RevoltingPink" value="#FF00FF"/>
<constant name="Background" value="gtk:bg[NORMAL]"/>
<frame_style> has two new optional attributes, background and alpha.
If you specify alpha, you must specify background. background is a
colour used for the background of the frame. alpha is the transparency
as a real between 0.0 and 1.0. If the current X server does not support
alpha channels, the value is ignored.
The filename attribute of <image> may begin with "theme:". If so, the
rest of the string is the name of a theme icon. The 64x64 version of the
icon is used, except for fallback mini_icons, which use the 16x16 version.
This does not affect ordinary resizing. For example:
<button function="close" state="normal">
<draw_ops>
<include name="active_button"/>
<image filename="theme:gnome-logout" x="2" y="2"
width="width-4" height="height-4"/>
<!-- Note: not "theme:gnome-logout.png" or similar. -->
</draw_ops>
</button>
<menu_icon>s are parsed but ignored.
Fallback icons can be specified using <fallback>. There are two
optional arguments, icon and mini_icon. The values of these arguments
are identical to that of the filename attribute of <image>. Fallback
icons are used when a window does not supply its own icon. If a fallback
icon is not specified with <fallback>, Metacity will use a built-in
icon, as in metacity-theme-1.
The <arc> element, as well as the original start_angle and end_angle
attributes, may be given from and to attributes. The values of these
attributes are given in degrees clockwise, with 0 being straight up.
For example:
<arc from="0.0" to="90.0" filled="true" color="#FF00FF"
x="0" y="5" width="15" height="15"/>
<frame state="shaded"> may now take an optional resize attribute, with
the same interpretation as the resize attribute on <frame state="normal">.
If this attribute is omitted for state="shaded", it defaults to "both".
(If it is omitted for state="normal", it remains an error.)
In addition to the four <button> functions which are required in
metacity-theme-1, there are six new functions in metacity-theme-2:
shade, unshade, above, unabove, stick and unstick.
Overview of Theme Format Version 1
==================================
<?xml version="1.0"?>
<metacity_theme>
<!-- Only one info section is allowed -->
<info>
<name>Foo</name>
<author>Foo P. Bar</author>
<copyright>whoever, 2002</copyright>
<date>Jan 31 2005</date>
<description>A sentence about the theme.</description>
</info>
<!-- define a frame geometry to be referenced later -->
<!-- frame_geometry has an optional has_title attribute which
determines whether the title text height is included in the
height calculation. if not specified, defaults to true.
It also has an optional text_size="medium" attribute
(same sizes as with Pango markup, xx-small thru medium thru
xx-large)
Finally it has optional args rounded_top_left=true,
rounded_top_right=true, rounded_bottom_left=true,
rounded_bottom_right=true.
-->
<frame_geometry name="normal" has_title="true" title_scale="medium">
<distance name="left_width" value="6"/>
<distance name="right_width" value="6"/>
<distance name="bottom_height" value="7"/>
<distance name="left_titlebar_edge" value="6"/>
<distance name="right_titlebar_edge" value="6"/>
<distance name="button_width" value="17"/>
<distance name="button_height" value="17"/>
<!-- alternative to button_width button_height distances -->
<aspect_ratio name="button" value="1.0"/>
<distance name="title_vertical_pad" value="4"/>
<border name="title_border" left="3" right="12" top="4" bottom="3"/>
<border name="button_border" left="0" right="0" top="1" bottom="1"/>
</frame_geometry>
<!-- inheritance is allowed; simply overwrites values from parent -->
<frame_geometry name="borderless" parent="normal">
<distance name="left_width" value="0"/>
<distance name="right_width" value="0"/>
<distance name="bottom_height" value="0"/>
<distance name="left_titlebar_edge" value="0"/>
<distance name="right_titlebar_edge" value="0"/>
</frame_geometry>
<!-- define a constant to use in positions/sizes of draw operations;
constant names must start with a capital letter.
-->
<constant name="LineOffset" value="3"/>
<!-- define drawing operations to be referenced later;
these draw-op lists can also be placed inline.
Positions/lengths are given as expressions.
Operators are: +,-,*,/,%,`max`,`min`
All operators are infix including `max` and `min`,
i.e. "2 `max` 5"
Some variables are predefined, and constants can also
be used. Variables are:
width - width of target area
height - height of target area
object_width - natural width of object being drawn
object_height - natural height of object being drawn
left_width - distance from left of frame to client window
right_width - distance from right of frame to client window
top_height - distance from top of frame to client window
bottom_height - distance from bottom of frame to client window
mini_icon_width - width of mini icon for window
mini_icon_height - height of mini icon
icon_width - width of large icon
icon_height - height of large icon
title_width - width of title text
title_height - height of title text
All these are always defined, except object_width/object_height
which only exists for <image> right now.
-->
<draw_ops name="demo_all_ops">
<line color="#00FF00" x1="LineOffset" y1="0" x2="0" y2="height"/>
<line color="gtk:fg[NORMAL]"
x1="width - 1" y1="0" x2="width - 1" y2="height"
width="3" dash_on_length="2" dash_off_length="3"/>
<rectangle color="blend/gtk:fg[NORMAL]/gtk:bg[NORMAL]/0.7"
x="0" y="0" width="width - 1" height="height - 1" filled="true"/>
<arc color="dark gray" x="0" y="0" width="width - 1" height="height - 1"
filled="false" start_angle="30" extent_angle="180"/>
<tint color="orange" alpha="0.5" x="0" y="0" width="width" height="height"/>
<!-- may be vertical, horizontal, diagonal -->
<gradient type="diagonal"
x="10" y="30" width="width / 3" height="height / 4">
<!-- any number of colors allowed here. A color can be
a color name like "blue" (look at gcolorsel), a hex color
as in HTML (#FFBB99), or a color from the gtk theme
given as "gtk:base[NORMAL]", "gtk:fg[ACTIVE]", etc.
-->
<color value="gtk:fg[SELECTED]"/>
<!-- color obtained by a 0.5 alpha composite of the second color onto the first -->
<color value="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.5"/>
</gradient>
<!-- image has an optional colorize="#color" attribute to give the
image a certain color -->
<image filename="foo.png" alpha="0.7"
x="10" y="30" width="width / 3" height="height / 4"/>
<gtk_arrow state="normal" shadow="in" arrow="up"
filled="true"
x="2" y="2" width="width - 4" height="height - 4"/>
<gtk_box state="normal" shadow="out"
x="2" y="2" width="width - 4" height="height - 4"/>
<gtk_vline state="normal" x="2" y1="0" y2="height"/>
<!-- window's icon -->
<icon alpha="0.7"
x="10" y="30" width="width / 3" height="height / 4"/>
<!-- window's title -->
<title color="gtk:text[NORMAL]" x="20" y="30"/>
<!-- include another draw ops list; has optional x/y/width/height attrs -->
<include name="some_other_draw_ops"/>
<!-- tile another draw ops list; has optional
x/y/width/height/tile_xoffset/tile_yoffset -->
<tile name="some_other_draw_ops" tile_width="10" tile_height="10"/>
</draw_ops>
<frame_style name="normal" geometry="normal">
<!-- How to draw each piece of the frame.
For each piece, a draw_ops can be given inline or referenced
by name. If a piece is omitted, then nothing will be drawn
for that piece.
For each piece, the "width" and "height" variables in
coordinate expressions refers to the dimensions of the piece,
the origin is at the top left of the piece.
So <rectangle x="0" y="0" width="width-1" height="height-1"/>
will outline a piece.
-->
<piece position="entire_background" draw_ops="demo_all_ops"/>
<piece position="left_titlebar_edge">
<draw_ops>
<line color="#00FF00" x1="0" y1="0" x2="0" y2="height"/>
</draw_ops>
</piece>
<!-- The complete list of frame pieces:
entire_background: whole frame
titlebar: entire area above the app's window
titlebar_middle: area of titlebar_background not considered
part of an edge
left_titlebar_edge: left side of titlebar background
right_titlebar_edge: right side of titlebar background
top_titlebar_edge: top side of titlebar background
bottom_titlebar_edge: bottom side of titlebar background
title: the title area (doesn't include buttons)
left_edge: left edge of the frame
right_edge: right edge of the frame
bottom_edge: bottom edge of the frame
overlay: same area as entire_background, but drawn after
drawing all sub-pieces instead of before
-->
<!-- For buttons, drawing methods have to be provided for
each of three states:
normal, pressed, prelight
and the button function or position must be provided:
close, maximize, minimize, menu,
left_left_background, left_middle_background,
left_right_background, right_left_background,
right_middle_background, right_right_background
So a working theme needs 3*4 = 12 button declarations
and a theme may have up to 3*10 = 30 button declarations
in order to handle button-rearrangement preferences.
(The name "function" for the attribute is from before the
background values existed.)
-->
<button function="close" state="normal" draw_ops="previously_named"/>
<button function="menu" state="normal">
<draw_ops>
<icon alpha="0.7"
x="0" y="0" width="object_width" height="object_height"/>
</draw_ops>
</button>
</frame_style>
<!-- styles can inherit from each other with the parent="" attribute.
In a subclass anything can be re-specified to override
the parent style. -->
<frame_style name="focused" parent="normal">
<piece position="title">
<draw_ops>
<rectangle color="gtk:bg[SELECTED]"
x="0" y="0" width="width-1" height="height-1"/>
<title color="gtk:fg[SELECTED]" x="(width - title_width) / 2"
y="(height - title_height) / 2"/>
</draw_ops>
</piece>
</frame_style>
<!-- Maps styles to states of frame.
Focus: yes (focused), no (not focused)
Window states: normal, maximized, shaded, maximized_and_shaded
Window resizability: none, vertical, horizontal, both
Everything unspecified just does the same as
unfocused/normal/both.
only state="normal" needs a resize="" attribute.
-->
<frame_style_set name="normal">
<frame focus="yes" state="normal" resize="both" style="focused"/>
<frame focus="no" state="normal" resize="both" style="normal"/>
</frame_style_set>
<!-- Each window type needs a style set
Types: normal, dialog, modal_dialog, menu, utility, border
-->
<window type="normal" style_set="normal"/>
<!-- For menu icons, drawing methods are needed for the same
four types as the buttons, and GTK states
(insensitive,prelight,normal,etc.)
-->
<menu_icon function="close" state="normal" draw_ops="previously_named"/>
</metacity_theme>

View File

@@ -22,7 +22,9 @@ src/core/screen.c
src/core/util.c
src/core/window.c
src/ui/frames.c
src/ui/resizepopup.c
src/ui/theme.c
src/ui/theme-parser.c
src/x11/session.c
src/x11/window-props.c
src/x11/xprops.c

4046
po/bs.po

File diff suppressed because it is too large Load Diff

1200
po/cs.po

File diff suppressed because it is too large Load Diff

1321
po/el.po

File diff suppressed because it is too large Load Diff

2425
po/eo.po

File diff suppressed because it is too large Load Diff

1301
po/es.po

File diff suppressed because it is too large Load Diff

1324
po/eu.po

File diff suppressed because it is too large Load Diff

818
po/fr.po
View File

@@ -1,5 +1,5 @@
# French translation of mutter.
# Copyright (C) 2002-2015 Free Software Foundation, Inc.
# Copyright (C) 2002-2014 Free Software Foundation, Inc.
# This file is distributed under the same license as the metacity package.
#
# Christophe Fergeau <teuf@users.sourceforge.net>, 2002.
@@ -11,16 +11,17 @@
# Cyprien Le Pannérer <cyplp@free.fr>, 2006.
# Robert-André Mauchin <zebob.m@gmail.com>, 2007.
# Stéphane Raimbault <stephane.raimbault@gmail.com>, 2007.
# Claude Paroz <claude@2xlibre.net>, 2008-2015.
# Claude Paroz <claude@2xlibre.net>, 2008-2014.
# Bruno Brouard <annoa.b@gmail.com>, 2011-12.
#
msgid ""
msgstr ""
"Project-Id-Version: mutter master\n"
"Project-Id-Version: mutter masterReport-Msgid-Bugs-To: http://bugzilla.gnome."
"org/enter_bug.cgi?product=mutter&component=general\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2015-02-23 23:11+0000\n"
"PO-Revision-Date: 2015-02-24 10:08+0100\n"
"POT-Creation-Date: 2014-08-29 21:52+0000\n"
"PO-Revision-Date: 2014-08-30 11:59+0200\n"
"Last-Translator: Claude Paroz <claude@2xlibre.net>\n"
"Language-Team: GNOME French Team <gnomefr@traduc.org>\n"
"Language: fr\n"
@@ -407,8 +408,8 @@ msgid ""
"When true, the new windows will always be put in the center of the active "
"screen of the monitor."
msgstr ""
"Si true (vrai), les nouvelles fenêtres seront toujours placées au centre de "
"l'écran actif du moniteur."
"Si true (vrai), les nouvelles fenêtres seront toujours placées au centre "
"de l'écran actif du moniteur."
#: ../data/org.gnome.mutter.gschema.xml.in.h:21
msgid "Select window from tab popup"
@@ -448,49 +449,29 @@ msgstr "Passer à l'émulateur de terminal 6"
msgid "Switch to VT 7"
msgstr "Passer à l'émulateur de terminal 7"
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:8
msgid "Switch to VT 8"
msgstr "Passer à l'émulateur de terminal 8"
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:9
msgid "Switch to VT 9"
msgstr "Passer à l'émulateur de terminal 9"
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:10
msgid "Switch to VT 10"
msgstr "Passer à l'émulateur de terminal 10"
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:11
msgid "Switch to VT 11"
msgstr "Passer à l'émulateur de terminal 11"
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:12
msgid "Switch to VT 12"
msgstr "Passer à l'émulateur de terminal 12"
#: ../src/backends/meta-monitor-manager.c:364
#: ../src/backends/meta-monitor-manager.c:412
msgid "Built-in display"
msgstr "Affichage intégré"
#: ../src/backends/meta-monitor-manager.c:391
#: ../src/backends/meta-monitor-manager.c:437
msgid "Unknown"
msgstr "Inconnu"
#: ../src/backends/meta-monitor-manager.c:393
#: ../src/backends/meta-monitor-manager.c:439
msgid "Unknown Display"
msgstr "Affichage inconnu"
#. TRANSLATORS: this is a monitor vendor name, followed by a
#. * size in inches, like 'Dell 15"'
#.
#: ../src/backends/meta-monitor-manager.c:401
#: ../src/backends/meta-monitor-manager.c:447
#, c-format
msgid "%s %s"
msgstr "%s %s"
#. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit
#: ../src/compositor/compositor.c:456
#: ../src/compositor/compositor.c:443
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
@@ -499,6 +480,10 @@ msgstr ""
"Un autre gestionnaire de composition est déjà lancé sur l'écran %i de "
"l'affichage « %s »."
#: ../src/compositor/meta-background.c:1044
msgid "background texture could not be created from file"
msgstr "la texture d'arrière-plan n'a pas pu être créée depuis le fichier"
#: ../src/core/bell.c:185
msgid "Bell event"
msgstr "Évènement sonore"
@@ -528,7 +513,7 @@ msgstr "_Attendre"
msgid "_Force Quit"
msgstr "_Forcer à quitter"
#: ../src/core/display.c:562
#: ../src/core/display.c:547
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Impossible d'ouvrir l'affichage « %s » du système X Window\n"
@@ -565,6 +550,19 @@ msgstr "Lancer comme un compositeur wayland"
msgid "Run as a full display server, rather than nested"
msgstr "Lancer comme un serveur d'affichage complet, plutôt qu'imbriqué"
#: ../src/core/main.c:459
#, c-format
msgid "Failed to scan themes directory: %s\n"
msgstr "Le parcours du répertoire de thèmes a échoué : %s\n"
#: ../src/core/main.c:475
#, c-format
msgid ""
"Could not find a theme! Be sure %s exists and contains the usual themes.\n"
msgstr ""
"Impossible de trouver un thème ! Assurez-vous que %s existe et contient les "
"thèmes habituels.\n"
#: ../src/core/mutter.c:39
#, c-format
msgid ""
@@ -589,29 +587,759 @@ msgstr "Afficher la version"
msgid "Mutter plugin to use"
msgstr "Greffon de Mutter à utiliser"
#: ../src/core/prefs.c:2004
#: ../src/core/prefs.c:2101
#, c-format
msgid "Workspace %d"
msgstr "Espace de travail %d"
#: ../src/core/screen.c:525
#, c-format
msgid ""
"Display \"%s\" already has a window manager; try using the --replace option "
"to replace the current window manager."
msgstr ""
"L'affichage « %s » a déjà un gestionnaire de fenêtres ; essayez d'utiliser "
"l'option --replace pour remplacer le gestionnaire de fenêtres actuel."
#: ../src/core/screen.c:607
#: ../src/core/screen.c:548
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "L'écran %d sur l'affichage « %s » n'est pas valide\n"
#: ../src/core/screen.c:564
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
"replace option to replace the current window manager.\n"
msgstr ""
"L'écran %d sur l'affichage « %s » a déjà un gestionnaire de fenêtres ; "
"essayez d'utiliser l'option --replace pour remplacer le gestionnaire de "
"fenêtres actuel.\n"
#: ../src/core/screen.c:657
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr "L'écran %d sur l'affichage « %s » a déjà un gestionnaire de fenêtres\n"
#: ../src/core/util.c:118
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Mutter a été compilé sans la prise en charge du mode bavard\n"
#. Translators: This represents the size of a window. The first number is
#. * the width of the window and the second is the height.
#.
#: ../src/ui/resizepopup.c:134
#, c-format
msgid "%d x %d"
msgstr "%d x %d"
#: ../src/ui/theme.c:233
msgid "top"
msgstr "haut"
#: ../src/ui/theme.c:235
msgid "bottom"
msgstr "bas"
#: ../src/ui/theme.c:237
msgid "left"
msgstr "gauche"
#: ../src/ui/theme.c:239
msgid "right"
msgstr "droite"
#: ../src/ui/theme.c:267
#, c-format
msgid "frame geometry does not specify \"%s\" dimension"
msgstr "la géométrie du cadre n'indique pas la dimension « %s »"
#: ../src/ui/theme.c:286
#, c-format
msgid "frame geometry does not specify dimension \"%s\" for border \"%s\""
msgstr ""
"la géométrie du cadre n'indique pas la dimension « %s » pour la bordure "
"« %s »"
#: ../src/ui/theme.c:323
#, c-format
msgid "Button aspect ratio %g is not reasonable"
msgstr "La proportion du bouton %g n'est pas raisonnable"
#: ../src/ui/theme.c:335
#, c-format
msgid "Frame geometry does not specify size of buttons"
msgstr "La géométrie du cadre n'indique pas la taille des boutons"
#: ../src/ui/theme.c:1061
#, c-format
msgid "Gradients should have at least two colors"
msgstr "Les dégradés doivent comporter au moins deux couleurs"
#: ../src/ui/theme.c:1211
#, c-format
msgid ""
"GTK custom color specification must have color name and fallback in "
"parentheses, e.g. gtk:custom(foo,bar); could not parse \"%s\""
msgstr ""
"Une spécification de couleur personnalisée GTK doit comporter un nom de "
"couleur et un substitut entre parenthèses, par ex. gtk:custom(foo,bar) ; "
"impossible d'analyser « %s »"
#: ../src/ui/theme.c:1227
#, c-format
msgid ""
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
"_ are valid"
msgstr ""
"Caractère « %c » non valide dans le paramètre color_name de gtk:custom, "
"seuls A-Za-z0-9-_ sont acceptés"
#: ../src/ui/theme.c:1241
#, c-format
msgid ""
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
"fit the format"
msgstr ""
"Le format de gtk:custom est « gtk:custom(nom_couleur,substitut) », « %s » ne "
"correspond pas à ce format"
#: ../src/ui/theme.c:1286
#, c-format
msgid ""
"GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] "
"where NORMAL is the state; could not parse \"%s\""
msgstr ""
"La spécification de couleur GTK doit présenter l'état entre crochets, p. ex. "
"gtk:fg[NORMAL] où NORMAL est l'état ; impossible d'analyser « %s »"
#: ../src/ui/theme.c:1300
#, c-format
msgid ""
"GTK color specification must have a close bracket after the state, e.g. gtk:"
"fg[NORMAL] where NORMAL is the state; could not parse \"%s\""
msgstr ""
"La spécification de couleur GTK doit comporter un crochet de fermeture après "
"l'état, p. ex. gtk:fg[NORMAL] où NORMAL est l'état ; impossible d'analyser "
"« %s »"
#: ../src/ui/theme.c:1311
#, c-format
msgid "Did not understand state \"%s\" in color specification"
msgstr ""
"Impossible de comprendre l'état « %s » dans la spécification de couleur"
#: ../src/ui/theme.c:1324
#, c-format
msgid "Did not understand color component \"%s\" in color specification"
msgstr ""
"Impossible de comprendre le composant de couleur « %s » dans la "
"spécification de couleur"
#: ../src/ui/theme.c:1352
#, c-format
msgid ""
"Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the "
"format"
msgstr ""
"Le format de mélange est « blend/bg_color/fg_color/alpha », « %s » ne "
"correspond pas à ce format ."
#: ../src/ui/theme.c:1363
#, c-format
msgid "Could not parse alpha value \"%s\" in blended color"
msgstr "Impossible d'analyser la valeur alpha « %s » en couleur mélangée"
#: ../src/ui/theme.c:1373
#, c-format
msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0"
msgstr ""
"La valeur alpha « %s » en couleur mélangée n'est pas comprise entre 0,0 et "
"1,0"
#: ../src/ui/theme.c:1419
#, c-format
msgid ""
"Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"
msgstr ""
"Le format d'ombre est « shade/base_color/factor », « %s » ne correspond pas "
"au format"
#: ../src/ui/theme.c:1430
#, c-format
msgid "Could not parse shade factor \"%s\" in shaded color"
msgstr "Impossible d'analyser le facteur d'ombre « %s » en couleur ombrée"
#: ../src/ui/theme.c:1440
#, c-format
msgid "Shade factor \"%s\" in shaded color is negative"
msgstr "Le facteur d'ombre « %s » en couleur ombrée est négatif"
#: ../src/ui/theme.c:1469
#, c-format
msgid "Could not parse color \"%s\""
msgstr "Impossible d'analyser la couleur « %s »"
#: ../src/ui/theme.c:1778
#, c-format
msgid "Coordinate expression contains character '%s' which is not allowed"
msgstr ""
"L'expression de la coordonnée contient le caractère « %s » qui n'est pas "
"autorisé"
#: ../src/ui/theme.c:1805
#, c-format
msgid ""
"Coordinate expression contains floating point number '%s' which could not be "
"parsed"
msgstr ""
"L'expression de la coordonnée contient la valeur en virgule flottante « %s » "
"qui ne peut pas être analysée"
#: ../src/ui/theme.c:1819
#, c-format
msgid "Coordinate expression contains integer '%s' which could not be parsed"
msgstr ""
"L'expression de la coordonnée contient l'entier « %s » qui n'a pas pu être "
"analysé"
#: ../src/ui/theme.c:1940
#, c-format
msgid ""
"Coordinate expression contained unknown operator at the start of this text: "
"\"%s\""
msgstr ""
"L'expression de la coordonnée contenait un opérateur inconnu au début de ce "
"texte : « %s »"
#: ../src/ui/theme.c:1997
#, c-format
msgid "Coordinate expression was empty or not understood"
msgstr "L'expression de la coordonnée était vide ou incomprise"
#: ../src/ui/theme.c:2110 ../src/ui/theme.c:2120 ../src/ui/theme.c:2154
#, c-format
msgid "Coordinate expression results in division by zero"
msgstr "L'expression de la coordonnée entraîne une division par zéro"
#: ../src/ui/theme.c:2162
#, c-format
msgid ""
"Coordinate expression tries to use mod operator on a floating-point number"
msgstr ""
"L'expression de la coordonnée tente d'utiliser l'opérateur mod sur une "
"valeur en virgule flottante"
#: ../src/ui/theme.c:2218
#, c-format
msgid ""
"Coordinate expression has an operator \"%s\" where an operand was expected"
msgstr ""
"L'expression de la coordonnée a un opérateur « %s » là où un opérande était "
"attendu"
#: ../src/ui/theme.c:2227
#, c-format
msgid "Coordinate expression had an operand where an operator was expected"
msgstr ""
"L'expression de la coordonnée a un opérande là où un opérateur était attendu"
#: ../src/ui/theme.c:2235
#, c-format
msgid "Coordinate expression ended with an operator instead of an operand"
msgstr ""
"L'expression de la coordonnée était terminée par un opérateur au lieu d'un "
"opérande"
#: ../src/ui/theme.c:2245
#, c-format
msgid ""
"Coordinate expression has operator \"%c\" following operator \"%c\" with no "
"operand in between"
msgstr ""
"L'expression de la coordonnée a un opérateur « %c » suivant l'opérateur "
"« %c » sans opérande entre eux"
#: ../src/ui/theme.c:2396 ../src/ui/theme.c:2441
#, c-format
msgid "Coordinate expression had unknown variable or constant \"%s\""
msgstr ""
"L'expression de la coordonnée possède une variable ou constante inconnue "
"« %s »"
#: ../src/ui/theme.c:2495
#, c-format
msgid "Coordinate expression parser overflowed its buffer."
msgstr ""
"L'analyseur d'expression de coordonnées a dépassé la capacité de son tampon."
#: ../src/ui/theme.c:2524
#, c-format
msgid "Coordinate expression had a close parenthesis with no open parenthesis"
msgstr ""
"L'expression de la coordonnée comporte une parenthèse de fermeture, mais pas "
"de parenthèse d'ouverture"
#: ../src/ui/theme.c:2588
#, c-format
msgid "Coordinate expression had an open parenthesis with no close parenthesis"
msgstr ""
"L'expression de la coordonnée comporte une parenthèse d'ouverture, mais pas "
"de parenthèse de fermeture"
#: ../src/ui/theme.c:2599
#, c-format
msgid "Coordinate expression doesn't seem to have any operators or operands"
msgstr ""
"L'expression de la coordonnée ne semble pas comprendre d'opérateur ni "
"d'opérande"
#: ../src/ui/theme.c:2812 ../src/ui/theme.c:2832 ../src/ui/theme.c:2852
#, c-format
msgid "Theme contained an expression that resulted in an error: %s\n"
msgstr "Le thème contient une expression qui a entraîné une erreur : %s\n"
#: ../src/ui/theme.c:4455
#, c-format
msgid ""
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be "
"specified for this frame style"
msgstr ""
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> doit être "
"indiqué pour ce style de cadre"
#: ../src/ui/theme.c:4970 ../src/ui/theme.c:4995
#, c-format
msgid ""
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
msgstr ""
"<frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/> manquant"
#: ../src/ui/theme.c:5041
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr "Impossible de charger le thème « %s » : %s\n"
#: ../src/ui/theme.c:5177 ../src/ui/theme.c:5184 ../src/ui/theme.c:5191
#: ../src/ui/theme.c:5198 ../src/ui/theme.c:5205
#, c-format
msgid "No <%s> set for theme \"%s\""
msgstr "Aucun <%s> défini pour le thème « %s »"
#: ../src/ui/theme.c:5213
#, c-format
msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
"type=\"%s\" style_set=\"whatever\"/> element"
msgstr ""
"Aucun style de cadre défini pour le type de fenêtre « %s » dans le thème "
"« %s », ajoutez un élément <window type=\"%s\" style_set=\"whatever\"/>"
#: ../src/ui/theme.c:5620 ../src/ui/theme.c:5682 ../src/ui/theme.c:5745
#, c-format
msgid ""
"User-defined constants must begin with a capital letter; \"%s\" does not"
msgstr ""
"Les constantes définies par l'utilisateur doivent commencer par une "
"majuscule ; « %s » commence par une minuscule"
#: ../src/ui/theme.c:5628 ../src/ui/theme.c:5690 ../src/ui/theme.c:5753
#, c-format
msgid "Constant \"%s\" has already been defined"
msgstr "La constante « %s » a déjà été définie"
#. Translators: This means that an attribute which should have been found
#. * on an XML element was not in fact found.
#.
#: ../src/ui/theme-parser.c:234
#, c-format
msgid "No \"%s\" attribute on element <%s>"
msgstr "Aucun attribut « %s » sur l'élément <%s>"
#: ../src/ui/theme-parser.c:263 ../src/ui/theme-parser.c:281
#, c-format
msgid "Line %d character %d: %s"
msgstr "Ligne %d caractère %d: %s"
#: ../src/ui/theme-parser.c:481
#, c-format
msgid "Attribute \"%s\" repeated twice on the same <%s> element"
msgstr "Attribut « %s » répété deux fois sur le même élément <%s>"
#: ../src/ui/theme-parser.c:505 ../src/ui/theme-parser.c:554
#, c-format
msgid "Attribute \"%s\" is invalid on <%s> element in this context"
msgstr "Attribut « %s » non valide sur l'élément <%s> dans ce contexte"
#: ../src/ui/theme-parser.c:596
#, c-format
msgid "Could not parse \"%s\" as an integer"
msgstr "Impossible d'analyser « %s » en tant qu'entier"
#: ../src/ui/theme-parser.c:605 ../src/ui/theme-parser.c:660
#, c-format
msgid "Did not understand trailing characters \"%s\" in string \"%s\""
msgstr "Caractères de fin « %s » non compris dans la chaîne « %s »"
#: ../src/ui/theme-parser.c:615
#, c-format
msgid "Integer %ld must be positive"
msgstr "L'entier %ld doit être positif"
#: ../src/ui/theme-parser.c:623
#, c-format
msgid "Integer %ld is too large, current max is %d"
msgstr "L'entier %ld est trop élevé, le max. actuel est %d"
#: ../src/ui/theme-parser.c:651 ../src/ui/theme-parser.c:767
#, c-format
msgid "Could not parse \"%s\" as a floating point number"
msgstr "Impossible d'analyser « %s » en tant que valeur en virgule flottante"
#: ../src/ui/theme-parser.c:682 ../src/ui/theme-parser.c:710
#, c-format
msgid "Boolean values must be \"true\" or \"false\" not \"%s\""
msgstr ""
"Les valeurs booléennes doivent être « true » ou « false » et non « %s »"
#: ../src/ui/theme-parser.c:737
#, c-format
msgid "Angle must be between 0.0 and 360.0, was %g\n"
msgstr "L'angle doit être compris entre 0,0 et 360,0. Il était de %g\n"
#: ../src/ui/theme-parser.c:800
#, c-format
msgid "Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n"
msgstr ""
"La valeur alpha doit être comprise entre 0,0 (invisible) et 1,0 (entièrement "
"opaque). Elle était de %g\n"
#: ../src/ui/theme-parser.c:865
#, c-format
msgid ""
"Invalid title scale \"%s\" (must be one of xx-small,x-small,small,medium,"
"large,x-large,xx-large)\n"
msgstr ""
"Échelle de titre non valide « %s » (elle doit avoir l'une des valeurs "
"suivantes : xx-small, x-small, small, medium,large, x-large, xx-large)\n"
#: ../src/ui/theme-parser.c:1021 ../src/ui/theme-parser.c:1084
#: ../src/ui/theme-parser.c:1118 ../src/ui/theme-parser.c:1221
#, c-format
msgid "<%s> name \"%s\" used a second time"
msgstr "<%s> - nom « %s » utilisé une deuxième fois"
#: ../src/ui/theme-parser.c:1033 ../src/ui/theme-parser.c:1130
#: ../src/ui/theme-parser.c:1233
#, c-format
msgid "<%s> parent \"%s\" has not been defined"
msgstr "<%s> - parent « %s » non défini"
#: ../src/ui/theme-parser.c:1143
#, c-format
msgid "<%s> geometry \"%s\" has not been defined"
msgstr "<%s> - géométrie « %s » non définie"
#: ../src/ui/theme-parser.c:1156
#, c-format
msgid "<%s> must specify either a geometry or a parent that has a geometry"
msgstr "<%s> doit indiquer une géométrie ou un parent qui en possède une"
#: ../src/ui/theme-parser.c:1198
msgid "You must specify a background for an alpha value to be meaningful"
msgstr ""
"Vous devez indiquer un arrière-plan pour qu'une valeur alpha ait du sens."
#: ../src/ui/theme-parser.c:1266
#, c-format
msgid "Unknown type \"%s\" on <%s> element"
msgstr "Type inconnu « %s » sur l'élément <%s>"
#: ../src/ui/theme-parser.c:1277
#, c-format
msgid "Unknown style_set \"%s\" on <%s> element"
msgstr "style_set inconnu « %s » sur l'élément <%s>"
#: ../src/ui/theme-parser.c:1285
#, c-format
msgid "Window type \"%s\" has already been assigned a style set"
msgstr "Le type de fenêtre « %s » s'est déjà vu attribuer un jeu de styles"
#: ../src/ui/theme-parser.c:1315 ../src/ui/theme-parser.c:1379
#: ../src/ui/theme-parser.c:1605 ../src/ui/theme-parser.c:2840
#: ../src/ui/theme-parser.c:2886 ../src/ui/theme-parser.c:3036
#: ../src/ui/theme-parser.c:3272 ../src/ui/theme-parser.c:3310
#: ../src/ui/theme-parser.c:3348 ../src/ui/theme-parser.c:3386
#, c-format
msgid "Element <%s> is not allowed below <%s>"
msgstr "L'élément <%s> n'est pas autorisé sous <%s>"
#: ../src/ui/theme-parser.c:1429 ../src/ui/theme-parser.c:1443
#: ../src/ui/theme-parser.c:1488
msgid ""
"Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" "
"for buttons"
msgstr ""
"Impossible d'indiquer à la fois « button_width » / "
 button_height » (largeur/hauteur) et « aspect_ratio » (proportion) pour "
"les boutons"
#: ../src/ui/theme-parser.c:1452
#, c-format
msgid "Distance \"%s\" is unknown"
msgstr "Distance « %s » inconnue"
#: ../src/ui/theme-parser.c:1497
#, c-format
msgid "Aspect ratio \"%s\" is unknown"
msgstr "Proportion « %s » inconnue"
#: ../src/ui/theme-parser.c:1559
#, c-format
msgid "Border \"%s\" is unknown"
msgstr "Bordure « %s » inconnue"
#: ../src/ui/theme-parser.c:1870
#, c-format
msgid "No \"start_angle\" or \"from\" attribute on element <%s>"
msgstr ""
"Aucun attribut « start_angle » (« début d'angle ») ou « from » (« depuis ») "
"sur l'élément <%s>"
#: ../src/ui/theme-parser.c:1877
#, c-format
msgid "No \"extent_angle\" or \"to\" attribute on element <%s>"
msgstr ""
"Aucun attribut « extent_angle » (« extension d'angle ») ou « to » (« vers ») "
"sur l'élément <%s>"
#: ../src/ui/theme-parser.c:2117
#, c-format
msgid "Did not understand value \"%s\" for type of gradient"
msgstr "Impossible de comprendre la valeur « %s » pour le type de dégradé"
#: ../src/ui/theme-parser.c:2195 ../src/ui/theme-parser.c:2570
#, c-format
msgid "Did not understand fill type \"%s\" for <%s> element"
msgstr ""
"Impossible de comprendre le type de remplissage « %s » pour l'élément <%s>"
#: ../src/ui/theme-parser.c:2362 ../src/ui/theme-parser.c:2445
#: ../src/ui/theme-parser.c:2508
#, c-format
msgid "Did not understand state \"%s\" for <%s> element"
msgstr "Impossible de comprendre l'état « %s » pour l'élément <%s>"
#: ../src/ui/theme-parser.c:2372 ../src/ui/theme-parser.c:2455
#, c-format
msgid "Did not understand shadow \"%s\" for <%s> element"
msgstr "Impossible de comprendre l'ombre « %s » pour l'élément <%s>"
#: ../src/ui/theme-parser.c:2382
#, c-format
msgid "Did not understand arrow \"%s\" for <%s> element"
msgstr "Impossible de comprendre la flèche « %s » pour l'élément <%s>"
#: ../src/ui/theme-parser.c:2696 ../src/ui/theme-parser.c:2792
#, c-format
msgid "No <draw_ops> called \"%s\" has been defined"
msgstr "Aucun <draw_ops> appelé « %s » n'a été défini"
#: ../src/ui/theme-parser.c:2708 ../src/ui/theme-parser.c:2804
#, c-format
msgid "Including draw_ops \"%s\" here would create a circular reference"
msgstr "L'inclusion du draw_ops « %s » ici créerait une référence circulaire"
#: ../src/ui/theme-parser.c:2919
#, c-format
msgid "Unknown position \"%s\" for frame piece"
msgstr "Position inconnue « %s » de la pièce du cadre"
#: ../src/ui/theme-parser.c:2927
#, c-format
msgid "Frame style already has a piece at position %s"
msgstr "Le style de cadre a déjà une pièce à la position %s"
#: ../src/ui/theme-parser.c:2944 ../src/ui/theme-parser.c:3021
#, c-format
msgid "No <draw_ops> with the name \"%s\" has been defined"
msgstr "Aucun <draw_ops> avec le nom « %s » n'a été défini"
#: ../src/ui/theme-parser.c:2974
#, c-format
msgid "Unknown function \"%s\" for button"
msgstr "Fonction inconnue « %s » pour le bouton"
#: ../src/ui/theme-parser.c:2984
#, c-format
msgid "Button function \"%s\" does not exist in this version (%d, need %d)"
msgstr ""
"La fonction « %s » du bouton n'existe pas dans la version (%d, a besoin de "
"%d)"
#: ../src/ui/theme-parser.c:2996
#, c-format
msgid "Unknown state \"%s\" for button"
msgstr "État inconnu « %s » pour le bouton"
#: ../src/ui/theme-parser.c:3004
#, c-format
msgid "Frame style already has a button for function %s state %s"
msgstr "Le style de cadre a déjà un bouton pour la fonction %s, état %s"
#: ../src/ui/theme-parser.c:3075
#, c-format
msgid "\"%s\" is not a valid value for focus attribute"
msgstr "« %s » n'est pas une valeur valide pour l'attribut de focus"
#: ../src/ui/theme-parser.c:3084
#, c-format
msgid "\"%s\" is not a valid value for state attribute"
msgstr "« %s » n'est pas une valeur valide pour l'attribut d'état"
#: ../src/ui/theme-parser.c:3094
#, c-format
msgid "A style called \"%s\" has not been defined"
msgstr "Aucun style appelé « %s » n'a été défini"
#: ../src/ui/theme-parser.c:3115 ../src/ui/theme-parser.c:3138
#, c-format
msgid "\"%s\" is not a valid value for resize attribute"
msgstr ""
"« %s » n'est pas une valeur valide pour l'attribut de redimensionnement"
#: ../src/ui/theme-parser.c:3149
#, c-format
msgid ""
"Should not have \"resize\" attribute on <%s> element for maximized/shaded "
"states"
msgstr ""
"L'attribut « resize » (« redimensionnement ») ne devrait pas figurer sur "
"l'élément <%s> pour les états maximisé/réduit dans la barre de titre"
#: ../src/ui/theme-parser.c:3163
#, c-format
msgid ""
"Should not have \"resize\" attribute on <%s> element for maximized states"
msgstr ""
"L'attribut « resize » (« redimensionnement ») ne devrait pas figurer sur "
"l'élément <%s> pour l'état maximisé"
#: ../src/ui/theme-parser.c:3177 ../src/ui/theme-parser.c:3221
#, c-format
msgid "Style has already been specified for state %s resize %s focus %s"
msgstr ""
"Le style a déjà été indiqué pour l'état %s, redimensionnement %s, focus %s"
#: ../src/ui/theme-parser.c:3188 ../src/ui/theme-parser.c:3199
#: ../src/ui/theme-parser.c:3210 ../src/ui/theme-parser.c:3232
#: ../src/ui/theme-parser.c:3243 ../src/ui/theme-parser.c:3254
#, c-format
msgid "Style has already been specified for state %s focus %s"
msgstr "Le style a déjà été indiqué pour l'état %s, focus %s"
#: ../src/ui/theme-parser.c:3293
msgid ""
"Can't have a two draw_ops for a <piece> element (theme specified a draw_ops "
"attribute and also a <draw_ops> element, or specified two elements)"
msgstr ""
"Impossible d'avoir deux attributs draw_ops pour un élément <piece> (le thème "
"indiquait un attribut draw_ops et un élément <draw_ops> ou deux éléments)"
#: ../src/ui/theme-parser.c:3331
msgid ""
"Can't have a two draw_ops for a <button> element (theme specified a draw_ops "
"attribute and also a <draw_ops> element, or specified two elements)"
msgstr ""
"Impossible d'avoir deux attributs draw_ops pour un élément <button> (le "
"thème indiquait un attribut draw_ops et un élément <draw_ops> ou deux "
"éléments)"
#: ../src/ui/theme-parser.c:3369
msgid ""
"Can't have a two draw_ops for a <menu_icon> element (theme specified a "
"draw_ops attribute and also a <draw_ops> element, or specified two elements)"
msgstr ""
"Impossible d'avoir deux attributs draw_ops pour un élément <menu_icon> (le "
"thème indiquait un attribut draw_ops et un élément <draw_ops> ou deux "
"éléments)"
#: ../src/ui/theme-parser.c:3433
#, c-format
msgid "Bad version specification '%s'"
msgstr "Mauvaise spécification de version « %s »"
#: ../src/ui/theme-parser.c:3506
msgid ""
"\"version\" attribute cannot be used in metacity-theme-1.xml or metacity-"
"theme-2.xml"
msgstr ""
"L'attribut « version » ne peut pas être utilisé dans metacity-theme-1.xml or "
"metacity-theme-2.xml"
#: ../src/ui/theme-parser.c:3529
#, c-format
msgid "Theme requires version %s but latest supported theme version is %d.%d"
msgstr ""
"Le thème nécessite la version %s mais la version de thème la plus récente "
"prise en charge est %d.%d"
#: ../src/ui/theme-parser.c:3561
#, c-format
msgid "Outermost element in theme must be <metacity_theme> not <%s>"
msgstr ""
"L'élément le plus extérieur dans le thème doit être <metacity_theme> et non <"
"%s>"
#: ../src/ui/theme-parser.c:3581
#, c-format
msgid ""
"Element <%s> is not allowed inside a name/author/date/description element"
msgstr ""
"L'élément <%s> n'est pas autorisé dans un élément name/author/date/"
"description"
#: ../src/ui/theme-parser.c:3586
#, c-format
msgid "Element <%s> is not allowed inside a <constant> element"
msgstr "L'élément <%s> n'est pas autorisé dans un élément <constant>"
#: ../src/ui/theme-parser.c:3598
#, c-format
msgid ""
"Element <%s> is not allowed inside a distance/border/aspect_ratio element"
msgstr ""
"L'élément <%s> n'est pas autorisé dans un élément distance/border/"
"aspect_ratio"
#: ../src/ui/theme-parser.c:3620
#, c-format
msgid "Element <%s> is not allowed inside a draw operation element"
msgstr ""
"L'élément <%s> n'est pas autorisé dans un élément d'opération de dessin"
#: ../src/ui/theme-parser.c:3630 ../src/ui/theme-parser.c:3660
#: ../src/ui/theme-parser.c:3665 ../src/ui/theme-parser.c:3670
#, c-format
msgid "Element <%s> is not allowed inside a <%s> element"
msgstr "L'élément <%s> n'est pas autorisé dans un élément <%s>"
#: ../src/ui/theme-parser.c:3898
msgid "No draw_ops provided for frame piece"
msgstr "Aucun attribut draw_ops fourni pour la pièce du cadre"
#: ../src/ui/theme-parser.c:3913
msgid "No draw_ops provided for button"
msgstr "Aucun attribut draw_ops fourni pour le bouton"
#: ../src/ui/theme-parser.c:3967
#, c-format
msgid "No text is allowed inside element <%s>"
msgstr "Aucun texte autorisé dans l'élément <%s>"
#: ../src/ui/theme-parser.c:4025 ../src/ui/theme-parser.c:4037
#: ../src/ui/theme-parser.c:4049 ../src/ui/theme-parser.c:4061
#: ../src/ui/theme-parser.c:4073
#, c-format
msgid "<%s> specified twice for this theme"
msgstr "<%s> indiqué deux fois pour ce thème"
#: ../src/ui/theme-parser.c:4335
#, c-format
msgid "Failed to find a valid file for theme %s\n"
msgstr "Impossible de trouver un fichier valide pour le thème %s\n"
#: ../src/x11/session.c:1815
msgid ""
"These windows do not support &quot;save current setup&quot; and will have to "
@@ -621,7 +1349,7 @@ msgstr ""
"configuration actuelle » et devront être redémarrées manuellement à la "
"prochaine connexion."
#: ../src/x11/window-props.c:549
#: ../src/x11/window-props.c:515
#, c-format
msgid "%s (on %s)"
msgstr "%s (sur %s)"

1275
po/gl.po

File diff suppressed because it is too large Load Diff

1225
po/he.po

File diff suppressed because it is too large Load Diff

1271
po/hu.po

File diff suppressed because it is too large Load Diff

1268
po/lt.po

File diff suppressed because it is too large Load Diff

273
po/nb.po
View File

@@ -4,10 +4,10 @@
#
msgid ""
msgstr ""
"Project-Id-Version: mutter 3.15.x\n"
"Project-Id-Version: mutter 3.13.x\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-11-15 18:32+0100\n"
"PO-Revision-Date: 2014-11-15 18:34+0100\n"
"POT-Creation-Date: 2014-09-06 14:13+0200\n"
"PO-Revision-Date: 2014-08-23 13:37+0200\n"
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
"Language-Team: Norwegian bokmål <i18n-no@lister.ping.uio.no>\n"
"Language: \n"
@@ -351,7 +351,7 @@ msgid ""
"If set to true, and the focus mode is either \"sloppy\" or \"mouse\" then "
"the focus will not be changed immediately when entering a window, but only "
"after the pointer stops moving."
msgstr "Hvis denne settes til «true» og fokusmodus er enten «sloppy» eller «mouse» så vil fokus ikke endres med en gang markøren kommer inn i et vindu, men i stedet når markørens bevegelse stopper."
msgstr ""
#: ../data/org.gnome.mutter.gschema.xml.in.h:15
msgid "Draggable border width"
@@ -385,7 +385,7 @@ msgstr "Plasser nye vinduer i senter"
msgid ""
"When true, the new windows will always be put in the center of the active "
"screen of the monitor."
msgstr "Når denne er «true» vil mye vinduer alltid plasseres midt på aktivt område på skjermen."
msgstr ""
#: ../data/org.gnome.mutter.gschema.xml.in.h:21
msgid "Select window from tab popup"
@@ -423,29 +423,29 @@ msgstr "Bytt til VT 6"
msgid "Switch to VT 7"
msgstr "Bytt til VT 7"
#: ../src/backends/meta-monitor-manager.c:350
#: ../src/backends/meta-monitor-manager.c:412
msgid "Built-in display"
msgstr "Innebygget skjerm"
#: ../src/backends/meta-monitor-manager.c:375
#: ../src/backends/meta-monitor-manager.c:437
msgid "Unknown"
msgstr "Ukjent"
#: ../src/backends/meta-monitor-manager.c:377
#: ../src/backends/meta-monitor-manager.c:439
msgid "Unknown Display"
msgstr "Ukjent skjerm"
#. TRANSLATORS: this is a monitor vendor name, followed by a
#. * size in inches, like 'Dell 15"'
#.
#: ../src/backends/meta-monitor-manager.c:385
#: ../src/backends/meta-monitor-manager.c:447
#, c-format
msgid "%s %s"
msgstr "%s %s"
#. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit
#: ../src/compositor/compositor.c:456
#: ../src/compositor/compositor.c:443
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
@@ -481,7 +481,7 @@ msgstr "_Vent"
msgid "_Force Quit"
msgstr "_Tvungen nedstenging"
#: ../src/core/display.c:550
#: ../src/core/display.c:547
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Feil under åpning av X Window System skjerm «%s»\n"
@@ -518,12 +518,12 @@ msgstr "Kjør som en wayland-kompositør"
msgid "Run as a full display server, rather than nested"
msgstr "Kjør som en full skjermtjener, heller enn nøstet"
#: ../src/core/main.c:451
#: ../src/core/main.c:459
#, c-format
msgid "Failed to scan themes directory: %s\n"
msgstr "Feil under søk i temakatalog: %s\n"
#: ../src/core/main.c:467
#: ../src/core/main.c:475
#, c-format
msgid ""
"Could not find a theme! Be sure %s exists and contains the usual themes.\n"
@@ -553,17 +553,17 @@ msgstr "Skriv versjonsnummer"
msgid "Mutter plugin to use"
msgstr "Mutter-tillegg som skal brukes"
#: ../src/core/prefs.c:2064
#: ../src/core/prefs.c:2101
#, c-format
msgid "Workspace %d"
msgstr "Arbeidsområde %d"
#: ../src/core/screen.c:543
#: ../src/core/screen.c:548
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "Skjerm %d på display «%s» er ugyldig\n"
#: ../src/core/screen.c:559
#: ../src/core/screen.c:564
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
@@ -572,7 +572,7 @@ msgstr ""
"Skjerm %d på display «%s» har allerede en vindushåndterer; prøv å bruke "
"flagget --replace for å erstatte aktiv vindushåndterer.\n"
#: ../src/core/screen.c:652
#: ../src/core/screen.c:657
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr "Skjerm %d på display «%s» har allerede en vinduhåndterer\n"
@@ -589,48 +589,48 @@ msgstr "Mutter er kompilert uten støtte for «verbose» modus\n"
msgid "%d x %d"
msgstr "%d x %d"
#: ../src/ui/theme.c:154
#: ../src/ui/theme.c:233
msgid "top"
msgstr "topp"
#: ../src/ui/theme.c:156
#: ../src/ui/theme.c:235
msgid "bottom"
msgstr "bunn"
#: ../src/ui/theme.c:158
#: ../src/ui/theme.c:237
msgid "left"
msgstr "venstre"
#: ../src/ui/theme.c:160
#: ../src/ui/theme.c:239
msgid "right"
msgstr "høyre"
#: ../src/ui/theme.c:188
#: ../src/ui/theme.c:267
#, c-format
msgid "frame geometry does not specify \"%s\" dimension"
msgstr "rammegeometrien spesifiserer ikke «%s»-dimensjon"
#: ../src/ui/theme.c:207
#: ../src/ui/theme.c:286
#, c-format
msgid "frame geometry does not specify dimension \"%s\" for border \"%s\""
msgstr "rammegeometri spesifiserer ikke dimensjon «%s» for kant «%s»"
#: ../src/ui/theme.c:244
#: ../src/ui/theme.c:323
#, c-format
msgid "Button aspect ratio %g is not reasonable"
msgstr "Aspektrate %g for knapp er ikke fornuftig"
#: ../src/ui/theme.c:256
#: ../src/ui/theme.c:335
#, c-format
msgid "Frame geometry does not specify size of buttons"
msgstr "Rammegeometrien spesifiserer ikke størrelse på knapper"
#: ../src/ui/theme.c:1024
#: ../src/ui/theme.c:1061
#, c-format
msgid "Gradients should have at least two colors"
msgstr "Gradienter må ha minst to farger"
#: ../src/ui/theme.c:1174
#: ../src/ui/theme.c:1211
#, c-format
msgid ""
"GTK custom color specification must have color name and fallback in "
@@ -639,7 +639,7 @@ msgstr ""
"Egendefinert GTK-fargespesifikasjon må ha fargenavn og reserve i parantes, f."
"eks gtk:custom(foo,bar); kunne ikke lese «%s»"
#: ../src/ui/theme.c:1190
#: ../src/ui/theme.c:1227
#, c-format
msgid ""
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
@@ -648,7 +648,7 @@ msgstr ""
"Ugyldig tegn «%c» i parameter color_name for gtk:custom, kun A-Za-z0-9-_ er "
"gyldig"
#: ../src/ui/theme.c:1204
#: ../src/ui/theme.c:1241
#, c-format
msgid ""
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
@@ -657,7 +657,7 @@ msgstr ""
"Gtk:custom-format er «gtk:custom(color_name,fallback)», «%s» passer ikke i "
"formatet"
#: ../src/ui/theme.c:1249
#: ../src/ui/theme.c:1286
#, c-format
msgid ""
"GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] "
@@ -666,7 +666,7 @@ msgstr ""
"GTK-fargespesifikasjon må ha tilstand i klammer, f.eks. gtk:fg[NORMAL], hvor "
"NORMAL er tilstanden; kunne ikke lese «%s»"
#: ../src/ui/theme.c:1263
#: ../src/ui/theme.c:1300
#, c-format
msgid ""
"GTK color specification must have a close bracket after the state, e.g. gtk:"
@@ -675,17 +675,17 @@ msgstr ""
"GTK-fargespesifikasjon må ha en avsluttende klamme etter tilstanden, f.eks. "
"gtk:fg[NORMAL], hvor NORMAL er tilstanden; kunne ikke lese «%s»"
#: ../src/ui/theme.c:1274
#: ../src/ui/theme.c:1311
#, c-format
msgid "Did not understand state \"%s\" in color specification"
msgstr "Forsto ikke tilstand «%s» i fargespesifikasjonen"
#: ../src/ui/theme.c:1287
#: ../src/ui/theme.c:1324
#, c-format
msgid "Did not understand color component \"%s\" in color specification"
msgstr "Forsto ikke fargekomponent «%s» i fargespesifikasjonen"
#: ../src/ui/theme.c:1315
#: ../src/ui/theme.c:1352
#, c-format
msgid ""
"Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the "
@@ -694,56 +694,56 @@ msgstr ""
"Blandingsformat er «blend/bg_color/fg_color/alpha», «%s» passer ikke i "
"formatet"
#: ../src/ui/theme.c:1326
#: ../src/ui/theme.c:1363
#, c-format
msgid "Could not parse alpha value \"%s\" in blended color"
msgstr "Kunne ikke lese alpha-verdi «%s» i blandet farge"
#: ../src/ui/theme.c:1336
#: ../src/ui/theme.c:1373
#, c-format
msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0"
msgstr "Alpha-verdi «%s» i blandet farge er ikke mellom 0.0 og 1.0"
#: ../src/ui/theme.c:1382
#: ../src/ui/theme.c:1419
#, c-format
msgid ""
"Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"
msgstr ""
"Skyggeformatet er «shade/base_color/factor», «%s» passer ikke i formatet"
#: ../src/ui/theme.c:1393
#: ../src/ui/theme.c:1430
#, c-format
msgid "Could not parse shade factor \"%s\" in shaded color"
msgstr "Kunne ikke lese skyggefaktor «%s» i skyggelagt farge"
#: ../src/ui/theme.c:1403
#: ../src/ui/theme.c:1440
#, c-format
msgid "Shade factor \"%s\" in shaded color is negative"
msgstr "Skyggefaktor «%s» i skyggelagt farge er negativ"
#: ../src/ui/theme.c:1432
#: ../src/ui/theme.c:1469
#, c-format
msgid "Could not parse color \"%s\""
msgstr "Kunne ikke lese farge «%s»"
#: ../src/ui/theme.c:1741
#: ../src/ui/theme.c:1778
#, c-format
msgid "Coordinate expression contains character '%s' which is not allowed"
msgstr "Koordinatuttrykk inneholder tegn «%s» som ikke er tillatt"
#: ../src/ui/theme.c:1768
#: ../src/ui/theme.c:1805
#, c-format
msgid ""
"Coordinate expression contains floating point number '%s' which could not be "
"parsed"
msgstr "Koordinatuttrykk inneholder flyttall «%s» som ikke kunne tolkes"
#: ../src/ui/theme.c:1782
#: ../src/ui/theme.c:1819
#, c-format
msgid "Coordinate expression contains integer '%s' which could not be parsed"
msgstr "Koordinatuttrykk inneholder heltall «%s» som ikke kunne tolkes"
#: ../src/ui/theme.c:1903
#: ../src/ui/theme.c:1940
#, c-format
msgid ""
"Coordinate expression contained unknown operator at the start of this text: "
@@ -752,39 +752,39 @@ msgstr ""
"Koordinatuttrykket inneholdt en ukjent operator ved begynnelsen av denne "
"teksten: «%s»"
#: ../src/ui/theme.c:1960
#: ../src/ui/theme.c:1997
#, c-format
msgid "Coordinate expression was empty or not understood"
msgstr "Koordinatuttrykket var tomt eller ble ikke forstått"
#: ../src/ui/theme.c:2073 ../src/ui/theme.c:2083 ../src/ui/theme.c:2117
#: ../src/ui/theme.c:2110 ../src/ui/theme.c:2120 ../src/ui/theme.c:2154
#, c-format
msgid "Coordinate expression results in division by zero"
msgstr "Koordinatuttrykket resulterer i divisjon med null"
#: ../src/ui/theme.c:2125
#: ../src/ui/theme.c:2162
#, c-format
msgid ""
"Coordinate expression tries to use mod operator on a floating-point number"
msgstr "Koordinatuttrykket prøver å bruke mod-operator på et flyttall"
#: ../src/ui/theme.c:2181
#: ../src/ui/theme.c:2218
#, c-format
msgid ""
"Coordinate expression has an operator \"%s\" where an operand was expected"
msgstr "Koordinatuttrykket har en operator «%s» hvor en operand var ventet"
#: ../src/ui/theme.c:2190
#: ../src/ui/theme.c:2227
#, c-format
msgid "Coordinate expression had an operand where an operator was expected"
msgstr "Koordinatuttrykket hadde en operand hvor en operator var ventet"
#: ../src/ui/theme.c:2198
#: ../src/ui/theme.c:2235
#, c-format
msgid "Coordinate expression ended with an operator instead of an operand"
msgstr "Koordinatuttrykket sluttet med en operator i stedet for en operand"
#: ../src/ui/theme.c:2208
#: ../src/ui/theme.c:2245
#, c-format
msgid ""
"Coordinate expression has operator \"%c\" following operator \"%c\" with no "
@@ -793,38 +793,38 @@ msgstr ""
"Koordinatuttrykket har en operator «%c» etter en operator «%c» og ingen "
"operand mellom dem."
#: ../src/ui/theme.c:2359 ../src/ui/theme.c:2404
#: ../src/ui/theme.c:2396 ../src/ui/theme.c:2441
#, c-format
msgid "Coordinate expression had unknown variable or constant \"%s\""
msgstr "Koordinatuttrykket haddeen ukjent variabel eller konstant «%s»"
#: ../src/ui/theme.c:2458
#: ../src/ui/theme.c:2495
#, c-format
msgid "Coordinate expression parser overflowed its buffer."
msgstr "Tolkeren for koordinatuttrykk oversteg buffergrensen."
#: ../src/ui/theme.c:2487
#: ../src/ui/theme.c:2524
#, c-format
msgid "Coordinate expression had a close parenthesis with no open parenthesis"
msgstr "Koordinatuttrykket hadde en parantes slutt uten parantes start"
#: ../src/ui/theme.c:2551
#: ../src/ui/theme.c:2588
#, c-format
msgid "Coordinate expression had an open parenthesis with no close parenthesis"
msgstr "Koordinatuttrykket hadde en åpen parantes uten en avsluttende parantes"
#: ../src/ui/theme.c:2562
#: ../src/ui/theme.c:2599
#, c-format
msgid "Coordinate expression doesn't seem to have any operators or operands"
msgstr ""
"Koordinatuttrykket ser ikke ut til å ha noen operatorer eller operander"
#: ../src/ui/theme.c:2775 ../src/ui/theme.c:2795 ../src/ui/theme.c:2815
#: ../src/ui/theme.c:2812 ../src/ui/theme.c:2832 ../src/ui/theme.c:2852
#, c-format
msgid "Theme contained an expression that resulted in an error: %s\n"
msgstr "Tema inneholdt et uttrykk som resulterte i en feil: %s\n"
#: ../src/ui/theme.c:4055
#: ../src/ui/theme.c:4455
#, c-format
msgid ""
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be "
@@ -833,25 +833,25 @@ msgstr ""
"<button function=«%s» state=«%s» draw_ops=«ett-eller-annet»/> må "
"spesifiseres for denne rammestilen"
#: ../src/ui/theme.c:4570 ../src/ui/theme.c:4595
#: ../src/ui/theme.c:4970 ../src/ui/theme.c:4995
#, c-format
msgid ""
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
msgstr ""
"Mangler <frame state=«%s» resize=«%s» focus=«%s» stil=«ett-eller-annet»/>"
#: ../src/ui/theme.c:4641
#: ../src/ui/theme.c:5041
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr "Klarte ikke å laste tema «%s»: %s\n"
#: ../src/ui/theme.c:4777 ../src/ui/theme.c:4784 ../src/ui/theme.c:4791
#: ../src/ui/theme.c:4798 ../src/ui/theme.c:4805
#: ../src/ui/theme.c:5177 ../src/ui/theme.c:5184 ../src/ui/theme.c:5191
#: ../src/ui/theme.c:5198 ../src/ui/theme.c:5205
#, c-format
msgid "No <%s> set for theme \"%s\""
msgstr "<%s> er ikke satt for tema «%s»"
#: ../src/ui/theme.c:4813
#: ../src/ui/theme.c:5213
#, c-format
msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
@@ -860,14 +860,14 @@ msgstr ""
"Ingen rammestil satt for vindutype «%s» i tema «%s», legg til et <window "
"type=«%s» style_set=«ett-eller-annet»/>-element"
#: ../src/ui/theme.c:5220 ../src/ui/theme.c:5282 ../src/ui/theme.c:5345
#: ../src/ui/theme.c:5620 ../src/ui/theme.c:5682 ../src/ui/theme.c:5745
#, c-format
msgid ""
"User-defined constants must begin with a capital letter; \"%s\" does not"
msgstr ""
"Brukerdefinerte konstanter må begynne med stor bokstav; «%s» gjør ikke det"
#: ../src/ui/theme.c:5228 ../src/ui/theme.c:5290 ../src/ui/theme.c:5353
#: ../src/ui/theme.c:5628 ../src/ui/theme.c:5690 ../src/ui/theme.c:5753
#, c-format
msgid "Constant \"%s\" has already been defined"
msgstr "Konstant «%s» er allerede definert"
@@ -930,13 +930,13 @@ msgstr "Bolske verdier må være «sann» eller «usann» ikke «%s»"
msgid "Angle must be between 0.0 and 360.0, was %g\n"
msgstr "Vinkelen må være mellom 0.0 og 360.0, var %g\n"
#: ../src/ui/theme-parser.c:797
#: ../src/ui/theme-parser.c:800
#, c-format
msgid "Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n"
msgstr ""
"Alpha må være mellom 0.0 (usynlig) og 1.0 (helt ugjennomsiktig), var %g\n"
#: ../src/ui/theme-parser.c:862
#: ../src/ui/theme-parser.c:865
#, c-format
msgid ""
"Invalid title scale \"%s\" (must be one of xx-small,x-small,small,medium,"
@@ -945,58 +945,58 @@ msgstr ""
"Ugyldig skalering av tittel «%s» (må være en av xx-small,x-small,small,"
"medium,large,x-large,xx-large)\n"
#: ../src/ui/theme-parser.c:1018 ../src/ui/theme-parser.c:1081
#: ../src/ui/theme-parser.c:1115 ../src/ui/theme-parser.c:1218
#: ../src/ui/theme-parser.c:1021 ../src/ui/theme-parser.c:1084
#: ../src/ui/theme-parser.c:1118 ../src/ui/theme-parser.c:1221
#, c-format
msgid "<%s> name \"%s\" used a second time"
msgstr "<%s> navn «%s» brukt på nytt"
#: ../src/ui/theme-parser.c:1030 ../src/ui/theme-parser.c:1127
#: ../src/ui/theme-parser.c:1230
#: ../src/ui/theme-parser.c:1033 ../src/ui/theme-parser.c:1130
#: ../src/ui/theme-parser.c:1233
#, c-format
msgid "<%s> parent \"%s\" has not been defined"
msgstr "<%s> opphav «%s» er ikke definert"
#: ../src/ui/theme-parser.c:1140
#: ../src/ui/theme-parser.c:1143
#, c-format
msgid "<%s> geometry \"%s\" has not been defined"
msgstr "<%s> geometri «%s» er ikke definert"
#: ../src/ui/theme-parser.c:1153
#: ../src/ui/theme-parser.c:1156
#, c-format
msgid "<%s> must specify either a geometry or a parent that has a geometry"
msgstr "<%s> må spesifisere enten en geometri eller et opphav som har geometri"
#: ../src/ui/theme-parser.c:1195
#: ../src/ui/theme-parser.c:1198
msgid "You must specify a background for an alpha value to be meaningful"
msgstr "Du må oppgi en bakgrunn for at en alpha-verdi skal ha mening"
#: ../src/ui/theme-parser.c:1263
#: ../src/ui/theme-parser.c:1266
#, c-format
msgid "Unknown type \"%s\" on <%s> element"
msgstr "Ukjent type «%s» på <%s>-element"
#: ../src/ui/theme-parser.c:1274
#: ../src/ui/theme-parser.c:1277
#, c-format
msgid "Unknown style_set \"%s\" on <%s> element"
msgstr "Ukjent style_set «%s» på <%s>-element"
#: ../src/ui/theme-parser.c:1282
#: ../src/ui/theme-parser.c:1285
#, c-format
msgid "Window type \"%s\" has already been assigned a style set"
msgstr "Vindutype «%s» er allerede tildelt et stilsett"
#: ../src/ui/theme-parser.c:1312 ../src/ui/theme-parser.c:1376
#: ../src/ui/theme-parser.c:1602 ../src/ui/theme-parser.c:2821
#: ../src/ui/theme-parser.c:2867 ../src/ui/theme-parser.c:3017
#: ../src/ui/theme-parser.c:3253 ../src/ui/theme-parser.c:3291
#: ../src/ui/theme-parser.c:3329 ../src/ui/theme-parser.c:3367
#: ../src/ui/theme-parser.c:1315 ../src/ui/theme-parser.c:1379
#: ../src/ui/theme-parser.c:1605 ../src/ui/theme-parser.c:2840
#: ../src/ui/theme-parser.c:2886 ../src/ui/theme-parser.c:3036
#: ../src/ui/theme-parser.c:3272 ../src/ui/theme-parser.c:3310
#: ../src/ui/theme-parser.c:3348 ../src/ui/theme-parser.c:3386
#, c-format
msgid "Element <%s> is not allowed below <%s>"
msgstr "Element <%s> er ikke tillatt under <%s>"
#: ../src/ui/theme-parser.c:1426 ../src/ui/theme-parser.c:1440
#: ../src/ui/theme-parser.c:1485
#: ../src/ui/theme-parser.c:1429 ../src/ui/theme-parser.c:1443
#: ../src/ui/theme-parser.c:1488
msgid ""
"Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" "
"for buttons"
@@ -1004,123 +1004,123 @@ msgstr ""
"Kan ikke spesifisere både «button_width»/«button_height» og «aspect_ratio» "
"for knapper"
#: ../src/ui/theme-parser.c:1449
#: ../src/ui/theme-parser.c:1452
#, c-format
msgid "Distance \"%s\" is unknown"
msgstr "Avstand «%s» er ukjent"
#: ../src/ui/theme-parser.c:1494
#: ../src/ui/theme-parser.c:1497
#, c-format
msgid "Aspect ratio \"%s\" is unknown"
msgstr "Aspektrate «%s» er ukjent"
#: ../src/ui/theme-parser.c:1556
#: ../src/ui/theme-parser.c:1559
#, c-format
msgid "Border \"%s\" is unknown"
msgstr "Grense «%s» er ukjent"
#: ../src/ui/theme-parser.c:1867
#: ../src/ui/theme-parser.c:1870
#, c-format
msgid "No \"start_angle\" or \"from\" attribute on element <%s>"
msgstr "Ingen «start_angle» eller «from»-attributt på element <%s>"
#: ../src/ui/theme-parser.c:1874
#: ../src/ui/theme-parser.c:1877
#, c-format
msgid "No \"extent_angle\" or \"to\" attribute on element <%s>"
msgstr "Ingen «extent_angle» eller «to»-attributt <%s>-element"
#: ../src/ui/theme-parser.c:2114
#: ../src/ui/theme-parser.c:2117
#, c-format
msgid "Did not understand value \"%s\" for type of gradient"
msgstr "Forsto ikke verdi «%s» for gradienttype"
#: ../src/ui/theme-parser.c:2189 ../src/ui/theme-parser.c:2551
#: ../src/ui/theme-parser.c:2195 ../src/ui/theme-parser.c:2570
#, c-format
msgid "Did not understand fill type \"%s\" for <%s> element"
msgstr "Forsto ikke fyll-type «%s» for <%s>-element"
#: ../src/ui/theme-parser.c:2343 ../src/ui/theme-parser.c:2426
#: ../src/ui/theme-parser.c:2489
#: ../src/ui/theme-parser.c:2362 ../src/ui/theme-parser.c:2445
#: ../src/ui/theme-parser.c:2508
#, c-format
msgid "Did not understand state \"%s\" for <%s> element"
msgstr "Forsto ikke tilstand «%s» for element <%s>"
#: ../src/ui/theme-parser.c:2353 ../src/ui/theme-parser.c:2436
#: ../src/ui/theme-parser.c:2372 ../src/ui/theme-parser.c:2455
#, c-format
msgid "Did not understand shadow \"%s\" for <%s> element"
msgstr "Forsto ikke skygge «%s» for element <%s>"
#: ../src/ui/theme-parser.c:2363
#: ../src/ui/theme-parser.c:2382
#, c-format
msgid "Did not understand arrow \"%s\" for <%s> element"
msgstr "Forsto ikke pil «%s» for element <%s>"
#: ../src/ui/theme-parser.c:2677 ../src/ui/theme-parser.c:2773
#: ../src/ui/theme-parser.c:2696 ../src/ui/theme-parser.c:2792
#, c-format
msgid "No <draw_ops> called \"%s\" has been defined"
msgstr "Ingen <draw_ops> kalt «%s» er definert"
#: ../src/ui/theme-parser.c:2689 ../src/ui/theme-parser.c:2785
#: ../src/ui/theme-parser.c:2708 ../src/ui/theme-parser.c:2804
#, c-format
msgid "Including draw_ops \"%s\" here would create a circular reference"
msgstr "Hvis du tar med draw_ops «%s» her vil dette lage en sirkulær referanse"
#: ../src/ui/theme-parser.c:2900
#: ../src/ui/theme-parser.c:2919
#, c-format
msgid "Unknown position \"%s\" for frame piece"
msgstr "Ukjent posisjon «%s» for rammesdel"
#: ../src/ui/theme-parser.c:2908
#: ../src/ui/theme-parser.c:2927
#, c-format
msgid "Frame style already has a piece at position %s"
msgstr "Rammestil har allerede en del i posisjon %s"
#: ../src/ui/theme-parser.c:2925 ../src/ui/theme-parser.c:3002
#: ../src/ui/theme-parser.c:2944 ../src/ui/theme-parser.c:3021
#, c-format
msgid "No <draw_ops> with the name \"%s\" has been defined"
msgstr "Ingen <draw_ops> med navn «%s» er definert"
#: ../src/ui/theme-parser.c:2955
#: ../src/ui/theme-parser.c:2974
#, c-format
msgid "Unknown function \"%s\" for button"
msgstr "Ukjent funksjon «%s» for knapp"
#: ../src/ui/theme-parser.c:2965
#: ../src/ui/theme-parser.c:2984
#, c-format
msgid "Button function \"%s\" does not exist in this version (%d, need %d)"
msgstr "Knappefunksjon «%s» eksisterer ikke i denne versjonen (%d, trenger %d)"
#: ../src/ui/theme-parser.c:2977
#: ../src/ui/theme-parser.c:2996
#, c-format
msgid "Unknown state \"%s\" for button"
msgstr "Ukjent tilstand «%s» for knapp"
#: ../src/ui/theme-parser.c:2985
#: ../src/ui/theme-parser.c:3004
#, c-format
msgid "Frame style already has a button for function %s state %s"
msgstr "Rammestil har allerede en knapp for funksjon %s tilstand %s"
#: ../src/ui/theme-parser.c:3056
#: ../src/ui/theme-parser.c:3075
#, c-format
msgid "\"%s\" is not a valid value for focus attribute"
msgstr "«%s» er ikke en gyldig verdi for fokusattributt"
#: ../src/ui/theme-parser.c:3065
#: ../src/ui/theme-parser.c:3084
#, c-format
msgid "\"%s\" is not a valid value for state attribute"
msgstr "«%s» er ikke en gyldig verdi for tilstandsattributt"
#: ../src/ui/theme-parser.c:3075
#: ../src/ui/theme-parser.c:3094
#, c-format
msgid "A style called \"%s\" has not been defined"
msgstr "En stil med navn «%s» er ikke definert"
#: ../src/ui/theme-parser.c:3096 ../src/ui/theme-parser.c:3119
#: ../src/ui/theme-parser.c:3115 ../src/ui/theme-parser.c:3138
#, c-format
msgid "\"%s\" is not a valid value for resize attribute"
msgstr "«%s» er ikke en gyldig verdi for attributt for endring av størrelse"
#: ../src/ui/theme-parser.c:3130
#: ../src/ui/theme-parser.c:3149
#, c-format
msgid ""
"Should not have \"resize\" attribute on <%s> element for maximized/shaded "
@@ -1129,27 +1129,27 @@ msgstr ""
"Skal ikke være noen «resize»-attributt på <%s>-element for maksimert/"
"skyggelagt tilstand"
#: ../src/ui/theme-parser.c:3144
#: ../src/ui/theme-parser.c:3163
#, c-format
msgid ""
"Should not have \"resize\" attribute on <%s> element for maximized states"
msgstr ""
"Skal ikke være noen «resize»-attributt på <%s>-element for maksimert tilstand"
#: ../src/ui/theme-parser.c:3158 ../src/ui/theme-parser.c:3202
#: ../src/ui/theme-parser.c:3177 ../src/ui/theme-parser.c:3221
#, c-format
msgid "Style has already been specified for state %s resize %s focus %s"
msgstr ""
"Stil er allerede spesifisert for tilstand %s størrelsesendring %s fokus %s"
#: ../src/ui/theme-parser.c:3169 ../src/ui/theme-parser.c:3180
#: ../src/ui/theme-parser.c:3191 ../src/ui/theme-parser.c:3213
#: ../src/ui/theme-parser.c:3224 ../src/ui/theme-parser.c:3235
#: ../src/ui/theme-parser.c:3188 ../src/ui/theme-parser.c:3199
#: ../src/ui/theme-parser.c:3210 ../src/ui/theme-parser.c:3232
#: ../src/ui/theme-parser.c:3243 ../src/ui/theme-parser.c:3254
#, c-format
msgid "Style has already been specified for state %s focus %s"
msgstr "Stil er allerede spesifisert for tilstand %s fokus %s"
#: ../src/ui/theme-parser.c:3274
#: ../src/ui/theme-parser.c:3293
msgid ""
"Can't have a two draw_ops for a <piece> element (theme specified a draw_ops "
"attribute and also a <draw_ops> element, or specified two elements)"
@@ -1158,7 +1158,7 @@ msgstr ""
"draw_ops-attributt i tillegg til et <draw_ops>-element, eller så "
"spesifiserte det to elementer)"
#: ../src/ui/theme-parser.c:3312
#: ../src/ui/theme-parser.c:3331
msgid ""
"Can't have a two draw_ops for a <button> element (theme specified a draw_ops "
"attribute and also a <draw_ops> element, or specified two elements)"
@@ -1167,7 +1167,7 @@ msgstr ""
"draw_ops-attributt i tillegg til et <draw_ops>-element, eller det "
"spesifiserte to elementer)"
#: ../src/ui/theme-parser.c:3350
#: ../src/ui/theme-parser.c:3369
msgid ""
"Can't have a two draw_ops for a <menu_icon> element (theme specified a "
"draw_ops attribute and also a <draw_ops> element, or specified two elements)"
@@ -1176,12 +1176,12 @@ msgstr ""
"draw_ops-attributt i tillegg til et <draw_ops>-element, eller det "
"spesifiserte to elementer)"
#: ../src/ui/theme-parser.c:3414
#: ../src/ui/theme-parser.c:3433
#, c-format
msgid "Bad version specification '%s'"
msgstr "Ugyldig versjonspesifikasjon «%s»"
#: ../src/ui/theme-parser.c:3487
#: ../src/ui/theme-parser.c:3506
msgid ""
"\"version\" attribute cannot be used in metacity-theme-1.xml or metacity-"
"theme-2.xml"
@@ -1189,66 +1189,66 @@ msgstr ""
"«version»-attributt kan ikke brukes i metacity-theme-1.xml eller metacity-"
"theme-2.xml"
#: ../src/ui/theme-parser.c:3510
#: ../src/ui/theme-parser.c:3529
#, c-format
msgid "Theme requires version %s but latest supported theme version is %d.%d"
msgstr "Tema krever versjon %s men siste støttede temaversjon er %d.%d"
#: ../src/ui/theme-parser.c:3542
#: ../src/ui/theme-parser.c:3561
#, c-format
msgid "Outermost element in theme must be <metacity_theme> not <%s>"
msgstr "Ytterste element i temaet må være <metacity_theme> ikke <%s>"
#: ../src/ui/theme-parser.c:3562
#: ../src/ui/theme-parser.c:3581
#, c-format
msgid ""
"Element <%s> is not allowed inside a name/author/date/description element"
msgstr ""
"Element <%s> er ikke tillatt inne i et name/author/date/description element"
#: ../src/ui/theme-parser.c:3567
#: ../src/ui/theme-parser.c:3586
#, c-format
msgid "Element <%s> is not allowed inside a <constant> element"
msgstr "Element <%s> er ikke tillatt inne i et <constand> element"
#: ../src/ui/theme-parser.c:3579
#: ../src/ui/theme-parser.c:3598
#, c-format
msgid ""
"Element <%s> is not allowed inside a distance/border/aspect_ratio element"
msgstr "Element <%s> er ikke tillatt inne i et avstand/kant/aspektrate-element"
#: ../src/ui/theme-parser.c:3601
#: ../src/ui/theme-parser.c:3620
#, c-format
msgid "Element <%s> is not allowed inside a draw operation element"
msgstr "Element <%s> er ikke tillatt inne i et element for tegneoperasjon"
#: ../src/ui/theme-parser.c:3611 ../src/ui/theme-parser.c:3641
#: ../src/ui/theme-parser.c:3646 ../src/ui/theme-parser.c:3651
#: ../src/ui/theme-parser.c:3630 ../src/ui/theme-parser.c:3660
#: ../src/ui/theme-parser.c:3665 ../src/ui/theme-parser.c:3670
#, c-format
msgid "Element <%s> is not allowed inside a <%s> element"
msgstr "Element <%s> er ikke tillatt inne i et <%s>-element"
#: ../src/ui/theme-parser.c:3879
#: ../src/ui/theme-parser.c:3898
msgid "No draw_ops provided for frame piece"
msgstr "Ingen draw_ops tilbys for rammedelen"
#: ../src/ui/theme-parser.c:3894
#: ../src/ui/theme-parser.c:3913
msgid "No draw_ops provided for button"
msgstr "Ingen draw_ops tilbys for knappen"
#: ../src/ui/theme-parser.c:3948
#: ../src/ui/theme-parser.c:3967
#, c-format
msgid "No text is allowed inside element <%s>"
msgstr "Ingen tekst er tillatt inne i element <%s>"
#: ../src/ui/theme-parser.c:4006 ../src/ui/theme-parser.c:4018
#: ../src/ui/theme-parser.c:4030 ../src/ui/theme-parser.c:4042
#: ../src/ui/theme-parser.c:4054
#: ../src/ui/theme-parser.c:4025 ../src/ui/theme-parser.c:4037
#: ../src/ui/theme-parser.c:4049 ../src/ui/theme-parser.c:4061
#: ../src/ui/theme-parser.c:4073
#, c-format
msgid "<%s> specified twice for this theme"
msgstr "<%s> spesifisert to ganger for dette temaet"
#: ../src/ui/theme-parser.c:4316
#: ../src/ui/theme-parser.c:4335
#, c-format
msgid "Failed to find a valid file for theme %s\n"
msgstr "Fant ikke en gyldig fil for tema %s\n"
@@ -1261,7 +1261,10 @@ msgstr ""
"Disse vinduene støtter ikke &quot;lagre aktiv konfigurasjon&quot;og vil "
"måtte startes på nytt manuelt neste gang du logger inn."
#: ../src/x11/window-props.c:558
#: ../src/x11/window-props.c:515
#, c-format
msgid "%s (on %s)"
msgstr "%s (på %s)"
#~ msgid "background texture could not be created from file"
#~ msgstr "bakgrunnstekstur kunne ikke lages fra fil"

3564
po/oc.po

File diff suppressed because it is too large Load Diff

1430
po/pt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1277
po/ru.po

File diff suppressed because it is too large Load Diff

1430
po/sk.po

File diff suppressed because it is too large Load Diff

762
po/sl.po
View File

@@ -4,15 +4,15 @@
#
# Andraž Tori <andraz.tori1@guest.arnes.si>, 2000.
# Matjaž Horvat <m@owca.info>, 2006.
# Matej Urbančič <mateju@svn.gnome.org>, 2007-2015.
# Matej Urbančič <mateju@svn.gnome.org>, 2007-2014.
#
msgid ""
msgstr ""
"Project-Id-Version: mutter master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2015-02-15 11:07+0000\n"
"PO-Revision-Date: 2015-02-15 20:57+0100\n"
"POT-Creation-Date: 2014-12-26 10:55+0000\n"
"PO-Revision-Date: 2014-12-26 19:24+0100\n"
"Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n"
"Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n"
"Language: sl_SI\n"
@@ -435,22 +435,22 @@ msgstr "Preklopi na VT 6"
msgid "Switch to VT 7"
msgstr "Preklopi na VT 7"
#: ../src/backends/meta-monitor-manager.c:364
#: ../src/backends/meta-monitor-manager.c:375
msgid "Built-in display"
msgstr "Vgrajen zaslon"
#: ../src/backends/meta-monitor-manager.c:391
#: ../src/backends/meta-monitor-manager.c:400
msgid "Unknown"
msgstr "Neznano"
#: ../src/backends/meta-monitor-manager.c:393
#: ../src/backends/meta-monitor-manager.c:402
msgid "Unknown Display"
msgstr "Neznan zaslon"
#. TRANSLATORS: this is a monitor vendor name, followed by a
#. * size in inches, like 'Dell 15"'
#.
#: ../src/backends/meta-monitor-manager.c:401
#: ../src/backends/meta-monitor-manager.c:410
#, c-format
msgid "%s %s"
msgstr "%s %s"
@@ -494,7 +494,7 @@ msgstr "_Počakaj"
msgid "_Force Quit"
msgstr "_Vsili konec"
#: ../src/core/display.c:562
#: ../src/core/display.c:550
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Ni mogoče odpreti zaslona '%s' okenskega sistema X\n"
@@ -531,6 +531,19 @@ msgstr "Zaženi izbirnik wayland"
msgid "Run as a full display server, rather than nested"
msgstr "Zaženi kot polni strežnik zaslona in ne vstavljeno"
#: ../src/core/main.c:451
#, c-format
msgid "Failed to scan themes directory: %s\n"
msgstr "Ni mogoče preiskati mape tem: %s\n"
#: ../src/core/main.c:467
#, c-format
msgid ""
"Could not find a theme! Be sure %s exists and contains the usual themes.\n"
msgstr ""
"Ni mogoče najti teme! Prepričajte se, da %s obstaja in vsebuje običajni "
"zapis teme.\n"
#: ../src/core/mutter.c:39
#, c-format
msgid ""
@@ -555,30 +568,717 @@ msgid "Mutter plugin to use"
msgstr "Vstavek Mutter za uporabo"
# G:1 K:0 O:0
#: ../src/core/prefs.c:2004
#: ../src/core/prefs.c:2064
#, c-format
msgid "Workspace %d"
msgstr "Delovna površina %d"
#: ../src/core/screen.c:525
#, c-format
msgid ""
"Display \"%s\" already has a window manager; try using the --replace option "
"to replace the current window manager."
msgstr ""
"Zaslon \"%s\" že ima določen upravljalnik oken; poskušajte uporabiti možnost "
"--replace za zamenjavo trenutnega upravljalnika zaslona."
#: ../src/core/screen.c:607
#: ../src/core/screen.c:534
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "Zaslon %d na prikazu '%s' ni veljaven\n"
#: ../src/core/screen.c:550
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
"replace option to replace the current window manager.\n"
msgstr ""
"Zaslon %d na prikazu \"%s\" je že upravljan z upravljalnikom oken; "
"poskušajte uporabiti možnost --replace za zamenjavo trenutnega.\n"
#: ../src/core/screen.c:643
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr "Zaslon %d na prikazu \"%s\" je že upravljan z upravljalnikom oken\n"
#: ../src/core/util.c:118
msgid "Mutter was compiled without support for verbose mode\n"
msgstr ""
"Program Mutter je kodno preveden brez podpore za podrobni način izpisovanja\n"
#. Translators: This represents the size of a window. The first number is
#. * the width of the window and the second is the height.
#.
#: ../src/ui/resizepopup.c:134
#, c-format
msgid "%d x %d"
msgstr "%d x %d"
#: ../src/ui/theme.c:233
msgid "top"
msgstr "zgoraj"
# G:12 K:5 O:0
#: ../src/ui/theme.c:235
msgid "bottom"
msgstr "spodaj"
# G:10 K:4 O:0
#: ../src/ui/theme.c:237
msgid "left"
msgstr "levo"
# G:1 K:0 O:0
#: ../src/ui/theme.c:239
msgid "right"
msgstr "desno"
# G:1 K:0 O:0
#: ../src/ui/theme.c:267
#, c-format
msgid "frame geometry does not specify \"%s\" dimension"
msgstr "geometrija okvirja ne navaja dimenzije \"%s\""
#: ../src/ui/theme.c:286
#, c-format
msgid "frame geometry does not specify dimension \"%s\" for border \"%s\""
msgstr "geometrija okvirja ne navaja dimenzije \"%s\" za rob \"%s\""
#: ../src/ui/theme.c:323
#, c-format
msgid "Button aspect ratio %g is not reasonable"
msgstr "Vrednost razmerja gumba %g ni smiselna"
#: ../src/ui/theme.c:335
#, c-format
msgid "Frame geometry does not specify size of buttons"
msgstr "Geometrija okvirja ne navaja velikosti gumbov"
#: ../src/ui/theme.c:1061
#, c-format
msgid "Gradients should have at least two colors"
msgstr "Prelivi bi morali imeti vsaj dve barvi"
#: ../src/ui/theme.c:1211
#, c-format
msgid ""
"GTK custom color specification must have color name and fallback in "
"parentheses, e.g. gtk:custom(foo,bar); could not parse \"%s\""
msgstr ""
"Navedba barve GTK mora biti opredeljena z imenom barve in v navednicah "
"povrnjeno barvo , npr. gtk:izbirno(ime_barve,povrnjena_barva); ni mogoče "
"razčleniti \"%s\""
#: ../src/ui/theme.c:1227
#, c-format
msgid ""
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
"_ are valid"
msgstr ""
"Neveljaven znak '%c' v imenu barve gtk:izbirno; dovoljeni znaki so le A-Za-"
"z0-9-_."
#: ../src/ui/theme.c:1241
#, c-format
msgid ""
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
"fit the format"
msgstr ""
"Gtk:zapis po meri \"gtk:izbirno(ime_barve,povrnjena_barva)\", \"%s\" ne "
"ustreza pravilni obliki."
#: ../src/ui/theme.c:1286
#, c-format
msgid ""
"GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] "
"where NORMAL is the state; could not parse \"%s\""
msgstr ""
"Navedba barve GTK mora vsebovati stanje v oglatih oklepajih, npr. gtk:"
"fg[NORMAL], kjer je NORMAL stanje; ni mogoče razčleniti \"%s\""
#: ../src/ui/theme.c:1300
#, c-format
msgid ""
"GTK color specification must have a close bracket after the state, e.g. gtk:"
"fg[NORMAL] where NORMAL is the state; could not parse \"%s\""
msgstr ""
"Navedbi barve GTK manjka oglati zaklepaj za stanjem, npr. gtk:fg[NORMAL], "
"kjer je NORMAL stanje; ni mogoče razčleniti \"%s\""
#: ../src/ui/theme.c:1311
#, c-format
msgid "Did not understand state \"%s\" in color specification"
msgstr "Ni mogoče razumeti stanja \"%s\" v navedbi barve "
#: ../src/ui/theme.c:1324
#, c-format
msgid "Did not understand color component \"%s\" in color specification"
msgstr "Ni mogoče razumeti barvne komponente \"%s\" v navedbi barve"
#: ../src/ui/theme.c:1352
#, c-format
msgid ""
"Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the "
"format"
msgstr ""
"Oblika zapisa preliva je \"blend/bg_color/fg_color/alpha\", \"%s\" ne "
"ustreza pravilni obliki"
#: ../src/ui/theme.c:1363
#, c-format
msgid "Could not parse alpha value \"%s\" in blended color"
msgstr "V prelivni barvi ni mogoče razčleniti vrednosti alfa \"%s\""
#: ../src/ui/theme.c:1373
#, c-format
msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0"
msgstr "V prelivni barvi alfa vrednost \"%s\" ni med 0.0 in 1.0"
#: ../src/ui/theme.c:1419
#, c-format
msgid ""
"Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"
msgstr ""
"Oblika zapisa barve senčenja je \"shade/base_color/factor\", \"%s\" ne "
"ustreza pravilni obliki."
#: ../src/ui/theme.c:1430
#, c-format
msgid "Could not parse shade factor \"%s\" in shaded color"
msgstr "Ni mogoče razčleniti vrednosti senčenja \"%s\" v senčeni barvi"
#: ../src/ui/theme.c:1440
#, c-format
msgid "Shade factor \"%s\" in shaded color is negative"
msgstr "V senčeni barvi je vrednost senčenja \"%s\" negativna"
#: ../src/ui/theme.c:1469
#, c-format
msgid "Could not parse color \"%s\""
msgstr "Ni mogoče razčleniti barve \"%s\""
#: ../src/ui/theme.c:1778
#, c-format
msgid "Coordinate expression contains character '%s' which is not allowed"
msgstr "Izraz koordinat vsebuje znak '%s', ki pa ni dovoljen"
#: ../src/ui/theme.c:1805
#, c-format
msgid ""
"Coordinate expression contains floating point number '%s' which could not be "
"parsed"
msgstr ""
"Izraz koordinat vsebuje številko s plavajočo vejico '%s', ki je ni mogoče "
"razčleniti"
#: ../src/ui/theme.c:1819
#, c-format
msgid "Coordinate expression contains integer '%s' which could not be parsed"
msgstr "Izraz koordinat vsebuje celo število '%s', ki ga ni mogoče razčleniti"
#: ../src/ui/theme.c:1940
#, c-format
msgid ""
"Coordinate expression contained unknown operator at the start of this text: "
"\"%s\""
msgstr "Izraz koordinat vsebuje neznan operator na začetku besedila: \"%s\""
#: ../src/ui/theme.c:1997
#, c-format
msgid "Coordinate expression was empty or not understood"
msgstr "Izraz koordinat je prazen ali pa ni v razumljivem zapisu"
#: ../src/ui/theme.c:2110 ../src/ui/theme.c:2120 ../src/ui/theme.c:2154
#, c-format
msgid "Coordinate expression results in division by zero"
msgstr "Izraz koordinat povzroči deljenje z vrednostjo nič"
#: ../src/ui/theme.c:2162
#, c-format
msgid ""
"Coordinate expression tries to use mod operator on a floating-point number"
msgstr ""
"Izraz koordinat poskuša uporabiti operator mod ali številko s plavajočo "
"vejico"
#: ../src/ui/theme.c:2218
#, c-format
msgid ""
"Coordinate expression has an operator \"%s\" where an operand was expected"
msgstr "Izraz koordinat vsebuje operator \"%s\", kjer je pričakovan operand"
#: ../src/ui/theme.c:2227
#, c-format
msgid "Coordinate expression had an operand where an operator was expected"
msgstr "Izraz koordinat vsebuje operand kjer je pričakovan operator"
#: ../src/ui/theme.c:2235
#, c-format
msgid "Coordinate expression ended with an operator instead of an operand"
msgstr "Izraz koordinat se konča z operatorjem namesto z operandom"
#: ../src/ui/theme.c:2245
#, c-format
msgid ""
"Coordinate expression has operator \"%c\" following operator \"%c\" with no "
"operand in between"
msgstr ""
"Izraz koordinat vsebuje operator \"%c\", ki sledi operatorju \"%c\", brez "
"vmesnega operanda"
#: ../src/ui/theme.c:2396 ../src/ui/theme.c:2441
#, c-format
msgid "Coordinate expression had unknown variable or constant \"%s\""
msgstr "Izraz koordinat vsebuje neznano spremenljivko ali konstanto \"%s\""
#: ../src/ui/theme.c:2495
#, c-format
msgid "Coordinate expression parser overflowed its buffer."
msgstr "Razčlenjevalnik izrazov koordinat je preplavil medpomnilnik."
#: ../src/ui/theme.c:2524
#, c-format
msgid "Coordinate expression had a close parenthesis with no open parenthesis"
msgstr "Izraz koordinat vsebuje zaklepaj, ne pa tudi uklepaja"
#: ../src/ui/theme.c:2588
#, c-format
msgid "Coordinate expression had an open parenthesis with no close parenthesis"
msgstr "Izraz koordinat vsebuje uklepaj, vendar je brez zaklepaja"
#: ../src/ui/theme.c:2599
#, c-format
msgid "Coordinate expression doesn't seem to have any operators or operands"
msgstr "Videti je, da izraz koordinat ne vsebuje operatorjev ali operandov"
#: ../src/ui/theme.c:2812 ../src/ui/theme.c:2832 ../src/ui/theme.c:2852
#, c-format
msgid "Theme contained an expression that resulted in an error: %s\n"
msgstr "Tema vsebuje izraz, ki povzroča napako: %s\n"
#: ../src/ui/theme.c:4455
#, c-format
msgid ""
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be "
"specified for this frame style"
msgstr ""
"Za ta slog okvirja mora biti naveden <button function=\"%s\" state=\"%s\" "
"draw_ops=\"karkoli\"/>"
#: ../src/ui/theme.c:4970 ../src/ui/theme.c:4995
#, c-format
msgid ""
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
msgstr ""
"Manjka <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"karkoli\"/>"
#: ../src/ui/theme.c:5041
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr "Napaka med nalaganjem teme \"%s\": %s\n"
#: ../src/ui/theme.c:5177 ../src/ui/theme.c:5184 ../src/ui/theme.c:5191
#: ../src/ui/theme.c:5198 ../src/ui/theme.c:5205
#, c-format
msgid "No <%s> set for theme \"%s\""
msgstr "Ni nastavljena vrednost <%s> za temo \"%s\""
#: ../src/ui/theme.c:5213
#, c-format
msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
"type=\"%s\" style_set=\"whatever\"/> element"
msgstr ""
"Ni določenega sloga okvirja okna vrste \"%s\" v temi \"%s\". Dodajte predmet "
"<window type=\"%s\" style_set=\"whatever\"/>"
#: ../src/ui/theme.c:5620 ../src/ui/theme.c:5682 ../src/ui/theme.c:5745
#, c-format
msgid ""
"User-defined constants must begin with a capital letter; \"%s\" does not"
msgstr ""
"Uporabniško določene konstante se morajo začeti z veliko črko; vrednost \"%s"
"\" se ne"
#: ../src/ui/theme.c:5628 ../src/ui/theme.c:5690 ../src/ui/theme.c:5753
#, c-format
msgid "Constant \"%s\" has already been defined"
msgstr "Konstanta \"%s\" je že določena"
#. Translators: This means that an attribute which should have been found
#. * on an XML element was not in fact found.
#.
#: ../src/ui/theme-parser.c:234
#, c-format
msgid "No \"%s\" attribute on element <%s>"
msgstr "Ni atributa \"%s\" za predmet <%s>"
#: ../src/ui/theme-parser.c:263 ../src/ui/theme-parser.c:281
#, c-format
msgid "Line %d character %d: %s"
msgstr "Vrstica %d, znak %d: %s"
#: ../src/ui/theme-parser.c:481
#, c-format
msgid "Attribute \"%s\" repeated twice on the same <%s> element"
msgstr "Atribut \"%s\" je bil v enakem predmetu <%s> ponovljen dvakrat"
#: ../src/ui/theme-parser.c:505 ../src/ui/theme-parser.c:554
#, c-format
msgid "Attribute \"%s\" is invalid on <%s> element in this context"
msgstr "Atribut \"%s\" je na ta način v predmetu <%s> neveljaven"
#: ../src/ui/theme-parser.c:596
#, c-format
msgid "Could not parse \"%s\" as an integer"
msgstr "Ni mogoče razčleniti \"%s\" kot celoštevilčne vrednosti"
#: ../src/ui/theme-parser.c:605 ../src/ui/theme-parser.c:660
#, c-format
msgid "Did not understand trailing characters \"%s\" in string \"%s\""
msgstr "Ni mogoče razumeti končnih znakov \"%s\" v nizu \"%s\""
#: ../src/ui/theme-parser.c:615
#, c-format
msgid "Integer %ld must be positive"
msgstr "Celoštevilska vrednost %ld mora biti pozitivna"
#: ../src/ui/theme-parser.c:623
#, c-format
msgid "Integer %ld is too large, current max is %d"
msgstr "Celoštevilska vrednost %ld je prevelika; trenutna omejitev je %d"
#: ../src/ui/theme-parser.c:651 ../src/ui/theme-parser.c:767
#, c-format
msgid "Could not parse \"%s\" as a floating point number"
msgstr "Ni mogoče razčleniti \"%s\" kot števila s plavajočo vejico"
#: ../src/ui/theme-parser.c:682 ../src/ui/theme-parser.c:710
#, c-format
msgid "Boolean values must be \"true\" or \"false\" not \"%s\""
msgstr "Logične vrednosti morajo biti \"prav\" ali \"napak\" in ne \"%s\""
#: ../src/ui/theme-parser.c:737
#, c-format
msgid "Angle must be between 0.0 and 360.0, was %g\n"
msgstr "Kot mora biti med 0.0 in 360.0, določen pa je z vrednostjo %g\n"
#: ../src/ui/theme-parser.c:800
#, c-format
msgid "Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n"
msgstr ""
"Alfa mora biti med 0.0 (nevidno) in 1.0 (popolnoma vidno), vrednost pa je "
"določena na %g\n"
#: ../src/ui/theme-parser.c:865
#, c-format
msgid ""
"Invalid title scale \"%s\" (must be one of xx-small,x-small,small,medium,"
"large,x-large,xx-large)\n"
msgstr ""
"Neveljavna velikost naziva \"%s\" (mora biti eno od xx-small,x-small,small,"
"medium,large,x-large,xx-large)\n"
#: ../src/ui/theme-parser.c:1021 ../src/ui/theme-parser.c:1084
#: ../src/ui/theme-parser.c:1118 ../src/ui/theme-parser.c:1221
#, c-format
msgid "<%s> name \"%s\" used a second time"
msgstr "ime <%s> \"%s\" je uporabljeno drugič"
#: ../src/ui/theme-parser.c:1033 ../src/ui/theme-parser.c:1130
#: ../src/ui/theme-parser.c:1233
#, c-format
msgid "<%s> parent \"%s\" has not been defined"
msgstr "nadrejeni predmet <%s> \"%s\" ni naveden"
#: ../src/ui/theme-parser.c:1143
#, c-format
msgid "<%s> geometry \"%s\" has not been defined"
msgstr "geometrija <%s> \"%s\" ni navedena"
#: ../src/ui/theme-parser.c:1156
#, c-format
msgid "<%s> must specify either a geometry or a parent that has a geometry"
msgstr ""
"<%s> mora imeti navedeno ali geometrijo ali nadrejeni predmet z določeno "
"geometrijo"
#: ../src/ui/theme-parser.c:1198
msgid "You must specify a background for an alpha value to be meaningful"
msgstr "Določiti je treba ozadje, v kolikor naj ima alfa vrednost pomen."
#: ../src/ui/theme-parser.c:1266
#, c-format
msgid "Unknown type \"%s\" on <%s> element"
msgstr "Neznana vrsta \"%s\" v predmetu <%s>"
#: ../src/ui/theme-parser.c:1277
#, c-format
msgid "Unknown style_set \"%s\" on <%s> element"
msgstr "Neznan style_set \"%s\" v predmetu <%s>"
#: ../src/ui/theme-parser.c:1285
#, c-format
msgid "Window type \"%s\" has already been assigned a style set"
msgstr "Vrsti okna \"%s\" je slog že določen"
#: ../src/ui/theme-parser.c:1315 ../src/ui/theme-parser.c:1379
#: ../src/ui/theme-parser.c:1605 ../src/ui/theme-parser.c:2840
#: ../src/ui/theme-parser.c:2886 ../src/ui/theme-parser.c:3036
#: ../src/ui/theme-parser.c:3272 ../src/ui/theme-parser.c:3310
#: ../src/ui/theme-parser.c:3348 ../src/ui/theme-parser.c:3386
#, c-format
msgid "Element <%s> is not allowed below <%s>"
msgstr "Predmet <%s> ni dovoljen pod <%s>"
#: ../src/ui/theme-parser.c:1429 ../src/ui/theme-parser.c:1443
#: ../src/ui/theme-parser.c:1488
msgid ""
"Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" "
"for buttons"
msgstr ""
"Ni mogoče navesti tako vrednosti \"button_width\"/\"button_height\", kot "
"vrednosti razmerja\"aspect_ratio\" gumba"
#: ../src/ui/theme-parser.c:1452
#, c-format
msgid "Distance \"%s\" is unknown"
msgstr "Razdalja \"%s\" ni znana"
#: ../src/ui/theme-parser.c:1497
#, c-format
msgid "Aspect ratio \"%s\" is unknown"
msgstr "Razmerje \"%s\" ni znano"
#: ../src/ui/theme-parser.c:1559
#, c-format
msgid "Border \"%s\" is unknown"
msgstr "Rob \"%s\" ni znane vrste"
#: ../src/ui/theme-parser.c:1870
#, c-format
msgid "No \"start_angle\" or \"from\" attribute on element <%s>"
msgstr "Predmet <%s> nima določenega atributa \"start_angle\" ali \"from\""
#: ../src/ui/theme-parser.c:1877
#, c-format
msgid "No \"extent_angle\" or \"to\" attribute on element <%s>"
msgstr "Predmet <%s> nima določenega atributa \"extent_angle\" ali \"to\""
#: ../src/ui/theme-parser.c:2117
#, c-format
msgid "Did not understand value \"%s\" for type of gradient"
msgstr "Ni mogoče razumeti vrednosti za vrsto preliva \"%s\""
#: ../src/ui/theme-parser.c:2195 ../src/ui/theme-parser.c:2570
#, c-format
msgid "Did not understand fill type \"%s\" for <%s> element"
msgstr "Neprepoznana vrsta polnjenja \"%s\" za predmet <%s>"
#: ../src/ui/theme-parser.c:2362 ../src/ui/theme-parser.c:2445
#: ../src/ui/theme-parser.c:2508
#, c-format
msgid "Did not understand state \"%s\" for <%s> element"
msgstr "Ni mogoče razumeti stanja \"%s\" za predmet <%s>"
#: ../src/ui/theme-parser.c:2372 ../src/ui/theme-parser.c:2455
#, c-format
msgid "Did not understand shadow \"%s\" for <%s> element"
msgstr "Ni mogoče razumeti senčenja \"%s\" za predmet <%s>"
#: ../src/ui/theme-parser.c:2382
#, c-format
msgid "Did not understand arrow \"%s\" for <%s> element"
msgstr "Ni mogoče razumeti puščice \"%s\" za predmet <%s>"
#: ../src/ui/theme-parser.c:2696 ../src/ui/theme-parser.c:2792
#, c-format
msgid "No <draw_ops> called \"%s\" has been defined"
msgstr "<draw_ops> imenovan \"%s\" ni naveden"
#: ../src/ui/theme-parser.c:2708 ../src/ui/theme-parser.c:2804
#, c-format
msgid "Including draw_ops \"%s\" here would create a circular reference"
msgstr "Vključevanje draw_ops \"%s\" na tem mestu ustvari krožno sklicevanje"
#: ../src/ui/theme-parser.c:2919
#, c-format
msgid "Unknown position \"%s\" for frame piece"
msgstr "Neznan položaj \"%s\" za del okvirja"
#: ../src/ui/theme-parser.c:2927
#, c-format
msgid "Frame style already has a piece at position %s"
msgstr "Slog okvirja že ima del na položaju %s"
#: ../src/ui/theme-parser.c:2944 ../src/ui/theme-parser.c:3021
#, c-format
msgid "No <draw_ops> with the name \"%s\" has been defined"
msgstr "Za ime \"%s\" ni navedenega <draw_ops>"
#: ../src/ui/theme-parser.c:2974
#, c-format
msgid "Unknown function \"%s\" for button"
msgstr "Neznana funkcija \"%s\" za gumb"
#: ../src/ui/theme-parser.c:2984
#, c-format
msgid "Button function \"%s\" does not exist in this version (%d, need %d)"
msgstr "Funkcija gumba \"%s\" ne obstaja v tej različici (%d, zahtevana %d)"
#: ../src/ui/theme-parser.c:2996
#, c-format
msgid "Unknown state \"%s\" for button"
msgstr "Neznano stanje \"%s\" za gumb"
#: ../src/ui/theme-parser.c:3004
#, c-format
msgid "Frame style already has a button for function %s state %s"
msgstr "Slog okvirja že ima gumb za funkcijo %s stanje %s"
#: ../src/ui/theme-parser.c:3075
#, c-format
msgid "\"%s\" is not a valid value for focus attribute"
msgstr "\"%s\" ni veljavna vrednost za atribut \"focus\""
#: ../src/ui/theme-parser.c:3084
#, c-format
msgid "\"%s\" is not a valid value for state attribute"
msgstr "\"%s\" ni veljavna vrednost za atribut \"state\""
#: ../src/ui/theme-parser.c:3094
#, c-format
msgid "A style called \"%s\" has not been defined"
msgstr "Slog imenovan \"%s\" ni določen"
#: ../src/ui/theme-parser.c:3115 ../src/ui/theme-parser.c:3138
#, c-format
msgid "\"%s\" is not a valid value for resize attribute"
msgstr "\"%s\" ni veljavna vrednost za atribut \"resize\""
#: ../src/ui/theme-parser.c:3149
#, c-format
msgid ""
"Should not have \"resize\" attribute on <%s> element for maximized/shaded "
"states"
msgstr ""
"Predmetu <%s> ni mogoče določiti atributa \"resize\" za razpeta/senčena "
"stanja"
#: ../src/ui/theme-parser.c:3163
#, c-format
msgid ""
"Should not have \"resize\" attribute on <%s> element for maximized states"
msgstr "Predmetu <%s> ni mogoče določiti atributa \"resize\" za razpeta stanja"
#: ../src/ui/theme-parser.c:3177 ../src/ui/theme-parser.c:3221
#, c-format
msgid "Style has already been specified for state %s resize %s focus %s"
msgstr "Slog za stanje %s, spremenjeno velikost %s in žarišče %s je že naveden"
#: ../src/ui/theme-parser.c:3188 ../src/ui/theme-parser.c:3199
#: ../src/ui/theme-parser.c:3210 ../src/ui/theme-parser.c:3232
#: ../src/ui/theme-parser.c:3243 ../src/ui/theme-parser.c:3254
#, c-format
msgid "Style has already been specified for state %s focus %s"
msgstr "Slog za stanje %s in žarišče %s je že naveden"
#: ../src/ui/theme-parser.c:3293
msgid ""
"Can't have a two draw_ops for a <piece> element (theme specified a draw_ops "
"attribute and also a <draw_ops> element, or specified two elements)"
msgstr ""
"Za predmet <piece> ni mogoče imeti določenih dveh vrednosti draw_ops (tema "
"je navedla atribut draw_ops in hkrati predmet <draw_ops> ali navedena dva "
"predmeta)"
#: ../src/ui/theme-parser.c:3331
msgid ""
"Can't have a two draw_ops for a <button> element (theme specified a draw_ops "
"attribute and also a <draw_ops> element, or specified two elements)"
msgstr ""
"Za predmet <button> ni mogoče imeti določenih dveh vrednosti draw_ops (tema "
"ima naveden atribut draw_ops in hkrati element <draw_ops> ali pa ima "
"navedena dva elementa)"
#: ../src/ui/theme-parser.c:3369
msgid ""
"Can't have a two draw_ops for a <menu_icon> element (theme specified a "
"draw_ops attribute and also a <draw_ops> element, or specified two elements)"
msgstr ""
"Za element <menu_icon> ni mogoče imeti dveh draw_ops (tema ima naveden "
"atribut draw_ops in hkrati predmet <draw_ops> ali pa ima navedena dva "
"predmeta)"
#: ../src/ui/theme-parser.c:3433
#, c-format
msgid "Bad version specification '%s'"
msgstr "Slabo določilo različice '%s'"
#: ../src/ui/theme-parser.c:3506
msgid ""
"\"version\" attribute cannot be used in metacity-theme-1.xml or metacity-"
"theme-2.xml"
msgstr ""
"atributa \"version\" ni mogoče uporabiti v temi metacity-theme-1.xml oziroma "
"metacity-theme-2.xml"
#: ../src/ui/theme-parser.c:3529
#, c-format
msgid "Theme requires version %s but latest supported theme version is %d.%d"
msgstr "Tema zahteva različico %s, zadnja podprta različica teme pa je %d.%d"
#: ../src/ui/theme-parser.c:3561
#, c-format
msgid "Outermost element in theme must be <metacity_theme> not <%s>"
msgstr "Najbolj zunanji predmet teme mora biti <metacity_theme> in ne <%s>"
#: ../src/ui/theme-parser.c:3581
#, c-format
msgid ""
"Element <%s> is not allowed inside a name/author/date/description element"
msgstr ""
"Predmet <%s> ni dovoljen znotraj predmetov imena, avtorja, datuma ali opisa"
#: ../src/ui/theme-parser.c:3586
#, c-format
msgid "Element <%s> is not allowed inside a <constant> element"
msgstr "Predmet <%s> ni dovoljen znotraj predmeta <constant>"
#: ../src/ui/theme-parser.c:3598
#, c-format
msgid ""
"Element <%s> is not allowed inside a distance/border/aspect_ratio element"
msgstr ""
"Predmet <%s> ni dovoljen znotraj predmetov razdalje/robov/razmerja velikosti"
#: ../src/ui/theme-parser.c:3620
#, c-format
msgid "Element <%s> is not allowed inside a draw operation element"
msgstr "Predmet <%s> ni dovoljen znotraj predmeta izrisevanja"
#: ../src/ui/theme-parser.c:3630 ../src/ui/theme-parser.c:3660
#: ../src/ui/theme-parser.c:3665 ../src/ui/theme-parser.c:3670
#, c-format
msgid "Element <%s> is not allowed inside a <%s> element"
msgstr "Predmet <%s> ni dovoljen znotraj predmeta <%s>"
#: ../src/ui/theme-parser.c:3898
msgid "No draw_ops provided for frame piece"
msgstr "Za del okvirja ni navedena vrednost draw_ops"
#: ../src/ui/theme-parser.c:3913
msgid "No draw_ops provided for button"
msgstr "Za gumb ni navedena vrednost draw_ops"
#: ../src/ui/theme-parser.c:3967
#, c-format
msgid "No text is allowed inside element <%s>"
msgstr "Znotraj predmeta <%s> besedilo ni dovoljeno"
#: ../src/ui/theme-parser.c:4025 ../src/ui/theme-parser.c:4037
#: ../src/ui/theme-parser.c:4049 ../src/ui/theme-parser.c:4061
#: ../src/ui/theme-parser.c:4073
#, c-format
msgid "<%s> specified twice for this theme"
msgstr "Vrednost <%s> je za to temo navedena dvakrat"
#: ../src/ui/theme-parser.c:4335
#, c-format
msgid "Failed to find a valid file for theme %s\n"
msgstr "Ni mogoče najti veljavne datoteke za temo %s\n"
# G:2 K:6 O:0
#: ../src/x11/session.c:1815
msgid ""
@@ -588,26 +1288,16 @@ msgstr ""
"Ta okna ne podpirajo možnosti &quot;shranjevanja trenutnih nastavitev&quot;, "
"zato jih bo treba ob naslednji prijavi zagnati ročno."
#: ../src/x11/window-props.c:549
#: ../src/x11/window-props.c:558
#, c-format
msgid "%s (on %s)"
msgstr "%s (na %s)"
#~ msgid "Failed to scan themes directory: %s\n"
#~ msgstr "Ni mogoče preiskati mape tem: %s\n"
#~ msgid "background texture could not be created from file"
#~ msgstr "teksture ozadja iz datoteke ni mogoče ustvariti"
#~ msgid ""
#~ "Could not find a theme! Be sure %s exists and contains the usual themes.\n"
#~ msgstr ""
#~ "Ni mogoče najti teme! Prepričajte se, da %s obstaja in vsebuje običajni "
#~ "zapis teme.\n"
#~ msgid "Unknown window information request: %d"
#~ msgstr "Zahteva izpisa podrobnosti neznanega okna: %d"
#~ msgid "Screen %d on display \"%s\" already has a window manager\n"
#~ msgstr ""
#~ "Zaslon %d na prikazu \"%s\" je že upravljan z upravljalnikom oken\n"
#~ msgid "%d x %d"
#~ msgstr "%d x %d"
#~ msgid "top"
#~ msgstr "zgoraj"
#~ msgid "Missing %s extension required for compositing"
#~ msgstr "Manjka razširitev %s, ki je ključna za sestavljanje"

1252
po/sr.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1572
po/sv.po

File diff suppressed because it is too large Load Diff

403
po/tr.po

File diff suppressed because it is too large Load Diff

3857
po/vi.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -6,7 +6,6 @@ lib_LTLIBRARIES = libmutter.la
SUBDIRS=compositor/plugins
EXTRA_DIST =
NULL =
AM_CPPFLAGS = \
-DCLUTTER_ENABLE_COMPOSITOR_API \
@@ -32,37 +31,31 @@ AM_CPPFLAGS = \
-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\" \
-DMUTTER_PLUGIN_DIR=\"$(MUTTER_PLUGIN_DIR)\" \
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
-DXWAYLAND_PATH=\"$(XWAYLAND_PATH)\" \
$(NULL)
-DXWAYLAND_PATH=\"$(XWAYLAND_PATH)\"
mutter_built_sources = \
$(dbus_idle_built_sources) \
$(dbus_display_config_built_sources) \
$(dbus_login1_built_sources) \
mutter-enum-types.h \
mutter-enum-types.c \
$(NULL)
mutter-enum-types.c
if HAVE_WAYLAND
mutter_built_sources += \
gtk-shell-protocol.c \
gtk-shell-server-protocol.h \
xdg-shell-protocol.c \
xdg-shell-server-protocol.h \
$(NULL)
xdg-shell-server-protocol.h
endif
wayland_protocols = \
wayland_protocols = \
wayland/protocol/gtk-shell.xml \
wayland/protocol/xdg-shell.xml \
$(NULL)
wayland/protocol/xdg-shell.xml
libmutter_la_SOURCES = \
backends/meta-backend.c \
meta/meta-backend.h \
backends/meta-backend-private.h \
backends/meta-barrier.c \
backends/meta-barrier-private.h \
backends/meta-cursor.c \
backends/meta-cursor.h \
backends/meta-cursor-private.h \
@@ -75,13 +68,10 @@ libmutter_la_SOURCES = \
backends/meta-idle-monitor-private.h \
backends/meta-idle-monitor-dbus.c \
backends/meta-idle-monitor-dbus.h \
backends/meta-input-settings.c \
backends/meta-input-settings-private.h \
backends/meta-monitor-config.c \
backends/meta-monitor-config.h \
backends/meta-monitor-manager.c \
meta/meta-monitor-manager.h \
backends/meta-monitor-manager-private.h \
backends/meta-monitor-manager.h \
backends/meta-monitor-manager-dummy.c \
backends/meta-monitor-manager-dummy.h \
backends/meta-stage.h \
@@ -90,18 +80,15 @@ libmutter_la_SOURCES = \
backends/edid.h \
backends/x11/meta-backend-x11.c \
backends/x11/meta-backend-x11.h \
backends/x11/meta-barrier-x11.c \
backends/x11/meta-barrier-x11.h \
backends/x11/meta-cursor-renderer-x11.c \
backends/x11/meta-cursor-renderer-x11.h \
backends/x11/meta-idle-monitor-xsync.c \
backends/x11/meta-idle-monitor-xsync.h \
backends/x11/meta-input-settings-x11.c \
backends/x11/meta-input-settings-x11.h \
backends/x11/meta-monitor-manager-xrandr.c \
backends/x11/meta-monitor-manager-xrandr.h \
core/meta-accel-parse.c \
core/meta-accel-parse.h \
core/barrier.c \
meta/barrier.h \
core/bell.c \
core/bell.h \
@@ -139,6 +126,8 @@ libmutter_la_SOURCES = \
compositor/meta-surface-actor.h \
compositor/meta-surface-actor-x11.c \
compositor/meta-surface-actor-x11.h \
compositor/meta-sync-ring.c \
compositor/meta-sync-ring.h \
compositor/meta-texture-rectangle.c \
compositor/meta-texture-rectangle.h \
compositor/meta-texture-tower.c \
@@ -175,6 +164,8 @@ libmutter_la_SOURCES = \
meta/errors.h \
core/frame.c \
core/frame.h \
ui/gradient.c \
meta/gradient.h \
core/meta-gesture-tracker.c \
core/meta-gesture-tracker-private.h \
core/keybindings.c \
@@ -206,6 +197,9 @@ libmutter_la_SOURCES = \
ui/ui.h \
ui/frames.c \
ui/frames.h \
ui/resizepopup.c \
ui/resizepopup.h \
ui/theme-parser.c \
ui/theme.c \
meta/theme.h \
ui/theme-private.h \
@@ -230,8 +224,7 @@ libmutter_la_SOURCES = \
x11/window-x11-private.h \
x11/xprops.c \
x11/xprops.h \
x11/mutter-Xatomtype.h \
$(NULL)
x11/mutter-Xatomtype.h
if HAVE_WAYLAND
libmutter_la_SOURCES += \
@@ -253,8 +246,6 @@ libmutter_la_SOURCES += \
wayland/meta-wayland-keyboard.h \
wayland/meta-wayland-pointer.c \
wayland/meta-wayland-pointer.h \
wayland/meta-wayland-popup.c \
wayland/meta-wayland-popup.h \
wayland/meta-wayland-seat.c \
wayland/meta-wayland-seat.h \
wayland/meta-wayland-touch.c \
@@ -266,35 +257,29 @@ libmutter_la_SOURCES += \
wayland/meta-wayland-outputs.c \
wayland/meta-wayland-outputs.h \
wayland/window-wayland.c \
wayland/window-wayland.h \
$(NULL)
wayland/window-wayland.h
endif
if HAVE_NATIVE_BACKEND
libmutter_la_SOURCES += \
backends/native/meta-backend-native.c \
backends/native/meta-backend-native.h \
backends/native/meta-backend-native-private.h \
backends/native/meta-barrier-native.c \
backends/native/meta-barrier-native.h \
backends/native/meta-cursor-renderer-native.c \
backends/native/meta-cursor-renderer-native.h \
backends/native/meta-idle-monitor-native.c \
backends/native/meta-idle-monitor-native.h \
backends/native/meta-input-settings-native.c \
backends/native/meta-input-settings-native.h \
backends/native/meta-monitor-manager-kms.c \
backends/native/meta-monitor-manager-kms.h \
backends/native/meta-launcher.c \
backends/native/meta-launcher.h \
backends/native/dbus-utils.c \
backends/native/dbus-utils.h \
$(NULL)
backends/native/dbus-utils.h
endif
nodist_libmutter_la_SOURCES = $(mutter_built_sources)
nodist_libmutter_la_SOURCES = \
$(mutter_built_sources)
libmutter_la_LDFLAGS = -no-undefined -export-symbols-regex "^(meta|ag)_.*"
libmutter_la_LDFLAGS = -no-undefined
libmutter_la_LIBADD = $(MUTTER_LIBS) $(MUTTER_NATIVE_BACKEND_LIBS)
# Headers installed for plugins; introspected information will
@@ -307,6 +292,7 @@ libmutterinclude_headers = \
meta/compositor.h \
meta/display.h \
meta/errors.h \
meta/gradient.h \
meta/group.h \
meta/keybindings.h \
meta/main.h \
@@ -318,7 +304,6 @@ libmutterinclude_headers = \
meta/meta-cursor-tracker.h \
meta/meta-idle-monitor.h \
meta/meta-plugin.h \
meta/meta-monitor-manager.h \
meta/meta-shaped-texture.h \
meta/meta-shadow-factory.h \
meta/meta-window-actor.h \
@@ -328,8 +313,7 @@ libmutterinclude_headers = \
meta/types.h \
meta/util.h \
meta/window.h \
meta/workspace.h \
$(NULL)
meta/workspace.h
libmutterinclude_built_headers = \
meta/meta-version.h
@@ -410,15 +394,14 @@ DISTCLEANFILES = \
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libmutter.pc
EXTRA_DIST += \
$(wayland_protocols) \
libmutter.pc.in \
mutter-enum-types.h.in \
mutter-enum-types.c.in \
org.freedesktop.login1.xml \
EXTRA_DIST += \
$(wayland_protocols) \
libmutter.pc.in \
mutter-enum-types.h.in \
mutter-enum-types.c.in \
org.freedesktop.login1.xml \
org.gnome.Mutter.DisplayConfig.xml \
org.gnome.Mutter.IdleMonitor.xml \
$(NULL)
org.gnome.Mutter.IdleMonitor.xml
BUILT_SOURCES = \
$(mutter_built_sources) \

View File

@@ -33,7 +33,7 @@
#include <meta/meta-backend.h>
#include <meta/meta-idle-monitor.h>
#include "meta-cursor-renderer.h"
#include "meta-monitor-manager-private.h"
#include "meta-monitor-manager.h"
#define DEFAULT_XKB_RULES_FILE "evdev"
#define DEFAULT_XKB_MODEL "pc105+inet"
@@ -49,7 +49,8 @@ struct _MetaBackend
{
GObject parent;
GHashTable *device_monitors;
MetaIdleMonitor *device_monitors[256];
int device_id_max;
};
struct _MetaBackendClass

View File

@@ -26,7 +26,6 @@
#include <meta/meta-backend.h>
#include "meta-backend-private.h"
#include "meta-input-settings-private.h"
#include "backends/x11/meta-backend-x11.h"
#include "meta-stage.h"
@@ -35,10 +34,6 @@
#include "backends/native/meta-backend-native.h"
#endif
#include "backends/meta-idle-monitor-private.h"
#include "backends/meta-monitor-manager-dummy.h"
static MetaBackend *_backend;
/**
@@ -58,7 +53,6 @@ struct _MetaBackendPrivate
{
MetaMonitorManager *monitor_manager;
MetaCursorRenderer *cursor_renderer;
MetaInputSettings *input_settings;
ClutterActor *stage;
};
@@ -71,11 +65,15 @@ meta_backend_finalize (GObject *object)
{
MetaBackend *backend = META_BACKEND (object);
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
int i;
g_clear_object (&priv->monitor_manager);
g_clear_object (&priv->input_settings);
g_hash_table_destroy (backend->device_monitors);
for (i = 0; i <= backend->device_id_max; i++)
{
if (backend->device_monitors[i])
g_object_unref (backend->device_monitors[i]);
}
G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object);
}
@@ -110,19 +108,27 @@ static void
create_device_monitor (MetaBackend *backend,
int device_id)
{
MetaIdleMonitor *idle_monitor;
g_assert (backend->device_monitors[device_id] == NULL);
g_assert (g_hash_table_lookup (backend->device_monitors, &device_id) == NULL);
idle_monitor = meta_backend_create_idle_monitor (backend, device_id);
g_hash_table_insert (backend->device_monitors, &idle_monitor->device_id, idle_monitor);
backend->device_monitors[device_id] = meta_backend_create_idle_monitor (backend, device_id);
backend->device_id_max = MAX (backend->device_id_max, device_id);
}
static void
destroy_device_monitor (MetaBackend *backend,
int device_id)
{
g_hash_table_remove (backend->device_monitors, &device_id);
g_clear_object (&backend->device_monitors[device_id]);
if (device_id == backend->device_id_max)
{
/* Reset the max device ID */
int i, new_max = 0;
for (i = 0; i < backend->device_id_max; i++)
if (backend->device_monitors[i] != NULL)
new_max = i;
backend->device_id_max = new_max;
}
}
static void
@@ -147,15 +153,6 @@ on_device_removed (ClutterDeviceManager *device_manager,
destroy_device_monitor (backend, device_id);
}
static MetaMonitorManager *
create_monitor_manager (MetaBackend *backend)
{
if (g_getenv ("META_DUMMY_MONITORS"))
return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL);
return META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend);
}
static void
meta_backend_real_post_init (MetaBackend *backend)
{
@@ -165,7 +162,7 @@ meta_backend_real_post_init (MetaBackend *backend)
clutter_actor_realize (priv->stage);
META_BACKEND_GET_CLASS (backend)->select_stage_events (backend);
priv->monitor_manager = create_monitor_manager (backend);
priv->monitor_manager = META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend);
g_signal_connect (priv->monitor_manager, "monitors-changed",
G_CALLBACK (on_monitors_changed), backend);
@@ -173,9 +170,6 @@ meta_backend_real_post_init (MetaBackend *backend)
priv->cursor_renderer = META_BACKEND_GET_CLASS (backend)->create_cursor_renderer (backend);
backend->device_monitors = g_hash_table_new_full (g_int_hash, g_int_equal,
NULL, (GDestroyNotify) g_object_unref);
{
ClutterDeviceManager *manager;
GSList *devices, *l;
@@ -199,8 +193,6 @@ meta_backend_real_post_init (MetaBackend *backend)
g_slist_free (devices);
}
priv->input_settings = meta_input_settings_create ();
}
static MetaCursorRenderer *
@@ -289,7 +281,9 @@ MetaIdleMonitor *
meta_backend_get_idle_monitor (MetaBackend *backend,
int device_id)
{
return g_hash_table_lookup (backend->device_monitors, &device_id);
g_return_val_if_fail (device_id >= 0 && device_id < 256, NULL);
return backend->device_monitors[device_id];
}
/**

View File

@@ -1,81 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014-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:
* Jasper St. Pierre <jstpierre@mecheye.net>
* Jonas Ådahl <jadahl@gmail.com>
*/
#ifndef META_BARRIER_PRIVATE_H
#define META_BARRIER_PRIVATE_H
G_BEGIN_DECLS
#define META_TYPE_BARRIER_IMPL (meta_barrier_impl_get_type ())
#define META_BARRIER_IMPL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BARRIER_IMPL, MetaBarrierImpl))
#define META_BARRIER_IMPL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BARRIER_IMPL, MetaBarrierImplClass))
#define META_IS_BARRIER_IMPL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BARRIER_IMPL))
#define META_IS_BARRIER_IMPL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_BARRIER_IMPL))
#define META_BARRIER_IMPL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_BARRIER_IMPL, MetaBarrierImplClass))
typedef struct _MetaBarrierImpl MetaBarrierImpl;
typedef struct _MetaBarrierImplClass MetaBarrierImplClass;
struct _MetaBarrierImpl
{
GObject parent;
};
struct _MetaBarrierImplClass
{
GObjectClass parent_class;
gboolean (*is_active) (MetaBarrierImpl *barrier);
void (*release) (MetaBarrierImpl *barrier,
MetaBarrierEvent *event);
void (*destroy) (MetaBarrierImpl *barrier);
};
GType meta_barrier_impl_get_type (void) G_GNUC_CONST;
void _meta_barrier_emit_hit_signal (MetaBarrier *barrier,
MetaBarrierEvent *event);
void _meta_barrier_emit_left_signal (MetaBarrier *barrier,
MetaBarrierEvent *event);
void meta_barrier_event_unref (MetaBarrierEvent *event);
G_END_DECLS
struct _MetaBarrierPrivate
{
MetaDisplay *display;
int x1;
int y1;
int x2;
int y2;
MetaBarrierDirection directions;
MetaBarrierImpl *impl;
};
#endif /* META_BARRIER_PRIVATE_H */

View File

@@ -25,10 +25,7 @@
#include "meta-cursor.h"
#include <cogl/cogl.h>
#ifdef HAVE_NATIVE_BACKEND
#include <gbm.h>
#endif
typedef struct {
CoglTexture2D *texture;

View File

@@ -30,6 +30,8 @@
#include <meta/screen.h>
#include "meta-cursor.h"
#include <gbm.h>
#define META_TYPE_CURSOR_RENDERER (meta_cursor_renderer_get_type ())
#define META_CURSOR_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_RENDERER, MetaCursorRenderer))
#define META_CURSOR_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_RENDERER, MetaCursorRendererClass))

View File

@@ -27,9 +27,7 @@
* pointer abstraction"
*/
#include "config.h"
#include "meta-cursor-tracker-private.h"
#include <config.h>
#include <string.h>
#include <meta/main.h>
#include <meta/util.h>
@@ -40,10 +38,11 @@
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <X11/extensions/Xfixes.h>
#include "meta-backend-private.h"
#include "meta-cursor-private.h"
#include "meta-cursor-tracker-private.h"
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);

View File

@@ -55,8 +55,7 @@ meta_cursor_reference_ref (MetaCursorReference *self)
static void
meta_cursor_image_free (MetaCursorImage *image)
{
if (image->texture)
cogl_object_unref (image->texture);
cogl_object_unref (image->texture);
#ifdef HAVE_NATIVE_BACKEND
if (image->bo)
@@ -256,30 +255,22 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
#endif
}
static void
load_cursor_image (MetaCursorReference *cursor)
{
XcursorImage *image;
/* Either cursors are loaded from X cursors or buffers. Since
* buffers are converted over immediately, we can make sure to
* load this directly. */
g_assert (cursor->cursor != META_CURSOR_NONE);
image = load_cursor_on_client (cursor->cursor);
if (!image)
return;
meta_cursor_image_load_from_xcursor_image (&cursor->image, image);
XcursorImageDestroy (image);
}
MetaCursorReference *
meta_cursor_reference_from_theme (MetaCursor cursor)
{
MetaCursorReference *self = g_slice_new0 (MetaCursorReference);
MetaCursorReference *self;
XcursorImage *image;
image = load_cursor_on_client (cursor);
if (!image)
return NULL;
self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
self->cursor = cursor;
meta_cursor_image_load_from_xcursor_image (&self->image, image);
XcursorImageDestroy (image);
return self;
}
@@ -317,8 +308,6 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
{
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
wl_shm_buffer_begin_access (shm_buffer);
switch (wl_shm_buffer_get_format (shm_buffer))
{
#if G_BYTE_ORDER == G_BIG_ENDIAN
@@ -346,8 +335,6 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
(uint8_t *) wl_shm_buffer_get_data (shm_buffer),
width, height, rowstride,
gbm_format);
wl_shm_buffer_end_access (shm_buffer);
}
else
{
@@ -393,14 +380,10 @@ meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
int *hot_x,
int *hot_y)
{
if (!cursor->image.texture)
load_cursor_image (cursor);
if (hot_x)
*hot_x = cursor->image.hot_x;
if (hot_y)
*hot_y = cursor->image.hot_y;
return COGL_TEXTURE (cursor->image.texture);
}
@@ -410,9 +393,6 @@ meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
int *hot_x,
int *hot_y)
{
if (!cursor->image.bo)
load_cursor_image (cursor);
if (hot_x)
*hot_x = cursor->image.hot_x;
if (hot_y)

View File

@@ -1,83 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2014 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef META_INPUT_SETTINGS_PRIVATE_H
#define META_INPUT_SETTINGS_PRIVATE_H
#include "display-private.h"
#include <clutter/clutter.h>
#define META_TYPE_INPUT_SETTINGS (meta_input_settings_get_type ())
#define META_INPUT_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_INPUT_SETTINGS, MetaInputSettings))
#define META_INPUT_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_INPUT_SETTINGS, MetaInputSettingsClass))
#define META_IS_INPUT_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_INPUT_SETTINGS))
#define META_IS_INPUT_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_INPUT_SETTINGS))
#define META_INPUT_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_INPUT_SETTINGS, MetaInputSettingsClass))
typedef struct _MetaInputSettings MetaInputSettings;
typedef struct _MetaInputSettingsClass MetaInputSettingsClass;
struct _MetaInputSettings
{
GObject parent_instance;
};
struct _MetaInputSettingsClass
{
GObjectClass parent_class;
void (* set_send_events) (MetaInputSettings *settings,
ClutterInputDevice *device,
GDesktopDeviceSendEvents mode);
void (* set_matrix) (MetaInputSettings *settings,
ClutterInputDevice *device,
gfloat matrix[6]);
void (* set_speed) (MetaInputSettings *settings,
ClutterInputDevice *device,
gdouble speed);
void (* set_left_handed) (MetaInputSettings *settings,
ClutterInputDevice *device,
gboolean enabled);
void (* set_tap_enabled) (MetaInputSettings *settings,
ClutterInputDevice *device,
gboolean enabled);
void (* set_invert_scroll) (MetaInputSettings *settings,
ClutterInputDevice *device,
gboolean inverted);
void (* set_scroll_method) (MetaInputSettings *settings,
ClutterInputDevice *device,
GDesktopTouchpadScrollMethod mode);
void (* set_scroll_button) (MetaInputSettings *settings,
ClutterInputDevice *device,
guint button);
void (* set_keyboard_repeat) (MetaInputSettings *settings,
gboolean repeat,
guint delay,
guint interval);
};
GType meta_input_settings_get_type (void) G_GNUC_CONST;
MetaInputSettings * meta_input_settings_create (void);
#endif /* META_INPUT_SETTINGS_PRIVATE_H */

View File

@@ -1,838 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2014 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
/**
* SECTION:input-settings
* @title: MetaInputSettings
* @short_description: Mutter input device configuration
*/
#include "config.h"
#include <string.h>
#include "meta-backend-private.h"
#include "meta-input-settings-private.h"
#include "x11/meta-input-settings-x11.h"
#ifdef HAVE_NATIVE_BACKEND
#include "native/meta-backend-native.h"
#include "native/meta-input-settings-native.h"
#endif
#include <meta/util.h>
typedef struct _MetaInputSettingsPrivate MetaInputSettingsPrivate;
typedef struct _DeviceMappingInfo DeviceMappingInfo;
struct _DeviceMappingInfo
{
MetaInputSettings *input_settings;
ClutterInputDevice *device;
GSettings *settings;
};
struct _MetaInputSettingsPrivate
{
ClutterDeviceManager *device_manager;
MetaMonitorManager *monitor_manager;
guint monitors_changed_id;
GSettings *mouse_settings;
GSettings *touchpad_settings;
GSettings *trackball_settings;
GSettings *keyboard_settings;
GHashTable *mappable_devices;
};
typedef void (*ConfigBoolFunc) (MetaInputSettings *input_settings,
ClutterInputDevice *device,
gboolean setting);
typedef void (*ConfigDoubleFunc) (MetaInputSettings *input_settings,
ClutterInputDevice *device,
gdouble value);
typedef void (*ConfigUintFunc) (MetaInputSettings *input_settings,
ClutterInputDevice *device,
guint value);
G_DEFINE_TYPE_WITH_PRIVATE (MetaInputSettings, meta_input_settings, G_TYPE_OBJECT)
static GSList *
meta_input_settings_get_devices (MetaInputSettings *settings,
ClutterInputDeviceType type)
{
MetaInputSettingsPrivate *priv;
const GSList *devices;
GSList *list = NULL;
priv = meta_input_settings_get_instance_private (settings);
devices = clutter_device_manager_peek_devices (priv->device_manager);
while (devices)
{
ClutterInputDevice *device = devices->data;
if (clutter_input_device_get_device_type (device) == type &&
clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_MASTER)
list = g_slist_prepend (list, device);
devices = devices->next;
}
return list;
}
static void
meta_input_settings_dispose (GObject *object)
{
MetaInputSettings *settings = META_INPUT_SETTINGS (object);
MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (settings);
g_clear_object (&priv->mouse_settings);
g_clear_object (&priv->touchpad_settings);
g_clear_object (&priv->trackball_settings);
g_clear_object (&priv->keyboard_settings);
g_clear_pointer (&priv->mappable_devices, g_hash_table_unref);
if (priv->monitors_changed_id && priv->monitor_manager)
{
g_signal_handler_disconnect (priv->monitor_manager,
priv->monitors_changed_id);
priv->monitors_changed_id = 0;
}
g_clear_object (&priv->monitor_manager);
G_OBJECT_CLASS (meta_input_settings_parent_class)->dispose (object);
}
static void
settings_device_set_bool_setting (MetaInputSettings *input_settings,
ClutterInputDevice *device,
ConfigBoolFunc func,
gboolean enabled)
{
func (input_settings, device, enabled);
}
static void
settings_set_bool_setting (MetaInputSettings *input_settings,
ClutterInputDeviceType type,
ConfigBoolFunc func,
gboolean enabled)
{
GSList *devices, *d;
devices = meta_input_settings_get_devices (input_settings, type);
for (d = devices; d; d = d->next)
settings_device_set_bool_setting (input_settings, d->data, func, enabled);
g_slist_free (devices);
}
static void
settings_device_set_double_setting (MetaInputSettings *input_settings,
ClutterInputDevice *device,
ConfigDoubleFunc func,
gdouble value)
{
func (input_settings, device, value);
}
static void
settings_set_double_setting (MetaInputSettings *input_settings,
ClutterInputDeviceType type,
ConfigDoubleFunc func,
gdouble value)
{
GSList *devices, *d;
devices = meta_input_settings_get_devices (input_settings, type);
for (d = devices; d; d = d->next)
settings_device_set_double_setting (input_settings, d->data, func, value);
g_slist_free (devices);
}
static void
settings_device_set_uint_setting (MetaInputSettings *input_settings,
ClutterInputDevice *device,
ConfigUintFunc func,
guint value)
{
(func) (input_settings, device, value);
}
static void
settings_set_uint_setting (MetaInputSettings *input_settings,
ClutterInputDeviceType type,
ConfigUintFunc func,
guint value)
{
GSList *devices, *d;
devices = meta_input_settings_get_devices (input_settings, type);
for (d = devices; d; d = d->next)
settings_device_set_uint_setting (input_settings, d->data, func, value);
g_slist_free (devices);
}
static void
update_touchpad_left_handed (MetaInputSettings *input_settings,
ClutterInputDevice *device)
{
MetaInputSettingsClass *input_settings_class;
GDesktopTouchpadHandedness handedness;
MetaInputSettingsPrivate *priv;
gboolean enabled = FALSE;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
handedness = g_settings_get_enum (priv->touchpad_settings, "left-handed");
switch (handedness)
{
case G_DESKTOP_TOUCHPAD_HANDEDNESS_RIGHT:
enabled = FALSE;
break;
case G_DESKTOP_TOUCHPAD_HANDEDNESS_LEFT:
enabled = TRUE;
break;
case G_DESKTOP_TOUCHPAD_HANDEDNESS_MOUSE:
enabled = g_settings_get_boolean (priv->mouse_settings, "left-handed");
break;
default:
g_assert_not_reached ();
}
if (device)
{
g_assert (clutter_input_device_get_device_type (device) == CLUTTER_TOUCHPAD_DEVICE);
settings_device_set_bool_setting (input_settings, device,
input_settings_class->set_left_handed,
enabled);
}
else
{
settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
input_settings_class->set_left_handed,
enabled);
}
}
static void
update_mouse_left_handed (MetaInputSettings *input_settings,
ClutterInputDevice *device)
{
MetaInputSettingsClass *input_settings_class;
MetaInputSettingsPrivate *priv;
gboolean enabled;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
enabled = g_settings_get_boolean (priv->mouse_settings, "left-handed");
if (device)
{
g_assert (clutter_input_device_get_device_type (device) == CLUTTER_POINTER_DEVICE);
settings_device_set_bool_setting (input_settings, device,
input_settings_class->set_left_handed,
enabled);
}
else
{
GDesktopTouchpadHandedness touchpad_handedness;
settings_set_bool_setting (input_settings, CLUTTER_POINTER_DEVICE,
input_settings_class->set_left_handed,
enabled);
touchpad_handedness = g_settings_get_enum (priv->touchpad_settings,
"left-handed");
/* Also update touchpads if they're following mouse settings */
if (touchpad_handedness == G_DESKTOP_TOUCHPAD_HANDEDNESS_MOUSE)
update_touchpad_left_handed (input_settings, NULL);
}
}
static void
update_device_speed (MetaInputSettings *input_settings,
GSettings *settings,
ClutterInputDevice *device,
ClutterInputDeviceType type)
{
MetaInputSettingsClass *input_settings_class;
gdouble speed;
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
speed = g_settings_get_double (settings, "speed");
if (device)
settings_device_set_double_setting (input_settings, device,
input_settings_class->set_speed,
speed);
else
settings_set_double_setting (input_settings, type,
input_settings_class->set_speed,
speed);
}
static void
update_device_natural_scroll (MetaInputSettings *input_settings,
GSettings *settings,
ClutterInputDevice *device,
ClutterInputDeviceType type)
{
MetaInputSettingsClass *input_settings_class;
gboolean enabled;
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
enabled = g_settings_get_boolean (settings, "natural-scroll");
if (device)
{
settings_device_set_bool_setting (input_settings, device,
input_settings_class->set_invert_scroll,
enabled);
}
else
{
settings_set_bool_setting (input_settings, type,
input_settings_class->set_invert_scroll,
enabled);
}
}
static void
update_touchpad_tap_enabled (MetaInputSettings *input_settings,
ClutterInputDevice *device)
{
MetaInputSettingsClass *input_settings_class;
MetaInputSettingsPrivate *priv;
gboolean enabled;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-to-click");
if (device)
{
settings_device_set_bool_setting (input_settings, device,
input_settings_class->set_tap_enabled,
enabled);
}
else
{
settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
input_settings_class->set_tap_enabled,
enabled);
}
}
static void
update_touchpad_scroll_method (MetaInputSettings *input_settings,
ClutterInputDevice *device)
{
MetaInputSettingsClass *input_settings_class;
GDesktopTouchpadScrollMethod method;
MetaInputSettingsPrivate *priv;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
method = g_settings_get_enum (priv->touchpad_settings, "scroll-method");
if (device)
{
settings_device_set_uint_setting (input_settings, device,
input_settings_class->set_scroll_method,
method);
}
else
{
settings_set_uint_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
(ConfigUintFunc) input_settings_class->set_scroll_method,
method);
}
}
static void
update_touchpad_send_events (MetaInputSettings *input_settings,
ClutterInputDevice *device)
{
MetaInputSettingsClass *input_settings_class;
MetaInputSettingsPrivate *priv;
GDesktopDeviceSendEvents mode;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
mode = g_settings_get_enum (priv->touchpad_settings, "send-events");
if (device)
{
settings_device_set_uint_setting (input_settings, device,
input_settings_class->set_send_events,
mode);
}
else
{
settings_set_uint_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
input_settings_class->set_send_events,
mode);
}
}
static gboolean
device_is_trackball (ClutterInputDevice *device)
{
gboolean is_trackball;
char *name;
if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER)
return FALSE;
name = g_ascii_strdown (clutter_input_device_get_device_name (device), -1);
is_trackball = strstr (name, "trackball") != NULL;
g_free (name);
return is_trackball;
}
static void
update_trackball_scroll_button (MetaInputSettings *input_settings,
ClutterInputDevice *device)
{
MetaInputSettingsClass *input_settings_class;
MetaInputSettingsPrivate *priv;
guint button;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
button = g_settings_get_uint (priv->trackball_settings, "scroll-wheel-emulation-button");
if (device && device_is_trackball (device))
{
input_settings_class->set_scroll_button (input_settings, device, button);
}
else if (!device)
{
MetaInputSettingsPrivate *priv;
const GSList *devices;
priv = meta_input_settings_get_instance_private (input_settings);
devices = clutter_device_manager_peek_devices (priv->device_manager);
while (devices)
{
ClutterInputDevice *device = devices->data;
if (device_is_trackball (device))
input_settings_class->set_scroll_button (input_settings, device, button);
devices = devices->next;
}
}
}
static void
update_keyboard_repeat (MetaInputSettings *input_settings)
{
MetaInputSettingsClass *input_settings_class;
MetaInputSettingsPrivate *priv;
guint delay, interval;
gboolean repeat;
priv = meta_input_settings_get_instance_private (input_settings);
repeat = g_settings_get_boolean (priv->keyboard_settings, "repeat");
delay = g_settings_get_uint (priv->keyboard_settings, "delay");
interval = g_settings_get_uint (priv->keyboard_settings, "repeat-interval");
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
input_settings_class->set_keyboard_repeat (input_settings,
repeat, delay, interval);
}
static MetaOutput *
meta_input_settings_find_output (MetaInputSettings *input_settings,
GSettings *settings,
ClutterInputDevice *device)
{
MetaInputSettingsPrivate *priv;
guint n_values, n_outputs, i;
MetaOutput *outputs;
gchar **edid;
priv = meta_input_settings_get_instance_private (input_settings);
edid = g_settings_get_strv (settings, "display");
n_values = g_strv_length (edid);
if (n_values != 3)
{
g_warning ("EDID configuration for device '%s' "
"is incorrect, must have 3 values",
clutter_input_device_get_device_name (device));
return NULL;
}
if (!*edid[0] && !*edid[1] && !*edid[2])
return NULL;
outputs = meta_monitor_manager_get_outputs (priv->monitor_manager,
&n_outputs);
for (i = 0; i < n_outputs; i++)
{
if (g_strcmp0 (outputs[i].vendor, edid[0]) == 0 &&
g_strcmp0 (outputs[i].product, edid[1]) == 0 &&
g_strcmp0 (outputs[i].serial, edid[2]) == 0)
return &outputs[i];
}
return NULL;
}
static void
update_device_display (MetaInputSettings *input_settings,
GSettings *settings,
ClutterInputDevice *device)
{
MetaInputSettingsClass *input_settings_class;
MetaInputSettingsPrivate *priv;
gfloat matrix[6] = { 1, 0, 0, 0, 1, 0 };
MetaOutput *output;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
output = meta_input_settings_find_output (input_settings, settings, device);
if (output)
meta_monitor_manager_get_monitor_matrix (priv->monitor_manager,
output, matrix);
input_settings_class->set_matrix (input_settings, device, matrix);
}
static void
meta_input_settings_changed_cb (GSettings *settings,
const char *key,
gpointer user_data)
{
MetaInputSettings *input_settings = META_INPUT_SETTINGS (user_data);
MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings);
if (settings == priv->mouse_settings)
{
if (strcmp (key, "left-handed") == 0)
update_mouse_left_handed (input_settings, NULL);
else if (strcmp (key, "speed") == 0)
update_device_speed (input_settings, settings, NULL,
CLUTTER_POINTER_DEVICE);
else if (strcmp (key, "natural-scroll") == 0)
update_device_natural_scroll (input_settings, settings,
NULL, CLUTTER_POINTER_DEVICE);
}
else if (settings == priv->touchpad_settings)
{
if (strcmp (key, "left-handed") == 0)
update_touchpad_left_handed (input_settings, NULL);
else if (strcmp (key, "speed") == 0)
update_device_speed (input_settings, settings, NULL,
CLUTTER_TOUCHPAD_DEVICE);
else if (strcmp (key, "natural-scroll") == 0)
update_device_natural_scroll (input_settings, settings,
NULL, CLUTTER_TOUCHPAD_DEVICE);
else if (strcmp (key, "tap-to-click") == 0)
update_touchpad_tap_enabled (input_settings, NULL);
else if (strcmp (key, "send-events") == 0)
update_touchpad_send_events (input_settings, NULL);
else if (strcmp (key, "scroll-method") == 0)
update_touchpad_scroll_method (input_settings, NULL);
}
else if (settings == priv->trackball_settings)
{
if (strcmp (key, "scroll-wheel-emulation-button") == 0)
update_trackball_scroll_button (input_settings, NULL);
}
else if (settings == priv->keyboard_settings)
{
if (strcmp (key, "repeat") == 0 ||
strcmp (key, "repeat-interval") == 0 ||
strcmp (key, "delay") == 0)
update_keyboard_repeat (input_settings);
}
}
static void
mapped_device_changed_cb (GSettings *settings,
const gchar *key,
DeviceMappingInfo *info)
{
if (strcmp (key, "display") == 0)
update_device_display (info->input_settings, settings, info->device);
}
static GSettings *
lookup_device_settings (ClutterInputDevice *device)
{
const gchar *group, *schema, *vendor, *product;
ClutterInputDeviceType type;
GSettings *settings;
gchar *path;
type = clutter_input_device_get_device_type (device);
if (type == CLUTTER_TOUCHSCREEN_DEVICE)
{
group = "touchscreens";
schema = "org.gnome.desktop.peripherals.touchscreen";
}
else if (type == CLUTTER_TABLET_DEVICE ||
type == CLUTTER_PEN_DEVICE ||
type == CLUTTER_ERASER_DEVICE ||
type == CLUTTER_CURSOR_DEVICE)
{
group = "tablets";
schema = "org.gnome.desktop.peripherals.tablet";
}
else
return NULL;
vendor = clutter_input_device_get_vendor_id (device);
product = clutter_input_device_get_product_id (device);
path = g_strdup_printf ("/org/gnome/desktop/peripherals/%s/%s:%s/",
group, vendor, product);
settings = g_settings_new_with_path (schema, path);
g_free (path);
return settings;
}
static void
monitors_changed_cb (MetaMonitorManager *monitor_manager,
MetaInputSettings *input_settings)
{
MetaInputSettingsPrivate *priv;
ClutterInputDevice *device;
GSettings *settings;
GHashTableIter iter;
priv = meta_input_settings_get_instance_private (input_settings);
g_hash_table_iter_init (&iter, priv->mappable_devices);
while (g_hash_table_iter_next (&iter, (gpointer *) &device,
(gpointer *) &settings))
update_device_display (input_settings, settings, device);
}
static gboolean
check_add_mappable_device (MetaInputSettings *input_settings,
ClutterInputDevice *device)
{
MetaInputSettingsPrivate *priv;
DeviceMappingInfo *info;
GSettings *settings;
settings = lookup_device_settings (device);
if (!settings)
return FALSE;
priv = meta_input_settings_get_instance_private (input_settings);
info = g_new0 (DeviceMappingInfo, 1);
info->input_settings = input_settings;
info->device = device;
info->settings = settings;
g_signal_connect_data (settings, "changed",
G_CALLBACK (mapped_device_changed_cb),
info, (GClosureNotify) g_free, 0);
g_hash_table_insert (priv->mappable_devices, device, settings);
update_device_display (input_settings, settings, device);
return TRUE;
}
static void
meta_input_settings_device_added (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
MetaInputSettings *input_settings)
{
ClutterInputDeviceType type;
MetaInputSettingsPrivate *priv;
if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER)
return;
priv = meta_input_settings_get_instance_private (input_settings);
type = clutter_input_device_get_device_type (device);
if (type == CLUTTER_POINTER_DEVICE)
{
update_mouse_left_handed (input_settings, device);
update_device_speed (input_settings, priv->mouse_settings, device, type);
if (device_is_trackball (device))
update_trackball_scroll_button (input_settings, device);
}
else if (type == CLUTTER_TOUCHPAD_DEVICE)
{
update_touchpad_left_handed (input_settings, device);
update_touchpad_tap_enabled (input_settings, device);
update_touchpad_scroll_method (input_settings, device);
update_touchpad_send_events (input_settings, device);
update_device_speed (input_settings, priv->touchpad_settings,
device, type);
update_device_natural_scroll (input_settings, priv->touchpad_settings,
device, type);
}
else
{
check_add_mappable_device (input_settings, device);
}
}
static void
meta_input_settings_device_removed (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
MetaInputSettings *input_settings)
{
MetaInputSettingsPrivate *priv;
priv = meta_input_settings_get_instance_private (input_settings);
g_hash_table_remove (priv->mappable_devices, device);
}
static void
check_mappable_devices (MetaInputSettings *input_settings)
{
MetaInputSettingsPrivate *priv;
const GSList *devices, *l;
priv = meta_input_settings_get_instance_private (input_settings);
devices = clutter_device_manager_peek_devices (priv->device_manager);
for (l = devices; l; l = l->next)
{
ClutterInputDevice *device = l->data;
if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER)
continue;
check_add_mappable_device (input_settings, device);
}
}
static void
meta_input_settings_constructed (GObject *object)
{
MetaInputSettings *input_settings = META_INPUT_SETTINGS (object);
MetaInputSettingsPrivate *priv;
priv = meta_input_settings_get_instance_private (input_settings);
update_mouse_left_handed (input_settings, NULL);
update_touchpad_left_handed (input_settings, NULL);
update_touchpad_tap_enabled (input_settings, NULL);
update_touchpad_send_events (input_settings, NULL);
update_device_natural_scroll (input_settings, priv->touchpad_settings,
NULL, CLUTTER_TOUCHPAD_DEVICE);
update_device_speed (input_settings, priv->touchpad_settings, NULL,
CLUTTER_TOUCHPAD_DEVICE);
update_device_speed (input_settings, priv->mouse_settings, NULL,
CLUTTER_POINTER_DEVICE);
update_keyboard_repeat (input_settings);
check_mappable_devices (input_settings);
}
static void
meta_input_settings_class_init (MetaInputSettingsClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = meta_input_settings_dispose;
object_class->constructed = meta_input_settings_constructed;
}
static void
meta_input_settings_init (MetaInputSettings *settings)
{
MetaInputSettingsPrivate *priv;
priv = meta_input_settings_get_instance_private (settings);
priv->device_manager = clutter_device_manager_get_default ();
g_signal_connect (priv->device_manager, "device-added",
G_CALLBACK (meta_input_settings_device_added), settings);
g_signal_connect (priv->device_manager, "device-removed",
G_CALLBACK (meta_input_settings_device_removed), settings);
priv->mouse_settings = g_settings_new ("org.gnome.desktop.peripherals.mouse");
g_signal_connect (priv->mouse_settings, "changed",
G_CALLBACK (meta_input_settings_changed_cb), settings);
priv->touchpad_settings = g_settings_new ("org.gnome.desktop.peripherals.touchpad");
g_signal_connect (priv->touchpad_settings, "changed",
G_CALLBACK (meta_input_settings_changed_cb), settings);
priv->trackball_settings = g_settings_new ("org.gnome.desktop.peripherals.trackball");
g_signal_connect (priv->trackball_settings, "changed",
G_CALLBACK (meta_input_settings_changed_cb), settings);
priv->keyboard_settings = g_settings_new ("org.gnome.desktop.peripherals.keyboard");
g_signal_connect (priv->keyboard_settings, "changed",
G_CALLBACK (meta_input_settings_changed_cb), settings);
priv->mappable_devices =
g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_object_unref);
priv->monitor_manager = g_object_ref (meta_monitor_manager_get ());
g_signal_connect (priv->monitor_manager, "monitors-changed",
G_CALLBACK (monitors_changed_cb), settings);
}
MetaInputSettings *
meta_input_settings_create (void)
{
#ifdef HAVE_NATIVE_BACKEND
MetaBackend *backend;
backend = meta_get_backend ();
if (META_IS_BACKEND_NATIVE (backend))
return g_object_new (META_TYPE_INPUT_SETTINGS_NATIVE, NULL);
#endif
if (!meta_is_wayland_compositor ())
return g_object_new (META_TYPE_INPUT_SETTINGS_X11, NULL);
return NULL;
}

View File

@@ -34,7 +34,6 @@
#include "config.h"
#include "boxes-private.h"
#include "meta-monitor-config.h"
#include <string.h>
@@ -68,7 +67,6 @@ typedef struct {
} MetaOutputConfig;
typedef struct {
guint refcount;
MetaOutputKey *keys;
MetaOutputConfig *outputs;
unsigned int n_outputs;
@@ -79,6 +77,7 @@ struct _MetaMonitorConfig {
GHashTable *configs;
MetaConfiguration *current;
gboolean current_is_stored;
gboolean current_is_for_laptop_lid;
MetaConfiguration *previous;
@@ -125,29 +124,11 @@ config_clear (MetaConfiguration *config)
g_free (config->outputs);
}
static MetaConfiguration *
config_ref (MetaConfiguration *config)
{
config->refcount++;
return config;
}
static void
config_unref (MetaConfiguration *config)
config_free (gpointer config)
{
if (--config->refcount == 0)
{
config_clear (config);
g_slice_free (MetaConfiguration, config);
}
}
static MetaConfiguration *
config_new (void)
{
MetaConfiguration *config = g_slice_new0 (MetaConfiguration);
config->refcount = 1;
return config;
config_clear (config);
g_slice_free (MetaConfiguration, config);
}
static unsigned long
@@ -239,7 +220,7 @@ meta_monitor_config_init (MetaMonitorConfig *self)
const char *filename;
char *path;
self->configs = g_hash_table_new_full (config_hash, config_equal, NULL, (GDestroyNotify) config_unref);
self->configs = g_hash_table_new_full (config_hash, config_equal, NULL, config_free);
filename = g_getenv ("MUTTER_MONITOR_FILENAME");
if (filename == NULL)
@@ -849,45 +830,73 @@ meta_monitor_config_get_stored (MetaMonitorConfig *self,
return stored;
}
static void
set_current (MetaMonitorConfig *self,
MetaConfiguration *config)
{
g_clear_pointer (&self->previous, (GDestroyNotify) config_unref);
self->previous = self->current;
self->current = config_ref (config);
}
static gboolean
apply_configuration (MetaMonitorConfig *self,
MetaConfiguration *config,
MetaMonitorManager *manager)
MetaMonitorManager *manager,
gboolean stored)
{
GPtrArray *crtcs, *outputs;
gboolean ret = FALSE;
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;
{
g_ptr_array_unref (crtcs);
g_ptr_array_unref (outputs);
if (!stored)
config_free (config);
return FALSE;
}
meta_monitor_manager_apply_configuration (manager,
(MetaCRTCInfo**)crtcs->pdata, crtcs->len,
(MetaOutputInfo**)outputs->pdata, outputs->len);
set_current (self, config);
/* Stored (persistent) configurations override the previous one always.
Also, we clear the previous configuration if the current one (which is
about to become previous) is stored, or if the current one has
different outputs.
*/
if (stored ||
(self->current && self->current_is_stored))
{
if (self->previous)
config_free (self->previous);
self->previous = NULL;
}
else
{
/* Despite the name, config_equal() only checks the set of outputs,
not their modes
*/
if (self->current && config_equal (self->current, config))
{
self->previous = self->current;
}
else
{
if (self->current)
config_free (self->current);
self->previous = NULL;
}
}
self->current = config;
self->current_is_stored = stored;
/* If true, we'll be overridden at the end of this call
* inside turn_off_laptop_display / apply_configuration_with_lid */
inside turn_off_laptop_display()
*/
self->current_is_for_laptop_lid = FALSE;
ret = TRUE;
if (self->current == self->previous)
self->previous = NULL;
out:
g_ptr_array_unref (crtcs);
g_ptr_array_unref (outputs);
return ret;
return TRUE;
}
static gboolean
@@ -898,20 +907,6 @@ key_is_laptop (MetaOutputKey *key)
g_str_has_prefix (key->connector, "eDP");
}
static gboolean
output_is_laptop (MetaOutput *output)
{
/* FIXME: extend with better heuristics */
switch (output->connector_type)
{
case META_CONNECTOR_TYPE_eDP:
case META_CONNECTOR_TYPE_LVDS:
return TRUE;
default:
return FALSE;
}
}
static gboolean
laptop_display_is_on (MetaConfiguration *config)
{
@@ -953,7 +948,7 @@ make_laptop_lid_config (MetaConfiguration *reference)
g_assert (multiple_outputs_are_enabled (reference));
new = config_new ();
new = g_slice_new0 (MetaConfiguration);
new->n_outputs = reference->n_outputs;
new->keys = g_new0 (MetaOutputKey, reference->n_outputs);
new->outputs = g_new0 (MetaOutputConfig, reference->n_outputs);
@@ -970,7 +965,8 @@ make_laptop_lid_config (MetaConfiguration *reference)
new->keys[i].product = g_strdup (current_key->product);
new->keys[i].serial = g_strdup (current_key->serial);
if (key_is_laptop (current_key))
if (g_str_has_prefix (current_key->connector, "LVDS") ||
g_str_has_prefix (current_key->connector, "eDP"))
{
new->outputs[i].enabled = FALSE;
x_after = current_output->rect.x;
@@ -1007,32 +1003,6 @@ make_laptop_lid_config (MetaConfiguration *reference)
return new;
}
static gboolean
apply_configuration_with_lid (MetaMonitorConfig *self,
MetaConfiguration *config,
MetaMonitorManager *manager)
{
if (self->lid_is_closed &&
multiple_outputs_are_enabled (config) &&
laptop_display_is_on (config))
{
MetaConfiguration *laptop_lid_config = make_laptop_lid_config (config);
if (apply_configuration (self, laptop_lid_config, manager))
{
self->current_is_for_laptop_lid = TRUE;
config_unref (laptop_lid_config);
return TRUE;
}
else
{
config_unref (laptop_lid_config);
return FALSE;
}
}
else
return apply_configuration (self, config, manager);
}
gboolean
meta_monitor_config_apply_stored (MetaMonitorConfig *self,
MetaMonitorManager *manager)
@@ -1045,7 +1015,23 @@ meta_monitor_config_apply_stored (MetaMonitorConfig *self,
stored = meta_monitor_config_get_stored (self, outputs, n_outputs);
if (stored)
return apply_configuration_with_lid (self, stored, manager);
{
if (self->lid_is_closed &&
multiple_outputs_are_enabled (stored) &&
laptop_display_is_on (stored))
{
if (apply_configuration (self, make_laptop_lid_config (stored),
manager, FALSE))
{
self->current_is_for_laptop_lid = TRUE;
return TRUE;
}
else
return FALSE;
}
else
return apply_configuration (self, stored, manager, TRUE);
}
else
return FALSE;
}
@@ -1074,7 +1060,8 @@ find_primary_output (MetaOutput *outputs,
for (i = 0; i < n_outputs; i++)
{
if (output_is_laptop (&outputs[i]))
if (g_str_has_prefix (outputs[i].name, "LVDS") ||
g_str_has_prefix (outputs[i].name, "eDP"))
return &outputs[i];
}
@@ -1094,123 +1081,47 @@ find_primary_output (MetaOutput *outputs,
return best;
}
static void
init_config_from_preferred_mode (MetaOutputConfig *config,
MetaOutput *output)
static MetaConfiguration *
make_default_config (MetaMonitorConfig *self,
MetaOutput *outputs,
unsigned n_outputs,
int max_width,
int max_height)
{
config->enabled = TRUE;
config->rect.x = 0;
config->rect.y = 0;
config->rect.width = output->preferred_mode->width;
config->rect.height = output->preferred_mode->height;
config->refresh_rate = output->preferred_mode->refresh_rate;
config->transform = META_MONITOR_TRANSFORM_NORMAL;
config->is_primary = FALSE;
config->is_presentation = FALSE;
}
/* This function handles configuring the outputs when the driver provides a
* suggested layout position for each output. This is done in recent versions
* of qxl and allows displays to be aligned on the guest in the same order as
* they are aligned on the client.
*/
static gboolean
make_suggested_config (MetaMonitorConfig *self,
MetaOutput *outputs,
unsigned n_outputs,
int max_width,
int max_height,
MetaConfiguration *config)
{
unsigned int i;
MetaOutput *primary;
GList *region = NULL;
g_return_val_if_fail (config != NULL, FALSE);
primary = find_primary_output (outputs, n_outputs);
for (i = 0; i < n_outputs; i++)
{
gboolean is_primary = (&outputs[i] == primary);
if (outputs[i].suggested_x < 0 || outputs[i].suggested_y < 0)
return FALSE;
init_config_from_preferred_mode (&config->outputs[i], &outputs[i]);
config->outputs[i].is_primary = is_primary;
config->outputs[i].rect.x = outputs[i].suggested_x;
config->outputs[i].rect.y = outputs[i].suggested_y;
/* Reject the configuration if the suggested positions result in
* overlapping displays */
if (meta_rectangle_overlaps_with_region (region, &config->outputs[i].rect))
{
g_warning ("Overlapping outputs, rejecting suggested configuration");
g_list_free (region);
return FALSE;
}
region = g_list_prepend (region, &config->outputs[i].rect);
}
g_list_free (region);
return TRUE;
}
static void
make_linear_config (MetaMonitorConfig *self,
MetaOutput *outputs,
unsigned n_outputs,
int max_width,
int max_height,
MetaConfiguration *config)
{
MetaOutput *primary;
unsigned i;
int x;
g_return_if_fail (config != NULL);
primary = find_primary_output (outputs, n_outputs);
x = primary->preferred_mode->width;
for (i = 0; i < n_outputs; i++)
{
gboolean is_primary = (&outputs[i] == primary);
init_config_from_preferred_mode (&config->outputs[i], &outputs[i]);
config->outputs[i].is_primary = is_primary;
if (is_primary)
{
config->outputs[i].rect.x = 0;
}
else
{
config->outputs[i].rect.x = x;
x += config->outputs[i].rect.width;
}
}
}
/* Search for a configuration that includes one less screen, then add the new
* one as a presentation screen in preferred mode.
*
* XXX: but presentation mode is not implemented in the control-center or in
* mutter core, so let's do extended for now.
*/
static gboolean
extend_stored_config (MetaMonitorConfig *self,
MetaOutput *outputs,
unsigned n_outputs,
int max_width,
int max_height,
MetaConfiguration *config)
{
int x, y;
unsigned i, j;
int x, y;
MetaConfiguration *ret;
MetaOutput *primary;
ret = g_slice_new (MetaConfiguration);
make_config_key (ret, outputs, n_outputs, -1);
ret->outputs = g_new0 (MetaOutputConfig, n_outputs);
/* Special case the simple case: one output, primary at preferred mode,
nothing else to do */
if (n_outputs == 1)
{
ret->outputs[0].enabled = TRUE;
ret->outputs[0].rect.x = 0;
ret->outputs[0].rect.y = 0;
ret->outputs[0].rect.width = outputs[0].preferred_mode->width;
ret->outputs[0].rect.height = outputs[0].preferred_mode->height;
ret->outputs[0].refresh_rate = outputs[0].preferred_mode->refresh_rate;
ret->outputs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[0].is_primary = TRUE;
return ret;
}
/* If we reach this point, this is either the first time mutter runs
on this system ever, or we just hotplugged a new screen.
In the latter case, search for a configuration that includes one
less screen, then add the new one as a presentation screen
in preferred mode.
XXX: but presentation mode is not implemented in the control-center
or in mutter core, so let's do extended for now.
*/
x = 0;
y = 0;
for (i = 0; i < n_outputs; i++)
@@ -1228,80 +1139,69 @@ extend_stored_config (MetaMonitorConfig *self,
{
if (j < i)
{
g_assert (output_key_equal (&config->keys[j], &ref->keys[j]));
config->outputs[j] = ref->outputs[j];
g_assert (output_key_equal (&ret->keys[j], &ref->keys[j]));
ret->outputs[j] = ref->outputs[j];
x = MAX (x, ref->outputs[j].rect.x + ref->outputs[j].rect.width);
y = MAX (y, ref->outputs[j].rect.y + ref->outputs[j].rect.height);
}
else if (j > i)
{
g_assert (output_key_equal (&config->keys[j], &ref->keys[j - 1]));
config->outputs[j] = ref->outputs[j - 1];
g_assert (output_key_equal (&ret->keys[j], &ref->keys[j - 1]));
ret->outputs[j] = ref->outputs[j - 1];
x = MAX (x, ref->outputs[j - 1].rect.x + ref->outputs[j - 1].rect.width);
y = MAX (y, ref->outputs[j - 1].rect.y + ref->outputs[j - 1].rect.height);
}
else
{
init_config_from_preferred_mode (&config->outputs[j], &outputs[0]);
ret->outputs[j].enabled = TRUE;
ret->outputs[j].rect.x = 0;
ret->outputs[j].rect.y = 0;
ret->outputs[j].rect.width = outputs[0].preferred_mode->width;
ret->outputs[j].rect.height = outputs[0].preferred_mode->height;
ret->outputs[j].refresh_rate = outputs[0].preferred_mode->refresh_rate;
ret->outputs[j].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[j].is_primary = FALSE;
ret->outputs[j].is_presentation = FALSE;
}
}
/* Place the new output at the right end of the screen, if it fits,
otherwise below it, otherwise disable it (or apply_configuration will fail) */
if (x + config->outputs[i].rect.width <= max_width)
config->outputs[i].rect.x = x;
else if (y + config->outputs[i].rect.height <= max_height)
config->outputs[i].rect.y = y;
if (x + ret->outputs[i].rect.width <= max_width)
ret->outputs[i].rect.x = x;
else if (y + ret->outputs[i].rect.height <= max_height)
ret->outputs[i].rect.y = y;
else
config->outputs[i].enabled = FALSE;
ret->outputs[i].enabled = FALSE;
return TRUE;
return ret;
}
}
return FALSE;
}
/* No previous configuration found, try with a really default one, which
is one primary that goes first and the rest to the right of it, extended.
*/
primary = find_primary_output (outputs, n_outputs);
static MetaConfiguration *
make_default_config (MetaMonitorConfig *self,
MetaOutput *outputs,
unsigned n_outputs,
int max_width,
int max_height,
gboolean use_stored_config)
{
MetaConfiguration *ret = NULL;
unsigned i;
ret = config_new ();
make_config_key (ret, outputs, n_outputs, -1);
ret->outputs = g_new0 (MetaOutputConfig, n_outputs);
/* Special case the simple case: one output, primary at preferred mode,
nothing else to do */
if (n_outputs == 1)
{
init_config_from_preferred_mode (&ret->outputs[0], &outputs[0]);
ret->outputs[0].is_primary = TRUE;
goto check_limits;
}
if (make_suggested_config (self, outputs, n_outputs, max_width, max_height, ret))
goto check_limits;
if (use_stored_config &&
extend_stored_config (self, outputs, n_outputs, max_width, max_height, ret))
goto check_limits;
make_linear_config (self, outputs, n_outputs, max_width, max_height, ret);
check_limits:
/* Disable outputs that would go beyond framebuffer limits */
x = primary->preferred_mode->width;
for (i = 0; i < n_outputs; i++)
{
if ((ret->outputs[i].rect.x + ret->outputs[i].rect.width > max_width)
|| (ret->outputs[i].rect.y + ret->outputs[i].rect.height > max_height))
ret->outputs[i].enabled = FALSE;
MetaOutput *output = &outputs[i];
ret->outputs[i].enabled = TRUE;
ret->outputs[i].rect.x = (output == primary) ? 0 : x;
ret->outputs[i].rect.y = 0;
ret->outputs[i].rect.width = output->preferred_mode->width;
ret->outputs[i].rect.height = output->preferred_mode->height;
ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[i].is_primary = (output == primary);
/* Disable outputs that would go beyond framebuffer limits */
if (ret->outputs[i].rect.x + ret->outputs[i].rect.width > max_width)
ret->outputs[i].enabled = FALSE;
else if (output != primary)
x += output->preferred_mode->width;
}
return ret;
@@ -1313,7 +1213,7 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
MetaOutput *outputs,
unsigned n_outputs)
{
MetaConfiguration *config;
MetaConfiguration *ret;
MetaOutput *primary;
unsigned i;
@@ -1324,29 +1224,34 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
/* Oh no, we don't! Activate the primary one and disable everything else */
config = config_new ();
make_config_key (config, outputs, n_outputs, -1);
config->outputs = g_new0 (MetaOutputConfig, n_outputs);
ret = g_slice_new (MetaConfiguration);
make_config_key (ret, outputs, n_outputs, -1);
ret->outputs = g_new0 (MetaOutputConfig, n_outputs);
primary = find_primary_output (outputs, n_outputs);
for (i = 0; i < n_outputs; i++)
{
gboolean is_primary = (&outputs[i] == primary);
MetaOutput *output = &outputs[i];
if (is_primary)
if (output == primary)
{
init_config_from_preferred_mode (&config->outputs[i], &outputs[0]);
config->outputs[i].is_primary = TRUE;
ret->outputs[i].enabled = TRUE;
ret->outputs[i].rect.x = 0;
ret->outputs[i].rect.y = 0;
ret->outputs[i].rect.width = output->preferred_mode->width;
ret->outputs[i].rect.height = output->preferred_mode->height;
ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[i].is_primary = TRUE;
}
else
{
config->outputs[i].enabled = FALSE;
ret->outputs[i].enabled = FALSE;
}
}
apply_configuration (self, config, manager);
config_unref (config);
apply_configuration (self, ret, manager, FALSE);
return FALSE;
}
@@ -1357,9 +1262,8 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
MetaOutput *outputs;
MetaConfiguration *default_config;
unsigned n_outputs;
gboolean ok = FALSE;
gboolean ok;
int max_width, max_height;
gboolean use_stored_config;
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
meta_monitor_manager_get_screen_limits (manager, &max_width, &max_height);
@@ -1370,21 +1274,23 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
return;
}
/* if the device has hotplug_mode_update, it's possible that the
* current display configuration does not match a stored configuration.
* Since extend_existing_config() tries to build a configuration that is
* based on a previously-stored configuration, it's quite likely that the
* resulting config will fail. Even if it doesn't fail, it may result in
* an unexpected configuration, so don't attempt to use a stored config
* in this situation. */
use_stored_config = !meta_monitor_manager_has_hotplug_mode_update (manager);
default_config = make_default_config (self, outputs, n_outputs, max_width, max_height, use_stored_config);
default_config = make_default_config (self, outputs, n_outputs, max_width, max_height);
if (default_config != NULL)
{
ok = apply_configuration_with_lid (self, default_config, manager);
config_unref (default_config);
if (self->lid_is_closed &&
multiple_outputs_are_enabled (default_config) &&
laptop_display_is_on (default_config))
{
ok = apply_configuration (self, make_laptop_lid_config (default_config),
manager, FALSE);
config_free (default_config);
}
else
ok = apply_configuration (self, default_config, manager, FALSE);
}
else
ok = FALSE;
if (!ok)
{
@@ -1421,7 +1327,7 @@ meta_monitor_config_update_current (MetaMonitorConfig *self,
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
current = config_new ();
current = g_slice_new (MetaConfiguration);
current->n_outputs = n_outputs;
current->outputs = g_new0 (MetaOutputConfig, n_outputs);
current->keys = g_new0 (MetaOutputKey, n_outputs);
@@ -1434,11 +1340,15 @@ meta_monitor_config_update_current (MetaMonitorConfig *self,
if (self->current && config_equal_full (current, self->current))
{
config_unref (current);
config_free (current);
return;
}
set_current (self, current);
if (self->current && !self->current_is_stored)
config_free (self->current);
self->current = current;
self->current_is_stored = FALSE;
}
void
@@ -1446,17 +1356,7 @@ meta_monitor_config_restore_previous (MetaMonitorConfig *self,
MetaMonitorManager *manager)
{
if (self->previous)
{
/* The user chose to restore the previous configuration. In this
* case, restore the previous configuration. */
MetaConfiguration *prev_config = config_ref (self->previous);
apply_configuration (self, prev_config, manager);
config_unref (prev_config);
/* After this, self->previous contains the rejected configuration.
* Since it was rejected, nuke it. */
g_clear_pointer (&self->previous, (GDestroyNotify) config_unref);
}
apply_configuration (self, self->previous, manager, FALSE);
else
{
if (!meta_monitor_config_apply_stored (self, manager))
@@ -1474,8 +1374,7 @@ turn_off_laptop_display (MetaMonitorConfig *self,
return;
new = make_laptop_lid_config (self->current);
apply_configuration (self, new, manager);
config_unref (new);
apply_configuration (self, new, manager, FALSE);
self->current_is_for_laptop_lid = TRUE;
}
@@ -1634,7 +1533,16 @@ meta_monitor_config_save (MetaMonitorConfig *self)
void
meta_monitor_config_make_persistent (MetaMonitorConfig *self)
{
g_hash_table_replace (self->configs, self->current, config_ref (self->current));
if (self->current_is_stored)
return;
self->current_is_stored = TRUE;
g_hash_table_replace (self->configs, self->current, self->current);
if (self->previous)
config_free (self->previous);
self->previous = NULL;
meta_monitor_config_save (self);
}

View File

@@ -23,7 +23,7 @@
#ifndef META_MONITOR_CONFIG_H
#define META_MONITOR_CONFIG_H
#include "meta-monitor-manager-private.h"
#include "meta-monitor-manager.h"
#define META_TYPE_MONITOR_CONFIG (meta_monitor_config_get_type ())
#define META_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig))

View File

@@ -95,8 +95,6 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
manager->outputs[0].backlight = -1;
manager->outputs[0].backlight_min = 0;
manager->outputs[0].backlight_max = 0;
manager->outputs[0].connector_type = META_CONNECTOR_TYPE_LVDS;
manager->outputs[0].scale = 1;
}
static void

View File

@@ -23,7 +23,7 @@
#ifndef META_MONITOR_MANAGER_DUMMY_H
#define META_MONITOR_MANAGER_DUMMY_H
#include "meta-monitor-manager-private.h"
#include "meta-monitor-manager.h"
#define META_TYPE_MONITOR_MANAGER_DUMMY (meta_monitor_manager_dummy_get_type ())
#define META_MONITOR_MANAGER_DUMMY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_DUMMY, MetaMonitorManagerDummy))

View File

@@ -25,7 +25,7 @@
#include "config.h"
#include "meta-monitor-manager-private.h"
#include "meta-monitor-manager.h"
#include <string.h>
#include <math.h>
@@ -35,7 +35,6 @@
#include <meta/main.h>
#include "util-private.h"
#include <meta/errors.h>
#include "edid.h"
#include "meta-monitor-config.h"
#include "backends/x11/meta-monitor-manager-xrandr.h"
#include "meta-backend-private.h"
@@ -45,18 +44,6 @@ enum {
SIGNALS_LAST
};
/* Array index matches MetaMonitorTransform */
static gfloat transform_matrices[][6] = {
{ 1, 0, 0, 0, 1, 0 }, /* normal */
{ 0, -1, 1, 1, 0, 0 }, /* 90° */
{ -1, 0, 1, 0, -1, 1 }, /* 180° */
{ 0, 1, 0, -1, 0, 1 }, /* 270° */
{ -1, 0, 1, 0, 1, 0 }, /* normal flipped */
{ 0, 1, 0, 1, 0, 0 }, /* 90° flipped */
{ 1, 0, 0, 0, -1, 1 }, /* 180° flipped */
{ 0, -1, 1, -1, 0, 1 }, /* 270° flipped */
};
static int signals[SIGNALS_LAST];
static void meta_monitor_manager_display_config_init (MetaDBusDisplayConfigIface *iface);
@@ -71,6 +58,14 @@ meta_monitor_manager_init (MetaMonitorManager *manager)
{
}
static void
read_current_config (MetaMonitorManager *manager)
{
manager->serial++;
META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager);
}
/*
* make_logical_config:
*
@@ -203,7 +198,7 @@ meta_monitor_manager_constructed (GObject *object)
manager->config = meta_monitor_config_new ();
meta_monitor_manager_read_current_config (manager);
read_current_config (manager);
if (!meta_monitor_config_apply_stored (manager->config, manager))
meta_monitor_config_make_default (manager->config, manager);
@@ -216,7 +211,24 @@ meta_monitor_manager_constructed (GObject *object)
so this is not needed.
*/
if (META_IS_MONITOR_MANAGER_XRANDR (manager))
meta_monitor_manager_read_current_config (manager);
{
MetaOutput *old_outputs;
MetaCRTC *old_crtcs;
MetaMonitorMode *old_modes;
unsigned int n_old_outputs, n_old_modes;
old_outputs = manager->outputs;
n_old_outputs = manager->n_outputs;
old_modes = manager->modes;
n_old_modes = manager->n_modes;
old_crtcs = manager->crtcs;
read_current_config (manager);
meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
g_free (old_crtcs);
}
make_logical_config (manager);
initialize_dbus_interface (manager);
@@ -224,7 +236,7 @@ meta_monitor_manager_constructed (GObject *object)
manager->in_init = FALSE;
}
static void
void
meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
int n_old_outputs)
{
@@ -247,7 +259,7 @@ meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
g_free (old_outputs);
}
static void
void
meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
int n_old_modes)
{
@@ -357,14 +369,11 @@ make_display_name (MetaMonitorManager *manager,
char *vendor_name = NULL;
char *ret;
switch (output->connector_type)
if (g_str_has_prefix (output->name, "LVDS") ||
g_str_has_prefix (output->name, "eDP"))
{
case META_CONNECTOR_TYPE_LVDS:
case META_CONNECTOR_TYPE_eDP:
ret = g_strdup (_("Built-in display"));
goto out;
default:
break;
}
if (output->width_mm > 0 && output->height_mm > 0)
@@ -412,32 +421,6 @@ make_display_name (MetaMonitorManager *manager,
return ret;
}
static const char *
get_connector_type_name (MetaConnectorType connector_type)
{
switch (connector_type)
{
case META_CONNECTOR_TYPE_Unknown: return "Unknown";
case META_CONNECTOR_TYPE_VGA: return "VGA";
case META_CONNECTOR_TYPE_DVII: return "DVII";
case META_CONNECTOR_TYPE_DVID: return "DVID";
case META_CONNECTOR_TYPE_DVIA: return "DVIA";
case META_CONNECTOR_TYPE_Composite: return "Composite";
case META_CONNECTOR_TYPE_SVIDEO: return "SVIDEO";
case META_CONNECTOR_TYPE_LVDS: return "LVDS";
case META_CONNECTOR_TYPE_Component: return "Component";
case META_CONNECTOR_TYPE_9PinDIN: return "9PinDIN";
case META_CONNECTOR_TYPE_DisplayPort: return "DisplayPort";
case META_CONNECTOR_TYPE_HDMIA: return "HDMIA";
case META_CONNECTOR_TYPE_HDMIB: return "HDMIB";
case META_CONNECTOR_TYPE_TV: return "TV";
case META_CONNECTOR_TYPE_eDP: return "eDP";
case META_CONNECTOR_TYPE_VIRTUAL: return "VIRTUAL";
case META_CONNECTOR_TYPE_DSI: return "DSI";
default: g_assert_not_reached ();
}
}
static gboolean
meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
GDBusMethodInvocation *invocation)
@@ -518,8 +501,6 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_new_boolean (output->is_primary));
g_variant_builder_add (&properties, "{sv}", "presentation",
g_variant_new_boolean (output->is_presentation));
g_variant_builder_add (&properties, "{sv}", "connector-type",
g_variant_new_string (get_connector_type_name (output->connector_type)));
edid_file = manager_class->get_edid_file (manager, output);
if (edid_file)
@@ -1107,13 +1088,6 @@ initialize_dbus_interface (MetaMonitorManager *manager)
g_object_unref);
}
/**
* meta_monitor_manager_get:
*
* Accessor for the singleton MetaMonitorManager.
*
* Returns: (transfer none): The only #MetaMonitorManager there is.
*/
MetaMonitorManager *
meta_monitor_manager_get (void)
{
@@ -1188,31 +1162,6 @@ meta_monitor_manager_get_screen_limits (MetaMonitorManager *manager,
*height = manager->max_screen_height;
}
void
meta_monitor_manager_read_current_config (MetaMonitorManager *manager)
{
MetaOutput *old_outputs;
MetaCRTC *old_crtcs;
MetaMonitorMode *old_modes;
unsigned int n_old_outputs, n_old_modes;
/* Some implementations of read_current use the existing information
* we have available, so don't free the old configuration until after
* read_current finishes. */
old_outputs = manager->outputs;
n_old_outputs = manager->n_outputs;
old_modes = manager->modes;
n_old_modes = manager->n_modes;
old_crtcs = manager->crtcs;
manager->serial++;
META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager);
meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
g_free (old_crtcs);
}
void
meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager)
{
@@ -1230,141 +1179,3 @@ meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager)
g_free (old_monitor_infos);
}
void
meta_output_parse_edid (MetaOutput *meta_output,
GBytes *edid)
{
MonitorInfo *parsed_edid;
gsize len;
if (!edid)
goto out;
parsed_edid = decode_edid (g_bytes_get_data (edid, &len));
if (parsed_edid)
{
meta_output->vendor = g_strndup (parsed_edid->manufacturer_code, 4);
if (parsed_edid->dsc_product_name[0])
meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14);
else
meta_output->product = g_strdup_printf ("0x%04x", (unsigned) parsed_edid->product_code);
if (parsed_edid->dsc_serial_number[0])
meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14);
else
meta_output->serial = g_strdup_printf ("0x%08x", parsed_edid->serial_number);
g_free (parsed_edid);
}
out:
if (!meta_output->vendor)
{
meta_output->vendor = g_strdup ("unknown");
meta_output->product = g_strdup ("unknown");
meta_output->serial = g_strdup ("unknown");
}
}
void
meta_monitor_manager_on_hotplug (MetaMonitorManager *manager)
{
gboolean applied_config = FALSE;
/* If the monitor has hotplug_mode_update (which is used by VMs), don't bother
* applying our stored configuration, because it's likely the user just resizing
* the window.
*/
if (!meta_monitor_manager_has_hotplug_mode_update (manager))
{
if (meta_monitor_config_apply_stored (manager->config, manager))
applied_config = TRUE;
}
/* If we haven't applied any configuration, apply the default configuration. */
if (!applied_config)
meta_monitor_config_make_default (manager->config, manager);
}
static gboolean
calculate_viewport_matrix (MetaMonitorManager *manager,
MetaOutput *output,
gfloat viewport[6])
{
gfloat x, y, width, height;
if (!output->crtc)
return FALSE;
x = (float) output->crtc->rect.x / manager->screen_width;
y = (float) output->crtc->rect.y / manager->screen_height;
width = (float) output->crtc->rect.width / manager->screen_width;
height = (float) output->crtc->rect.height / manager->screen_height;
viewport[0] = width;
viewport[1] = 0.0f;
viewport[2] = x;
viewport[3] = 0.0f;
viewport[4] = height;
viewport[5] = y;
return TRUE;
}
static inline void
multiply_matrix (float a[6],
float b[6],
float res[6])
{
res[0] = a[0] * b[0] + a[1] * b[3];
res[1] = a[0] * b[1] + a[1] * b[4];
res[2] = a[0] * b[2] + a[1] * b[5] + a[2];
res[3] = a[3] * b[0] + a[4] * b[3];
res[4] = a[3] * b[1] + a[4] * b[4];
res[5] = a[3] * b[2] + a[4] * b[5] + a[5];
}
gboolean
meta_monitor_manager_get_monitor_matrix (MetaMonitorManager *manager,
MetaOutput *output,
gfloat matrix[6])
{
gfloat viewport[9];
if (!calculate_viewport_matrix (manager, output, viewport))
return FALSE;
multiply_matrix (viewport, transform_matrices[output->crtc->transform],
matrix);
return TRUE;
}
/**
* meta_monitor_manager_get_output_geometry:
* @manager: A #MetaMonitorManager
* @id: A valid #MetaOutput id
*
* Returns: The monitor index or -1 if @id isn't valid or the output
* isn't associated with a logical monitor.
*/
gint
meta_monitor_manager_get_monitor_for_output (MetaMonitorManager *manager,
guint id)
{
MetaOutput *output;
guint i;
g_return_val_if_fail (META_IS_MONITOR_MANAGER (manager), -1);
g_return_val_if_fail (id < manager->n_outputs, -1);
output = &manager->outputs[id];
if (!output || !output->crtc)
return -1;
for (i = 0; i < manager->n_monitor_infos; i++)
if (meta_rectangle_contains_rect (&manager->monitor_infos[i].rect,
&output->crtc->rect))
return i;
return -1;
}

View File

@@ -41,17 +41,18 @@
#include "display-private.h"
#include <meta/screen.h>
#include "stack-tracker.h"
#include <meta/meta-monitor-manager.h>
#include "meta-display-config-shared.h"
#include "meta-dbus-display-config.h"
#include "meta-cursor.h"
typedef struct _MetaMonitorManagerClass MetaMonitorManagerClass;
typedef struct _MetaMonitorManager MetaMonitorManager;
typedef struct _MetaMonitorConfigClass MetaMonitorConfigClass;
typedef struct _MetaMonitorConfig MetaMonitorConfig;
typedef struct _MetaCRTC MetaCRTC;
typedef struct _MetaOutput MetaOutput;
typedef struct _MetaCRTC MetaCRTC;
typedef struct _MetaMonitorMode MetaMonitorMode;
typedef struct _MetaMonitorInfo MetaMonitorInfo;
typedef struct _MetaCRTCInfo MetaCRTCInfo;
@@ -68,27 +69,6 @@ typedef enum {
META_MONITOR_TRANSFORM_FLIPPED_270,
} MetaMonitorTransform;
/* This matches the values in drm_mode.h */
typedef enum {
META_CONNECTOR_TYPE_Unknown = 0,
META_CONNECTOR_TYPE_VGA = 1,
META_CONNECTOR_TYPE_DVII = 2,
META_CONNECTOR_TYPE_DVID = 3,
META_CONNECTOR_TYPE_DVIA = 4,
META_CONNECTOR_TYPE_Composite = 5,
META_CONNECTOR_TYPE_SVIDEO = 6,
META_CONNECTOR_TYPE_LVDS = 7,
META_CONNECTOR_TYPE_Component = 8,
META_CONNECTOR_TYPE_9PinDIN = 9,
META_CONNECTOR_TYPE_DisplayPort = 10,
META_CONNECTOR_TYPE_HDMIA = 11,
META_CONNECTOR_TYPE_HDMIB = 12,
META_CONNECTOR_TYPE_TV = 13,
META_CONNECTOR_TYPE_eDP = 14,
META_CONNECTOR_TYPE_VIRTUAL = 15,
META_CONNECTOR_TYPE_DSI = 16,
} MetaConnectorType;
struct _MetaOutput
{
/* The CRTC driving this output, NULL if the output is not enabled */
@@ -104,8 +84,6 @@ struct _MetaOutput
CoglSubpixelOrder subpixel_order;
int scale;
MetaConnectorType connector_type;
MetaMonitorMode *preferred_mode;
MetaMonitorMode **modes;
unsigned int n_modes;
@@ -138,8 +116,6 @@ struct _MetaOutput
/* get a new preferred mode on hotplug events, to handle dynamic guest resizing */
gboolean hotplug_mode_update;
gint suggested_x;
gint suggested_y;
};
struct _MetaCRTC
@@ -321,6 +297,10 @@ struct _MetaMonitorManagerClass
unsigned short *);
};
GType meta_monitor_manager_get_type (void);
MetaMonitorManager *meta_monitor_manager_get (void);
void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager);
MetaMonitorInfo *meta_monitor_manager_get_monitor_infos (MetaMonitorManager *manager,
@@ -356,19 +336,14 @@ void meta_monitor_manager_apply_configuration (MetaMonitorManager
void meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager,
gboolean ok);
void meta_output_parse_edid (MetaOutput *output,
GBytes *edid);
void meta_crtc_info_free (MetaCRTCInfo *info);
void meta_output_info_free (MetaOutputInfo *info);
void meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
int n_old_outputs);
void meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
int n_old_modes);
gboolean meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager);
void meta_monitor_manager_read_current_config (MetaMonitorManager *manager);
void meta_monitor_manager_on_hotplug (MetaMonitorManager *manager);
gboolean meta_monitor_manager_get_monitor_matrix (MetaMonitorManager *manager,
MetaOutput *output,
gfloat matrix[6]);
/* Returns true if transform causes width and height to be inverted
This is true for the odd transforms in the enum */

View File

@@ -1,32 +0,0 @@
/* -*- 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_BACKEND_NATIVE_PRIVATE_H
#define META_BACKEND_NATIVE_PRIVATE_H
#include "backends/native/meta-barrier-native.h"
MetaBarrierManagerNative *meta_backend_native_get_barrier_manager (MetaBackendNative *native);
#endif /* META_BACKEND_NATIVE_PRIVATE_H */

View File

@@ -24,13 +24,10 @@
#include "config.h"
#include "meta-backend-native.h"
#include "meta-backend-native-private.h"
#include <meta/main.h>
#include <clutter/evdev/clutter-evdev.h>
#include "meta-backend-native.h"
#include "meta-barrier-native.h"
#include "meta-idle-monitor-native.h"
#include "meta-monitor-manager-kms.h"
#include "meta-cursor-renderer-native.h"
@@ -40,8 +37,6 @@ struct _MetaBackendNativePrivate
{
MetaLauncher *launcher;
MetaBarrierManagerNative *barrier_manager;
GSettings *keyboard_settings;
};
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
@@ -54,27 +49,11 @@ meta_backend_native_finalize (GObject *object)
MetaBackendNative *native = META_BACKEND_NATIVE (object);
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
meta_launcher_free (priv->launcher);
g_clear_object (&priv->keyboard_settings);
G_OBJECT_CLASS (meta_backend_native_parent_class)->finalize (object);
}
static void
constrain_to_barriers (ClutterInputDevice *device,
guint32 time,
float *new_x,
float *new_y)
{
MetaBackendNative *native = META_BACKEND_NATIVE (meta_get_backend ());
MetaBackendNativePrivate *priv =
meta_backend_native_get_instance_private (native);
meta_barrier_manager_native_process (priv->barrier_manager,
device,
time,
new_x, new_y);
}
/*
* The pointer constrain code is mostly a rip-off of the XRandR code from Xorg.
* (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder)
@@ -100,7 +79,7 @@ check_all_screen_monitors(MetaMonitorInfo *monitors,
left = monitor->rect.x;
right = left + monitor->rect.width;
top = monitor->rect.y;
bottom = top + monitor->rect.height;
bottom = left + monitor->rect.height;
if ((x >= left) && (x < right) && (y >= top) && (y < bottom))
return TRUE;
@@ -118,25 +97,25 @@ constrain_all_screen_monitors (ClutterInputDevice *device,
{
ClutterPoint current;
unsigned int i;
float cx, cy;
clutter_input_device_get_coords (device, NULL, &current);
cx = current.x;
cy = current.y;
/* if we're trying to escape, clamp to the CRTC we're coming from */
for (i = 0; i < n_monitors; i++)
{
MetaMonitorInfo *monitor = &monitors[i];
int left, right, top, bottom;
float nx, ny;
left = monitor->rect.x;
right = left + monitor->rect.width;
top = monitor->rect.y;
bottom = top + monitor->rect.height;
bottom = left + monitor->rect.height;
if ((cx >= left) && (cx < right) && (cy >= top) && (cy < bottom))
nx = current.x;
ny = current.y;
if ((nx >= left) && (nx < right) && (ny >= top) && (ny < bottom))
{
if (*x < left)
*x = left;
@@ -164,9 +143,6 @@ pointer_constrain_callback (ClutterInputDevice *device,
unsigned int n_monitors;
gboolean ret;
/* Constrain to barriers */
constrain_to_barriers (device, time, new_x, new_y);
monitor_manager = meta_monitor_manager_get ();
monitors = meta_monitor_manager_get_monitor_infos (monitor_manager, &n_monitors);
@@ -179,15 +155,46 @@ pointer_constrain_callback (ClutterInputDevice *device,
constrain_all_screen_monitors(device, monitors, n_monitors, new_x, new_y);
}
static void
set_keyboard_repeat (MetaBackendNative *native)
{
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
gboolean repeat;
unsigned int delay, interval;
repeat = g_settings_get_boolean (priv->keyboard_settings, "repeat");
delay = g_settings_get_uint (priv->keyboard_settings, "delay");
interval = g_settings_get_uint (priv->keyboard_settings, "repeat-interval");
clutter_evdev_set_keyboard_repeat (manager, repeat, delay, interval);
}
static void
keyboard_settings_changed (GSettings *settings,
const char *key,
gpointer data)
{
MetaBackendNative *native = data;
set_keyboard_repeat (native);
}
static void
meta_backend_native_post_init (MetaBackend *backend)
{
MetaBackendNative *native = META_BACKEND_NATIVE (backend);
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
META_BACKEND_CLASS (meta_backend_native_parent_class)->post_init (backend);
clutter_evdev_set_pointer_constrain_callback (manager, pointer_constrain_callback,
NULL, NULL);
priv->keyboard_settings = g_settings_new ("org.gnome.settings-daemon.peripherals.keyboard");
g_signal_connect (priv->keyboard_settings, "changed",
G_CALLBACK (keyboard_settings_changed), native);
set_keyboard_repeat (native);
}
static MetaIdleMonitor *
@@ -295,8 +302,6 @@ meta_backend_native_init (MetaBackendNative *native)
/* We're a display server, so start talking to weston-launch. */
priv->launcher = meta_launcher_new ();
priv->barrier_manager = meta_barrier_manager_native_new ();
}
gboolean
@@ -309,15 +314,6 @@ meta_activate_vt (int vt, GError **error)
return meta_launcher_activate_vt (priv->launcher, vt, error);
}
MetaBarrierManagerNative *
meta_backend_native_get_barrier_manager (MetaBackendNative *native)
{
MetaBackendNativePrivate *priv =
meta_backend_native_get_instance_private (native);
return priv->barrier_manager;
}
/**
* meta_activate_session:
*

View File

@@ -1,744 +0,0 @@
/* -*- 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>
*/
/**
* SECTION:barrier-native
* @Title: MetaBarrierImplNative
* @Short_Description: Pointer barriers implementation for the native backend
*/
#include "config.h"
#include <stdlib.h>
#include <meta/barrier.h>
#include <meta/util.h>
#include "backends/meta-backend-private.h"
#include "backends/meta-barrier-private.h"
#include "backends/native/meta-backend-native.h"
#include "backends/native/meta-backend-native-private.h"
#include "backends/native/meta-barrier-native.h"
struct _MetaBarrierManagerNative
{
GHashTable *barriers;
};
typedef enum {
/* The barrier is active and responsive to pointer motion. */
META_BARRIER_STATE_ACTIVE,
/* An intermediate state after a pointer hit the pointer barrier. */
META_BARRIER_STATE_HIT,
/* The barrier was hit by a pointer and is still within the hit box and
* has not been released.*/
META_BARRIER_STATE_HELD,
/* The pointer was released by the user. If the following motion hits
* the barrier, it will pass through. */
META_BARRIER_STATE_RELEASE,
/* An intermediate state when the pointer has left the barrier. */
META_BARRIER_STATE_LEFT,
} MetaBarrierState;
struct _MetaBarrierImplNativePrivate
{
MetaBarrier *barrier;
MetaBarrierManagerNative *manager;
gboolean is_active;
MetaBarrierState state;
int trigger_serial;
guint32 last_event_time;
MetaBarrierDirection blocked_dir;
};
G_DEFINE_TYPE_WITH_PRIVATE (MetaBarrierImplNative, meta_barrier_impl_native,
META_TYPE_BARRIER_IMPL)
static int
next_serial (void)
{
static int barrier_serial = 1;
barrier_serial++;
/* If it wraps, avoid 0 as it's not a valid serial. */
if (barrier_serial == 0)
barrier_serial++;
return barrier_serial;
}
typedef struct _Vector2
{
float x, y;
} Vector2;
static float
vector2_cross_product (Vector2 a, Vector2 b)
{
return a.x * b.y - a.y * b.x;
}
static Vector2
vector2_add (Vector2 a, Vector2 b)
{
return (Vector2) {
.x = a.x + b.x,
.y = a.y + b.y,
};
}
static Vector2
vector2_subtract (Vector2 a, Vector2 b)
{
return (Vector2) {
.x = a.x - b.x,
.y = a.y - b.y,
};
}
static Vector2
vector2_multiply_constant (float c, Vector2 a)
{
return (Vector2) {
.x = c * a.x,
.y = c * a.y,
};
}
typedef struct _Line2
{
Vector2 a;
Vector2 b;
} Line2;
static gboolean
lines_intersect (Line2 *line1, Line2 *line2, Vector2 *intersection)
{
Vector2 p = line1->a;
Vector2 r = vector2_subtract (line1->b, line1->a);
Vector2 q = line2->a;
Vector2 s = vector2_subtract (line2->b, line2->a);
float rxs;
float sxr;
float t;
float u;
/*
* The line (p, r) and (q, s) intersects where
*
* p + t r = q + u s
*
* Calculate t:
*
* (p + t r) × s = (q + u s) × s
* p × s + t (r × s) = q × s + u (s × s)
* p × s + t (r × s) = q × s
* t (r × s) = q × s - p × s
* t (r × s) = (q - p) × s
* t = ((q - p) × s) / (r × s)
*
* Using the same method, for u we get:
*
* u = ((p - q) × r) / (s × r)
*/
rxs = vector2_cross_product (r, s);
sxr = vector2_cross_product (s, r);
/* If r × s = 0 then the lines are either parallel or collinear. */
if (fabs ( rxs) < DBL_MIN)
return FALSE;
t = vector2_cross_product (vector2_subtract (q, p), s) / rxs;
u = vector2_cross_product (vector2_subtract (p, q), r) / sxr;
/* The lines only intersect if 0 ≤ t ≤ 1 and 0 ≤ u ≤ 1. */
if (t < 0.0 || t > 1.0 || u < 0.0 || u > 1.0)
return FALSE;
*intersection = vector2_add (p, vector2_multiply_constant (t, r));
return TRUE;
}
static gboolean
is_barrier_horizontal (MetaBarrier *barrier)
{
return barrier->priv->y1 == barrier->priv->y2;
}
static gboolean
is_barrier_blocking_directions (MetaBarrier *barrier,
MetaBarrierDirection directions)
{
/* Barriers doesn't block parallel motions. */
if (is_barrier_horizontal (barrier))
{
if ((directions & (META_BARRIER_DIRECTION_POSITIVE_Y |
META_BARRIER_DIRECTION_NEGATIVE_Y)) == 0)
return FALSE;
}
else
{
if ((directions & (META_BARRIER_DIRECTION_POSITIVE_X |
META_BARRIER_DIRECTION_NEGATIVE_X)) == 0)
return FALSE;
}
return (barrier->priv->directions & directions) != directions;
}
static void
dismiss_pointer (MetaBarrierImplNative *self)
{
MetaBarrierImplNativePrivate *priv =
meta_barrier_impl_native_get_instance_private (self);
priv->state = META_BARRIER_STATE_LEFT;
}
static Line2
barrier_to_line (MetaBarrier *barrier)
{
return (Line2) {
.a = (Vector2) {
.x = MIN (barrier->priv->x1, barrier->priv->x2),
.y = MIN (barrier->priv->y1, barrier->priv->y2),
},
.b = (Vector2) {
.x = MAX (barrier->priv->x1, barrier->priv->x2),
.y = MAX (barrier->priv->y1, barrier->priv->y2),
},
};
}
/*
* Calculate the hit box for a held motion. The hit box is a 2 px wide region
* in the opposite direction of every direction the barrier blocks. The purpose
* of this is to allow small movements without receiving a "left" signal. This
* heuristic comes from the X.org pointer barrier implementation.
*/
static Line2
calculate_barrier_hit_box (MetaBarrier *barrier)
{
Line2 hit_box = barrier_to_line (barrier);
if (is_barrier_horizontal (barrier))
{
if (is_barrier_blocking_directions (barrier,
META_BARRIER_DIRECTION_POSITIVE_Y))
hit_box.a.y -= 2.0f;
if (is_barrier_blocking_directions (barrier,
META_BARRIER_DIRECTION_NEGATIVE_Y))
hit_box.b.y += 2.0f;
}
else
{
if (is_barrier_blocking_directions (barrier,
META_BARRIER_DIRECTION_POSITIVE_X))
hit_box.a.x -= 2.0f;
if (is_barrier_blocking_directions (barrier,
META_BARRIER_DIRECTION_NEGATIVE_X))
hit_box.b.x += 2.0f;
}
return hit_box;
}
static gboolean
is_within_box (Line2 box, Vector2 point)
{
return (point.x >= box.a.x && point.x < box.b.x &&
point.y >= box.a.y && point.y < box.b.y);
}
static void
maybe_release_barrier (gpointer key,
gpointer value,
gpointer user_data)
{
MetaBarrierImplNative *self = key;
MetaBarrierImplNativePrivate *priv =
meta_barrier_impl_native_get_instance_private (self);
MetaBarrier *barrier = priv->barrier;
Line2 *motion = user_data;
Line2 hit_box;
if (priv->state != META_BARRIER_STATE_HELD)
return;
/* Release if we end up outside barrier end points. */
if (is_barrier_horizontal (barrier))
{
if (motion->b.x > MAX (barrier->priv->x1, barrier->priv->x2) ||
motion->b.x < MIN (barrier->priv->x1, barrier->priv->x2))
{
dismiss_pointer (self);
return;
}
}
else
{
if (motion->b.y > MAX (barrier->priv->y1, barrier->priv->y2) ||
motion->b.y < MIN (barrier->priv->y1, barrier->priv->y2))
{
dismiss_pointer (self);
return;
}
}
/* Release if we don't intersect and end up outside of hit box. */
hit_box = calculate_barrier_hit_box (barrier);
if (!is_within_box (hit_box, motion->b))
{
dismiss_pointer (self);
return;
}
}
static void
maybe_release_barriers (MetaBarrierManagerNative *manager,
float prev_x,
float prev_y,
float x,
float y)
{
Line2 motion = {
.a = {
.x = prev_x,
.y = prev_y,
},
.b = {
.x = x,
.y = y,
},
};
g_hash_table_foreach (manager->barriers,
maybe_release_barrier,
&motion);
}
typedef struct _MetaClosestBarrierData
{
struct
{
Line2 motion;
MetaBarrierDirection directions;
} in;
struct
{
float closest_distance_2;
MetaBarrierImplNative *barrier_impl;
} out;
} MetaClosestBarrierData;
static void
update_closest_barrier (gpointer key,
gpointer value,
gpointer user_data)
{
MetaBarrierImplNative *self = key;
MetaBarrierImplNativePrivate *priv =
meta_barrier_impl_native_get_instance_private (self);
MetaBarrier *barrier = priv->barrier;
MetaClosestBarrierData *data = user_data;
Line2 barrier_line;
Vector2 intersection;
float dx, dy;
float distance_2;
/* Ignore if the barrier is not blocking in any of the motions directions. */
if (!is_barrier_blocking_directions (barrier, data->in.directions))
return;
/* Ignore if the barrier released the pointer. */
if (priv->state == META_BARRIER_STATE_RELEASE)
return;
/* Ignore if we are moving away from barrier. */
if (priv->state == META_BARRIER_STATE_HELD &&
(data->in.directions & priv->blocked_dir) == 0)
return;
/* Check if the motion intersects with the barrier, and retrieve the
* intersection point if any. */
barrier_line = (Line2) {
.a = {
.x = barrier->priv->x1,
.y = barrier->priv->y1
},
.b = {
.x = barrier->priv->x2,
.y = barrier->priv->y2
},
};
if (!lines_intersect (&barrier_line, &data->in.motion, &intersection))
return;
/* Calculate the distance to the barrier and keep track of the closest
* barrier. */
dx = intersection.x - data->in.motion.a.x;
dy = intersection.y - data->in.motion.a.y;
distance_2 = dx*dx + dy*dy;
if (data->out.barrier_impl == NULL ||
distance_2 < data->out.closest_distance_2)
{
data->out.barrier_impl = self;
data->out.closest_distance_2 = distance_2;
}
}
static gboolean
get_closest_barrier (MetaBarrierManagerNative *manager,
float prev_x,
float prev_y,
float x,
float y,
MetaBarrierDirection motion_dir,
MetaBarrierImplNative **barrier_impl)
{
MetaClosestBarrierData closest_barrier_data;
closest_barrier_data = (MetaClosestBarrierData) {
.in = {
.motion = {
.a = {
.x = prev_x,
.y = prev_y,
},
.b = {
.x = x,
.y = y,
},
},
.directions = motion_dir,
},
};
g_hash_table_foreach (manager->barriers,
update_closest_barrier,
&closest_barrier_data);
if (closest_barrier_data.out.barrier_impl != NULL)
{
*barrier_impl = closest_barrier_data.out.barrier_impl;
return TRUE;
}
else
{
return FALSE;
}
}
typedef struct _MetaBarrierEventData
{
guint32 time;
float prev_x;
float prev_y;
float x;
float y;
float dx;
float dy;
} MetaBarrierEventData;
static void
emit_barrier_event (MetaBarrierImplNative *self,
guint32 time,
float prev_x,
float prev_y,
float x,
float y,
float dx,
float dy)
{
MetaBarrierImplNativePrivate *priv =
meta_barrier_impl_native_get_instance_private (self);
MetaBarrier *barrier = priv->barrier;
MetaBarrierEvent *event = g_slice_new0 (MetaBarrierEvent);
MetaBarrierState old_state = priv->state;
switch (priv->state)
{
case META_BARRIER_STATE_HIT:
priv->state = META_BARRIER_STATE_HELD;
priv->trigger_serial = next_serial ();
event->dt = 0;
break;
case META_BARRIER_STATE_RELEASE:
case META_BARRIER_STATE_LEFT:
priv->state = META_BARRIER_STATE_ACTIVE;
/* Intentional fall-through. */
case META_BARRIER_STATE_HELD:
event->dt = time - priv->last_event_time;
break;
case META_BARRIER_STATE_ACTIVE:
g_assert_not_reached (); /* Invalid state. */
}
event->ref_count = 1;
event->event_id = priv->trigger_serial;
event->time = time;
event->x = x;
event->y = y;
event->dx = dx;
event->dy = dy;
event->grabbed = priv->state == META_BARRIER_STATE_HELD;
event->released = old_state == META_BARRIER_STATE_RELEASE;
priv->last_event_time = time;
if (priv->state == META_BARRIER_STATE_HELD)
_meta_barrier_emit_hit_signal (barrier, event);
else
_meta_barrier_emit_left_signal (barrier, event);
meta_barrier_event_unref (event);
}
static void
maybe_emit_barrier_event (gpointer key, gpointer value, gpointer user_data)
{
MetaBarrierImplNative *self = key;
MetaBarrierImplNativePrivate *priv =
meta_barrier_impl_native_get_instance_private (self);
MetaBarrierEventData *data = user_data;
switch (priv->state) {
case META_BARRIER_STATE_ACTIVE:
break;
case META_BARRIER_STATE_HIT:
case META_BARRIER_STATE_HELD:
case META_BARRIER_STATE_RELEASE:
case META_BARRIER_STATE_LEFT:
emit_barrier_event (self,
data->time,
data->prev_x,
data->prev_y,
data->x,
data->y,
data->dx,
data->dy);
break;
}
}
/* Clamp (x, y) to the barrier and remove clamped direction from motion_dir. */
static void
clamp_to_barrier (MetaBarrierImplNative *self,
MetaBarrierDirection *motion_dir,
float *x,
float *y)
{
MetaBarrierImplNativePrivate *priv =
meta_barrier_impl_native_get_instance_private (self);
MetaBarrier *barrier = priv->barrier;
if (is_barrier_horizontal (barrier))
{
if (*motion_dir & META_BARRIER_DIRECTION_POSITIVE_Y)
*y = barrier->priv->y1;
else if (*motion_dir & META_BARRIER_DIRECTION_NEGATIVE_Y)
*y = barrier->priv->y1;
priv->blocked_dir = *motion_dir & (META_BARRIER_DIRECTION_POSITIVE_Y |
META_BARRIER_DIRECTION_NEGATIVE_Y);
*motion_dir &= ~(META_BARRIER_DIRECTION_POSITIVE_Y |
META_BARRIER_DIRECTION_NEGATIVE_Y);
}
else
{
if (*motion_dir & META_BARRIER_DIRECTION_POSITIVE_X)
*x = barrier->priv->x1;
else if (*motion_dir & META_BARRIER_DIRECTION_NEGATIVE_X)
*x = barrier->priv->x1;
priv->blocked_dir = *motion_dir & (META_BARRIER_DIRECTION_POSITIVE_X |
META_BARRIER_DIRECTION_NEGATIVE_X);
*motion_dir &= ~(META_BARRIER_DIRECTION_POSITIVE_X |
META_BARRIER_DIRECTION_NEGATIVE_X);
}
priv->state = META_BARRIER_STATE_HIT;
}
void
meta_barrier_manager_native_process (MetaBarrierManagerNative *manager,
ClutterInputDevice *device,
guint32 time,
float *x,
float *y)
{
ClutterPoint prev_pos;
float prev_x;
float prev_y;
float orig_x = *x;
float orig_y = *y;
MetaBarrierDirection motion_dir = 0;
MetaBarrierEventData barrier_event_data;
MetaBarrierImplNative *barrier_impl;
if (!clutter_input_device_get_coords (device, NULL, &prev_pos))
return;
prev_x = prev_pos.x;
prev_y = prev_pos.y;
/* Get the direction of the motion vector. */
if (prev_x < *x)
motion_dir |= META_BARRIER_DIRECTION_POSITIVE_X;
else if (prev_x > *x)
motion_dir |= META_BARRIER_DIRECTION_NEGATIVE_X;
if (prev_y < *y)
motion_dir |= META_BARRIER_DIRECTION_POSITIVE_Y;
else if (prev_y > *y)
motion_dir |= META_BARRIER_DIRECTION_NEGATIVE_Y;
/* Clamp to the closest barrier in any direction until either there are no
* more barriers to clamp to or all directions have been clamped. */
while (motion_dir != 0)
{
if (get_closest_barrier (manager,
prev_x, prev_y,
*x, *y,
motion_dir,
&barrier_impl))
clamp_to_barrier (barrier_impl, &motion_dir, x, y);
else
break;
}
/* Potentially release active barrier movements. */
maybe_release_barriers (manager, prev_x, prev_y, *x, *y);
/* Initiate or continue barrier interaction. */
barrier_event_data = (MetaBarrierEventData) {
.time = time,
.prev_x = prev_x,
.prev_y = prev_y,
.x = *x,
.y = *y,
.dx = orig_x - prev_x,
.dy = orig_y - prev_y,
};
g_hash_table_foreach (manager->barriers,
maybe_emit_barrier_event,
&barrier_event_data);
}
static gboolean
_meta_barrier_impl_native_is_active (MetaBarrierImpl *impl)
{
MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl);
MetaBarrierImplNativePrivate *priv =
meta_barrier_impl_native_get_instance_private (self);
return priv->is_active;
}
static void
_meta_barrier_impl_native_release (MetaBarrierImpl *impl,
MetaBarrierEvent *event)
{
MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl);
MetaBarrierImplNativePrivate *priv =
meta_barrier_impl_native_get_instance_private (self);
if (priv->state == META_BARRIER_STATE_HELD &&
event->event_id == priv->trigger_serial)
priv->state = META_BARRIER_STATE_RELEASE;
}
static void
_meta_barrier_impl_native_destroy (MetaBarrierImpl *impl)
{
MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl);
MetaBarrierImplNativePrivate *priv =
meta_barrier_impl_native_get_instance_private (self);
g_hash_table_remove (priv->manager->barriers, self);
priv->is_active = FALSE;
}
MetaBarrierImpl *
meta_barrier_impl_native_new (MetaBarrier *barrier)
{
MetaBarrierImplNative *self;
MetaBarrierImplNativePrivate *priv;
MetaBackendNative *native;
MetaBarrierManagerNative *manager;
self = g_object_new (META_TYPE_BARRIER_IMPL_NATIVE, NULL);
priv = meta_barrier_impl_native_get_instance_private (self);
priv->barrier = barrier;
priv->is_active = TRUE;
native = META_BACKEND_NATIVE (meta_get_backend ());
manager = meta_backend_native_get_barrier_manager (native);
priv->manager = manager;
g_hash_table_add (manager->barriers, self);
return META_BARRIER_IMPL (self);
}
static void
meta_barrier_impl_native_class_init (MetaBarrierImplNativeClass *klass)
{
MetaBarrierImplClass *impl_class = META_BARRIER_IMPL_CLASS (klass);
impl_class->is_active = _meta_barrier_impl_native_is_active;
impl_class->release = _meta_barrier_impl_native_release;
impl_class->destroy = _meta_barrier_impl_native_destroy;
}
static void
meta_barrier_impl_native_init (MetaBarrierImplNative *self)
{
}
MetaBarrierManagerNative *
meta_barrier_manager_native_new (void)
{
MetaBarrierManagerNative *manager;
manager = g_new0 (MetaBarrierManagerNative, 1);
manager->barriers = g_hash_table_new (NULL, NULL);
return manager;
}

View File

@@ -1,68 +0,0 @@
/* -*- 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_BARRIER_NATIVE_H
#define META_BARRIER_NATIVE_H
#include "backends/meta-barrier-private.h"
G_BEGIN_DECLS
#define META_TYPE_BARRIER_IMPL_NATIVE (meta_barrier_impl_native_get_type ())
#define META_BARRIER_IMPL_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BARRIER_IMPL_NATIVE, MetaBarrierImplNative))
#define META_BARRIER_IMPL_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BARRIER_IMPL_NATIVE, MetaBarrierImplNativeClass))
#define META_IS_BARRIER_IMPL_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BARRIER_IMPL_NATIVE))
#define META_IS_BARRIER_IMPL_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_BARRIER_IMPL_NATIVE))
#define META_BARRIER_IMPL_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_BARRIER_IMPL_NATIVE, MetaBarrierImplNativeClass))
typedef struct _MetaBarrierImplNative MetaBarrierImplNative;
typedef struct _MetaBarrierImplNativeClass MetaBarrierImplNativeClass;
typedef struct _MetaBarrierImplNativePrivate MetaBarrierImplNativePrivate;
typedef struct _MetaBarrierManagerNative MetaBarrierManagerNative;
struct _MetaBarrierImplNative
{
MetaBarrierImpl parent;
};
struct _MetaBarrierImplNativeClass
{
MetaBarrierImplClass parent_class;
};
GType meta_barrier_impl_native_get_type (void) G_GNUC_CONST;
MetaBarrierImpl *meta_barrier_impl_native_new (MetaBarrier *barrier);
MetaBarrierManagerNative *meta_barrier_manager_native_new (void);
void meta_barrier_manager_native_process (MetaBarrierManagerNative *manager,
ClutterInputDevice *device,
guint32 time,
float *x,
float *y);
G_END_DECLS
#endif /* META_BARRIER_NATIVE_H */

View File

@@ -30,7 +30,7 @@
#include <xf86drm.h>
#include "meta-cursor-private.h"
#include "meta-monitor-manager-private.h"
#include "meta-monitor-manager.h"
#ifndef DRM_CAP_CURSOR_WIDTH
#define DRM_CAP_CURSOR_WIDTH 0x8

View File

@@ -1,217 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 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.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#include "config.h"
#include <clutter/evdev/clutter-evdev.h>
#include <libinput.h>
#include "meta-input-settings-native.h"
G_DEFINE_TYPE (MetaInputSettingsNative, meta_input_settings_native, META_TYPE_INPUT_SETTINGS)
static void
meta_input_settings_native_set_send_events (MetaInputSettings *settings,
ClutterInputDevice *device,
GDesktopDeviceSendEvents mode)
{
enum libinput_config_send_events_mode libinput_mode;
struct libinput_device *libinput_device;
switch (mode)
{
case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED:
libinput_mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
break;
case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE:
libinput_mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
break;
case G_DESKTOP_DEVICE_SEND_EVENTS_ENABLED:
libinput_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
break;
default:
g_assert_not_reached ();
}
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
libinput_device_config_send_events_set_mode (libinput_device, libinput_mode);
}
static void
meta_input_settings_native_set_matrix (MetaInputSettings *settings,
ClutterInputDevice *device,
gfloat matrix[6])
{
struct libinput_device *libinput_device;
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
if (libinput_device_config_calibration_has_matrix (libinput_device) > 0)
libinput_device_config_calibration_set_matrix (libinput_device, matrix);
}
static void
meta_input_settings_native_set_speed (MetaInputSettings *settings,
ClutterInputDevice *device,
gdouble speed)
{
struct libinput_device *libinput_device;
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
libinput_device_config_accel_set_speed (libinput_device,
CLAMP (speed, -1, 1));
}
static void
meta_input_settings_native_set_left_handed (MetaInputSettings *settings,
ClutterInputDevice *device,
gboolean enabled)
{
struct libinput_device *libinput_device;
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
if (libinput_device_config_left_handed_is_available (libinput_device))
libinput_device_config_left_handed_set (libinput_device, enabled);
}
static void
meta_input_settings_native_set_tap_enabled (MetaInputSettings *settings,
ClutterInputDevice *device,
gboolean enabled)
{
struct libinput_device *libinput_device;
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
if (libinput_device_config_tap_get_finger_count (libinput_device) > 0)
libinput_device_config_tap_set_enabled (libinput_device,
enabled ?
LIBINPUT_CONFIG_TAP_ENABLED :
LIBINPUT_CONFIG_TAP_DISABLED);
}
static void
meta_input_settings_native_set_invert_scroll (MetaInputSettings *settings,
ClutterInputDevice *device,
gboolean inverted)
{
struct libinput_device *libinput_device;
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
if (libinput_device_config_scroll_has_natural_scroll (libinput_device))
libinput_device_config_scroll_set_natural_scroll_enabled (libinput_device,
inverted);
}
static gboolean
device_set_scroll_method (struct libinput_device *libinput_device,
enum libinput_config_scroll_method method)
{
enum libinput_config_scroll_method supported;
supported = libinput_device_config_scroll_get_methods (libinput_device);
if (method & supported)
libinput_device_config_scroll_set_method (libinput_device, method);
return (method & supported) != 0;
}
static void
meta_input_settings_native_set_scroll_method (MetaInputSettings *settings,
ClutterInputDevice *device,
GDesktopTouchpadScrollMethod mode)
{
enum libinput_config_scroll_method scroll_method = 0;
struct libinput_device *libinput_device;
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
switch (mode)
{
case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_DISABLED:
scroll_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
break;
case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_EDGE_SCROLLING:
scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
break;
case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING:
scroll_method = LIBINPUT_CONFIG_SCROLL_EDGE;
break;
default:
g_assert_not_reached ();
return;
}
device_set_scroll_method (libinput_device, scroll_method);
}
static void
meta_input_settings_native_set_scroll_button (MetaInputSettings *settings,
ClutterInputDevice *device,
guint button)
{
struct libinput_device *libinput_device;
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
if (!device_set_scroll_method (libinput_device,
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN))
return;
libinput_device_config_scroll_set_button (libinput_device, button);
}
static void
meta_input_settings_native_set_keyboard_repeat (MetaInputSettings *settings,
gboolean enabled,
guint delay,
guint interval)
{
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
clutter_evdev_set_keyboard_repeat (manager, enabled, delay, interval);
}
static void
meta_input_settings_native_class_init (MetaInputSettingsNativeClass *klass)
{
MetaInputSettingsClass *input_settings_class = META_INPUT_SETTINGS_CLASS (klass);
input_settings_class->set_send_events = meta_input_settings_native_set_send_events;
input_settings_class->set_matrix = meta_input_settings_native_set_matrix;
input_settings_class->set_speed = meta_input_settings_native_set_speed;
input_settings_class->set_left_handed = meta_input_settings_native_set_left_handed;
input_settings_class->set_tap_enabled = meta_input_settings_native_set_tap_enabled;
input_settings_class->set_invert_scroll = meta_input_settings_native_set_invert_scroll;
input_settings_class->set_scroll_method = meta_input_settings_native_set_scroll_method;
input_settings_class->set_scroll_button = meta_input_settings_native_set_scroll_button;
input_settings_class->set_keyboard_repeat = meta_input_settings_native_set_keyboard_repeat;
}
static void
meta_input_settings_native_init (MetaInputSettingsNative *settings)
{
}

View File

@@ -1,49 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2014 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef META_INPUT_SETTINGS_NATIVE_H
#define META_INPUT_SETTINGS_NATIVE_H
#include "meta-input-settings-private.h"
#define META_TYPE_INPUT_SETTINGS_NATIVE (meta_input_settings_native_get_type ())
#define META_INPUT_SETTINGS_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_INPUT_SETTINGS_NATIVE, MetaInputSettingsNative))
#define META_INPUT_SETTINGS_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_INPUT_SETTINGS_NATIVE, MetaInputSettingsNativeClass))
#define META_IS_INPUT_SETTINGS_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_INPUT_SETTINGS_NATIVE))
#define META_IS_INPUT_SETTINGS_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_INPUT_SETTINGS_NATIVE))
#define META_INPUT_SETTINGS_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_INPUT_SETTINGS_NATIVE, MetaInputSettingsNativeClass))
typedef struct _MetaInputSettingsNative MetaInputSettingsNative;
typedef struct _MetaInputSettingsNativeClass MetaInputSettingsNativeClass;
struct _MetaInputSettingsNative
{
MetaInputSettings parent_instance;
};
struct _MetaInputSettingsNativeClass
{
MetaInputSettingsClass parent_class;
};
GType meta_input_settings_native_get_type (void) G_GNUC_CONST;
#endif /* META_INPUT_SETTINGS_NATIVE_H */

View File

@@ -307,7 +307,7 @@ get_kms_fd (Login1Session *session_proxy,
MetaLauncher *
meta_launcher_new (void)
{
MetaLauncher *self = NULL;
MetaLauncher *self;
Login1Session *session_proxy;
GError *error = NULL;
int kms_fd;
@@ -317,14 +317,14 @@ meta_launcher_new (void)
{
g_warning ("Could not take control: %s", error->message);
g_error_free (error);
goto out;
return NULL;
}
if (!get_kms_fd (session_proxy, &kms_fd))
goto out;
return NULL;
self = g_slice_new0 (MetaLauncher);
self->session_proxy = g_object_ref (session_proxy);
self->session_proxy = session_proxy;
self->seat_proxy = get_seat_proxy (NULL);
self->session_active = TRUE;
@@ -336,9 +336,6 @@ meta_launcher_new (void)
g_signal_connect (self->session_proxy, "notify::active", G_CALLBACK (on_active_changed), self);
out:
g_object_unref (session_proxy);
return self;
}

View File

@@ -24,7 +24,6 @@
#include "config.h"
#include "meta-monitor-manager-kms.h"
#include "meta-monitor-config.h"
#include <string.h>
#include <stdlib.h>
@@ -39,8 +38,7 @@
#include <meta/main.h>
#include <meta/errors.h>
#include <gudev/gudev.h>
#include "edid.h"
typedef struct {
drmModeConnector *connector;
@@ -66,9 +64,10 @@ struct _MetaMonitorManagerKms
drmModeConnector **connectors;
unsigned int n_connectors;
GUdevClient *udev;
drmModeEncoder **encoders;
unsigned int n_encoders;
GSettings *desktop_settings;
drmModeEncoder *current_encoder;
};
struct _MetaMonitorManagerKmsClass
@@ -83,9 +82,12 @@ free_resources (MetaMonitorManagerKms *manager_kms)
{
unsigned i;
for (i = 0; i < manager_kms->n_encoders; i++)
drmModeFreeEncoder (manager_kms->encoders[i]);
for (i = 0; i < manager_kms->n_connectors; i++)
drmModeFreeConnector (manager_kms->connectors[i]);
g_free (manager_kms->encoders);
g_free (manager_kms->connectors);
}
@@ -200,7 +202,7 @@ find_properties (MetaMonitorManagerKms *manager_kms,
strcmp (prop->name, "EDID") == 0)
output_kms->edid_blob_id = output_kms->connector->prop_values[i];
drmModeFreeProperty (prop);
drmModeFreeProperty(prop);
}
}
@@ -222,10 +224,8 @@ read_output_edid (MetaMonitorManagerKms *manager_kms,
}
if (edid_blob->length > 0)
{
return g_bytes_new_with_free_func (edid_blob->data, edid_blob->length,
(GDestroyNotify)drmModeFreePropertyBlob, edid_blob);
}
return g_bytes_new_with_free_func (edid_blob->data, edid_blob->length,
(GDestroyNotify)drmModeFreePropertyBlob, edid_blob);
else
{
drmModeFreePropertyBlob (edid_blob);
@@ -263,77 +263,11 @@ find_output_by_id (MetaOutput *outputs,
return NULL;
}
/* The minimum resolution at which we turn on a window-scale of 2 */
#define HIDPI_LIMIT 192
/* The minimum screen height at which we turn on a window-scale of 2;
* below this there just isn't enough vertical real estate for GNOME
* apps to work, and it's better to just be tiny */
#define HIDPI_MIN_HEIGHT 1200
/* From http://en.wikipedia.org/wiki/4K_resolution#Resolutions_of_common_formats */
#define SMALLEST_4K_WIDTH 3656
/* Based on code from gnome-settings-daemon */
static int
compute_scale (MetaOutput *output)
{
int scale = 1;
if (!output->crtc)
goto out;
/* Scaling makes no sense */
if (output->crtc->rect.width < HIDPI_MIN_HEIGHT)
goto out;
/* 4K TV */
if (output->name != NULL && strstr(output->name, "HDMI") != NULL &&
output->crtc->rect.width >= SMALLEST_4K_WIDTH)
goto out;
/* Somebody encoded the aspect ratio (16/9 or 16/10)
* instead of the physical size */
if ((output->width_mm == 160 && output->height_mm == 90) ||
(output->width_mm == 160 && output->height_mm == 100) ||
(output->width_mm == 16 && output->height_mm == 9) ||
(output->width_mm == 16 && output->height_mm == 10))
goto out;
if (output->width_mm > 0 && output->height_mm > 0)
{
double dpi_x, dpi_y;
dpi_x = (double)output->crtc->rect.width / (output->width_mm / 25.4);
dpi_y = (double)output->crtc->rect.height / (output->height_mm / 25.4);
/* We don't completely trust these values so both
must be high, and never pick higher ratio than
2 automatically */
if (dpi_x > HIDPI_LIMIT && dpi_y > HIDPI_LIMIT)
scale = 2;
}
out:
return scale;
}
static int
get_output_scale (MetaMonitorManager *manager,
MetaOutput *output)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
int scale = g_settings_get_uint (manager_kms->desktop_settings, "scaling-factor");
if (scale > 0)
return scale;
else
return compute_scale (output);
}
static void
meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
drmModeRes *resources;
drmModeEncoder **encoders;
GHashTable *modes;
GHashTableIter iter;
drmModeModeInfo *mode;
@@ -369,7 +303,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
connector = drmModeGetConnector (manager_kms->fd, resources->connectors[i]);
manager_kms->connectors[i] = connector;
if (connector && connector->connection == DRM_MODE_CONNECTED)
if (connector->connection == DRM_MODE_CONNECTED)
{
/* Collect all modes for this connector */
for (j = 0; j < (unsigned)connector->count_modes; j++)
@@ -377,9 +311,13 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
}
}
encoders = g_new (drmModeEncoder *, resources->count_encoders);
for (i = 0; i < (unsigned)resources->count_encoders; i++)
encoders[i] = drmModeGetEncoder (manager_kms->fd, resources->encoders[i]);
manager_kms->n_encoders = resources->count_encoders;
manager_kms->encoders = g_new (drmModeEncoder *, manager_kms->n_encoders);
for (i = 0; i < manager_kms->n_encoders; i++)
{
manager_kms->encoders[i] = drmModeGetEncoder (manager_kms->fd,
resources->encoders[i]);
}
manager->n_modes = g_hash_table_size (modes);
manager->modes = g_new0 (MetaMonitorMode, manager->n_modes);
@@ -463,7 +401,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
connector = manager_kms->connectors[i];
meta_output = &manager->outputs[n_actual_outputs];
if (connector && connector->connection == DRM_MODE_CONNECTED)
if (connector->connection == DRM_MODE_CONNECTED)
{
meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms);
meta_output->driver_notify = (GDestroyNotify)meta_output_destroy_notify;
@@ -472,8 +410,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)
{
@@ -512,8 +448,6 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
for (j = 0; j < output_kms->n_encoders; j++)
{
output_kms->encoders[j] = drmModeGetEncoder (manager_kms->fd, connector->encoders[j]);
if (!output_kms->encoders[j])
continue;
/* We only list CRTCs as supported if they are supported by all encoders
for this connectors.
@@ -570,13 +504,29 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
find_properties (manager_kms, output_kms);
edid = read_output_edid (manager_kms, meta_output);
meta_output_parse_edid (meta_output, edid);
g_bytes_unref (edid);
if (edid)
{
MonitorInfo *parsed_edid;
gsize len;
/* MetaConnectorType matches DRM's connector types */
meta_output->connector_type = (MetaConnectorType) connector->connector_type;
parsed_edid = decode_edid (g_bytes_get_data (edid, &len));
if (parsed_edid)
{
meta_output->vendor = g_strndup (parsed_edid->manufacturer_code, 4);
meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14);
meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14);
meta_output->scale = get_output_scale (manager, meta_output);
g_free (parsed_edid);
}
g_bytes_unref (edid);
}
if (!meta_output->vendor)
{
meta_output->vendor = g_strdup ("unknown");
meta_output->product = g_strdup ("unknown");
meta_output->serial = g_strdup ("unknown");
}
/* FIXME: backlight is a very driver specific thing unfortunately,
every DDX does its own thing, and the dumb KMS API does not include it.
@@ -619,10 +569,9 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
for (j = 0; j < output_kms->n_encoders; j++)
{
for (k = 0; k < (unsigned)resources->count_encoders; k++)
for (k = 0; k < manager_kms->n_encoders; k++)
{
if (output_kms->encoders[j] && encoders[k] &&
output_kms->encoders[j]->encoder_id == encoders[k]->encoder_id)
if (output_kms->encoders[j]->encoder_id == manager_kms->encoders[k]->encoder_id)
{
output_kms->encoder_mask |= (1 << k);
break;
@@ -669,10 +618,6 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
}
}
for (i = 0; i < (unsigned)resources->count_encoders; i++)
drmModeFreeEncoder (encoders[i]);
g_free (encoders);
drmModeFreeResources (resources);
}
@@ -948,23 +893,6 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
drmModeCrtcSetGamma (manager_kms->fd, crtc->crtc_id, size, red, green, blue);
}
static void
on_uevent (GUdevClient *client,
const char *action,
GUdevDevice *device,
gpointer user_data)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (user_data);
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
if (!g_udev_device_get_property_as_boolean (device, "HOTPLUG"))
return;
meta_monitor_manager_read_current_config (manager);
meta_monitor_manager_on_hotplug (manager);
}
static void
meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
{
@@ -979,24 +907,6 @@ meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
cogl_renderer = cogl_display_get_renderer (cogl_display);
manager_kms->fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
const char *subsystems[2] = { "drm", NULL };
manager_kms->udev = g_udev_client_new (subsystems);
g_signal_connect (manager_kms->udev, "uevent",
G_CALLBACK (on_uevent), manager_kms);
manager_kms->desktop_settings = g_settings_new ("org.gnome.desktop.interface");
}
static void
meta_monitor_manager_kms_dispose (GObject *object)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (object);
g_clear_object (&manager_kms->udev);
g_clear_object (&manager_kms->desktop_settings);
G_OBJECT_CLASS (meta_monitor_manager_kms_parent_class)->dispose (object);
}
static void
@@ -1015,7 +925,6 @@ meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass)
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = meta_monitor_manager_kms_dispose;
object_class->finalize = meta_monitor_manager_kms_finalize;
manager_class->read_current = meta_monitor_manager_kms_read_current;

View File

@@ -23,7 +23,7 @@
#ifndef META_MONITOR_MANAGER_KMS_H
#define META_MONITOR_MANAGER_KMS_H
#include "meta-monitor-manager-private.h"
#include "meta-monitor-manager.h"
#define META_TYPE_MONITOR_MANAGER_KMS (meta_monitor_manager_kms_get_type ())
#define META_MONITOR_MANAGER_KMS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKms))

View File

@@ -79,15 +79,11 @@ static void
handle_alarm_notify (MetaBackend *backend,
XEvent *event)
{
GHashTableIter iter;
gpointer value;
int i;
g_hash_table_iter_init (&iter, backend->device_monitors);
while (g_hash_table_iter_next (&iter, NULL, &value))
{
MetaIdleMonitor *device_monitor = META_IDLE_MONITOR (value);
meta_idle_monitor_xsync_handle_xevent (device_monitor, (XSyncAlarmNotifyEvent*) event);
}
for (i = 0; i <= backend->device_id_max; i++)
if (backend->device_monitors[i])
meta_idle_monitor_xsync_handle_xevent (backend->device_monitors[i], (XSyncAlarmNotifyEvent*) event);
}
static void
@@ -129,21 +125,6 @@ translate_device_event (MetaBackendX11 *x11,
}
}
static void
translate_crossing_event (MetaBackendX11 *x11,
XIEnterEvent *enter_event)
{
/* Throw out weird events generated by grabs. */
if (enter_event->mode == XINotifyGrab ||
enter_event->mode == XINotifyUngrab)
{
enter_event->event = None;
return;
}
enter_event->event = meta_backend_x11_get_xwindow (x11);
}
/* Clutter makes the assumption that there is only one X window
* per stage, which is a valid assumption to make for a generic
* application toolkit. As such, it will ignore any events sent
@@ -176,10 +157,6 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
case XI_TouchEnd:
translate_device_event (x11, (XIDeviceEvent *) input_event);
break;
case XI_Enter:
case XI_Leave:
translate_crossing_event (x11, (XIEnterEvent *) input_event);
break;
default:
break;
}

View File

@@ -1,216 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014-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:
* Jasper St. Pierre <jstpierre@mecheye.net>
* Jonas Ådahl <jadahl@gmail.com>
*/
/**
* SECTION:barrier-x11
* @Title: MetaBarrierImplX11
* @Short_Description: Pointer barriers implementation for X11
*/
#include "config.h"
#ifdef HAVE_XI23
#include <glib-object.h>
#include <X11/extensions/XInput2.h>
#include <X11/extensions/Xfixes.h>
#include <meta/barrier.h>
#include "backends/x11/meta-barrier-x11.h"
#include "display-private.h"
struct _MetaBarrierImplX11Private
{
MetaBarrier *barrier;
PointerBarrier xbarrier;
};
G_DEFINE_TYPE_WITH_PRIVATE (MetaBarrierImplX11, meta_barrier_impl_x11,
META_TYPE_BARRIER_IMPL)
static gboolean
_meta_barrier_impl_x11_is_active (MetaBarrierImpl *impl)
{
MetaBarrierImplX11 *self = META_BARRIER_IMPL_X11 (impl);
MetaBarrierImplX11Private *priv =
meta_barrier_impl_x11_get_instance_private (self);
return priv->xbarrier != 0;
}
static void
_meta_barrier_impl_x11_release (MetaBarrierImpl *impl,
MetaBarrierEvent *event)
{
MetaBarrierImplX11 *self = META_BARRIER_IMPL_X11 (impl);
MetaBarrierImplX11Private *priv =
meta_barrier_impl_x11_get_instance_private (self);
MetaDisplay *display = priv->barrier->priv->display;
if (META_DISPLAY_HAS_XINPUT_23 (display))
{
XIBarrierReleasePointer (display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
priv->xbarrier, event->event_id);
}
}
static void
_meta_barrier_impl_x11_destroy (MetaBarrierImpl *impl)
{
MetaBarrierImplX11 *self = META_BARRIER_IMPL_X11 (impl);
MetaBarrierImplX11Private *priv =
meta_barrier_impl_x11_get_instance_private (self);
MetaDisplay *display = priv->barrier->priv->display;
Display *dpy;
if (display == NULL)
return;
dpy = display->xdisplay;
if (!meta_barrier_is_active (priv->barrier))
return;
XFixesDestroyPointerBarrier (dpy, priv->xbarrier);
g_hash_table_remove (display->xids, &priv->xbarrier);
priv->xbarrier = 0;
}
MetaBarrierImpl *
meta_barrier_impl_x11_new (MetaBarrier *barrier)
{
MetaBarrierImplX11 *self;
MetaBarrierImplX11Private *priv;
MetaDisplay *display = barrier->priv->display;
Display *dpy;
Window root;
if (display == NULL)
{
g_warning ("A display must be provided when constructing a barrier.");
return NULL;
}
self = g_object_new (META_TYPE_BARRIER_IMPL_X11, NULL);
priv = meta_barrier_impl_x11_get_instance_private (self);
priv->barrier = barrier;
dpy = display->xdisplay;
root = DefaultRootWindow (dpy);
priv->xbarrier = XFixesCreatePointerBarrier (dpy, root,
barrier->priv->x1,
barrier->priv->y1,
barrier->priv->x2,
barrier->priv->y2,
barrier->priv->directions,
0, NULL);
g_hash_table_insert (display->xids, &priv->xbarrier, barrier);
return META_BARRIER_IMPL (self);
}
static void
meta_barrier_fire_xevent (MetaBarrier *barrier,
XIBarrierEvent *xevent)
{
MetaBarrierEvent *event = g_slice_new0 (MetaBarrierEvent);
event->ref_count = 1;
event->event_id = xevent->eventid;
event->time = xevent->time;
event->dt = xevent->dtime;
event->x = xevent->root_x;
event->y = xevent->root_y;
event->dx = xevent->dx;
event->dy = xevent->dy;
event->released = (xevent->flags & XIBarrierPointerReleased) != 0;
event->grabbed = (xevent->flags & XIBarrierDeviceIsGrabbed) != 0;
switch (xevent->evtype)
{
case XI_BarrierHit:
_meta_barrier_emit_hit_signal (barrier, event);
break;
case XI_BarrierLeave:
_meta_barrier_emit_left_signal (barrier, event);
break;
default:
g_assert_not_reached ();
}
meta_barrier_event_unref (event);
}
gboolean
meta_display_process_barrier_xevent (MetaDisplay *display,
XIEvent *event)
{
MetaBarrier *barrier;
XIBarrierEvent *xev;
if (event == NULL)
return FALSE;
switch (event->evtype)
{
case XI_BarrierHit:
case XI_BarrierLeave:
break;
default:
return FALSE;
}
xev = (XIBarrierEvent *) event;
barrier = g_hash_table_lookup (display->xids, &xev->barrier);
if (barrier != NULL)
{
meta_barrier_fire_xevent (barrier, xev);
return TRUE;
}
return FALSE;
}
static void
meta_barrier_impl_x11_class_init (MetaBarrierImplX11Class *klass)
{
MetaBarrierImplClass *impl_class = META_BARRIER_IMPL_CLASS (klass);
impl_class->is_active = _meta_barrier_impl_x11_is_active;
impl_class->release = _meta_barrier_impl_x11_release;
impl_class->destroy = _meta_barrier_impl_x11_destroy;
}
static void
meta_barrier_impl_x11_init (MetaBarrierImplX11 *self)
{
}
#endif /* HAVE_XI23 */

View File

@@ -1,59 +0,0 @@
/* -*- 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_BARRIER_X11_H
#define META_BARRIER_X11_H
#include "backends/meta-barrier-private.h"
G_BEGIN_DECLS
#define META_TYPE_BARRIER_IMPL_X11 (meta_barrier_impl_x11_get_type ())
#define META_BARRIER_IMPL_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BARRIER_IMPL_X11, MetaBarrierImplX11))
#define META_BARRIER_IMPL_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BARRIER_IMPL_X11, MetaBarrierImplX11Class))
#define META_IS_BARRIER_IMPL_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BARRIER_IMPL_X11))
#define META_IS_BARRIER_IMPL_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_BARRIER_IMPL_X11))
#define META_BARRIER_IMPL_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_BARRIER_IMPL_X11, MetaBarrierImplX11Class))
typedef struct _MetaBarrierImplX11 MetaBarrierImplX11;
typedef struct _MetaBarrierImplX11Class MetaBarrierImplX11Class;
typedef struct _MetaBarrierImplX11Private MetaBarrierImplX11Private;
struct _MetaBarrierImplX11
{
MetaBarrierImpl parent;
};
struct _MetaBarrierImplX11Class
{
MetaBarrierImplClass parent_class;
};
GType meta_barrier_impl_x11_get_type (void) G_GNUC_CONST;
MetaBarrierImpl *meta_barrier_impl_x11_new (MetaBarrier *barrier);
G_END_DECLS
#endif /* META_BARRIER_X11_H1 */

View File

@@ -26,8 +26,6 @@
#include "meta-cursor-renderer-x11.h"
#include <X11/extensions/Xfixes.h>
#include "meta-backend-x11.h"
#include "meta-stage.h"

View File

@@ -1,226 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 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.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#include "config.h"
#include "meta-backend-x11.h"
#include "meta-input-settings-x11.h"
#include <gdk/gdkx.h>
#include <X11/Xatom.h>
#include <X11/extensions/XInput2.h>
#include <X11/XKBlib.h>
#include <meta/errors.h>
G_DEFINE_TYPE (MetaInputSettingsX11, meta_input_settings_x11, META_TYPE_INPUT_SETTINGS)
static void
change_property (ClutterInputDevice *device,
const gchar *property,
Atom type,
int format,
void *data,
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;
property_atom = XInternAtom (xdisplay, property, False);
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);
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
meta_input_settings_x11_set_send_events (MetaInputSettings *settings,
ClutterInputDevice *device,
GDesktopDeviceSendEvents mode)
{
guchar values[2] = { 0 }; /* disabled, disabled-on-external-mouse */
switch (mode)
{
case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED:
values[0] = 1;
break;
case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE:
values[1] = 1;
break;
default:
break;
}
change_property (device, "libinput Send Events Mode Enabled",
XA_INTEGER, 8, &values, 2);
}
static void
meta_input_settings_x11_set_matrix (MetaInputSettings *settings,
ClutterInputDevice *device,
gfloat matrix[6])
{
MetaBackend *backend = meta_get_backend ();
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
gfloat full_matrix[9] = { matrix[0], matrix[1], matrix[2],
matrix[3], matrix[4], matrix[5],
0, 0, 1 };
change_property (device, "Coordinate Transformation Matrix",
XInternAtom (xdisplay, "FLOAT", False),
32, &full_matrix, 9);
}
static void
meta_input_settings_x11_set_speed (MetaInputSettings *settings,
ClutterInputDevice *device,
gdouble speed)
{
MetaBackend *backend = meta_get_backend ();
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
gfloat value = speed;
change_property (device, "libinput Accel Speed",
XInternAtom (xdisplay, "FLOAT", False),
32, &value, 1);
}
static void
meta_input_settings_x11_set_left_handed (MetaInputSettings *settings,
ClutterInputDevice *device,
gboolean enabled)
{
guchar value = (enabled) ? 1 : 0;
change_property (device, "libinput Left Handed Enabled",
XA_INTEGER, 8, &value, 1);
}
static void
meta_input_settings_x11_set_tap_enabled (MetaInputSettings *settings,
ClutterInputDevice *device,
gboolean enabled)
{
guchar value = (enabled) ? 1 : 0;
change_property (device, "libinput Tapping Enabled",
XA_INTEGER, 8, &value, 1);
}
static void
meta_input_settings_x11_set_invert_scroll (MetaInputSettings *settings,
ClutterInputDevice *device,
gboolean inverted)
{
guchar value = (inverted) ? 1 : 0;
change_property (device, "libinput Natural Scrolling Enabled",
XA_INTEGER, 8, &value, 1);
}
static void
meta_input_settings_x11_set_scroll_method (MetaInputSettings *settings,
ClutterInputDevice *device,
GDesktopTouchpadScrollMethod mode)
{
guchar values[3] = { 0 }; /* 2fg, edge, button. The last value is unused */
switch (mode)
{
case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_DISABLED:
break;
case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_EDGE_SCROLLING:
values[1] = 1;
break;
case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING:
values[0] = 1;
break;
default:
g_assert_not_reached ();
}
change_property (device, "libinput Scroll Method Enabled",
XA_INTEGER, 8, &values, 3);
}
static void
meta_input_settings_x11_set_scroll_button (MetaInputSettings *settings,
ClutterInputDevice *device,
guint button)
{
change_property (device, "libinput Scroll Method Enabled",
XA_INTEGER, 32, &button, 1);
}
static void
meta_input_settings_x11_set_keyboard_repeat (MetaInputSettings *settings,
gboolean enabled,
guint delay,
guint interval)
{
MetaBackend *backend = meta_get_backend ();
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
if (enabled)
{
XAutoRepeatOn (xdisplay);
XkbSetAutoRepeatRate (xdisplay, XkbUseCoreKbd, delay, interval);
}
else
{
XAutoRepeatOff (xdisplay);
}
}
static void
meta_input_settings_x11_class_init (MetaInputSettingsX11Class *klass)
{
MetaInputSettingsClass *input_settings_class = META_INPUT_SETTINGS_CLASS (klass);
input_settings_class->set_send_events = meta_input_settings_x11_set_send_events;
input_settings_class->set_matrix = meta_input_settings_x11_set_matrix;
input_settings_class->set_speed = meta_input_settings_x11_set_speed;
input_settings_class->set_left_handed = meta_input_settings_x11_set_left_handed;
input_settings_class->set_tap_enabled = meta_input_settings_x11_set_tap_enabled;
input_settings_class->set_invert_scroll = meta_input_settings_x11_set_invert_scroll;
input_settings_class->set_scroll_method = meta_input_settings_x11_set_scroll_method;
input_settings_class->set_scroll_button = meta_input_settings_x11_set_scroll_button;
input_settings_class->set_keyboard_repeat = meta_input_settings_x11_set_keyboard_repeat;
}
static void
meta_input_settings_x11_init (MetaInputSettingsX11 *settings)
{
}

View File

@@ -1,49 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2014 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef META_INPUT_SETTINGS_X11_H
#define META_INPUT_SETTINGS_X11_H
#include "meta-input-settings-private.h"
#define META_TYPE_INPUT_SETTINGS_X11 (meta_input_settings_x11_get_type ())
#define META_INPUT_SETTINGS_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_INPUT_SETTINGS_X11, MetaInputSettingsX11))
#define META_INPUT_SETTINGS_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_INPUT_SETTINGS_X11, MetaInputSettingsX11Class))
#define META_IS_INPUT_SETTINGS_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_INPUT_SETTINGS_X11))
#define META_IS_INPUT_SETTINGS_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_INPUT_SETTINGS_X11))
#define META_INPUT_SETTINGS_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_INPUT_SETTINGS_X11, MetaInputSettingsX11Class))
typedef struct _MetaInputSettingsX11 MetaInputSettingsX11;
typedef struct _MetaInputSettingsX11Class MetaInputSettingsX11Class;
struct _MetaInputSettingsX11
{
MetaInputSettings parent_instance;
};
struct _MetaInputSettingsX11Class
{
MetaInputSettingsClass parent_class;
};
GType meta_input_settings_x11_get_type (void) G_GNUC_CONST;
#endif /* META_INPUT_SETTINGS_X11_H */

View File

@@ -41,6 +41,7 @@
#include "meta-backend-x11.h"
#include <meta/main.h>
#include <meta/errors.h>
#include "edid.h"
#include "meta-monitor-config.h"
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
@@ -56,6 +57,7 @@ struct _MetaMonitorManagerXrandr
Display *xdisplay;
XRRScreenResources *resources;
int time;
int rr_event_base;
int rr_error_base;
};
@@ -138,34 +140,6 @@ meta_monitor_transform_from_xrandr_all (Rotation rotation)
return ret;
}
static gboolean
output_get_integer_property (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output, const char *propname,
gint *value)
{
gboolean exists = FALSE;
Atom atom, actual_type;
int actual_format;
unsigned long nitems, bytes_after;
unsigned char *buffer;
atom = XInternAtom (manager_xrandr->xdisplay, propname, False);
XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
atom,
0, G_MAXLONG, False, False, XA_INTEGER,
&actual_type, &actual_format,
&nitems, &bytes_after, &buffer);
exists = (actual_type == XA_INTEGER && actual_format == 32 && nitems == 1);
if (exists && value != NULL)
*value = ((int*)buffer)[0];
XFree (buffer);
return exists;
}
static gboolean
output_get_property_exists (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output, const char *propname)
@@ -383,175 +357,18 @@ output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
return output_get_property_exists (manager_xrandr, output, "hotplug_mode_update");
}
static gint
output_get_suggested_x (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
{
gint val;
if (output_get_integer_property (manager_xrandr, output, "suggested X", &val))
return val;
return -1;
}
static gint
output_get_suggested_y (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
{
gint val;
if (output_get_integer_property (manager_xrandr, output, "suggested Y", &val))
return val;
return -1;
}
static MetaConnectorType
connector_type_from_atom (MetaMonitorManagerXrandr *manager_xrandr,
Atom atom)
{
Display *xdpy = manager_xrandr->xdisplay;
if (atom == XInternAtom (xdpy, "HDMI", True))
return META_CONNECTOR_TYPE_HDMIA;
if (atom == XInternAtom (xdpy, "VGA", True))
return META_CONNECTOR_TYPE_VGA;
/* Doesn't have a DRM equivalent, but means an internal panel.
* We could pick either LVDS or eDP here. */
if (atom == XInternAtom (xdpy, "Panel", True))
return META_CONNECTOR_TYPE_LVDS;
if (atom == XInternAtom (xdpy, "DVI", True) || atom == XInternAtom (xdpy, "DVI-I", True))
return META_CONNECTOR_TYPE_DVII;
if (atom == XInternAtom (xdpy, "DVI-A", True))
return META_CONNECTOR_TYPE_DVIA;
if (atom == XInternAtom (xdpy, "DVI-D", True))
return META_CONNECTOR_TYPE_DVID;
if (atom == XInternAtom (xdpy, "DisplayPort", True))
return META_CONNECTOR_TYPE_DisplayPort;
if (atom == XInternAtom (xdpy, "TV", True))
return META_CONNECTOR_TYPE_TV;
if (atom == XInternAtom (xdpy, "TV-Composite", True))
return META_CONNECTOR_TYPE_Composite;
if (atom == XInternAtom (xdpy, "TV-SVideo", True))
return META_CONNECTOR_TYPE_SVIDEO;
/* Another set of mismatches. */
if (atom == XInternAtom (xdpy, "TV-SCART", True))
return META_CONNECTOR_TYPE_TV;
if (atom == XInternAtom (xdpy, "TV-C4", True))
return META_CONNECTOR_TYPE_TV;
return META_CONNECTOR_TYPE_Unknown;
}
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;
atom = XInternAtom (manager_xrandr->xdisplay, "ConnectorType", 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)
goto out;
connector_type_atom = ((Atom *) buffer)[0];
ret = connector_type_from_atom (manager_xrandr, connector_type_atom);
out:
meta_XFree (buffer);
return ret;
}
static MetaConnectorType
output_get_connector_type_from_name (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
{
const char *name = output->name;
/* drmmode_display.c, which was copy/pasted across all the FOSS
* xf86-video-* drivers, seems to name its outputs based on the
* connector type, so look for that....
*
* SNA has its own naming scheme, because what else did you expect
* from SNA, but it's not too different, so we can thankfully use
* that with minor changes.
*
* http://cgit.freedesktop.org/xorg/xserver/tree/hw/xfree86/drivers/modesetting/drmmode_display.c#n953
* http://cgit.freedesktop.org/xorg/driver/xf86-video-intel/tree/src/sna/sna_display.c#n3486
*/
if (g_str_has_prefix (name, "DVI"))
return META_CONNECTOR_TYPE_DVII;
if (g_str_has_prefix (name, "LVDS"))
return META_CONNECTOR_TYPE_LVDS;
if (g_str_has_prefix (name, "HDMI"))
return META_CONNECTOR_TYPE_HDMIA;
if (g_str_has_prefix (name, "VGA"))
return META_CONNECTOR_TYPE_VGA;
/* SNA uses DP, not DisplayPort. Test for both. */
if (g_str_has_prefix (name, "DP") || g_str_has_prefix (name, "DisplayPort"))
return META_CONNECTOR_TYPE_DisplayPort;
if (g_str_has_prefix (name, "eDP"))
return META_CONNECTOR_TYPE_eDP;
if (g_str_has_prefix (name, "Virtual"))
return META_CONNECTOR_TYPE_VIRTUAL;
if (g_str_has_prefix (name, "Composite"))
return META_CONNECTOR_TYPE_VGA;
if (g_str_has_prefix (name, "S-video"))
return META_CONNECTOR_TYPE_SVIDEO;
if (g_str_has_prefix (name, "TV"))
return META_CONNECTOR_TYPE_TV;
if (g_str_has_prefix (name, "CTV"))
return META_CONNECTOR_TYPE_Composite;
if (g_str_has_prefix (name, "DSI"))
return META_CONNECTOR_TYPE_DSI;
if (g_str_has_prefix (name, "DIN"))
return META_CONNECTOR_TYPE_9PinDIN;
return META_CONNECTOR_TYPE_Unknown;
}
static MetaConnectorType
output_get_connector_type (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
{
MetaConnectorType ret;
/* The "ConnectorType" property is considered mandatory since RandR 1.3,
* but none of the FOSS drivers support it, because we're a bunch of
* professional software developers.
*
* Try poking it first, without any expectations that it will work.
* If it's not there, we thankfully have other bonghits to try next.
*/
ret = output_get_connector_type_from_prop (manager_xrandr, output);
if (ret != META_CONNECTOR_TYPE_Unknown)
return ret;
/* Fall back to heuristics based on the output name. */
ret = output_get_connector_type_from_name (manager_xrandr, output);
if (ret != META_CONNECTOR_TYPE_Unknown)
return ret;
return META_CONNECTOR_TYPE_Unknown;
}
static char *
get_xmode_name (XRRModeInfo *xmode)
{
int width = xmode->width;
int height = xmode->height;
if (xmode->hSkew != 0)
{
width += 2 * (xmode->hSkew >> 8);
height += 2 * (xmode->hSkew & 0xff);
}
return g_strdup_printf ("%dx%d", width, height);
}
@@ -620,6 +437,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
return;
manager_xrandr->resources = resources;
manager_xrandr->time = resources->configTimestamp;
manager->n_outputs = resources->noutput;
manager->n_crtcs = resources->ncrtc;
manager->n_modes = resources->nmode;
@@ -688,21 +506,45 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
if (output->connection != RR_Disconnected)
{
GBytes *edid;
MonitorInfo *parsed_edid;
meta_output->winsys_id = resources->outputs[i];
meta_output->name = g_strdup (output->name);
edid = read_output_edid (manager_xrandr, meta_output->winsys_id);
meta_output_parse_edid (meta_output, edid);
g_bytes_unref (edid);
if (edid)
{
gsize len;
parsed_edid = decode_edid (g_bytes_get_data (edid, &len));
if (parsed_edid)
{
meta_output->vendor = g_strndup (parsed_edid->manufacturer_code, 4);
if (parsed_edid->dsc_product_name[0])
meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14);
else
meta_output->product = g_strdup_printf ("0x%04x", (unsigned)parsed_edid->product_code);
if (parsed_edid->dsc_serial_number[0])
meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14);
else
meta_output->serial = g_strdup_printf ("0x%08x", parsed_edid->serial_number);
g_free (parsed_edid);
}
g_bytes_unref (edid);
}
if (!meta_output->vendor)
{
meta_output->vendor = g_strdup ("unknown");
meta_output->product = g_strdup ("unknown");
meta_output->serial = g_strdup ("unknown");
}
meta_output->width_mm = output->mm_width;
meta_output->height_mm = output->mm_height;
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
meta_output->hotplug_mode_update = output_get_hotplug_mode_update (manager_xrandr, meta_output);
meta_output->suggested_x = output_get_suggested_x (manager_xrandr, meta_output);
meta_output->suggested_y = output_get_suggested_y (manager_xrandr, meta_output);
meta_output->connector_type = output_get_connector_type (manager_xrandr, meta_output);
meta_output->n_modes = output->nmode;
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
@@ -929,7 +771,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
XRRSetCrtcConfig (manager_xrandr->xdisplay,
manager_xrandr->resources,
(XID)crtc->crtc_id,
CurrentTime,
manager_xrandr->time,
0, 0,
None,
RR_Rotate_0,
@@ -959,7 +801,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
XRRSetCrtcConfig (manager_xrandr->xdisplay,
manager_xrandr->resources,
(XID)crtc->crtc_id,
CurrentTime,
manager_xrandr->time,
0, 0,
None,
RR_Rotate_0,
@@ -1017,7 +859,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
manager_xrandr->resources,
(XID)crtc->crtc_id,
CurrentTime,
manager_xrandr->time,
crtc_info->x, crtc_info->y,
(XID)mode->mode_id,
meta_monitor_transform_to_xrandr (crtc_info->transform),
@@ -1025,7 +867,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
if (ok != Success)
{
meta_warning ("Configuring CRTC %d with mode %d (%d x %d @ %f) at position %d, %d and transform %u failed\n",
meta_warning ("Configuring CRTC %d with mode %d (%d x %d @ %f) at position %d, %d and transfrom %u failed\n",
(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);
@@ -1158,6 +1000,16 @@ meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager,
XRRFreeGamma (gamma);
}
static void
meta_monitor_manager_xrandr_rebuild_derived (MetaMonitorManager *manager)
{
/* This will be a no-op if the change was from our side, as
we already called it in the DBus method handler */
meta_monitor_config_update_current (manager->config, manager);
meta_monitor_manager_rebuild_derived (manager);
}
static void
meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
{
@@ -1217,26 +1069,57 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
XEvent *event)
{
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
gboolean hotplug;
MetaOutput *old_outputs;
MetaCRTC *old_crtcs;
MetaMonitorMode *old_modes;
unsigned int n_old_outputs, n_old_modes;
gboolean new_config;
gboolean applied_config = FALSE;
if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
return FALSE;
XRRUpdateConfiguration (event);
meta_monitor_manager_read_current_config (manager);
/* Save the old structures, so they stay valid during the update */
old_outputs = manager->outputs;
n_old_outputs = manager->n_outputs;
old_modes = manager->modes;
n_old_modes = manager->n_modes;
old_crtcs = manager->crtcs;
hotplug = manager_xrandr->resources->timestamp < manager_xrandr->resources->configTimestamp;
if (hotplug)
manager->serial++;
meta_monitor_manager_xrandr_read_current (manager);
new_config = manager_xrandr->resources->timestamp >= manager_xrandr->resources->configTimestamp;
/* If this is the X server telling us we set a new configuration,
* we can simply short-cut to rebuilding our logical configuration.
*/
if (new_config)
{
/* This is a hotplug event, so go ahead and build a new configuration. */
meta_monitor_manager_on_hotplug (manager);
meta_monitor_manager_xrandr_rebuild_derived (manager);
goto out;
}
else
/* If the monitor has hotplug_mode_update (which is used by VMs), don't bother
* applying our stored configuration, because it's likely the user just resizing
* the window.
*/
if (!meta_monitor_manager_has_hotplug_mode_update (manager))
{
/* Something else changed -- tell the world about it. */
meta_monitor_manager_rebuild_derived (manager);
if (meta_monitor_config_apply_stored (manager->config, manager))
applied_config = TRUE;
}
/* If we haven't applied any configuration, apply the default configuration. */
if (!applied_config)
meta_monitor_config_make_default (manager->config, manager);
out:
meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
g_free (old_crtcs);
return TRUE;
}

View File

@@ -23,7 +23,7 @@
#ifndef META_MONITOR_MANAGER_XRANDR_H
#define META_MONITOR_MANAGER_XRANDR_H
#include "meta-monitor-manager-private.h"
#include "meta-monitor-manager.h"
#define META_TYPE_MONITOR_MANAGER_XRANDR (meta_monitor_manager_xrandr_get_type ())
#define META_MONITOR_MANAGER_XRANDR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandr))

View File

@@ -15,7 +15,8 @@ struct _MetaCompositor
{
MetaDisplay *display;
guint repaint_func_id;
guint pre_paint_func_id;
guint post_paint_func_id;
gint64 server_time_query_time;
gint64 server_time_offset;
@@ -40,6 +41,7 @@ struct _MetaCompositor
MetaPluginManager *plugin_mgr;
gboolean frame_has_updated_xsurfaces;
gboolean have_x11_sync_object;
};
/* Wait 2ms after vblank before starting to draw next frame */

View File

@@ -79,6 +79,7 @@
#include "frame.h"
#include <X11/extensions/shape.h>
#include <X11/extensions/Xcomposite.h>
#include "meta-sync-ring.h"
#include "backends/x11/meta-backend-x11.h"
@@ -125,7 +126,11 @@ meta_switch_workspace_completed (MetaCompositor *compositor)
void
meta_compositor_destroy (MetaCompositor *compositor)
{
clutter_threads_remove_repaint_func (compositor->repaint_func_id);
clutter_threads_remove_repaint_func (compositor->pre_paint_func_id);
clutter_threads_remove_repaint_func (compositor->post_paint_func_id);
if (compositor->have_x11_sync_object)
meta_sync_ring_destroy ();
}
static void
@@ -468,13 +473,11 @@ meta_compositor_manage (MetaCompositor *compositor)
MetaDisplay *display = compositor->display;
Display *xdisplay = display->xdisplay;
MetaScreen *screen = display->screen;
MetaBackend *backend = meta_get_backend ();
meta_screen_set_cm_selection (display->screen);
{
MetaBackend *backend = meta_get_backend ();
compositor->stage = meta_backend_get_stage (backend);
}
compositor->stage = meta_backend_get_stage (backend);
/* We use connect_after() here to accomodate code in GNOME Shell that,
* when benchmarking drawing performance, connects to ::after-paint
@@ -510,7 +513,7 @@ meta_compositor_manage (MetaCompositor *compositor)
compositor->output = screen->composite_overlay_window;
xwin = meta_backend_x11_get_xwindow (META_BACKEND_X11 (meta_get_backend ()));
xwin = meta_backend_x11_get_xwindow (META_BACKEND_X11 (backend));
XReparentWindow (xdisplay, xwin, compositor->output, 0, 0);
@@ -530,6 +533,8 @@ meta_compositor_manage (MetaCompositor *compositor)
* contents until we show the stage.
*/
XMapWindow (xdisplay, compositor->output);
compositor->have_x11_sync_object = meta_sync_ring_init (xdisplay);
}
redirect_windows (display->screen);
@@ -731,6 +736,9 @@ meta_compositor_process_event (MetaCompositor *compositor,
process_damage (compositor, (XDamageNotifyEvent *) event, window);
}
if (compositor->have_x11_sync_object)
meta_sync_ring_handle_event (event);
/* Clutter needs to know about MapNotify events otherwise it will
think the stage is invisible */
if (!meta_is_wayland_compositor () && event->type == MapNotify)
@@ -1044,11 +1052,12 @@ frame_callback (CoglOnscreen *onscreen,
}
}
static void
pre_paint_windows (MetaCompositor *compositor)
static gboolean
meta_pre_paint_func (gpointer data)
{
GList *l;
MetaWindowActor *top_window;
MetaCompositor *compositor = data;
if (compositor->onscreen == NULL)
{
@@ -1060,7 +1069,7 @@ pre_paint_windows (MetaCompositor *compositor)
}
if (compositor->windows == NULL)
return;
return TRUE;
top_window = g_list_last (compositor->windows)->data;
@@ -1077,10 +1086,12 @@ pre_paint_windows (MetaCompositor *compositor)
{
/* We need to make sure that any X drawing that happens before
* the XDamageSubtract() for each window above is visible to
* subsequent GL rendering; the only standardized way to do this
* is EXT_x11_sync_object, which isn't yet widely available. For
* now, we count on details of Xorg and the open source drivers,
* and hope for the best otherwise.
* subsequent GL rendering; the standardized way to do this is
* GL_EXT_X11_sync_object. Since this isn't implemented yet in
* mesa, we also have a path that relies on the implementation
* of the open source drivers.
*
* Anything else, we just hope for the best.
*
* Xorg and open source driver specifics:
*
@@ -1095,17 +1106,28 @@ pre_paint_windows (MetaCompositor *compositor)
* round trip request at this point is sufficient to flush the
* GLX buffers.
*/
XSync (compositor->display->xdisplay, False);
compositor->frame_has_updated_xsurfaces = FALSE;
if (compositor->have_x11_sync_object)
compositor->have_x11_sync_object = meta_sync_ring_insert_wait ();
else
XSync (compositor->display->xdisplay, False);
}
return TRUE;
}
static gboolean
meta_repaint_func (gpointer data)
meta_post_paint_func (gpointer data)
{
MetaCompositor *compositor = data;
pre_paint_windows (compositor);
if (compositor->frame_has_updated_xsurfaces)
{
if (compositor->have_x11_sync_object)
compositor->have_x11_sync_object = meta_sync_ring_after_frame ();
compositor->frame_has_updated_xsurfaces = FALSE;
}
return TRUE;
}
@@ -1140,10 +1162,16 @@ meta_compositor_new (MetaDisplay *display)
G_CALLBACK (on_shadow_factory_changed),
compositor);
compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func,
compositor,
NULL);
compositor->pre_paint_func_id =
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_PRE_PAINT,
meta_pre_paint_func,
compositor,
NULL);
compositor->post_paint_func_id =
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
meta_post_paint_func,
compositor,
NULL);
return compositor;
}

View File

@@ -53,7 +53,7 @@ struct _MetaBackgroundImageCacheClass
struct _MetaBackgroundImage
{
GObject parent_instance;
GFile *file;
char *filename;
MetaBackgroundImageCache *cache;
gboolean in_cache;
gboolean loaded;
@@ -70,7 +70,7 @@ G_DEFINE_TYPE (MetaBackgroundImageCache, meta_background_image_cache, G_TYPE_OBJ
static void
meta_background_image_cache_init (MetaBackgroundImageCache *cache)
{
cache->images = g_hash_table_new (g_file_hash, (GEqualFunc) g_file_equal);
cache->images = g_hash_table_new (g_str_hash, g_str_equal);
}
static void
@@ -124,17 +124,9 @@ load_file (GTask *task,
{
GError *error = NULL;
GdkPixbuf *pixbuf;
GFileInputStream *stream;
stream = g_file_read (image->file, NULL, &error);
if (stream == NULL)
{
g_task_return_error (task, error);
return;
}
pixbuf = gdk_pixbuf_new_from_stream (G_INPUT_STREAM (stream), NULL, &error);
g_object_unref (stream);
pixbuf = gdk_pixbuf_new_from_file (image->filename,
&error);
if (pixbuf == NULL)
{
@@ -164,11 +156,9 @@ file_loaded (GObject *source_object,
if (pixbuf == NULL)
{
char *uri = g_file_get_uri (image->file);
g_warning ("Failed to load background '%s': %s",
uri, error->message);
image->filename, error->message);
g_clear_error (&error);
g_free (uri);
goto out;
}
@@ -205,7 +195,7 @@ out:
/**
* meta_background_image_cache_load:
* @cache: a #MetaBackgroundImageCache
* @file: #GFile to load
* @filename: filename to load
*
* Loads an image to use as a background, or returns a reference to an
* image that is already in the process of loading or loaded. In either
@@ -219,23 +209,23 @@ out:
*/
MetaBackgroundImage *
meta_background_image_cache_load (MetaBackgroundImageCache *cache,
GFile *file)
const char *filename)
{
MetaBackgroundImage *image;
GTask *task;
g_return_val_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache), NULL);
g_return_val_if_fail (file != NULL, NULL);
g_return_val_if_fail (filename != NULL, NULL);
image = g_hash_table_lookup (cache->images, file);
image = g_hash_table_lookup (cache->images, filename);
if (image != NULL)
return g_object_ref (image);
image = g_object_new (META_TYPE_BACKGROUND_IMAGE, NULL);
image->cache = cache;
image->in_cache = TRUE;
image->file = g_object_ref (file);
g_hash_table_insert (cache->images, image->file, image);
image->filename = g_strdup (filename);
g_hash_table_insert (cache->images, image->filename, image);
task = g_task_new (image, NULL, file_loaded, NULL);
@@ -248,25 +238,25 @@ meta_background_image_cache_load (MetaBackgroundImageCache *cache,
/**
* meta_background_image_cache_purge:
* @cache: a #MetaBackgroundImageCache
* @file: file to remove from the cache
* @filename: filename to remove from the cache
*
* Remove an entry from the cache; this would be used if monitoring
* showed that the file changed.
*/
void
meta_background_image_cache_purge (MetaBackgroundImageCache *cache,
GFile *file)
const char *filename)
{
MetaBackgroundImage *image;
g_return_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache));
g_return_if_fail (file != NULL);
g_return_if_fail (filename != NULL);
image = g_hash_table_lookup (cache->images, file);
image = g_hash_table_lookup (cache->images, filename);
if (image == NULL)
return;
g_hash_table_remove (cache->images, image->file);
g_hash_table_remove (cache->images, image->filename);
image->in_cache = FALSE;
}
@@ -283,12 +273,12 @@ meta_background_image_finalize (GObject *object)
MetaBackgroundImage *image = META_BACKGROUND_IMAGE (object);
if (image->in_cache)
g_hash_table_remove (image->cache->images, image->file);
g_hash_table_remove (image->cache->images, image->filename);
if (image->texture)
cogl_object_unref (image->texture);
if (image->file)
g_object_unref (image->file);
if (image->filename)
g_free (image->filename);
G_OBJECT_CLASS (meta_background_image_parent_class)->finalize (object);
}

View File

@@ -50,9 +50,9 @@ struct _MetaBackgroundPrivate
ClutterColor color;
ClutterColor second_color;
GFile *file1;
char *filename1;
MetaBackgroundImage *background_image1;
GFile *file2;
char *filename2;
MetaBackgroundImage *background_image2;
CoglTexture *color_texture;
@@ -71,6 +71,8 @@ enum
G_DEFINE_TYPE (MetaBackground, meta_background, G_TYPE_OBJECT)
static GSList *all_backgrounds = NULL;
static void
free_fbos (MetaBackground *self)
{
@@ -241,28 +243,16 @@ on_background_loaded (MetaBackgroundImage *image,
mark_changed (self);
}
static gboolean
file_equal0 (GFile *file1,
GFile *file2)
{
if (file1 == file2)
return TRUE;
if ((file1 == NULL) || (file2 == NULL))
return FALSE;
return g_file_equal (file1, file2);
}
static void
set_file (MetaBackground *self,
GFile **filep,
MetaBackgroundImage **imagep,
GFile *file)
set_filename (MetaBackground *self,
char **filenamep,
MetaBackgroundImage **imagep,
const char *filename)
{
if (!file_equal0 (*filep, file))
if (g_strcmp0 (filename, *filenamep) != 0)
{
g_clear_object (filep);
g_free (*filenamep);
*filenamep = g_strdup (filename);
if (*imagep)
{
@@ -273,12 +263,10 @@ set_file (MetaBackground *self,
*imagep = NULL;
}
if (file)
if (filename)
{
MetaBackgroundImageCache *cache = meta_background_image_cache_get_default ();
*filep = g_object_ref (file);
*imagep = meta_background_image_cache_load (cache, file);
*imagep = meta_background_image_cache_load (cache, filename);
g_signal_connect (*imagep, "loaded",
G_CALLBACK (on_background_loaded), self);
}
@@ -294,8 +282,8 @@ meta_background_dispose (GObject *object)
free_color_texture (self);
free_wallpaper_texture (self);
set_file (self, &priv->file1, &priv->background_image1, NULL);
set_file (self, &priv->file2, &priv->background_image2, NULL);
set_filename (self, &priv->filename1, &priv->background_image1, NULL);
set_filename (self, &priv->filename2, &priv->background_image2, NULL);
set_screen (self, NULL);
@@ -305,6 +293,8 @@ meta_background_dispose (GObject *object)
static void
meta_background_finalize (GObject *object)
{
all_backgrounds = g_slist_remove (all_backgrounds, object);
G_OBJECT_CLASS (meta_background_parent_class)->finalize (object);
}
@@ -347,6 +337,7 @@ meta_background_init (MetaBackground *self)
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
META_TYPE_BACKGROUND,
MetaBackgroundPrivate);
all_backgrounds = g_slist_prepend (all_backgrounds, self);
}
static void
@@ -881,19 +872,19 @@ meta_background_set_gradient (MetaBackground *self,
}
void
meta_background_set_file (MetaBackground *self,
GFile *file,
GDesktopBackgroundStyle style)
meta_background_set_filename (MetaBackground *self,
const char *filename,
GDesktopBackgroundStyle style)
{
g_return_if_fail (META_IS_BACKGROUND (self));
meta_background_set_blend (self, file, NULL, 0.0, style);
meta_background_set_blend (self, filename, NULL, 0.0, style);
}
void
meta_background_set_blend (MetaBackground *self,
GFile *file1,
GFile *file2,
const char *filename1,
const char *filename2,
double blend_factor,
GDesktopBackgroundStyle style)
{
@@ -904,8 +895,8 @@ meta_background_set_blend (MetaBackground *self,
priv = self->priv;
set_file (self, &priv->file1, &priv->background_image1, file1);
set_file (self, &priv->file2, &priv->background_image2, file2);
set_filename (self, &priv->filename1, &priv->background_image1, filename1);
set_filename (self, &priv->filename2, &priv->background_image2, filename2);
priv->blend_factor = blend_factor;
priv->style = style;
@@ -913,3 +904,12 @@ meta_background_set_blend (MetaBackground *self,
free_wallpaper_texture (self);
mark_changed (self);
}
void
meta_background_refresh_all (void)
{
GSList *l;
for (l = all_backgrounds; l; l = l->next)
mark_changed (l->data);
}

View File

@@ -40,7 +40,7 @@
#include "compositor-private.h"
#include "meta-window-actor-private.h"
#include "meta-monitor-manager-private.h"
#include "meta-monitor-manager.h"
G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);

View File

@@ -31,8 +31,6 @@
#include "wayland/meta-wayland-private.h"
#include "compositor/region-utils.h"
struct _MetaSurfaceActorWaylandPrivate
{
MetaWaylandSurface *surface;
@@ -128,68 +126,12 @@ meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor)
}
void
meta_surface_actor_wayland_sync_state (MetaSurfaceActorWayland *self)
meta_surface_actor_wayland_scale_texture (MetaSurfaceActorWayland *actor)
{
MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
MetaShapedTexture *stex =
meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
double texture_scale;
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (actor));
double output_scale = meta_surface_actor_wayland_get_scale (actor);
/* Given the surface's window type and what output the surface actor has the
* largest region, scale the actor with the determined scale. */
texture_scale = meta_surface_actor_wayland_get_scale (self);
/* Actor scale. */
clutter_actor_set_scale (CLUTTER_ACTOR (stex), texture_scale, texture_scale);
/* Input region */
if (surface->input_region)
{
cairo_region_t *scaled_input_region;
int region_scale;
/* The input region from the Wayland surface is in the Wayland surface
* coordinate space, while the surface actor input region is in the
* physical pixel coordinate space. */
region_scale = (int)(surface->scale * texture_scale);
scaled_input_region = meta_region_scale (surface->input_region,
region_scale);
meta_surface_actor_set_input_region (META_SURFACE_ACTOR (self),
scaled_input_region);
cairo_region_destroy (scaled_input_region);
}
/* Opaque region */
if (surface->opaque_region)
{
cairo_region_t *scaled_opaque_region;
/* The opaque region from the Wayland surface is in Wayland surface
* coordinate space, while the surface actor opaque region is in the
* same coordinate space as the unscaled buffer texture. */
scaled_opaque_region = meta_region_scale (surface->opaque_region,
surface->scale);
meta_surface_actor_set_opaque_region (META_SURFACE_ACTOR (self),
scaled_opaque_region);
cairo_region_destroy (scaled_opaque_region);
}
}
void
meta_surface_actor_wayland_sync_state_recursive (MetaSurfaceActorWayland *self)
{
MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
GList *iter;
meta_surface_actor_wayland_sync_state (self);
for (iter = surface->subsurfaces; iter != NULL; iter = iter->next)
{
MetaWaylandSurface *subsurf = iter->data;
meta_surface_actor_wayland_sync_state_recursive (
META_SURFACE_ACTOR_WAYLAND (subsurf->surface_actor));
}
clutter_actor_set_scale (CLUTTER_ACTOR (stex), output_scale, output_scale);
}
static MetaWindow *

View File

@@ -63,10 +63,7 @@ void meta_surface_actor_wayland_set_texture (MetaSurfaceActorWayland *self,
double meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor);
void meta_surface_actor_wayland_sync_state (MetaSurfaceActorWayland *self);
void meta_surface_actor_wayland_sync_state_recursive (MetaSurfaceActorWayland *self);
void meta_surface_actor_wayland_scale_texture (MetaSurfaceActorWayland *actor);
G_END_DECLS
#endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */

View File

@@ -49,8 +49,6 @@ meta_surface_actor_pick (ClutterActor *actor,
{
MetaSurfaceActor *self = META_SURFACE_ACTOR (actor);
MetaSurfaceActorPrivate *priv = self->priv;
ClutterActorIter iter;
ClutterActor *child;
if (!clutter_actor_should_pick_paint (actor))
return;
@@ -94,11 +92,6 @@ meta_surface_actor_pick (ClutterActor *actor,
cogl_framebuffer_draw_rectangles (fb, pipeline, rectangles, n_rects);
cogl_object_unref (pipeline);
}
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &child))
clutter_actor_paint (child);
}
static void

View File

@@ -0,0 +1,592 @@
/*
* This is based on an original C++ implementation for compiz that
* carries the following copyright notice:
*
*
* Copyright © 2011 NVIDIA Corporation
*
* 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, and that the name of NVIDIA
* Corporation not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. NVIDIA Corporation makes no representations about the
* suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* NVIDIA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*
* Authors: James Jones <jajones@nvidia.com>
*/
#include <string.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <X11/extensions/sync.h>
#include <cogl/cogl.h>
#include <clutter/clutter.h>
#include <meta/util.h>
#include "meta-sync-ring.h"
/* Theory of operation:
*
* We use a ring of NUM_SYNCS fence objects. On each frame we advance
* to the next fence in the ring. For each fence we do:
*
* 1. fence is XSyncTriggerFence()'d and glWaitSync()'d
* 2. NUM_SYNCS / 2 frames later, fence should be triggered
* 3. fence is XSyncResetFence()'d
* 4. NUM_SYNCS / 2 frames later, fence should be reset
* 5. go back to 1 and re-use fence
*
* glClientWaitSync() and XAlarms are used in steps 2 and 4,
* respectively, to double-check the expectections.
*/
#define NUM_SYNCS 10
#define MAX_SYNC_WAIT_TIME (1 * 1000 * 1000 * 1000) /* one sec */
#define MAX_REBOOT_ATTEMPTS 2
typedef enum
{
META_SYNC_STATE_READY,
META_SYNC_STATE_WAITING,
META_SYNC_STATE_DONE,
META_SYNC_STATE_RESET_PENDING,
} MetaSyncState;
typedef struct
{
Display *xdisplay;
XSyncFence xfence;
GLsync gl_x11_sync;
GLsync gpu_fence;
XSyncCounter xcounter;
XSyncAlarm xalarm;
XSyncValue next_counter_value;
MetaSyncState state;
} MetaSync;
typedef struct
{
Display *xdisplay;
int xsync_event_base;
int xsync_error_base;
GHashTable *alarm_to_sync;
MetaSync *syncs_array[NUM_SYNCS];
guint current_sync_idx;
MetaSync *current_sync;
guint warmup_syncs;
guint reboots;
} MetaSyncRing;
static MetaSyncRing meta_sync_ring = { 0 };
static XSyncValue SYNC_VALUE_ZERO;
static XSyncValue SYNC_VALUE_ONE;
static const char* (*meta_gl_get_string) (GLenum name);
static void (*meta_gl_get_integerv) (GLenum pname,
GLint *params);
static const char* (*meta_gl_get_stringi) (GLenum name,
GLuint index);
static void (*meta_gl_delete_sync) (GLsync sync);
static GLenum (*meta_gl_client_wait_sync) (GLsync sync,
GLbitfield flags,
GLuint64 timeout);
static void (*meta_gl_wait_sync) (GLsync sync,
GLbitfield flags,
GLuint64 timeout);
static GLsync (*meta_gl_import_sync) (GLenum external_sync_type,
GLintptr external_sync,
GLbitfield flags);
static GLsync (*meta_gl_fence_sync) (GLenum condition,
GLbitfield flags);
static MetaSyncRing *
meta_sync_ring_get (void)
{
if (meta_sync_ring.reboots > MAX_REBOOT_ATTEMPTS)
return NULL;
return &meta_sync_ring;
}
static gboolean
load_gl_symbol (const char *name,
void **func)
{
*func = cogl_get_proc_address (name);
if (!*func)
{
meta_verbose ("MetaSyncRing: failed to resolve required GL symbol \"%s\"\n", name);
return FALSE;
}
return TRUE;
}
static gboolean
check_gl_extensions (void)
{
ClutterBackend *backend;
CoglContext *cogl_context;
CoglDisplay *cogl_display;
CoglRenderer *cogl_renderer;
backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (backend);
cogl_display = cogl_context_get_display (cogl_context);
cogl_renderer = cogl_display_get_renderer (cogl_display);
switch (cogl_renderer_get_driver (cogl_renderer))
{
case COGL_DRIVER_GL3:
{
int num_extensions, i;
gboolean arb_sync = FALSE;
gboolean x11_sync_object = FALSE;
meta_gl_get_integerv (GL_NUM_EXTENSIONS, &num_extensions);
for (i = 0; i < num_extensions; ++i)
{
const char *ext = meta_gl_get_stringi (GL_EXTENSIONS, i);
if (g_strcmp0 ("GL_ARB_sync", ext) == 0)
arb_sync = TRUE;
else if (g_strcmp0 ("GL_EXT_x11_sync_object", ext) == 0)
x11_sync_object = TRUE;
}
return arb_sync && x11_sync_object;
}
case COGL_DRIVER_GL:
{
const char *extensions = meta_gl_get_string (GL_EXTENSIONS);
return (extensions != NULL &&
strstr (extensions, "GL_ARB_sync") != NULL &&
strstr (extensions, "GL_EXT_x11_sync_object") != NULL);
}
default:
break;
}
return FALSE;
}
static gboolean
load_required_symbols (void)
{
static gboolean success = FALSE;
if (success)
return TRUE;
/* We don't link against libGL directly because cogl may want to
* use something else. This assumes that cogl has been initialized
* and dynamically loaded libGL at this point.
*/
if (!load_gl_symbol ("glGetString", (void **) &meta_gl_get_string))
goto out;
if (!load_gl_symbol ("glGetIntegerv", (void **) &meta_gl_get_integerv))
goto out;
if (!load_gl_symbol ("glGetStringi", (void **) &meta_gl_get_stringi))
goto out;
if (!check_gl_extensions ())
{
meta_verbose ("MetaSyncRing: couldn't find required GL extensions\n");
goto out;
}
if (!load_gl_symbol ("glDeleteSync", (void **) &meta_gl_delete_sync))
goto out;
if (!load_gl_symbol ("glClientWaitSync", (void **) &meta_gl_client_wait_sync))
goto out;
if (!load_gl_symbol ("glWaitSync", (void **) &meta_gl_wait_sync))
goto out;
if (!load_gl_symbol ("glImportSyncEXT", (void **) &meta_gl_import_sync))
goto out;
if (!load_gl_symbol ("glFenceSync", (void **) &meta_gl_fence_sync))
goto out;
success = TRUE;
out:
return success;
}
static void
meta_sync_insert (MetaSync *self)
{
g_return_if_fail (self->state == META_SYNC_STATE_READY);
XSyncTriggerFence (self->xdisplay, self->xfence);
XFlush (self->xdisplay);
meta_gl_wait_sync (self->gl_x11_sync, 0, GL_TIMEOUT_IGNORED);
self->gpu_fence = meta_gl_fence_sync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
self->state = META_SYNC_STATE_WAITING;
}
static GLenum
meta_sync_check_update_finished (MetaSync *self,
GLuint64 timeout)
{
GLenum status = GL_WAIT_FAILED;
switch (self->state)
{
case META_SYNC_STATE_DONE:
status = GL_ALREADY_SIGNALED;
break;
case META_SYNC_STATE_WAITING:
status = meta_gl_client_wait_sync (self->gpu_fence, 0, timeout);
if (status == GL_ALREADY_SIGNALED || status == GL_CONDITION_SATISFIED)
{
self->state = META_SYNC_STATE_DONE;
meta_gl_delete_sync (self->gpu_fence);
self->gpu_fence = 0;
}
break;
default:
break;
}
g_warn_if_fail (status != GL_WAIT_FAILED);
return status;
}
static void
meta_sync_reset (MetaSync *self)
{
XSyncAlarmAttributes attrs;
int overflow;
g_return_if_fail (self->state == META_SYNC_STATE_DONE);
XSyncResetFence (self->xdisplay, self->xfence);
attrs.trigger.wait_value = self->next_counter_value;
XSyncChangeAlarm (self->xdisplay, self->xalarm, XSyncCAValue, &attrs);
XSyncSetCounter (self->xdisplay, self->xcounter, self->next_counter_value);
XSyncValueAdd (&self->next_counter_value,
self->next_counter_value,
SYNC_VALUE_ONE,
&overflow);
self->state = META_SYNC_STATE_RESET_PENDING;
}
static void
meta_sync_handle_event (MetaSync *self,
XSyncAlarmNotifyEvent *event)
{
g_return_if_fail (event->alarm == self->xalarm);
g_return_if_fail (self->state == META_SYNC_STATE_RESET_PENDING);
self->state = META_SYNC_STATE_READY;
}
static MetaSync *
meta_sync_new (Display *xdisplay)
{
MetaSync *self;
XSyncAlarmAttributes attrs;
self = g_malloc0 (sizeof (MetaSync));
self->xdisplay = xdisplay;
self->xfence = XSyncCreateFence (xdisplay, DefaultRootWindow (xdisplay), FALSE);
self->gl_x11_sync = 0;
self->gpu_fence = 0;
self->xcounter = XSyncCreateCounter (xdisplay, SYNC_VALUE_ZERO);
attrs.trigger.counter = self->xcounter;
attrs.trigger.value_type = XSyncAbsolute;
attrs.trigger.wait_value = SYNC_VALUE_ONE;
attrs.trigger.test_type = XSyncPositiveTransition;
attrs.events = TRUE;
self->xalarm = XSyncCreateAlarm (xdisplay,
XSyncCACounter |
XSyncCAValueType |
XSyncCAValue |
XSyncCATestType |
XSyncCAEvents,
&attrs);
XSyncIntToValue (&self->next_counter_value, 1);
self->state = META_SYNC_STATE_READY;
return self;
}
static void
meta_sync_import (MetaSync *self)
{
g_return_if_fail (self->gl_x11_sync == 0);
self->gl_x11_sync = meta_gl_import_sync (GL_SYNC_X11_FENCE_EXT, self->xfence, 0);
}
static Bool
alarm_event_predicate (Display *dpy,
XEvent *event,
XPointer data)
{
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return False;
if (event->type == ring->xsync_event_base + XSyncAlarmNotify)
{
if (((MetaSync *) data)->xalarm == ((XSyncAlarmNotifyEvent *) event)->alarm)
return True;
}
return False;
}
static void
meta_sync_free (MetaSync *self)
{
/* When our assumptions don't hold, something has gone wrong but we
* don't know what, so we reboot the ring. While doing that, we
* trigger fences before deleting them to try to get ourselves out
* of a potentially stuck GPU state.
*/
switch (self->state)
{
case META_SYNC_STATE_WAITING:
meta_gl_delete_sync (self->gpu_fence);
break;
case META_SYNC_STATE_DONE:
/* nothing to do */
break;
case META_SYNC_STATE_RESET_PENDING:
{
XEvent event;
XIfEvent (self->xdisplay, &event, alarm_event_predicate, (XPointer) self);
meta_sync_handle_event (self, (XSyncAlarmNotifyEvent *) &event);
}
/* fall through */
case META_SYNC_STATE_READY:
XSyncTriggerFence (self->xdisplay, self->xfence);
XFlush (self->xdisplay);
break;
default:
break;
}
meta_gl_delete_sync (self->gl_x11_sync);
XSyncDestroyFence (self->xdisplay, self->xfence);
XSyncDestroyCounter (self->xdisplay, self->xcounter);
XSyncDestroyAlarm (self->xdisplay, self->xalarm);
g_free (self);
}
gboolean
meta_sync_ring_init (Display *xdisplay)
{
gint major, minor;
guint i;
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return FALSE;
g_return_val_if_fail (xdisplay != NULL, FALSE);
g_return_val_if_fail (ring->xdisplay == NULL, FALSE);
if (!load_required_symbols ())
return FALSE;
if (!XSyncQueryExtension (xdisplay, &ring->xsync_event_base, &ring->xsync_error_base) ||
!XSyncInitialize (xdisplay, &major, &minor))
return FALSE;
XSyncIntToValue (&SYNC_VALUE_ZERO, 0);
XSyncIntToValue (&SYNC_VALUE_ONE, 1);
ring->xdisplay = xdisplay;
ring->alarm_to_sync = g_hash_table_new (NULL, NULL);
for (i = 0; i < NUM_SYNCS; ++i)
{
MetaSync *sync = meta_sync_new (ring->xdisplay);
ring->syncs_array[i] = sync;
g_hash_table_replace (ring->alarm_to_sync, (gpointer) sync->xalarm, sync);
}
/* Since the connection we create the X fences on isn't the same as
* the one used for the GLX context, we need to XSync() here to
* ensure glImportSync() succeeds. */
XSync (xdisplay, False);
for (i = 0; i < NUM_SYNCS; ++i)
meta_sync_import (ring->syncs_array[i]);
ring->current_sync_idx = 0;
ring->current_sync = ring->syncs_array[0];
ring->warmup_syncs = 0;
return TRUE;
}
void
meta_sync_ring_destroy (void)
{
guint i;
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return;
g_return_if_fail (ring->xdisplay != NULL);
ring->current_sync_idx = 0;
ring->current_sync = NULL;
ring->warmup_syncs = 0;
for (i = 0; i < NUM_SYNCS; ++i)
meta_sync_free (ring->syncs_array[i]);
g_hash_table_destroy (ring->alarm_to_sync);
ring->xsync_event_base = 0;
ring->xsync_error_base = 0;
ring->xdisplay = NULL;
}
static gboolean
meta_sync_ring_reboot (Display *xdisplay)
{
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return FALSE;
meta_sync_ring_destroy ();
ring->reboots += 1;
if (!meta_sync_ring_get ())
{
meta_warning ("MetaSyncRing: Too many reboots -- disabling\n");
return FALSE;
}
return meta_sync_ring_init (xdisplay);
}
gboolean
meta_sync_ring_after_frame (void)
{
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return FALSE;
g_return_val_if_fail (ring->xdisplay != NULL, FALSE);
if (ring->warmup_syncs >= NUM_SYNCS / 2)
{
guint reset_sync_idx = (ring->current_sync_idx + NUM_SYNCS - (NUM_SYNCS / 2)) % NUM_SYNCS;
MetaSync *sync_to_reset = ring->syncs_array[reset_sync_idx];
GLenum status = meta_sync_check_update_finished (sync_to_reset, 0);
if (status == GL_TIMEOUT_EXPIRED)
{
meta_warning ("MetaSyncRing: We should never wait for a sync -- add more syncs?\n");
status = meta_sync_check_update_finished (sync_to_reset, MAX_SYNC_WAIT_TIME);
}
if (status != GL_ALREADY_SIGNALED && status != GL_CONDITION_SATISFIED)
{
meta_warning ("MetaSyncRing: Timed out waiting for sync object.\n");
return meta_sync_ring_reboot (ring->xdisplay);
}
meta_sync_reset (sync_to_reset);
}
else
{
ring->warmup_syncs += 1;
}
ring->current_sync_idx += 1;
ring->current_sync_idx %= NUM_SYNCS;
ring->current_sync = ring->syncs_array[ring->current_sync_idx];
return TRUE;
}
gboolean
meta_sync_ring_insert_wait (void)
{
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return FALSE;
g_return_val_if_fail (ring->xdisplay != NULL, FALSE);
if (ring->current_sync->state != META_SYNC_STATE_READY)
{
meta_warning ("MetaSyncRing: Sync object is not ready -- were events handled properly?\n");
if (!meta_sync_ring_reboot (ring->xdisplay))
return FALSE;
}
meta_sync_insert (ring->current_sync);
return TRUE;
}
void
meta_sync_ring_handle_event (XEvent *xevent)
{
XSyncAlarmNotifyEvent *event;
MetaSync *sync;
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return;
g_return_if_fail (ring->xdisplay != NULL);
if (xevent->type != (ring->xsync_event_base + XSyncAlarmNotify))
return;
event = (XSyncAlarmNotifyEvent *) xevent;
sync = g_hash_table_lookup (ring->alarm_to_sync, (gpointer) event->alarm);
if (sync)
meta_sync_handle_event (sync, event);
}

View File

@@ -0,0 +1,14 @@
#ifndef _META_SYNC_RING_H_
#define _META_SYNC_RING_H_
#include <glib.h>
#include <X11/Xlib.h>
gboolean meta_sync_ring_init (Display *dpy);
void meta_sync_ring_destroy (void);
gboolean meta_sync_ring_after_frame (void);
gboolean meta_sync_ring_insert_wait (void);
void meta_sync_ring_handle_event (XEvent *event);
#endif /* _META_SYNC_RING_H_ */

View File

@@ -27,7 +27,7 @@
#include "meta-window-actor-private.h"
#include "meta-texture-rectangle.h"
#include "region-utils.h"
#include "meta-monitor-manager-private.h"
#include "meta-monitor-manager.h"
#include "meta-cullable.h"
#include "meta-surface-actor.h"

View File

@@ -24,8 +24,8 @@ pkglib_LTLIBRARIES = default.la
# (There is no way to stop libtool generating static libs locally, and we
# cannot do this globally because of libmutter-private.so).
install-exec-hook:
-rm -f $(DESTDIR)$(pkglibdir)/*.a
-rm -f $(DESTDIR)$(pkglibdir)/*.la
-rm $(DESTDIR)$(pkglibdir)/*.a
-rm $(DESTDIR)$(pkglibdir)/*.la
# Since we removed the .la file, 'make uninstall' doesn't work properly,
# since it counts on libtool to remove the .la files, so just kill the

View File

@@ -172,35 +172,6 @@ meta_region_iterator_next (MetaRegionIterator *iter)
}
}
cairo_region_t *
meta_region_scale (cairo_region_t *region, int scale)
{
int n_rects, i;
cairo_rectangle_int_t *rects;
cairo_region_t *scaled_region;
if (scale == 1)
return cairo_region_copy (region);
n_rects = cairo_region_num_rectangles (region);
rects = g_malloc (sizeof(cairo_rectangle_int_t) * n_rects);
for (i = 0; i < n_rects; i++)
{
cairo_region_get_rectangle (region, i, &rects[i]);
rects[i].x *= scale;
rects[i].y *= scale;
rects[i].width *= scale;
rects[i].height *= scale;
}
scaled_region = cairo_region_create_rectangles (rects, n_rects);
g_free (rects);
return scaled_region;
}
static void
add_expanded_rect (MetaRegionBuilder *builder,
int x,

View File

@@ -92,8 +92,6 @@ void meta_region_iterator_init (MetaRegionIterator *iter,
gboolean meta_region_iterator_at_end (MetaRegionIterator *iter);
void meta_region_iterator_next (MetaRegionIterator *iter);
cairo_region_t *meta_region_scale (cairo_region_t *region, int scale);
cairo_region_t *meta_make_border_region (cairo_region_t *region,
int x_amount,
int y_amount,

View File

@@ -10,16 +10,15 @@
#include <glib-object.h>
#include <X11/extensions/XInput2.h>
#include <X11/extensions/Xfixes.h>
#include <meta/util.h>
#include <meta/barrier.h>
#include "backends/native/meta-backend-native.h"
#include "backends/native/meta-barrier-native.h"
#include "backends/x11/meta-backend-x11.h"
#include "backends/x11/meta-barrier-x11.h"
#include "display-private.h"
#include "mutter-enum-types.h"
#include "core.h"
G_DEFINE_TYPE (MetaBarrier, meta_barrier, G_TYPE_OBJECT)
G_DEFINE_TYPE (MetaBarrierImpl, meta_barrier_impl, G_TYPE_OBJECT)
enum {
PROP_0,
@@ -46,6 +45,21 @@ enum {
static guint obj_signals[LAST_SIGNAL];
struct _MetaBarrierPrivate
{
MetaDisplay *display;
int x1;
int y1;
int x2;
int y2;
MetaBarrierDirection directions;
PointerBarrier xbarrier;
};
static void meta_barrier_event_unref (MetaBarrierEvent *event);
static void
meta_barrier_get_property (GObject *object,
@@ -119,11 +133,13 @@ static void
meta_barrier_dispose (GObject *object)
{
MetaBarrier *barrier = META_BARRIER (object);
MetaBarrierPrivate *priv = barrier->priv;
if (meta_barrier_is_active (barrier))
{
meta_bug ("MetaBarrier %p was destroyed while it was still active.",
barrier);
meta_bug ("MetaBarrier wrapper %p for X barrier %ld was destroyed"
" while the X barrier is still active.",
barrier, priv->xbarrier);
}
G_OBJECT_CLASS (meta_barrier_parent_class)->dispose (object);
@@ -132,12 +148,7 @@ meta_barrier_dispose (GObject *object)
gboolean
meta_barrier_is_active (MetaBarrier *barrier)
{
MetaBarrierImpl *impl = barrier->priv->impl;
if (impl)
return META_BARRIER_IMPL_GET_CLASS (impl)->is_active (impl);
else
return FALSE;
return barrier->priv->xbarrier != 0;
}
/**
@@ -154,10 +165,15 @@ void
meta_barrier_release (MetaBarrier *barrier,
MetaBarrierEvent *event)
{
MetaBarrierImpl *impl = barrier->priv->impl;
if (impl)
META_BARRIER_IMPL_GET_CLASS (impl)->release (impl, event);
#ifdef HAVE_XI23
MetaBarrierPrivate *priv = barrier->priv;
if (META_DISPLAY_HAS_XINPUT_23 (priv->display))
{
XIBarrierReleasePointer (priv->display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
priv->xbarrier, event->event_id);
}
#endif /* HAVE_XI23 */
}
static void
@@ -165,26 +181,31 @@ meta_barrier_constructed (GObject *object)
{
MetaBarrier *barrier = META_BARRIER (object);
MetaBarrierPrivate *priv = barrier->priv;
Display *dpy;
Window root;
g_return_if_fail (priv->x1 == priv->x2 || priv->y1 == priv->y2);
#if defined(HAVE_NATIVE_BACKEND)
if (META_IS_BACKEND_NATIVE (meta_get_backend ()))
priv->impl = meta_barrier_impl_native_new (barrier);
#endif
#if defined(HAVE_XI23)
if (META_IS_BACKEND_X11 (meta_get_backend ()) &&
!meta_is_wayland_compositor ())
priv->impl = meta_barrier_impl_x11_new (barrier);
#endif
if (priv->display == NULL)
{
g_warning ("A display must be provided when constructing a barrier.");
return;
}
if (priv->impl == NULL)
g_warning ("Created a non-working barrier");
dpy = priv->display->xdisplay;
root = DefaultRootWindow (dpy);
/* Take a ref that we'll release in destroy() so that the object stays
* alive while active. */
priv->xbarrier = XFixesCreatePointerBarrier (dpy, root,
priv->x1, priv->y1,
priv->x2, priv->y2,
priv->directions, 0, NULL);
/* Take a ref that we'll release when the XID dies inside destroy(),
* so that the object stays alive and doesn't get GC'd. */
g_object_ref (barrier);
g_hash_table_insert (priv->display->xids, &priv->xbarrier, barrier);
G_OBJECT_CLASS (meta_barrier_parent_class)->constructed (object);
}
@@ -285,10 +306,20 @@ meta_barrier_class_init (MetaBarrierClass *klass)
void
meta_barrier_destroy (MetaBarrier *barrier)
{
MetaBarrierImpl *impl = barrier->priv->impl;
MetaBarrierPrivate *priv = barrier->priv;
Display *dpy;
if (impl)
return META_BARRIER_IMPL_GET_CLASS (impl)->destroy (impl);
if (priv->display == NULL)
return;
dpy = priv->display->xdisplay;
if (!meta_barrier_is_active (barrier))
return;
XFixesDestroyPointerBarrier (dpy, priv->xbarrier);
g_hash_table_remove (priv->display->xids, &priv->xbarrier);
priv->xbarrier = 0;
g_object_unref (barrier);
}
@@ -299,32 +330,71 @@ meta_barrier_init (MetaBarrier *barrier)
barrier->priv = G_TYPE_INSTANCE_GET_PRIVATE (barrier, META_TYPE_BARRIER, MetaBarrierPrivate);
}
void
_meta_barrier_emit_hit_signal (MetaBarrier *barrier,
MetaBarrierEvent *event)
{
g_signal_emit (barrier, obj_signals[HIT], 0, event);
}
void
_meta_barrier_emit_left_signal (MetaBarrier *barrier,
MetaBarrierEvent *event)
{
g_signal_emit (barrier, obj_signals[LEFT], 0, event);
}
#ifdef HAVE_XI23
static void
meta_barrier_impl_class_init (MetaBarrierImplClass *klass)
meta_barrier_fire_event (MetaBarrier *barrier,
XIBarrierEvent *xevent)
{
klass->is_active = NULL;
klass->release = NULL;
klass->destroy = NULL;
MetaBarrierEvent *event = g_slice_new0 (MetaBarrierEvent);
event->ref_count = 1;
event->event_id = xevent->eventid;
event->time = xevent->time;
event->dt = xevent->dtime;
event->x = xevent->root_x;
event->y = xevent->root_y;
event->dx = xevent->dx;
event->dy = xevent->dy;
event->released = (xevent->flags & XIBarrierPointerReleased) != 0;
event->grabbed = (xevent->flags & XIBarrierDeviceIsGrabbed) != 0;
switch (xevent->evtype)
{
case XI_BarrierHit:
g_signal_emit (barrier, obj_signals[HIT], 0, event);
break;
case XI_BarrierLeave:
g_signal_emit (barrier, obj_signals[LEFT], 0, event);
break;
default:
g_assert_not_reached ();
}
meta_barrier_event_unref (event);
}
static void
meta_barrier_impl_init (MetaBarrierImpl *impl)
gboolean
meta_display_process_barrier_event (MetaDisplay *display,
XIEvent *event)
{
MetaBarrier *barrier;
XIBarrierEvent *xev;
if (event == NULL)
return FALSE;
switch (event->evtype)
{
case XI_BarrierHit:
case XI_BarrierLeave:
break;
default:
return FALSE;
}
xev = (XIBarrierEvent *) event;
barrier = g_hash_table_lookup (display->xids, &xev->barrier);
if (barrier != NULL)
{
meta_barrier_fire_event (barrier, xev);
return TRUE;
}
return FALSE;
}
#endif /* HAVE_XI23 */
static MetaBarrierEvent *
meta_barrier_event_ref (MetaBarrierEvent *event)
@@ -336,7 +406,7 @@ meta_barrier_event_ref (MetaBarrierEvent *event)
return event;
}
void
static void
meta_barrier_event_unref (MetaBarrierEvent *event)
{
g_return_if_fail (event != NULL);

View File

@@ -328,17 +328,17 @@ setup_constraint_info (ConstraintInfo *info,
info->orig = *orig;
info->current = *new;
if (flags & META_MOVE_RESIZE_MOVE_ACTION && flags & META_MOVE_RESIZE_RESIZE_ACTION)
if (flags & META_IS_MOVE_ACTION && flags & META_IS_RESIZE_ACTION)
info->action_type = ACTION_MOVE_AND_RESIZE;
else if (flags & META_MOVE_RESIZE_RESIZE_ACTION)
else if (flags & META_IS_RESIZE_ACTION)
info->action_type = ACTION_RESIZE;
else if (flags & META_MOVE_RESIZE_MOVE_ACTION)
else if (flags & META_IS_MOVE_ACTION)
info->action_type = ACTION_MOVE;
else
g_error ("BAD, BAD developer! No treat for you! (Fix your calls to "
"meta_window_move_resize_internal()).\n");
info->is_user_action = (flags & META_MOVE_RESIZE_USER_ACTION);
info->is_user_action = (flags & META_IS_USER_ACTION);
info->resize_gravity = resize_gravity;
@@ -1017,7 +1017,6 @@ constrain_aspect_ratio (MetaWindow *window,
double best_width, best_height;
double alt_width, alt_height;
MetaRectangle *start_rect;
MetaRectangle client_rect;
if (priority > PRIORITY_ASPECT_RATIO)
return TRUE;
@@ -1069,18 +1068,15 @@ constrain_aspect_ratio (MetaWindow *window,
fudge = 1;
break;
}
meta_window_frame_rect_to_client_rect (window, &info->current, &client_rect);
constraint_already_satisfied =
client_rect.width - (client_rect.height * minr ) > -minr*fudge &&
client_rect.width - (client_rect.height * maxr ) < maxr*fudge;
info->current.width - (info->current.height * minr ) > -minr*fudge &&
info->current.width - (info->current.height * maxr ) < maxr*fudge;
if (check_only || constraint_already_satisfied)
return constraint_already_satisfied;
/*** Enforce constraint ***/
new_width = client_rect.width;
new_height = client_rect.height;
new_width = info->current.width;
new_height = info->current.height;
switch (info->resize_gravity)
{
@@ -1127,14 +1123,6 @@ constrain_aspect_ratio (MetaWindow *window,
break;
}
{
client_rect.width = new_width;
client_rect.height = new_height;
meta_window_client_rect_to_frame_rect (window, &client_rect, &client_rect);
new_width = client_rect.width;
new_height = client_rect.height;
}
/* Figure out what original rect to pass to meta_rectangle_resize_with_gravity
* See bug 448183
*/

View File

@@ -62,6 +62,87 @@ get_window (Display *xdisplay,
return window;
}
void
meta_core_get (Display *xdisplay,
Window xwindow,
...)
{
va_list args;
MetaCoreGetType request;
MetaDisplay *display = meta_display_for_x_display (xdisplay);
MetaWindow *window = meta_display_lookup_x_window (display, xwindow);
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = window_x11->priv;
va_start (args, xwindow);
request = va_arg (args, MetaCoreGetType);
/* Now, we special-case the first request slightly. Mostly, requests
* for information on windows which have no frame are errors.
* But sometimes we may want to know *whether* a window has a frame.
* In this case, pass the key META_CORE_WINDOW_HAS_FRAME
* as the *first* request, with a pointer to a boolean; if the window
* has no frame, this will be set to False and meta_core_get will
* exit immediately (so the values of any other requests will be
* undefined). Otherwise it will be set to True and meta_core_get will
* continue happily on its way.
*/
if (request != META_CORE_WINDOW_HAS_FRAME &&
(window == NULL || window->frame == NULL))
{
meta_bug ("No such frame window 0x%lx!\n", xwindow);
goto out;
}
while (request != META_CORE_GET_END)
{
gpointer answer = va_arg (args, gpointer);
switch (request)
{
case META_CORE_WINDOW_HAS_FRAME:
*((gboolean*)answer) = window != NULL && window->frame != NULL;
if (!*((gboolean*)answer)) goto out; /* see above */
break;
case META_CORE_GET_CLIENT_WIDTH:
*((gint*)answer) = priv->client_rect.width;
break;
case META_CORE_GET_CLIENT_HEIGHT:
*((gint*)answer) = priv->client_rect.height;
break;
case META_CORE_GET_FRAME_FLAGS:
*((MetaFrameFlags*)answer) = meta_frame_get_flags (window->frame);
break;
case META_CORE_GET_FRAME_TYPE:
*((MetaFrameType*)answer) = meta_window_get_frame_type (window);
break;
case META_CORE_GET_MINI_ICON:
*((GdkPixbuf**)answer) = window->mini_icon;
break;
case META_CORE_GET_ICON:
*((GdkPixbuf**)answer) = window->icon;
break;
case META_CORE_GET_FRAME_RECT:
meta_window_get_frame_rect (window, ((MetaRectangle*)answer));
break;
case META_CORE_GET_THEME_VARIANT:
*((char**)answer) = window->gtk_theme_variant;
break;
default:
meta_warning("Unknown window information request: %d\n", request);
}
request = va_arg (args, MetaCoreGetType);
}
out:
va_end (args);
}
void
meta_core_queue_frame_resize (Display *xdisplay,
Window frame_xwindow)
@@ -80,7 +161,8 @@ lower_window_and_transients (MetaWindow *window,
meta_window_foreach_transient (window, lower_window_and_transients, NULL);
if (meta_prefs_get_raise_on_click ())
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK &&
meta_prefs_get_raise_on_click ())
{
/* Move window to the back of the focusing workspace's MRU list.
* Do extra sanity checks to avoid possible race conditions.
@@ -127,6 +209,37 @@ meta_core_user_lower_and_unfocus (Display *xdisplay,
timestamp);
}
void
meta_core_user_focus (Display *xdisplay,
Window frame_xwindow,
guint32 timestamp)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
meta_window_focus (window, timestamp);
}
void
meta_core_minimize (Display *xdisplay,
Window frame_xwindow)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
meta_window_minimize (window);
}
void
meta_core_maximize (Display *xdisplay,
Window frame_xwindow)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
if (meta_prefs_get_raise_on_click ())
meta_window_raise (window);
meta_window_maximize (window, META_MAXIMIZE_BOTH);
}
void
meta_core_toggle_maximize_vertically (Display *xdisplay,
Window frame_xwindow)
@@ -172,6 +285,84 @@ meta_core_toggle_maximize (Display *xdisplay,
meta_window_maximize (window, META_MAXIMIZE_BOTH);
}
void
meta_core_unmaximize (Display *xdisplay,
Window frame_xwindow)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
if (meta_prefs_get_raise_on_click ())
meta_window_raise (window);
meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
}
void
meta_core_delete (Display *xdisplay,
Window frame_xwindow,
guint32 timestamp)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
meta_window_delete (window, timestamp);
}
void
meta_core_unshade (Display *xdisplay,
Window frame_xwindow,
guint32 timestamp)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
meta_window_unshade (window, timestamp);
}
void
meta_core_shade (Display *xdisplay,
Window frame_xwindow,
guint32 timestamp)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
meta_window_shade (window, timestamp);
}
void
meta_core_unstick (Display *xdisplay,
Window frame_xwindow)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
meta_window_unstick (window);
}
void
meta_core_make_above (Display *xdisplay,
Window frame_xwindow)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
meta_window_make_above (window);
}
void
meta_core_unmake_above (Display *xdisplay,
Window frame_xwindow)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
meta_window_unmake_above (window);
}
void
meta_core_stick (Display *xdisplay,
Window frame_xwindow)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
meta_window_stick (window);
}
void
meta_core_change_workspace (Display *xdisplay,
Window frame_xwindow,
@@ -306,10 +497,3 @@ meta_invalidate_default_icons (void)
{
/* XXX: Actually invalidate the icons when they're used. */
}
void
meta_retheme_all (void)
{
if (meta_get_display ())
meta_display_retheme_all ();
}

View File

@@ -28,6 +28,60 @@
#include <meta/common.h>
#include <meta/boxes.h>
typedef enum
{
META_CORE_GET_END = 0,
META_CORE_WINDOW_HAS_FRAME,
META_CORE_GET_CLIENT_WIDTH,
META_CORE_GET_CLIENT_HEIGHT,
META_CORE_GET_FRAME_FLAGS,
META_CORE_GET_FRAME_TYPE,
META_CORE_GET_MINI_ICON,
META_CORE_GET_ICON,
META_CORE_GET_FRAME_RECT,
META_CORE_GET_THEME_VARIANT,
} MetaCoreGetType;
/* General information function about the given window. Pass in a sequence of
* pairs of MetaCoreGetTypes and pointers to variables; the variables will be
* filled with the requested values. End the list with META_CORE_GET_END.
* For example:
*
* meta_core_get (my_display, my_window,
* META_CORE_GET_FRAME_WIDTH, &width,
* META_CORE_GET_FRAME_HEIGHT, &height,
* META_CORE_GET_END);
*
* If the window doesn't have a frame, this will raise a meta_bug. To suppress
* this behaviour, ask META_CORE_WINDOW_HAS_FRAME as the *first* question in
* the list. If the window has no frame, the answer to this question will be
* False, and anything else you asked will be undefined. Otherwise, the answer
* will be True. The answer will necessarily be True if you ask the question
* in any other position. The positions of all other questions don't matter.
*
* The reason for this function is that some parts of the program don't know
* about MetaWindows. But they *can* see core.h. So we used to have a whole
* load of functions which took a display and an X window, looked up the
* relevant MetaWindow, and returned information about it. The trouble with
* that is that looking up the MetaWindow is a nontrivial operation, and
* consolidating the calls in this way makes (for example) frame exposes
* 33% faster, according to valgrind.
*
* This function would perhaps be slightly better if the questions were
* represented by pointers, perhaps gchar*s, because then we could take
* advantage of gcc's automatic sentinel checking. On the other hand, this
* immediately suggests string comparison, and that's slow.
*
* Another possible improvement is that core.h still has a bunch of
* functions which can't be described by the formula "give a display and
* an X window, get a single value" (meta_core_user_move, for example), but
* which could theoretically be handled by this function if we relaxed the
* requirement that all questions should have exactly one argument.
*/
void meta_core_get (Display *xdisplay,
Window window,
...);
void meta_core_queue_frame_resize (Display *xdisplay,
Window frame_xwindow);
@@ -35,12 +89,39 @@ void meta_core_user_lower_and_unfocus (Display *xdisplay,
Window frame_xwindow,
guint32 timestamp);
void meta_core_user_focus (Display *xdisplay,
Window frame_xwindow,
guint32 timestamp);
void meta_core_minimize (Display *xdisplay,
Window frame_xwindow);
void meta_core_toggle_maximize (Display *xdisplay,
Window frame_xwindow);
void meta_core_toggle_maximize_horizontally (Display *xdisplay,
Window frame_xwindow);
void meta_core_toggle_maximize_vertically (Display *xdisplay,
Window frame_xwindow);
void meta_core_unmaximize (Display *xdisplay,
Window frame_xwindow);
void meta_core_maximize (Display *xdisplay,
Window frame_xwindow);
void meta_core_delete (Display *xdisplay,
Window frame_xwindow,
guint32 timestamp);
void meta_core_unshade (Display *xdisplay,
Window frame_xwindow,
guint32 timestamp);
void meta_core_shade (Display *xdisplay,
Window frame_xwindow,
guint32 timestamp);
void meta_core_unstick (Display *xdisplay,
Window frame_xwindow);
void meta_core_stick (Display *xdisplay,
Window frame_xwindow);
void meta_core_unmake_above (Display *xdisplay,
Window frame_xwindow);
void meta_core_make_above (Display *xdisplay,
Window frame_xwindow);
void meta_core_change_workspace (Display *xdisplay,
Window frame_xwindow,
int new_workspace);
@@ -87,6 +168,5 @@ void meta_core_set_screen_cursor (Display *xdisplay,
MetaCursor cursor);
void meta_invalidate_default_icons (void);
void meta_retheme_all (void);
#endif

View File

@@ -85,10 +85,6 @@ typedef enum {
* Events go to windows normally. */
META_EVENT_ROUTE_NORMAL,
/* In a window operation like moving or resizing. All events
* goes to MetaWindow, but not to the actual client window. */
META_EVENT_ROUTE_WINDOW_OP,
/* In a compositor grab operation. All events go to the
* compositor plugin. */
META_EVENT_ROUTE_COMPOSITOR_GRAB,
@@ -97,8 +93,9 @@ typedef enum {
* the Wayland application. */
META_EVENT_ROUTE_WAYLAND_POPUP,
/* The user is clicking on a window button. */
META_EVENT_ROUTE_FRAME_BUTTON,
/* In a window operation like moving or resizing. All events
* goes to MetaWindow, but not to the actual client window. */
META_EVENT_ROUTE_WINDOW_OP,
} MetaEventRoute;
typedef gboolean (*MetaAlarmFilter) (MetaDisplay *display,
@@ -178,6 +175,7 @@ struct _MetaDisplay
* ignore
*/
unsigned long ignored_crossing_serials[N_IGNORED_CROSSING_SERIALS];
Window ungrab_should_not_cause_focus_window;
guint32 current_time;
@@ -450,8 +448,8 @@ void meta_display_accelerator_activate (MetaDisplay *display,
gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
#ifdef HAVE_XI23
gboolean meta_display_process_barrier_xevent (MetaDisplay *display,
XIEvent *event);
gboolean meta_display_process_barrier_event (MetaDisplay *display,
XIEvent *event);
#endif /* HAVE_XI23 */
void meta_display_set_input_focus_xwindow (MetaDisplay *display,
@@ -480,12 +478,6 @@ gboolean meta_display_show_restart_message (MetaDisplay *display,
const char *message);
gboolean meta_display_request_restart (MetaDisplay *display);
gboolean meta_display_show_resize_popup (MetaDisplay *display,
gboolean show,
MetaRectangle *rect,
int display_w,
int display_h);
void meta_restart_init (void);
void meta_restart_finish (void);

View File

@@ -50,7 +50,6 @@
#include "meta-idle-monitor-dbus.h"
#include "meta-cursor-tracker-private.h"
#include <meta/meta-backend.h>
#include "backends/native/meta-backend-native.h"
#include "backends/x11/meta-backend-x11.h"
#include <clutter/x11/clutter-x11.h>
@@ -123,7 +122,6 @@ enum
GRAB_OP_END,
SHOW_RESTART_MESSAGE,
RESTART,
SHOW_RESIZE_POPUP,
LAST_SIGNAL
};
@@ -331,16 +329,6 @@ meta_display_class_init (MetaDisplayClass *klass)
NULL, NULL,
G_TYPE_BOOLEAN, 0);
display_signals[SHOW_RESIZE_POPUP] =
g_signal_new ("show-resize-popup",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
g_signal_accumulator_true_handled,
NULL, NULL,
G_TYPE_BOOLEAN, 4,
G_TYPE_BOOLEAN, META_TYPE_RECTANGLE, G_TYPE_INT, G_TYPE_INT);
g_object_class_install_property (object_class,
PROP_FOCUS_WINDOW,
g_param_spec_object ("focus-window",
@@ -652,6 +640,7 @@ meta_display_open (void)
display->ignored_crossing_serials[i] = 0;
++i;
}
display->ungrab_should_not_cause_focus_window = None;
display->current_time = CurrentTime;
display->sentinel_counter = 0;
@@ -1216,7 +1205,7 @@ meta_grab_op_is_resizing (MetaGrabOp op)
if (!grab_op_is_window (op))
return FALSE;
return (op & META_GRAB_OP_WINDOW_DIR_MASK) != 0 || op == META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN;
return (op & META_GRAB_OP_WINDOW_DIR_MASK) != 0;
}
gboolean
@@ -1802,9 +1791,6 @@ get_event_route_from_grab_op (MetaGrabOp op)
case META_GRAB_OP_WAYLAND_POPUP:
return META_EVENT_ROUTE_WAYLAND_POPUP;
case META_GRAB_OP_FRAME_BUTTON:
return META_EVENT_ROUTE_FRAME_BUTTON;
default:
g_assert_not_reached ();
}
@@ -1967,11 +1953,6 @@ meta_display_end_grab_op (MetaDisplay *display,
g_signal_emit (display, display_signals[GRAB_OP_END], 0,
display->screen, grab_window, grab_op);
/* We need to reset this early, since the
* meta_window_grab_op_ended callback relies on this being
* up to date. */
display->grab_op = META_GRAB_OP_NONE;
if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
{
/* Clear out the edge cache */
@@ -2004,6 +1985,7 @@ meta_display_end_grab_op (MetaDisplay *display,
}
display->event_route = META_EVENT_ROUTE_NORMAL;
display->grab_op = META_GRAB_OP_NONE;
display->grab_window = NULL;
display->grab_tile_mode = META_TILE_NONE;
display->grab_tile_monitor_number = -1;
@@ -2910,11 +2892,9 @@ meta_display_get_xinput_opcode (MetaDisplay *display)
* meta_display_supports_extended_barriers:
* @display: a #MetaDisplay
*
* Returns: whether pointer barriers can be supported.
*
* When running as an X compositor the X server needs XInput 2
* version 2.3. When running as a display server it is supported
* when running on the native backend.
* Returns: whether the X server supports extended barrier
* features as defined in version 2.3 of the XInput 2
* specification.
*
* Clients should use this method to determine whether their
* interfaces should depend on new barrier features.
@@ -2922,18 +2902,7 @@ meta_display_get_xinput_opcode (MetaDisplay *display)
gboolean
meta_display_supports_extended_barriers (MetaDisplay *display)
{
#ifdef HAVE_NATIVE_BACKEND
if (META_IS_BACKEND_NATIVE (meta_get_backend ()))
return TRUE;
#endif
if (META_IS_BACKEND_X11 (meta_get_backend ()))
{
return (META_DISPLAY_HAS_XINPUT_23 (display) &&
!meta_is_wayland_compositor());
}
g_assert_not_reached ();
return META_DISPLAY_HAS_XINPUT_23 (display) && !meta_is_wayland_compositor ();
}
/**
@@ -3045,22 +3014,6 @@ meta_display_request_restart (MetaDisplay *display)
return result;
}
gboolean
meta_display_show_resize_popup (MetaDisplay *display,
gboolean show,
MetaRectangle *rect,
int display_w,
int display_h)
{
gboolean result = FALSE;
g_signal_emit (display,
display_signals[SHOW_RESIZE_POPUP], 0,
show, rect, display_w, display_h, &result);
return result;
}
/**
* meta_display_is_pointer_emulating_sequence:
* @display: the display

View File

@@ -66,10 +66,9 @@ get_window_for_event (MetaDisplay *display,
else
return NULL;
}
case META_EVENT_ROUTE_WAYLAND_POPUP:
case META_EVENT_ROUTE_WINDOW_OP:
case META_EVENT_ROUTE_COMPOSITOR_GRAB:
case META_EVENT_ROUTE_WAYLAND_POPUP:
case META_EVENT_ROUTE_FRAME_BUTTON:
return display->grab_window;
default:
g_assert_not_reached ();
@@ -152,6 +151,23 @@ sequence_is_pointer_emulated (MetaDisplay *display,
return FALSE;
}
static void
meta_display_update_pointer_emulating_sequence (MetaDisplay *display,
const ClutterEvent *event)
{
ClutterEventSequence *sequence;
sequence = clutter_event_get_event_sequence (event);
if (event->type == CLUTTER_TOUCH_BEGIN &&
!display->pointer_emulating_sequence &&
sequence_is_pointer_emulated (display, event))
display->pointer_emulating_sequence = sequence;
else if (event->type == CLUTTER_TOUCH_END &&
display->pointer_emulating_sequence == sequence)
display->pointer_emulating_sequence = NULL;
}
static gboolean
meta_display_handle_event (MetaDisplay *display,
const ClutterEvent *event)
@@ -160,15 +176,8 @@ meta_display_handle_event (MetaDisplay *display,
gboolean bypass_clutter = FALSE;
G_GNUC_UNUSED gboolean bypass_wayland = FALSE;
MetaGestureTracker *tracker;
ClutterEventSequence *sequence;
sequence = clutter_event_get_event_sequence (event);
/* Set the pointer emulating sequence on touch begin, if eligible */
if (event->type == CLUTTER_TOUCH_BEGIN &&
!display->pointer_emulating_sequence &&
sequence_is_pointer_emulated (display, event))
display->pointer_emulating_sequence = sequence;
meta_display_update_pointer_emulating_sequence (display, event);
#ifdef HAVE_WAYLAND
MetaWaylandCompositor *compositor = NULL;
@@ -262,8 +271,7 @@ meta_display_handle_event (MetaDisplay *display,
* event, and if it doesn't, replay the event to release our
* own sync grab. */
if (display->event_route == META_EVENT_ROUTE_WINDOW_OP ||
display->event_route == META_EVENT_ROUTE_FRAME_BUTTON)
if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
{
bypass_clutter = TRUE;
bypass_wayland = TRUE;
@@ -306,11 +314,6 @@ meta_display_handle_event (MetaDisplay *display,
}
#endif
/* Unset the pointer emulating sequence after its end event is processed */
if (event->type == CLUTTER_TOUCH_END &&
display->pointer_emulating_sequence == sequence)
display->pointer_emulating_sequence = NULL;
display->current_time = CurrentTime;
return bypass_clutter;
}

View File

@@ -85,18 +85,15 @@ meta_window_ensure_frame (MetaWindow *window)
else
visual = NULL;
frame->ui_frame = meta_ui_create_frame (window->screen->ui,
window->display->xdisplay,
frame->window,
visual,
frame->rect.x,
frame->rect.y,
frame->rect.width,
frame->rect.height,
frame->window->screen->number,
&create_serial);
frame->xwindow = frame->ui_frame->xwindow;
frame->xwindow = meta_ui_create_frame_window (window->screen->ui,
window->display->xdisplay,
visual,
frame->rect.x,
frame->rect.y,
frame->rect.width,
frame->rect.height,
frame->window->screen->number,
&create_serial);
meta_stack_tracker_record_add (window->screen->stack_tracker,
frame->xwindow,
create_serial);
@@ -106,6 +103,19 @@ meta_window_ensure_frame (MetaWindow *window)
XChangeWindowAttributes (window->display->xdisplay,
frame->xwindow, CWEventMask, &attrs);
{
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Motion);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISelectEvents (window->display->xdisplay, frame->xwindow, &mask, 1);
}
meta_display_register_x_window (window->display, &frame->xwindow, window);
meta_error_trap_push (window->display);
@@ -136,8 +146,12 @@ meta_window_ensure_frame (MetaWindow *window)
/* Now that frame->xwindow is registered with window, we can set its
* style and background.
*/
meta_frame_update_style (frame);
meta_frame_update_title (frame);
meta_ui_update_frame_style (window->screen->ui, frame->xwindow);
if (window->title)
meta_ui_set_frame_title (window->screen->ui,
window->frame->xwindow,
window->title);
meta_ui_map_frame (frame->window->screen->ui, frame->xwindow);
@@ -145,23 +159,10 @@ meta_window_ensure_frame (MetaWindow *window)
MetaBackend *backend = meta_get_backend ();
if (META_IS_BACKEND_X11 (backend))
{
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
/* Since the backend selects for events on another connection,
* make sure to sync the GTK+ connection to ensure that the
* frame window has been created on the server at this point. */
/* Since the backend takes keygrabs on another connection, make sure
* to sync the GTK+ connection to ensure that the frame window has
* been created on the server at this point. */
XSync (window->display->xdisplay, False);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Motion);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISelectEvents (xdisplay, frame->xwindow, &mask, 1);
}
}
@@ -214,7 +215,7 @@ meta_window_destroy_frame (MetaWindow *window)
window->frame->rect.y + borders.invisible.top);
meta_error_trap_pop (window->display);
meta_ui_frame_unmanage (frame->ui_frame);
meta_ui_destroy_frame_window (window->screen->ui, frame->xwindow);
meta_display_unregister_x_window (window->display,
frame->xwindow);
@@ -334,7 +335,9 @@ meta_frame_calc_borders (MetaFrame *frame,
{
if (!frame->borders_cached)
{
meta_ui_frame_get_borders (frame->ui_frame, &frame->cached_borders);
meta_ui_get_frame_borders (frame->window->screen->ui,
frame->xwindow,
&frame->cached_borders);
frame->borders_cached = TRUE;
}
@@ -350,6 +353,8 @@ meta_frame_clear_cached_borders (MetaFrame *frame)
gboolean
meta_frame_sync_to_window (MetaFrame *frame,
int resize_gravity,
gboolean need_move,
gboolean need_resize)
{
meta_topic (META_DEBUG_GEOMETRY,
@@ -359,32 +364,49 @@ meta_frame_sync_to_window (MetaFrame *frame,
frame->rect.x + frame->rect.width,
frame->rect.y + frame->rect.height);
meta_ui_frame_move_resize (frame->ui_frame,
meta_ui_move_resize_frame (frame->window->screen->ui,
frame->xwindow,
frame->rect.x,
frame->rect.y,
frame->rect.width,
frame->rect.height);
if (need_resize)
{
/* If we're interactively resizing the frame, repaint
* it immediately so we don't start to lag.
*/
if (frame->window->display->grab_window ==
frame->window)
meta_ui_repaint_frame (frame->window->screen->ui,
frame->xwindow);
}
return need_resize;
}
cairo_region_t *
meta_frame_get_frame_bounds (MetaFrame *frame)
{
return meta_ui_frame_get_bounds (frame->ui_frame);
return meta_ui_get_frame_bounds (frame->window->screen->ui,
frame->xwindow,
frame->rect.width,
frame->rect.height);
}
void
meta_frame_get_mask (MetaFrame *frame,
cairo_t *cr)
{
meta_ui_frame_get_mask (frame->ui_frame, cr);
meta_ui_get_frame_mask (frame->window->screen->ui, frame->xwindow,
frame->rect.width, frame->rect.height, cr);
}
void
meta_frame_queue_draw (MetaFrame *frame)
{
meta_ui_frame_queue_draw (frame->ui_frame);
meta_ui_queue_frame_draw (frame->window->screen->ui,
frame->xwindow);
}
void
@@ -411,16 +433,3 @@ meta_frame_get_xwindow (MetaFrame *frame)
{
return frame->xwindow;
}
void
meta_frame_update_style (MetaFrame *frame)
{
meta_ui_frame_update_style (frame->ui_frame);
}
void
meta_frame_update_title (MetaFrame *frame)
{
if (frame->window->title)
meta_ui_frame_set_title (frame->ui_frame, frame->window->title);
}

View File

@@ -24,8 +24,6 @@
#include "window-private.h"
#include "ui/frames.h"
struct _MetaFrame
{
/* window we frame */
@@ -52,8 +50,6 @@ struct _MetaFrame
guint need_reapply_frame_shape : 1;
guint is_flashing : 1; /* used by the visual bell flash */
guint borders_cached : 1;
MetaUIFrame *ui_frame;
};
void meta_window_ensure_frame (MetaWindow *window);
@@ -68,6 +64,8 @@ void meta_frame_calc_borders (MetaFrame *frame,
MetaFrameBorders *borders);
gboolean meta_frame_sync_to_window (MetaFrame *frame,
int gravity,
gboolean need_move,
gboolean need_resize);
void meta_frame_clear_cached_borders (MetaFrame *frame);
@@ -80,7 +78,8 @@ void meta_frame_get_mask (MetaFrame *frame,
void meta_frame_set_screen_cursor (MetaFrame *frame,
MetaCursor cursor);
void meta_frame_update_style (MetaFrame *frame);
void meta_frame_update_title (MetaFrame *frame);
#endif

View File

@@ -42,10 +42,16 @@ struct _MetaKeyHandler
GDestroyNotify user_data_free_func;
};
typedef struct _MetaResolvedKeyCombo {
xkb_keycode_t keycode;
xkb_mod_mask_t mask;
} MetaResolvedKeyCombo;
struct _MetaKeyBinding
{
const char *name;
KeySym keysym;
KeyCode keycode;
unsigned int mask;
MetaVirtualModifier modifiers;
gint flags;
MetaKeyHandler *handler;
};
/**
* MetaKeyCombo:
@@ -61,15 +67,6 @@ struct _MetaKeyCombo
MetaVirtualModifier modifiers;
};
struct _MetaKeyBinding
{
const char *name;
MetaKeyCombo combo;
MetaResolvedKeyCombo resolved_combo;
gint flags;
MetaKeyHandler *handler;
};
typedef struct
{
char *name;
@@ -84,6 +81,9 @@ typedef struct
*/
GSList *combos;
/* for keybindings that apply only to a window */
gboolean per_window:1;
/* for keybindings not added with meta_display_add_keybinding() */
gboolean builtin:1;
} MetaKeyPref;
@@ -97,9 +97,8 @@ typedef struct
xkb_mod_mask_t super_mask;
xkb_mod_mask_t meta_mask;
MetaKeyCombo overlay_key_combo;
MetaResolvedKeyCombo overlay_resolved_key_combo;
gboolean overlay_key_only_pressed;
MetaResolvedKeyCombo *iso_next_group_combos;
MetaKeyCombo *iso_next_group_combos;
int n_iso_next_group_combos;
xkb_level_index_t keymap_num_levels;

View File

@@ -91,7 +91,7 @@ meta_key_binding_get_name (MetaKeyBinding *binding)
MetaVirtualModifier
meta_key_binding_get_modifiers (MetaKeyBinding *binding)
{
return binding->combo.modifiers;
return binding->modifiers;
}
gboolean
@@ -103,7 +103,7 @@ meta_key_binding_is_reversed (MetaKeyBinding *binding)
guint
meta_key_binding_get_mask (MetaKeyBinding *binding)
{
return binding->resolved_combo.mask;
return binding->mask;
}
gboolean
@@ -153,18 +153,20 @@ typedef struct _MetaKeyGrab MetaKeyGrab;
struct _MetaKeyGrab {
char *name;
guint action;
MetaKeyCombo combo;
MetaKeyCombo *combo;
};
static void
meta_key_grab_free (MetaKeyGrab *grab)
{
g_free (grab->name);
g_free (grab->combo);
g_free (grab);
}
static guint32
key_combo_key (MetaResolvedKeyCombo *resolved_combo)
key_binding_key (guint32 keycode,
guint32 mask)
{
/* On X, keycodes are only 8 bits while libxkbcommon supports 32 bit
keycodes, but since we're using the same XKB keymaps that X uses,
@@ -174,8 +176,16 @@ key_combo_key (MetaResolvedKeyCombo *resolved_combo)
can use a 32 bit integer to safely concatenate both keycode and
mask and thus making it easy to use them as an index in a
GHashTable. */
guint32 key = resolved_combo->keycode & 0xffff;
return (key << 16) | (resolved_combo->mask & 0xffff);
guint32 key = keycode & 0xffff;
return (key << 16) | (mask & 0xffff);
}
static const char *
keysym_name (xkb_keysym_t keysym)
{
static char name[32] = "";
xkb_keysym_get_name (keysym, name, sizeof (name));
return name;
}
static void
@@ -361,7 +371,7 @@ static void
reload_iso_next_group_combos (MetaKeyBindingManager *keys)
{
const char *iso_next_group_option;
MetaResolvedKeyCombo *combos;
MetaKeyCombo *combos;
int *keycodes;
int n_keycodes;
int n_combos;
@@ -389,36 +399,39 @@ reload_iso_next_group_combos (MetaKeyBindingManager *keys)
g_str_equal (iso_next_group_option, "caps_toggle"))
{
n_combos = n_keycodes;
combos = g_new (MetaResolvedKeyCombo, n_combos);
combos = g_new (MetaKeyCombo, n_combos);
for (i = 0; i < n_keycodes; ++i)
{
combos[i].keysym = XKB_KEY_ISO_Next_Group;
combos[i].keycode = keycodes[i];
combos[i].mask = 0;
combos[i].modifiers = 0;
}
}
else if (g_str_equal (iso_next_group_option, "shift_caps_toggle") ||
g_str_equal (iso_next_group_option, "shifts_toggle"))
{
n_combos = n_keycodes;
combos = g_new (MetaResolvedKeyCombo, n_combos);
combos = g_new (MetaKeyCombo, n_combos);
for (i = 0; i < n_keycodes; ++i)
{
combos[i].keysym = XKB_KEY_ISO_Next_Group;
combos[i].keycode = keycodes[i];
combos[i].mask = ShiftMask;
combos[i].modifiers = ShiftMask;
}
}
else if (g_str_equal (iso_next_group_option, "alt_caps_toggle") ||
g_str_equal (iso_next_group_option, "alt_space_toggle"))
{
n_combos = n_keycodes;
combos = g_new (MetaResolvedKeyCombo, n_combos);
combos = g_new (MetaKeyCombo, n_combos);
for (i = 0; i < n_keycodes; ++i)
{
combos[i].keysym = XKB_KEY_ISO_Next_Group;
combos[i].keycode = keycodes[i];
combos[i].mask = Mod1Mask;
combos[i].modifiers = Mod1Mask;
}
}
else if (g_str_equal (iso_next_group_option, "ctrl_shift_toggle") ||
@@ -426,44 +439,50 @@ reload_iso_next_group_combos (MetaKeyBindingManager *keys)
g_str_equal (iso_next_group_option, "rctrl_rshift_toggle"))
{
n_combos = n_keycodes * 2;
combos = g_new (MetaResolvedKeyCombo, n_combos);
combos = g_new (MetaKeyCombo, n_combos);
for (i = 0; i < n_keycodes; ++i)
{
combos[i].keysym = XKB_KEY_ISO_Next_Group;
combos[i].keycode = keycodes[i];
combos[i].mask = ShiftMask;
combos[i].modifiers = ShiftMask;
combos[i + n_keycodes].keysym = XKB_KEY_ISO_Next_Group;
combos[i + n_keycodes].keycode = keycodes[i];
combos[i + n_keycodes].mask = ControlMask;
combos[i + n_keycodes].modifiers = ControlMask;
}
}
else if (g_str_equal (iso_next_group_option, "ctrl_alt_toggle"))
{
n_combos = n_keycodes * 2;
combos = g_new (MetaResolvedKeyCombo, n_combos);
combos = g_new (MetaKeyCombo, n_combos);
for (i = 0; i < n_keycodes; ++i)
{
combos[i].keysym = XKB_KEY_ISO_Next_Group;
combos[i].keycode = keycodes[i];
combos[i].mask = Mod1Mask;
combos[i].modifiers = Mod1Mask;
combos[i + n_keycodes].keysym = XKB_KEY_ISO_Next_Group;
combos[i + n_keycodes].keycode = keycodes[i];
combos[i + n_keycodes].mask = ControlMask;
combos[i + n_keycodes].modifiers = ControlMask;
}
}
else if (g_str_equal (iso_next_group_option, "alt_shift_toggle") ||
g_str_equal (iso_next_group_option, "lalt_lshift_toggle"))
{
n_combos = n_keycodes * 2;
combos = g_new (MetaResolvedKeyCombo, n_combos);
combos = g_new (MetaKeyCombo, n_combos);
for (i = 0; i < n_keycodes; ++i)
{
combos[i].keysym = XKB_KEY_ISO_Next_Group;
combos[i].keycode = keycodes[i];
combos[i].mask = Mod1Mask;
combos[i].modifiers = Mod1Mask;
combos[i + n_keycodes].keysym = XKB_KEY_ISO_Next_Group;
combos[i + n_keycodes].keycode = keycodes[i];
combos[i + n_keycodes].mask = ShiftMask;
combos[i + n_keycodes].modifiers = ShiftMask;
}
}
else
@@ -478,6 +497,41 @@ reload_iso_next_group_combos (MetaKeyBindingManager *keys)
keys->iso_next_group_combos = combos;
}
static void
binding_reload_keycode_foreach (gpointer key,
gpointer value,
gpointer data)
{
MetaKeyBindingManager *keys = data;
MetaKeyBinding *binding = value;
if (binding->keysym)
binding->keycode = get_first_keycode_for_keysym (keys, binding->keysym);
}
static void
reload_keycodes (MetaKeyBindingManager *keys)
{
meta_topic (META_DEBUG_KEYBINDINGS,
"Reloading keycodes for binding tables\n");
determine_keymap_num_levels (keys);
if (keys->overlay_key_combo.keysym != 0)
{
keys->overlay_key_combo.keycode =
get_first_keycode_for_keysym (keys, keys->overlay_key_combo.keysym);
}
else
{
keys->overlay_key_combo.keycode = 0;
}
reload_iso_next_group_combos (keys);
g_hash_table_foreach (keys->key_bindings, binding_reload_keycode_foreach, keys);
}
static void
devirtualize_modifiers (MetaKeyBindingManager *keys,
MetaVirtualModifier modifiers,
@@ -507,56 +561,58 @@ devirtualize_modifiers (MetaKeyBindingManager *keys,
*mask |= Mod5Mask;
}
static void
binding_reload_modifiers_foreach (gpointer key,
gpointer value,
gpointer data)
{
MetaKeyBindingManager *keys = data;
MetaKeyBinding *binding = value;
devirtualize_modifiers (keys, binding->modifiers, &binding->mask);
meta_topic (META_DEBUG_KEYBINDINGS,
" Devirtualized mods 0x%x -> 0x%x (%s)\n",
binding->modifiers,
binding->mask,
binding->name);
}
static void
reload_modifiers (MetaKeyBindingManager *keys)
{
meta_topic (META_DEBUG_KEYBINDINGS,
"Reloading keycodes for binding tables\n");
g_hash_table_foreach (keys->key_bindings, binding_reload_modifiers_foreach, keys);
}
static void
index_binding (MetaKeyBindingManager *keys,
MetaKeyBinding *binding)
{
guint32 index_key;
index_key = key_combo_key (&binding->resolved_combo);
index_key = key_binding_key (binding->keycode, binding->mask);
g_hash_table_replace (keys->key_bindings_index,
GINT_TO_POINTER (index_key), binding);
}
static void
resolve_key_combo (MetaKeyBindingManager *keys,
MetaKeyCombo *combo,
MetaResolvedKeyCombo *resolved_combo)
{
if (combo->keysym != 0)
resolved_combo->keycode = get_first_keycode_for_keysym (keys, combo->keysym);
else
resolved_combo->keycode = combo->keycode;
devirtualize_modifiers (keys, combo->modifiers, &resolved_combo->mask);
}
static void
binding_reload_combos_foreach (gpointer key,
gpointer value,
gpointer data)
binding_index_foreach (gpointer key,
gpointer value,
gpointer data)
{
MetaKeyBindingManager *keys = data;
MetaKeyBinding *binding = value;
resolve_key_combo (keys, &binding->combo, &binding->resolved_combo);
index_binding (keys, binding);
}
static void
reload_combos (MetaKeyBindingManager *keys)
rebuild_binding_index (MetaKeyBindingManager *keys)
{
g_hash_table_remove_all (keys->key_bindings_index);
determine_keymap_num_levels (keys);
resolve_key_combo (keys,
&keys->overlay_key_combo,
&keys->overlay_resolved_key_combo);
reload_iso_next_group_combos (keys);
g_hash_table_foreach (keys->key_bindings, binding_reload_combos_foreach, keys);
g_hash_table_foreach (keys->key_bindings, binding_index_foreach, keys);
}
static void
@@ -583,11 +639,15 @@ rebuild_binding_table (MetaKeyBindingManager *keys,
{
MetaKeyHandler *handler = HANDLER (pref->name);
b = g_slice_new0 (MetaKeyBinding);
b = g_malloc0 (sizeof (MetaKeyBinding));
b->name = pref->name;
b->handler = handler;
b->flags = handler->flags;
b->combo = *combo;
b->keysym = combo->keysym;
b->keycode = combo->keycode;
b->modifiers = combo->modifiers;
b->mask = 0;
g_hash_table_add (keys->key_bindings, b);
}
@@ -602,15 +662,19 @@ rebuild_binding_table (MetaKeyBindingManager *keys,
while (g)
{
MetaKeyGrab *grab = (MetaKeyGrab*)g->data;
if (grab->combo.keysym != None || grab->combo.keycode != 0)
if (grab->combo && (grab->combo->keysym != None || grab->combo->keycode != 0))
{
MetaKeyHandler *handler = HANDLER ("external-grab");
b = g_slice_new0 (MetaKeyBinding);
b = g_malloc0 (sizeof (MetaKeyBinding));
b->name = grab->name;
b->handler = handler;
b->flags = handler->flags;
b->combo = grab->combo;
b->keysym = grab->combo->keysym;
b->keycode = grab->combo->keycode;
b->modifiers = grab->combo->modifiers;
b->mask = 0;
g_hash_table_add (keys->key_bindings, b);
}
@@ -683,10 +747,14 @@ grab_key_bindings (MetaDisplay *display)
static MetaKeyBinding *
get_keybinding (MetaKeyBindingManager *keys,
MetaResolvedKeyCombo *resolved_combo)
guint32 keycode,
guint32 mask)
{
guint32 key;
key = key_combo_key (resolved_combo);
mask = mask & 0xff & ~keys->ignored_modifier_mask;
key = key_binding_key (keycode, mask);
return g_hash_table_lookup (keys->key_bindings_index, GINT_TO_POINTER (key));
}
@@ -805,46 +873,6 @@ meta_display_remove_keybinding (MetaDisplay *display,
return TRUE;
}
static guint
get_keybinding_action (MetaKeyBindingManager *keys,
MetaResolvedKeyCombo *resolved_combo)
{
MetaKeyBinding *binding;
/* This is much more vague than the MetaDisplay::overlay-key signal,
* which is only emitted if the overlay-key is the only key pressed;
* as this method is primarily intended for plugins to allow processing
* of mutter keybindings while holding a grab, the overlay-key-only-pressed
* tracking is left to the plugin here.
*/
if (resolved_combo->keycode == (unsigned int)keys->overlay_resolved_key_combo.keycode)
return META_KEYBINDING_ACTION_OVERLAY_KEY;
binding = get_keybinding (keys, resolved_combo);
if (binding)
{
MetaKeyGrab *grab = g_hash_table_lookup (external_grabs, binding->name);
if (grab)
return grab->action;
else
return (guint) meta_prefs_get_keybinding_action (binding->name);
}
else
{
return META_KEYBINDING_ACTION_NONE;
}
}
static void
resolved_combo_from_event_params (MetaResolvedKeyCombo *resolved_combo,
MetaKeyBindingManager *keys,
unsigned int keycode,
unsigned long mask)
{
resolved_combo->keycode = keycode;
resolved_combo->mask = mask & 0xff & ~keys->ignored_modifier_mask;
}
/**
* meta_display_get_keybinding_action:
* @display: A #MetaDisplay
@@ -865,9 +893,31 @@ meta_display_get_keybinding_action (MetaDisplay *display,
unsigned long mask)
{
MetaKeyBindingManager *keys = &display->key_binding_manager;
MetaResolvedKeyCombo resolved_combo;
resolved_combo_from_event_params (&resolved_combo, keys, keycode, mask);
return get_keybinding_action (keys, &resolved_combo);
MetaKeyBinding *binding;
/* This is much more vague than the MetaDisplay::overlay-key signal,
* which is only emitted if the overlay-key is the only key pressed;
* as this method is primarily intended for plugins to allow processing
* of mutter keybindings while holding a grab, the overlay-key-only-pressed
* tracking is left to the plugin here.
*/
if (keycode == (unsigned int)keys->overlay_key_combo.keycode)
return META_KEYBINDING_ACTION_OVERLAY_KEY;
binding = get_keybinding (keys, keycode, mask);
if (binding)
{
MetaKeyGrab *grab = g_hash_table_lookup (external_grabs, binding->name);
if (grab)
return grab->action;
else
return (guint) meta_prefs_get_keybinding_action (binding->name);
}
else
{
return META_KEYBINDING_ACTION_NONE;
}
}
static void
@@ -884,7 +934,11 @@ on_keymap_changed (MetaBackend *backend,
* even when only the keymap changes */
reload_modmap (keys);
reload_combos (keys);
reload_keycodes (keys);
reload_modifiers (keys);
rebuild_binding_index (keys);
grab_key_bindings (display);
}
@@ -1104,7 +1158,9 @@ prefs_changed_callback (MetaPreference pref,
ungrab_key_bindings (display);
rebuild_key_binding_table (keys);
rebuild_special_bindings (keys);
reload_combos (keys);
reload_keycodes (keys);
reload_modifiers (keys);
rebuild_binding_index (keys);
grab_key_bindings (display);
break;
case META_PREF_MOUSE_BUTTON_MODS:
@@ -1149,9 +1205,11 @@ meta_display_shutdown_keys (MetaDisplay *display)
/* Grab/ungrab, ignoring all annoying modifiers like NumLock etc. */
static void
meta_change_keygrab (MetaKeyBindingManager *keys,
Window xwindow,
gboolean grab,
MetaResolvedKeyCombo *resolved_combo)
Window xwindow,
gboolean grab,
int keysym,
unsigned int keycode,
int modmask)
{
unsigned int ignored_mask;
@@ -1170,9 +1228,10 @@ meta_change_keygrab (MetaKeyBindingManager *keys,
*/
meta_topic (META_DEBUG_KEYBINDINGS,
"%s keybinding keycode %d mask 0x%x on 0x%lx\n",
"%s keybinding %s keycode %d mask 0x%x on 0x%lx\n",
grab ? "Grabbing" : "Ungrabbing",
resolved_combo->keycode, resolved_combo->mask, xwindow);
keysym_name (keysym), keycode,
modmask, xwindow);
ignored_mask = 0;
while (ignored_mask <= keys->ignored_modifier_mask)
@@ -1188,18 +1247,18 @@ meta_change_keygrab (MetaKeyBindingManager *keys,
continue;
}
mods = (XIGrabModifiers) { resolved_combo->mask | ignored_mask, 0 };
mods = (XIGrabModifiers) { modmask | ignored_mask, 0 };
if (grab)
XIGrabKeycode (xdisplay,
META_VIRTUAL_CORE_KEYBOARD_ID,
resolved_combo->keycode, xwindow,
keycode, xwindow,
XIGrabModeSync, XIGrabModeAsync,
False, &mask, 1, &mods);
else
XIUngrabKeycode (xdisplay,
META_VIRTUAL_CORE_KEYBOARD_ID,
resolved_combo->keycode, xwindow, 1, &mods);
keycode, xwindow, 1, &mods);
++ignored_mask;
}
@@ -1225,10 +1284,13 @@ change_keygrab_foreach (gpointer key,
if (data->only_per_window != binding_is_per_window)
return;
if (binding->resolved_combo.keycode == 0)
if (binding->keycode == 0)
return;
meta_change_keygrab (data->keys, data->xwindow, data->grab, &binding->resolved_combo);
meta_change_keygrab (data->keys, data->xwindow, data->grab,
binding->keysym,
binding->keycode,
binding->mask);
}
static void
@@ -1254,8 +1316,11 @@ meta_screen_change_keygrabs (MetaScreen *screen,
MetaDisplay *display = screen->display;
MetaKeyBindingManager *keys = &display->key_binding_manager;
if (keys->overlay_resolved_key_combo.keycode != 0)
meta_change_keygrab (keys, screen->xroot, grab, &keys->overlay_resolved_key_combo);
if (keys->overlay_key_combo.keycode != 0)
meta_change_keygrab (keys, screen->xroot, grab,
keys->overlay_key_combo.keysym,
keys->overlay_key_combo.keycode,
keys->overlay_key_combo.modifiers);
if (keys->iso_next_group_combos)
{
@@ -1263,8 +1328,12 @@ meta_screen_change_keygrabs (MetaScreen *screen,
while (i < keys->n_iso_next_group_combos)
{
if (keys->iso_next_group_combos[i].keycode != 0)
meta_change_keygrab (keys, screen->xroot, grab, &keys->iso_next_group_combos[i]);
{
meta_change_keygrab (keys, screen->xroot, grab,
keys->iso_next_group_combos[i].keysym,
keys->iso_next_group_combos[i].keycode,
keys->iso_next_group_combos[i].modifiers);
}
++i;
}
}
@@ -1374,8 +1443,9 @@ handle_external_grab (MetaDisplay *display,
MetaKeyBinding *binding,
gpointer user_data)
{
MetaKeyBindingManager *keys = &display->key_binding_manager;
guint action = get_keybinding_action (keys, &binding->resolved_combo);
guint action = meta_display_get_keybinding_action (display,
binding->keycode,
binding->mask);
meta_display_accelerator_activate (display, action, event);
}
@@ -1388,10 +1458,12 @@ meta_display_grab_accelerator (MetaDisplay *display,
MetaKeyBindingManager *keys = &display->key_binding_manager;
MetaKeyBinding *binding;
MetaKeyGrab *grab;
MetaKeyCombo combo;
MetaResolvedKeyCombo resolved_combo;
guint keysym = 0;
guint keycode = 0;
guint mask = 0;
MetaVirtualModifier modifiers = 0;
if (!meta_parse_accelerator (accelerator, &combo))
if (!meta_parse_accelerator (accelerator, &keysym, &keycode, &modifiers))
{
meta_topic (META_DEBUG_KEYBINDINGS,
"Failed to parse accelerator\n");
@@ -1400,29 +1472,35 @@ meta_display_grab_accelerator (MetaDisplay *display,
return META_KEYBINDING_ACTION_NONE;
}
resolve_key_combo (keys, &combo, &resolved_combo);
devirtualize_modifiers (keys, modifiers, &mask);
keycode = get_first_keycode_for_keysym (keys, keysym);
if (resolved_combo.keycode == 0)
if (keycode == 0)
return META_KEYBINDING_ACTION_NONE;
if (get_keybinding (keys, &resolved_combo))
if (get_keybinding (keys, keycode, mask))
return META_KEYBINDING_ACTION_NONE;
if (META_IS_BACKEND_X11 (backend))
meta_change_keygrab (keys, display->screen->xroot, TRUE, &resolved_combo);
meta_change_keygrab (keys, display->screen->xroot, TRUE, keysym, keycode, mask);
grab = g_new0 (MetaKeyGrab, 1);
grab->action = next_dynamic_keybinding_action ();
grab->name = meta_external_binding_name_for_action (grab->action);
grab->combo = combo;
grab->combo = g_malloc0 (sizeof (MetaKeyCombo));
grab->combo->keysym = keysym;
grab->combo->keycode = keycode;
grab->combo->modifiers = modifiers;
g_hash_table_insert (external_grabs, grab->name, grab);
binding = g_slice_new0 (MetaKeyBinding);
binding = g_malloc0 (sizeof (MetaKeyBinding));
binding->name = grab->name;
binding->handler = HANDLER ("external-grab");
binding->combo = combo;
binding->resolved_combo = resolved_combo;
binding->keysym = grab->combo->keysym;
binding->keycode = grab->combo->keycode;
binding->modifiers = grab->combo->modifiers;
binding->mask = mask;
g_hash_table_add (keys->key_bindings, binding);
index_binding (keys, binding);
@@ -1439,7 +1517,8 @@ meta_display_ungrab_accelerator (MetaDisplay *display,
MetaKeyBinding *binding;
MetaKeyGrab *grab;
char *key;
MetaResolvedKeyCombo resolved_combo;
guint mask = 0;
guint keycode = 0;
g_return_val_if_fail (action != META_KEYBINDING_ACTION_NONE, FALSE);
@@ -1448,16 +1527,21 @@ meta_display_ungrab_accelerator (MetaDisplay *display,
if (!grab)
return FALSE;
resolve_key_combo (keys, &grab->combo, &resolved_combo);
binding = get_keybinding (keys, &resolved_combo);
devirtualize_modifiers (keys, grab->combo->modifiers, &mask);
keycode = get_first_keycode_for_keysym (keys, grab->combo->keysym);
binding = get_keybinding (keys, keycode, mask);
if (binding)
{
guint32 index_key;
if (META_IS_BACKEND_X11 (backend))
meta_change_keygrab (keys, display->screen->xroot, FALSE, &binding->resolved_combo);
meta_change_keygrab (keys, display->screen->xroot, FALSE,
binding->keysym,
binding->keycode,
binding->mask);
index_key = key_combo_key (&binding->resolved_combo);
index_key = key_binding_key (binding->keycode, binding->mask);
g_hash_table_remove (keys->key_bindings_index, GINT_TO_POINTER (index_key));
g_hash_table_remove (keys->key_bindings, binding);
@@ -1576,14 +1660,13 @@ meta_window_ungrab_all_keys (MetaWindow *window, guint32 timestamp)
}
void
meta_display_freeze_keyboard (MetaDisplay *display, guint32 timestamp)
meta_display_freeze_keyboard (MetaDisplay *display, Window window, guint32 timestamp)
{
MetaBackend *backend = meta_get_backend ();
if (!META_IS_BACKEND_X11 (backend))
return;
Window window = meta_backend_x11_get_xwindow (META_BACKEND_X11 (backend));
grab_keyboard (window, timestamp, XIGrabModeSync);
}
@@ -1673,19 +1756,15 @@ process_event (MetaDisplay *display,
ClutterKeyEvent *event)
{
MetaKeyBindingManager *keys = &display->key_binding_manager;
MetaResolvedKeyCombo resolved_combo;
MetaKeyBinding *binding;
/* we used to have release-based bindings but no longer. */
if (event->type == CLUTTER_KEY_RELEASE)
return FALSE;
resolved_combo_from_event_params (&resolved_combo, keys,
event->hardware_keycode,
event->modifier_state);
binding = get_keybinding (keys, &resolved_combo);
binding = get_keybinding (keys,
event->hardware_keycode,
event->modifier_state);
if (!binding ||
(!window && binding->flags & META_KEY_BINDING_PER_WINDOW))
goto not_found;
@@ -1736,7 +1815,7 @@ process_overlay_key (MetaDisplay *display,
if (keys->overlay_key_only_pressed)
{
if (event->hardware_keycode != (int)keys->overlay_resolved_key_combo.keycode)
if (event->hardware_keycode != (int)keys->overlay_key_combo.keycode)
{
keys->overlay_key_only_pressed = FALSE;
@@ -1789,7 +1868,7 @@ process_overlay_key (MetaDisplay *display,
clutter_input_device_get_device_id (event->device),
XIAsyncDevice, event->time);
binding = get_keybinding (keys, &keys->overlay_resolved_key_combo);
binding = get_keybinding (keys, keys->overlay_key_combo.keycode, 0);
if (binding &&
meta_compositor_filter_keybinding (display->compositor, binding))
return TRUE;
@@ -1818,7 +1897,7 @@ process_overlay_key (MetaDisplay *display,
return TRUE;
}
else if (event->type == CLUTTER_KEY_PRESS &&
event->hardware_keycode == (int)keys->overlay_resolved_key_combo.keycode)
event->hardware_keycode == (int)keys->overlay_key_combo.keycode)
{
keys->overlay_key_only_pressed = TRUE;
/* We keep the keyboard frozen - this allows us to use ReplayKeyboard
@@ -1841,7 +1920,8 @@ process_iso_next_group (MetaDisplay *display,
{
MetaKeyBindingManager *keys = &display->key_binding_manager;
gboolean activate;
MetaResolvedKeyCombo resolved_combo;
guint32 keycode;
guint32 modifiers;
int i;
if (event->type == CLUTTER_KEY_RELEASE)
@@ -1849,14 +1929,13 @@ process_iso_next_group (MetaDisplay *display,
activate = FALSE;
resolved_combo_from_event_params (&resolved_combo, keys,
event->hardware_keycode,
event->modifier_state);
keycode = event->hardware_keycode;
modifiers = event->modifier_state & 0xff & ~keys->ignored_modifier_mask;
for (i = 0; i < keys->n_iso_next_group_combos; ++i)
{
if (resolved_combo.keycode == keys->iso_next_group_combos[i].keycode &&
resolved_combo.mask == keys->iso_next_group_combos[i].mask)
if (keycode == keys->iso_next_group_combos[i].keycode &&
modifiers == keys->iso_next_group_combos[i].modifiers)
{
/* If the signal handler returns TRUE the keyboard will
remain frozen. It's the signal handler's responsibility
@@ -3636,41 +3715,6 @@ init_builtin_key_bindings (MetaDisplay *display)
META_KEY_BINDING_NONE,
META_KEYBINDING_ACTION_NONE,
handle_switch_vt, 7);
add_builtin_keybinding (display,
"switch-to-session-8",
mutter_wayland_keybindings,
META_KEY_BINDING_NONE,
META_KEYBINDING_ACTION_NONE,
handle_switch_vt, 8);
add_builtin_keybinding (display,
"switch-to-session-9",
mutter_wayland_keybindings,
META_KEY_BINDING_NONE,
META_KEYBINDING_ACTION_NONE,
handle_switch_vt, 9);
add_builtin_keybinding (display,
"switch-to-session-10",
mutter_wayland_keybindings,
META_KEY_BINDING_NONE,
META_KEYBINDING_ACTION_NONE,
handle_switch_vt, 10);
add_builtin_keybinding (display,
"switch-to-session-11",
mutter_wayland_keybindings,
META_KEY_BINDING_NONE,
META_KEYBINDING_ACTION_NONE,
handle_switch_vt, 11);
add_builtin_keybinding (display,
"switch-to-session-12",
mutter_wayland_keybindings,
META_KEY_BINDING_NONE,
META_KEYBINDING_ACTION_NONE,
handle_switch_vt, 12);
}
#endif /* HAVE_NATIVE_BACKEND */
@@ -4047,7 +4091,7 @@ meta_display_init_keys (MetaDisplay *display)
keys->super_mask = 0;
keys->meta_mask = 0;
keys->key_bindings = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) meta_key_binding_free);
keys->key_bindings = g_hash_table_new_full (NULL, NULL, NULL, g_free);
keys->key_bindings_index = g_hash_table_new (NULL, NULL);
reload_modmap (keys);
@@ -4083,7 +4127,9 @@ meta_display_init_keys (MetaDisplay *display)
rebuild_key_binding_table (keys);
rebuild_special_bindings (keys);
reload_combos (keys);
reload_keycodes (keys);
reload_modifiers (keys);
rebuild_binding_index (keys);
update_window_grab_modifiers (keys);

View File

@@ -431,6 +431,42 @@ meta_run (void)
meta_prefs_init ();
meta_prefs_add_listener (prefs_changed_callback, NULL);
meta_ui_set_current_theme (meta_prefs_get_theme ());
/* Try to find some theme that'll work if the theme preference
* doesn't exist. First try Simple (the default theme) then just
* try anything in the themes directory.
*/
if (!meta_ui_have_a_theme ())
meta_ui_set_current_theme ("Simple");
if (!meta_ui_have_a_theme ())
{
const char *dir_entry = NULL;
GError *err = NULL;
GDir *themes_dir = NULL;
if (!(themes_dir = g_dir_open (MUTTER_DATADIR"/themes", 0, &err)))
{
meta_fatal (_("Failed to scan themes directory: %s\n"), err->message);
g_error_free (err);
}
else
{
while (((dir_entry = g_dir_read_name (themes_dir)) != NULL) &&
(!meta_ui_have_a_theme ()))
{
meta_ui_set_current_theme (dir_entry);
}
g_dir_close (themes_dir);
}
}
if (!meta_ui_have_a_theme ())
meta_fatal (_("Could not find a theme! Be sure %s exists and contains the usual themes.\n"),
MUTTER_DATADIR"/themes");
if (!meta_display_open ())
meta_exit (META_EXIT_ERROR);
@@ -477,7 +513,9 @@ prefs_changed_callback (MetaPreference pref,
{
switch (pref)
{
case META_PREF_THEME:
case META_PREF_DRAGGABLE_BORDER_WIDTH:
meta_ui_set_current_theme (meta_prefs_get_theme ());
meta_display_retheme_all ();
break;

View File

@@ -25,7 +25,6 @@
#include "config.h"
#include "meta-accel-parse.h"
#include "keybindings-private.h"
#include <xkbcommon/xkbcommon.h>
#include <string.h>
@@ -174,16 +173,21 @@ is_keycode (const gchar *string)
static gboolean
accelerator_parse (const gchar *accelerator,
MetaKeyCombo *combo)
guint *accelerator_key,
guint *accelerator_keycode,
MetaVirtualModifier *accelerator_mods)
{
gboolean error = FALSE;
guint keyval, keycode;
MetaVirtualModifier mods;
gint len;
combo->keysym = 0;
combo->keycode = 0;
combo->modifiers = 0;
if (accelerator_key)
*accelerator_key = 0;
if (accelerator_keycode)
*accelerator_keycode = 0;
if (accelerator_mods)
*accelerator_mods = 0;
if (accelerator == NULL)
{
@@ -326,35 +330,34 @@ out:
if (error)
return FALSE;
combo->keysym = keyval;
combo->keycode = keycode;
combo->modifiers = mods;
if (accelerator_key)
*accelerator_key = keyval;
if (accelerator_keycode)
*accelerator_keycode = keycode;
if (accelerator_mods)
*accelerator_mods = mods;
return TRUE;
}
gboolean
meta_parse_accelerator (const char *accel,
MetaKeyCombo *combo)
meta_parse_accelerator (const char *accel,
unsigned int *keysym,
unsigned int *keycode,
MetaVirtualModifier *mask)
{
if (!accel[0] || strcmp (accel, "disabled") == 0)
return TRUE;
return accelerator_parse (accel, combo);
return accelerator_parse (accel, keysym, keycode, mask);
}
gboolean
meta_parse_modifier (const char *accel,
MetaVirtualModifier *mask)
{
MetaKeyCombo combo;
if (accel == NULL || !accel[0] || strcmp (accel, "disabled") == 0)
return TRUE;
if (!accelerator_parse (accel, &combo))
return FALSE;
*mask = combo.modifiers;
return TRUE;
return accelerator_parse (accel, NULL, NULL, mask);
}

View File

@@ -27,16 +27,16 @@
#include <glib.h>
#include <meta/common.h>
typedef struct _MetaKeyCombo MetaKeyCombo;
/* Not a real key symbol but means "key above the tab key"; this is
* used as the default keybinding for cycle_group.
* 0x2xxxxxxx is a range not used by GDK or X. the remaining digits are
* randomly chosen */
#define META_KEY_ABOVE_TAB 0x2f7259c9
gboolean meta_parse_accelerator (const char *accel,
MetaKeyCombo *combo);
gboolean meta_parse_accelerator (const char *accel,
unsigned int *keysym,
unsigned int *keycode,
MetaVirtualModifier *mask);
gboolean meta_parse_modifier (const char *accel,
MetaVirtualModifier *mask);

View File

@@ -82,6 +82,7 @@ static GDesktopFocusNewWindows focus_new_windows = G_DESKTOP_FOCUS_NEW_WINDOWS_S
static gboolean raise_on_click = TRUE;
static gboolean center_new_windows = FALSE;
static gboolean attach_modal_dialogs = FALSE;
static char* current_theme = NULL;
static int num_workspaces = 4;
static GDesktopTitlebarAction action_double_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_TOGGLE_MAXIMIZE;
static GDesktopTitlebarAction action_middle_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_LOWER;
@@ -143,6 +144,7 @@ static void queue_changed (MetaPreference pref);
static void maybe_give_disable_workarounds_warning (void);
static gboolean titlebar_handler (GVariant*, gpointer*, gpointer);
static gboolean theme_name_handler (GVariant*, gpointer*, gpointer);
static gboolean mouse_button_mods_handler (GVariant*, gpointer*, gpointer);
static gboolean button_layout_handler (GVariant*, gpointer*, gpointer);
static gboolean overlay_key_handler (GVariant*, gpointer*, gpointer);
@@ -399,6 +401,14 @@ static MetaStringPreference preferences_string[] =
mouse_button_mods_handler,
NULL,
},
{
{ "theme",
SCHEMA_GENERAL,
META_PREF_THEME,
},
theme_name_handler,
NULL,
},
{
{ KEY_TITLEBAR_FONT,
SCHEMA_GENERAL,
@@ -439,7 +449,7 @@ static MetaStringArrayPreference preferences_string_array[] =
{
{ KEY_WORKSPACE_NAMES,
SCHEMA_GENERAL,
META_PREF_WORKSPACE_NAMES,
META_PREF_KEYBINDINGS,
},
NULL,
&workspace_names,
@@ -561,7 +571,8 @@ handle_preference_init_string (void)
if (!cursor->target)
meta_bug ("%s must have handler or target\n", cursor->base.key);
g_free (*(cursor->target));
if (*(cursor->target))
g_free (*(cursor->target));
value = g_settings_get_string (SETTINGS (cursor->base.schema),
cursor->base.key);
@@ -717,7 +728,8 @@ handle_preference_update_string (GSettings *settings,
inform_listeners = (g_strcmp0 (value, *(cursor->target)) != 0);
g_free(*(cursor->target));
if (*(cursor->target))
g_free(*(cursor->target));
*(cursor->target) = value;
}
@@ -1290,7 +1302,10 @@ meta_prefs_get_attach_modal_dialogs (void)
gboolean
meta_prefs_get_raise_on_click (void)
{
return raise_on_click;
/* Force raise_on_click on for click-to-focus, as requested by Havoc
* in #326156.
*/
return raise_on_click || focus_mode == G_DESKTOP_FOCUS_MODE_CLICK;
}
gboolean
@@ -1299,6 +1314,12 @@ meta_prefs_get_show_fallback_app_menu (void)
return show_fallback_app_menu;
}
const char*
meta_prefs_get_theme (void)
{
return current_theme;
}
const char*
meta_prefs_get_cursor_theme (void)
{
@@ -1355,6 +1376,31 @@ titlebar_handler (GVariant *value,
return TRUE;
}
static gboolean
theme_name_handler (GVariant *value,
gpointer *result,
gpointer data)
{
const gchar *string_value;
*result = NULL; /* ignored */
string_value = g_variant_get_string (value, NULL);
if (!string_value || !*string_value)
return FALSE;
if (g_strcmp0 (current_theme, string_value) != 0)
{
if (current_theme)
g_free (current_theme);
current_theme = g_strdup (string_value);
queue_changed (META_PREF_THEME);
}
return TRUE;
}
static gboolean
mouse_button_mods_handler (GVariant *value,
gpointer *result,
@@ -1672,7 +1718,9 @@ overlay_key_handler (GVariant *value,
*result = NULL; /* ignored */
string_value = g_variant_get_string (value, NULL);
if (string_value && meta_parse_accelerator (string_value, &combo))
if (string_value && meta_parse_accelerator (string_value, &combo.keysym,
&combo.keycode,
&combo.modifiers))
;
else
{
@@ -1681,10 +1729,9 @@ overlay_key_handler (GVariant *value,
return FALSE;
}
combo.modifiers = 0;
if (overlay_key_combo.keysym != combo.keysym ||
overlay_key_combo.keycode != combo.keycode)
overlay_key_combo.keycode != combo.keycode ||
overlay_key_combo.modifiers != combo.modifiers)
{
overlay_key_combo = combo;
queue_changed (META_PREF_KEYBINDINGS);
@@ -1778,6 +1825,9 @@ meta_preference_to_string (MetaPreference pref)
case META_PREF_RAISE_ON_CLICK:
return "RAISE_ON_CLICK";
case META_PREF_THEME:
return "THEME";
case META_PREF_TITLEBAR_FONT:
return "TITLEBAR_FONT";
@@ -1915,6 +1965,10 @@ update_binding (MetaKeyPref *binding,
{
GSList *old_combos, *a, *b;
gboolean changed;
unsigned int keysym;
unsigned int keycode;
MetaVirtualModifier mods;
MetaKeyCombo *combo;
int i;
meta_topic (META_DEBUG_KEYBINDINGS,
@@ -1926,25 +1980,31 @@ update_binding (MetaKeyPref *binding,
for (i = 0; strokes && strokes[i]; i++)
{
MetaKeyCombo *combo;
keysym = 0;
keycode = 0;
mods = 0;
combo = g_malloc0 (sizeof (MetaKeyCombo));
if (!meta_parse_accelerator (strokes[i], combo))
if (!meta_parse_accelerator (strokes[i], &keysym, &keycode, &mods))
{
meta_topic (META_DEBUG_KEYBINDINGS,
"Failed to parse new GSettings value\n");
meta_warning ("\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n",
strokes[i], binding->name);
g_free (combo);
/* Value is kept and will thus be removed next time we save the key.
* Changing the key in response to a modification could lead to cyclic calls. */
continue;
}
combo = g_malloc0 (sizeof (MetaKeyCombo));
combo->keysym = keysym;
combo->keycode = keycode;
combo->modifiers = mods;
binding->combos = g_slist_prepend (binding->combos, combo);
meta_topic (META_DEBUG_KEYBINDINGS,
"New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n",
binding->name, keysym, keycode, mods);
}
binding->combos = g_slist_reverse (binding->combos);
@@ -2111,6 +2171,7 @@ meta_prefs_add_keybinding (const char *name,
pref->settings = g_object_ref (settings);
pref->action = action;
pref->combos = NULL;
pref->per_window = (flags & META_KEY_BINDING_PER_WINDOW) != 0;
pref->builtin = (flags & META_KEY_BINDING_BUILTIN) != 0;
strokes = g_settings_get_strv (settings, name);
@@ -2173,7 +2234,7 @@ meta_prefs_remove_keybinding (const char *name)
}
GList *
meta_prefs_get_keybindings (void)
meta_prefs_get_keybindings ()
{
return g_hash_table_get_values (key_bindings);
}
@@ -2221,25 +2282,25 @@ meta_prefs_get_auto_raise_delay (void)
}
gboolean
meta_prefs_get_focus_change_on_pointer_rest (void)
meta_prefs_get_focus_change_on_pointer_rest ()
{
return focus_change_on_pointer_rest;
}
gboolean
meta_prefs_get_gnome_accessibility (void)
meta_prefs_get_gnome_accessibility ()
{
return gnome_accessibility;
}
gboolean
meta_prefs_get_gnome_animations (void)
meta_prefs_get_gnome_animations ()
{
return gnome_animations;
}
gboolean
meta_prefs_get_edge_tiling (void)
meta_prefs_get_edge_tiling ()
{
return edge_tiling;
}

View File

@@ -36,7 +36,7 @@
#include <X11/Xutil.h>
#include "stack-tracker.h"
#include "ui.h"
#include "meta-monitor-manager-private.h"
#include "meta-monitor-manager.h"
typedef void (* MetaScreenWindowFunc) (MetaWindow *window,
gpointer user_data);
@@ -100,6 +100,8 @@ struct _MetaScreen
#endif
Window wm_cm_selection_window;
guint32 wm_cm_timestamp;
guint work_area_later;
guint check_fullscreen_later;

View File

@@ -496,81 +496,6 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
return guard_window;
}
static Window
take_manager_selection (MetaDisplay *display,
Window xroot,
Atom manager_atom,
int timestamp,
gboolean should_replace)
{
Display *xdisplay = display->xdisplay;
Window current_owner, new_owner;
current_owner = XGetSelectionOwner (xdisplay, manager_atom);
if (current_owner != None)
{
XSetWindowAttributes attrs;
if (should_replace)
{
/* We want to find out when the current selection owner dies */
meta_error_trap_push (display);
attrs.event_mask = StructureNotifyMask;
XChangeWindowAttributes (xdisplay, current_owner, CWEventMask, &attrs);
if (meta_error_trap_pop_with_return (display) != Success)
current_owner = None; /* don't wait for it to die later on */
}
else
{
meta_warning (_("Display \"%s\" already has a window manager; try using the --replace option to replace the current window manager."),
display->name);
return None;
}
}
/* We need SelectionClear and SelectionRequest events on the new owner,
* but those cannot be masked, so we only need NoEventMask.
*/
new_owner = meta_create_offscreen_window (xdisplay, xroot, NoEventMask);
XSetSelectionOwner (xdisplay, manager_atom, new_owner, timestamp);
if (XGetSelectionOwner (xdisplay, manager_atom) != new_owner)
{
meta_warning ("Could not acquire selection: %s", XGetAtomName (xdisplay, manager_atom));
return None;
}
{
/* Send client message indicating that we are now the selection owner */
XClientMessageEvent ev;
ev.type = ClientMessage;
ev.window = xroot;
ev.message_type = display->atom_MANAGER;
ev.format = 32;
ev.data.l[0] = timestamp;
ev.data.l[1] = manager_atom;
XSendEvent (xdisplay, xroot, False, StructureNotifyMask, (XEvent *) &ev);
}
/* Wait for old window manager to go away */
if (current_owner != None)
{
XEvent event;
/* We sort of block infinitely here which is probably lame. */
meta_verbose ("Waiting for old window manager to exit\n");
do
XWindowEvent (xdisplay, current_owner, StructureNotifyMask, &event);
while (event.type != DestroyNotify);
}
return new_owner;
}
MetaScreen*
meta_screen_new (MetaDisplay *display,
int number,
@@ -580,9 +505,11 @@ meta_screen_new (MetaDisplay *display,
Window xroot;
Display *xdisplay;
Window new_wm_sn_owner;
Window current_wm_sn_owner;
gboolean replace_current_wm;
Atom wm_sn_atom;
char buf[128];
guint32 manager_timestamp;
MetaMonitorManager *manager;
replace_current_wm = meta_get_replace_current_wm ();
@@ -610,11 +537,83 @@ meta_screen_new (MetaDisplay *display,
}
sprintf (buf, "WM_S%d", number);
wm_sn_atom = XInternAtom (xdisplay, buf, False);
new_wm_sn_owner = take_manager_selection (display, xroot, wm_sn_atom, timestamp, replace_current_wm);
if (new_wm_sn_owner == None)
return NULL;
current_wm_sn_owner = XGetSelectionOwner (xdisplay, wm_sn_atom);
if (current_wm_sn_owner != None)
{
XSetWindowAttributes attrs;
if (!replace_current_wm)
{
meta_warning (_("Screen %d on display \"%s\" already has a window manager; try using the --replace option to replace the current window manager.\n"),
number, display->name);
return NULL;
}
/* We want to find out when the current selection owner dies */
meta_error_trap_push (display);
attrs.event_mask = StructureNotifyMask;
XChangeWindowAttributes (xdisplay,
current_wm_sn_owner, CWEventMask, &attrs);
if (meta_error_trap_pop_with_return (display) != Success)
current_wm_sn_owner = None; /* don't wait for it to die later on */
}
/* We need SelectionClear and SelectionRequest events on the new_wm_sn_owner,
* but those cannot be masked, so we only need NoEventMask.
*/
new_wm_sn_owner = meta_create_offscreen_window (xdisplay, xroot, NoEventMask);
manager_timestamp = timestamp;
XSetSelectionOwner (xdisplay, wm_sn_atom, new_wm_sn_owner,
manager_timestamp);
if (XGetSelectionOwner (xdisplay, wm_sn_atom) != new_wm_sn_owner)
{
meta_warning ("Could not acquire window manager selection on screen %d display \"%s\"\n",
number, display->name);
XDestroyWindow (xdisplay, new_wm_sn_owner);
return NULL;
}
{
/* Send client message indicating that we are now the WM */
XClientMessageEvent ev;
ev.type = ClientMessage;
ev.window = xroot;
ev.message_type = display->atom_MANAGER;
ev.format = 32;
ev.data.l[0] = manager_timestamp;
ev.data.l[1] = wm_sn_atom;
XSendEvent (xdisplay, xroot, False, StructureNotifyMask, (XEvent*)&ev);
}
/* Wait for old window manager to go away */
if (current_wm_sn_owner != None)
{
XEvent event;
/* We sort of block infinitely here which is probably lame. */
meta_verbose ("Waiting for old window manager to exit\n");
do
{
XWindowEvent (xdisplay, current_wm_sn_owner,
StructureNotifyMask, &event);
}
while (event.type != DestroyNotify);
}
/* select our root window events */
meta_error_trap_push (display);
{
long event_mask;
@@ -639,6 +638,16 @@ meta_screen_new (MetaDisplay *display,
XSelectInput (xdisplay, xroot, event_mask);
}
if (meta_error_trap_pop_with_return (display) != Success)
{
meta_warning (_("Screen %d on display \"%s\" already has a window manager\n"),
number, display->name);
XDestroyWindow (xdisplay, new_wm_sn_owner);
return NULL;
}
/* Select for cursor changes so the cursor tracker is up to date. */
XFixesSelectCursorInput (xdisplay, xroot, XFixesDisplayCursorNotifyMask);
@@ -666,7 +675,11 @@ meta_screen_new (MetaDisplay *display,
screen->wm_sn_selection_window = new_wm_sn_owner;
screen->wm_sn_atom = wm_sn_atom;
screen->wm_sn_timestamp = timestamp;
screen->wm_sn_timestamp = manager_timestamp;
screen->wm_cm_selection_window = meta_create_offscreen_window (xdisplay,
xroot,
NoEventMask);
screen->work_area_later = 0;
screen->check_fullscreen_later = 0;
@@ -678,10 +691,7 @@ meta_screen_new (MetaDisplay *display,
screen->starting_corner = META_SCREEN_TOPLEFT;
screen->guard_window = None;
/* If we're a Wayland compositor, then we don't grab the COW, since it
* will map it. */
if (!meta_is_wayland_compositor ())
screen->composite_overlay_window = XCompositeGetOverlayWindow (xdisplay, xroot);
screen->composite_overlay_window = XCompositeGetOverlayWindow (xdisplay, xroot);
/* Now that we've gotten taken a reference count on the COW, we
* can close the helper that is holding on to it */
@@ -838,7 +848,8 @@ meta_screen_free (MetaScreen *screen,
if (screen->check_fullscreen_later != 0)
meta_later_remove (screen->check_fullscreen_later);
g_free (screen->monitor_infos);
if (screen->monitor_infos)
g_free (screen->monitor_infos);
if (screen->tile_preview_timeout_id)
g_source_remove (screen->tile_preview_timeout_id);
@@ -1265,11 +1276,9 @@ meta_screen_update_cursor (MetaScreen *screen)
MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (screen);
cursor_ref = meta_cursor_reference_from_theme (cursor);
if (cursor_ref == NULL)
meta_fatal ("Could not find cursor. Perhaps set XCURSOR_PATH?");
meta_cursor_tracker_set_root_cursor (tracker, cursor_ref);
meta_cursor_reference_unref (cursor_ref);
if (cursor_ref)
meta_cursor_reference_unref (cursor_ref);
/* Set a cursor for X11 applications that don't specify their own */
xcursor = meta_display_create_x_cursor (display, cursor);
@@ -2889,12 +2898,27 @@ meta_screen_set_cm_selection (MetaScreen *screen)
{
char selection[32];
Atom a;
guint32 timestamp;
timestamp = meta_display_get_current_time_roundtrip (screen->display);
g_snprintf (selection, sizeof (selection), "_NET_WM_CM_S%d", screen->number);
a = XInternAtom (screen->display->xdisplay, selection, False);
screen->wm_cm_selection_window = take_manager_selection (screen->display, screen->xroot, a, timestamp, TRUE);
screen->wm_cm_timestamp = meta_display_get_current_time_roundtrip (
screen->display);
g_snprintf (selection, sizeof(selection), "_NET_WM_CM_S%d", screen->number);
meta_verbose ("Setting selection: %s\n", selection);
a = XInternAtom (screen->display->xdisplay, selection, FALSE);
XSetSelectionOwner (screen->display->xdisplay, a,
screen->wm_cm_selection_window, screen->wm_cm_timestamp);
}
void
meta_screen_unset_cm_selection (MetaScreen *screen)
{
char selection[32];
Atom a;
g_snprintf (selection, sizeof(selection), "_NET_WM_CM_S%d", screen->number);
a = XInternAtom (screen->display->xdisplay, selection, FALSE);
XSetSelectionOwner (screen->display->xdisplay, a,
None, screen->wm_cm_timestamp);
}
/**

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