Compare commits

..

16 Commits

Author SHA1 Message Date
Carlos Garnacho
3ed80495e0 compositor: emit grab-op-begin/end signals on plugin grabs
This makes it possible to track there grabs triggered this way, in
addition to the ones handled by mutter.
2014-06-25 16:38:29 +02:00
Carlos Garnacho
f13c86d651 gesture-tracker: Implement threshold-based sequence rejection
If a sequence moves past a certain distance without being used by a
gesture, reject it so clients may see and react to it ASAP. This makes
gestures to be began by initially quasi-static touchpoints, in addition to
quasi-simultaneous.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
be2ca66735 wayland: Export meta_wayland_touch_cancel()
This will be necessary in order to hook the gesture tracker
to clients.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
2df807549e frames: Keep information about the ongoing grab operation, and retry if needed.
When a passive touch grab is rejected over the frame, management is punted to
the frame itself, and pointer events emulated, but the attempt to transfer the
grab from the GDK connection to the Clutter one fails with AlreadyGrabbed, and
will fail until the Clutter connection receives the XI_TouchEnd resulting from
XIRejectTouch, gotten after the XI_ButtonPress on the GDK connection.

In order to bypass this shortcoming, store the current grab operation on the
frame as long as the button is pressed, so it is retried once on the next
motion event happening during frame dragging, that will have a recent enough
timestamp to succeed. If no grabbing succeeded, the current grab operation
data will be reset on GDK_BUTTON_RELEASE.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
66cdb1bb71 backend: Use the most recent event time on replayed touch events
When a touch sequence is passively grabbed and later rejected, events
will be replayed on the next client in propagation order, although those
events (either transformed to pointer events or not) will contain the
original timestamps, this will make grabs fail with InvalidTime if triggered
from the replayed ButtonPress/TouchBegin handler.

In order to work around this, store the most recent event time (presumably
gotten from the XI_TouchEnd caused by the passive grab being rejected), and
use that time on the events being replayed afterwards and grabs, so we don't
possibly fail with InvalidTime if those events result in a compositor grab.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
8030a2972e display: Set an X11 passive touch grab on the root window
Touch events will be caught first by the compositor this way,
whenever the MetaGestureTracker notifies of the accepted/rejected
state of a sequence, XIAllowTouchEvents() will be called on it
accordingly, so it is handled exclusively by the compositor or
punted to clients.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
ba086dea8c events: Hook MetaGestureTracker to display event processing
Events aren't actually consumed by the MetaGestureTracker, but it
rather defines whether the event will reach clients, or the stage.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
6a02d7dfa3 backend: Ensure touch event coordinates are translated to the stage's
Now that those events are going to be received, coordinates translation
should also happen on those.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
c5db56da5c display: Add a getter for the gesture tracker
The MetaDisplay will contain a global MetaGestureTracker,
shared through this getter.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
b5c605df5e core: Add MetaGestureTracker
This object tracks both touch sequences happening on the stage and
gestures attached to the stage actor. When a gesture emits
::gesture-begin, All triggering sequences and future ones will be
marked as "accepted" by the compositor, and events will be listened
for meanwhile there are active gestures.

If a sequence goes unclaimed for a short time, it will be
automatically "denied", and punted to the client or shell element
below.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
4ad2865cce events: Update current time on CLUTTER_TOUCH_BEGIN events
Just as with key/button press events, update the current interaction
time when a touch begins on a window.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
b9687d1a72 ui: Remove unneeded code
There's no way now that GDK will hold a grab, so it is safe to remove
this now.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
66d18fcc55 x11/events: Filter out all pointer/touch GDK events
Mutter does its own input event processing, including for the places
where interaction is wanted with the remaining GTK UI elements
(frames), so GDK is largely disposable.

Even though the GDK display connection remains, and events will
be delivered over there due to event selections on that display,
all pointer and touch events will be handled and filtered out by
the GDK filter function.

The dedicated event processing meant for frames in src/ui/ui.c
now hooks to the display connection through
meta_display_events_x11_add_func(), added to let all event filters
run and stop processing at a single point.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
321cd5d85f ui: Remove XI_TouchBegin handling from window frame event handlers
This is now unnecessary as only pointer events are selected, so pointer
emulation will take care of sending only pointer events.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
ae91de5d03 frame: Only select for ButtonPress/Release/Motion/Crossing
Touch events are largely ignored on GdkEvent emulation, so only
make frames receive pointer events, only the pointer emulating
touch will be reported, and any other further touches will be
ignored, which is about the behavior we want. This makes window
dragging possible again on touch.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
7247b8d81b backend-x11: Remove pointless goto
The function is not as complex as needing that, plus it always jumped
anytime bypass_clutter is TRUE, so make all conditional code depend on
that.
2014-06-25 15:17:12 +02:00
247 changed files with 90414 additions and 58612 deletions

14
.gitignore vendored
View File

@@ -43,10 +43,6 @@ POTFILES
po/*.pot
libmutter.pc
mutter
mutter-restart-helper
mutter-test-client
mutter-test-runner
mutter-all.test
org.gnome.mutter.gschema.valid
org.gnome.mutter.gschema.xml
org.gnome.mutter.wayland.gschema.valid
@@ -55,6 +51,16 @@ testasyncgetprop
testboxes
testgradient
m4/*
mutter-grayscale
mutter-mag
mutter-message
mutter-window-demo
focus-window
test-attached
test-focus
test-gravity
test-resizing
test-size-hints
INSTALL
mkinstalldirs
src/mutter-enum-types.[ch]

280
NEWS
View File

@@ -1,283 +1,3 @@
3.16.2
======
* Fix scroll button setting [Ondrej; #747967]
* Don't reset idle time for non-hardware events [Rui; #748541]
* Honor default value for click method setting [Rui; #746290]
* Misc. bug fixes [Rui; #748478]
Contributors:
Carlos Garnacho, Ondrej Holy, Rui Matos
3.16.1.1
========
* Prevent a crash when switching VTs or adding input devices [Carlos; #747886]
Contributors:
Carlos Garnacho
3.16.1
======
* Add function to refresh all background instances [Rui; #739178]
* Fix swapped scroll methods on wayland [Ondrej; #746870]
* Manually activate stage to fix accessibility on wayland [Ray, Rui; #746670]
* Center pointer on primary monitor on startup [Carlos; #746896]
* wayland: Reword synchronized state application semantics [Jonas; #743617]
* Ensure input settings are applied on startup [Rui; #747434]
* Misc. bug fixes [Jonas, Giovanni, Calvin, Ray, Rui; #744932, #746509, #746692,
#746510, #746545, #747263]
Contributors:
Jonas Ådahl, Giovanni Campagna, Carlos Garnacho, Ondrej Holy, Rui Matos,
Jasper St. Pierre, Ray Strode, Calvin Walton
Translations:
Khaled Hosny [ar], Marek Černocký [cs]
3.16.0
======
* wayland: Don't skip notifying about initial maximized state [Jonas; #745303]
Contributors:
Jonas Ådahl
Translations:
Kjartan Maraas [nb], Jiri Grönroos [fi], Andika Triwidada [id],
Inaki Larranaga Murgoitio [eu], Ask H. Larsen [da], Muhammet Kara [tr]
3.15.92
=======
* Ensure pointer visibility on monitor changes [Rui, Marek; #745121, #745752]
* Fix geometry of shaded windows [Florian; #746145]
* Take over cursor visibility handling from gsd [Carlos; #712775]
* Fix touch interaction on window decorations [Carlos; #745335]
* Add options for libinput_config_click_method [Carlos; #746290]
* Scale window decorations on HiDPI displays [Florian; #744354]
* Misc. bug fixes [Carlos, Ray, Rui; #745163, #746295, #746098, #745734]
Contributors:
Marek Chalupa, Carlos Garnacho, Rui Matos, Florian Müllner,
Jasper St. Pierre, Ray Strode
Translations:
Piotr Drąg [pl], Milo Casagrande [it], Changwoo Ryu [ko],
Daniel Korostil [uk], Baurzhan Muftakhidinov [kk], Trần Ngọc Quân [vi],
Alexander Shopov [bg], Jordi Mas [ca], Samir Ribic [bs], A S Alam [pa],
Matej Urbančič [sl]
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]
* 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]
Contributors:
Jonas Ådahl, Cosimo Cecchi, Carlos Garnacho, Rui Matos, Jasper St. Pierre,
Ray Strode, Chris Wilson
Translations:
Yosef Or Boczko [he], Yuri Myasoedov [ru], Kristjan SCHMIDT [eo],
Matej Urbančič [sl], Dušan Kazik [sk]
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
======
* 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
Translations:
Trần Ngọc Quân [vi], Muhammet Kara [tr]
3.15.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]
Contributors:
Emmanuele Bassi, Carlos Garnacho, Jonathon Jongsma, Ting-Wei Lan, Rui Matos,
Florian Müllner, Bastien Nocera, Jasper St. Pierre, Ray Strode
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
3.14.1
======
* Fix move-titlebar-onscreen function [Florian; #736915]
* Fix stacking of the guard window [Owen; #737233]
* Fix keycode lookup for non-default layouts [Rui; #737134]
* Fix workspaces-only-on-primary handling [Florian; #737178]
* Don't unstick sticky windows on workspace removal [Florian; #737625]
* Do not auto-minimize fullscreen windows [Jasper; #705177]
* Upload keymap to newly added keyboard devices [Rui; #737673]
* Apply keyboard repeat settings [Rui; #728055]
* Don't send pressed keys on enter [Rui; #727178]
* Fix build without wayland/native [Rico; #738225]
* Send modifiers after the key event [Rui; #738238]
* Fix unredirect heuristic [Adel; #738271]
* Do not show system chrome over fullscreen windows [Florian; #693991]
* Misc. bug fixes [Florian, Adel, Tom; #737135, #737581, #738146, #738384]
Contributors:
Tom Beckmann, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
Jasper St. Pierre, Rico Tzschichholz, Owen W. Taylor
Translations:
Krishnababu Krothapalli [te], Мирослав Николић [sr, sr@latin],
Alexander Shopov [bg], Saibal Ray [bn_IN], Milo Casagrande [it],
Rūdolfs Mazurs [lv]
3.14.0
======
* Fix placement of popup windows on wayland [Jasper; #736812]
* Only increment serial once per event [Jasper; #736840]
* Fix window positioning regression with non-GTK+ toolkits [Owen; #736719]
Contributors:
Jasper St. Pierre, Owen W. Taylor
Translations:
Saibal Ray [bn_IN], Dušan Kazik [sk], Manoj Kumar Giri [or],
Christian Kirbach [de], Ask H. Larsen [da], YunQiang Su [zh_CN],
Bernd Homuth [de], Shankar Prasad [kn], Petr Kovar [cs], Rajesh Ranjan [hi]
3.13.92
=======
* Rewrite background code [Owen; #735637, #736568]
* Fix size in nested mode [Owen; #736279]
* Fix destroy animation of background windows [Florian; #735927]
* Wire keymap changes up to the wayland frontend [Rui; #736433]
* Add a test framework and stacking tests [Owen; #736505]
* Simplify handling of the merged X and wayland stack [Owen; #736559]
* Fix cursor size on HiDPI [Adel; #729337]
* Misc. bug fixes [Owen; #735632, #736589, #736694]
Contributors:
Adel Gadllah, Rui Matos, Florian Müllner, Jasper St. Pierre, Owen W. Taylor
Translations:
Andika Triwidada [id], Piotr Drąg [pl], Changwoo Ryu [ko],
Kjartan Maraas [nb], Ville-Pekka Vainio [fi], Yuri Myasoedov [ru],
Aurimas Černius [lt], Balázs Úr [hu], Sweta Kothari [gu], A S Alam [pa],
Sandeep Sheshrao Shedmake [mr], Shantha kumar [ta], Gil Forcada [ca],
Carles Ferrando [ca@valencia], Mattias Eriksson [sv]
3.13.91
=======
* Misc. bug fixes [Carlos; #735452]
Contributors:
Adel Gadllah, Carlos Garnacho, Rui Matos, Jasper St. Pierre,
Rico Tzschichholz
Translations:
Chao-Hsiung Liao po/zh_HK, zh_TW.po, Enrico Nicoletto [pt_BR],
Kjartan Maraas [nb], Fran Diéguez [gl], Yosef Or Boczko [he],
Maria Mavridou [el], Claude Paroz [fr]
3.13.90
=======
* Only call XSync() once per frame [Rui; #728464]
* Update capabilities on device list changes [Carlos; #733563]
* Make use of GLSL optional [Adel; #733623]
* Handle gestures and touch events on wayland [Carlos; #733631]
* Add support for unminimize compositor effects [Cosimo; #733789]
* Always set the frame background to None [Giovanni; #734054]
* Add backend methods to handle keymaps [Rui; #734301]
* Actually mark revalidated MetaTextureTower levels as valid [Owen; #734400]
* Rely on explicit -backward switcher keybindings instead of <shift>-magic
[Christophe; #732295, #732385]
* Misc. bug fixes and cleanups [Rui, Adel, Christophe; #727178, #734852,
#734960]
Contributors:
Emmanuele Bassi, Giovanni Campagna, Cosimo Cecchi, Piotr Drąg,
Christophe Fergeau, Adel Gadllah, Carlos Garnacho, Rui Matos,
Florian Müllner, Jasper St. Pierre, Rico Tzschichholz, Olav Vitters,
Owen W. Taylor
Translations:
Kjartan Maraas [nb], Inaki Larranaga Murgoitio [eu], Lasse Liehu [fi],
ngoswami [as], Daniel Mustieles [es]
3.13.4
======
* Fix move/resize operations for wayland clients [Marek; #731237]
* Add ::first-frame signal to MetaWindowActor [Owen; #732343]
* Handle keysyms without the XF86 prefix [Owen; #727993]
* Add touch gesture support [Carlos]
* Fix a deadlock when exiting [Owen; #733068]
* Add framework for restarting the compositor with nice visuals
[Owen; #733026]
* Toggle seat capabilities on VT switch [Carlos; #733563]
* Misc bug fixes [Florian, Owen; #732695, #732350]
Contributors:
Tom Beckmann, Giovanni Campagna, Marek Chalupa, Adel Gadllah,
Carlos Garnacho, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz,
Owen W. Taylor
Translations:
Yuri Myasoedov [ru], Fran Diéguez [gl], Aurimas Černius [lt], MarMav [el],
Enrico Nicoletto [pt_BR]
3.13.3
======
* Improve behavior of window buttons with compositor menus [Florian; #731058]

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], [16])
m4_define([mutter_micro_version], [2])
m4_define([mutter_minor_version], [13])
m4_define([mutter_micro_version], [3])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@@ -72,27 +72,20 @@ CLUTTER_PACKAGE=clutter-1.0
MUTTER_PC_MODULES="
gtk+-3.0 >= 3.9.11
gio-unix-2.0 >= 2.35.1
gio-2.0 >= 2.25.10
pango >= 1.2.0
cairo >= 1.10.0
gsettings-desktop-schemas >= 3.15.92
$CLUTTER_PACKAGE >= 1.21.3
gsettings-desktop-schemas >= 3.7.3
xcomposite >= 0.2 xfixes xext xdamage xi >= 1.6.0
xcursor
$CLUTTER_PACKAGE >= 1.17.5
clutter-wayland-1.0
clutter-wayland-compositor-1.0
clutter-egl-1.0
cogl-1.0 >= 1.17.1
wayland-server >= 1.4.93
upower-glib >= 0.99.0
gnome-desktop-3.0
xcomposite >= 0.2
xcursor
xdamage
xext
xfixes
xi >= 1.6.0
xkbfile
xkeyboard-config
xkbcommon >= 0.4.3
xkbcommon-x11
xrender
x11-xcb
xcb-randr
"
GLIB_GSETTINGS
@@ -126,12 +119,6 @@ AC_ARG_WITH([xwayland-path],
[XWAYLAND_PATH="$withval"],
[XWAYLAND_PATH="$bindir/Xwayland"])
AC_ARG_ENABLE(installed_tests,
AS_HELP_STRING([--enable-installed-tests],
[Install test programs (default: no)]),,
[enable_installed_tests=no])
AM_CONDITIONAL(BUILDOPT_INSTALL_TESTS, test x$enable_installed_tests = xyes)
## here we get the flags we'll actually use
# Unconditionally use this dir to avoid a circular dep with gnomecc
@@ -197,43 +184,19 @@ if test x$found_introspection != xno; then
AC_SUBST(META_GIR)
fi
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
AC_SUBST([WAYLAND_SCANNER])
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"
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]))
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"])
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [libdrm libsystemd], [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])
PKG_CHECK_EXISTS([xi >= 1.6.99.1],
AC_DEFINE([HAVE_XI23],[1],[Define if you have support for XInput 2.3 or greater]))
@@ -271,8 +234,16 @@ if test x$have_xinerama = xno; then
AC_MSG_ERROR([Xinerama extension was not found])
fi
AC_DEFINE_UNQUOTED([XKB_BASE], ["`$PKG_CONFIG --variable xkb_base xkeyboard-config`"],
[XKB base dir])
found_xkb=no
AC_CHECK_LIB(X11, XkbQueryExtension,
[AC_CHECK_HEADER(X11/XKBlib.h,
found_xkb=yes)],
, $ALL_X_LIBS)
if test "x$found_xkb" = "xyes"; then
AC_DEFINE(HAVE_XKB, , [Have keyboard extension library])
fi
RANDR_LIBS=
found_randr=no
@@ -434,8 +405,6 @@ mutter-$VERSION
libcanberra: ${have_libcanberra}
Introspection: ${found_introspection}
Session management: ${found_sm}
Wayland: ${have_wayland}
Native (KMS) backend: ${have_native_backend}
"

View File

@@ -45,68 +45,26 @@
_description="Move window one monitor down" />
<KeyListEntry name="switch-applications"
reverse-entry="switch-applications-backward"
_description="Switch applications"/>
<KeyListEntry name="switch-applications-backward"
reverse-entry="switch-applications"
hidden="true"
_description="Switch to previous application"/>
<KeyListEntry name="switch-windows"
reverse-entry="switch-windows-backward"
_description="Switch windows"/>
<KeyListEntry name="switch-windows-backward"
reverse-entry="switch-windows"
hidden="true"
_description="Switch to previous window"/>
<KeyListEntry name="switch-group"
reverse-entry="switch-group-backward"
_description="Switch windows of an application"/>
<KeyListEntry name="switch-group-backward"
reverse-entry="switch-group"
hidden="true"
_description="Switch to previous window of an application"/>
<KeyListEntry name="switch-panels"
reverse-entry="switch-panels-backward"
_description="Switch system controls"/>
<KeyListEntry name="switch-panels-backward"
reverse-entry="switch-panels"
hidden="true"
_description="Switch to previous system control"/>
<KeyListEntry name="cycle-windows"
reverse-entry="cycle-windows-backward"
_description="Switch windows directly"/>
<KeyListEntry name="cycle-windows-backward"
reverse-entry="cycle-windows"
hidden="true"
_description="Switch directly to previous window"/>
<KeyListEntry name="cycle-group"
reverse-entry="cycle-group-backward"
_description="Switch windows of an app directly"/>
<KeyListEntry name="cycle-group-backward"
reverse-entry="cycle-group"
hidden="true"
_description="Switch directly to previous window of an app"/>
<KeyListEntry name="cycle-panels"
reverse-entry="cycle-panels-backward"
_description="Switch system controls directly"/>
<KeyListEntry name="cycle-panels-backward"
reverse-entry="cycle-panels"
hidden="true"
_description="Switch directly to previous system control"/>
<KeyListEntry name="show-desktop"
_description="Hide all normal windows"/>

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,24 +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 \
wayland \
$(NULL)
endif
MKDB_OPTIONS+=--ignore-files="$(IGNORE_HFILES)"
# Images to copy into HTML directory.

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
@@ -291,7 +300,6 @@ MetaPluginVersion
META_PLUGIN_DECLARE
meta_plugin_switch_workspace_completed
meta_plugin_minimize_completed
meta_plugin_unminimize_completed
meta_plugin_maximize_completed
meta_plugin_unmaximize_completed
meta_plugin_map_completed
@@ -549,6 +557,7 @@ meta_window_is_skip_taskbar
meta_window_get_rect
meta_window_get_buffer_rect
meta_window_get_frame_rect
meta_window_get_outer_rect
meta_window_client_rect_to_frame_rect
meta_window_frame_rect_to_client_rect
meta_window_get_screen

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

@@ -23,8 +23,7 @@ environment.</description>
<download-page rdf:resource="http://download.gnome.org/sources/mutter/" />
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=mutter" />
<category rdf:resource="http://api.gnome.org/doap-extensions#core" />
<programming-language>C</programming-language>
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
<maintainer>
<foaf:Person>

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

2298
po/ar.po

File diff suppressed because it is too large Load Diff

1520
po/as.po

File diff suppressed because it is too large Load Diff

1903
po/bg.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3797
po/bs.po

File diff suppressed because it is too large Load Diff

2204
po/ca.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2362
po/cs.po

File diff suppressed because it is too large Load Diff

2400
po/da.po

File diff suppressed because it is too large Load Diff

1530
po/de.po

File diff suppressed because it is too large Load Diff

3287
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

2098
po/es.po

File diff suppressed because it is too large Load Diff

2427
po/eu.po

File diff suppressed because it is too large Load Diff

2277
po/fi.po

File diff suppressed because it is too large Load Diff

1752
po/fr.po

File diff suppressed because it is too large Load Diff

2067
po/gl.po

File diff suppressed because it is too large Load Diff

1759
po/gu.po

File diff suppressed because it is too large Load Diff

2019
po/he.po

File diff suppressed because it is too large Load Diff

1952
po/hi.po

File diff suppressed because it is too large Load Diff

2450
po/hu.po

File diff suppressed because it is too large Load Diff

1602
po/id.po

File diff suppressed because it is too large Load Diff

1772
po/it.po

File diff suppressed because it is too large Load Diff

1621
po/kk.po

File diff suppressed because it is too large Load Diff

1978
po/kn.po

File diff suppressed because it is too large Load Diff

2020
po/ko.po

File diff suppressed because it is too large Load Diff

2197
po/lt.po

File diff suppressed because it is too large Load Diff

1297
po/lv.po

File diff suppressed because it is too large Load Diff

1810
po/mr.po

File diff suppressed because it is too large Load Diff

2049
po/nb.po

File diff suppressed because it is too large Load Diff

1808
po/or.po

File diff suppressed because it is too large Load Diff

2376
po/pa.po

File diff suppressed because it is too large Load Diff

1731
po/pl.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2318
po/ru.po

File diff suppressed because it is too large Load Diff

2669
po/sk.po

File diff suppressed because it is too large Load Diff

1864
po/sl.po

File diff suppressed because it is too large Load Diff

2394
po/sr.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2334
po/sv.po

File diff suppressed because it is too large Load Diff

1846
po/ta.po

File diff suppressed because it is too large Load Diff

1877
po/te.po

File diff suppressed because it is too large Load Diff

2948
po/tr.po

File diff suppressed because it is too large Load Diff

2414
po/uk.po

File diff suppressed because it is too large Load Diff

4473
po/vi.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,49 +0,0 @@
# A framework for running scripted tests
if HAVE_WAYLAND
if BUILDOPT_INSTALL_TESTS
stackingdir = $(pkgdatadir)/tests/stacking
dist_stacking_DATA = \
tests/stacking/basic-x11.metatest \
tests/stacking/basic-wayland.metatest \
tests/stacking/minimized.metatest \
tests/stacking/mixed-windows.metatest \
tests/stacking/override-redirect.metatest
mutter-all.test: tests/mutter-all.test.in
$(AM_V_GEN) sed -e "s|@libexecdir[@]|$(libexecdir)|g" $< > $@.tmp && mv $@.tmp $@
installedtestsdir = $(datadir)/installed-tests/mutter
installedtests_DATA = mutter-all.test
installedtestsbindir = $(libexecdir)/installed-tests/mutter
installedtestsbin_PROGRAMS = mutter-test-client mutter-test-runner
else
noinst_PROGRAMS += mutter-test-client mutter-test-runner
endif
EXTRA_DIST += tests/mutter-all.test.in
mutter_test_client_SOURCES = tests/test-client.c
mutter_test_client_LDADD = $(MUTTER_LIBS) libmutter.la
mutter_test_runner_SOURCES = tests/test-runner.c
mutter_test_runner_LDADD = $(MUTTER_LIBS) libmutter.la
.PHONY: run-tests
run-tests: mutter-test-client mutter-test-runner
./mutter-test-runner $(dist_stacking_DATA)
endif
# Some random test programs for bits of the code
testboxes_SOURCES = core/testboxes.c
testasyncgetprop_SOURCES = x11/testasyncgetprop.c
noinst_PROGRAMS+=testboxes testasyncgetprop
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la

View File

@@ -5,16 +5,11 @@ lib_LTLIBRARIES = libmutter.la
SUBDIRS=compositor/plugins
EXTRA_DIST =
NULL =
AM_CPPFLAGS = \
-DCLUTTER_ENABLE_COMPOSITOR_API \
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
-DCLUTTER_DISABLE_DEPRECATION_WARNINGS \
-DCOGL_DISABLE_DEPRECATION_WARNINGS \
$(MUTTER_CFLAGS) \
$(MUTTER_NATIVE_BACKEND_CFLAGS) \
-I$(builddir) \
@@ -32,37 +27,28 @@ 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) \
meta/meta-version.h \
mutter-enum-types.h \
mutter-enum-types.c \
$(NULL)
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)
endif
xdg-shell-server-protocol.h
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.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,33 +61,25 @@ 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 \
backends/meta-stage.c \
backends/edid-parse.c \
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 \
@@ -115,17 +93,11 @@ libmutter_la_SOURCES = \
compositor/compositor.c \
compositor/compositor-private.h \
compositor/meta-background.c \
compositor/meta-background-private.h \
compositor/meta-background-actor.c \
compositor/meta-background-actor-private.h \
compositor/meta-background-image.c \
compositor/meta-background-group.c \
compositor/meta-cullable.c \
compositor/meta-cullable.h \
compositor/meta-dnd-actor.c \
compositor/meta-dnd-actor-private.h \
compositor/meta-feedback-actor.c \
compositor/meta-feedback-actor-private.h \
compositor/meta-module.c \
compositor/meta-module.h \
compositor/meta-plugin.c \
@@ -139,6 +111,10 @@ libmutter_la_SOURCES = \
compositor/meta-surface-actor.h \
compositor/meta-surface-actor-x11.c \
compositor/meta-surface-actor-x11.h \
compositor/meta-surface-actor-wayland.c \
compositor/meta-surface-actor-wayland.h \
compositor/meta-stage.h \
compositor/meta-stage.c \
compositor/meta-texture-rectangle.c \
compositor/meta-texture-rectangle.h \
compositor/meta-texture-tower.c \
@@ -154,7 +130,6 @@ libmutter_la_SOURCES = \
meta/compositor.h \
meta/meta-background.h \
meta/meta-background-actor.h \
meta/meta-background-image.h \
meta/meta-background-group.h \
meta/meta-plugin.h \
meta/meta-shadow-factory.h \
@@ -175,8 +150,10 @@ libmutter_la_SOURCES = \
meta/errors.h \
core/frame.c \
core/frame.h \
core/meta-gesture-tracker.c \
core/meta-gesture-tracker-private.h \
ui/gradient.c \
meta/gradient.h \
core/gesture-tracker.c \
core/gesture-tracker-private.h \
core/keybindings.c \
core/keybindings-private.h \
core/main.c \
@@ -188,7 +165,6 @@ libmutter_la_SOURCES = \
core/screen-private.h \
meta/screen.h \
meta/types.h \
core/restart.c \
core/stack.c \
core/stack.h \
core/stack-tracker.c \
@@ -206,6 +182,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 \
@@ -231,30 +210,18 @@ libmutter_la_SOURCES = \
x11/xprops.c \
x11/xprops.h \
x11/mutter-Xatomtype.h \
$(NULL)
if HAVE_WAYLAND
libmutter_la_SOURCES += \
compositor/meta-surface-actor-wayland.c \
compositor/meta-surface-actor-wayland.h \
wayland/meta-wayland.c \
wayland/meta-wayland.h \
wayland/meta-wayland-private.h \
wayland/meta-xwayland.c \
wayland/meta-xwayland.h \
wayland/meta-xwayland-private.h \
wayland/meta-wayland-buffer.c \
wayland/meta-wayland-buffer.h \
wayland/meta-wayland-region.c \
wayland/meta-wayland-region.h \
wayland/meta-wayland-data-device.c \
wayland/meta-wayland-data-device.h \
wayland/meta-wayland-keyboard.c \
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 +233,28 @@ libmutter_la_SOURCES += \
wayland/meta-wayland-outputs.c \
wayland/meta-wayland-outputs.h \
wayland/window-wayland.c \
wayland/window-wayland.h \
$(NULL)
endif
wayland/window-wayland.h
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,18 +267,16 @@ libmutterinclude_headers = \
meta/compositor.h \
meta/display.h \
meta/errors.h \
meta/gradient.h \
meta/group.h \
meta/keybindings.h \
meta/main.h \
meta/meta-backend.h \
meta/meta-background.h \
meta/meta-background-actor.h \
meta/meta-background-image.h \
meta/meta-background-group.h \
meta/meta-background.h \
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 +286,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
@@ -353,17 +310,10 @@ nodist_libmutterinclude_HEADERS = \
$(libmutterinclude_built_headers)
bin_PROGRAMS=mutter
noinst_PROGRAMS=
mutter_SOURCES = core/mutter.c
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
libexec_PROGRAMS = mutter-restart-helper
mutter_restart_helper_SOURCES = core/restart-helper.c
mutter_restart_helper_LDADD = $(MUTTER_LIBS)
include Makefile-tests.am
if HAVE_INTROSPECTION
include $(INTROSPECTION_MAKEFILE)
@@ -397,33 +347,37 @@ Meta-$(api_version).gir: libmutter.la
endif
testboxes_SOURCES = core/testboxes.c
testgradient_SOURCES = ui/testgradient.c
testasyncgetprop_SOURCES = x11/testasyncgetprop.c
noinst_PROGRAMS=testboxes testgradient testasyncgetprop
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
testgradient_LDADD = $(MUTTER_LIBS) libmutter.la
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
CLEANFILES = \
$(mutter_built_sources) \
$(libmutterinclude_built_headers) \
$(typelib_DATA) \
$(gir_DATA)
DISTCLEANFILES = \
$(libmutterinclude_built_headers)
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)
BUILT_SOURCES = \
$(mutter_built_sources) \
$(libmutterinclude_built_headers)
org.gnome.Mutter.IdleMonitor.xml
BUILT_SOURCES = $(mutter_built_sources)
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
CLEANFILES += $(MUTTER_STAMP_FILES)

View File

@@ -189,5 +189,7 @@ struct MonitorInfo
};
MonitorInfo *decode_edid (const uchar *data);
char *make_display_name (const MonitorInfo *info);
char *make_display_size_string (int width_mm, int height_mm);
#endif

View File

@@ -28,15 +28,7 @@
#include <glib-object.h>
#include <xkbcommon/xkbcommon.h>
#include <meta/meta-backend.h>
#include <meta/meta-idle-monitor.h>
#include "meta-cursor-renderer.h"
#include "meta-monitor-manager-private.h"
#define DEFAULT_XKB_RULES_FILE "evdev"
#define DEFAULT_XKB_MODEL "pc105+inet"
#include "meta-backend.h"
#define META_TYPE_BACKEND (meta_backend_get_type ())
#define META_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKEND, MetaBackend))
@@ -49,8 +41,8 @@ struct _MetaBackend
{
GObject parent;
GHashTable *device_monitors;
gint current_device_id;
MetaIdleMonitor *device_monitors[256];
int device_id_max;
};
struct _MetaBackendClass
@@ -74,40 +66,6 @@ struct _MetaBackendClass
void (* warp_pointer) (MetaBackend *backend,
int x,
int y);
void (* set_keymap) (MetaBackend *backend,
const char *layouts,
const char *variants,
const char *options);
struct xkb_keymap * (* get_keymap) (MetaBackend *backend);
void (* lock_layout_group) (MetaBackend *backend,
guint idx);
void (* update_screen_size) (MetaBackend *backend, int width, int height);
void (* select_stage_events) (MetaBackend *backend);
};
MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend,
int device_id);
MetaMonitorManager * meta_backend_get_monitor_manager (MetaBackend *backend);
MetaCursorRenderer * meta_backend_get_cursor_renderer (MetaBackend *backend);
gboolean meta_backend_grab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp);
gboolean meta_backend_ungrab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp);
void meta_backend_warp_pointer (MetaBackend *backend,
int x,
int y);
struct xkb_keymap * meta_backend_get_keymap (MetaBackend *backend);
void meta_backend_update_last_device (MetaBackend *backend,
int device_id);
#endif /* META_BACKEND_PRIVATE_H */

View File

@@ -24,31 +24,19 @@
#include "config.h"
#include <meta/meta-backend.h>
#include "meta-backend.h"
#include "meta-backend-private.h"
#include "meta-input-settings-private.h"
#include <clutter/clutter.h>
#include "backends/x11/meta-backend-x11.h"
#include "meta-cursor-tracker-private.h"
#include "meta-stage.h"
#ifdef HAVE_NATIVE_BACKEND
#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;
/**
* meta_get_backend:
*
* Accessor for the singleton MetaBackend.
*
* Returns: (transfer none): The only #MetaBackend there is.
*/
MetaBackend *
meta_get_backend (void)
{
@@ -59,9 +47,6 @@ struct _MetaBackendPrivate
{
MetaMonitorManager *monitor_manager;
MetaCursorRenderer *cursor_renderer;
MetaInputSettings *input_settings;
ClutterActor *stage;
};
typedef struct _MetaBackendPrivate MetaBackendPrivate;
@@ -72,244 +57,26 @@ 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);
}
static void
meta_backend_sync_screen_size (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
int width, height;
meta_monitor_manager_get_screen_size (priv->monitor_manager, &width, &height);
META_BACKEND_GET_CLASS (backend)->update_screen_size (backend, width, height);
}
static void
center_pointer (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
MetaMonitorInfo *monitors, *primary;
guint n_monitors;
monitors = meta_monitor_manager_get_monitor_infos (priv->monitor_manager, &n_monitors);
primary = &monitors[meta_monitor_manager_get_primary_index (priv->monitor_manager)];
meta_backend_warp_pointer (backend,
primary->rect.x + primary->rect.width / 2,
primary->rect.y + primary->rect.height / 2);
}
static void
on_monitors_changed (MetaMonitorManager *monitors,
gpointer user_data)
{
MetaBackend *backend = META_BACKEND (user_data);
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
ClutterInputDevice *device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE);
ClutterPoint point;
meta_backend_sync_screen_size (backend);
if (clutter_input_device_get_coords (device, NULL, &point))
{
/* If we're outside all monitors, warp the pointer back inside */
if (meta_monitor_manager_get_monitor_at_point (monitors, point.x, point.y) < 0)
center_pointer (backend);
}
}
static MetaIdleMonitor *
meta_backend_create_idle_monitor (MetaBackend *backend,
int device_id)
{
return META_BACKEND_GET_CLASS (backend)->create_idle_monitor (backend, device_id);
}
static void
create_device_monitor (MetaBackend *backend,
int device_id)
{
MetaIdleMonitor *idle_monitor;
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);
}
static void
destroy_device_monitor (MetaBackend *backend,
int device_id)
{
g_hash_table_remove (backend->device_monitors, &device_id);
}
static void
on_device_added (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
gpointer user_data)
{
MetaBackend *backend = META_BACKEND (user_data);
int device_id = clutter_input_device_get_device_id (device);
create_device_monitor (backend, device_id);
}
static inline gboolean
device_is_slave_touchscreen (ClutterInputDevice *device)
{
return (clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_MASTER &&
clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE);
}
static inline gboolean
check_has_pointing_device (ClutterDeviceManager *manager)
{
const GSList *devices;
devices = clutter_device_manager_peek_devices (manager);
for (; devices; devices = devices->next)
{
ClutterInputDevice *device = devices->data;
if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER)
continue;
if (clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE ||
clutter_input_device_get_device_type (device) == CLUTTER_KEYBOARD_DEVICE)
continue;
return TRUE;
}
return FALSE;
}
static inline gboolean
check_has_slave_touchscreen (ClutterDeviceManager *manager)
{
const GSList *devices;
devices = clutter_device_manager_peek_devices (manager);
for (; devices; devices = devices->next)
{
ClutterInputDevice *device = devices->data;
if (clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_MASTER &&
clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE)
return TRUE;
}
return FALSE;
}
static void
on_device_removed (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
gpointer user_data)
{
MetaBackend *backend = META_BACKEND (user_data);
int device_id = clutter_input_device_get_device_id (device);
destroy_device_monitor (backend, device_id);
/* If the device the user last interacted goes away, check again pointer
* visibility.
*/
if (backend->current_device_id == device_id)
{
MetaCursorTracker *cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
gboolean has_touchscreen, has_pointing_device;
ClutterInputDeviceType device_type;
device_type = clutter_input_device_get_device_type (device);
has_touchscreen = check_has_slave_touchscreen (device_manager);
if (device_type == CLUTTER_TOUCHSCREEN_DEVICE && has_touchscreen)
{
/* There's more touchscreens left, keep the pointer hidden */
meta_cursor_tracker_set_pointer_visible (cursor_tracker, FALSE);
}
else if (device_type != CLUTTER_KEYBOARD_DEVICE)
{
has_pointing_device = check_has_pointing_device (device_manager);
meta_cursor_tracker_set_pointer_visible (cursor_tracker,
has_pointing_device &&
!has_touchscreen);
}
}
}
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)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
priv->stage = meta_stage_new ();
clutter_actor_realize (priv->stage);
META_BACKEND_GET_CLASS (backend)->select_stage_events (backend);
priv->monitor_manager = create_monitor_manager (backend);
g_signal_connect (priv->monitor_manager, "monitors-changed",
G_CALLBACK (on_monitors_changed), backend);
meta_backend_sync_screen_size (backend);
priv->monitor_manager = META_BACKEND_GET_CLASS (backend)->create_monitor_manager (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);
{
MetaCursorTracker *cursor_tracker;
ClutterDeviceManager *manager;
gboolean has_touchscreen = FALSE;
GSList *devices, *l;
/* Create the core device monitor. */
create_device_monitor (backend, 0);
manager = clutter_device_manager_get_default ();
g_signal_connect_object (manager, "device-added",
G_CALLBACK (on_device_added), backend, 0);
g_signal_connect_object (manager, "device-removed",
G_CALLBACK (on_device_removed), backend, 0);
devices = clutter_device_manager_list_devices (manager);
for (l = devices; l != NULL; l = l->next)
{
ClutterInputDevice *device = l->data;
on_device_added (manager, device, backend);
has_touchscreen |= device_is_slave_touchscreen (device);
}
cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
meta_cursor_tracker_set_pointer_visible (cursor_tracker, !has_touchscreen);
g_slist_free (devices);
}
priv->input_settings = meta_input_settings_create ();
center_pointer (backend);
}
static MetaCursorRenderer *
@@ -336,21 +103,6 @@ meta_backend_real_ungrab_device (MetaBackend *backend,
return TRUE;
}
static void
meta_backend_real_update_screen_size (MetaBackend *backend,
int width, int height)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
clutter_actor_set_size (priv->stage, width, height);
}
static void
meta_backend_real_select_stage_events (MetaBackend *backend)
{
/* Do nothing */
}
static void
meta_backend_class_init (MetaBackendClass *klass)
{
@@ -362,27 +114,6 @@ meta_backend_class_init (MetaBackendClass *klass)
klass->create_cursor_renderer = meta_backend_real_create_cursor_renderer;
klass->grab_device = meta_backend_real_grab_device;
klass->ungrab_device = meta_backend_real_ungrab_device;
klass->update_screen_size = meta_backend_real_update_screen_size;
klass->select_stage_events = meta_backend_real_select_stage_events;
g_signal_new ("keymap-changed",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
g_signal_new ("keymap-layout-group-changed",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 1, G_TYPE_UINT);
g_signal_new ("last-device-changed",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 1, G_TYPE_INT);
}
static void
@@ -391,25 +122,44 @@ meta_backend_init (MetaBackend *backend)
_backend = backend;
}
/* FIXME -- destroy device monitors at some point */
G_GNUC_UNUSED static void
destroy_device_monitor (MetaBackend *backend,
int device_id)
{
g_clear_object (&backend->device_monitors[device_id]);
if (device_id == backend->device_id_max)
backend->device_id_max--;
}
static MetaIdleMonitor *
meta_backend_create_idle_monitor (MetaBackend *backend,
int device_id)
{
return META_BACKEND_GET_CLASS (backend)->create_idle_monitor (backend, device_id);
}
static void
meta_backend_post_init (MetaBackend *backend)
{
META_BACKEND_GET_CLASS (backend)->post_init (backend);
}
/**
* meta_backend_get_idle_monitor: (skip)
*/
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);
if (!backend->device_monitors[device_id])
{
backend->device_monitors[device_id] = meta_backend_create_idle_monitor (backend, device_id);
backend->device_id_max = MAX (backend->device_id_max, device_id);
}
return backend->device_monitors[device_id];
}
/**
* meta_backend_get_monitor_manager: (skip)
*/
MetaMonitorManager *
meta_backend_get_monitor_manager (MetaBackend *backend)
{
@@ -418,9 +168,6 @@ meta_backend_get_monitor_manager (MetaBackend *backend)
return priv->monitor_manager;
}
/**
* meta_backend_get_cursor_renderer: (skip)
*/
MetaCursorRenderer *
meta_backend_get_cursor_renderer (MetaBackend *backend)
{
@@ -429,9 +176,6 @@ meta_backend_get_cursor_renderer (MetaBackend *backend)
return priv->cursor_renderer;
}
/**
* meta_backend_grab_device: (skip)
*/
gboolean
meta_backend_grab_device (MetaBackend *backend,
int device_id,
@@ -440,9 +184,6 @@ meta_backend_grab_device (MetaBackend *backend,
return META_BACKEND_GET_CLASS (backend)->grab_device (backend, device_id, timestamp);
}
/**
* meta_backend_ungrab_device: (skip)
*/
gboolean
meta_backend_ungrab_device (MetaBackend *backend,
int device_id,
@@ -451,9 +192,6 @@ meta_backend_ungrab_device (MetaBackend *backend,
return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp);
}
/**
* meta_backend_warp_pointer: (skip)
*/
void
meta_backend_warp_pointer (MetaBackend *backend,
int x,
@@ -462,86 +200,6 @@ meta_backend_warp_pointer (MetaBackend *backend,
META_BACKEND_GET_CLASS (backend)->warp_pointer (backend, x, y);
}
void
meta_backend_set_keymap (MetaBackend *backend,
const char *layouts,
const char *variants,
const char *options)
{
META_BACKEND_GET_CLASS (backend)->set_keymap (backend, layouts, variants, options);
}
/**
* meta_backend_get_keymap: (skip)
*/
struct xkb_keymap *
meta_backend_get_keymap (MetaBackend *backend)
{
return META_BACKEND_GET_CLASS (backend)->get_keymap (backend);
}
void
meta_backend_lock_layout_group (MetaBackend *backend,
guint idx)
{
META_BACKEND_GET_CLASS (backend)->lock_layout_group (backend, idx);
}
/**
* meta_backend_get_stage:
* @backend: A #MetaBackend
*
* Gets the global #ClutterStage that's managed by this backend.
*
* Returns: (transfer none): the #ClutterStage
*/
ClutterActor *
meta_backend_get_stage (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
return priv->stage;
}
void
meta_backend_update_last_device (MetaBackend *backend,
int device_id)
{
ClutterInputDeviceType device_type;
MetaCursorTracker *cursor_tracker;
ClutterDeviceManager *manager;
ClutterInputDevice *device;
if (backend->current_device_id == device_id)
return;
manager = clutter_device_manager_get_default ();
device = clutter_device_manager_get_device (manager, device_id);
if (!device ||
clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER)
return;
device_type = clutter_input_device_get_device_type (device);
cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
backend->current_device_id = device_id;
g_signal_emit_by_name (backend, "last-device-changed", device_id);
if (device_type == CLUTTER_KEYBOARD_DEVICE)
return;
switch (device_type)
{
case CLUTTER_TOUCHSCREEN_DEVICE:
meta_cursor_tracker_set_pointer_visible (cursor_tracker, FALSE);
break;
default:
meta_cursor_tracker_set_pointer_visible (cursor_tracker, TRUE);
break;
}
}
static GType
get_backend_type (void)
{
@@ -614,13 +272,9 @@ static GSourceFuncs event_funcs = {
event_dispatch
};
/**
* meta_clutter_init: (skip)
*/
void
meta_clutter_init (void)
{
ClutterSettings *clutter_settings;
GSource *source;
meta_create_backend ();
@@ -628,13 +282,6 @@ meta_clutter_init (void)
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
g_error ("Unable to initialize Clutter.\n");
/*
* XXX: We cannot handle high dpi scaling yet, so fix the scale to 1
* for now.
*/
clutter_settings = clutter_settings_get_default ();
g_object_set (clutter_settings, "window-scaling-factor", 1, NULL);
source = g_source_new (&event_funcs, sizeof (GSource));
g_source_attach (source, NULL);
g_source_unref (source);

View File

@@ -27,7 +27,9 @@
#include <glib-object.h>
#include <clutter/clutter.h>
#include <meta/meta-idle-monitor.h>
#include "meta-monitor-manager.h"
#include "meta-cursor-renderer.h"
typedef struct _MetaBackend MetaBackend;
typedef struct _MetaBackendClass MetaBackendClass;
@@ -36,15 +38,21 @@ GType meta_backend_get_type (void);
MetaBackend * meta_get_backend (void);
void meta_backend_set_keymap (MetaBackend *backend,
const char *layouts,
const char *variants,
const char *options);
MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend,
int device_id);
MetaMonitorManager * meta_backend_get_monitor_manager (MetaBackend *backend);
MetaCursorRenderer * meta_backend_get_cursor_renderer (MetaBackend *backend);
void meta_backend_lock_layout_group (MetaBackend *backend,
guint idx);
gboolean meta_backend_grab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp);
gboolean meta_backend_ungrab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp);
ClutterActor *meta_backend_get_stage (MetaBackend *backend);
void meta_backend_warp_pointer (MetaBackend *backend,
int x,
int y);
void meta_clutter_init (void);

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,18 +25,12 @@
#include "meta-cursor.h"
#include <cogl/cogl.h>
#ifdef HAVE_NATIVE_BACKEND
#include <gbm.h>
#endif
typedef struct {
CoglTexture2D *texture;
int hot_x, hot_y;
#ifdef HAVE_NATIVE_BACKEND
struct gbm_bo *bo;
#endif
int hot_x, hot_y;
} MetaCursorImage;
struct _MetaCursorReference {
@@ -50,10 +44,8 @@ CoglTexture *meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor
int *hot_x,
int *hot_y);
#ifdef HAVE_NATIVE_BACKEND
struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
int *hot_x,
int *hot_y);
#endif
#endif /* META_CURSOR_PRIVATE_H */

View File

@@ -27,14 +27,14 @@
#include "meta-cursor-renderer.h"
#include "meta-cursor-private.h"
#include <meta/meta-backend.h>
#include <meta/util.h>
#include <cogl/cogl.h>
#include <cogl/cogl-wayland-server.h>
#include <clutter/clutter.h>
#include "meta-stage.h"
#include "wayland/meta-wayland-private.h"
struct _MetaCursorRendererPrivate
{
int current_x, current_y;
@@ -51,20 +51,17 @@ static void
queue_redraw (MetaCursorRenderer *renderer)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
MetaBackend *backend = meta_get_backend ();
ClutterActor *stage = meta_backend_get_stage (backend);
CoglTexture *texture;
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
ClutterActor *stage = compositor->stage;
/* During early initialization, we can have no stage */
if (!stage)
return;
if (priv->displayed_cursor && !priv->handled_by_backend)
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, NULL, NULL);
if (priv->handled_by_backend)
meta_stage_set_cursor (META_STAGE (stage), NULL, &priv->current_rect);
else
texture = NULL;
meta_stage_set_cursor (META_STAGE (stage), texture, &priv->current_rect);
meta_stage_set_cursor (META_STAGE (stage), priv->displayed_cursor, &priv->current_rect);
}
static gboolean

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

@@ -23,6 +23,8 @@
#define META_CURSOR_TRACKER_PRIVATE_H
#include <meta/meta-cursor-tracker.h>
#include <wayland-server.h>
#include <gbm.h>
#include "meta-cursor.h"
#include "meta-cursor-renderer.h"
@@ -30,6 +32,7 @@
struct _MetaCursorTracker {
GObject parent_instance;
MetaScreen *screen;
MetaCursorRenderer *renderer;
gboolean is_showing;

View File

@@ -27,29 +27,32 @@
* 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>
#include <meta/errors.h>
#include <cogl/cogl.h>
#include <cogl/cogl-wayland-server.h>
#include <clutter/clutter.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <X11/extensions/Xfixes.h>
#include "meta-backend-private.h"
#include "meta-backend.h"
#include "meta-cursor-private.h"
#include "meta-cursor-tracker-private.h"
#include "screen-private.h"
#include "wayland/meta-wayland-private.h"
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
enum {
CURSOR_CHANGED,
LAST_SIGNAL
CURSOR_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
@@ -57,12 +60,10 @@ static guint signals[LAST_SIGNAL];
static MetaCursorReference *
get_displayed_cursor (MetaCursorTracker *tracker)
{
MetaDisplay *display = meta_get_display ();
if (!tracker->is_showing)
return NULL;
if (meta_display_windows_are_interactable (display))
if (tracker->screen->display->grab_op == META_GRAB_OP_NONE)
{
if (tracker->has_window_cursor)
return tracker->window_cursor;
@@ -96,9 +97,6 @@ sync_cursor (MetaCursorTracker *tracker)
static void
meta_cursor_tracker_init (MetaCursorTracker *self)
{
MetaBackend *backend = meta_get_backend ();
self->renderer = meta_backend_get_cursor_renderer (backend);
self->is_showing = TRUE;
}
@@ -131,9 +129,47 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
}
static MetaCursorTracker *
meta_cursor_tracker_new (void)
make_wayland_cursor_tracker (MetaScreen *screen)
{
return g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
MetaBackend *backend = meta_get_backend ();
MetaWaylandCompositor *compositor;
MetaCursorTracker *self;
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
self->screen = screen;
self->renderer = meta_backend_get_cursor_renderer (backend);
compositor = meta_wayland_compositor_get_default ();
compositor->seat->pointer.cursor_tracker = self;
meta_cursor_tracker_update_position (self, 0, 0);
return self;
}
static MetaCursorTracker *
make_x11_cursor_tracker (MetaScreen *screen)
{
MetaBackend *backend = meta_get_backend ();
MetaCursorTracker *self;
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
self->screen = screen;
self->renderer = meta_backend_get_cursor_renderer (backend);
XFixesSelectCursorInput (screen->display->xdisplay,
screen->xroot,
XFixesDisplayCursorNotifyMask);
return self;
}
static MetaCursorTracker *
meta_cursor_tracker_new (MetaScreen *screen)
{
if (meta_is_wayland_compositor ())
return make_wayland_cursor_tracker (screen);
else
return make_x11_cursor_tracker (screen);
}
static MetaCursorTracker *_cursor_tracker;
@@ -150,7 +186,7 @@ MetaCursorTracker *
meta_cursor_tracker_get_for_screen (MetaScreen *screen)
{
if (!_cursor_tracker)
_cursor_tracker = meta_cursor_tracker_new ();
_cursor_tracker = meta_cursor_tracker_new (screen);
return _cursor_tracker;
}
@@ -171,13 +207,12 @@ gboolean
meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
XEvent *xevent)
{
MetaDisplay *display = meta_get_display ();
XFixesCursorNotifyEvent *notify_event;
if (meta_is_wayland_compositor ())
return FALSE;
if (xevent->xany.type != display->xfixes_event_base + XFixesCursorNotify)
if (xevent->xany.type != tracker->screen->display->xfixes_event_base + XFixesCursorNotify)
return FALSE;
notify_event = (XFixesCursorNotifyEvent *)xevent;
@@ -185,7 +220,6 @@ meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
return FALSE;
g_clear_pointer (&tracker->xfixes_cursor, meta_cursor_reference_unref);
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
return TRUE;
}
@@ -209,7 +243,6 @@ meta_cursor_reference_take_texture (CoglTexture2D *texture,
static void
ensure_xfixes_cursor (MetaCursorTracker *tracker)
{
MetaDisplay *display = meta_get_display ();
XFixesCursorImage *cursor_image;
CoglTexture2D *sprite;
guint8 *cursor_data;
@@ -219,7 +252,7 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
if (tracker->xfixes_cursor)
return;
cursor_image = XFixesGetCursorImage (display->xdisplay);
cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
if (!cursor_image)
return;

View File

@@ -27,7 +27,7 @@
#include "display-private.h"
#include "screen-private.h"
#include "meta-backend-private.h"
#include "meta-backend.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-cursor-renderer-native.h"
@@ -39,9 +39,7 @@
#include <X11/extensions/Xfixes.h>
#include <X11/Xcursor/Xcursor.h>
#ifdef HAVE_WAYLAND
#include <cogl/cogl-wayland-server.h>
#endif
MetaCursorReference *
meta_cursor_reference_ref (MetaCursorReference *self)
@@ -55,13 +53,9 @@ meta_cursor_reference_ref (MetaCursorReference *self)
static void
meta_cursor_image_free (MetaCursorImage *image)
{
if (image->texture)
cogl_object_unref (image->texture);
#ifdef HAVE_NATIVE_BACKEND
cogl_object_unref (image->texture);
if (image->bo)
gbm_bo_destroy (image->bo);
#endif
}
static void
@@ -143,90 +137,70 @@ load_cursor_on_client (MetaCursor cursor)
meta_prefs_get_cursor_size ());
}
#ifdef HAVE_NATIVE_BACKEND
static void
get_hardware_cursor_size (uint64_t *cursor_width, uint64_t *cursor_height)
{
MetaBackend *meta_backend = meta_get_backend ();
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
{
meta_cursor_renderer_native_get_cursor_size (META_CURSOR_RENDERER_NATIVE (renderer), cursor_width, cursor_height);
return;
}
g_assert_not_reached ();
}
#endif
#ifdef HAVE_NATIVE_BACKEND
static void
meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
MetaCursorImage *image,
uint8_t *pixels,
uint width,
uint height,
int width,
int height,
int rowstride,
uint32_t gbm_format)
{
uint64_t cursor_width, cursor_height;
get_hardware_cursor_size (&cursor_width, &cursor_height);
if (width > cursor_width || height > cursor_height)
if (width > 64 || height > 64)
{
meta_warning ("Invalid theme cursor size (must be at most %ux%u)\n",
(unsigned int)cursor_width, (unsigned int)cursor_height);
meta_warning ("Invalid theme cursor size (must be at most 64x64)\n");
return;
}
if (gbm_device_is_format_supported (gbm, gbm_format,
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE))
{
uint8_t buf[4 * cursor_width * cursor_height];
uint i;
uint8_t buf[4 * 64 * 64];
int i;
image->bo = gbm_bo_create (gbm, cursor_width, cursor_height,
gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
image->bo = gbm_bo_create (gbm, 64, 64,
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
memset (buf, 0, sizeof(buf));
for (i = 0; i < height; i++)
memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4);
memcpy (buf + i * 4 * 64, pixels + i * rowstride, width * 4);
gbm_bo_write (image->bo, buf, cursor_width * cursor_height * 4);
gbm_bo_write (image->bo, buf, 64 * 64 * 4);
}
else
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
}
#endif
#ifdef HAVE_NATIVE_BACKEND
static struct gbm_device *
get_gbm_device (void)
{
#ifdef HAVE_NATIVE_BACKEND
MetaBackend *meta_backend = meta_get_backend ();
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer));
else
return NULL;
}
#endif
return NULL;
}
static void
meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
XcursorImage *xc_image)
{
uint width, height, rowstride;
int width, height, rowstride;
CoglPixelFormat cogl_format;
uint32_t gbm_format;
ClutterBackend *clutter_backend;
CoglContext *cogl_context;
struct gbm_device *gbm;
width = xc_image->width;
height = xc_image->height;
rowstride = width * 4;
gbm_format = GBM_FORMAT_ARGB8888;
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
#else
@@ -245,53 +219,47 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
(uint8_t *) xc_image->pixels,
NULL);
#ifdef HAVE_NATIVE_BACKEND
struct gbm_device *gbm = get_gbm_device ();
gbm = get_gbm_device ();
if (gbm)
meta_cursor_image_load_gbm_buffer (gbm,
image,
(uint8_t *) xc_image->pixels,
width, height, rowstride,
GBM_FORMAT_ARGB8888);
#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);
gbm_format);
}
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;
}
#ifdef HAVE_WAYLAND
static void
meta_cursor_image_load_from_buffer (MetaCursorImage *image,
struct wl_resource *buffer,
int hot_x,
int hot_y)
{
struct gbm_device *gbm = get_gbm_device ();
ClutterBackend *backend;
CoglContext *cogl_context;
struct wl_shm_buffer *shm_buffer;
uint32_t gbm_format;
int width, height;
image->hot_x = hot_x;
image->hot_y = hot_y;
@@ -301,24 +269,16 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
#ifdef HAVE_NATIVE_BACKEND
struct gbm_device *gbm = get_gbm_device ();
if (gbm)
width = cogl_texture_get_width (COGL_TEXTURE (image->texture));
height = cogl_texture_get_height (COGL_TEXTURE (image->texture));
shm_buffer = wl_shm_buffer_get (buffer);
if (shm_buffer)
{
uint32_t gbm_format;
uint64_t cursor_width, cursor_height;
uint width, height;
width = cogl_texture_get_width (COGL_TEXTURE (image->texture));
height = cogl_texture_get_height (COGL_TEXTURE (image->texture));
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer);
if (shm_buffer)
if (gbm)
{
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,31 +306,30 @@ 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
}
else
{
/* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses
that, so themed cursors must be padded with transparent pixels to fill the
overlay. This is trivial if we have CPU access to the data, but it's not
possible if the buffer is in GPU memory (and possibly tiled too), so if we
don't get the right size, we fallback to GL.
*/
if (width != 64 || height != 64)
{
/* HW cursors have a predefined size (at least 64x64), which usually is bigger than cursor theme
size, so themed cursors must be padded with transparent pixels to fill the
overlay. This is trivial if we have CPU access to the data, but it's not
possible if the buffer is in GPU memory (and possibly tiled too), so if we
don't get the right size, we fallback to GL.
*/
get_hardware_cursor_size (&cursor_width, &cursor_height);
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
return;
}
if (width != cursor_width || height != cursor_height)
{
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
return;
}
image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER, buffer, GBM_BO_USE_CURSOR);
if (gbm)
{
image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER,
buffer, GBM_BO_USE_CURSOR_64X64);
if (!image->bo)
meta_warning ("Importing HW cursor from wl_buffer failed\n");
}
}
#endif
}
MetaCursorReference *
@@ -386,40 +345,30 @@ meta_cursor_reference_from_buffer (struct wl_resource *buffer,
return self;
}
#endif
CoglTexture *
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);
}
#ifdef HAVE_NATIVE_BACKEND
struct gbm_bo *
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)
*hot_y = cursor->image.hot_y;
return cursor->image.bo;
}
#endif
MetaCursor
meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor)

View File

@@ -28,15 +28,13 @@ MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor);
void meta_cursor_reference_unref (MetaCursorReference *cursor);
#include <meta/common.h>
#include <wayland-server.h>
MetaCursorReference * meta_cursor_reference_from_theme (MetaCursor cursor);
#ifdef HAVE_WAYLAND
#include <wayland-server.h>
MetaCursorReference * meta_cursor_reference_from_buffer (struct wl_resource *buffer,
int hot_x,
int hot_y);
#endif
MetaCursor meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor);

View File

@@ -38,7 +38,7 @@
#include <meta/meta-idle-monitor.h>
#include "meta-idle-monitor-private.h"
#include "meta-idle-monitor-dbus.h"
#include "meta-backend-private.h"
#include "meta-backend.h"
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));

View File

@@ -1,87 +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_click_method) (MetaInputSettings *settings,
ClutterInputDevice *device,
GDesktopTouchpadClickMethod mode);
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,895 +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;
if (device &&
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
return;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
handedness = g_settings_get_enum (priv->touchpad_settings, "left-handed");
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)
{
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;
if (device &&
clutter_input_device_get_device_type (device) != CLUTTER_POINTER_DEVICE)
return;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
enabled = g_settings_get_boolean (priv->mouse_settings, "left-handed");
if (device)
{
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 GSettings *
get_settings_for_device_type (MetaInputSettings *input_settings,
ClutterInputDeviceType type)
{
MetaInputSettingsPrivate *priv;
priv = meta_input_settings_get_instance_private (input_settings);
switch (type)
{
case CLUTTER_POINTER_DEVICE:
return priv->mouse_settings;
case CLUTTER_TOUCHPAD_DEVICE:
return priv->touchpad_settings;
default:
return NULL;
}
}
static void
update_device_speed (MetaInputSettings *input_settings,
ClutterInputDevice *device)
{
GSettings *settings;
ConfigDoubleFunc func;
const gchar *key = "speed";
func = META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_speed;
if (device)
{
settings = get_settings_for_device_type (input_settings,
clutter_input_device_get_device_type (device));
if (!settings)
return;
settings_device_set_double_setting (input_settings, device, func,
g_settings_get_double (settings, key));
}
else
{
settings = get_settings_for_device_type (input_settings, CLUTTER_POINTER_DEVICE);
settings_set_double_setting (input_settings, CLUTTER_POINTER_DEVICE, func,
g_settings_get_double (settings, key));
settings = get_settings_for_device_type (input_settings, CLUTTER_TOUCHPAD_DEVICE);
settings_set_double_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, func,
g_settings_get_double (settings, key));
}
}
static void
update_device_natural_scroll (MetaInputSettings *input_settings,
ClutterInputDevice *device)
{
GSettings *settings;
ConfigBoolFunc func;
const gchar *key = "natural-scroll";
func = META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_invert_scroll;
if (device)
{
settings = get_settings_for_device_type (input_settings,
clutter_input_device_get_device_type (device));
if (!settings)
return;
settings_device_set_bool_setting (input_settings, device, func,
g_settings_get_boolean (settings, key));
}
else
{
settings = get_settings_for_device_type (input_settings, CLUTTER_POINTER_DEVICE);
settings_set_bool_setting (input_settings, CLUTTER_POINTER_DEVICE, func,
g_settings_get_boolean (settings, key));
settings = get_settings_for_device_type (input_settings, CLUTTER_TOUCHPAD_DEVICE);
settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, func,
g_settings_get_boolean (settings, key));
}
}
static void
update_touchpad_tap_enabled (MetaInputSettings *input_settings,
ClutterInputDevice *device)
{
MetaInputSettingsClass *input_settings_class;
MetaInputSettingsPrivate *priv;
gboolean enabled;
if (device &&
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
return;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-to-click");
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;
if (device &&
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
return;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
method = g_settings_get_enum (priv->touchpad_settings, "scroll-method");
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_click_method (MetaInputSettings *input_settings,
ClutterInputDevice *device)
{
MetaInputSettingsClass *input_settings_class;
GDesktopTouchpadScrollMethod method;
MetaInputSettingsPrivate *priv;
if (device &&
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
return;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
method = g_settings_get_enum (priv->touchpad_settings, "click-method");
if (device)
{
settings_device_set_uint_setting (input_settings, device,
input_settings_class->set_click_method,
method);
}
else
{
settings_set_uint_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
(ConfigUintFunc) input_settings_class->set_click_method,
method);
}
}
static void
update_touchpad_send_events (MetaInputSettings *input_settings,
ClutterInputDevice *device)
{
MetaInputSettingsClass *input_settings_class;
MetaInputSettingsPrivate *priv;
GDesktopDeviceSendEvents mode;
if (device &&
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
return;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
mode = g_settings_get_enum (priv->touchpad_settings, "send-events");
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;
if (device && !device_is_trackball (device))
return;
priv = meta_input_settings_get_instance_private (input_settings);
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
/* This key is 'i' in the schema but it also specifies a minimum
* range of 0 so the cast here is safe. */
button = (guint) g_settings_get_int (priv->trackball_settings, "scroll-wheel-emulation-button");
if (device)
{
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, NULL);
else if (strcmp (key, "natural-scroll") == 0)
update_device_natural_scroll (input_settings, NULL);
}
else if (settings == priv->touchpad_settings)
{
if (strcmp (key, "left-handed") == 0)
update_touchpad_left_handed (input_settings, NULL);
else if (strcmp (key, "speed") == 0)
update_device_speed (input_settings, NULL);
else if (strcmp (key, "natural-scroll") == 0)
update_device_natural_scroll (input_settings, NULL);
else if (strcmp (key, "tap-to-click") == 0)
update_touchpad_tap_enabled (input_settings, NULL);
else if (strcmp (key, "send-events") == 0)
update_touchpad_send_events (input_settings, NULL);
else if (strcmp (key, "scroll-method") == 0)
update_touchpad_scroll_method (input_settings, NULL);
else if (strcmp (key, "click-method") == 0)
update_touchpad_click_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
apply_device_settings (MetaInputSettings *input_settings,
ClutterInputDevice *device)
{
update_mouse_left_handed (input_settings, device);
update_device_speed (input_settings, device);
update_device_natural_scroll (input_settings, device);
update_touchpad_left_handed (input_settings, device);
update_device_speed (input_settings, device);
update_device_natural_scroll (input_settings, device);
update_touchpad_tap_enabled (input_settings, device);
update_touchpad_send_events (input_settings, device);
update_touchpad_scroll_method (input_settings, device);
update_touchpad_click_method (input_settings, device);
update_trackball_scroll_button (input_settings, device);
}
static void
meta_input_settings_device_added (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
MetaInputSettings *input_settings)
{
if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER)
return;
apply_device_settings (input_settings, device);
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);
apply_device_settings (input_settings, NULL);
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>
@@ -61,14 +60,13 @@ typedef struct {
gboolean enabled;
MetaRectangle rect;
float refresh_rate;
MetaMonitorTransform transform;
enum wl_output_transform transform;
gboolean is_primary;
gboolean is_presentation;
} 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)
@@ -675,20 +656,20 @@ handle_text (GMarkupParseContext *context,
else if (strcmp (parser->output_field, "rotation") == 0)
{
if (strncmp (text, "normal", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_NORMAL;
parser->output.transform = WL_OUTPUT_TRANSFORM_NORMAL;
else if (strncmp (text, "left", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_90;
parser->output.transform = WL_OUTPUT_TRANSFORM_90;
else if (strncmp (text, "upside_down", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_180;
parser->output.transform = WL_OUTPUT_TRANSFORM_180;
else if (strncmp (text, "right", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_270;
parser->output.transform = WL_OUTPUT_TRANSFORM_270;
else
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
"Invalid rotation type %.*s", (int)text_len, text);
}
else if (strcmp (parser->output_field, "reflect_x") == 0)
parser->output.transform += read_bool (text, text_len, error) ?
META_MONITOR_TRANSFORM_FLIPPED : 0;
WL_OUTPUT_TRANSFORM_FLIPPED : 0;
else if (strcmp (parser->output_field, "reflect_y") == 0)
{
/* FIXME (look at the rotation map in monitor.c) */
@@ -815,6 +796,27 @@ make_config_key (MetaConfiguration *key,
key->n_outputs = o;
}
gboolean
meta_monitor_config_match_current (MetaMonitorConfig *self,
MetaMonitorManager *manager)
{
MetaOutput *outputs;
unsigned n_outputs;
MetaConfiguration key;
gboolean ok;
if (self->current == NULL)
return FALSE;
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
make_config_key (&key, outputs, n_outputs, -1);
ok = config_equal (&key, self->current);
config_clear (&key);
return ok;
}
gboolean
meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager)
{
@@ -849,45 +851,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 +928,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)
{
@@ -929,19 +945,6 @@ laptop_display_is_on (MetaConfiguration *config)
return FALSE;
}
static gboolean
multiple_outputs_are_enabled (MetaConfiguration *config)
{
unsigned int i, enabled;
enabled = 0;
for (i = 0; i < config->n_outputs; i++)
if (config->outputs[i].enabled)
enabled++;
return enabled > 1;
}
static MetaConfiguration *
make_laptop_lid_config (MetaConfiguration *reference)
{
@@ -951,9 +954,9 @@ make_laptop_lid_config (MetaConfiguration *reference)
int x_after, y_after;
int x_offset, y_offset;
g_assert (multiple_outputs_are_enabled (reference));
g_assert (reference->n_outputs > 1);
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 +973,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 +1011,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 +1023,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 &&
stored->n_outputs > 1 &&
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 +1068,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 +1089,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 = WL_OUTPUT_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 +1147,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 = WL_OUTPUT_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 = WL_OUTPUT_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 +1221,7 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
MetaOutput *outputs,
unsigned n_outputs)
{
MetaConfiguration *config;
MetaConfiguration *ret;
MetaOutput *primary;
unsigned i;
@@ -1324,29 +1232,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 = WL_OUTPUT_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 +1270,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 +1282,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 &&
default_config->n_outputs > 1 &&
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 +1335,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 +1348,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 +1364,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))
@@ -1470,12 +1378,11 @@ turn_off_laptop_display (MetaMonitorConfig *self,
{
MetaConfiguration *new;
if (!multiple_outputs_are_enabled (self->current))
if (self->current->n_outputs == 1)
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;
}
@@ -1605,7 +1512,7 @@ meta_monitor_config_save (MetaMonitorConfig *self)
output->rect.x,
output->rect.y,
rotation_map[output->transform & 0x3],
output->transform >= META_MONITOR_TRANSFORM_FLIPPED ? "yes" : "no",
output->transform >= WL_OUTPUT_TRANSFORM_FLIPPED ? "yes" : "no",
output->is_primary ? "yes" : "no",
output->is_presentation ? "yes" : "no");
}
@@ -1634,7 +1541,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);
}
@@ -1705,13 +1621,13 @@ output_supports_mode (MetaOutput *output,
}
static gboolean
crtc_assignment_assign (CrtcAssignment *assign,
MetaCRTC *crtc,
MetaMonitorMode *mode,
int x,
int y,
MetaMonitorTransform transform,
MetaOutput *output)
crtc_assignment_assign (CrtcAssignment *assign,
MetaCRTC *crtc,
MetaMonitorMode *mode,
int x,
int y,
enum wl_output_transform transform,
MetaOutput *output)
{
MetaCRTCInfo *info = g_hash_table_lookup (assign->info, crtc);
@@ -1873,6 +1789,7 @@ real_assign_crtcs (CrtcAssignment *assignment,
output_config->transform,
pass);
if (crtc_assignment_assign (assignment, crtc, &modes[j],
output_config->rect.x, output_config->rect.y,
output_config->transform,

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))
@@ -36,6 +36,9 @@ GType meta_monitor_config_get_type (void) G_GNUC_CONST;
MetaMonitorConfig *meta_monitor_config_new (void);
gboolean meta_monitor_config_match_current (MetaMonitorConfig *config,
MetaMonitorManager *manager);
gboolean meta_monitor_config_apply_stored (MetaMonitorConfig *config,
MetaMonitorManager *manager);

View File

@@ -27,7 +27,7 @@
#include "meta-monitor-manager-dummy.h"
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
struct _MetaMonitorManagerDummy
{
@@ -66,8 +66,8 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
manager->crtcs[0].rect.width = manager->modes[0].width;
manager->crtcs[0].rect.height = manager->modes[0].height;
manager->crtcs[0].current_mode = &manager->modes[0];
manager->crtcs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
manager->crtcs[0].all_transforms = ALL_TRANSFORMS;
manager->crtcs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
manager->crtcs[0].all_transforms = ALL_WL_TRANSFORMS;
manager->crtcs[0].is_dirty = FALSE;
manager->crtcs[0].logical_monitor = NULL;
@@ -75,7 +75,7 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
manager->n_outputs = 1;
manager->outputs[0].crtc = &manager->crtcs[0];
manager->outputs[0].winsys_id = 1;
manager->outputs[0].output_id = 1;
manager->outputs[0].name = g_strdup ("LVDS");
manager->outputs[0].vendor = g_strdup ("MetaProducts Inc.");
manager->outputs[0].product = g_strdup ("unknown");
@@ -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,26 +35,19 @@
#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"
#include "meta-backend.h"
enum {
CONFIRM_DISPLAY_CHANGE,
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 */
enum {
PROP_0,
PROP_POWER_SAVE_MODE,
PROP_LAST
};
static int signals[SIGNALS_LAST];
@@ -71,6 +64,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:
*
@@ -124,7 +125,7 @@ make_logical_config (MetaMonitorManager *manager)
*/
info.is_presentation = TRUE;
info.in_fullscreen = -1;
info.winsys_id = 0;
info.output_id = 0;
g_array_append_val (monitor_infos, info);
@@ -155,8 +156,8 @@ make_logical_config (MetaMonitorManager *manager)
info->is_primary = info->is_primary || output->is_primary;
info->is_presentation = info->is_presentation && output->is_presentation;
if (output->is_primary || info->winsys_id == 0)
info->winsys_id = output->winsys_id;
if (output->is_primary || info->output_id == 0)
info->output_id = output->output_id;
if (info->is_primary)
manager->primary_monitor_index = info->number;
@@ -166,44 +167,16 @@ make_logical_config (MetaMonitorManager *manager)
manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
}
static void
power_save_mode_changed (MetaMonitorManager *manager,
GParamSpec *pspec,
gpointer user_data)
{
MetaMonitorManagerClass *klass;
int mode = meta_dbus_display_config_get_power_save_mode (META_DBUS_DISPLAY_CONFIG (manager));
if (mode == META_POWER_SAVE_UNSUPPORTED)
return;
/* If DPMS is unsupported, force the property back. */
if (manager->power_save_mode == META_POWER_SAVE_UNSUPPORTED)
{
meta_dbus_display_config_set_power_save_mode (META_DBUS_DISPLAY_CONFIG (manager), META_POWER_SAVE_UNSUPPORTED);
return;
}
klass = META_MONITOR_MANAGER_GET_CLASS (manager);
if (klass->set_power_save_mode)
klass->set_power_save_mode (manager, mode);
manager->power_save_mode = mode;
}
static void
meta_monitor_manager_constructed (GObject *object)
{
MetaMonitorManager *manager = META_MONITOR_MANAGER (object);
g_signal_connect_object (manager, "notify::power-save-mode",
G_CALLBACK (power_save_mode_changed), manager, 0);
manager->in_init = TRUE;
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 +189,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);
@@ -225,6 +215,23 @@ meta_monitor_manager_constructed (GObject *object)
}
static void
meta_monitor_manager_set_power_save_mode (MetaMonitorManager *manager,
MetaPowerSave mode)
{
MetaMonitorManagerClass *klass;
if (manager->power_save_mode == META_POWER_SAVE_UNSUPPORTED ||
mode == META_POWER_SAVE_UNSUPPORTED)
return;
klass = META_MONITOR_MANAGER_GET_CLASS (manager);
if (klass->set_power_save_mode)
klass->set_power_save_mode (manager, mode);
manager->power_save_mode = mode;
}
void
meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
int n_old_outputs)
{
@@ -247,7 +254,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)
{
@@ -291,6 +298,44 @@ meta_monitor_manager_dispose (GObject *object)
G_OBJECT_CLASS (meta_monitor_manager_parent_class)->dispose (object);
}
static void
meta_monitor_manager_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaMonitorManager *self = META_MONITOR_MANAGER (object);
switch (prop_id)
{
case PROP_POWER_SAVE_MODE:
meta_monitor_manager_set_power_save_mode (self, g_value_get_int (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_monitor_manager_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaMonitorManager *self = META_MONITOR_MANAGER (object);
switch (prop_id)
{
case PROP_POWER_SAVE_MODE:
g_value_set_int (value, self->power_save_mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static GBytes *
meta_monitor_manager_real_read_edid (MetaMonitorManager *manager,
MetaOutput *output)
@@ -311,6 +356,8 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = meta_monitor_manager_constructed;
object_class->get_property = meta_monitor_manager_get_property;
object_class->set_property = meta_monitor_manager_set_property;
object_class->dispose = meta_monitor_manager_dispose;
object_class->finalize = meta_monitor_manager_finalize;
@@ -324,6 +371,8 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
g_object_class_override_property (object_class, PROP_POWER_SAVE_MODE, "power-save-mode");
}
static const double known_diagonals[] = {
@@ -357,14 +406,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 +458,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)
@@ -457,7 +477,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
GVariantBuilder transforms;
g_variant_builder_init (&transforms, G_VARIANT_TYPE ("au"));
for (j = 0; j <= META_MONITOR_TRANSFORM_FLIPPED_270; j++)
for (j = 0; j <= WL_OUTPUT_TRANSFORM_FLIPPED_270; j++)
if (crtc->all_transforms & (1 << j))
g_variant_builder_add (&transforms, "u", j);
@@ -518,8 +538,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)
@@ -542,7 +560,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
i, /* ID */
(gint64)output->winsys_id,
(gint64)output->output_id,
(int)(output->crtc ? output->crtc - manager->crtcs : -1),
&crtcs,
output->name,
@@ -649,7 +667,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
int new_mode, x, y;
int new_screen_width, new_screen_height;
guint transform;
guint output_index;
guint output_id;
GPtrArray *crtc_infos, *output_infos;
if (serial != manager->serial)
@@ -676,6 +694,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
MetaOutput *first_output;
MetaCRTC *crtc;
MetaMonitorMode *mode;
guint output_id;
crtc_info = g_slice_new (MetaCRTCInfo);
crtc_info->outputs = g_ptr_array_new ();
@@ -737,8 +756,8 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
crtc_info->y = 0;
}
if (transform < META_MONITOR_TRANSFORM_NORMAL ||
transform > META_MONITOR_TRANSFORM_FLIPPED_270 ||
if (transform < WL_OUTPUT_TRANSFORM_NORMAL ||
transform > WL_OUTPUT_TRANSFORM_FLIPPED_270 ||
((crtc->all_transforms & (1 << transform)) == 0))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
@@ -749,18 +768,18 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
crtc_info->transform = transform;
first_output = NULL;
while (g_variant_iter_loop (nested_outputs, "u", &output_index))
while (g_variant_iter_loop (nested_outputs, "u", &output_id))
{
MetaOutput *output;
if (output_index >= manager->n_outputs)
if (output_id >= manager->n_outputs)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
"Invalid output id");
return TRUE;
}
output = &manager->outputs[output_index];
output = &manager->outputs[output_id];
if (!output_can_config (output, crtc, mode))
{
@@ -805,12 +824,12 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
}
g_variant_iter_init (&output_iter, outputs);
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_index, &properties))
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_id, &properties))
{
MetaOutputInfo *output_info;
gboolean primary, presentation;
if (output_index >= manager->n_outputs)
if (output_id >= manager->n_outputs)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
@@ -819,7 +838,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
}
output_info = g_slice_new0 (MetaOutputInfo);
output_info->output = &manager->outputs[output_index];
output_info->output = &manager->outputs[output_id];
if (g_variant_lookup (properties, "primary", "b", &primary))
output_info->is_primary = primary;
@@ -890,7 +909,7 @@ static gboolean
meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
GDBusMethodInvocation *invocation,
guint serial,
guint output_index,
guint output_id,
gint value)
{
MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton);
@@ -904,14 +923,14 @@ meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
return TRUE;
}
if (output_index >= manager->n_outputs)
if (output_id >= manager->n_outputs)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
"Invalid output id");
return TRUE;
}
output = &manager->outputs[output_index];
output = &manager->outputs[output_id];
if (value < 0 || value > 100)
{
@@ -1107,13 +1126,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 +1200,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,165 +1217,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;
}
gint
meta_monitor_manager_get_monitor_at_point (MetaMonitorManager *manager,
gfloat x,
gfloat y)
{
unsigned int i;
for (i = 0; i < manager->n_monitor_infos; i++)
{
MetaMonitorInfo *monitor = &manager->monitor_infos[i];
int left, right, top, bottom;
left = monitor->rect.x;
right = left + monitor->rect.width;
top = monitor->rect.y;
bottom = top + monitor->rect.height;
if ((x >= left) && (x < right) && (y >= top) && (y < bottom))
return i;
}
return -1;
}

View File

@@ -41,60 +41,31 @@
#include "display-private.h"
#include <meta/screen.h>
#include "stack-tracker.h"
#include <meta/meta-monitor-manager.h>
#include "ui.h"
#include <wayland-server.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;
typedef struct _MetaOutputInfo MetaOutputInfo;
typedef enum {
META_MONITOR_TRANSFORM_NORMAL,
META_MONITOR_TRANSFORM_90,
META_MONITOR_TRANSFORM_180,
META_MONITOR_TRANSFORM_270,
META_MONITOR_TRANSFORM_FLIPPED,
META_MONITOR_TRANSFORM_FLIPPED_90,
META_MONITOR_TRANSFORM_FLIPPED_180,
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 */
MetaCRTC *crtc;
/* The low-level ID of this output, used to apply back configuration */
glong winsys_id;
glong output_id;
char *name;
char *vendor;
char *product;
@@ -104,8 +75,6 @@ struct _MetaOutput
CoglSubpixelOrder subpixel_order;
int scale;
MetaConnectorType connector_type;
MetaMonitorMode *preferred_mode;
MetaMonitorMode **modes;
unsigned int n_modes;
@@ -138,8 +107,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
@@ -147,7 +114,7 @@ struct _MetaCRTC
glong crtc_id;
MetaRectangle rect;
MetaMonitorMode *current_mode;
MetaMonitorTransform transform;
enum wl_output_transform transform;
unsigned int all_transforms;
/* Only used to build the logical configuration
@@ -195,14 +162,14 @@ struct _MetaMonitorInfo
gboolean in_fullscreen;
/* The primary or first output for this monitor, 0 if we can't figure out.
It can be matched to a winsys_id of a MetaOutput.
It can be matched to an output_id of a MetaOutput.
This is used as an opaque token on reconfiguration when switching from
clone to extened, to decide on what output the windows should go next
(it's an attempt to keep windows on the same monitor, and preferably on
the primary one).
*/
glong winsys_id;
glong output_id;
};
/*
@@ -218,13 +185,13 @@ struct _MetaCRTCInfo {
MetaMonitorMode *mode;
int x;
int y;
MetaMonitorTransform transform;
enum wl_output_transform transform;
GPtrArray *outputs;
};
/*
* MetaOutputInfo:
* this is the same as MetaCRTCInfo, but for outputs
* this is the same as MetaOutputInfo, but for CRTCs
*/
struct _MetaOutputInfo {
MetaOutput *output;
@@ -321,6 +288,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,28 +327,19 @@ 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]);
gint meta_monitor_manager_get_monitor_at_point (MetaMonitorManager *manager,
gfloat x,
gfloat y);
/* Returns true if transform causes width and height to be inverted
This is true for the odd transforms in the enum */
static inline gboolean
meta_monitor_transform_is_rotated (MetaMonitorTransform transform)
meta_monitor_transform_is_rotated (enum wl_output_transform transform)
{
return (transform % 2);
}

View File

@@ -1,264 +0,0 @@
/*
* 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.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include <config.h>
#include "meta-stage.h"
#include "meta-cursor-private.h"
#include <meta/meta-backend.h>
#include <meta/util.h>
typedef struct {
gboolean enabled;
CoglPipeline *pipeline;
CoglTexture *texture;
MetaRectangle current_rect;
MetaRectangle previous_rect;
gboolean previous_is_valid;
} MetaOverlay;
struct _MetaStagePrivate {
MetaOverlay cursor_overlay;
gboolean is_active;
};
typedef struct _MetaStagePrivate MetaStagePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaStage, meta_stage, CLUTTER_TYPE_STAGE);
static void
meta_overlay_init (MetaOverlay *overlay)
{
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
overlay->pipeline = cogl_pipeline_new (ctx);
}
static void
meta_overlay_free (MetaOverlay *overlay)
{
if (overlay->pipeline)
cogl_object_unref (overlay->pipeline);
}
static void
meta_overlay_set (MetaOverlay *overlay,
CoglTexture *texture,
MetaRectangle *rect)
{
if (overlay->texture != texture)
{
overlay->texture = texture;
if (texture)
{
cogl_pipeline_set_layer_texture (overlay->pipeline, 0, texture);
overlay->enabled = TRUE;
}
else
{
cogl_pipeline_set_layer_texture (overlay->pipeline, 0, NULL);
overlay->enabled = FALSE;
}
}
overlay->current_rect = *rect;
}
static void
meta_overlay_paint (MetaOverlay *overlay)
{
if (!overlay->enabled)
return;
g_assert (meta_is_wayland_compositor ());
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
overlay->pipeline,
overlay->current_rect.x,
overlay->current_rect.y,
overlay->current_rect.x +
overlay->current_rect.width,
overlay->current_rect.y +
overlay->current_rect.height);
overlay->previous_rect = overlay->current_rect;
overlay->previous_is_valid = TRUE;
}
static void
meta_stage_finalize (GObject *object)
{
MetaStage *stage = META_STAGE (object);
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
meta_overlay_free (&priv->cursor_overlay);
}
static void
meta_stage_paint (ClutterActor *actor)
{
MetaStage *stage = META_STAGE (actor);
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
meta_overlay_paint (&priv->cursor_overlay);
}
static void
meta_stage_activate (ClutterStage *actor)
{
MetaStage *stage = META_STAGE (actor);
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
CLUTTER_STAGE_CLASS (meta_stage_parent_class)->activate (actor);
priv->is_active = TRUE;
}
static void
meta_stage_deactivate (ClutterStage *actor)
{
MetaStage *stage = META_STAGE (actor);
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
CLUTTER_STAGE_CLASS (meta_stage_parent_class)->deactivate (actor);
priv->is_active = FALSE;
}
static void
meta_stage_class_init (MetaStageClass *klass)
{
ClutterStageClass *stage_class = (ClutterStageClass *) klass;
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
GObjectClass *object_class = (GObjectClass *) klass;
object_class->finalize = meta_stage_finalize;
actor_class->paint = meta_stage_paint;
stage_class->activate = meta_stage_activate;
stage_class->deactivate = meta_stage_deactivate;
}
static void
meta_stage_init (MetaStage *stage)
{
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
meta_overlay_init (&priv->cursor_overlay);
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE);
}
ClutterActor *
meta_stage_new (void)
{
return g_object_new (META_TYPE_STAGE,
"cursor-visible", FALSE,
NULL);
}
static void
queue_redraw_for_overlay (MetaStage *stage,
MetaOverlay *overlay)
{
cairo_rectangle_int_t clip;
/* Clear the location the overlay was at before, if we need to. */
if (overlay->previous_is_valid)
{
clip.x = overlay->previous_rect.x;
clip.y = overlay->previous_rect.y;
clip.width = overlay->previous_rect.width;
clip.height = overlay->previous_rect.height;
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
overlay->previous_is_valid = FALSE;
}
/* Draw the overlay at the new position */
if (overlay->enabled)
{
clip.x = overlay->current_rect.x;
clip.y = overlay->current_rect.y;
clip.width = overlay->current_rect.width;
clip.height = overlay->current_rect.height;
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
}
}
void
meta_stage_set_cursor (MetaStage *stage,
CoglTexture *texture,
MetaRectangle *rect)
{
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
g_assert (meta_is_wayland_compositor () || texture == NULL);
meta_overlay_set (&priv->cursor_overlay, texture, rect);
queue_redraw_for_overlay (stage, &priv->cursor_overlay);
}
void
meta_stage_set_active (MetaStage *stage,
gboolean is_active)
{
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
ClutterEvent event = { 0 };
/* Used by the native backend to inform accessibility technologies
* about when the stage loses and gains input focus.
*
* For the X11 backend, clutter transparently takes care of this
* for us.
*/
if (priv->is_active == is_active)
return;
event.type = CLUTTER_STAGE_STATE;
clutter_event_set_stage (&event, CLUTTER_STAGE (stage));
event.stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED;
if (is_active)
event.stage_state.new_state = CLUTTER_STAGE_STATE_ACTIVATED;
/* Emitting this StageState event will result in the stage getting
* activated or deactivated (with the activated or deactivated signal
* getting emitted from the stage)
*
* FIXME: This won't update ClutterStage's own notion of its
* activeness. For that we would need to somehow trigger a
* _clutter_stage_update_state call, which will probably
* require new API in clutter. In practice, nothing relies
* on the ClutterStage's own notion of activeness when using
* the EGL backend.
*
* See http://bugzilla.gnome.org/746670
*/
clutter_stage_event (CLUTTER_STAGE (stage), &event);
}

View File

@@ -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"
@@ -39,42 +36,11 @@
struct _MetaBackendNativePrivate
{
MetaLauncher *launcher;
MetaBarrierManagerNative *barrier_manager;
GSettings *keyboard_settings;
};
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendNative, meta_backend_native, META_TYPE_BACKEND);
static void
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_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)
@@ -84,6 +50,31 @@ constrain_to_barriers (ClutterInputDevice *device,
*
*/
static gboolean
check_all_screen_monitors(MetaMonitorInfo *monitors,
unsigned n_monitors,
float x,
float y)
{
unsigned int i;
for (i = 0; i < n_monitors; i++)
{
MetaMonitorInfo *monitor = &monitors[i];
int left, right, top, bottom;
left = monitor->rect.x;
right = left + monitor->rect.width;
top = monitor->rect.y;
bottom = left + monitor->rect.height;
if ((x >= left) && (x < right) && (y >= top) && (y < bottom))
return TRUE;
}
return FALSE;
}
static void
constrain_all_screen_monitors (ClutterInputDevice *device,
MetaMonitorInfo *monitors,
@@ -93,25 +84,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;
@@ -137,15 +128,14 @@ pointer_constrain_callback (ClutterInputDevice *device,
MetaMonitorManager *monitor_manager;
MetaMonitorInfo *monitors;
unsigned int n_monitors;
/* Constrain to barriers */
constrain_to_barriers (device, time, new_x, new_y);
gboolean ret;
monitor_manager = meta_monitor_manager_get ();
monitors = meta_monitor_manager_get_monitor_infos (monitor_manager, &n_monitors);
/* if we're moving inside a monitor, we're fine */
if (meta_monitor_manager_get_monitor_at_point (monitor_manager, *new_x, *new_y) >= 0)
ret = check_all_screen_monitors(monitors, n_monitors, *new_x, *new_y);
if (ret == TRUE)
return;
/* if we're trying to escape, clamp to the CRTC we're coming from */
@@ -198,57 +188,10 @@ meta_backend_native_warp_pointer (MetaBackend *backend,
clutter_evdev_warp_pointer (device, time_, x, y);
}
static void
meta_backend_native_set_keymap (MetaBackend *backend,
const char *layouts,
const char *variants,
const char *options)
{
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
struct xkb_rule_names names;
struct xkb_keymap *keymap;
struct xkb_context *context;
names.rules = DEFAULT_XKB_RULES_FILE;
names.model = DEFAULT_XKB_MODEL;
names.layout = layouts;
names.variant = variants;
names.options = options;
context = xkb_context_new (XKB_CONTEXT_NO_FLAGS);
keymap = xkb_keymap_new_from_names (context, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
xkb_context_unref (context);
clutter_evdev_set_keyboard_map (manager, keymap);
g_signal_emit_by_name (backend, "keymap-changed", 0);
xkb_keymap_unref (keymap);
}
static struct xkb_keymap *
meta_backend_native_get_keymap (MetaBackend *backend)
{
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
return clutter_evdev_get_keyboard_map (manager);
}
static void
meta_backend_native_lock_layout_group (MetaBackend *backend,
guint idx)
{
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
clutter_evdev_set_keyboard_layout_index (manager, idx);
g_signal_emit_by_name (backend, "keymap-layout-group-changed", idx, 0);
}
static void
meta_backend_native_class_init (MetaBackendNativeClass *klass)
{
MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_backend_native_finalize;
backend_class->post_init = meta_backend_native_post_init;
backend_class->create_idle_monitor = meta_backend_native_create_idle_monitor;
@@ -256,9 +199,6 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass)
backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer;
backend_class->warp_pointer = meta_backend_native_warp_pointer;
backend_class->set_keymap = meta_backend_native_set_keymap;
backend_class->get_keymap = meta_backend_native_get_keymap;
backend_class->lock_layout_group = meta_backend_native_lock_layout_group;
}
static void
@@ -268,8 +208,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
@@ -282,20 +220,11 @@ 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:
*
* Tells mutter to activate the session. When mutter is a
* display server, this tells logind to switch over to
* Wayland compositor, this tells logind to switch over to
* the new session.
*/
gboolean

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

@@ -27,17 +27,9 @@
#include "meta-cursor-renderer-native.h"
#include <gbm.h>
#include <xf86drm.h>
#include "meta-cursor-private.h"
#include "meta-monitor-manager-private.h"
#ifndef DRM_CAP_CURSOR_WIDTH
#define DRM_CAP_CURSOR_WIDTH 0x8
#endif
#ifndef DRM_CAP_CURSOR_HEIGHT
#define DRM_CAP_CURSOR_HEIGHT 0x9
#endif
#include "meta-monitor-manager.h"
struct _MetaCursorRendererNativePrivate
{
@@ -45,9 +37,6 @@ struct _MetaCursorRendererNativePrivate
int drm_fd;
struct gbm_device *gbm;
uint64_t cursor_width;
uint64_t cursor_height;
};
typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate;
@@ -82,13 +71,17 @@ set_crtc_cursor (MetaCursorRendererNative *native,
{
struct gbm_bo *bo;
union gbm_bo_handle handle;
int width, height;
int hot_x, hot_y;
bo = meta_cursor_reference_get_gbm_bo (cursor, &hot_x, &hot_y);
handle = gbm_bo_get_handle (bo);
width = gbm_bo_get_width (bo);
height = gbm_bo_get_height (bo);
drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, handle.u32,
priv->cursor_width, priv->cursor_height, hot_x, hot_y);
width, height, hot_x, hot_y);
}
else
{
@@ -193,19 +186,6 @@ meta_cursor_renderer_native_init (MetaCursorRendererNative *native)
CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx));
priv->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
priv->gbm = gbm_create_device (priv->drm_fd);
uint64_t width, height;
if (drmGetCap (priv->drm_fd, DRM_CAP_CURSOR_WIDTH, &width) == 0 &&
drmGetCap (priv->drm_fd, DRM_CAP_CURSOR_HEIGHT, &height) == 0)
{
priv->cursor_width = width;
priv->cursor_height = height;
}
else
{
priv->cursor_width = 64;
priv->cursor_height = 64;
}
}
#endif
}
@@ -218,16 +198,6 @@ meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *native)
return priv->gbm;
}
void
meta_cursor_renderer_native_get_cursor_size (MetaCursorRendererNative *native,
uint64_t *width, uint64_t *height)
{
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
*width = priv->cursor_width;
*height = priv->cursor_height;
}
void
meta_cursor_renderer_native_force_update (MetaCursorRendererNative *native)
{

View File

@@ -50,7 +50,6 @@ struct _MetaCursorRendererNativeClass
GType meta_cursor_renderer_native_get_type (void) G_GNUC_CONST;
struct gbm_device * meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *renderer);
void meta_cursor_renderer_native_get_cursor_size (MetaCursorRendererNative *native, uint64_t *width, uint64_t *height);
void meta_cursor_renderer_native_force_update (MetaCursorRendererNative *renderer);
#endif /* META_CURSOR_RENDERER_NATIVE_H */

View File

@@ -1,264 +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 gboolean
device_set_click_method (struct libinput_device *libinput_device,
enum libinput_config_click_method method)
{
enum libinput_config_click_method supported;
supported = libinput_device_config_click_get_methods (libinput_device);
if (method & supported)
libinput_device_config_click_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_EDGE;
break;
case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING:
scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
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_click_method (MetaInputSettings *settings,
ClutterInputDevice *device,
GDesktopTouchpadClickMethod mode)
{
enum libinput_config_click_method click_method = 0;
struct libinput_device *libinput_device;
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
switch (mode)
{
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_DEFAULT:
click_method = libinput_device_config_click_get_default_method (libinput_device);
break;
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_NONE:
click_method = LIBINPUT_CONFIG_CLICK_METHOD_NONE;
break;
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_AREAS:
click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
break;
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_FINGERS:
click_method = LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
break;
default:
g_assert_not_reached ();
return;
}
device_set_click_method (libinput_device, click_method);
}
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_click_method = meta_input_settings_native_set_click_method;
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

@@ -41,7 +41,8 @@
#include "dbus-utils.h"
#include "meta-dbus-login1.h"
#include "backends/meta-backend-private.h"
#include "wayland/meta-wayland-private.h"
#include "backends/meta-backend.h"
#include "meta-cursor-renderer-native.h"
struct _MetaLauncher
@@ -100,15 +101,15 @@ session_unpause (void)
clutter_egl_thaw_master_clock ();
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaBackend *backend = meta_get_backend ();
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (backend);
ClutterActor *stage = meta_backend_get_stage (backend);
/* When we mode-switch back, we need to immediately queue a redraw
* in case nothing else queued one for us, and force the cursor to
* update. */
clutter_actor_queue_redraw (stage);
clutter_actor_queue_redraw (compositor->stage);
meta_cursor_renderer_native_force_update (META_CURSOR_RENDERER_NATIVE (renderer));
}
}
@@ -130,8 +131,8 @@ take_device (Login1Session *session_proxy,
{
gboolean ret = FALSE;
GVariant *fd_variant = NULL;
GUnixFDList *fd_list = NULL;
int fd = -1;
GUnixFDList *fd_list;
if (!login1_session_call_take_device_sync (session_proxy,
dev_major,
@@ -307,7 +308,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 +318,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 +337,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,9 @@
#include <meta/main.h>
#include <meta/errors.h>
#include "edid.h"
#include <gudev/gudev.h>
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
typedef struct {
drmModeConnector *connector;
@@ -66,9 +66,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 +84,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 +204,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 +226,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);
@@ -257,83 +259,17 @@ find_output_by_id (MetaOutput *outputs,
unsigned i;
for (i = 0; i < n_outputs; i++)
if (outputs[i].winsys_id == id)
if (outputs[i].output_id == id)
return &outputs[i];
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 +305,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 +313,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);
@@ -423,9 +363,9 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_crtc->rect.width = crtc->width;
meta_crtc->rect.height = crtc->height;
meta_crtc->is_dirty = FALSE;
meta_crtc->transform = META_MONITOR_TRANSFORM_NORMAL;
meta_crtc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
/* FIXME: implement! */
meta_crtc->all_transforms = 1 << META_MONITOR_TRANSFORM_NORMAL;
meta_crtc->all_transforms = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
if (crtc->mode_valid)
{
@@ -463,17 +403,15 @@ 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;
meta_output->winsys_id = connector->connector_id;
meta_output->output_id = connector->connector_id;
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 +450,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.
@@ -555,7 +491,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_output->crtc = NULL;
old_output = find_output_by_id (old_outputs, n_old_outputs,
meta_output->winsys_id);
meta_output->output_id);
if (old_output)
{
meta_output->is_primary = old_output->is_primary;
@@ -570,13 +506,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 +571,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 +620,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);
}
@@ -690,9 +637,6 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
MetaPowerSave mode)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
ClutterBackend *backend;
CoglContext *cogl_context;
CoglDisplay *cogl_display;
uint64_t state;
unsigned i;
@@ -723,7 +667,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
if (output_kms->dpms_prop_id != 0)
{
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->winsys_id,
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->output_id,
output_kms->dpms_prop_id, state);
if (ok < 0)
@@ -731,14 +675,6 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
meta_output->name, strerror (errno));
}
}
backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (backend);
cogl_display = cogl_context_get_display (cogl_context);
for (i = 0; i < manager->n_crtcs; i++)
cogl_kms_display_set_ignore_crtc (cogl_display, manager->crtcs[i].crtc_id,
mode != META_POWER_SAVE_ON);
}
static void
@@ -812,7 +748,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
{
MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j);
connectors[j] = output->winsys_id;
connectors[j] = output->output_id;
output->is_dirty = TRUE;
output->crtc = crtc;
@@ -959,23 +895,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)
{
@@ -990,24 +909,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
@@ -1026,7 +927,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

@@ -24,18 +24,11 @@
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include "meta-backend-x11.h"
#include <clutter/x11/clutter-x11.h>
#include <X11/extensions/sync.h>
#include <X11/XKBlib.h>
#include <X11/extensions/XKBrules.h>
#include <X11/Xlib-xcb.h>
#include <xkbcommon/xkbcommon-x11.h>
#include "meta-idle-monitor-xsync.h"
#include "meta-monitor-manager-xrandr.h"
@@ -50,7 +43,6 @@ struct _MetaBackendX11Private
{
/* The host X11 display */
Display *xdisplay;
xcb_connection_t *xcb;
GSource *source;
int xsync_event_base;
@@ -60,34 +52,20 @@ struct _MetaBackendX11Private
int xinput_event_base;
int xinput_error_base;
Time latest_evtime;
uint8_t xkb_event_base;
uint8_t xkb_error_base;
struct xkb_keymap *keymap;
gchar *keymap_layouts;
gchar *keymap_variants;
gchar *keymap_options;
};
typedef struct _MetaBackendX11Private MetaBackendX11Private;
static void apply_keymap (MetaBackendX11 *x11);
G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND);
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,39 +107,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);
}
static void
handle_device_change (MetaBackendX11 *x11,
XIEvent *event)
{
XIDeviceChangedEvent *device_changed;
if (event->evtype != XI_DeviceChanged)
return;
device_changed = (XIDeviceChangedEvent *) event;
if (device_changed->reason != XISlaveSwitch)
return;
meta_backend_update_last_device (META_BACKEND (x11),
device_changed->sourceid);
}
/* 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
@@ -173,32 +118,7 @@ handle_device_change (MetaBackendX11 *x11,
*/
static void
maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
XIEvent *input_event)
{
switch (input_event->evtype)
{
case XI_Motion:
case XI_ButtonPress:
case XI_ButtonRelease:
case XI_KeyPress:
case XI_KeyRelease:
case XI_TouchBegin:
case XI_TouchUpdate:
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;
}
}
static void
handle_input_event (MetaBackendX11 *x11,
XEvent *event)
XEvent *event)
{
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
@@ -207,28 +127,24 @@ handle_input_event (MetaBackendX11 *x11,
{
XIEvent *input_event = (XIEvent *) event->xcookie.data;
if (input_event->evtype == XI_DeviceChanged)
handle_device_change (x11, input_event);
else
maybe_spoof_event_as_stage_event (x11, input_event);
switch (input_event->evtype)
{
case XI_Motion:
case XI_ButtonPress:
case XI_ButtonRelease:
case XI_KeyPress:
case XI_KeyRelease:
case XI_TouchBegin:
case XI_TouchUpdate:
case XI_TouchEnd:
translate_device_event (x11, (XIDeviceEvent *) input_event);
break;
default:
break;
}
}
}
static void
keymap_changed (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
if (priv->keymap)
{
xkb_keymap_unref (priv->keymap);
priv->keymap = NULL;
}
g_signal_emit_by_name (backend, "keymap-changed", 0);
}
static void
handle_host_xevent (MetaBackend *backend,
XEvent *event)
@@ -239,37 +155,9 @@ handle_host_xevent (MetaBackend *backend,
XGetEventData (priv->xdisplay, &event->xcookie);
{
MetaDisplay *display = meta_get_display ();
if (display)
{
MetaCompositor *compositor = display->compositor;
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
bypass_clutter = TRUE;
}
}
if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
handle_alarm_notify (backend, event);
if (event->type == priv->xkb_event_base)
{
XkbAnyEvent *xkb_ev = (XkbAnyEvent *) event;
if (xkb_ev->device == META_VIRTUAL_CORE_KEYBOARD_ID)
{
switch (xkb_ev->xkb_type)
{
case XkbNewKeyboardNotify:
case XkbMapNotify:
keymap_changed (backend);
default:
break;
}
}
}
{
MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend);
if (META_IS_MONITOR_MANAGER_XRANDR (manager) &&
@@ -279,7 +167,7 @@ handle_host_xevent (MetaBackend *backend,
if (!bypass_clutter)
{
handle_input_event (x11, event);
maybe_spoof_event_as_stage_event (x11, event);
clutter_x11_handle_event (event);
}
@@ -364,35 +252,6 @@ x_event_source_new (MetaBackend *backend)
return source;
}
static void
take_touch_grab (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { META_VIRTUAL_CORE_POINTER_ID, sizeof (mask_bits), mask_bits };
XIGrabModifiers mods = { XIAnyModifier, 0 };
XISetMask (mask.mask, XI_TouchBegin);
XISetMask (mask.mask, XI_TouchUpdate);
XISetMask (mask.mask, XI_TouchEnd);
XIGrabTouchBegin (priv->xdisplay, META_VIRTUAL_CORE_POINTER_ID,
DefaultRootWindow (priv->xdisplay),
False, &mask, 1, &mods);
}
static void
on_device_added (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
gpointer user_data)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (user_data);
if (clutter_input_device_get_device_type (device) == CLUTTER_KEYBOARD_DEVICE)
apply_keymap (x11);
}
static void
meta_backend_x11_post_init (MetaBackend *backend)
{
@@ -430,22 +289,6 @@ meta_backend_x11_post_init (MetaBackend *backend)
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
}
take_touch_grab (backend);
priv->xcb = XGetXCBConnection (priv->xdisplay);
if (!xkb_x11_setup_xkb_extension (priv->xcb,
XKB_X11_MIN_MAJOR_XKB_VERSION,
XKB_X11_MIN_MINOR_XKB_VERSION,
XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS,
NULL, NULL,
&priv->xkb_event_base,
&priv->xkb_error_base))
meta_fatal ("X server doesn't have the XKB extension, version %d.%d or newer\n",
XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION);
g_signal_connect_object (clutter_device_manager_get_default (), "device-added",
G_CALLBACK (on_device_added), backend, 0);
META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
}
@@ -539,228 +382,6 @@ meta_backend_x11_warp_pointer (MetaBackend *backend,
x, y);
}
static void
get_xkbrf_var_defs (Display *xdisplay,
const char *layouts,
const char *variants,
const char *options,
char **rules_p,
XkbRF_VarDefsRec *var_defs)
{
char *rules = NULL;
/* Get it from the X property or fallback on defaults */
if (!XkbRF_GetNamesProp (xdisplay, &rules, var_defs) || !rules)
{
rules = strdup (DEFAULT_XKB_RULES_FILE);
var_defs->model = strdup (DEFAULT_XKB_MODEL);
var_defs->layout = NULL;
var_defs->variant = NULL;
var_defs->options = NULL;
}
/* Swap in our new options... */
free (var_defs->layout);
var_defs->layout = strdup (layouts);
free (var_defs->variant);
var_defs->variant = strdup (variants);
free (var_defs->options);
var_defs->options = strdup (options);
/* Sometimes, the property is a file path, and sometimes it's
not. Normalize it so it's always a file path. */
if (rules[0] == '/')
*rules_p = g_strdup (rules);
else
*rules_p = g_build_filename (XKB_BASE, "rules", rules, NULL);
free (rules);
}
static void
free_xkbrf_var_defs (XkbRF_VarDefsRec *var_defs)
{
free (var_defs->model);
free (var_defs->layout);
free (var_defs->variant);
free (var_defs->options);
}
static void
free_xkb_component_names (XkbComponentNamesRec *p)
{
free (p->keymap);
free (p->keycodes);
free (p->types);
free (p->compat);
free (p->symbols);
free (p->geometry);
}
static void
upload_xkb_description (Display *xdisplay,
const gchar *rules_file_path,
XkbRF_VarDefsRec *var_defs,
XkbComponentNamesRec *comp_names)
{
XkbDescRec *xkb_desc;
gchar *rules_file;
/* Upload it to the X server using the same method as setxkbmap */
xkb_desc = XkbGetKeyboardByName (xdisplay,
XkbUseCoreKbd,
comp_names,
XkbGBN_AllComponentsMask,
XkbGBN_AllComponentsMask &
(~XkbGBN_GeometryMask), True);
if (!xkb_desc)
{
g_warning ("Couldn't upload new XKB keyboard description");
return;
}
XkbFreeKeyboard (xkb_desc, 0, True);
rules_file = g_path_get_basename (rules_file_path);
if (!XkbRF_SetNamesProp (xdisplay, rules_file, var_defs))
g_warning ("Couldn't update the XKB root window property");
g_free (rules_file);
}
static void
apply_keymap (MetaBackendX11 *x11)
{
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
XkbRF_RulesRec *xkb_rules;
XkbRF_VarDefsRec xkb_var_defs = { 0 };
gchar *rules_file_path;
if (!priv->keymap_layouts ||
!priv->keymap_variants ||
!priv->keymap_options)
return;
get_xkbrf_var_defs (priv->xdisplay,
priv->keymap_layouts,
priv->keymap_variants,
priv->keymap_options,
&rules_file_path,
&xkb_var_defs);
xkb_rules = XkbRF_Load (rules_file_path, NULL, True, True);
if (xkb_rules)
{
XkbComponentNamesRec xkb_comp_names = { 0 };
XkbRF_GetComponents (xkb_rules, &xkb_var_defs, &xkb_comp_names);
upload_xkb_description (priv->xdisplay, rules_file_path, &xkb_var_defs, &xkb_comp_names);
free_xkb_component_names (&xkb_comp_names);
XkbRF_Free (xkb_rules, True);
}
else
{
g_warning ("Couldn't load XKB rules");
}
free_xkbrf_var_defs (&xkb_var_defs);
g_free (rules_file_path);
}
static void
meta_backend_x11_set_keymap (MetaBackend *backend,
const char *layouts,
const char *variants,
const char *options)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
g_free (priv->keymap_layouts);
priv->keymap_layouts = g_strdup (layouts);
g_free (priv->keymap_variants);
priv->keymap_variants = g_strdup (variants);
g_free (priv->keymap_options);
priv->keymap_options = g_strdup (options);
apply_keymap (x11);
}
static struct xkb_keymap *
meta_backend_x11_get_keymap (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
if (priv->keymap == NULL)
{
struct xkb_context *context = xkb_context_new (XKB_CONTEXT_NO_FLAGS);
priv->keymap = xkb_x11_keymap_new_from_device (context,
priv->xcb,
xkb_x11_get_core_keyboard_device_id (priv->xcb),
XKB_KEYMAP_COMPILE_NO_FLAGS);
xkb_context_unref (context);
}
return priv->keymap;
}
static void
meta_backend_x11_lock_layout_group (MetaBackend *backend,
guint idx)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, idx);
}
static void
meta_backend_x11_update_screen_size (MetaBackend *backend,
int width, int height)
{
if (meta_is_wayland_compositor ())
{
/* For a nested wayland session, we want to go through Clutter to update the
* toplevel window size, rather than doing it directly.
*/
META_BACKEND_CLASS (meta_backend_x11_parent_class)->update_screen_size (backend, width, height);
}
else
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
Window xwin = meta_backend_x11_get_xwindow (x11);
XResizeWindow (priv->xdisplay, xwin, width, height);
}
}
static void
meta_backend_x11_select_stage_events (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
Window xwin = meta_backend_x11_get_xwindow (x11);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_FocusIn);
XISetMask (mask.mask, XI_FocusOut);
XISetMask (mask.mask, XI_Motion);
XIClearMask (mask.mask, XI_TouchBegin);
XIClearMask (mask.mask, XI_TouchEnd);
XIClearMask (mask.mask, XI_TouchUpdate);
XISelectEvents (priv->xdisplay, xwin, &mask, 1);
}
static void
meta_backend_x11_class_init (MetaBackendX11Class *klass)
{
@@ -770,14 +391,10 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
backend_class->create_idle_monitor = meta_backend_x11_create_idle_monitor;
backend_class->create_monitor_manager = meta_backend_x11_create_monitor_manager;
backend_class->create_cursor_renderer = meta_backend_x11_create_cursor_renderer;
backend_class->grab_device = meta_backend_x11_grab_device;
backend_class->ungrab_device = meta_backend_x11_ungrab_device;
backend_class->warp_pointer = meta_backend_x11_warp_pointer;
backend_class->set_keymap = meta_backend_x11_set_keymap;
backend_class->get_keymap = meta_backend_x11_get_keymap;
backend_class->lock_layout_group = meta_backend_x11_lock_layout_group;
backend_class->update_screen_size = meta_backend_x11_update_screen_size;
backend_class->select_stage_events = meta_backend_x11_select_stage_events;
}
static void
@@ -798,6 +415,12 @@ meta_backend_x11_get_xdisplay (MetaBackendX11 *x11)
Window
meta_backend_x11_get_xwindow (MetaBackendX11 *x11)
{
ClutterActor *stage = meta_backend_get_stage (META_BACKEND (x11));
return clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
MetaDisplay *display = meta_get_display ();
MetaCompositor *compositor = display->compositor;
if (compositor == NULL)
return None;
ClutterStage *stage = CLUTTER_STAGE (compositor->stage);
return clutter_x11_get_stage_window (stage);
}

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"

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