Compare commits
	
		
			16 Commits
		
	
	
		
			3.14.1
			...
			wip/gestur
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 3ed80495e0 | ||
|   | f13c86d651 | ||
|   | be2ca66735 | ||
|   | 2df807549e | ||
|   | 66cdb1bb71 | ||
|   | 8030a2972e | ||
|   | ba086dea8c | ||
|   | 6a02d7dfa3 | ||
|   | c5db56da5c | ||
|   | b5c605df5e | ||
|   | 4ad2865cce | ||
|   | b9687d1a72 | ||
|   | 66d18fcc55 | ||
|   | 321cd5d85f | ||
|   | ae91de5d03 | ||
|   | 7247b8d81b | 
							
								
								
									
										14
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -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] | ||||
|   | ||||
							
								
								
									
										120
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										120
									
								
								NEWS
									
									
									
									
									
								
							| @@ -1,123 +1,3 @@ | ||||
| 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] | ||||
|   | ||||
							
								
								
									
										62
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										62
									
								
								configure.ac
									
									
									
									
									
								
							| @@ -1,8 +1,8 @@ | ||||
| AC_PREREQ(2.62) | ||||
|  | ||||
| m4_define([mutter_major_version], [3]) | ||||
| m4_define([mutter_minor_version], [14]) | ||||
| m4_define([mutter_micro_version], [1]) | ||||
| 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.25.10 | ||||
|    gio-2.0 >= 2.25.10 | ||||
|    pango >= 1.2.0 | ||||
|    cairo >= 1.10.0 | ||||
|    gsettings-desktop-schemas >= 3.7.3 | ||||
|    $CLUTTER_PACKAGE >= 1.19.5 | ||||
|    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 | ||||
|    gbm >= 10.3 | ||||
|    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 | ||||
|    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,27 +184,20 @@ 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) | ||||
|  | ||||
| PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [clutter-egl-1.0 libdrm libsystemd libinput], [have_native_backend=yes], [have_native_backend=no]) | ||||
| 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_MODULES(MUTTER_WAYLAND, [clutter-wayland-1.0 clutter-wayland-compositor-1.0 wayland-server >= 1.5.90], [have_wayland=yes], [have_wayland=no]) | ||||
| if test $have_wayland = yes; then | ||||
|    AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no]) | ||||
|    AS_IF([test $WAYLAND_SCANNER = "no"], | ||||
|      AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols])) | ||||
|    AC_SUBST([WAYLAND_SCANNER]) | ||||
|  | ||||
|    AC_DEFINE([HAVE_WAYLAND],[1],[Define if you want to enable Wayland support]) | ||||
| fi | ||||
| AM_CONDITIONAL([HAVE_WAYLAND],[test $have_wayland = yes]) | ||||
|  | ||||
| PKG_CHECK_EXISTS([xi >= 1.6.99.1], | ||||
|                  AC_DEFINE([HAVE_XI23],[1],[Define if you have support for XInput 2.3 or greater])) | ||||
|  | ||||
| @@ -254,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 | ||||
|   | ||||
| @@ -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"/> | ||||
|  | ||||
|   | ||||
| @@ -111,13 +111,6 @@ IGNORE_HFILES= \ | ||||
| 	xprops.h \ | ||||
| 	$(NULL) | ||||
|  | ||||
| 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. | ||||
|   | ||||
| @@ -300,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 | ||||
|   | ||||
| @@ -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> | ||||
|   | ||||
							
								
								
									
										2681
									
								
								po/bn_IN.po
									
									
									
									
									
								
							
							
						
						
									
										2681
									
								
								po/bn_IN.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1275
									
								
								po/ca@valencia.po
									
									
									
									
									
								
							
							
						
						
									
										1275
									
								
								po/ca@valencia.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1308
									
								
								po/pt_BR.po
									
									
									
									
									
								
							
							
						
						
									
										1308
									
								
								po/pt_BR.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1300
									
								
								po/sr@latin.po
									
									
									
									
									
								
							
							
						
						
									
										1300
									
								
								po/sr@latin.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1240
									
								
								po/zh_CN.po
									
									
									
									
									
								
							
							
						
						
									
										1240
									
								
								po/zh_CN.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1193
									
								
								po/zh_HK.po
									
									
									
									
									
								
							
							
						
						
									
										1193
									
								
								po/zh_HK.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1221
									
								
								po/zh_TW.po
									
									
									
									
									
								
							
							
						
						
									
										1221
									
								
								po/zh_TW.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,51 +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 | ||||
| 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 | ||||
| @@ -5,15 +5,11 @@ lib_LTLIBRARIES = libmutter.la | ||||
|  | ||||
| SUBDIRS=compositor/plugins | ||||
|  | ||||
| EXTRA_DIST = | ||||
|  | ||||
| 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)							\ | ||||
| @@ -37,16 +33,13 @@ 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 | ||||
|  | ||||
| if HAVE_WAYLAND | ||||
| mutter_built_sources += \ | ||||
| 	mutter-enum-types.c			\ | ||||
| 	gtk-shell-protocol.c			\ | ||||
| 	gtk-shell-server-protocol.h		\ | ||||
| 	xdg-shell-protocol.c			\ | ||||
| 	xdg-shell-server-protocol.h | ||||
| endif | ||||
|  | ||||
| wayland_protocols = \ | ||||
| 	wayland/protocol/gtk-shell.xml		\ | ||||
| @@ -54,7 +47,7 @@ wayland_protocols = \ | ||||
|  | ||||
| libmutter_la_SOURCES =				\ | ||||
| 	backends/meta-backend.c			\ | ||||
| 	meta/meta-backend.h			\ | ||||
| 	backends/meta-backend.h			\ | ||||
| 	backends/meta-backend-private.h		\ | ||||
| 	backends/meta-cursor.c			\ | ||||
| 	backends/meta-cursor.h			\ | ||||
| @@ -74,8 +67,6 @@ libmutter_la_SOURCES =				\ | ||||
| 	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			\ | ||||
| @@ -102,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		\ | ||||
| @@ -126,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		\ | ||||
| @@ -141,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		\ | ||||
| @@ -164,8 +152,8 @@ libmutter_la_SOURCES =				\ | ||||
| 	core/frame.h				\ | ||||
| 	ui/gradient.c				\ | ||||
| 	meta/gradient.h				\ | ||||
| 	core/meta-gesture-tracker.c		\ | ||||
| 	core/meta-gesture-tracker-private.h	\ | ||||
| 	core/gesture-tracker.c			\ | ||||
| 	core/gesture-tracker-private.h		\ | ||||
| 	core/keybindings.c			\ | ||||
| 	core/keybindings-private.h		\ | ||||
| 	core/main.c				\ | ||||
| @@ -177,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			\ | ||||
| @@ -222,22 +209,13 @@ libmutter_la_SOURCES =				\ | ||||
| 	x11/window-x11-private.h		\ | ||||
| 	x11/xprops.c				\ | ||||
| 	x11/xprops.h				\ | ||||
| 	x11/mutter-Xatomtype.h | ||||
|  | ||||
| if HAVE_WAYLAND | ||||
| libmutter_la_SOURCES +=				\ | ||||
| 	compositor/meta-surface-actor-wayland.c	\ | ||||
| 	compositor/meta-surface-actor-wayland.h	\ | ||||
| 	x11/mutter-Xatomtype.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		\ | ||||
| @@ -256,7 +234,6 @@ libmutter_la_SOURCES +=				\ | ||||
| 	wayland/meta-wayland-outputs.h		\ | ||||
| 	wayland/window-wayland.c		\ | ||||
| 	wayland/window-wayland.h | ||||
| endif | ||||
|  | ||||
| if HAVE_NATIVE_BACKEND | ||||
| libmutter_la_SOURCES +=					\ | ||||
| @@ -294,11 +271,9 @@ libmutterinclude_headers =			\ | ||||
| 	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			\ | ||||
| @@ -335,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) | ||||
|  | ||||
| @@ -379,20 +347,28 @@ 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 +=				\ | ||||
| EXTRA_DIST =				\ | ||||
| 	$(wayland_protocols)		\ | ||||
| 	libmutter.pc.in \ | ||||
| 	mutter-enum-types.h.in \ | ||||
| @@ -401,10 +377,7 @@ EXTRA_DIST +=				\ | ||||
| 	org.gnome.Mutter.DisplayConfig.xml	\ | ||||
| 	org.gnome.Mutter.IdleMonitor.xml | ||||
|  | ||||
| BUILT_SOURCES =					\ | ||||
| 	$(mutter_built_sources)			\ | ||||
| 	$(libmutterinclude_built_headers) | ||||
|  | ||||
| BUILT_SOURCES = $(mutter_built_sources) | ||||
| MUTTER_STAMP_FILES = stamp-mutter-enum-types.h | ||||
| CLEANFILES += $(MUTTER_STAMP_FILES) | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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.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)) | ||||
| @@ -74,37 +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); | ||||
|  | ||||
| #endif /* META_BACKEND_PRIVATE_H */ | ||||
|   | ||||
| @@ -24,11 +24,12 @@ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include <meta/meta-backend.h> | ||||
| #include "meta-backend.h" | ||||
| #include "meta-backend-private.h" | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include "backends/x11/meta-backend-x11.h" | ||||
| #include "meta-stage.h" | ||||
|  | ||||
| #ifdef HAVE_NATIVE_BACKEND | ||||
| #include "backends/native/meta-backend-native.h" | ||||
| @@ -36,13 +37,6 @@ | ||||
|  | ||||
| static MetaBackend *_backend; | ||||
|  | ||||
| /** | ||||
|  * meta_get_backend: | ||||
|  * | ||||
|  * Accessor for the singleton MetaBackend. | ||||
|  * | ||||
|  * Returns: (transfer none): The only #MetaBackend there is. | ||||
|  */ | ||||
| MetaBackend * | ||||
| meta_get_backend (void) | ||||
| { | ||||
| @@ -53,8 +47,6 @@ struct _MetaBackendPrivate | ||||
| { | ||||
|   MetaMonitorManager *monitor_manager; | ||||
|   MetaCursorRenderer *cursor_renderer; | ||||
|  | ||||
|   ClutterActor *stage; | ||||
| }; | ||||
| typedef struct _MetaBackendPrivate MetaBackendPrivate; | ||||
|  | ||||
| @@ -78,121 +70,13 @@ meta_backend_finalize (GObject *object) | ||||
|   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 | ||||
| on_monitors_changed (MetaMonitorManager *monitors, | ||||
|                      gpointer user_data) | ||||
| { | ||||
|   MetaBackend *backend = META_BACKEND (user_data); | ||||
|   meta_backend_sync_screen_size (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) | ||||
| { | ||||
|   g_assert (backend->device_monitors[device_id] == NULL); | ||||
|  | ||||
|   backend->device_monitors[device_id] = meta_backend_create_idle_monitor (backend, device_id); | ||||
|   backend->device_id_max = MAX (backend->device_id_max, device_id); | ||||
| } | ||||
|  | ||||
| static void | ||||
| destroy_device_monitor (MetaBackend *backend, | ||||
|                         int          device_id) | ||||
| { | ||||
|   g_clear_object (&backend->device_monitors[device_id]); | ||||
|  | ||||
|   if (device_id == backend->device_id_max) | ||||
|     { | ||||
|       /* Reset the max device ID */ | ||||
|       int i, new_max = 0; | ||||
|       for (i = 0; i < backend->device_id_max; i++) | ||||
|         if (backend->device_monitors[i] != NULL) | ||||
|           new_max = i; | ||||
|       backend->device_id_max = new_max; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| 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 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); | ||||
| } | ||||
|  | ||||
| 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 = META_BACKEND_GET_CLASS (backend)->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->cursor_renderer = META_BACKEND_GET_CLASS (backend)->create_cursor_renderer (backend); | ||||
|  | ||||
|   { | ||||
|     ClutterDeviceManager *manager; | ||||
|     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); | ||||
|       } | ||||
|  | ||||
|     g_slist_free (devices); | ||||
|   } | ||||
| } | ||||
|  | ||||
| static MetaCursorRenderer * | ||||
| @@ -219,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) | ||||
| { | ||||
| @@ -245,21 +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); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -268,27 +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) | ||||
| { | ||||
|   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) | ||||
| { | ||||
| @@ -297,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) | ||||
| { | ||||
| @@ -308,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, | ||||
| @@ -319,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, | ||||
| @@ -330,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, | ||||
| @@ -341,47 +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; | ||||
| } | ||||
|  | ||||
| static GType | ||||
| get_backend_type (void) | ||||
| { | ||||
| @@ -454,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 (); | ||||
| @@ -468,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); | ||||
|   | ||||
| @@ -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); | ||||
| 
 | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -34,21 +34,25 @@ | ||||
| #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 "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]; | ||||
| @@ -56,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; | ||||
| @@ -95,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; | ||||
| } | ||||
|  | ||||
| @@ -130,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; | ||||
| @@ -149,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; | ||||
| } | ||||
| @@ -170,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; | ||||
| @@ -207,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; | ||||
| @@ -217,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; | ||||
|  | ||||
|   | ||||
| @@ -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) | ||||
| @@ -139,56 +137,35 @@ load_cursor_on_client (MetaCursor cursor) | ||||
|                                   meta_prefs_get_cursor_size ()); | ||||
| } | ||||
|  | ||||
| static void | ||||
| get_hardware_cursor_size (uint64_t *cursor_width, uint64_t *cursor_height) | ||||
| { | ||||
| #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)) | ||||
|     { | ||||
|       meta_cursor_renderer_native_get_cursor_size (META_CURSOR_RENDERER_NATIVE (renderer), cursor_width, cursor_height); | ||||
|       return; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|   g_assert_not_reached (); | ||||
| } | ||||
|  | ||||
| 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); | ||||
| @@ -212,7 +189,7 @@ 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; | ||||
| @@ -270,7 +247,6 @@ meta_cursor_reference_from_theme (MetaCursor cursor) | ||||
|   return self; | ||||
| } | ||||
|  | ||||
| #ifdef HAVE_WAYLAND | ||||
| static void | ||||
| meta_cursor_image_load_from_buffer (MetaCursorImage    *image, | ||||
|                                     struct wl_resource *buffer, | ||||
| @@ -283,8 +259,7 @@ meta_cursor_image_load_from_buffer (MetaCursorImage    *image, | ||||
|   CoglContext *cogl_context; | ||||
|   struct wl_shm_buffer *shm_buffer; | ||||
|   uint32_t gbm_format; | ||||
|   uint64_t cursor_width, cursor_height; | ||||
|   uint width, height; | ||||
|   int width, height; | ||||
|  | ||||
|   image->hot_x = hot_x; | ||||
|   image->hot_y = hot_y; | ||||
| @@ -335,23 +310,22 @@ meta_cursor_image_load_from_buffer (MetaCursorImage    *image, | ||||
|     } | ||||
|   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) | ||||
|         { | ||||
|           meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n"); | ||||
|           return; | ||||
|         } | ||||
|  | ||||
|       if (gbm) | ||||
|         { | ||||
|           /* 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); | ||||
|  | ||||
|           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); | ||||
|           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"); | ||||
|         } | ||||
| @@ -371,7 +345,6 @@ meta_cursor_reference_from_buffer (struct wl_resource *buffer, | ||||
|  | ||||
|   return self; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| CoglTexture * | ||||
| meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor, | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -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)); | ||||
|  | ||||
|   | ||||
| @@ -60,7 +60,7 @@ typedef struct { | ||||
|   gboolean enabled; | ||||
|   MetaRectangle rect; | ||||
|   float refresh_rate; | ||||
|   MetaMonitorTransform transform; | ||||
|   enum wl_output_transform transform; | ||||
|  | ||||
|   gboolean is_primary; | ||||
|   gboolean is_presentation; | ||||
| @@ -656,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) */ | ||||
| @@ -1115,7 +1115,7 @@ make_default_config (MetaMonitorConfig *self, | ||||
|       ret->outputs[0].rect.width = outputs[0].preferred_mode->width; | ||||
|       ret->outputs[0].rect.height = outputs[0].preferred_mode->height; | ||||
|       ret->outputs[0].refresh_rate = outputs[0].preferred_mode->refresh_rate; | ||||
|       ret->outputs[0].transform = META_MONITOR_TRANSFORM_NORMAL; | ||||
|       ret->outputs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL; | ||||
|       ret->outputs[0].is_primary = TRUE; | ||||
|  | ||||
|       return ret; | ||||
| @@ -1167,7 +1167,7 @@ make_default_config (MetaMonitorConfig *self, | ||||
|                   ret->outputs[j].rect.width = outputs[0].preferred_mode->width; | ||||
|                   ret->outputs[j].rect.height = outputs[0].preferred_mode->height; | ||||
|                   ret->outputs[j].refresh_rate = outputs[0].preferred_mode->refresh_rate; | ||||
|                   ret->outputs[j].transform = META_MONITOR_TRANSFORM_NORMAL; | ||||
|                   ret->outputs[j].transform = WL_OUTPUT_TRANSFORM_NORMAL; | ||||
|                   ret->outputs[j].is_primary = FALSE; | ||||
|                   ret->outputs[j].is_presentation = FALSE; | ||||
|                 } | ||||
| @@ -1202,7 +1202,7 @@ make_default_config (MetaMonitorConfig *self, | ||||
|       ret->outputs[i].rect.width = output->preferred_mode->width; | ||||
|       ret->outputs[i].rect.height = output->preferred_mode->height; | ||||
|       ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate; | ||||
|       ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL; | ||||
|       ret->outputs[i].transform = WL_OUTPUT_TRANSFORM_NORMAL; | ||||
|       ret->outputs[i].is_primary = (output == primary); | ||||
|  | ||||
|       /* Disable outputs that would go beyond framebuffer limits */ | ||||
| @@ -1250,7 +1250,7 @@ ensure_at_least_one_output (MetaMonitorConfig  *self, | ||||
|           ret->outputs[i].rect.width = output->preferred_mode->width; | ||||
|           ret->outputs[i].rect.height = output->preferred_mode->height; | ||||
|           ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate; | ||||
|           ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL; | ||||
|           ret->outputs[i].transform = WL_OUTPUT_TRANSFORM_NORMAL; | ||||
|           ret->outputs[i].is_primary = TRUE; | ||||
|         } | ||||
|       else | ||||
| @@ -1512,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"); | ||||
|             } | ||||
| @@ -1621,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); | ||||
|  | ||||
| @@ -1789,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, | ||||
|   | ||||
| @@ -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"); | ||||
|   | ||||
| @@ -37,13 +37,19 @@ | ||||
| #include <meta/errors.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 | ||||
| }; | ||||
|  | ||||
| enum { | ||||
|   PROP_0, | ||||
|   PROP_POWER_SAVE_MODE, | ||||
|   PROP_LAST | ||||
| }; | ||||
|  | ||||
| static int signals[SIGNALS_LAST]; | ||||
|  | ||||
| static void meta_monitor_manager_display_config_init (MetaDBusDisplayConfigIface *iface); | ||||
| @@ -119,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); | ||||
|  | ||||
| @@ -150,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; | ||||
| @@ -161,39 +167,11 @@ 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 (); | ||||
| @@ -236,6 +214,23 @@ meta_monitor_manager_constructed (GObject *object) | ||||
|   manager->in_init = FALSE; | ||||
| } | ||||
|  | ||||
| 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) | ||||
| @@ -303,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) | ||||
| @@ -323,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; | ||||
|  | ||||
| @@ -336,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[] = { | ||||
| @@ -440,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); | ||||
|  | ||||
| @@ -523,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, | ||||
| @@ -630,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) | ||||
| @@ -657,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 (); | ||||
| @@ -718,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, | ||||
| @@ -730,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)) | ||||
|             { | ||||
| @@ -786,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, | ||||
| @@ -800,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; | ||||
| @@ -871,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); | ||||
| @@ -885,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) | ||||
|     { | ||||
|   | ||||
| @@ -41,6 +41,8 @@ | ||||
| #include "display-private.h" | ||||
| #include <meta/screen.h> | ||||
| #include "stack-tracker.h" | ||||
| #include "ui.h" | ||||
| #include <wayland-server.h> | ||||
|  | ||||
| #include "meta-display-config-shared.h" | ||||
| #include "meta-dbus-display-config.h" | ||||
| @@ -58,23 +60,12 @@ 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; | ||||
|  | ||||
| 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; | ||||
| @@ -123,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 | ||||
| @@ -171,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; | ||||
| }; | ||||
|  | ||||
| /* | ||||
| @@ -194,7 +185,7 @@ struct _MetaCRTCInfo { | ||||
|   MetaMonitorMode          *mode; | ||||
|   int                       x; | ||||
|   int                       y; | ||||
|   MetaMonitorTransform      transform; | ||||
|   enum wl_output_transform  transform; | ||||
|   GPtrArray                *outputs; | ||||
| }; | ||||
|  | ||||
| @@ -348,7 +339,7 @@ gboolean           meta_monitor_manager_has_hotplug_mode_update (MetaMonitorMana | ||||
| /* 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); | ||||
| } | ||||
|   | ||||
| @@ -36,24 +36,11 @@ | ||||
| struct _MetaBackendNativePrivate | ||||
| { | ||||
|   MetaLauncher *launcher; | ||||
|  | ||||
|   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); | ||||
|  | ||||
|   g_clear_object (&priv->keyboard_settings); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_backend_native_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * The pointer constrain code is mostly a rip-off of the XRandR code from Xorg. | ||||
|  * (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder) | ||||
| @@ -155,46 +142,15 @@ pointer_constrain_callback (ClutterInputDevice *device, | ||||
|   constrain_all_screen_monitors(device, monitors, n_monitors, new_x, new_y); | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_keyboard_repeat (MetaBackendNative *native) | ||||
| { | ||||
|   MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native); | ||||
|   ClutterDeviceManager *manager = clutter_device_manager_get_default (); | ||||
|   gboolean repeat; | ||||
|   unsigned int delay, interval; | ||||
|  | ||||
|   repeat = g_settings_get_boolean (priv->keyboard_settings, "repeat"); | ||||
|   delay = g_settings_get_uint (priv->keyboard_settings, "delay"); | ||||
|   interval = g_settings_get_uint (priv->keyboard_settings, "repeat-interval"); | ||||
|  | ||||
|   clutter_evdev_set_keyboard_repeat (manager, repeat, delay, interval); | ||||
| } | ||||
|  | ||||
| static void | ||||
| keyboard_settings_changed (GSettings           *settings, | ||||
|                            const char          *key, | ||||
|                            gpointer             data) | ||||
| { | ||||
|   MetaBackendNative *native = data; | ||||
|   set_keyboard_repeat (native); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_backend_native_post_init (MetaBackend *backend) | ||||
| { | ||||
|   MetaBackendNative *native = META_BACKEND_NATIVE (backend); | ||||
|   MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native); | ||||
|   ClutterDeviceManager *manager = clutter_device_manager_get_default (); | ||||
|  | ||||
|   META_BACKEND_CLASS (meta_backend_native_parent_class)->post_init (backend); | ||||
|  | ||||
|   clutter_evdev_set_pointer_constrain_callback (manager, pointer_constrain_callback, | ||||
|                                                 NULL, NULL); | ||||
|  | ||||
|   priv->keyboard_settings = g_settings_new ("org.gnome.settings-daemon.peripherals.keyboard"); | ||||
|   g_signal_connect (priv->keyboard_settings, "changed", | ||||
|                     G_CALLBACK (keyboard_settings_changed), native); | ||||
|   set_keyboard_repeat (native); | ||||
| } | ||||
|  | ||||
| static MetaIdleMonitor * | ||||
| @@ -232,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; | ||||
| @@ -290,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 | ||||
| @@ -318,7 +224,7 @@ meta_activate_vt (int vt, GError **error) | ||||
|  * 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 | ||||
|   | ||||
| @@ -27,27 +27,16 @@ | ||||
| #include "meta-cursor-renderer-native.h" | ||||
|  | ||||
| #include <gbm.h> | ||||
| #include <xf86drm.h> | ||||
|  | ||||
| #include "meta-cursor-private.h" | ||||
| #include "meta-monitor-manager.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 | ||||
|  | ||||
| struct _MetaCursorRendererNativePrivate | ||||
| { | ||||
|   gboolean has_hw_cursor; | ||||
|  | ||||
|   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) | ||||
| { | ||||
|   | ||||
| @@ -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 */ | ||||
|   | ||||
| @@ -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)); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -40,6 +40,8 @@ | ||||
| #include <meta/errors.h> | ||||
| #include "edid.h" | ||||
|  | ||||
| #define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1) | ||||
|  | ||||
| typedef struct { | ||||
|   drmModeConnector *connector; | ||||
|  | ||||
| @@ -257,7 +259,7 @@ 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; | ||||
| @@ -361,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) | ||||
|         { | ||||
| @@ -406,7 +408,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager) | ||||
|           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; | ||||
| @@ -489,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; | ||||
| @@ -665,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) | ||||
| @@ -746,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; | ||||
|   | ||||
| @@ -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,19 +52,9 @@ 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 | ||||
| @@ -163,21 +145,6 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11, | ||||
|     } | ||||
| } | ||||
|  | ||||
| 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) | ||||
| @@ -188,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) && | ||||
| @@ -313,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) | ||||
| { | ||||
| @@ -379,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); | ||||
| } | ||||
|  | ||||
| @@ -488,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) | ||||
| { | ||||
| @@ -719,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 | ||||
| @@ -747,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); | ||||
| } | ||||
|   | ||||
| @@ -35,8 +35,6 @@ | ||||
| #include <X11/Xatom.h> | ||||
| #include <X11/extensions/Xrandr.h> | ||||
| #include <X11/extensions/dpms.h> | ||||
| #include <X11/Xlib-xcb.h> | ||||
| #include <xcb/randr.h> | ||||
|  | ||||
| #include "meta-backend-x11.h" | ||||
| #include <meta/main.h> | ||||
| @@ -44,7 +42,7 @@ | ||||
| #include "edid.h" | ||||
| #include "meta-monitor-config.h" | ||||
|  | ||||
| #define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1) | ||||
| #define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1) | ||||
|  | ||||
| /* Look for DPI_FALLBACK in: | ||||
|  * http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c | ||||
| @@ -69,31 +67,31 @@ struct _MetaMonitorManagerXrandrClass | ||||
|  | ||||
| G_DEFINE_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, META_TYPE_MONITOR_MANAGER); | ||||
|  | ||||
| static MetaMonitorTransform | ||||
| meta_monitor_transform_from_xrandr (Rotation rotation) | ||||
| static enum wl_output_transform | ||||
| wl_transform_from_xrandr (Rotation rotation) | ||||
| { | ||||
|   static const MetaMonitorTransform y_reflected_map[4] = { | ||||
|     META_MONITOR_TRANSFORM_FLIPPED_180, | ||||
|     META_MONITOR_TRANSFORM_FLIPPED_90, | ||||
|     META_MONITOR_TRANSFORM_FLIPPED, | ||||
|     META_MONITOR_TRANSFORM_FLIPPED_270 | ||||
|   static const enum wl_output_transform y_reflected_map[4] = { | ||||
|     WL_OUTPUT_TRANSFORM_FLIPPED_180, | ||||
|     WL_OUTPUT_TRANSFORM_FLIPPED_90, | ||||
|     WL_OUTPUT_TRANSFORM_FLIPPED, | ||||
|     WL_OUTPUT_TRANSFORM_FLIPPED_270 | ||||
|   }; | ||||
|   MetaMonitorTransform ret; | ||||
|   enum wl_output_transform ret; | ||||
|  | ||||
|   switch (rotation & 0x7F) | ||||
|     { | ||||
|     default: | ||||
|     case RR_Rotate_0: | ||||
|       ret = META_MONITOR_TRANSFORM_NORMAL; | ||||
|       ret = WL_OUTPUT_TRANSFORM_NORMAL; | ||||
|       break; | ||||
|     case RR_Rotate_90: | ||||
|       ret = META_MONITOR_TRANSFORM_90; | ||||
|       ret = WL_OUTPUT_TRANSFORM_90; | ||||
|       break; | ||||
|     case RR_Rotate_180: | ||||
|       ret = META_MONITOR_TRANSFORM_180; | ||||
|       ret = WL_OUTPUT_TRANSFORM_180; | ||||
|       break; | ||||
|     case RR_Rotate_270: | ||||
|       ret = META_MONITOR_TRANSFORM_270; | ||||
|       ret = WL_OUTPUT_TRANSFORM_270; | ||||
|       break; | ||||
|     } | ||||
|  | ||||
| @@ -107,74 +105,67 @@ meta_monitor_transform_from_xrandr (Rotation rotation) | ||||
|  | ||||
| #define ALL_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270) | ||||
|  | ||||
| static MetaMonitorTransform | ||||
| meta_monitor_transform_from_xrandr_all (Rotation rotation) | ||||
| static unsigned int | ||||
| wl_transform_from_xrandr_all (Rotation rotation) | ||||
| { | ||||
|   unsigned ret; | ||||
|  | ||||
|   /* Handle the common cases first (none or all) */ | ||||
|   if (rotation == 0 || rotation == RR_Rotate_0) | ||||
|     return (1 << META_MONITOR_TRANSFORM_NORMAL); | ||||
|     return (1 << WL_OUTPUT_TRANSFORM_NORMAL); | ||||
|  | ||||
|   /* All rotations and one reflection -> all of them by composition */ | ||||
|   if ((rotation & ALL_ROTATIONS) && | ||||
|       ((rotation & RR_Reflect_X) || (rotation & RR_Reflect_Y))) | ||||
|     return ALL_TRANSFORMS; | ||||
|     return ALL_WL_TRANSFORMS; | ||||
|  | ||||
|   ret = 1 << META_MONITOR_TRANSFORM_NORMAL; | ||||
|   ret = 1 << WL_OUTPUT_TRANSFORM_NORMAL; | ||||
|   if (rotation & RR_Rotate_90) | ||||
|     ret |= 1 << META_MONITOR_TRANSFORM_90; | ||||
|     ret |= 1 << WL_OUTPUT_TRANSFORM_90; | ||||
|   if (rotation & RR_Rotate_180) | ||||
|     ret |= 1 << META_MONITOR_TRANSFORM_180; | ||||
|     ret |= 1 << WL_OUTPUT_TRANSFORM_180; | ||||
|   if (rotation & RR_Rotate_270) | ||||
|     ret |= 1 << META_MONITOR_TRANSFORM_270; | ||||
|     ret |= 1 << WL_OUTPUT_TRANSFORM_270; | ||||
|   if (rotation & (RR_Rotate_0 | RR_Reflect_X)) | ||||
|     ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED; | ||||
|     ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED; | ||||
|   if (rotation & (RR_Rotate_90 | RR_Reflect_X)) | ||||
|     ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_90; | ||||
|     ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_90; | ||||
|   if (rotation & (RR_Rotate_180 | RR_Reflect_X)) | ||||
|     ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_180; | ||||
|     ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_180; | ||||
|   if (rotation & (RR_Rotate_270 | RR_Reflect_X)) | ||||
|     ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_270; | ||||
|     ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_270; | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr, | ||||
|                              MetaOutput *output, const char *propname) | ||||
| output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr, | ||||
|                                 MetaOutput               *output) | ||||
| { | ||||
|   gboolean value = FALSE; | ||||
|   gboolean value; | ||||
|   Atom atom, actual_type; | ||||
|   int actual_format; | ||||
|   unsigned long nitems, bytes_after; | ||||
|   unsigned char *buffer; | ||||
|  | ||||
|   atom = XInternAtom (manager_xrandr->xdisplay, propname, False); | ||||
|   atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False); | ||||
|   XRRGetOutputProperty (manager_xrandr->xdisplay, | ||||
|                         (XID)output->winsys_id, | ||||
|                         (XID)output->output_id, | ||||
|                         atom, | ||||
|                         0, G_MAXLONG, False, False, XA_CARDINAL, | ||||
|                         &actual_type, &actual_format, | ||||
|                         &nitems, &bytes_after, &buffer); | ||||
|  | ||||
|   if (actual_type != XA_CARDINAL || actual_format != 32 || nitems < 1) | ||||
|     goto out; | ||||
|   if (actual_type != XA_CARDINAL || actual_format != 32 || | ||||
|       nitems < 1) | ||||
|     return FALSE; | ||||
|  | ||||
|   value = ((int*)buffer)[0]; | ||||
|  | ||||
|  out: | ||||
|   XFree (buffer); | ||||
|   return value; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr, | ||||
|                                 MetaOutput *output) | ||||
| { | ||||
|   return output_get_boolean_property (manager_xrandr, output, "_MUTTER_PRESENTATION_OUTPUT"); | ||||
| } | ||||
|  | ||||
| static int | ||||
| normalize_backlight (MetaOutput *output, | ||||
|                      int         hw_value) | ||||
| @@ -187,7 +178,7 @@ static int | ||||
| output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr, | ||||
|                              MetaOutput               *output) | ||||
| { | ||||
|   int value = -1; | ||||
|   gboolean value; | ||||
|   Atom atom, actual_type; | ||||
|   int actual_format; | ||||
|   unsigned long nitems, bytes_after; | ||||
| @@ -195,23 +186,20 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr, | ||||
|  | ||||
|   atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False); | ||||
|   XRRGetOutputProperty (manager_xrandr->xdisplay, | ||||
|                         (XID)output->winsys_id, | ||||
|                         (XID)output->output_id, | ||||
|                         atom, | ||||
|                         0, G_MAXLONG, False, False, XA_INTEGER, | ||||
|                         &actual_type, &actual_format, | ||||
|                         &nitems, &bytes_after, &buffer); | ||||
|  | ||||
|   if (actual_type != XA_INTEGER || actual_format != 32 || nitems < 1) | ||||
|     goto out; | ||||
|   if (actual_type != XA_INTEGER || actual_format != 32 || | ||||
|       nitems < 1) | ||||
|     return -1; | ||||
|  | ||||
|   value = ((int*)buffer)[0]; | ||||
|  | ||||
|  out: | ||||
|   XFree (buffer); | ||||
|   if (value > 0) | ||||
|     return normalize_backlight (output, value); | ||||
|   else | ||||
|     return -1; | ||||
|   return normalize_backlight (output, value); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -219,34 +207,30 @@ output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr, | ||||
|                                     MetaOutput               *output) | ||||
| { | ||||
|   Atom atom; | ||||
|   xcb_connection_t *xcb_conn; | ||||
|   xcb_randr_query_output_property_reply_t *reply; | ||||
|   XRRPropertyInfo *info; | ||||
|  | ||||
|   atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False); | ||||
|   info = XRRQueryOutputProperty (manager_xrandr->xdisplay, | ||||
|                                  (XID)output->output_id, | ||||
|                                  atom); | ||||
|  | ||||
|   xcb_conn = XGetXCBConnection (manager_xrandr->xdisplay); | ||||
|   reply = xcb_randr_query_output_property_reply (xcb_conn, | ||||
|                                                  xcb_randr_query_output_property (xcb_conn, | ||||
|                                                                                   (xcb_randr_output_t) output->winsys_id, | ||||
|                                                                                   (xcb_atom_t) atom), | ||||
|                                                  NULL); | ||||
|   if (info == NULL) | ||||
|     { | ||||
|       meta_verbose ("could not get output property for %s\n", output->name); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   /* This can happen on systems without backlights. */ | ||||
|   if (reply == NULL) | ||||
|     return; | ||||
|  | ||||
|   if (!reply->range || reply->length != 2) | ||||
|   if (!info->range || info->num_values != 2) | ||||
|     { | ||||
|       meta_verbose ("backlight %s was not range\n", output->name); | ||||
|       goto out; | ||||
|     } | ||||
|  | ||||
|   int32_t *values = xcb_randr_query_output_property_valid_values (reply); | ||||
|   output->backlight_min = values[0]; | ||||
|   output->backlight_max = values[1]; | ||||
|   output->backlight_min = info->values[0]; | ||||
|   output->backlight_max = info->values[1]; | ||||
|  | ||||
| out: | ||||
|   free (reply); | ||||
|   XFree (info); | ||||
| } | ||||
|  | ||||
| static int | ||||
| @@ -294,25 +278,25 @@ get_edid_property (Display  *dpy, | ||||
|  | ||||
| static GBytes * | ||||
| read_output_edid (MetaMonitorManagerXrandr *manager_xrandr, | ||||
|                   XID                       winsys_id) | ||||
|                   XID                       output_id) | ||||
| { | ||||
|   Atom edid_atom; | ||||
|   guint8 *result; | ||||
|   gsize len; | ||||
|  | ||||
|   edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID", FALSE); | ||||
|   result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len); | ||||
|   result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len); | ||||
|  | ||||
|   if (!result) | ||||
|     { | ||||
|       edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID_DATA", FALSE); | ||||
|       result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len); | ||||
|       result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len); | ||||
|     } | ||||
|  | ||||
|   if (!result) | ||||
|     { | ||||
|       edid_atom = XInternAtom (manager_xrandr->xdisplay, "XFree86_DDC_EDID1_RAWDATA", FALSE); | ||||
|       result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len); | ||||
|       result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len); | ||||
|     } | ||||
|  | ||||
|   if (result) | ||||
| @@ -328,26 +312,26 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr, | ||||
|  | ||||
| static gboolean | ||||
| output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr, | ||||
|                                 MetaOutput               *output) | ||||
|                                 XID                       output_id) | ||||
| { | ||||
|   return output_get_boolean_property (manager_xrandr, output, "hotplug_mode_update"); | ||||
| } | ||||
|   Atom atom; | ||||
|   XRRPropertyInfo *info; | ||||
|   gboolean result = FALSE; | ||||
|  | ||||
| static char * | ||||
| get_xmode_name (XRRModeInfo *xmode) | ||||
| { | ||||
|   int width = xmode->width; | ||||
|   int height = xmode->height; | ||||
|   atom = XInternAtom (manager_xrandr->xdisplay, "hotplug_mode_update", False); | ||||
|   info = XRRQueryOutputProperty (manager_xrandr->xdisplay, output_id, | ||||
|                                  atom); | ||||
|  | ||||
|   if (xmode->hSkew != 0) | ||||
|   if (info) | ||||
|     { | ||||
|       width += 2 * (xmode->hSkew >> 8); | ||||
|       height += 2 * (xmode->hSkew & 0xff); | ||||
|       result = TRUE; | ||||
|       XFree (info); | ||||
|     } | ||||
|  | ||||
|   return g_strdup_printf ("%dx%d", width, height); | ||||
|   return result; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager) | ||||
| { | ||||
| @@ -433,7 +417,6 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager) | ||||
|       mode->height = xmode->height; | ||||
|       mode->refresh_rate = (xmode->dotClock / | ||||
| 			    ((float)xmode->hTotal * xmode->vTotal)); | ||||
|       mode->name = get_xmode_name (xmode); | ||||
|     } | ||||
|  | ||||
|   for (i = 0; i < (unsigned)resources->ncrtc; i++) | ||||
| @@ -451,8 +434,8 @@ meta_monitor_manager_xrandr_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_from_xrandr (crtc->rotation); | ||||
|       meta_crtc->all_transforms = meta_monitor_transform_from_xrandr_all (crtc->rotations); | ||||
|       meta_crtc->transform = wl_transform_from_xrandr (crtc->rotation); | ||||
|       meta_crtc->all_transforms = wl_transform_from_xrandr_all (crtc->rotations); | ||||
|  | ||||
|       for (j = 0; j < (unsigned)resources->nmode; j++) | ||||
| 	{ | ||||
| @@ -484,10 +467,10 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager) | ||||
|           GBytes *edid; | ||||
|           MonitorInfo *parsed_edid; | ||||
|  | ||||
| 	  meta_output->winsys_id = resources->outputs[i]; | ||||
| 	  meta_output->output_id = resources->outputs[i]; | ||||
| 	  meta_output->name = g_strdup (output->name); | ||||
|  | ||||
|           edid = read_output_edid (manager_xrandr, meta_output->winsys_id); | ||||
|           edid = read_output_edid (manager_xrandr, meta_output->output_id); | ||||
|           if (edid) | ||||
|             { | ||||
|               gsize len; | ||||
| @@ -520,7 +503,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager) | ||||
| 	  meta_output->width_mm = output->mm_width; | ||||
| 	  meta_output->height_mm = output->mm_height; | ||||
| 	  meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN; | ||||
|           meta_output->hotplug_mode_update = output_get_hotplug_mode_update (manager_xrandr, meta_output); | ||||
|           meta_output->hotplug_mode_update = | ||||
|               output_get_hotplug_mode_update (manager_xrandr, meta_output->output_id); | ||||
|  | ||||
| 	  meta_output->n_modes = output->nmode; | ||||
| 	  meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes); | ||||
| @@ -572,7 +556,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager) | ||||
| 	      meta_output->possible_clones[j] = GINT_TO_POINTER (output->clones[j]); | ||||
| 	    } | ||||
|  | ||||
| 	  meta_output->is_primary = ((XID)meta_output->winsys_id == primary_output); | ||||
| 	  meta_output->is_primary = ((XID)meta_output->output_id == primary_output); | ||||
| 	  meta_output->is_presentation = output_get_presentation_xrandr (manager_xrandr, meta_output); | ||||
| 	  output_get_backlight_limits_xrandr (manager_xrandr, meta_output); | ||||
|  | ||||
| @@ -605,7 +589,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager) | ||||
|  | ||||
| 	  for (k = 0; k < manager->n_outputs; k++) | ||||
| 	    { | ||||
| 	      if (clone == (XID)manager->outputs[k].winsys_id) | ||||
| 	      if (clone == (XID)manager->outputs[k].output_id) | ||||
| 		{ | ||||
| 		  meta_output->possible_clones[j] = &manager->outputs[k]; | ||||
| 		  break; | ||||
| @@ -621,7 +605,7 @@ meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager, | ||||
| { | ||||
|   MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); | ||||
|  | ||||
|   return read_output_edid (manager_xrandr, output->winsys_id); | ||||
|   return read_output_edid (manager_xrandr, output->output_id); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -653,25 +637,25 @@ meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager, | ||||
| } | ||||
|  | ||||
| static Rotation | ||||
| meta_monitor_transform_to_xrandr (MetaMonitorTransform transform) | ||||
| wl_transform_to_xrandr (enum wl_output_transform transform) | ||||
| { | ||||
|   switch (transform) | ||||
|     { | ||||
|     case META_MONITOR_TRANSFORM_NORMAL: | ||||
|     case WL_OUTPUT_TRANSFORM_NORMAL: | ||||
|       return RR_Rotate_0; | ||||
|     case META_MONITOR_TRANSFORM_90: | ||||
|     case WL_OUTPUT_TRANSFORM_90: | ||||
|       return RR_Rotate_90; | ||||
|     case META_MONITOR_TRANSFORM_180: | ||||
|     case WL_OUTPUT_TRANSFORM_180: | ||||
|       return RR_Rotate_180; | ||||
|     case META_MONITOR_TRANSFORM_270: | ||||
|     case WL_OUTPUT_TRANSFORM_270: | ||||
|       return RR_Rotate_270; | ||||
|     case META_MONITOR_TRANSFORM_FLIPPED: | ||||
|     case WL_OUTPUT_TRANSFORM_FLIPPED: | ||||
|       return RR_Reflect_X | RR_Rotate_0; | ||||
|     case META_MONITOR_TRANSFORM_FLIPPED_90: | ||||
|     case WL_OUTPUT_TRANSFORM_FLIPPED_90: | ||||
|       return RR_Reflect_X | RR_Rotate_90; | ||||
|     case META_MONITOR_TRANSFORM_FLIPPED_180: | ||||
|     case WL_OUTPUT_TRANSFORM_FLIPPED_180: | ||||
|       return RR_Reflect_X | RR_Rotate_180; | ||||
|     case META_MONITOR_TRANSFORM_FLIPPED_270: | ||||
|     case WL_OUTPUT_TRANSFORM_FLIPPED_270: | ||||
|       return RR_Reflect_X | RR_Rotate_270; | ||||
|     } | ||||
|  | ||||
| @@ -688,7 +672,7 @@ output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr, | ||||
|  | ||||
|   atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False); | ||||
|   XRRChangeOutputProperty (manager_xrandr->xdisplay, | ||||
|                            (XID)output->winsys_id, | ||||
|                            (XID)output->output_id, | ||||
|                            atom, | ||||
|                            XA_CARDINAL, 32, PropModeReplace, | ||||
|                            (unsigned char*) &value, 1); | ||||
| @@ -844,7 +828,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager, | ||||
|               output->crtc = crtc; | ||||
|               new_controlled_mask |= 1UL << j; | ||||
|  | ||||
|               outputs[j] = output->winsys_id; | ||||
|               outputs[j] = output->output_id; | ||||
|             } | ||||
|  | ||||
|           if (crtc->current_mode == mode && | ||||
| @@ -863,7 +847,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager, | ||||
|                                  manager_xrandr->time, | ||||
|                                  crtc_info->x, crtc_info->y, | ||||
|                                  (XID)mode->mode_id, | ||||
|                                  meta_monitor_transform_to_xrandr (crtc_info->transform), | ||||
|                                  wl_transform_to_xrandr (crtc_info->transform), | ||||
|                                  outputs, n_outputs); | ||||
|  | ||||
|           if (ok != Success) | ||||
| @@ -907,7 +891,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager, | ||||
|         { | ||||
|           XRRSetOutputPrimary (manager_xrandr->xdisplay, | ||||
|                                DefaultRootWindow (manager_xrandr->xdisplay), | ||||
|                                (XID)output_info->output->winsys_id); | ||||
|                                (XID)output_info->output->output_id); | ||||
|         } | ||||
|  | ||||
|       output_set_presentation_xrandr (manager_xrandr, | ||||
| @@ -950,7 +934,7 @@ meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager, | ||||
|  | ||||
|   atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False); | ||||
|   XRRChangeOutputProperty (manager_xrandr->xdisplay, | ||||
|                            (XID)output->winsys_id, | ||||
|                            (XID)output->output_id, | ||||
|                            atom, | ||||
|                            XA_INTEGER, 32, PropModeReplace, | ||||
|                            (unsigned char *) &hw_value, 1); | ||||
| @@ -1075,7 +1059,6 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra | ||||
|   MetaMonitorMode *old_modes; | ||||
|   unsigned int n_old_outputs, n_old_modes; | ||||
|   gboolean new_config; | ||||
|   gboolean applied_config = FALSE; | ||||
|  | ||||
|   if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify) | ||||
|     return FALSE; | ||||
| @@ -1092,32 +1075,39 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra | ||||
|   manager->serial++; | ||||
|   meta_monitor_manager_xrandr_read_current (manager); | ||||
|  | ||||
|   new_config = manager_xrandr->resources->timestamp >= manager_xrandr->resources->configTimestamp; | ||||
|   new_config = manager_xrandr->resources->timestamp >= | ||||
|     manager_xrandr->resources->configTimestamp; | ||||
|   if (meta_monitor_manager_has_hotplug_mode_update (manager)) | ||||
|  | ||||
|   /* If this is the X server telling us we set a new configuration, | ||||
|    * we can simply short-cut to rebuilding our logical configuration. | ||||
|    */ | ||||
|   if (new_config || meta_monitor_config_match_current (manager->config, manager)) | ||||
|     { | ||||
|       meta_monitor_manager_xrandr_rebuild_derived (manager); | ||||
|       goto out; | ||||
|       /* Check if the current intended configuration is a result of an | ||||
|          XRandR call.  Otherwise, hotplug_mode_update tells us to get | ||||
|          a new preferred mode on hotplug events to handle dynamic | ||||
|          guest resizing. */ | ||||
|       if (new_config) | ||||
|         meta_monitor_manager_xrandr_rebuild_derived (manager); | ||||
|       else | ||||
|         meta_monitor_config_make_default (manager->config, manager); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       /* Check if the current intended configuration has the same outputs | ||||
|          as the new real one, or if the event is a result of an XRandR call. | ||||
|          If so, we can go straight to rebuild the logical config and tell | ||||
|          the outside world. | ||||
|          Otherwise, this event was caused by hotplug, so give a chance to | ||||
|          MetaMonitorConfig. | ||||
|  | ||||
|          Note that we need to check both the timestamps and the list of | ||||
|          outputs, because the X server might emit spurious events with new | ||||
|          configTimestamps (bug 702804), and the driver may have changed | ||||
|          the EDID for some other reason (old qxl and vbox drivers). */ | ||||
|       if (new_config || meta_monitor_config_match_current (manager->config, manager)) | ||||
|         meta_monitor_manager_xrandr_rebuild_derived (manager); | ||||
|       else if (!meta_monitor_config_apply_stored (manager->config, manager)) | ||||
|         meta_monitor_config_make_default (manager->config, manager); | ||||
|     } | ||||
|  | ||||
|   /* 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); | ||||
|  | ||||
|  out: | ||||
|   meta_monitor_manager_free_output_array (old_outputs, n_old_outputs); | ||||
|   meta_monitor_manager_free_mode_array (old_modes, n_old_modes); | ||||
|   g_free (old_crtcs); | ||||
|   | ||||
| @@ -51,12 +51,6 @@ round_to_fixed (float x) | ||||
|   return roundf (x * 256); | ||||
| } | ||||
|  | ||||
| /* Help macros to scale from OpenGL <-1,1> coordinates system to | ||||
|  * window coordinates ranging [0,window-size]. Borrowed from clutter-utils.c | ||||
|  */ | ||||
| #define MTX_GL_SCALE_X(x,w,v1,v2) ((((((x) / (w)) + 1.0f) / 2.0f) * (v1)) + (v2)) | ||||
| #define MTX_GL_SCALE_Y(y,w,v1,v2) ((v1) - (((((y) / (w)) + 1.0f) / 2.0f) * (v1)) + (v2)) | ||||
|  | ||||
| /* This helper function checks if (according to our fixed point precision) | ||||
|  * the vertices @verts form a box of width @widthf and height @heightf | ||||
|  * located at integral coordinates. These coordinates are returned | ||||
| @@ -124,67 +118,3 @@ meta_actor_is_untransformed (ClutterActor *actor, | ||||
|   return meta_actor_vertices_are_untransformed (verts, widthf, heightf, x_origin, y_origin); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_actor_painting_untransformed: | ||||
|  * @paint_width: the width of the painted area | ||||
|  * @paint_height: the height of the painted area | ||||
|  * @x_origin: if the transform is only an integer translation | ||||
|  *  then the X coordinate of the location of the origin under the transformation | ||||
|  *  from drawing space to screen pixel space is returned here. | ||||
|  * @y_origin: if the transform is only an integer translation | ||||
|  *  then the X coordinate of the location of the origin under the transformation | ||||
|  *  from drawing space to screen pixel space is returned here. | ||||
|  * | ||||
|  * Determines if the current painting transform is an integer translation. | ||||
|  * This can differ from the result of meta_actor_is_untransformed() when | ||||
|  * painting an actor if we're inside a inside a clone paint. @paint_width | ||||
|  * and @paint_height are used to determine the vertices of the rectangle | ||||
|  * we check to see if the painted area is "close enough" to the integer | ||||
|  * transform. | ||||
|  */ | ||||
| gboolean | ||||
| meta_actor_painting_untransformed (int              paint_width, | ||||
|                                    int              paint_height, | ||||
|                                    int             *x_origin, | ||||
|                                    int             *y_origin) | ||||
| { | ||||
|   CoglMatrix modelview, projection, modelview_projection; | ||||
|   ClutterVertex vertices[4]; | ||||
|   float viewport[4]; | ||||
|   int i; | ||||
|  | ||||
|   cogl_get_modelview_matrix (&modelview); | ||||
|   cogl_get_projection_matrix (&projection); | ||||
|  | ||||
|   cogl_matrix_multiply (&modelview_projection, | ||||
|                         &projection, | ||||
|                         &modelview); | ||||
|  | ||||
|   vertices[0].x = 0; | ||||
|   vertices[0].y = 0; | ||||
|   vertices[0].z = 0; | ||||
|   vertices[1].x = paint_width; | ||||
|   vertices[1].y = 0; | ||||
|   vertices[1].z = 0; | ||||
|   vertices[2].x = 0; | ||||
|   vertices[2].y = paint_height; | ||||
|   vertices[2].z = 0; | ||||
|   vertices[3].x = paint_width; | ||||
|   vertices[3].y = paint_height; | ||||
|   vertices[3].z = 0; | ||||
|  | ||||
|   cogl_get_viewport (viewport); | ||||
|  | ||||
|   for (i = 0; i < 4; i++) | ||||
|     { | ||||
|       float w = 1; | ||||
|       cogl_matrix_transform_point (&modelview_projection, &vertices[i].x, &vertices[i].y, &vertices[i].z, &w); | ||||
|       vertices[i].x = MTX_GL_SCALE_X (vertices[i].x, w, | ||||
|                                       viewport[2], viewport[0]); | ||||
|       vertices[i].y = MTX_GL_SCALE_Y (vertices[i].y, w, | ||||
|                                       viewport[3], viewport[1]); | ||||
|     } | ||||
|  | ||||
|   return meta_actor_vertices_are_untransformed (vertices, paint_width, paint_height, x_origin, y_origin); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -31,9 +31,4 @@ gboolean meta_actor_is_untransformed (ClutterActor *actor, | ||||
|                                       int          *x_origin, | ||||
|                                       int          *y_origin); | ||||
|  | ||||
| gboolean meta_actor_painting_untransformed (int         paint_width, | ||||
|                                             int         paint_height, | ||||
|                                             int        *x_origin, | ||||
|                                             int        *y_origin); | ||||
|  | ||||
| #endif /* __META_CLUTTER_UTILS_H__ */ | ||||
|   | ||||
| @@ -22,6 +22,48 @@ | ||||
| #include <clutter/clutter.h> | ||||
| #include "cogl-utils.h" | ||||
|  | ||||
| /** | ||||
|  * meta_create_color_texture_4ub: | ||||
|  * @red: red component | ||||
|  * @green: green component | ||||
|  * @blue: blue component | ||||
|  * @alpha: alpha component | ||||
|  * @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE; | ||||
|  *   %COGL_TEXTURE_NO_SLICING is useful if the texture will be | ||||
|  *   repeated to create a constant color fill, since hardware | ||||
|  *   repeat can't be used for a sliced texture. | ||||
|  * | ||||
|  * Creates a texture that is a single pixel with the specified | ||||
|  * unpremultiplied color components. | ||||
|  * | ||||
|  * Return value: (transfer full): a newly created Cogl texture | ||||
|  */ | ||||
| CoglTexture * | ||||
| meta_create_color_texture_4ub (guint8           red, | ||||
|                                guint8           green, | ||||
|                                guint8           blue, | ||||
|                                guint8           alpha, | ||||
|                                CoglTextureFlags flags) | ||||
| { | ||||
|   CoglColor color; | ||||
|   guint8 pixel[4]; | ||||
|  | ||||
|   cogl_color_init_from_4ub (&color, red, green, blue, alpha); | ||||
|   cogl_color_premultiply (&color); | ||||
|  | ||||
|   pixel[0] = cogl_color_get_red_byte (&color); | ||||
|   pixel[1] = cogl_color_get_green_byte (&color); | ||||
|   pixel[2] = cogl_color_get_blue_byte (&color); | ||||
|   pixel[3] = cogl_color_get_alpha_byte (&color); | ||||
|  | ||||
|   return cogl_texture_new_from_data (1, 1, | ||||
|                                      flags, | ||||
|                                      COGL_PIXEL_FORMAT_RGBA_8888_PRE, | ||||
|                                      COGL_PIXEL_FORMAT_ANY, | ||||
|                                      4, pixel); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Based on gnome-shell/src/st/st-private.c:_st_create_texture_material.c */ | ||||
|  | ||||
| /** | ||||
| @@ -64,78 +106,3 @@ meta_create_texture_pipeline (CoglTexture *src_texture) | ||||
|  | ||||
|   return pipeline; | ||||
| } | ||||
|  | ||||
| static gboolean is_pot(int x) | ||||
| { | ||||
|   return x > 0 && (x & (x - 1)) == 0; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_create_texture: | ||||
|  * @width: width of the texture to create | ||||
|  * @height: height of the texture to create | ||||
|  * @components; components to store in the texture (color or alpha) | ||||
|  * @flags: flags that affect the allocation behavior | ||||
|  * | ||||
|  * Creates a texture of the given size with the specified components | ||||
|  * for use as a frame buffer object. | ||||
|  * | ||||
|  * If non-power-of-two textures are not supported on the system, then | ||||
|  * the texture will be created as a texture rectangle; in this case, | ||||
|  * hardware repeating isn't possible, and texture coordinates are also | ||||
|  * different, but Cogl hides these issues from the application, except from | ||||
|  * GLSL shaders. Since GLSL is never (or at least almost never) | ||||
|  * present on such a system, this is not typically an issue. | ||||
|  * | ||||
|  * If %META_TEXTURE_ALLOW_SLICING is present in @flags, and the texture | ||||
|  * is larger than the texture size limits of the system, then the texture | ||||
|  * will be created as a sliced texture. This also will cause problems | ||||
|  * with using the texture with GLSL, and is more likely to be an issue | ||||
|  * since all GL implementations have texture size limits, and they can | ||||
|  * be as small as 2048x2048 on reasonably current systems. | ||||
|  */ | ||||
| CoglTexture * | ||||
| meta_create_texture (int                   width, | ||||
|                      int                   height, | ||||
|                      CoglTextureComponents components, | ||||
|                      MetaTextureFlags      flags) | ||||
| { | ||||
|   ClutterBackend *backend = clutter_get_default_backend (); | ||||
|   CoglContext *ctx = clutter_backend_get_cogl_context (backend); | ||||
|   CoglTexture *texture; | ||||
|  | ||||
|   gboolean should_use_rectangle = FALSE; | ||||
|  | ||||
|   if (!(is_pot (width) && is_pot (height)) && | ||||
|       !cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT)) | ||||
|     { | ||||
|       if (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_RECTANGLE)) | ||||
|         should_use_rectangle = TRUE; | ||||
|       else | ||||
|         g_error ("Cannot create texture. Support for GL_ARB_texture_non_power_of_two or " | ||||
|                  "ARB_texture_rectangle is required"); | ||||
|     } | ||||
|  | ||||
|   if (should_use_rectangle) | ||||
|     texture = COGL_TEXTURE (cogl_texture_rectangle_new_with_size (ctx, width, height)); | ||||
|   else | ||||
|     texture = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx, width, height)); | ||||
|   cogl_texture_set_components (texture, components); | ||||
|  | ||||
|   if ((flags & META_TEXTURE_ALLOW_SLICING) != 0) | ||||
|     { | ||||
|       /* To find out if we need to slice the texture, we have to go ahead and force storage | ||||
|        * to be allocated | ||||
|        */ | ||||
|       CoglError *catch_error = NULL; | ||||
|       if (!cogl_texture_allocate (texture, &catch_error)) | ||||
|         { | ||||
|           cogl_error_free (catch_error); | ||||
|           cogl_object_unref (texture); | ||||
|           texture = COGL_TEXTURE (cogl_texture_2d_sliced_new_with_size (ctx, width, height, COGL_TEXTURE_MAX_WASTE)); | ||||
|           cogl_texture_set_components (texture, components); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   return texture; | ||||
| } | ||||
|   | ||||
| @@ -23,16 +23,11 @@ | ||||
|  | ||||
| #include <cogl/cogl.h> | ||||
|  | ||||
| CoglTexture * meta_create_color_texture_4ub (guint8           red, | ||||
|                                              guint8           green, | ||||
|                                              guint8           blue, | ||||
|                                              guint8           alpha, | ||||
|                                              CoglTextureFlags flags); | ||||
| CoglPipeline * meta_create_texture_pipeline (CoglTexture *texture); | ||||
|  | ||||
| typedef enum { | ||||
|   META_TEXTURE_FLAGS_NONE = 0, | ||||
|   META_TEXTURE_ALLOW_SLICING = 1 << 1 | ||||
| } MetaTextureFlags; | ||||
|  | ||||
| CoglTexture *meta_create_texture (int                   width, | ||||
|                                   int                   height, | ||||
|                                   CoglTextureComponents components, | ||||
|                                   MetaTextureFlags      flags); | ||||
|  | ||||
| #endif /* __META_COGL_UTILS_H__ */ | ||||
|   | ||||
| @@ -23,7 +23,7 @@ struct _MetaCompositor | ||||
|   guint           server_time_is_monotonic_time : 1; | ||||
|   guint           no_mipmaps  : 1; | ||||
|  | ||||
|   ClutterActor          *stage, *window_group, *top_window_group, *feedback_group; | ||||
|   ClutterActor          *stage, *window_group, *top_window_group; | ||||
|   ClutterActor          *background_actor; | ||||
|   GList                 *windows; | ||||
|   Window                 output; | ||||
| @@ -38,8 +38,6 @@ struct _MetaCompositor | ||||
|   gint                   switch_workspace_in_progress; | ||||
|  | ||||
|   MetaPluginManager *plugin_mgr; | ||||
|  | ||||
|   gboolean frame_has_updated_xsurfaces; | ||||
| }; | ||||
|  | ||||
| /* Wait 2ms after vblank before starting to draw next frame */ | ||||
|   | ||||
| @@ -67,29 +67,40 @@ | ||||
| #include <meta/compositor-mutter.h> | ||||
| #include <meta/prefs.h> | ||||
| #include <meta/main.h> | ||||
| #include <meta/meta-backend.h> | ||||
| #include <meta/meta-background-actor.h> | ||||
| #include <meta/meta-background-group.h> | ||||
| #include <meta/meta-shadow-factory.h> | ||||
| #include "meta-window-actor-private.h" | ||||
| #include "meta-window-group.h" | ||||
| #include "meta-stage.h" | ||||
| #include "window-private.h" /* to check window->hidden */ | ||||
| #include "display-private.h" /* for meta_display_lookup_x_window() and meta_display_cancel_touch() */ | ||||
| #include "display-private.h" /* for meta_display_lookup_x_window() */ | ||||
| #include "util-private.h" | ||||
| #include "frame.h" | ||||
| #include <X11/extensions/shape.h> | ||||
| #include <X11/extensions/Xcomposite.h> | ||||
|  | ||||
| #include "backends/meta-backend.h" | ||||
| #include "backends/x11/meta-backend-x11.h" | ||||
|  | ||||
| #ifdef HAVE_WAYLAND | ||||
| #include "wayland/meta-wayland-private.h" | ||||
| #endif | ||||
|  | ||||
| static gboolean | ||||
| is_modal (MetaDisplay *display) | ||||
| { | ||||
|   return display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB; | ||||
|   return display->grab_op == META_GRAB_OP_COMPOSITOR; | ||||
| } | ||||
|  | ||||
| static inline gboolean | ||||
| composite_at_least_version (MetaDisplay *display, int maj, int min) | ||||
| { | ||||
|   static int major = -1; | ||||
|   static int minor = -1; | ||||
|  | ||||
|   if (major == -1) | ||||
|     meta_display_get_compositor_version (display, &major, &minor); | ||||
|  | ||||
|   return (major > maj || (major == maj && minor >= min)); | ||||
| } | ||||
|  | ||||
| static void sync_actor_stacking (MetaCompositor *compositor); | ||||
| @@ -135,8 +146,33 @@ process_damage (MetaCompositor     *compositor, | ||||
| { | ||||
|   MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window)); | ||||
|   meta_window_actor_process_x11_damage (window_actor, event); | ||||
| } | ||||
|  | ||||
|   compositor->frame_has_updated_xsurfaces = TRUE; | ||||
| static Window | ||||
| get_output_window (MetaCompositor *compositor) | ||||
| { | ||||
|   MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); | ||||
|   Display *xdisplay = meta_backend_x11_get_xdisplay (backend); | ||||
|   Window output; | ||||
|   unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; | ||||
|   XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; | ||||
|  | ||||
|   output = XCompositeGetOverlayWindow (xdisplay, DefaultRootWindow (xdisplay)); | ||||
|  | ||||
|   meta_core_add_old_event_mask (xdisplay, output, &mask); | ||||
|  | ||||
|   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); | ||||
|   XISelectEvents (xdisplay, output, &mask, 1); | ||||
|  | ||||
|   return output; | ||||
| } | ||||
|  | ||||
| /* compat helper */ | ||||
| @@ -185,19 +221,6 @@ meta_get_top_window_group_for_screen (MetaScreen *screen) | ||||
|   return compositor->top_window_group; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_get_feedback_group_for_screen: | ||||
|  * @screen: a #MetaScreen | ||||
|  * | ||||
|  * Returns: (transfer none): The feedback group corresponding to @screen | ||||
|  */ | ||||
| ClutterActor * | ||||
| meta_get_feedback_group_for_screen (MetaScreen *screen) | ||||
| { | ||||
|   MetaCompositor *compositor = get_compositor_for_screen (screen); | ||||
|   return compositor->feedback_group; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_get_window_actors: | ||||
|  * @screen: a #MetaScreen | ||||
| @@ -358,7 +381,6 @@ meta_begin_modal_for_plugin (MetaCompositor   *compositor, | ||||
|     return FALSE; | ||||
|  | ||||
|   display->grab_op = META_GRAB_OP_COMPOSITOR; | ||||
|   display->event_route = META_EVENT_ROUTE_COMPOSITOR_GRAB; | ||||
|   display->grab_window = NULL; | ||||
|   display->grab_have_pointer = TRUE; | ||||
|   display->grab_have_keyboard = TRUE; | ||||
| @@ -368,10 +390,7 @@ meta_begin_modal_for_plugin (MetaCompositor   *compositor, | ||||
|                          display->grab_window, display->grab_op); | ||||
|  | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     { | ||||
|       meta_display_sync_wayland_input_focus (display); | ||||
|       meta_display_cancel_touch (display); | ||||
|     } | ||||
|     meta_display_sync_wayland_input_focus (display); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
| @@ -391,7 +410,6 @@ meta_end_modal_for_plugin (MetaCompositor *compositor, | ||||
|                          display->grab_window, display->grab_op); | ||||
|  | ||||
|   display->grab_op = META_GRAB_OP_NONE; | ||||
|   display->event_route = META_EVENT_ROUTE_NORMAL; | ||||
|   display->grab_window = NULL; | ||||
|   display->grab_have_pointer = FALSE; | ||||
|   display->grab_have_keyboard = FALSE; | ||||
| @@ -413,10 +431,8 @@ after_stage_paint (ClutterStage *stage, | ||||
|   for (l = compositor->windows; l; l = l->next) | ||||
|     meta_window_actor_post_paint (l->data); | ||||
|  | ||||
| #ifdef HAVE_WAYLAND | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ()); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -468,34 +484,70 @@ meta_compositor_manage (MetaCompositor *compositor) | ||||
|   MetaDisplay *display = compositor->display; | ||||
|   Display *xdisplay = display->xdisplay; | ||||
|   MetaScreen *screen = display->screen; | ||||
|   Window xwin = 0; | ||||
|   gint width, height; | ||||
|  | ||||
|   meta_screen_set_cm_selection (display->screen); | ||||
|  | ||||
|   { | ||||
|     MetaBackend *backend = meta_get_backend (); | ||||
|     compositor->stage = meta_backend_get_stage (backend); | ||||
|   } | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     { | ||||
|       MetaWaylandCompositor *wayland_compositor = meta_wayland_compositor_get_default (); | ||||
|  | ||||
|   /* We use connect_after() here to accomodate code in GNOME Shell that, | ||||
|    * when benchmarking drawing performance, connects to ::after-paint | ||||
|    * and calls glFinish(). The timing information from that will be | ||||
|    * more accurate if we hold off until that completes before we signal | ||||
|    * apps to begin drawing the next frame. If there are no other | ||||
|    * connections to ::after-paint, connect() vs. connect_after() doesn't | ||||
|    * matter. | ||||
|    */ | ||||
|   g_signal_connect_after (CLUTTER_STAGE (compositor->stage), "after-paint", | ||||
|                           G_CALLBACK (after_stage_paint), compositor); | ||||
|       compositor->stage = meta_stage_new (); | ||||
|       clutter_actor_show (compositor->stage); | ||||
|  | ||||
|       wayland_compositor->stage = compositor->stage; | ||||
|  | ||||
|       meta_screen_get_size (screen, &width, &height); | ||||
|       clutter_actor_set_size (compositor->stage, width, height); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       compositor->stage = clutter_stage_new (); | ||||
|  | ||||
|       meta_screen_get_size (screen, &width, &height); | ||||
|       clutter_actor_realize (compositor->stage); | ||||
|  | ||||
|       xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage)); | ||||
|  | ||||
|       XResizeWindow (xdisplay, xwin, width, height); | ||||
|  | ||||
|         { | ||||
|           MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); | ||||
|           Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend); | ||||
|           unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; | ||||
|           XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; | ||||
|  | ||||
|           meta_core_add_old_event_mask (backend_xdisplay, xwin, &mask); | ||||
|  | ||||
|           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 (backend_xdisplay, xwin, &mask, 1); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   clutter_stage_set_paint_callback (CLUTTER_STAGE (compositor->stage), | ||||
|                                     after_stage_paint, | ||||
|                                     compositor, | ||||
|                                     NULL); | ||||
|  | ||||
|   clutter_stage_set_sync_delay (CLUTTER_STAGE (compositor->stage), META_SYNC_DELAY); | ||||
|  | ||||
|   compositor->window_group = meta_window_group_new (screen); | ||||
|   compositor->top_window_group = meta_window_group_new (screen); | ||||
|   compositor->feedback_group = meta_window_group_new (screen); | ||||
|  | ||||
|   clutter_actor_add_child (compositor->stage, compositor->window_group); | ||||
|   clutter_actor_add_child (compositor->stage, compositor->top_window_group); | ||||
|   clutter_actor_add_child (compositor->stage, compositor->feedback_group); | ||||
|  | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     { | ||||
| @@ -506,12 +558,7 @@ meta_compositor_manage (MetaCompositor *compositor) | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       Window xwin; | ||||
|  | ||||
|       compositor->output = screen->composite_overlay_window; | ||||
|  | ||||
|       xwin = meta_backend_x11_get_xwindow (META_BACKEND_X11 (meta_get_backend ())); | ||||
|  | ||||
|       compositor->output = get_output_window (compositor); | ||||
|       XReparentWindow (xdisplay, xwin, compositor->output, 0, 0); | ||||
|  | ||||
|       meta_empty_stage_input_region (screen); | ||||
| @@ -716,6 +763,9 @@ meta_compositor_process_event (MetaCompositor *compositor, | ||||
|                                XEvent         *event, | ||||
|                                MetaWindow     *window) | ||||
| { | ||||
|   if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event)) | ||||
|     return TRUE; | ||||
|  | ||||
|   if (!meta_is_wayland_compositor () && | ||||
|       event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify) | ||||
|     { | ||||
| @@ -935,7 +985,7 @@ meta_compositor_sync_stack (MetaCompositor  *compositor, | ||||
|           old_actor = old_stack->data; | ||||
|           old_window = meta_window_actor_get_meta_window (old_actor); | ||||
|  | ||||
|           if ((old_window->hidden || old_window->unmanaging) && | ||||
|           if (old_window->hidden && | ||||
|               !meta_window_actor_effect_in_progress (old_actor)) | ||||
|             { | ||||
|               old_stack = g_list_delete_link (old_stack, old_stack); | ||||
| @@ -969,7 +1019,7 @@ meta_compositor_sync_stack (MetaCompositor  *compositor, | ||||
|        * filtered out non-animating hidden windows above. | ||||
|        */ | ||||
|       if (old_actor && | ||||
|           (!stack_actor || old_window->hidden || old_window->unmanaging)) | ||||
|           (!stack_actor || old_window->hidden)) | ||||
|         { | ||||
|           actor = old_actor; | ||||
|           window = old_window; | ||||
| @@ -1003,6 +1053,43 @@ meta_compositor_sync_window_geometry (MetaCompositor *compositor, | ||||
|   meta_window_actor_sync_actor_geometry (window_actor, did_placement); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_compositor_sync_screen_size (MetaCompositor  *compositor, | ||||
| 				  guint		   width, | ||||
| 				  guint		   height) | ||||
| { | ||||
|   MetaDisplay *display = compositor->display; | ||||
|  | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     { | ||||
|       /* FIXME: when we support a sliced stage, this is the place to do it | ||||
|          But! This is not the place to apply KMS config, here we only | ||||
|          notify Clutter/Cogl/GL that the framebuffer sizes changed. | ||||
|  | ||||
|          And because for now clutter does not do sliced, we use one | ||||
|          framebuffer the size of the whole screen, and when running on | ||||
|          bare metal MetaMonitorManager will do the necessary tricks to | ||||
|          show the right portions on the right screens. | ||||
|       */ | ||||
|  | ||||
|       clutter_actor_set_size (compositor->stage, width, height); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       Display        *xdisplay; | ||||
|       Window          xwin; | ||||
|  | ||||
|       xdisplay = meta_display_get_xdisplay (display); | ||||
|       xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage)); | ||||
|  | ||||
|       XResizeWindow (xdisplay, xwin, width, height); | ||||
|     } | ||||
|  | ||||
|   meta_verbose ("Changed size for stage on screen %d to %dx%d\n", | ||||
|                 meta_screen_get_screen_number (display->screen), | ||||
|                 width, height); | ||||
| } | ||||
|  | ||||
| static void | ||||
| frame_callback (CoglOnscreen  *onscreen, | ||||
|                 CoglFrameEvent event, | ||||
| @@ -1073,33 +1160,6 @@ pre_paint_windows (MetaCompositor *compositor) | ||||
|  | ||||
|   for (l = compositor->windows; l; l = l->next) | ||||
|     meta_window_actor_pre_paint (l->data); | ||||
|  | ||||
|   if (compositor->frame_has_updated_xsurfaces) | ||||
|     { | ||||
|       /* We need to make sure that any X drawing that happens before | ||||
|        * the XDamageSubtract() for each window above is visible to | ||||
|        * subsequent GL rendering; the only standardized way to do this | ||||
|        * is EXT_x11_sync_object, which isn't yet widely available. For | ||||
|        * now, we count on details of Xorg and the open source drivers, | ||||
|        * and hope for the best otherwise. | ||||
|        * | ||||
|        * Xorg and open source driver specifics: | ||||
|        * | ||||
|        * The X server makes sure to flush drawing to the kernel before | ||||
|        * sending out damage events, but since we use | ||||
|        * DamageReportBoundingBox there may be drawing between the last | ||||
|        * damage event and the XDamageSubtract() that needs to be | ||||
|        * flushed as well. | ||||
|        * | ||||
|        * Xorg always makes sure that drawing is flushed to the kernel | ||||
|        * before writing events or responses to the client, so any | ||||
|        * round trip request at this point is sufficient to flush the | ||||
|        * GLX buffers. | ||||
|        */ | ||||
|       XSync (compositor->display->xdisplay, False); | ||||
|  | ||||
|       compositor->frame_has_updated_xsurfaces = FALSE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| @@ -1130,7 +1190,11 @@ meta_compositor_new (MetaDisplay *display) | ||||
| { | ||||
|   MetaCompositor        *compositor; | ||||
|  | ||||
|   if (!composite_at_least_version (display, 0, 3)) | ||||
|     return NULL; | ||||
|  | ||||
|   compositor = g_new0 (MetaCompositor, 1); | ||||
|  | ||||
|   compositor->display = display; | ||||
|  | ||||
|   if (g_getenv("META_DISABLE_MIPMAPS")) | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * Copyright 2009 Sander Dijkhuis | ||||
|  * Copyright 2014 Red Hat, Inc. | ||||
|  * Copyright 2010 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
| @@ -26,122 +26,23 @@ | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * The overall model drawing model of this widget is that we have one | ||||
|  * texture, or two interpolated textures, possibly with alpha or | ||||
|  * margins that let the underlying background show through, blended | ||||
|  * over a solid color or a gradient. The result of that combination | ||||
|  * can then be affected by a "vignette" that darkens the background | ||||
|  * away from a central point (or as a no-GLSL fallback, simply darkens | ||||
|  * the background) and by overall opacity. | ||||
|  * | ||||
|  * As of GNOME 3.14, GNOME is only using a fraction of this when the | ||||
|  * user sets the background through the control center - what can be | ||||
|  * set is: | ||||
|  * | ||||
|  *  A single image without a border | ||||
|  *  An animation of images without a border that blend together, | ||||
|  *   with the blend changing every 4-5 minutes | ||||
|  *  A solid color with a repeated noise texture blended over it | ||||
|  * | ||||
|  * This all is pretty easy to do in a fragment shader, except when: | ||||
|  * | ||||
|  *  A) We don't have GLSL - in this case, the operation of | ||||
|  *     interpolating the two textures and blending the result over the | ||||
|  *     background can't be expressed with Cogl's fixed-function layer | ||||
|  *     combining (which is confined to what GL's texture environment | ||||
|  *     combining can do) So we can only handle the above directly if | ||||
|  *     there are no margins or alpha. | ||||
|  * | ||||
|  *  B) The image textures are sliced. Texture size limits on older | ||||
|  *     hardware (pre-965 intel hardware, r300, etc.)  is often 2048, | ||||
|  *     and it would be common to use a texture larger than this for a | ||||
|  *     background and expect it to be scaled down. Cogl can compensate | ||||
|  *     for this by breaking the texture up into multiple textures, but | ||||
|  *     can't multitexture with sliced textures. So we can only handle | ||||
|  *     the above if there's a single texture. | ||||
|  * | ||||
|  * However, even when we *can* represent everything in a single pass, | ||||
|  * it's not necessarily efficient. If we want to draw a 1024x768 | ||||
|  * background, it's pretty inefficient to bilinearly texture from | ||||
|  * two 2560x1440 images and mix that. So the drawing model we take | ||||
|  * here is that MetaBackground generates a single texture (which | ||||
|  * might be a 1x1 texture for a solid color, or a 1x2 texture for a | ||||
|  * gradient, or a repeated texture for wallpaper, or a pre-rendered | ||||
|  * texture the size of the screen), and we draw with that, possibly | ||||
|  * adding the vignette and opacity. | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include <cogl/cogl-texture-pixmap-x11.h> | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include <X11/Xatom.h> | ||||
|  | ||||
| #include "cogl-utils.h" | ||||
| #include "clutter-utils.h" | ||||
| #include "compositor-private.h" | ||||
| #include <meta/errors.h> | ||||
| #include <meta/meta-background.h> | ||||
| #include "meta-background-actor-private.h" | ||||
| #include "meta-background-private.h" | ||||
| #include "meta-cullable.h" | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_META_SCREEN = 1, | ||||
|   PROP_MONITOR, | ||||
|   PROP_BACKGROUND, | ||||
|   PROP_VIGNETTE, | ||||
|   PROP_VIGNETTE_SHARPNESS, | ||||
|   PROP_BRIGHTNESS | ||||
| }; | ||||
|  | ||||
| typedef enum { | ||||
|   CHANGED_BACKGROUND = 1 << 0, | ||||
|   CHANGED_EFFECTS = 1 << 2, | ||||
|   CHANGED_VIGNETTE_PARAMETERS = 1 << 3, | ||||
|   CHANGED_ALL = 0xFFFF | ||||
| } ChangedFlags; | ||||
|  | ||||
| #define VERTEX_SHADER_DECLARATIONS                                      \ | ||||
| "uniform vec2 scale;\n"                                                 \ | ||||
| "uniform vec2 offset;\n"                                                \ | ||||
| "varying vec2 position;\n"                                              \ | ||||
|  | ||||
| #define VERTEX_SHADER_CODE                                              \ | ||||
| "position = cogl_tex_coord0_in.xy * scale + offset;\n"                  \ | ||||
|  | ||||
| #define FRAGMENT_SHADER_DECLARATIONS                                    \ | ||||
| "uniform float vignette_sharpness;\n"                                   \ | ||||
| "varying vec2 position;\n"                                              \ | ||||
|  | ||||
| #define FRAGMENT_SHADER_CODE                                                   \ | ||||
| "float t = 2.0 * length(position);\n"                                          \ | ||||
| "t = min(t, 1.0);\n"                                                           \ | ||||
| "float pixel_brightness = 1 - t * vignette_sharpness;\n"                       \ | ||||
| "cogl_color_out.rgb = cogl_color_out.rgb * pixel_brightness;\n"                \ | ||||
|  | ||||
| typedef struct _MetaBackgroundLayer MetaBackgroundLayer; | ||||
|  | ||||
| typedef enum { | ||||
|   PIPELINE_VIGNETTE = (1 << 0), | ||||
|   PIPELINE_BLEND = (1 << 1), | ||||
| } PipelineFlags; | ||||
|  | ||||
| struct _MetaBackgroundActorPrivate | ||||
| { | ||||
|   MetaScreen *screen; | ||||
|   int monitor; | ||||
|  | ||||
|   MetaBackground *background; | ||||
|  | ||||
|   gboolean vignette; | ||||
|   double brightness; | ||||
|   double vignette_sharpness; | ||||
|  | ||||
|   ChangedFlags changed; | ||||
|   CoglPipeline *pipeline; | ||||
|   PipelineFlags pipeline_flags; | ||||
|   cairo_rectangle_int_t texture_area; | ||||
|   gboolean force_bilinear; | ||||
|  | ||||
|   cairo_region_t *clip_region; | ||||
| }; | ||||
|  | ||||
| @@ -165,45 +66,27 @@ static void | ||||
| meta_background_actor_dispose (GObject *object) | ||||
| { | ||||
|   MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object); | ||||
|   MetaBackgroundActorPrivate *priv = self->priv; | ||||
|  | ||||
|   set_clip_region (self, NULL); | ||||
|   meta_background_actor_set_background (self, NULL); | ||||
|   if (priv->pipeline) | ||||
|     { | ||||
|       cogl_object_unref (priv->pipeline); | ||||
|       priv->pipeline = NULL; | ||||
|     } | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_background_actor_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| get_preferred_size (MetaBackgroundActor *self, | ||||
|                     gfloat              *width, | ||||
|                     gfloat              *height) | ||||
| { | ||||
|   MetaBackgroundActorPrivate *priv = META_BACKGROUND_ACTOR (self)->priv; | ||||
|   MetaRectangle monitor_geometry; | ||||
|  | ||||
|   meta_screen_get_monitor_geometry (priv->screen, priv->monitor, &monitor_geometry); | ||||
|  | ||||
|   if (width != NULL) | ||||
|     *width = monitor_geometry.width; | ||||
|  | ||||
|   if (height != NULL) | ||||
|     *height = monitor_geometry.height; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_background_actor_get_preferred_width (ClutterActor *actor, | ||||
|                                            gfloat        for_height, | ||||
|                                            gfloat       *min_width_p, | ||||
|                                            gfloat       *natural_width_p) | ||||
| { | ||||
|   ClutterContent *content; | ||||
|   gfloat width; | ||||
|  | ||||
|   get_preferred_size (META_BACKGROUND_ACTOR (actor), &width, NULL); | ||||
|   content = clutter_actor_get_content (actor); | ||||
|  | ||||
|   if (content) | ||||
|     clutter_content_get_preferred_size (content, &width, NULL); | ||||
|   else | ||||
|     width = 0; | ||||
|  | ||||
|   if (min_width_p) | ||||
|     *min_width_p = width; | ||||
| @@ -218,9 +101,15 @@ meta_background_actor_get_preferred_height (ClutterActor *actor, | ||||
|                                             gfloat       *natural_height_p) | ||||
|  | ||||
| { | ||||
|   ClutterContent *content; | ||||
|   gfloat height; | ||||
|  | ||||
|   get_preferred_size (META_BACKGROUND_ACTOR (actor), NULL, &height); | ||||
|   content = clutter_actor_get_content (actor); | ||||
|  | ||||
|   if (content) | ||||
|     clutter_content_get_preferred_size (content, NULL, &height); | ||||
|   else | ||||
|     height = 0; | ||||
|  | ||||
|   if (min_height_p) | ||||
|     *min_height_p = height; | ||||
| @@ -228,430 +117,43 @@ meta_background_actor_get_preferred_height (ClutterActor *actor, | ||||
|     *natural_height_p = height; | ||||
| } | ||||
|  | ||||
| static CoglPipeline * | ||||
| make_pipeline (PipelineFlags pipeline_flags) | ||||
| { | ||||
|   static CoglPipeline *templates[4]; | ||||
|   CoglPipeline **templatep; | ||||
|  | ||||
|   templatep = &templates[pipeline_flags]; | ||||
|   if (*templatep == NULL) | ||||
|     { | ||||
|       /* Cogl automatically caches pipelines with no eviction policy, | ||||
|        * so we need to prevent identical pipelines from getting cached | ||||
|        * separately, by reusing the same shader snippets. | ||||
|        */ | ||||
|       *templatep = COGL_PIPELINE (meta_create_texture_pipeline (NULL)); | ||||
|  | ||||
|       if ((pipeline_flags & PIPELINE_VIGNETTE) != 0) | ||||
|         { | ||||
|           static CoglSnippet *vertex_snippet; | ||||
|           static CoglSnippet *fragment_snippet; | ||||
|  | ||||
|           if (!vertex_snippet) | ||||
|             vertex_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX, | ||||
|                                                VERTEX_SHADER_DECLARATIONS, VERTEX_SHADER_CODE); | ||||
|  | ||||
|           cogl_pipeline_add_snippet (*templatep, vertex_snippet); | ||||
|  | ||||
|           if (!fragment_snippet) | ||||
|             fragment_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, | ||||
|                                                  FRAGMENT_SHADER_DECLARATIONS, FRAGMENT_SHADER_CODE); | ||||
|  | ||||
|           cogl_pipeline_add_snippet (*templatep, fragment_snippet); | ||||
|         } | ||||
|  | ||||
|       if ((pipeline_flags & PIPELINE_BLEND) == 0) | ||||
|         cogl_pipeline_set_blend (*templatep, "RGBA = ADD (SRC_COLOR, 0)", NULL); | ||||
|     } | ||||
|  | ||||
|   return cogl_pipeline_copy (*templatep); | ||||
| } | ||||
|  | ||||
| static void | ||||
| setup_pipeline (MetaBackgroundActor   *self, | ||||
|                 cairo_rectangle_int_t *actor_pixel_rect) | ||||
| { | ||||
|   MetaBackgroundActorPrivate *priv = self->priv; | ||||
|   PipelineFlags pipeline_flags = 0; | ||||
|   guint8 opacity; | ||||
|   float color_component; | ||||
|   CoglPipelineFilter filter; | ||||
|  | ||||
|   opacity = clutter_actor_get_paint_opacity (CLUTTER_ACTOR (self)); | ||||
|   if (opacity < 255) | ||||
|     pipeline_flags |= PIPELINE_BLEND; | ||||
|   if (priv->vignette && clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) | ||||
|     pipeline_flags |= PIPELINE_VIGNETTE; | ||||
|  | ||||
|   if (priv->pipeline && | ||||
|       pipeline_flags != priv->pipeline_flags) | ||||
|     { | ||||
|       cogl_object_unref (priv->pipeline); | ||||
|       priv->pipeline = NULL; | ||||
|     } | ||||
|  | ||||
|   if (priv->pipeline == NULL) | ||||
|     { | ||||
|       priv->pipeline_flags = pipeline_flags; | ||||
|       priv->pipeline = make_pipeline (pipeline_flags); | ||||
|       priv->changed = CHANGED_ALL; | ||||
|     } | ||||
|  | ||||
|   if ((priv->changed & CHANGED_BACKGROUND) != 0) | ||||
|     { | ||||
|       CoglPipelineWrapMode wrap_mode; | ||||
|       CoglTexture *texture = meta_background_get_texture (priv->background, | ||||
|                                                           priv->monitor, | ||||
|                                                           &priv->texture_area, | ||||
|                                                           &wrap_mode); | ||||
|       priv->force_bilinear = texture && | ||||
|         (priv->texture_area.width != (int)cogl_texture_get_width (texture) || | ||||
|          priv->texture_area.height != (int)cogl_texture_get_height (texture)); | ||||
|  | ||||
|       cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture); | ||||
|       cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0, wrap_mode); | ||||
|     } | ||||
|  | ||||
|   if ((priv->changed & CHANGED_VIGNETTE_PARAMETERS) != 0) | ||||
|     { | ||||
|       cogl_pipeline_set_uniform_1f (priv->pipeline, | ||||
|                                     cogl_pipeline_get_uniform_location (priv->pipeline, | ||||
|                                                                         "vignette_sharpness"), | ||||
|                                     priv->vignette_sharpness); | ||||
|     } | ||||
|  | ||||
|   if (priv->vignette) | ||||
|     { | ||||
|       color_component = priv->brightness * opacity / 255.; | ||||
|  | ||||
|       if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) | ||||
|         { | ||||
|           /* Darken everything to match the average brightness that would | ||||
|            * be there if we were drawing the vignette, which is | ||||
|            * (1 - (pi/12.) * vignette_sharpness) [exercise for the reader :] | ||||
|            */ | ||||
|           color_component *= (1 - 0.74 * priv->vignette_sharpness); | ||||
|         } | ||||
|     } | ||||
|   else | ||||
|     color_component = opacity / 255.; | ||||
|  | ||||
|   cogl_pipeline_set_color4f (priv->pipeline, | ||||
|                              color_component, | ||||
|                              color_component, | ||||
|                              color_component, | ||||
|                              opacity / 255.); | ||||
|  | ||||
|   if (!priv->force_bilinear && | ||||
|       meta_actor_painting_untransformed (actor_pixel_rect->width, actor_pixel_rect->height, NULL, NULL)) | ||||
|     filter = COGL_PIPELINE_FILTER_NEAREST; | ||||
|   else | ||||
|     filter = COGL_PIPELINE_FILTER_LINEAR; | ||||
|  | ||||
|   cogl_pipeline_set_layer_filters (priv->pipeline, 0, filter, filter); | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_glsl_parameters (MetaBackgroundActor   *self, | ||||
|                      cairo_rectangle_int_t *actor_pixel_rect) | ||||
| { | ||||
|   MetaBackgroundActorPrivate *priv = self->priv; | ||||
|   float scale[2]; | ||||
|   float offset[2]; | ||||
|  | ||||
|   /* Compute a scale and offset for transforming texture coordinates to the | ||||
|    * coordinate system from [-0.5 to 0.5] across the area of the actor | ||||
|    */ | ||||
|   scale[0] = priv->texture_area.width / (float)actor_pixel_rect->width; | ||||
|   scale[1] = priv->texture_area.height / (float)actor_pixel_rect->height; | ||||
|   offset[0] = priv->texture_area.x / (float)actor_pixel_rect->width - 0.5; | ||||
|   offset[1] = priv->texture_area.y / (float)actor_pixel_rect->height - 0.5; | ||||
|  | ||||
|   cogl_pipeline_set_uniform_float (priv->pipeline, | ||||
|                                    cogl_pipeline_get_uniform_location (priv->pipeline, | ||||
|                                                                        "scale"), | ||||
|                                    2, 1, scale); | ||||
|  | ||||
|   cogl_pipeline_set_uniform_float (priv->pipeline, | ||||
|                                    cogl_pipeline_get_uniform_location (priv->pipeline, | ||||
|                                                                        "offset"), | ||||
|                                    2, 1, offset); | ||||
| } | ||||
|  | ||||
| static void | ||||
| paint_clipped_rectangle (CoglFramebuffer       *fb, | ||||
|                          CoglPipeline          *pipeline, | ||||
|                          cairo_rectangle_int_t *rect, | ||||
|                          cairo_rectangle_int_t *texture_area) | ||||
| { | ||||
|   float x1, y1, x2, y2; | ||||
|   float tx1, ty1, tx2, ty2; | ||||
|  | ||||
|   x1 = rect->x; | ||||
|   y1 = rect->y; | ||||
|   x2 = rect->x + rect->width; | ||||
|   y2 = rect->y + rect->height; | ||||
|  | ||||
|   tx1 = (x1 - texture_area->x) / texture_area->width; | ||||
|   ty1 = (y1 - texture_area->y) / texture_area->height; | ||||
|   tx2 = (x2 - texture_area->x) / texture_area->width; | ||||
|   ty2 = (y2 - texture_area->y) / texture_area->height; | ||||
|  | ||||
|   cogl_framebuffer_draw_textured_rectangle (fb, pipeline, | ||||
|                                             x1, y1, x2, y2, | ||||
|                                             tx1, ty1, tx2, ty2); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_background_actor_get_paint_volume (ClutterActor       *actor, | ||||
|                                         ClutterPaintVolume *volume) | ||||
| { | ||||
|   return clutter_paint_volume_set_from_allocation (volume, actor); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_background_actor_paint (ClutterActor *actor) | ||||
| { | ||||
|   MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor); | ||||
|   MetaBackgroundActorPrivate *priv = self->priv; | ||||
|   ClutterActorBox actor_box; | ||||
|   cairo_rectangle_int_t actor_pixel_rect; | ||||
|   CoglFramebuffer *fb; | ||||
|   int i; | ||||
|  | ||||
|   if ((priv->clip_region && cairo_region_is_empty (priv->clip_region))) | ||||
|     return; | ||||
|  | ||||
|   clutter_actor_get_content_box (actor, &actor_box); | ||||
|   actor_pixel_rect.x = actor_box.x1; | ||||
|   actor_pixel_rect.y = actor_box.y1; | ||||
|   actor_pixel_rect.width = actor_box.x2 - actor_box.x1; | ||||
|   actor_pixel_rect.height = actor_box.y2 - actor_box.y1; | ||||
|  | ||||
|   setup_pipeline (self, &actor_pixel_rect); | ||||
|   set_glsl_parameters (self, &actor_pixel_rect); | ||||
|  | ||||
|   /* Limit to how many separate rectangles we'll draw; beyond this just | ||||
|    * fall back and draw the whole thing */ | ||||
| #define MAX_RECTS 64 | ||||
|  | ||||
|   fb = cogl_get_draw_framebuffer (); | ||||
|  | ||||
|   /* Now figure out what to actually paint. | ||||
|    */ | ||||
|   if (priv->clip_region != NULL) | ||||
|     { | ||||
|       int n_rects = cairo_region_num_rectangles (priv->clip_region); | ||||
|       if (n_rects <= MAX_RECTS) | ||||
|         { | ||||
|            for (i = 0; i < n_rects; i++) | ||||
|              { | ||||
|                cairo_rectangle_int_t rect; | ||||
|                cairo_region_get_rectangle (priv->clip_region, i, &rect); | ||||
|  | ||||
|                if (!gdk_rectangle_intersect (&actor_pixel_rect, &rect, &rect)) | ||||
|                  continue; | ||||
|  | ||||
|                paint_clipped_rectangle (fb, priv->pipeline, &rect, &priv->texture_area); | ||||
|              } | ||||
|  | ||||
|            return; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   paint_clipped_rectangle (fb, priv->pipeline, &actor_pixel_rect, &priv->texture_area); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_background_actor_set_property (GObject      *object, | ||||
|                                     guint         prop_id, | ||||
|                                     const GValue *value, | ||||
|                                     GParamSpec   *pspec) | ||||
| { | ||||
|   MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object); | ||||
|   MetaBackgroundActorPrivate *priv = self->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_META_SCREEN: | ||||
|       priv->screen = g_value_get_object (value); | ||||
|       break; | ||||
|     case PROP_MONITOR: | ||||
|       priv->monitor = g_value_get_int (value); | ||||
|       break; | ||||
|     case PROP_BACKGROUND: | ||||
|       meta_background_actor_set_background (self, g_value_get_object (value)); | ||||
|       break; | ||||
|     case PROP_VIGNETTE: | ||||
|       meta_background_actor_set_vignette (self, | ||||
|                                           g_value_get_boolean (value), | ||||
|                                           priv->brightness, | ||||
|                                           priv->vignette_sharpness); | ||||
|       break; | ||||
|     case PROP_VIGNETTE_SHARPNESS: | ||||
|       meta_background_actor_set_vignette (self, | ||||
|                                           priv->vignette, | ||||
|                                           priv->brightness, | ||||
|                                           g_value_get_double (value)); | ||||
|       break; | ||||
|     case PROP_BRIGHTNESS: | ||||
|       meta_background_actor_set_vignette (self, | ||||
|                                           priv->vignette, | ||||
|                                           g_value_get_double (value), | ||||
|                                           priv->vignette_sharpness); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_background_actor_get_property (GObject      *object, | ||||
|                                     guint         prop_id, | ||||
|                                     GValue       *value, | ||||
|                                     GParamSpec   *pspec) | ||||
| { | ||||
|   MetaBackgroundActorPrivate *priv = META_BACKGROUND_ACTOR (object)->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_META_SCREEN: | ||||
|       g_value_set_object (value, priv->screen); | ||||
|       break; | ||||
|     case PROP_MONITOR: | ||||
|       g_value_set_int (value, priv->monitor); | ||||
|       break; | ||||
|     case PROP_BACKGROUND: | ||||
|       g_value_set_object (value, priv->background); | ||||
|       break; | ||||
|     case PROP_VIGNETTE: | ||||
|       g_value_set_boolean (value, priv->vignette); | ||||
|       break; | ||||
|     case PROP_BRIGHTNESS: | ||||
|       g_value_set_double (value, priv->brightness); | ||||
|       break; | ||||
|     case PROP_VIGNETTE_SHARPNESS: | ||||
|       g_value_set_double (value, priv->vignette_sharpness); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_background_actor_class_init (MetaBackgroundActorClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   GParamSpec *param_spec; | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (MetaBackgroundActorPrivate)); | ||||
|  | ||||
|   object_class->dispose = meta_background_actor_dispose; | ||||
|   object_class->set_property = meta_background_actor_set_property; | ||||
|   object_class->get_property = meta_background_actor_get_property; | ||||
|  | ||||
|   actor_class->get_preferred_width = meta_background_actor_get_preferred_width; | ||||
|   actor_class->get_preferred_height = meta_background_actor_get_preferred_height; | ||||
|   actor_class->get_paint_volume = meta_background_actor_get_paint_volume; | ||||
|   actor_class->paint = meta_background_actor_paint; | ||||
|  | ||||
|   param_spec = g_param_spec_object ("meta-screen", | ||||
|                                     "MetaScreen", | ||||
|                                     "MetaScreen", | ||||
|                                     META_TYPE_SCREEN, | ||||
|                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); | ||||
|  | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_META_SCREEN, | ||||
|                                    param_spec); | ||||
|  | ||||
|   param_spec = g_param_spec_int ("monitor", | ||||
|                                  "monitor", | ||||
|                                  "monitor", | ||||
|                                  0, G_MAXINT, 0, | ||||
|                                  G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); | ||||
|  | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_MONITOR, | ||||
|                                    param_spec); | ||||
|  | ||||
|   param_spec = g_param_spec_object ("background", | ||||
|                                     "Background", | ||||
|                                     "MetaBackground object holding background parameters", | ||||
|                                     META_TYPE_BACKGROUND, | ||||
|                                     G_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_BACKGROUND, | ||||
|                                    param_spec); | ||||
|  | ||||
|   param_spec = g_param_spec_boolean ("vignette", | ||||
|                                      "Vignette", | ||||
|                                      "Whether vignette effect is enabled", | ||||
|                                      FALSE, | ||||
|                                      G_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_VIGNETTE, | ||||
|                                    param_spec); | ||||
|  | ||||
|   param_spec = g_param_spec_double ("brightness", | ||||
|                                     "Brightness", | ||||
|                                     "Brightness of vignette effect", | ||||
|                                     0.0, 1.0, 1.0, | ||||
|                                     G_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_BRIGHTNESS, | ||||
|                                    param_spec); | ||||
|  | ||||
|   param_spec = g_param_spec_double ("vignette-sharpness", | ||||
|                                     "Vignette Sharpness", | ||||
|                                     "Sharpness of vignette effect", | ||||
|                                     0.0, G_MAXDOUBLE, 0.0, | ||||
|                                     G_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_VIGNETTE_SHARPNESS, | ||||
|                                    param_spec); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_background_actor_init (MetaBackgroundActor *self) | ||||
| { | ||||
|   MetaBackgroundActorPrivate *priv; | ||||
|  | ||||
|   priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, | ||||
|                                                    META_TYPE_BACKGROUND_ACTOR, | ||||
|                                                    MetaBackgroundActorPrivate); | ||||
|  | ||||
|   priv->vignette = FALSE; | ||||
|   priv->brightness = 1.0; | ||||
|   priv->vignette_sharpness = 0.0; | ||||
|   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, | ||||
|                                             META_TYPE_BACKGROUND_ACTOR, | ||||
|                                             MetaBackgroundActorPrivate); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_background_actor_new: | ||||
|  * @monitor: Index of the monitor for which to draw the background | ||||
|  * | ||||
|  * Creates a new actor to draw the background for the given monitor. | ||||
|  * This actor should be associated with a #MetaBackground using | ||||
|  * clutter_actor_set_content() | ||||
|  * | ||||
|  * Return value: the newly created background actor | ||||
|  */ | ||||
| ClutterActor * | ||||
| meta_background_actor_new (MetaScreen *screen, | ||||
|                            int         monitor) | ||||
| meta_background_actor_new (void) | ||||
| { | ||||
|   MetaBackgroundActor *self; | ||||
|  | ||||
|   self = g_object_new (META_TYPE_BACKGROUND_ACTOR, | ||||
|                        "meta-screen", screen, | ||||
|                        "monitor", monitor, | ||||
|                        NULL); | ||||
|   self = g_object_new (META_TYPE_BACKGROUND_ACTOR, NULL); | ||||
|  | ||||
|   return CLUTTER_ACTOR (self); | ||||
| } | ||||
| @@ -683,7 +185,7 @@ cullable_iface_init (MetaCullableInterface *iface) | ||||
|  * meta_background_actor_get_clip_region: | ||||
|  * @self: a #MetaBackgroundActor | ||||
|  * | ||||
|  * Return value (transfer none): a #cairo_region_t that represents the part of | ||||
|  * Return value (transfer full): a #cairo_region_t that represents the part of | ||||
|  * the background not obscured by other #MetaBackgroundActor or | ||||
|  * #MetaWindowActor objects. | ||||
|  */ | ||||
| @@ -691,92 +193,24 @@ cairo_region_t * | ||||
| meta_background_actor_get_clip_region (MetaBackgroundActor *self) | ||||
| { | ||||
|   MetaBackgroundActorPrivate *priv = self->priv; | ||||
|   return priv->clip_region; | ||||
| } | ||||
|  | ||||
| static void | ||||
| invalidate_pipeline (MetaBackgroundActor *self, | ||||
|                      ChangedFlags         changed) | ||||
| { | ||||
|   MetaBackgroundActorPrivate *priv = self->priv; | ||||
|  | ||||
|   priv->changed |= changed; | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_background_changed (MetaBackground      *background, | ||||
|                        MetaBackgroundActor *self) | ||||
| { | ||||
|   invalidate_pipeline (self, CHANGED_BACKGROUND); | ||||
|   clutter_actor_queue_redraw (CLUTTER_ACTOR (self)); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_background_actor_set_background (MetaBackgroundActor *self, | ||||
|                                       MetaBackground      *background) | ||||
| { | ||||
|   MetaBackgroundActorPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (META_IS_BACKGROUND_ACTOR (self)); | ||||
|   g_return_if_fail (background == NULL || META_IS_BACKGROUND (background)); | ||||
|  | ||||
|   priv = self->priv; | ||||
|  | ||||
|   if (background == priv->background) | ||||
|     return; | ||||
|  | ||||
|   if (priv->background) | ||||
|     { | ||||
|       g_signal_handlers_disconnect_by_func (priv->background, | ||||
|                                             (gpointer)on_background_changed, | ||||
|                                             self); | ||||
|       g_object_unref (priv->background); | ||||
|       priv->background = NULL; | ||||
|     } | ||||
|  | ||||
|   if (background) | ||||
|     { | ||||
|       priv->background = g_object_ref (background); | ||||
|       g_signal_connect (priv->background, "changed", | ||||
|                         G_CALLBACK (on_background_changed), self); | ||||
|     } | ||||
|  | ||||
|   invalidate_pipeline (self, CHANGED_BACKGROUND); | ||||
|   clutter_actor_queue_redraw (CLUTTER_ACTOR (self)); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_background_actor_set_vignette (MetaBackgroundActor *self, | ||||
|                                     gboolean             enabled, | ||||
|                                     double               brightness, | ||||
|                                     double               sharpness) | ||||
| { | ||||
|   MetaBackgroundActorPrivate *priv; | ||||
|   gboolean changed = FALSE; | ||||
|  | ||||
|   g_return_if_fail (META_IS_BACKGROUND_ACTOR (self)); | ||||
|   g_return_if_fail (brightness >= 0. && brightness <= 1.); | ||||
|   g_return_if_fail (sharpness >= 0.); | ||||
|  | ||||
|   priv = self->priv; | ||||
|  | ||||
|   enabled = enabled != FALSE; | ||||
|  | ||||
|   if (enabled != priv->vignette) | ||||
|     { | ||||
|       priv->vignette = enabled; | ||||
|       invalidate_pipeline (self, CHANGED_EFFECTS); | ||||
|       changed = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (brightness != priv->brightness || sharpness != priv->vignette_sharpness) | ||||
|     { | ||||
|       priv->brightness = brightness; | ||||
|       priv->vignette_sharpness = sharpness; | ||||
|       invalidate_pipeline (self, CHANGED_VIGNETTE_PARAMETERS); | ||||
|       changed = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (changed) | ||||
|     clutter_actor_queue_redraw (CLUTTER_ACTOR (self)); | ||||
|   ClutterActorBox content_box; | ||||
|   cairo_rectangle_int_t content_area = { 0 }; | ||||
|   cairo_region_t *clip_region; | ||||
|  | ||||
|   g_return_val_if_fail (META_IS_BACKGROUND_ACTOR (self), NULL); | ||||
|  | ||||
|   if (!priv->clip_region) | ||||
|       return NULL; | ||||
|  | ||||
|   clutter_actor_get_content_box (CLUTTER_ACTOR (self), &content_box); | ||||
|  | ||||
|   content_area.x = content_box.x1; | ||||
|   content_area.y = content_box.y1; | ||||
|   content_area.width = content_box.x2 - content_box.x1; | ||||
|   content_area.height = content_box.y2 - content_box.y1; | ||||
|  | ||||
|   clip_region = cairo_region_create_rectangle (&content_area); | ||||
|   cairo_region_intersect (clip_region, priv->clip_region); | ||||
|  | ||||
|   return clip_region; | ||||
| } | ||||
|   | ||||
| @@ -1,347 +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/>. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:meta-background-image | ||||
|  * @title: MetaBackgroundImage | ||||
|  * @short_description: objects holding images loaded from files, used for backgrounds | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include <gio/gio.h> | ||||
| #include <gdk-pixbuf/gdk-pixbuf.h> | ||||
| #include <clutter/clutter.h> | ||||
| #include <meta/meta-background-image.h> | ||||
| #include "cogl-utils.h" | ||||
|  | ||||
| enum | ||||
| { | ||||
|   LOADED, | ||||
|   LAST_SIGNAL | ||||
| }; | ||||
|  | ||||
| static guint signals[LAST_SIGNAL] = { 0 }; | ||||
|  | ||||
| struct _MetaBackgroundImageCache | ||||
| { | ||||
|   GObject parent_instance; | ||||
|  | ||||
|   GHashTable *images; | ||||
| }; | ||||
|  | ||||
| struct _MetaBackgroundImageCacheClass | ||||
| { | ||||
|   GObjectClass parent_class; | ||||
| }; | ||||
|  | ||||
| struct _MetaBackgroundImage | ||||
| { | ||||
|   GObject parent_instance; | ||||
|   char *filename; | ||||
|   MetaBackgroundImageCache *cache; | ||||
|   gboolean in_cache; | ||||
|   gboolean loaded; | ||||
|   CoglTexture *texture; | ||||
| }; | ||||
|  | ||||
| struct _MetaBackgroundImageClass | ||||
| { | ||||
|   GObjectClass parent_class; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (MetaBackgroundImageCache, meta_background_image_cache, G_TYPE_OBJECT); | ||||
|  | ||||
| static void | ||||
| meta_background_image_cache_init (MetaBackgroundImageCache *cache) | ||||
| { | ||||
|   cache->images = g_hash_table_new (g_str_hash, g_str_equal); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_background_image_cache_finalize (GObject *object) | ||||
| { | ||||
|   MetaBackgroundImageCache *cache = META_BACKGROUND_IMAGE_CACHE (object); | ||||
|   GHashTableIter iter; | ||||
|   gpointer key, value; | ||||
|  | ||||
|   g_hash_table_iter_init (&iter, cache->images); | ||||
|   while (g_hash_table_iter_next (&iter, &key, &value)) | ||||
|     { | ||||
|       MetaBackgroundImage *image = value; | ||||
|       image->in_cache = FALSE; | ||||
|     } | ||||
|  | ||||
|   g_hash_table_destroy (cache->images); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_background_image_cache_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_background_image_cache_class_init (MetaBackgroundImageCacheClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   object_class->finalize = meta_background_image_cache_finalize; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_background_image_cache_get_default: | ||||
|  * | ||||
|  * Return value: (transfer none): the global singleton background cache | ||||
|  */ | ||||
| MetaBackgroundImageCache * | ||||
| meta_background_image_cache_get_default (void) | ||||
| { | ||||
|   static MetaBackgroundImageCache *cache; | ||||
|  | ||||
|   if (cache == NULL) | ||||
|     cache = g_object_new (META_TYPE_BACKGROUND_IMAGE_CACHE, NULL); | ||||
|  | ||||
|   return cache; | ||||
| } | ||||
|  | ||||
| static void | ||||
| load_file (GTask               *task, | ||||
|            MetaBackgroundImage *image, | ||||
|            gpointer             task_data, | ||||
|            GCancellable        *cancellable) | ||||
| { | ||||
|   GError *error = NULL; | ||||
|   GdkPixbuf *pixbuf; | ||||
|  | ||||
|   pixbuf = gdk_pixbuf_new_from_file (image->filename, | ||||
|                                      &error); | ||||
|  | ||||
|   if (pixbuf == NULL) | ||||
|     { | ||||
|       g_task_return_error (task, error); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   g_task_return_pointer (task, pixbuf, (GDestroyNotify) g_object_unref); | ||||
| } | ||||
|  | ||||
| static void | ||||
| file_loaded (GObject      *source_object, | ||||
|              GAsyncResult *result, | ||||
|              gpointer      user_data) | ||||
| { | ||||
|   MetaBackgroundImage *image = META_BACKGROUND_IMAGE (source_object); | ||||
|   GError *error = NULL; | ||||
|   GTask *task; | ||||
|   CoglTexture *texture; | ||||
|   GdkPixbuf *pixbuf; | ||||
|   int width, height, row_stride; | ||||
|   guchar *pixels; | ||||
|   gboolean has_alpha; | ||||
|  | ||||
|   task = G_TASK (result); | ||||
|   pixbuf = g_task_propagate_pointer (task, &error); | ||||
|  | ||||
|   if (pixbuf == NULL) | ||||
|     { | ||||
|       g_warning ("Failed to load background '%s': %s", | ||||
|                  image->filename, error->message); | ||||
|       g_clear_error (&error); | ||||
|       goto out; | ||||
|     } | ||||
|  | ||||
|   width = gdk_pixbuf_get_width (pixbuf); | ||||
|   height = gdk_pixbuf_get_height (pixbuf); | ||||
|   row_stride = gdk_pixbuf_get_rowstride (pixbuf); | ||||
|   pixels = gdk_pixbuf_get_pixels (pixbuf); | ||||
|   has_alpha = gdk_pixbuf_get_has_alpha (pixbuf); | ||||
|  | ||||
|   texture = meta_create_texture (width, height, | ||||
|                                  has_alpha ? COGL_TEXTURE_COMPONENTS_RGBA : COGL_TEXTURE_COMPONENTS_RGB, | ||||
|                                  META_TEXTURE_ALLOW_SLICING); | ||||
|  | ||||
|   if (!cogl_texture_set_data (texture, | ||||
|                               has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888, | ||||
|                               row_stride, | ||||
|                               pixels, 0, | ||||
|                               NULL)) | ||||
|     { | ||||
|       g_warning ("Failed to create texture for background"); | ||||
|       cogl_object_unref (texture); | ||||
|     } | ||||
|  | ||||
|   image->texture = texture; | ||||
|  | ||||
| out: | ||||
|   if (pixbuf != NULL) | ||||
|     g_object_unref (pixbuf); | ||||
|  | ||||
|   image->loaded = TRUE; | ||||
|   g_signal_emit (image, signals[LOADED], 0); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_background_image_cache_load: | ||||
|  * @cache: a #MetaBackgroundImageCache | ||||
|  * @filename: filename to load | ||||
|  * | ||||
|  * Loads an image to use as a background, or returns a reference to an | ||||
|  * image that is already in the process of loading or loaded. In either | ||||
|  * case, what is returned is a #MetaBackgroundImage which can be derefenced | ||||
|  * to get a #CoglTexture. If meta_background_image_is_loaded() returns %TRUE, | ||||
|  * the background is loaded, otherwise the MetaBackgroundImage::loaded | ||||
|  * signal will be emitted exactly once. The 'loaded' state means that the | ||||
|  * loading process finished, whether it succeeded or failed. | ||||
|  * | ||||
|  * Return value: (transfer full): a #MetaBackgroundImage to dereference to get the loaded texture | ||||
|  */ | ||||
| MetaBackgroundImage * | ||||
| meta_background_image_cache_load (MetaBackgroundImageCache *cache, | ||||
|                                   const char               *filename) | ||||
| { | ||||
|   MetaBackgroundImage *image; | ||||
|   GTask *task; | ||||
|  | ||||
|   g_return_val_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache), NULL); | ||||
|   g_return_val_if_fail (filename != NULL, NULL); | ||||
|  | ||||
|   image = g_hash_table_lookup (cache->images, filename); | ||||
|   if (image != NULL) | ||||
|     return g_object_ref (image); | ||||
|  | ||||
|   image = g_object_new (META_TYPE_BACKGROUND_IMAGE, NULL); | ||||
|   image->cache = cache; | ||||
|   image->in_cache = TRUE; | ||||
|   image->filename = g_strdup (filename); | ||||
|   g_hash_table_insert (cache->images, image->filename, image); | ||||
|  | ||||
|   task = g_task_new (image, NULL, file_loaded, NULL); | ||||
|  | ||||
|   g_task_run_in_thread (task, (GTaskThreadFunc) load_file); | ||||
|   g_object_unref (task); | ||||
|  | ||||
|   return image; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_background_image_cache_purge: | ||||
|  * @cache: a #MetaBackgroundImageCache | ||||
|  * @filename: filename to remove from the cache | ||||
|  * | ||||
|  * Remove an entry from the cache; this would be used if monitoring | ||||
|  * showed that the file changed. | ||||
|  */ | ||||
| void | ||||
| meta_background_image_cache_purge (MetaBackgroundImageCache *cache, | ||||
|                                    const char               *filename) | ||||
| { | ||||
|   MetaBackgroundImage *image; | ||||
|  | ||||
|   g_return_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache)); | ||||
|   g_return_if_fail (filename != NULL); | ||||
|  | ||||
|   image = g_hash_table_lookup (cache->images, filename); | ||||
|   if (image == NULL) | ||||
|     return; | ||||
|  | ||||
|   g_hash_table_remove (cache->images, image->filename); | ||||
|   image->in_cache = FALSE; | ||||
| } | ||||
|  | ||||
| G_DEFINE_TYPE (MetaBackgroundImage, meta_background_image, G_TYPE_OBJECT); | ||||
|  | ||||
| static void | ||||
| meta_background_image_init (MetaBackgroundImage *image) | ||||
| { | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_background_image_finalize (GObject *object) | ||||
| { | ||||
|   MetaBackgroundImage *image = META_BACKGROUND_IMAGE (object); | ||||
|  | ||||
|   if (image->in_cache) | ||||
|     g_hash_table_remove (image->cache->images, image->filename); | ||||
|  | ||||
|   if (image->texture) | ||||
|     cogl_object_unref (image->texture); | ||||
|   if (image->filename) | ||||
|     g_free (image->filename); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_background_image_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_background_image_class_init (MetaBackgroundImageClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   object_class->finalize = meta_background_image_finalize; | ||||
|  | ||||
|   signals[LOADED] = | ||||
|     g_signal_new ("loaded", | ||||
|                   G_TYPE_FROM_CLASS (object_class), | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   0, | ||||
|                   NULL, NULL, NULL, | ||||
|                   G_TYPE_NONE, 0); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_background_image_is_loaded: | ||||
|  * @image: a #MetaBackgroundImage | ||||
|  * | ||||
|  * Return value: %TRUE if loading has already completed, %FALSE otherwise | ||||
|  */ | ||||
| gboolean | ||||
| meta_background_image_is_loaded (MetaBackgroundImage *image) | ||||
| { | ||||
|   g_return_val_if_fail (META_IS_BACKGROUND_IMAGE (image), FALSE); | ||||
|  | ||||
|   return image->loaded; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_background_image_get_success: | ||||
|  * @image: a #MetaBackgroundImage | ||||
|  * | ||||
|  * This function is a convenience function for checking for success, | ||||
|  * without having to call meta_background_image_get_texture() and | ||||
|  * handle the return of a Cogl type. | ||||
|  * | ||||
|  * Return value: %TRUE if loading completed successfully, otherwise %FALSE | ||||
|  */ | ||||
| gboolean | ||||
| meta_background_image_get_success (MetaBackgroundImage *image) | ||||
| { | ||||
|   g_return_val_if_fail (META_IS_BACKGROUND_IMAGE (image), FALSE); | ||||
|  | ||||
|   return image->texture != NULL; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_background_image_get_texture: | ||||
|  * @image: a #MetaBackgroundImage | ||||
|  * | ||||
|  * Return value: (transfer none): a #CoglTexture if loading succeeded; if | ||||
|  *  loading failed or has not yet finished, %NULL. | ||||
|  */ | ||||
| CoglTexture * | ||||
| meta_background_image_get_texture (MetaBackgroundImage *image) | ||||
| { | ||||
|   g_return_val_if_fail (META_IS_BACKGROUND_IMAGE (image), NULL); | ||||
|  | ||||
|   return image->texture; | ||||
| } | ||||
| @@ -1,15 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| #ifndef META_BACKGROUND_PRIVATE_H | ||||
| #define META_BACKGROUND_PRIVATE_H | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include "meta-background-private.h" | ||||
|  | ||||
| CoglTexture *meta_background_get_texture (MetaBackground         *self, | ||||
|                                           int                     monitor_index, | ||||
|                                           cairo_rectangle_int_t  *texture_area, | ||||
|                                           CoglPipelineWrapMode   *wrap_mode); | ||||
|  | ||||
| #endif /* META_BACKGROUND_PRIVATE_H */ | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,64 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * meta-dnd-actor-private.h: Actor for painting the DnD surface | ||||
|  * | ||||
|  * 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_DND_ACTOR_PRIVATE_H | ||||
| #define META_DND_ACTOR_PRIVATE_H | ||||
|  | ||||
| #include "meta-feedback-actor-private.h" | ||||
|  | ||||
| /** | ||||
|  * MetaDnDActor: | ||||
|  * | ||||
|  * This class handles the rendering of the DnD surface | ||||
|  */ | ||||
|  | ||||
| #define META_TYPE_DND_ACTOR            (meta_dnd_actor_get_type ()) | ||||
| #define META_DND_ACTOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DND_ACTOR, MetaDnDActor)) | ||||
| #define META_DND_ACTOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DND_ACTOR, MetaDnDActorClass)) | ||||
| #define META_IS_DND_ACTOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DND_ACTOR)) | ||||
| #define META_IS_DND_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DND_ACTOR)) | ||||
| #define META_DND_ACTOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DND_ACTOR, MetaDnDActorClass)) | ||||
|  | ||||
| typedef struct _MetaDnDActor        MetaDnDActor; | ||||
| typedef struct _MetaDnDActorClass   MetaDnDActorClass; | ||||
|  | ||||
| struct _MetaDnDActorClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   MetaFeedbackActorClass parent_class; | ||||
| }; | ||||
|  | ||||
| struct _MetaDnDActor | ||||
| { | ||||
|   MetaFeedbackActor parent; | ||||
| }; | ||||
|  | ||||
| GType         meta_dnd_actor_get_type (void); | ||||
|  | ||||
| ClutterActor *meta_dnd_actor_new (ClutterActor *drag_origin, | ||||
|                                   int           start_x, | ||||
|                                   int           start_y); | ||||
|  | ||||
| void          meta_dnd_actor_drag_finish (MetaDnDActor *self, | ||||
|                                           gboolean      success); | ||||
|  | ||||
| #endif /* META_DND_ACTOR_PRIVATE_H */ | ||||
| @@ -1,231 +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:meta-dnd-actor | ||||
|  * @title: MetaDnDActor | ||||
|  * @short_description: Actor for painting the drag and drop surface | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include "meta-dnd-actor-private.h" | ||||
|  | ||||
| #define DRAG_FAILED_DURATION 500 | ||||
|  | ||||
| enum { | ||||
|   PROP_DRAG_ORIGIN = 1, | ||||
|   PROP_DRAG_START_X, | ||||
|   PROP_DRAG_START_Y | ||||
| }; | ||||
|  | ||||
| typedef struct _MetaDnDActorPrivate MetaDnDActorPrivate; | ||||
|  | ||||
| struct _MetaDnDActorPrivate | ||||
| { | ||||
|   ClutterActor *drag_origin; | ||||
|   int drag_start_x; | ||||
|   int drag_start_y; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaDnDActor, meta_dnd_actor, META_TYPE_FEEDBACK_ACTOR) | ||||
|  | ||||
| static void | ||||
| meta_dnd_actor_set_property (GObject      *object, | ||||
|                              guint         prop_id, | ||||
|                              const GValue *value, | ||||
|                              GParamSpec   *pspec) | ||||
| { | ||||
|   MetaDnDActor *self = META_DND_ACTOR (object); | ||||
|   MetaDnDActorPrivate *priv = meta_dnd_actor_get_instance_private (self); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_DRAG_ORIGIN: | ||||
|       priv->drag_origin = g_value_get_object (value); | ||||
|       break; | ||||
|     case PROP_DRAG_START_X: | ||||
|       priv->drag_start_x = g_value_get_int (value); | ||||
|       break; | ||||
|     case PROP_DRAG_START_Y: | ||||
|       priv->drag_start_y = g_value_get_int (value); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_dnd_actor_get_property (GObject      *object, | ||||
|                              guint         prop_id, | ||||
|                              GValue       *value, | ||||
|                              GParamSpec   *pspec) | ||||
| { | ||||
|   MetaDnDActor *self = META_DND_ACTOR (object); | ||||
|   MetaDnDActorPrivate *priv = meta_dnd_actor_get_instance_private (self); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_DRAG_ORIGIN: | ||||
|       g_value_set_object (value, priv->drag_origin); | ||||
|       break; | ||||
|     case PROP_DRAG_START_X: | ||||
|       g_value_set_int (value, priv->drag_start_x); | ||||
|       break; | ||||
|     case PROP_DRAG_START_Y: | ||||
|       g_value_set_int (value, priv->drag_start_y); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_dnd_actor_class_init (MetaDnDActorClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   object_class->set_property = meta_dnd_actor_set_property; | ||||
|   object_class->get_property = meta_dnd_actor_get_property; | ||||
|  | ||||
|   pspec = g_param_spec_object ("drag-origin", | ||||
|                                "Drag origin", | ||||
|                                "The origin of the DnD operation", | ||||
|                                CLUTTER_TYPE_ACTOR, | ||||
|                                G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); | ||||
|  | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_DRAG_ORIGIN, | ||||
|                                    pspec); | ||||
|  | ||||
|   pspec = g_param_spec_int ("drag-start-x", | ||||
|                             "Drag start X", | ||||
|                             "The X axis of the drag start point", | ||||
|                             0, G_MAXINT, 0, | ||||
|                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); | ||||
|  | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_DRAG_START_X, | ||||
|                                    pspec); | ||||
|  | ||||
|   pspec = g_param_spec_int ("drag-start-y", | ||||
|                             "Drag start Y", | ||||
|                             "The Y axis of the drag start point", | ||||
|                             0, G_MAXINT, 0, | ||||
|                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); | ||||
|  | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_DRAG_START_Y, | ||||
|                                    pspec); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_dnd_actor_init (MetaDnDActor *self) | ||||
| { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_dnd_actor_new: | ||||
|  * | ||||
|  * Creates a new actor to draw the current drag and drop surface. | ||||
|  * | ||||
|  * Return value: the newly created background actor | ||||
|  */ | ||||
| ClutterActor * | ||||
| meta_dnd_actor_new (ClutterActor *drag_origin, | ||||
|                     int           drag_start_x, | ||||
|                     int           drag_start_y) | ||||
| { | ||||
|   MetaDnDActor *self; | ||||
|  | ||||
|   self = g_object_new (META_TYPE_DND_ACTOR, | ||||
|                        "drag-origin", drag_origin, | ||||
|                        "drag-start-x", drag_start_x, | ||||
|                        "drag-start-y", drag_start_y, | ||||
|                        NULL); | ||||
|  | ||||
|   return CLUTTER_ACTOR (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| drag_failed_complete (ClutterTimeline *timeline, | ||||
|                       gboolean         is_finished, | ||||
|                       gpointer         user_data) | ||||
| { | ||||
|   ClutterActor *self = user_data; | ||||
|  | ||||
|   clutter_actor_remove_all_children (self); | ||||
|   clutter_actor_destroy (self); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_dnd_actor_drag_finish (MetaDnDActor *self, | ||||
|                             gboolean      success) | ||||
| { | ||||
|   MetaDnDActorPrivate *priv; | ||||
|   ClutterActor *actor; | ||||
|  | ||||
|   g_return_if_fail (META_IS_DND_ACTOR (self)); | ||||
|  | ||||
|   actor = CLUTTER_ACTOR (self); | ||||
|   priv = meta_dnd_actor_get_instance_private (self); | ||||
|  | ||||
|   if (success) | ||||
|     { | ||||
|       clutter_actor_remove_all_children (CLUTTER_ACTOR (self)); | ||||
|       clutter_actor_destroy (CLUTTER_ACTOR (self)); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       ClutterTransition *transition; | ||||
|  | ||||
|       clutter_actor_save_easing_state (actor); | ||||
|       clutter_actor_set_easing_mode (actor, CLUTTER_EASE_OUT_CUBIC); | ||||
|       clutter_actor_set_easing_duration (actor, DRAG_FAILED_DURATION); | ||||
|       clutter_actor_set_opacity (actor, 0); | ||||
|  | ||||
|       if (CLUTTER_ACTOR_IS_VISIBLE (priv->drag_origin)) | ||||
|         { | ||||
|           int anchor_x, anchor_y; | ||||
|           ClutterPoint dest; | ||||
|  | ||||
|           clutter_actor_get_transformed_position (priv->drag_origin, | ||||
|                                                   &dest.x, &dest.y); | ||||
|           meta_feedback_actor_get_anchor (META_FEEDBACK_ACTOR (self), | ||||
|                                           &anchor_x, &anchor_y); | ||||
|  | ||||
|           dest.x += priv->drag_start_x - anchor_x; | ||||
|           dest.y += priv->drag_start_y - anchor_y; | ||||
|           clutter_actor_set_position (actor, dest.x, dest.y); | ||||
|         } | ||||
|  | ||||
|       transition = clutter_actor_get_transition (actor, "opacity"); | ||||
|       g_signal_connect (transition, "stopped", | ||||
|                         G_CALLBACK (drag_failed_complete), self); | ||||
|  | ||||
|       clutter_actor_restore_easing_state (actor); | ||||
|     } | ||||
| } | ||||
| @@ -1,74 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * meta-feedback-actor-private.h: Actor for painting user interaction feedback | ||||
|  * | ||||
|  * 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_FEEDBACK_ACTOR_PRIVATE_H | ||||
| #define META_FEEDBACK_ACTOR_PRIVATE_H | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| /** | ||||
|  * MetaFeedbackActor: | ||||
|  * | ||||
|  * This class handles the rendering of user interaction feedback | ||||
|  */ | ||||
|  | ||||
| #define META_TYPE_FEEDBACK_ACTOR            (meta_feedback_actor_get_type ()) | ||||
| #define META_FEEDBACK_ACTOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_FEEDBACK_ACTOR, MetaFeedbackActor)) | ||||
| #define META_FEEDBACK_ACTOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_FEEDBACK_ACTOR, MetaFeedbackActorClass)) | ||||
| #define META_IS_FEEDBACK_ACTOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_FEEDBACK_ACTOR)) | ||||
| #define META_IS_FEEDBACK_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_FEEDBACK_ACTOR)) | ||||
| #define META_FEEDBACK_ACTOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_FEEDBACK_ACTOR, MetaFeedbackActorClass)) | ||||
|  | ||||
| typedef struct _MetaFeedbackActor        MetaFeedbackActor; | ||||
| typedef struct _MetaFeedbackActorClass   MetaFeedbackActorClass; | ||||
|  | ||||
| struct _MetaFeedbackActorClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActorClass parent_class; | ||||
| }; | ||||
|  | ||||
| struct _MetaFeedbackActor | ||||
| { | ||||
|   ClutterActor parent; | ||||
| }; | ||||
|  | ||||
| GType meta_feedback_actor_get_type (void); | ||||
|  | ||||
| ClutterActor *meta_feedback_actor_new (int anchor_x, | ||||
|                                        int anchor_y); | ||||
|  | ||||
| void meta_feedback_actor_set_anchor (MetaFeedbackActor *actor, | ||||
|                                      int                anchor_x, | ||||
|                                      int                anchor_y); | ||||
| void meta_feedback_actor_get_anchor (MetaFeedbackActor *actor, | ||||
|                                      int               *anchor_x, | ||||
|                                      int               *anchor_y); | ||||
|  | ||||
| void meta_feedback_actor_set_position (MetaFeedbackActor  *self, | ||||
|                                        int                 x, | ||||
|                                        int                 y); | ||||
|  | ||||
| void meta_feedback_actor_update (MetaFeedbackActor  *self, | ||||
|                                  const ClutterEvent *event); | ||||
|  | ||||
| #endif /* META_FEEDBACK_ACTOR_PRIVATE_H */ | ||||
| @@ -1,249 +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:meta-feedback-actor | ||||
|  * @title: MetaFeedbackActor | ||||
|  * @short_description: Actor for painting user interaction feedback | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include "display-private.h" | ||||
| #include "compositor-private.h" | ||||
| #include "meta-feedback-actor-private.h" | ||||
|  | ||||
| enum { | ||||
|   PROP_ANCHOR_X = 1, | ||||
|   PROP_ANCHOR_Y | ||||
| }; | ||||
|  | ||||
| typedef struct _MetaFeedbackActorPrivate MetaFeedbackActorPrivate; | ||||
|  | ||||
| struct _MetaFeedbackActorPrivate | ||||
| { | ||||
|   int anchor_x; | ||||
|   int anchor_y; | ||||
|   int pos_x; | ||||
|   int pos_y; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaFeedbackActor, meta_feedback_actor, CLUTTER_TYPE_ACTOR) | ||||
|  | ||||
| static void | ||||
| meta_feedback_actor_constructed (GObject *object) | ||||
| { | ||||
|   MetaDisplay *display; | ||||
|  | ||||
|   display = meta_get_display (); | ||||
|   clutter_actor_add_child (display->compositor->feedback_group, | ||||
|                            CLUTTER_ACTOR (object)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_feedback_actor_update_position (MetaFeedbackActor *self) | ||||
| { | ||||
|   MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self); | ||||
|  | ||||
|   clutter_actor_set_position (CLUTTER_ACTOR (self), | ||||
|                               priv->pos_x - priv->anchor_x, | ||||
|                               priv->pos_y - priv->anchor_y); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_feedback_actor_set_property (GObject      *object, | ||||
|                                   guint         prop_id, | ||||
|                                   const GValue *value, | ||||
|                                   GParamSpec   *pspec) | ||||
| { | ||||
|   MetaFeedbackActor *self = META_FEEDBACK_ACTOR (object); | ||||
|   MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_ANCHOR_X: | ||||
|       priv->anchor_x = g_value_get_int (value); | ||||
|       meta_feedback_actor_update_position (self); | ||||
|       break; | ||||
|     case PROP_ANCHOR_Y: | ||||
|       priv->anchor_y = g_value_get_int (value); | ||||
|       meta_feedback_actor_update_position (self); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_feedback_actor_get_property (GObject      *object, | ||||
|                                   guint         prop_id, | ||||
|                                   GValue       *value, | ||||
|                                   GParamSpec   *pspec) | ||||
| { | ||||
|   MetaFeedbackActor *self = META_FEEDBACK_ACTOR (object); | ||||
|   MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_ANCHOR_X: | ||||
|       g_value_set_int (value, priv->anchor_x); | ||||
|       break; | ||||
|     case PROP_ANCHOR_Y: | ||||
|       g_value_set_int (value, priv->anchor_y); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_feedback_actor_class_init (MetaFeedbackActorClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   object_class->constructed = meta_feedback_actor_constructed; | ||||
|   object_class->set_property = meta_feedback_actor_set_property; | ||||
|   object_class->get_property = meta_feedback_actor_get_property; | ||||
|  | ||||
|   pspec = g_param_spec_int ("anchor-x", | ||||
|                             "Anchor X", | ||||
|                             "The X axis of the anchor point", | ||||
|                             0, G_MAXINT, 0, | ||||
|                             G_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_ANCHOR_X, | ||||
|                                    pspec); | ||||
|  | ||||
|   pspec = g_param_spec_int ("anchor-y", | ||||
|                             "Anchor Y", | ||||
|                             "The Y axis of the anchor point", | ||||
|                             0, G_MAXINT, 0, | ||||
|                             G_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_ANCHOR_Y, | ||||
|                                    pspec); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_feedback_actor_init (MetaFeedbackActor *self) | ||||
| { | ||||
|   clutter_actor_set_reactive (CLUTTER_ACTOR (self), FALSE); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_feedback_actor_new: | ||||
|  * | ||||
|  * Creates a new actor to draw the current drag and drop surface. | ||||
|  * | ||||
|  * Return value: the newly created background actor | ||||
|  */ | ||||
| ClutterActor * | ||||
| meta_feedback_actor_new (int anchor_x, | ||||
|                          int anchor_y) | ||||
| { | ||||
|   MetaFeedbackActor *self; | ||||
|  | ||||
|   self = g_object_new (META_TYPE_FEEDBACK_ACTOR, | ||||
|                        "anchor-x", anchor_x, | ||||
|                        "anchor-y", anchor_y, | ||||
|                        NULL); | ||||
|  | ||||
|   return CLUTTER_ACTOR (self); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_feedback_actor_set_anchor (MetaFeedbackActor *self, | ||||
|                                 int                anchor_x, | ||||
|                                 int                anchor_y) | ||||
| { | ||||
|   MetaFeedbackActorPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (META_IS_FEEDBACK_ACTOR (self)); | ||||
|  | ||||
|   priv = meta_feedback_actor_get_instance_private (self); | ||||
|  | ||||
|   if (priv->anchor_x == anchor_x && priv->anchor_y == anchor_y) | ||||
|     return; | ||||
|  | ||||
|   if (priv->anchor_x != anchor_y) | ||||
|     { | ||||
|       priv->anchor_x = anchor_x; | ||||
|       g_object_notify (G_OBJECT (self), "anchor-x"); | ||||
|     } | ||||
|  | ||||
|   if (priv->anchor_y != anchor_y) | ||||
|     { | ||||
|       priv->anchor_y = anchor_y; | ||||
|       g_object_notify (G_OBJECT (self), "anchor-y"); | ||||
|     } | ||||
|  | ||||
|   meta_feedback_actor_update_position (self); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_feedback_actor_get_anchor (MetaFeedbackActor *self, | ||||
|                                 int               *anchor_x, | ||||
|                                 int               *anchor_y) | ||||
| { | ||||
|   MetaFeedbackActorPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (META_IS_FEEDBACK_ACTOR (self)); | ||||
|  | ||||
|   priv = meta_feedback_actor_get_instance_private (self); | ||||
|  | ||||
|   if (anchor_x) | ||||
|     *anchor_x = priv->anchor_x; | ||||
|   if (anchor_y) | ||||
|     *anchor_y = priv->anchor_y; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_feedback_actor_set_position (MetaFeedbackActor  *self, | ||||
|                                   int                 x, | ||||
|                                   int                 y) | ||||
| { | ||||
|   MetaFeedbackActorPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (META_IS_FEEDBACK_ACTOR (self)); | ||||
|  | ||||
|   priv = meta_feedback_actor_get_instance_private (self); | ||||
|   priv->pos_x = x; | ||||
|   priv->pos_y = y; | ||||
|  | ||||
|   meta_feedback_actor_update_position (self); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_feedback_actor_update (MetaFeedbackActor  *self, | ||||
|                             const ClutterEvent *event) | ||||
| { | ||||
|   ClutterPoint point; | ||||
|  | ||||
|   g_return_if_fail (META_IS_FEEDBACK_ACTOR (self)); | ||||
|   g_return_if_fail (event != NULL); | ||||
|  | ||||
|   clutter_event_get_position (event, &point); | ||||
|   meta_feedback_actor_set_position (self, point.x, point.y); | ||||
| } | ||||
| @@ -170,15 +170,6 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr, | ||||
|           klass->minimize (plugin, actor); | ||||
|         } | ||||
|       break; | ||||
|     case META_PLUGIN_UNMINIMIZE: | ||||
|       if (klass->unminimize) | ||||
|         { | ||||
|           retval = TRUE; | ||||
|           meta_plugin_manager_kill_window_effects (plugin_mgr, | ||||
|                                                    actor); | ||||
|           klass->unminimize (plugin, actor); | ||||
|         } | ||||
|       break; | ||||
|     case META_PLUGIN_MAP: | ||||
|       if (klass->map) | ||||
|         { | ||||
|   | ||||
| @@ -35,7 +35,6 @@ | ||||
| #define META_PLUGIN_MAP              (1<<3) | ||||
| #define META_PLUGIN_DESTROY          (1<<4) | ||||
| #define META_PLUGIN_SWITCH_WORKSPACE (1<<5) | ||||
| #define META_PLUGIN_UNMINIMIZE       (1<<6) | ||||
|  | ||||
| #define META_PLUGIN_ALL_EFFECTS      (~0) | ||||
|  | ||||
|   | ||||
| @@ -110,13 +110,6 @@ meta_plugin_minimize_completed (MetaPlugin      *plugin, | ||||
|   meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MINIMIZE); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_plugin_unminimize_completed (MetaPlugin      *plugin, | ||||
|                                   MetaWindowActor *actor) | ||||
| { | ||||
|   meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_UNMINIMIZE); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_plugin_maximize_completed (MetaPlugin      *plugin, | ||||
|                                 MetaWindowActor *actor) | ||||
|   | ||||
| @@ -541,7 +541,7 @@ blur_xspan (guchar *row, | ||||
|    * be well predicted and there are enough different possibilities | ||||
|    * that trying to write this as a series of unconditional loops | ||||
|    * is hard and not an obvious win. The main slow down here seems | ||||
|    * to be the integer division per pixel; one possible optimization | ||||
|    * to be the integer division for pixel; one possible optimization | ||||
|    * would be to accumulate into two 16-bit integer buffers and | ||||
|    * only divide down after all three passes. (SSE parallel implementation | ||||
|    * of the divide step is possible.) | ||||
| @@ -549,27 +549,27 @@ blur_xspan (guchar *row, | ||||
|   for (i = x0 - d + offset; i < x1 + offset; i++) | ||||
|     { | ||||
|       if (i >= 0 && i < row_width) | ||||
|         sum += row[i]; | ||||
| 	sum += row[i]; | ||||
|  | ||||
|       if (i >= x0 + offset) | ||||
|         { | ||||
|           if (i >= d) | ||||
|             sum -= row[i - d]; | ||||
| 	{ | ||||
| 	  if (i >= d) | ||||
| 	    sum -= row[i - d]; | ||||
|  | ||||
|           tmp_buffer[i - offset] = (sum + d / 2) / d; | ||||
|         } | ||||
| 	  tmp_buffer[i - offset] = (sum + d / 2) / d; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|   memcpy (row + x0, tmp_buffer + x0, x1 - x0); | ||||
|   memcpy(row + x0, tmp_buffer + x0, x1 - x0); | ||||
| } | ||||
|  | ||||
| static void | ||||
| blur_rows (cairo_region_t   *convolve_region, | ||||
|            int               x_offset, | ||||
|            int               y_offset, | ||||
|            guchar           *buffer, | ||||
|            int               buffer_width, | ||||
|            int               buffer_height, | ||||
| 	   guchar           *buffer, | ||||
| 	   int               buffer_width, | ||||
| 	   int               buffer_height, | ||||
|            int               d) | ||||
| { | ||||
|   int i, j; | ||||
| @@ -586,30 +586,30 @@ blur_rows (cairo_region_t   *convolve_region, | ||||
|       cairo_region_get_rectangle (convolve_region, i, &rect); | ||||
|  | ||||
|       for (j = y_offset + rect.y; j < y_offset + rect.y + rect.height; j++) | ||||
|         { | ||||
|           guchar *row = buffer + j * buffer_width; | ||||
|           int x0 = x_offset + rect.x; | ||||
|           int x1 = x0 + rect.width; | ||||
| 	{ | ||||
| 	  guchar *row = buffer + j * buffer_width; | ||||
| 	  int x0 = x_offset + rect.x; | ||||
| 	  int x1 = x0 + rect.width; | ||||
|  | ||||
|           /* We want to produce a symmetric blur that spreads a pixel | ||||
|            * equally far to the left and right. If d is odd that happens | ||||
|            * naturally, but for d even, we approximate by using a blur | ||||
|            * on either side and then a centered blur of size d + 1. | ||||
|            * (technique also from the SVG specification) | ||||
|            * (techique also from the SVG specification) | ||||
|            */ | ||||
|           if (d % 2 == 1) | ||||
|             { | ||||
|               blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0); | ||||
|               blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0); | ||||
|               blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0); | ||||
|             } | ||||
|           else | ||||
|             { | ||||
|               blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 1); | ||||
|               blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, -1); | ||||
|               blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d + 1, 0); | ||||
|             } | ||||
|         } | ||||
| 	  if (d % 2 == 1) | ||||
| 	    { | ||||
| 	      blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0); | ||||
| 	      blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0); | ||||
| 	      blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0); | ||||
| 	    } | ||||
| 	  else | ||||
| 	    { | ||||
| 	      blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 1); | ||||
| 	      blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, -1); | ||||
| 	      blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d + 1, 0); | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|   g_free (tmp_buffer); | ||||
| @@ -634,7 +634,7 @@ fade_bytes (guchar *bytes, | ||||
|  */ | ||||
| static guchar * | ||||
| flip_buffer (guchar *buffer, | ||||
|              int     width, | ||||
| 	     int     width, | ||||
|              int     height) | ||||
| { | ||||
|   /* Working in blocks increases cache efficiency, compared to reading | ||||
| @@ -646,33 +646,33 @@ flip_buffer (guchar *buffer, | ||||
|       int i0, j0; | ||||
|  | ||||
|       for (j0 = 0; j0 < height; j0 += BLOCK_SIZE) | ||||
|         for (i0 = 0; i0 <= j0; i0 += BLOCK_SIZE) | ||||
|           { | ||||
|             int max_j = MIN(j0 + BLOCK_SIZE, height); | ||||
|             int max_i = MIN(i0 + BLOCK_SIZE, width); | ||||
|             int i, j; | ||||
| 	for (i0 = 0; i0 <= j0; i0 += BLOCK_SIZE) | ||||
| 	  { | ||||
| 	    int max_j = MIN(j0 + BLOCK_SIZE, height); | ||||
| 	    int max_i = MIN(i0 + BLOCK_SIZE, width); | ||||
| 	    int i, j; | ||||
|  | ||||
|             if (i0 == j0) | ||||
|               { | ||||
|                 for (j = j0; j < max_j; j++) | ||||
|                   for (i = i0; i < j; i++) | ||||
|                     { | ||||
|                       guchar tmp = buffer[j * width + i]; | ||||
|                       buffer[j * width + i] = buffer[i * width + j]; | ||||
|                       buffer[i * width + j] = tmp; | ||||
|                     } | ||||
|               } | ||||
|             else | ||||
|               { | ||||
|                 for (j = j0; j < max_j; j++) | ||||
|                   for (i = i0; i < max_i; i++) | ||||
|                     { | ||||
|                       guchar tmp = buffer[j * width + i]; | ||||
|                       buffer[j * width + i] = buffer[i * width + j]; | ||||
|                       buffer[i * width + j] = tmp; | ||||
|                     } | ||||
|               } | ||||
|           } | ||||
| 	    if (i0 == j0) | ||||
| 	      { | ||||
| 		for (j = j0; j < max_j; j++) | ||||
| 		  for (i = i0; i < j; i++) | ||||
| 		    { | ||||
| 		      guchar tmp = buffer[j * width + i]; | ||||
| 		      buffer[j * width + i] = buffer[i * width + j]; | ||||
| 		      buffer[i * width + j] = tmp; | ||||
| 		    } | ||||
| 	      } | ||||
| 	    else | ||||
| 	      { | ||||
| 		for (j = j0; j < max_j; j++) | ||||
| 		  for (i = i0; i < max_i; i++) | ||||
| 		    { | ||||
| 		      guchar tmp = buffer[j * width + i]; | ||||
| 		      buffer[j * width + i] = buffer[i * width + j]; | ||||
| 		      buffer[i * width + j] = tmp; | ||||
| 		    } | ||||
| 	      } | ||||
| 	  } | ||||
|  | ||||
|       return buffer; | ||||
|     } | ||||
| @@ -683,15 +683,15 @@ flip_buffer (guchar *buffer, | ||||
|  | ||||
|       for (i0 = 0; i0 < width; i0 += BLOCK_SIZE) | ||||
|         for (j0 = 0; j0 < height; j0 += BLOCK_SIZE) | ||||
|           { | ||||
|             int max_j = MIN(j0 + BLOCK_SIZE, height); | ||||
|             int max_i = MIN(i0 + BLOCK_SIZE, width); | ||||
|             int i, j; | ||||
| 	  { | ||||
| 	    int max_j = MIN(j0 + BLOCK_SIZE, height); | ||||
| 	    int max_i = MIN(i0 + BLOCK_SIZE, width); | ||||
| 	    int i, j; | ||||
|  | ||||
|             for (i = i0; i < max_i; i++) | ||||
|               for (j = j0; j < max_j; j++) | ||||
|                 new_buffer[i * height + j] = buffer[j * width + i]; | ||||
|           } | ||||
| 		new_buffer[i * height + j] = buffer[j * width + i]; | ||||
| 	  } | ||||
|  | ||||
|       g_free (buffer); | ||||
|  | ||||
| @@ -704,8 +704,6 @@ static void | ||||
| make_shadow (MetaShadow     *shadow, | ||||
|              cairo_region_t *region) | ||||
| { | ||||
|   ClutterBackend *backend = clutter_get_default_backend (); | ||||
|   CoglContext *ctx = clutter_backend_get_cogl_context (backend); | ||||
|   int d = get_box_filter_size (shadow->key.radius); | ||||
|   int spread = get_shadow_spread (shadow->key.radius); | ||||
|   cairo_rectangle_int_t extents; | ||||
| @@ -765,7 +763,7 @@ make_shadow (MetaShadow     *shadow, | ||||
|  | ||||
|       cairo_region_get_rectangle (region, k, &rect); | ||||
|       for (j = y_offset + rect.y; j < y_offset + rect.y + rect.height; j++) | ||||
|         memset (buffer + buffer_width * j + x_offset + rect.x, 255, rect.width); | ||||
| 	memset (buffer + buffer_width * j + x_offset + rect.x, 255, rect.width); | ||||
|     } | ||||
|  | ||||
|   /* Step 2: swap rows and columns */ | ||||
| @@ -795,15 +793,15 @@ make_shadow (MetaShadow     *shadow, | ||||
|    * in the case of top_fade >= 0. We also account for padding at the left for symmetry | ||||
|    * though that doesn't currently occur. | ||||
|    */ | ||||
|   shadow->texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, | ||||
|                                                                  shadow->outer_border_left + extents.width + shadow->outer_border_right, | ||||
|                                                                  shadow->outer_border_top + extents.height + shadow->outer_border_bottom, | ||||
|                                                                  COGL_PIXEL_FORMAT_A_8, | ||||
|                                                                  buffer_width, | ||||
|                                                                  (buffer + | ||||
|                                                                   (y_offset - shadow->outer_border_top) * buffer_width + | ||||
|                                                                   (x_offset - shadow->outer_border_left)), | ||||
|                                                                  NULL)); | ||||
|   shadow->texture = cogl_texture_new_from_data (shadow->outer_border_left + extents.width + shadow->outer_border_right, | ||||
|                                                 shadow->outer_border_top + extents.height + shadow->outer_border_bottom, | ||||
|                                                 COGL_TEXTURE_NONE, | ||||
|                                                 COGL_PIXEL_FORMAT_A_8, | ||||
|                                                 COGL_PIXEL_FORMAT_ANY, | ||||
|                                                 buffer_width, | ||||
|                                                 (buffer + | ||||
|                                                  (y_offset - shadow->outer_border_top) * buffer_width + | ||||
|                                                  (x_offset - shadow->outer_border_left))); | ||||
|  | ||||
|   cairo_region_destroy (row_convolve_region); | ||||
|   cairo_region_destroy (column_convolve_region); | ||||
|   | ||||
| @@ -32,6 +32,8 @@ | ||||
| ClutterActor *meta_shaped_texture_new (void); | ||||
| void meta_shaped_texture_set_texture (MetaShapedTexture *stex, | ||||
|                                       CoglTexture       *texture); | ||||
| gboolean meta_shaped_texture_get_unobscured_bounds (MetaShapedTexture     *stex, | ||||
|                                                     cairo_rectangle_int_t *unobscured_bounds); | ||||
| gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -28,14 +28,16 @@ | ||||
| #include <config.h> | ||||
|  | ||||
| #include <meta/meta-shaped-texture.h> | ||||
| #include "meta-shaped-texture-private.h" | ||||
|  | ||||
| #include <cogl/cogl.h> | ||||
| #include <gdk/gdk.h> /* for gdk_rectangle_intersect() */ | ||||
|  | ||||
| #include <meta/util.h> | ||||
| #include "clutter-utils.h" | ||||
| #include "meta-texture-tower.h" | ||||
|  | ||||
| #include "meta-shaped-texture-private.h" | ||||
| #include "meta-window-actor-private.h" | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include <cogl/cogl.h> | ||||
| #include <gdk/gdk.h> /* for gdk_rectangle_intersect() */ | ||||
| #include "meta-cullable.h" | ||||
|  | ||||
| static void meta_shaped_texture_dispose  (GObject    *object); | ||||
| @@ -63,14 +65,6 @@ G_DEFINE_TYPE_WITH_CODE (MetaShapedTexture, meta_shaped_texture, CLUTTER_TYPE_AC | ||||
|   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_SHAPED_TEXTURE, \ | ||||
|                                 MetaShapedTexturePrivate)) | ||||
|  | ||||
| enum { | ||||
|   SIZE_CHANGED, | ||||
|  | ||||
|   LAST_SIGNAL, | ||||
| }; | ||||
|  | ||||
| static guint signals[LAST_SIGNAL]; | ||||
|  | ||||
| struct _MetaShapedTexturePrivate | ||||
| { | ||||
|   MetaTextureTower *paint_tower; | ||||
| @@ -103,13 +97,6 @@ meta_shaped_texture_class_init (MetaShapedTextureClass *klass) | ||||
|   actor_class->paint = meta_shaped_texture_paint; | ||||
|   actor_class->get_paint_volume = meta_shaped_texture_get_paint_volume; | ||||
|  | ||||
|   signals[SIZE_CHANGED] = g_signal_new ("size-changed", | ||||
|                                         G_TYPE_FROM_CLASS (gobject_class), | ||||
|                                         G_SIGNAL_RUN_LAST, | ||||
|                                         0, | ||||
|                                         NULL, NULL, NULL, | ||||
|                                         G_TYPE_NONE, 0); | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (MetaShapedTexturePrivate)); | ||||
| } | ||||
|  | ||||
| @@ -262,20 +249,22 @@ set_cogl_texture (MetaShapedTexture *stex, | ||||
|       cogl_object_ref (cogl_tex); | ||||
|       width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex)); | ||||
|       height = cogl_texture_get_height (COGL_TEXTURE (cogl_tex)); | ||||
|  | ||||
|       if (width != priv->tex_width || | ||||
|           height != priv->tex_height) | ||||
|         { | ||||
|           priv->tex_width = width; | ||||
|           priv->tex_height = height; | ||||
|  | ||||
|           clutter_actor_queue_relayout (CLUTTER_ACTOR (stex)); | ||||
|         } | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       width = 0; | ||||
|       height = 0; | ||||
|     } | ||||
|  | ||||
|   if (priv->tex_width != width || | ||||
|       priv->tex_height != height) | ||||
|     { | ||||
|       priv->tex_width = width; | ||||
|       priv->tex_height = height; | ||||
|       /* size changed to 0 going to an invalid handle */ | ||||
|       priv->tex_width = 0; | ||||
|       priv->tex_height = 0; | ||||
|       clutter_actor_queue_relayout (CLUTTER_ACTOR (stex)); | ||||
|       g_signal_emit (stex, signals[SIZE_CHANGED], 0); | ||||
|     } | ||||
|  | ||||
|   /* NB: We don't queue a redraw of the actor here because we don't | ||||
| @@ -296,8 +285,10 @@ meta_shaped_texture_paint (ClutterActor *actor) | ||||
|   guchar opacity; | ||||
|   CoglContext *ctx; | ||||
|   CoglFramebuffer *fb; | ||||
|   CoglPipeline *pipeline = NULL; | ||||
|   CoglTexture *paint_tex; | ||||
|   ClutterActorBox alloc; | ||||
|   cairo_region_t *blended_region = NULL; | ||||
|   CoglPipelineFilter filter; | ||||
|  | ||||
|   if (priv->clip_region && cairo_region_is_empty (priv->clip_region)) | ||||
| @@ -335,15 +326,13 @@ meta_shaped_texture_paint (ClutterActor *actor) | ||||
|   if (tex_width == 0 || tex_height == 0) /* no contents yet */ | ||||
|     return; | ||||
|  | ||||
|   cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height }; | ||||
|  | ||||
|   /* Use nearest-pixel interpolation if the texture is unscaled. This | ||||
|    * improves performance, especially with software rendering. | ||||
|    */ | ||||
|  | ||||
|   filter = COGL_PIPELINE_FILTER_LINEAR; | ||||
|  | ||||
|   if (meta_actor_painting_untransformed (tex_width, tex_height, NULL, NULL)) | ||||
|   if (!clutter_actor_is_in_clone_paint (actor) && meta_actor_is_untransformed (actor, NULL, NULL)) | ||||
|     filter = COGL_PIPELINE_FILTER_NEAREST; | ||||
|  | ||||
|   ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
| @@ -352,45 +341,7 @@ meta_shaped_texture_paint (ClutterActor *actor) | ||||
|   opacity = clutter_actor_get_paint_opacity (actor); | ||||
|   clutter_actor_get_allocation_box (actor, &alloc); | ||||
|  | ||||
|   cairo_region_t *blended_region; | ||||
|   gboolean use_opaque_region = (priv->opaque_region != NULL && opacity == 255); | ||||
|  | ||||
|   if (use_opaque_region) | ||||
|     { | ||||
|       if (priv->clip_region != NULL) | ||||
|         blended_region = cairo_region_copy (priv->clip_region); | ||||
|       else | ||||
|         blended_region = cairo_region_create_rectangle (&tex_rect); | ||||
|  | ||||
|       cairo_region_subtract (blended_region, priv->opaque_region); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (priv->clip_region != NULL) | ||||
|         blended_region = cairo_region_reference (priv->clip_region); | ||||
|       else | ||||
|         blended_region = NULL; | ||||
|     } | ||||
|  | ||||
|   /* Limit to how many separate rectangles we'll draw; beyond this just | ||||
|    * fall back and draw the whole thing */ | ||||
| #define MAX_RECTS 16 | ||||
|  | ||||
|   if (blended_region != NULL) | ||||
|     { | ||||
|       int n_rects = cairo_region_num_rectangles (blended_region); | ||||
|       if (n_rects > MAX_RECTS) | ||||
|         { | ||||
|           /* Fall back to taking the fully blended path. */ | ||||
|           use_opaque_region = FALSE; | ||||
|  | ||||
|           cairo_region_destroy (blended_region); | ||||
|           blended_region = NULL; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   /* First, paint the unblended parts, which are part of the opaque region. */ | ||||
|   if (use_opaque_region) | ||||
|   if (priv->opaque_region != NULL && opacity == 255) | ||||
|     { | ||||
|       CoglPipeline *opaque_pipeline; | ||||
|       cairo_region_t *region; | ||||
| @@ -407,87 +358,103 @@ meta_shaped_texture_paint (ClutterActor *actor) | ||||
|           region = cairo_region_reference (priv->opaque_region); | ||||
|         } | ||||
|  | ||||
|       if (!cairo_region_is_empty (region)) | ||||
|       if (cairo_region_is_empty (region)) | ||||
|         goto paint_blended; | ||||
|  | ||||
|       opaque_pipeline = get_unblended_pipeline (ctx); | ||||
|       cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex); | ||||
|       cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter); | ||||
|  | ||||
|       n_rects = cairo_region_num_rectangles (region); | ||||
|       for (i = 0; i < n_rects; i++) | ||||
|         { | ||||
|           opaque_pipeline = get_unblended_pipeline (ctx); | ||||
|           cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex); | ||||
|           cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter); | ||||
|  | ||||
|           n_rects = cairo_region_num_rectangles (region); | ||||
|           for (i = 0; i < n_rects; i++) | ||||
|             { | ||||
|               cairo_rectangle_int_t rect; | ||||
|               cairo_region_get_rectangle (region, i, &rect); | ||||
|               paint_clipped_rectangle (fb, opaque_pipeline, &rect, &alloc); | ||||
|             } | ||||
|  | ||||
|           cogl_object_unref (opaque_pipeline); | ||||
|           cairo_rectangle_int_t rect; | ||||
|           cairo_region_get_rectangle (region, i, &rect); | ||||
|           paint_clipped_rectangle (fb, opaque_pipeline, &rect, &alloc); | ||||
|         } | ||||
|  | ||||
|       cogl_object_unref (opaque_pipeline); | ||||
|  | ||||
|       if (priv->clip_region != NULL) | ||||
|         { | ||||
|           blended_region = cairo_region_copy (priv->clip_region); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           cairo_rectangle_int_t rect = { 0, 0, tex_width, tex_height }; | ||||
|           blended_region = cairo_region_create_rectangle (&rect); | ||||
|         } | ||||
|  | ||||
|       cairo_region_subtract (blended_region, priv->opaque_region); | ||||
|  | ||||
|     paint_blended: | ||||
|       cairo_region_destroy (region); | ||||
|     } | ||||
|  | ||||
|   /* Now, go ahead and paint the blended parts. */ | ||||
|   if (blended_region == NULL && priv->clip_region != NULL) | ||||
|     blended_region = cairo_region_reference (priv->clip_region); | ||||
|  | ||||
|   /* We have three cases: | ||||
|    *   1) blended_region has rectangles - paint the rectangles. | ||||
|    *   2) blended_region is empty - don't paint anything | ||||
|    *   3) blended_region is NULL - paint fully-blended. | ||||
|    * | ||||
|    *   1) and 3) are the times where we have to paint stuff. This tests | ||||
|    *   for 1) and 3). | ||||
|    */ | ||||
|   if (blended_region == NULL || !cairo_region_is_empty (blended_region)) | ||||
|   if (blended_region != NULL && cairo_region_is_empty (blended_region)) | ||||
|     goto out; | ||||
|  | ||||
|   if (priv->mask_texture == NULL) | ||||
|     { | ||||
|       CoglPipeline *blended_pipeline; | ||||
|  | ||||
|       if (priv->mask_texture == NULL) | ||||
|         { | ||||
|           blended_pipeline = get_unmasked_pipeline (ctx); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           blended_pipeline = get_masked_pipeline (ctx); | ||||
|           cogl_pipeline_set_layer_texture (blended_pipeline, 1, priv->mask_texture); | ||||
|           cogl_pipeline_set_layer_filters (blended_pipeline, 1, filter, filter); | ||||
|         } | ||||
|  | ||||
|       cogl_pipeline_set_layer_texture (blended_pipeline, 0, paint_tex); | ||||
|       cogl_pipeline_set_layer_filters (blended_pipeline, 0, filter, filter); | ||||
|  | ||||
|       CoglColor color; | ||||
|       cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity); | ||||
|       cogl_pipeline_set_color (blended_pipeline, &color); | ||||
|  | ||||
|       if (blended_region != NULL) | ||||
|         { | ||||
|           /* 1) blended_region is not empty. Paint the rectangles. */ | ||||
|           int i; | ||||
|           int n_rects = cairo_region_num_rectangles (blended_region); | ||||
|  | ||||
|           for (i = 0; i < n_rects; i++) | ||||
|             { | ||||
|               cairo_rectangle_int_t rect; | ||||
|               cairo_region_get_rectangle (blended_region, i, &rect); | ||||
|  | ||||
|               if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect)) | ||||
|                 continue; | ||||
|  | ||||
|               paint_clipped_rectangle (fb, blended_pipeline, &rect, &alloc); | ||||
|             } | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           /* 3) blended_region is NULL. Do a full paint. */ | ||||
|           cogl_framebuffer_draw_rectangle (fb, blended_pipeline, | ||||
|                                            0, 0, | ||||
|                                            alloc.x2 - alloc.x1, | ||||
|                                            alloc.y2 - alloc.y1); | ||||
|         } | ||||
|  | ||||
|       cogl_object_unref (blended_pipeline); | ||||
|       pipeline = get_unmasked_pipeline (ctx); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       pipeline = get_masked_pipeline (ctx); | ||||
|       cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture); | ||||
|       cogl_pipeline_set_layer_filters (pipeline, 1, filter, filter); | ||||
|     } | ||||
|  | ||||
|   cogl_pipeline_set_layer_texture (pipeline, 0, paint_tex); | ||||
|   cogl_pipeline_set_layer_filters (pipeline, 0, filter, filter); | ||||
|  | ||||
|   { | ||||
|     CoglColor color; | ||||
|     cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity); | ||||
|     cogl_pipeline_set_color (pipeline, &color); | ||||
|   } | ||||
|  | ||||
|   if (blended_region != NULL) | ||||
|     { | ||||
|       int n_rects; | ||||
|  | ||||
|       /* Limit to how many separate rectangles we'll draw; beyond this just | ||||
|        * fall back and draw the whole thing */ | ||||
| #     define MAX_RECTS 16 | ||||
|  | ||||
|       n_rects = cairo_region_num_rectangles (blended_region); | ||||
|       if (n_rects <= MAX_RECTS) | ||||
| 	{ | ||||
|           int i; | ||||
|           cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height }; | ||||
|  | ||||
| 	  for (i = 0; i < n_rects; i++) | ||||
| 	    { | ||||
| 	      cairo_rectangle_int_t rect; | ||||
|  | ||||
| 	      cairo_region_get_rectangle (blended_region, i, &rect); | ||||
|  | ||||
| 	      if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect)) | ||||
| 		continue; | ||||
|  | ||||
|               paint_clipped_rectangle (fb, pipeline, &rect, &alloc); | ||||
|             } | ||||
|  | ||||
|           goto out; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|   cogl_framebuffer_draw_rectangle (fb, pipeline, | ||||
|                                    0, 0, | ||||
|                                    alloc.x2 - alloc.x1, | ||||
|                                    alloc.y2 - alloc.y1); | ||||
|  | ||||
|  out: | ||||
|   if (pipeline != NULL) | ||||
|     cogl_object_unref (pipeline); | ||||
|   if (blended_region != NULL) | ||||
|     cairo_region_destroy (blended_region); | ||||
| } | ||||
| @@ -505,7 +472,7 @@ meta_shaped_texture_get_preferred_width (ClutterActor *self, | ||||
|   priv = META_SHAPED_TEXTURE (self)->priv; | ||||
|  | ||||
|   if (min_width_p) | ||||
|     *min_width_p = priv->tex_width; | ||||
|     *min_width_p = 0; | ||||
|  | ||||
|   if (natural_width_p) | ||||
|     *natural_width_p = priv->tex_width; | ||||
| @@ -524,70 +491,43 @@ meta_shaped_texture_get_preferred_height (ClutterActor *self, | ||||
|   priv = META_SHAPED_TEXTURE (self)->priv; | ||||
|  | ||||
|   if (min_height_p) | ||||
|     *min_height_p = priv->tex_height; | ||||
|     *min_height_p = 0; | ||||
|  | ||||
|   if (natural_height_p) | ||||
|     *natural_height_p = priv->tex_height; | ||||
| } | ||||
|  | ||||
| static cairo_region_t * | ||||
| effective_unobscured_region (MetaShapedTexture *self) | ||||
| { | ||||
|   MetaShapedTexturePrivate *priv = self->priv; | ||||
|   ClutterActor *actor; | ||||
|  | ||||
|   /* Fail if we have any mapped clones. */ | ||||
|   actor = CLUTTER_ACTOR (self); | ||||
|   do | ||||
|     { | ||||
|       if (clutter_actor_has_mapped_clones (actor)) | ||||
|         return NULL; | ||||
|       actor = clutter_actor_get_parent (actor); | ||||
|     } | ||||
|   while (actor != NULL); | ||||
|  | ||||
|   return priv->unobscured_region; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| get_unobscured_bounds (MetaShapedTexture     *self, | ||||
|                        cairo_rectangle_int_t *unobscured_bounds) | ||||
| { | ||||
|   cairo_region_t *unobscured_region = effective_unobscured_region (self); | ||||
|  | ||||
|   if (unobscured_region) | ||||
|     { | ||||
|       cairo_region_get_extents (unobscured_region, unobscured_bounds); | ||||
|       return TRUE; | ||||
|     } | ||||
|   else | ||||
|     return FALSE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_shaped_texture_get_paint_volume (ClutterActor *actor, | ||||
|                                       ClutterPaintVolume *volume) | ||||
| { | ||||
|   MetaShapedTexture *self = META_SHAPED_TEXTURE (actor); | ||||
|   ClutterActorBox box; | ||||
|   cairo_rectangle_int_t unobscured_bounds; | ||||
|  | ||||
|   if (!clutter_actor_has_allocation (actor)) | ||||
|   if (!clutter_paint_volume_set_from_allocation (volume, actor)) | ||||
|     return FALSE; | ||||
|  | ||||
|   clutter_actor_get_allocation_box (actor, &box); | ||||
|  | ||||
|   if (get_unobscured_bounds (self, &unobscured_bounds)) | ||||
|   if (meta_shaped_texture_get_unobscured_bounds (self, &unobscured_bounds)) | ||||
|     { | ||||
|       box.x1 = MAX (unobscured_bounds.x, box.x1); | ||||
|       box.x2 = MIN (unobscured_bounds.x + unobscured_bounds.width, box.x2); | ||||
|       box.y1 = MAX (unobscured_bounds.y, box.y1); | ||||
|       box.y2 = MIN (unobscured_bounds.y + unobscured_bounds.height, box.y2); | ||||
|     } | ||||
|   box.x2 = MAX (box.x2, box.x1); | ||||
|   box.y2 = MAX (box.y2, box.y1); | ||||
|       ClutterVertex origin; | ||||
|       cairo_rectangle_int_t bounds; | ||||
|  | ||||
|       /* I hate ClutterPaintVolume so much... */ | ||||
|       clutter_paint_volume_get_origin (volume, &origin); | ||||
|       bounds.x = origin.x; | ||||
|       bounds.y = origin.y; | ||||
|       bounds.width = clutter_paint_volume_get_width (volume); | ||||
|       bounds.height = clutter_paint_volume_get_height (volume); | ||||
|  | ||||
|       gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds); | ||||
|  | ||||
|       origin.x = bounds.x; | ||||
|       origin.y = bounds.y; | ||||
|       clutter_paint_volume_set_origin (volume, &origin); | ||||
|       clutter_paint_volume_set_width (volume, bounds.width); | ||||
|       clutter_paint_volume_set_height (volume, bounds.height); | ||||
|     } | ||||
|  | ||||
|   clutter_paint_volume_union_box (volume, &box); | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| @@ -633,6 +573,39 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex, | ||||
|   clutter_actor_queue_redraw (CLUTTER_ACTOR (stex)); | ||||
| } | ||||
|  | ||||
| static cairo_region_t * | ||||
| effective_unobscured_region (MetaShapedTexture *self) | ||||
| { | ||||
|   MetaShapedTexturePrivate *priv = self->priv; | ||||
|   ClutterActor *parent = clutter_actor_get_parent (CLUTTER_ACTOR (self)); | ||||
|  | ||||
|   if (clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self))) | ||||
|     return NULL; | ||||
|  | ||||
|   while (parent && !META_IS_WINDOW_ACTOR (parent)) | ||||
|     parent = clutter_actor_get_parent (parent); | ||||
|  | ||||
|   if (parent && clutter_actor_has_mapped_clones (parent)) | ||||
|     return NULL; | ||||
|  | ||||
|   return priv->unobscured_region; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_shaped_texture_get_unobscured_bounds (MetaShapedTexture     *self, | ||||
|                                            cairo_rectangle_int_t *unobscured_bounds) | ||||
| { | ||||
|   cairo_region_t *unobscured_region = effective_unobscured_region (self); | ||||
|  | ||||
|   if (unobscured_region) | ||||
|     { | ||||
|       cairo_region_get_extents (unobscured_region, unobscured_bounds); | ||||
|       return TRUE; | ||||
|     } | ||||
|   else | ||||
|     return FALSE; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_shaped_texture_is_obscured (MetaShapedTexture *self) | ||||
| { | ||||
|   | ||||
| @@ -25,85 +25,35 @@ | ||||
| #include "meta-stage.h" | ||||
| 
 | ||||
| #include "meta-cursor-private.h" | ||||
| #include <meta/meta-backend.h> | ||||
| #include "meta-backend.h" | ||||
| #include <meta/util.h> | ||||
| 
 | ||||
| typedef struct { | ||||
|   gboolean enabled; | ||||
| 
 | ||||
| struct _MetaStagePrivate { | ||||
|   CoglPipeline *pipeline; | ||||
|   CoglTexture *texture; | ||||
|   gboolean should_paint_cursor; | ||||
| 
 | ||||
|   MetaCursorReference *cursor; | ||||
| 
 | ||||
|   MetaRectangle current_rect; | ||||
|   MetaRectangle previous_rect; | ||||
|   gboolean previous_is_valid; | ||||
| } MetaOverlay; | ||||
| 
 | ||||
| struct _MetaStagePrivate { | ||||
|   MetaOverlay cursor_overlay; | ||||
| }; | ||||
| typedef struct _MetaStagePrivate MetaStagePrivate; | ||||
| 
 | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaStage, meta_stage, CLUTTER_TYPE_STAGE); | ||||
| 
 | ||||
| static void | ||||
| meta_overlay_init (MetaOverlay *overlay) | ||||
| update_pipeline (MetaStage *stage) | ||||
| { | ||||
|   CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
| 
 | ||||
|   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) | ||||
|   if (priv->cursor) | ||||
|     { | ||||
|       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; | ||||
|         } | ||||
|       CoglTexture *texture = meta_cursor_reference_get_cogl_texture (priv->cursor, NULL, NULL); | ||||
|       cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture); | ||||
|     } | ||||
| 
 | ||||
|   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; | ||||
|   else | ||||
|     cogl_pipeline_set_layer_texture (priv->pipeline, 0, NULL); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @@ -112,18 +62,42 @@ meta_stage_finalize (GObject *object) | ||||
|   MetaStage *stage = META_STAGE (object); | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
| 
 | ||||
|   meta_overlay_free (&priv->cursor_overlay); | ||||
|   if (priv->pipeline) | ||||
|     cogl_object_unref (priv->pipeline); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| paint_cursor (MetaStage *stage) | ||||
| { | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
| 
 | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
| 
 | ||||
|   if (!priv->cursor) | ||||
|     return; | ||||
| 
 | ||||
|   cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (), | ||||
|                                    priv->pipeline, | ||||
|                                    priv->current_rect.x, | ||||
|                                    priv->current_rect.y, | ||||
|                                    priv->current_rect.x + | ||||
|                                    priv->current_rect.width, | ||||
|                                    priv->current_rect.y + | ||||
|                                    priv->current_rect.height); | ||||
| 
 | ||||
|   priv->previous_rect = priv->current_rect; | ||||
|   priv->previous_is_valid = TRUE; | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     paint_cursor (stage); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @@ -140,9 +114,10 @@ meta_stage_class_init (MetaStageClass *klass) | ||||
| static void | ||||
| meta_stage_init (MetaStage *stage) | ||||
| { | ||||
|   CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
| 
 | ||||
|   meta_overlay_init (&priv->cursor_overlay); | ||||
|   priv->pipeline = cogl_pipeline_new (ctx); | ||||
| 
 | ||||
|   clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE); | ||||
| } | ||||
| @@ -156,42 +131,46 @@ meta_stage_new (void) | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| queue_redraw_for_overlay (MetaStage   *stage, | ||||
|                           MetaOverlay *overlay) | ||||
| queue_redraw (MetaStage *stage) | ||||
| { | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
|   cairo_rectangle_int_t clip; | ||||
| 
 | ||||
|   /* Clear the location the overlay was at before, if we need to. */ | ||||
|   if (overlay->previous_is_valid) | ||||
|   /* Clear the location the cursor was at before, if we need to. */ | ||||
|   if (priv->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; | ||||
|       clip.x = priv->previous_rect.x; | ||||
|       clip.y = priv->previous_rect.y; | ||||
|       clip.width = priv->previous_rect.width; | ||||
|       clip.height = priv->previous_rect.height; | ||||
|       clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip); | ||||
|       overlay->previous_is_valid = FALSE; | ||||
|       priv->previous_is_valid = FALSE; | ||||
|     } | ||||
| 
 | ||||
|   /* Draw the overlay at the new position */ | ||||
|   if (overlay->enabled) | ||||
|   /* And queue a redraw for the current cursor location. */ | ||||
|   if (priv->cursor) | ||||
|     { | ||||
|       clip.x = overlay->current_rect.x; | ||||
|       clip.y = overlay->current_rect.y; | ||||
|       clip.width = overlay->current_rect.width; | ||||
|       clip.height = overlay->current_rect.height; | ||||
|       clip.x = priv->current_rect.x; | ||||
|       clip.y = priv->current_rect.y; | ||||
|       clip.width = priv->current_rect.width; | ||||
|       clip.height = priv->current_rect.height; | ||||
|       clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void | ||||
| meta_stage_set_cursor (MetaStage     *stage, | ||||
|                        CoglTexture   *texture, | ||||
|                        MetaRectangle *rect) | ||||
| meta_stage_set_cursor (MetaStage           *stage, | ||||
|                        MetaCursorReference *cursor, | ||||
|                        MetaRectangle       *rect) | ||||
| { | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
| 
 | ||||
|   g_assert (meta_is_wayland_compositor () || texture == NULL); | ||||
|   if (priv->cursor != cursor) | ||||
|     { | ||||
|       priv->cursor = cursor; | ||||
|       update_pipeline (stage); | ||||
|     } | ||||
| 
 | ||||
|   meta_overlay_set (&priv->cursor_overlay, texture, rect); | ||||
|   queue_redraw_for_overlay (stage, &priv->cursor_overlay); | ||||
|   priv->current_rect = *rect; | ||||
|   queue_redraw (stage); | ||||
| } | ||||
| @@ -51,9 +51,9 @@ GType             meta_stage_get_type                (void) G_GNUC_CONST; | ||||
| 
 | ||||
| ClutterActor     *meta_stage_new                     (void); | ||||
| 
 | ||||
| void meta_stage_set_cursor (MetaStage     *stage, | ||||
|                             CoglTexture   *texture, | ||||
|                             MetaRectangle *rect); | ||||
| void meta_stage_set_cursor (MetaStage           *stage, | ||||
|                             MetaCursorReference *cursor, | ||||
|                             MetaRectangle       *rect); | ||||
| G_END_DECLS | ||||
| 
 | ||||
| #endif /* META_STAGE_H */ | ||||
| @@ -34,15 +34,45 @@ | ||||
| struct _MetaSurfaceActorWaylandPrivate | ||||
| { | ||||
|   MetaWaylandSurface *surface; | ||||
|   MetaWaylandBuffer *buffer; | ||||
|   struct wl_listener buffer_destroy_listener; | ||||
| }; | ||||
| typedef struct _MetaSurfaceActorWaylandPrivate MetaSurfaceActorWaylandPrivate; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorWayland, meta_surface_actor_wayland, META_TYPE_SURFACE_ACTOR) | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_handle_buffer_destroy (struct wl_listener *listener, void *data) | ||||
| { | ||||
|   MetaSurfaceActorWaylandPrivate *priv = wl_container_of (listener, priv, buffer_destroy_listener); | ||||
|  | ||||
|   /* If the buffer is destroyed while we're attached to it, | ||||
|    * we want to unset priv->buffer so we don't access freed | ||||
|    * memory. Keep the texture set however so the user doesn't | ||||
|    * see the window disappear. */ | ||||
|   priv->buffer = NULL; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor, | ||||
|                                            int x, int y, int width, int height) | ||||
| { | ||||
|   MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor); | ||||
|   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); | ||||
|  | ||||
|   if (priv->buffer) | ||||
|     { | ||||
|       struct wl_resource *resource = priv->buffer->resource; | ||||
|       struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource); | ||||
|  | ||||
|       if (shm_buffer) | ||||
|         { | ||||
|           CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture); | ||||
|           cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y, 0, NULL); | ||||
|         } | ||||
|  | ||||
|       meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -79,7 +109,7 @@ meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor) | ||||
| } | ||||
|  | ||||
| static int | ||||
| get_output_scale (int winsys_id) | ||||
| get_output_scale (int output_id) | ||||
| { | ||||
|   MetaMonitorManager *monitor_manager = meta_monitor_manager_get (); | ||||
|   MetaOutput *outputs; | ||||
| @@ -90,7 +120,7 @@ get_output_scale (int winsys_id) | ||||
|  | ||||
|   for (i = 0; i < n_outputs; i++) | ||||
|     { | ||||
|       if (outputs[i].winsys_id == winsys_id) | ||||
|       if (outputs[i].output_id == output_id) | ||||
|         { | ||||
|           output_scale = outputs[i].scale; | ||||
|           break; | ||||
| @@ -120,7 +150,7 @@ meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor) | ||||
|  | ||||
|    /* XXX: We do not handle x11 clients yet */ | ||||
|    if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11) | ||||
|      output_scale = get_output_scale (window->monitor->winsys_id); | ||||
|      output_scale = get_output_scale (window->monitor->output_id); | ||||
|  | ||||
|    return (double)output_scale / (double)priv->surface->scale; | ||||
| } | ||||
| @@ -183,7 +213,7 @@ meta_surface_actor_wayland_dispose (GObject *object) | ||||
| { | ||||
|   MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (object); | ||||
|  | ||||
|   meta_surface_actor_wayland_set_texture (self, NULL); | ||||
|   meta_surface_actor_wayland_set_buffer (self, NULL); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_surface_actor_wayland_parent_class)->dispose (object); | ||||
| } | ||||
| @@ -214,6 +244,9 @@ meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass) | ||||
| static void | ||||
| meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self) | ||||
| { | ||||
|   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); | ||||
|  | ||||
|   priv->buffer_destroy_listener.notify = meta_surface_actor_handle_buffer_destroy; | ||||
| } | ||||
|  | ||||
| MetaSurfaceActor * | ||||
| @@ -230,11 +263,24 @@ meta_surface_actor_wayland_new (MetaWaylandSurface *surface) | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_wayland_set_texture (MetaSurfaceActorWayland *self, | ||||
|                                         CoglTexture *texture) | ||||
| meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self, | ||||
|                                        MetaWaylandBuffer       *buffer) | ||||
| { | ||||
|   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); | ||||
|   MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); | ||||
|   meta_shaped_texture_set_texture (stex, texture); | ||||
|  | ||||
|   if (priv->buffer) | ||||
|     wl_list_remove (&priv->buffer_destroy_listener.link); | ||||
|  | ||||
|   priv->buffer = buffer; | ||||
|  | ||||
|   if (priv->buffer) | ||||
|     { | ||||
|       wl_signal_add (&priv->buffer->destroy_signal, &priv->buffer_destroy_listener); | ||||
|       meta_shaped_texture_set_texture (stex, priv->buffer->texture); | ||||
|     } | ||||
|   else | ||||
|     meta_shaped_texture_set_texture (stex, NULL); | ||||
| } | ||||
|  | ||||
| MetaWaylandSurface * | ||||
|   | ||||
| @@ -58,8 +58,8 @@ GType meta_surface_actor_wayland_get_type (void); | ||||
| MetaSurfaceActor * meta_surface_actor_wayland_new (MetaWaylandSurface *surface); | ||||
| MetaWaylandSurface * meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self); | ||||
|  | ||||
| void meta_surface_actor_wayland_set_texture (MetaSurfaceActorWayland *self, | ||||
|                                              CoglTexture *texture); | ||||
| void meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self, | ||||
|                                             MetaWaylandBuffer         *buffer); | ||||
|  | ||||
| double meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor); | ||||
|  | ||||
|   | ||||
| @@ -179,6 +179,19 @@ is_visible (MetaSurfaceActorX11 *self) | ||||
|   return (priv->pixmap != None) && !priv->unredirected; | ||||
| } | ||||
|  | ||||
| static void | ||||
| damage_area (MetaSurfaceActorX11 *self, | ||||
|              int x, int y, int width, int height) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   if (!is_visible (self)) | ||||
|     return; | ||||
|  | ||||
|   cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height); | ||||
|   meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor, | ||||
|                                        int x, int y, int width, int height) | ||||
| @@ -193,8 +206,8 @@ meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor, | ||||
|       MetaRectangle window_rect; | ||||
|       meta_window_get_frame_rect (priv->window, &window_rect); | ||||
|  | ||||
|       if (x == 0 && | ||||
|           y == 0 && | ||||
|       if (window_rect.x == x && | ||||
|           window_rect.y == y && | ||||
|           window_rect.width == width && | ||||
|           window_rect.height == height) | ||||
|         priv->full_damage_frames_count++; | ||||
| @@ -205,10 +218,11 @@ meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor, | ||||
|         priv->does_full_damage = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (!is_visible (self)) | ||||
|   /* Drop damage event for unredirected windows */ | ||||
|   if (priv->unredirected) | ||||
|     return; | ||||
|  | ||||
|   cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height); | ||||
|   damage_area (self, x, y, width, height); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -225,6 +239,26 @@ meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor) | ||||
|       XDamageSubtract (xdisplay, priv->damage, None, None); | ||||
|       meta_error_trap_pop (display); | ||||
|  | ||||
|       /* We need to make sure that any X drawing that happens before the | ||||
|        * XDamageSubtract() above is visible to subsequent GL rendering; | ||||
|        * the only standardized way to do this is EXT_x11_sync_object, | ||||
|        * which isn't yet widely available. For now, we count on details | ||||
|        * of Xorg and the open source drivers, and hope for the best | ||||
|        * otherwise. | ||||
|        * | ||||
|        * Xorg and open source driver specifics: | ||||
|        * | ||||
|        * The X server makes sure to flush drawing to the kernel before | ||||
|        * sending out damage events, but since we use DamageReportBoundingBox | ||||
|        * there may be drawing between the last damage event and the | ||||
|        * XDamageSubtract() that needs to be flushed as well. | ||||
|        * | ||||
|        * Xorg always makes sure that drawing is flushed to the kernel | ||||
|        * before writing events or responses to the client, so any round trip | ||||
|        * request at this point is sufficient to flush the GLX buffers. | ||||
|        */ | ||||
|       XSync (xdisplay, False); | ||||
|  | ||||
|       priv->received_damage = FALSE; | ||||
|     } | ||||
|  | ||||
| @@ -383,7 +417,6 @@ window_decorated_notify (MetaWindow *window, | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (user_data); | ||||
|  | ||||
|   detach_pixmap (self); | ||||
|   free_damage (self); | ||||
|   create_damage (self); | ||||
| } | ||||
|   | ||||
| @@ -36,13 +36,20 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_ | ||||
|  | ||||
| enum { | ||||
|   REPAINT_SCHEDULED, | ||||
|   SIZE_CHANGED, | ||||
|  | ||||
|   LAST_SIGNAL, | ||||
| }; | ||||
|  | ||||
| static guint signals[LAST_SIGNAL]; | ||||
|  | ||||
| gboolean | ||||
| meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor      *self, | ||||
|                                           cairo_rectangle_int_t *unobscured_bounds) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|   return meta_shaped_texture_get_unobscured_bounds (priv->texture, unobscured_bounds); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_pick (ClutterActor       *actor, | ||||
|                          const ClutterColor *color) | ||||
| @@ -121,13 +128,6 @@ meta_surface_actor_class_init (MetaSurfaceActorClass *klass) | ||||
|                                              NULL, NULL, NULL, | ||||
|                                              G_TYPE_NONE, 0); | ||||
|  | ||||
|   signals[SIZE_CHANGED] = g_signal_new ("size-changed", | ||||
|                                         G_TYPE_FROM_CLASS (object_class), | ||||
|                                         G_SIGNAL_RUN_LAST, | ||||
|                                         0, | ||||
|                                         NULL, NULL, NULL, | ||||
|                                         G_TYPE_NONE, 0); | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (MetaSurfaceActorPrivate)); | ||||
| } | ||||
|  | ||||
| @@ -152,14 +152,6 @@ cullable_iface_init (MetaCullableInterface *iface) | ||||
|   iface->reset_culling = meta_surface_actor_reset_culling; | ||||
| } | ||||
|  | ||||
| static void | ||||
| texture_size_changed (MetaShapedTexture *texture, | ||||
|                       gpointer           user_data) | ||||
| { | ||||
|   MetaSurfaceActor *actor = META_SURFACE_ACTOR (user_data); | ||||
|   g_signal_emit (actor, signals[SIZE_CHANGED], 0); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_init (MetaSurfaceActor *self) | ||||
| { | ||||
| @@ -170,8 +162,6 @@ meta_surface_actor_init (MetaSurfaceActor *self) | ||||
|                                                    MetaSurfaceActorPrivate); | ||||
|  | ||||
|   priv->texture = META_SHAPED_TEXTURE (meta_shaped_texture_new ()); | ||||
|   g_signal_connect_object (priv->texture, "size-changed", | ||||
|                            G_CALLBACK (texture_size_changed), self, 0); | ||||
|   clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->texture)); | ||||
| } | ||||
|  | ||||
| @@ -188,7 +178,7 @@ meta_surface_actor_get_texture (MetaSurfaceActor *self) | ||||
|   return self->priv->texture; | ||||
| } | ||||
|  | ||||
| static void | ||||
| void | ||||
| meta_surface_actor_update_area (MetaSurfaceActor *self, | ||||
|                                 int x, int y, int width, int height) | ||||
| { | ||||
| @@ -262,9 +252,6 @@ meta_surface_actor_process_damage (MetaSurfaceActor *self, | ||||
|     } | ||||
|  | ||||
|   META_SURFACE_ACTOR_GET_CLASS (self)->process_damage (self, x, y, width, height); | ||||
|  | ||||
|   if (meta_surface_actor_is_visible (self)) | ||||
|     meta_surface_actor_update_area (self, x, y, width, height); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -280,15 +267,9 @@ meta_surface_actor_is_argb32 (MetaSurfaceActor *self) | ||||
|   CoglTexture *texture = meta_shaped_texture_get_texture (stex); | ||||
|  | ||||
|   /* If we don't have a texture, like during initialization, assume | ||||
|    * that we're ARGB32. | ||||
|    * | ||||
|    * If we are unredirected and we have no texture assume that we are | ||||
|    * not ARGB32 otherwise we wouldn't be unredirected in the first | ||||
|    * place. This prevents us from continually redirecting and | ||||
|    * unredirecting on every paint. | ||||
|    */ | ||||
|    * that we're ARGB32. */ | ||||
|   if (!texture) | ||||
|     return !meta_surface_actor_is_unredirected (self); | ||||
|     return TRUE; | ||||
|  | ||||
|   switch (cogl_texture_get_components (texture)) | ||||
|     { | ||||
|   | ||||
| @@ -55,12 +55,17 @@ MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self); | ||||
| MetaWindow        *meta_surface_actor_get_window  (MetaSurfaceActor *self); | ||||
|  | ||||
| gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self); | ||||
| gboolean meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor      *self, | ||||
|                                                    cairo_rectangle_int_t *unobscured_bounds); | ||||
|  | ||||
| void meta_surface_actor_set_input_region (MetaSurfaceActor *self, | ||||
|                                           cairo_region_t   *region); | ||||
| void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self, | ||||
|                                            cairo_region_t   *region); | ||||
|  | ||||
| void meta_surface_actor_update_area (MetaSurfaceActor *actor, | ||||
|                                      int x, int y, int width, int height); | ||||
|  | ||||
| void meta_surface_actor_process_damage (MetaSurfaceActor *actor, | ||||
|                                         int x, int y, int width, int height); | ||||
| void meta_surface_actor_pre_paint (MetaSurfaceActor *actor); | ||||
|   | ||||
| @@ -378,8 +378,8 @@ texture_tower_create_texture (MetaTextureTower *tower, | ||||
| } | ||||
|  | ||||
| static void | ||||
| texture_tower_revalidate (MetaTextureTower *tower, | ||||
|                           int               level) | ||||
| texture_tower_revalidate_fbo (MetaTextureTower *tower, | ||||
|                               int               level) | ||||
| { | ||||
|   CoglTexture *source_texture = tower->textures[level - 1]; | ||||
|   int source_texture_width = cogl_texture_get_width (source_texture); | ||||
| @@ -425,9 +425,13 @@ texture_tower_revalidate (MetaTextureTower *tower, | ||||
|                                             (2. * invalid->y2) / source_texture_height); | ||||
|  | ||||
|   cogl_object_unref (pipeline); | ||||
| } | ||||
|  | ||||
|   tower->invalid[level].x1 = tower->invalid[level].x2 = 0; | ||||
|   tower->invalid[level].y1 = tower->invalid[level].y2 = 0; | ||||
| static void | ||||
| texture_tower_revalidate (MetaTextureTower *tower, | ||||
|                           int               level) | ||||
| { | ||||
|   texture_tower_revalidate_fbo (tower, level); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -32,17 +32,9 @@ | ||||
|  | ||||
| #include "meta-surface-actor.h" | ||||
| #include "meta-surface-actor-x11.h" | ||||
|  | ||||
| #ifdef HAVE_WAYLAND | ||||
| #include "meta-surface-actor-wayland.h" | ||||
| #include "wayland/meta-wayland-surface.h" | ||||
| #endif | ||||
|  | ||||
| typedef enum { | ||||
|   INITIALLY_FROZEN, | ||||
|   DRAWING_FIRST_FRAME, | ||||
|   EMITTED_FIRST_FRAME | ||||
| } FirstFrameState; | ||||
| #include "wayland/meta-wayland-surface.h" | ||||
|  | ||||
| struct _MetaWindowActorPrivate | ||||
| { | ||||
| @@ -78,7 +70,7 @@ struct _MetaWindowActorPrivate | ||||
|   gint64            frame_drawn_time; | ||||
|  | ||||
|   guint             repaint_scheduled_id; | ||||
|   guint             size_changed_id; | ||||
|   guint             allocation_changed_id; | ||||
|  | ||||
|   /* | ||||
|    * These need to be counters rather than flags, since more plugins | ||||
| @@ -86,7 +78,6 @@ struct _MetaWindowActorPrivate | ||||
|    * might be dubious, but we have to at least handle it correctly. | ||||
|    */ | ||||
|   gint              minimize_in_progress; | ||||
|   gint              unminimize_in_progress; | ||||
|   gint              maximize_in_progress; | ||||
|   gint              unmaximize_in_progress; | ||||
|   gint              map_in_progress; | ||||
| @@ -113,7 +104,6 @@ struct _MetaWindowActorPrivate | ||||
|   guint             no_shadow              : 1; | ||||
|  | ||||
|   guint             updates_frozen         : 1; | ||||
|   guint             first_frame_state      : 2; /* FirstFrameState */ | ||||
| }; | ||||
|  | ||||
| typedef struct _FrameData FrameData; | ||||
| @@ -125,14 +115,6 @@ struct _FrameData | ||||
|   gint64 frame_drawn_time; | ||||
| }; | ||||
|  | ||||
| enum | ||||
| { | ||||
|   FIRST_FRAME, | ||||
|   LAST_SIGNAL | ||||
| }; | ||||
|  | ||||
| static guint signals[LAST_SIGNAL] = { 0 }; | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_META_WINDOW = 1, | ||||
| @@ -199,31 +181,6 @@ meta_window_actor_class_init (MetaWindowActorClass *klass) | ||||
|   actor_class->paint = meta_window_actor_paint; | ||||
|   actor_class->get_paint_volume = meta_window_actor_get_paint_volume; | ||||
|  | ||||
|   /** | ||||
|    * MetaWindowActor::first-frame: | ||||
|    * @actor: the #MetaWindowActor instance | ||||
|    * | ||||
|    * The ::first-frame signal will be emitted the first time a frame | ||||
|    * of window contents has been drawn by the application and Mutter | ||||
|    * has had the chance to drawn that frame to the screen. If the | ||||
|    * window starts off initially hidden, obscured, or on on a | ||||
|    * different workspace, the ::first-frame signal will be emitted | ||||
|    * even though the user doesn't see the contents. | ||||
|    * | ||||
|    * MetaDisplay::window-created is a good place to connect to this | ||||
|    * signal - at that point, the MetaWindowActor for the window | ||||
|    * exists, but the window has reliably not yet been drawn. | ||||
|    * Connecting to an existing window that has already been drawn to | ||||
|    * the screen is not useful. | ||||
|    */ | ||||
|   signals[FIRST_FRAME] = | ||||
|     g_signal_new ("first-frame", | ||||
|                   G_TYPE_FROM_CLASS (object_class), | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   0, | ||||
|                   NULL, NULL, NULL, | ||||
|                   G_TYPE_NONE, 0); | ||||
|  | ||||
|   pspec = g_param_spec_object ("meta-window", | ||||
|                                "MetaWindow", | ||||
|                                "The displayed MetaWindow", | ||||
| @@ -275,11 +232,12 @@ window_appears_focused_notify (MetaWindow *mw, | ||||
| } | ||||
|  | ||||
| static void | ||||
| surface_size_changed (MetaSurfaceActor *actor, | ||||
|                       gpointer          user_data) | ||||
| surface_allocation_changed_notify (ClutterActor           *actor, | ||||
|                                    const ClutterActorBox  *allocation, | ||||
|                                    ClutterAllocationFlags  flags, | ||||
|                                    MetaWindowActor        *self) | ||||
| { | ||||
|   MetaWindowActor *self = META_WINDOW_ACTOR (user_data); | ||||
|  | ||||
|   meta_window_actor_sync_actor_geometry (self, FALSE); | ||||
|   meta_window_actor_update_shape (self); | ||||
| } | ||||
|  | ||||
| @@ -348,9 +306,6 @@ meta_window_actor_thaw (MetaWindowActor *self) | ||||
|   if (priv->freeze_count > 0) | ||||
|     return; | ||||
|  | ||||
|   if (priv->first_frame_state == INITIALLY_FROZEN) | ||||
|     priv->first_frame_state = DRAWING_FIRST_FRAME; | ||||
|  | ||||
|   if (priv->surface) | ||||
|     meta_surface_actor_set_frozen (priv->surface, FALSE); | ||||
|  | ||||
| @@ -371,8 +326,9 @@ set_surface (MetaWindowActor  *self, | ||||
|   if (priv->surface) | ||||
|     { | ||||
|       g_signal_handler_disconnect (priv->surface, priv->repaint_scheduled_id); | ||||
|       g_signal_handler_disconnect (priv->surface, priv->size_changed_id); | ||||
|       priv->repaint_scheduled_id = 0; | ||||
|       g_signal_handler_disconnect (priv->surface, priv->allocation_changed_id); | ||||
|       priv->allocation_changed_id = 0; | ||||
|       clutter_actor_remove_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface)); | ||||
|       g_object_unref (priv->surface); | ||||
|     } | ||||
| @@ -384,17 +340,14 @@ set_surface (MetaWindowActor  *self, | ||||
|       g_object_ref_sink (priv->surface); | ||||
|       priv->repaint_scheduled_id = g_signal_connect (priv->surface, "repaint-scheduled", | ||||
|                                                      G_CALLBACK (surface_repaint_scheduled), self); | ||||
|       priv->size_changed_id = g_signal_connect (priv->surface, "size-changed", | ||||
|                                                 G_CALLBACK (surface_size_changed), self); | ||||
|       priv->allocation_changed_id = g_signal_connect (priv->surface, "allocation-changed", | ||||
|                                                       G_CALLBACK (surface_allocation_changed_notify), self); | ||||
|       clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface)); | ||||
|  | ||||
|       /* If the previous surface actor was frozen, start out | ||||
|        * frozen as well... */ | ||||
|       meta_surface_actor_set_frozen (priv->surface, priv->freeze_count > 0); | ||||
|  | ||||
|       if (!is_frozen (self) && priv->first_frame_state == INITIALLY_FROZEN) | ||||
|         priv->first_frame_state = DRAWING_FIRST_FRAME; | ||||
|  | ||||
|       meta_window_actor_update_shape (self); | ||||
|     } | ||||
| } | ||||
| @@ -406,12 +359,9 @@ meta_window_actor_update_surface (MetaWindowActor *self) | ||||
|   MetaWindow *window = priv->window; | ||||
|   MetaSurfaceActor *surface_actor; | ||||
|  | ||||
| #ifdef HAVE_WAYLAND | ||||
|   if (window->surface) | ||||
|     surface_actor = window->surface->surface_actor; | ||||
|   else | ||||
| #endif | ||||
|   if (!meta_is_wayland_compositor ()) | ||||
|   else if (!meta_is_wayland_compositor ()) | ||||
|     surface_actor = meta_surface_actor_x11_new (window); | ||||
|   else | ||||
|     surface_actor = NULL; | ||||
| @@ -601,7 +551,6 @@ meta_window_actor_get_shape_bounds (MetaWindowActor       *self, | ||||
|  | ||||
|   cairo_region_get_extents (priv->shape_region, bounds); | ||||
|  | ||||
| #ifdef HAVE_WAYLAND | ||||
|   if (META_IS_SURFACE_ACTOR_WAYLAND (priv->surface)) | ||||
|     { | ||||
|       double scale = priv->surface ? | ||||
| @@ -611,7 +560,6 @@ meta_window_actor_get_shape_bounds (MetaWindowActor       *self, | ||||
|       bounds->width *= scale; | ||||
|       bounds->height *= scale; | ||||
|     } | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -719,16 +667,25 @@ meta_window_actor_get_paint_volume (ClutterActor       *actor, | ||||
| { | ||||
|   MetaWindowActor *self = META_WINDOW_ACTOR (actor); | ||||
|   MetaWindowActorPrivate *priv = self->priv; | ||||
|   cairo_rectangle_int_t unobscured_bounds, bounds; | ||||
|   gboolean appears_focused = meta_window_appears_focused (priv->window); | ||||
|   ClutterVertex origin; | ||||
|  | ||||
|   /* The paint volume is computed before paint functions are called | ||||
|    * so our bounds might not be updated yet. Force an update. */ | ||||
|   meta_window_actor_handle_updates (self); | ||||
|  | ||||
|   meta_window_actor_get_shape_bounds (self, &bounds); | ||||
|  | ||||
|   if (priv->surface) | ||||
|     { | ||||
|       if (meta_surface_actor_get_unobscured_bounds (priv->surface, &unobscured_bounds)) | ||||
|         gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds); | ||||
|     } | ||||
|  | ||||
|   if (appears_focused ? priv->focused_shadow : priv->unfocused_shadow) | ||||
|     { | ||||
|       cairo_rectangle_int_t shadow_bounds; | ||||
|       ClutterActorBox shadow_box; | ||||
|  | ||||
|       /* We could compute an full clip region as we do for the window | ||||
|        * texture, but the shadow is relatively cheap to draw, and | ||||
| @@ -738,24 +695,16 @@ meta_window_actor_get_paint_volume (ClutterActor       *actor, | ||||
|        */ | ||||
|  | ||||
|       meta_window_actor_get_shadow_bounds (self, appears_focused, &shadow_bounds); | ||||
|       shadow_box.x1 = shadow_bounds.x; | ||||
|       shadow_box.x2 = shadow_bounds.x + shadow_bounds.width; | ||||
|       shadow_box.y1 = shadow_bounds.y; | ||||
|       shadow_box.y2 = shadow_bounds.y + shadow_bounds.height; | ||||
|  | ||||
|       clutter_paint_volume_union_box (volume, &shadow_box); | ||||
|       gdk_rectangle_union (&bounds, &shadow_bounds, &bounds); | ||||
|     } | ||||
|  | ||||
|   if (priv->surface) | ||||
|     { | ||||
|       const ClutterPaintVolume *child_volume; | ||||
|   origin.x = bounds.x; | ||||
|   origin.y = bounds.y; | ||||
|   origin.z = 0.0f; | ||||
|   clutter_paint_volume_set_origin (volume, &origin); | ||||
|  | ||||
|       child_volume = clutter_actor_get_transformed_paint_volume (CLUTTER_ACTOR (priv->surface), actor); | ||||
|       if (!child_volume) | ||||
|         return FALSE; | ||||
|  | ||||
|       clutter_paint_volume_union (volume, child_volume); | ||||
|     } | ||||
|   clutter_paint_volume_set_width (volume, bounds.width); | ||||
|   clutter_paint_volume_set_height (volume, bounds.height); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
| @@ -865,7 +814,7 @@ meta_window_actor_get_surface (MetaWindowActor *self) | ||||
| gboolean | ||||
| meta_window_actor_is_destroyed (MetaWindowActor *self) | ||||
| { | ||||
|   return self->priv->disposed || self->priv->needs_destroy; | ||||
|   return self->priv->disposed; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| @@ -904,7 +853,7 @@ queue_send_frame_messages_timeout (MetaWindowActor *self) | ||||
|   outputs = meta_monitor_manager_get_outputs (monitor_manager, &n_outputs); | ||||
|   for (i = 0; i < n_outputs; i++) | ||||
|     { | ||||
|       if (outputs[i].winsys_id == window->monitor->winsys_id && outputs[i].crtc) | ||||
|       if (outputs[i].output_id == window->monitor->output_id && outputs[i].crtc) | ||||
|         { | ||||
|           refresh_rate = outputs[i].crtc->current_mode->refresh_rate; | ||||
|           break; | ||||
| @@ -927,12 +876,7 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self, | ||||
|                                      gboolean         no_delay_frame) | ||||
| { | ||||
|   MetaWindowActorPrivate *priv = self->priv; | ||||
|   FrameData *frame; | ||||
|  | ||||
|   if (meta_window_actor_is_destroyed (self)) | ||||
|     return; | ||||
|  | ||||
|   frame = g_slice_new0 (FrameData); | ||||
|   FrameData *frame = g_slice_new0 (FrameData); | ||||
|  | ||||
|   priv->needs_frame_drawn = TRUE; | ||||
|  | ||||
| @@ -1018,9 +962,6 @@ start_simple_effect (MetaWindowActor *self, | ||||
|   case META_PLUGIN_MINIMIZE: | ||||
|     counter = &priv->minimize_in_progress; | ||||
|     break; | ||||
|   case META_PLUGIN_UNMINIMIZE: | ||||
|     counter = &priv->unminimize_in_progress; | ||||
|     break; | ||||
|   case META_PLUGIN_MAP: | ||||
|     counter = &priv->map_in_progress; | ||||
|     break; | ||||
| @@ -1091,16 +1032,6 @@ meta_window_actor_effect_completed (MetaWindowActor *self, | ||||
| 	} | ||||
|     } | ||||
|     break; | ||||
|   case META_PLUGIN_UNMINIMIZE: | ||||
|     { | ||||
|       priv->unminimize_in_progress--; | ||||
|       if (priv->unminimize_in_progress < 0) | ||||
|        { | ||||
|          g_warning ("Error in unminimize accounting."); | ||||
|          priv->unminimize_in_progress = 0; | ||||
|        } | ||||
|     } | ||||
|     break; | ||||
|   case META_PLUGIN_MAP: | ||||
|     /* | ||||
|      * Make sure that the actor is at the correct place in case | ||||
| @@ -1176,6 +1107,7 @@ meta_window_actor_destroy (MetaWindowActor *self) | ||||
| { | ||||
|   MetaWindowActorPrivate *priv = self->priv; | ||||
|   MetaWindow *window = priv->window; | ||||
|   MetaCompositor *compositor = priv->compositor; | ||||
|   MetaWindowType window_type = meta_window_get_window_type (window); | ||||
|  | ||||
|   meta_window_set_compositor_private (window, NULL); | ||||
| @@ -1186,6 +1118,12 @@ meta_window_actor_destroy (MetaWindowActor *self) | ||||
|       priv->send_frame_messages_timer = 0; | ||||
|     } | ||||
|  | ||||
|   /* | ||||
|    * We remove the window from internal lookup hashes and thus any other | ||||
|    * unmap events etc fail | ||||
|    */ | ||||
|   compositor->windows = g_list_remove (compositor->windows, (gconstpointer) self); | ||||
|  | ||||
|   if (window_type == META_WINDOW_DROPDOWN_MENU || | ||||
|       window_type == META_WINDOW_POPUP_MENU || | ||||
|       window_type == META_WINDOW_TOOLTIP || | ||||
| @@ -1259,7 +1197,8 @@ meta_window_actor_show (MetaWindowActor   *self, | ||||
|       event = META_PLUGIN_MAP; | ||||
|       break; | ||||
|     case META_COMP_EFFECT_UNMINIMIZE: | ||||
|       event = META_PLUGIN_UNMINIMIZE; | ||||
|       /* FIXME: should have META_PLUGIN_UNMINIMIZE */ | ||||
|       event = META_PLUGIN_MAP; | ||||
|       break; | ||||
|     case META_COMP_EFFECT_NONE: | ||||
|       break; | ||||
| @@ -1389,11 +1328,6 @@ meta_window_actor_new (MetaWindow *window) | ||||
|  | ||||
|   meta_window_actor_sync_updates_frozen (self); | ||||
|  | ||||
|   if (is_frozen (self)) | ||||
|     priv->first_frame_state = INITIALLY_FROZEN; | ||||
|   else | ||||
|     priv->first_frame_state = DRAWING_FIRST_FRAME; | ||||
|  | ||||
|   /* If a window doesn't start off with updates frozen, we should | ||||
|    * we should send a _NET_WM_FRAME_DRAWN immediately after the first drawn. | ||||
|    */ | ||||
| @@ -1662,8 +1596,6 @@ build_and_scan_frame_mask (MetaWindowActor       *self, | ||||
|                            cairo_rectangle_int_t *client_area, | ||||
|                            cairo_region_t        *shape_region) | ||||
| { | ||||
|   ClutterBackend *backend = clutter_get_default_backend (); | ||||
|   CoglContext *ctx = clutter_backend_get_cogl_context (backend); | ||||
|   MetaWindowActorPrivate *priv = self->priv; | ||||
|   guchar *mask_data; | ||||
|   guint tex_width, tex_height; | ||||
| @@ -1726,7 +1658,10 @@ build_and_scan_frame_mask (MetaWindowActor       *self, | ||||
|  | ||||
|   if (meta_texture_rectangle_check (paint_tex)) | ||||
|     { | ||||
|       mask_texture = COGL_TEXTURE (cogl_texture_rectangle_new_with_size (ctx, tex_width, tex_height)); | ||||
|       ClutterBackend *backend = clutter_get_default_backend (); | ||||
|       CoglContext *context = clutter_backend_get_cogl_context (backend); | ||||
|  | ||||
|       mask_texture = COGL_TEXTURE (cogl_texture_rectangle_new_with_size (context, tex_width, tex_height)); | ||||
|       cogl_texture_set_components (mask_texture, COGL_TEXTURE_COMPONENTS_A); | ||||
|       cogl_texture_set_region (mask_texture, | ||||
|                                0, 0, /* src_x/y */ | ||||
| @@ -1738,9 +1673,15 @@ build_and_scan_frame_mask (MetaWindowActor       *self, | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       mask_texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, tex_width, tex_height, | ||||
|                                                                   COGL_PIXEL_FORMAT_A_8, | ||||
|                                                                   stride, mask_data, NULL)); | ||||
|       /* Note: we don't allow slicing for this texture because we | ||||
|        * need to use it with multi-texturing which doesn't support | ||||
|        * sliced textures */ | ||||
|       mask_texture = cogl_texture_new_from_data (tex_width, tex_height, | ||||
|                                                  COGL_TEXTURE_NO_SLICING, | ||||
|                                                  COGL_PIXEL_FORMAT_A_8, | ||||
|                                                  COGL_PIXEL_FORMAT_ANY, | ||||
|                                                  stride, | ||||
|                                                  mask_data); | ||||
|     } | ||||
|  | ||||
|   meta_shaped_texture_set_mask_texture (stex, mask_texture); | ||||
| @@ -1908,9 +1849,6 @@ meta_window_actor_pre_paint (MetaWindowActor *self) | ||||
|   MetaWindowActorPrivate *priv = self->priv; | ||||
|   GList *l; | ||||
|  | ||||
|   if (meta_window_actor_is_destroyed (self)) | ||||
|     return; | ||||
|  | ||||
|   meta_window_actor_handle_updates (self); | ||||
|  | ||||
|   for (l = priv->frames; l != NULL; l = l->next) | ||||
| @@ -1960,9 +1898,6 @@ meta_window_actor_post_paint (MetaWindowActor *self) | ||||
|  | ||||
|   priv->repaint_scheduled = FALSE; | ||||
|  | ||||
|   if (meta_window_actor_is_destroyed (self)) | ||||
|     return; | ||||
|  | ||||
|  /* This window had damage, but wasn't actually redrawn because | ||||
|   * it is obscured. So we should wait until timer expiration | ||||
|   * before sending _NET_WM_FRAME_* messages. | ||||
| @@ -1975,12 +1910,6 @@ meta_window_actor_post_paint (MetaWindowActor *self) | ||||
|       do_send_frame_drawn (self, priv->frames->data); | ||||
|       priv->needs_frame_drawn = FALSE; | ||||
|     } | ||||
|  | ||||
|   if (priv->first_frame_state == DRAWING_FIRST_FRAME) | ||||
|     { | ||||
|       priv->first_frame_state = EMITTED_FIRST_FRAME; | ||||
|       g_signal_emit (self, signals[FIRST_FRAME], 0); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -2050,9 +1979,6 @@ meta_window_actor_frame_complete (MetaWindowActor *self, | ||||
|   MetaWindowActorPrivate *priv = self->priv; | ||||
|   GList *l; | ||||
|  | ||||
|   if (meta_window_actor_is_destroyed (self)) | ||||
|     return; | ||||
|  | ||||
|   for (l = priv->frames; l;) | ||||
|     { | ||||
|       GList *l_next = l->next; | ||||
|   | ||||
| @@ -31,6 +31,64 @@ static void cullable_iface_init (MetaCullableInterface *iface); | ||||
| G_DEFINE_TYPE_WITH_CODE (MetaWindowGroup, meta_window_group, CLUTTER_TYPE_ACTOR, | ||||
|                          G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)); | ||||
|  | ||||
| /* Help macros to scale from OpenGL <-1,1> coordinates system to | ||||
|  * window coordinates ranging [0,window-size]. Borrowed from clutter-utils.c | ||||
|  */ | ||||
| #define MTX_GL_SCALE_X(x,w,v1,v2) ((((((x) / (w)) + 1.0f) / 2.0f) * (v1)) + (v2)) | ||||
| #define MTX_GL_SCALE_Y(y,w,v1,v2) ((v1) - (((((y) / (w)) + 1.0f) / 2.0f) * (v1)) + (v2)) | ||||
|  | ||||
| /* Check if we're painting the MetaWindowGroup "untransformed". This can | ||||
|  * differ from the result of actor_is_untransformed(window_group) if we're | ||||
|  * inside a clone paint. The integer translation, if any, is returned. | ||||
|  */ | ||||
| static gboolean | ||||
| painting_untransformed (MetaWindowGroup *window_group, | ||||
|                         int             *x_origin, | ||||
|                         int             *y_origin) | ||||
| { | ||||
|   CoglMatrix modelview, projection, modelview_projection; | ||||
|   ClutterVertex vertices[4]; | ||||
|   int width, height; | ||||
|   float viewport[4]; | ||||
|   int i; | ||||
|  | ||||
|   cogl_get_modelview_matrix (&modelview); | ||||
|   cogl_get_projection_matrix (&projection); | ||||
|  | ||||
|   cogl_matrix_multiply (&modelview_projection, | ||||
|                         &projection, | ||||
|                         &modelview); | ||||
|  | ||||
|   meta_screen_get_size (window_group->screen, &width, &height); | ||||
|  | ||||
|   vertices[0].x = 0; | ||||
|   vertices[0].y = 0; | ||||
|   vertices[0].z = 0; | ||||
|   vertices[1].x = width; | ||||
|   vertices[1].y = 0; | ||||
|   vertices[1].z = 0; | ||||
|   vertices[2].x = 0; | ||||
|   vertices[2].y = height; | ||||
|   vertices[2].z = 0; | ||||
|   vertices[3].x = width; | ||||
|   vertices[3].y = height; | ||||
|   vertices[3].z = 0; | ||||
|  | ||||
|   cogl_get_viewport (viewport); | ||||
|  | ||||
|   for (i = 0; i < 4; i++) | ||||
|     { | ||||
|       float w = 1; | ||||
|       cogl_matrix_transform_point (&modelview_projection, &vertices[i].x, &vertices[i].y, &vertices[i].z, &w); | ||||
|       vertices[i].x = MTX_GL_SCALE_X (vertices[i].x, w, | ||||
|                                       viewport[2], viewport[0]); | ||||
|       vertices[i].y = MTX_GL_SCALE_Y (vertices[i].y, w, | ||||
|                                       viewport[3], viewport[1]); | ||||
|     } | ||||
|  | ||||
|   return meta_actor_vertices_are_untransformed (vertices, width, height, x_origin, y_origin); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_window_group_cull_out (MetaCullable   *cullable, | ||||
|                             cairo_region_t *unobscured_region, | ||||
| @@ -61,13 +119,10 @@ meta_window_group_paint (ClutterActor *actor) | ||||
|   int paint_x_offset, paint_y_offset; | ||||
|   int paint_x_origin, paint_y_origin; | ||||
|   int actor_x_origin, actor_y_origin; | ||||
|   int screen_width, screen_height; | ||||
|  | ||||
|   MetaWindowGroup *window_group = META_WINDOW_GROUP (actor); | ||||
|   ClutterActor *stage = clutter_actor_get_stage (actor); | ||||
|  | ||||
|   meta_screen_get_size (window_group->screen, &screen_width, &screen_height); | ||||
|  | ||||
|   /* Normally we expect an actor to be drawn at it's position on the screen. | ||||
|    * However, if we're inside the paint of a ClutterClone, that won't be the | ||||
|    * case and we need to compensate. We look at the position of the window | ||||
| @@ -81,7 +136,7 @@ meta_window_group_paint (ClutterActor *actor) | ||||
|    * painting currently, and never worry about how actors are positioned | ||||
|    * on the stage. | ||||
|    */ | ||||
|   if (!meta_actor_painting_untransformed (screen_width, screen_height, &paint_x_origin, &paint_y_origin) || | ||||
|   if (!painting_untransformed (window_group, &paint_x_origin, &paint_y_origin) || | ||||
|       !meta_actor_is_untransformed (actor, &actor_x_origin, &actor_y_origin)) | ||||
|     { | ||||
|       CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor); | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user