├── tests ├── big.png ├── blue.png ├── tiny.png ├── scale.png ├── small.png ├── gradient.png ├── seat_test.png ├── basic_damage.png ├── scale_damage.png ├── seat_child.png ├── simple_test.dump ├── subsurface_1.png ├── damage_test_1.dump ├── damage_test_2.dump ├── argb8888_linear.dump ├── basic_test_card.png ├── buffer_scale_1_1.dump ├── buffer_scale_1_2.dump ├── buffer_scale_2_1.dump ├── buffer_scale_2_2.dump ├── cow_transparent.png ├── subsurface_base.png ├── subsurface_damage.png ├── viewporter_test.png ├── viewporter_test_1.png ├── argb8888_implicit.dump ├── buffer_scale_1_2_1.dump ├── buffer_scale_1_2_2.dump ├── buffer_scale_2_2_1.dump ├── buffer_scale_2_2_2.dump ├── buffer_scale_2_5_1.dump ├── buffer_scale_2_5_2.dump ├── subsurface_stack_1.png ├── subsurface_stack_2.png ├── subsurface_test_1.dump ├── subsurface_test_10.dump ├── subsurface_test_11.dump ├── subsurface_test_12.dump ├── subsurface_test_13.dump ├── subsurface_test_14.dump ├── subsurface_test_15.dump ├── subsurface_test_16.dump ├── subsurface_test_17.dump ├── subsurface_test_18.dump ├── subsurface_test_19.dump ├── subsurface_test_2.dump ├── subsurface_test_20.dump ├── subsurface_test_21.dump ├── subsurface_test_22.dump ├── subsurface_test_23.dump ├── subsurface_test_24.dump ├── subsurface_test_25.dump ├── subsurface_test_26.dump ├── subsurface_test_27.dump ├── subsurface_test_28.dump ├── subsurface_test_29.dump ├── subsurface_test_3.dump ├── subsurface_test_30.dump ├── subsurface_test_31.dump ├── subsurface_test_32.dump ├── subsurface_test_33.dump ├── subsurface_test_34.dump ├── subsurface_test_35.dump ├── subsurface_test_36.dump ├── subsurface_test_37.dump ├── subsurface_test_38.dump ├── subsurface_test_39.dump ├── subsurface_test_4.dump ├── subsurface_test_5.dump ├── subsurface_test_6.dump ├── subsurface_test_7.dump ├── subsurface_test_8.dump ├── subsurface_test_9.dump ├── single_pixel_buffer.dump ├── subsurface_1_complex.png ├── subsurface_1_damaged.png ├── transform_test_180_1.dump ├── transform_test_180_2.dump ├── transform_test_270_1.dump ├── transform_test_270_2.dump ├── transform_test_90_1.dump ├── transform_test_90_2.dump ├── subsurface_transparency.png ├── viewport_dest_200_150_1.dump ├── viewport_dest_200_150_2.dump ├── transform_test_flipped_1.dump ├── transform_test_flipped_2.dump ├── single_pixel_buffer_viewport.dump ├── transform_test_flipped_180_1.dump ├── transform_test_flipped_180_2.dump ├── transform_test_flipped_270_1.dump ├── transform_test_flipped_270_2.dump ├── transform_test_flipped_90_1.dump ├── transform_test_flipped_90_2.dump ├── viewport_src_50_50_200_200_1.dump ├── viewport_src_50_50_200_200_2.dump ├── subsurface_transparency_damage.png ├── viewport_src_50_50_200_200_dest_500_500_1.dump ├── viewport_src_50_50_200_200_dest_500_500_2.dump ├── viewport_src_50_50_200_200_dest_50_75_1.dump ├── viewport_src_50_50_200_200_dest_50_75_2.dump ├── viewport_src_250_50_200_200_dest_50_75_90cw_1.dump ├── viewport_src_250_50_200_200_dest_50_75_90cw_2.dump ├── svnignore.txt ├── README ├── run_tests.sh ├── imgview.c ├── Imakefile ├── test_harness.h ├── select_helper.c ├── simple_test.c ├── buffer_test.c ├── single_pixel_buffer_test.c ├── tearing_control_test.c ├── damage_test.c └── select_helper_multiple.c ├── .gitignore ├── svnignore.txt ├── 12to11.conf ├── mime2.awk ├── mime0.awk ├── mime4.awk ├── mime3.awk ├── mime1.awk ├── modifiers.awk ├── shaders.awk ├── compositor.c ├── decoration.c ├── alloc.c ├── region.c ├── fence_ring.c ├── shaders.txt ├── buffer.c ├── single-pixel-buffer-v1.xml ├── ewmh.c ├── relative_pointer.c ├── idle-inhibit-unstable-v1.xml ├── buffer_release.c ├── xdg_wm.c ├── README ├── tearing-control-v1.xml ├── tearing_control.c ├── single_pixel_buffer.c ├── pointer_gestures.c ├── timer.c ├── relative-pointer-unstable-v1.xml ├── keyboard-shortcuts-inhibit-unstable-v1.xml ├── Imakefile ├── xdg-decoration-unstable-v1.xml └── port_gnu.h /tests/big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/big.png -------------------------------------------------------------------------------- /tests/blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/blue.png -------------------------------------------------------------------------------- /tests/tiny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/tiny.png -------------------------------------------------------------------------------- /tests/scale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/scale.png -------------------------------------------------------------------------------- /tests/small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/small.png -------------------------------------------------------------------------------- /tests/gradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/gradient.png -------------------------------------------------------------------------------- /tests/seat_test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/seat_test.png -------------------------------------------------------------------------------- /tests/basic_damage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/basic_damage.png -------------------------------------------------------------------------------- /tests/scale_damage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/scale_damage.png -------------------------------------------------------------------------------- /tests/seat_child.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/seat_child.png -------------------------------------------------------------------------------- /tests/simple_test.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/simple_test.dump -------------------------------------------------------------------------------- /tests/subsurface_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_1.png -------------------------------------------------------------------------------- /tests/damage_test_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/damage_test_1.dump -------------------------------------------------------------------------------- /tests/damage_test_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/damage_test_2.dump -------------------------------------------------------------------------------- /tests/argb8888_linear.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/argb8888_linear.dump -------------------------------------------------------------------------------- /tests/basic_test_card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/basic_test_card.png -------------------------------------------------------------------------------- /tests/buffer_scale_1_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/buffer_scale_1_1.dump -------------------------------------------------------------------------------- /tests/buffer_scale_1_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/buffer_scale_1_2.dump -------------------------------------------------------------------------------- /tests/buffer_scale_2_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/buffer_scale_2_1.dump -------------------------------------------------------------------------------- /tests/buffer_scale_2_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/buffer_scale_2_2.dump -------------------------------------------------------------------------------- /tests/cow_transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/cow_transparent.png -------------------------------------------------------------------------------- /tests/subsurface_base.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_base.png -------------------------------------------------------------------------------- /tests/subsurface_damage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_damage.png -------------------------------------------------------------------------------- /tests/viewporter_test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/viewporter_test.png -------------------------------------------------------------------------------- /tests/viewporter_test_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/viewporter_test_1.png -------------------------------------------------------------------------------- /tests/argb8888_implicit.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/argb8888_implicit.dump -------------------------------------------------------------------------------- /tests/buffer_scale_1_2_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/buffer_scale_1_2_1.dump -------------------------------------------------------------------------------- /tests/buffer_scale_1_2_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/buffer_scale_1_2_2.dump -------------------------------------------------------------------------------- /tests/buffer_scale_2_2_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/buffer_scale_2_2_1.dump -------------------------------------------------------------------------------- /tests/buffer_scale_2_2_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/buffer_scale_2_2_2.dump -------------------------------------------------------------------------------- /tests/buffer_scale_2_5_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/buffer_scale_2_5_1.dump -------------------------------------------------------------------------------- /tests/buffer_scale_2_5_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/buffer_scale_2_5_2.dump -------------------------------------------------------------------------------- /tests/subsurface_stack_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_stack_1.png -------------------------------------------------------------------------------- /tests/subsurface_stack_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_stack_2.png -------------------------------------------------------------------------------- /tests/subsurface_test_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_1.dump -------------------------------------------------------------------------------- /tests/subsurface_test_10.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_10.dump -------------------------------------------------------------------------------- /tests/subsurface_test_11.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_11.dump -------------------------------------------------------------------------------- /tests/subsurface_test_12.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_12.dump -------------------------------------------------------------------------------- /tests/subsurface_test_13.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_13.dump -------------------------------------------------------------------------------- /tests/subsurface_test_14.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_14.dump -------------------------------------------------------------------------------- /tests/subsurface_test_15.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_15.dump -------------------------------------------------------------------------------- /tests/subsurface_test_16.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_16.dump -------------------------------------------------------------------------------- /tests/subsurface_test_17.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_17.dump -------------------------------------------------------------------------------- /tests/subsurface_test_18.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_18.dump -------------------------------------------------------------------------------- /tests/subsurface_test_19.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_19.dump -------------------------------------------------------------------------------- /tests/subsurface_test_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_2.dump -------------------------------------------------------------------------------- /tests/subsurface_test_20.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_20.dump -------------------------------------------------------------------------------- /tests/subsurface_test_21.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_21.dump -------------------------------------------------------------------------------- /tests/subsurface_test_22.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_22.dump -------------------------------------------------------------------------------- /tests/subsurface_test_23.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_23.dump -------------------------------------------------------------------------------- /tests/subsurface_test_24.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_24.dump -------------------------------------------------------------------------------- /tests/subsurface_test_25.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_25.dump -------------------------------------------------------------------------------- /tests/subsurface_test_26.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_26.dump -------------------------------------------------------------------------------- /tests/subsurface_test_27.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_27.dump -------------------------------------------------------------------------------- /tests/subsurface_test_28.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_28.dump -------------------------------------------------------------------------------- /tests/subsurface_test_29.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_29.dump -------------------------------------------------------------------------------- /tests/subsurface_test_3.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_3.dump -------------------------------------------------------------------------------- /tests/subsurface_test_30.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_30.dump -------------------------------------------------------------------------------- /tests/subsurface_test_31.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_31.dump -------------------------------------------------------------------------------- /tests/subsurface_test_32.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_32.dump -------------------------------------------------------------------------------- /tests/subsurface_test_33.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_33.dump -------------------------------------------------------------------------------- /tests/subsurface_test_34.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_34.dump -------------------------------------------------------------------------------- /tests/subsurface_test_35.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_35.dump -------------------------------------------------------------------------------- /tests/subsurface_test_36.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_36.dump -------------------------------------------------------------------------------- /tests/subsurface_test_37.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_37.dump -------------------------------------------------------------------------------- /tests/subsurface_test_38.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_38.dump -------------------------------------------------------------------------------- /tests/subsurface_test_39.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_39.dump -------------------------------------------------------------------------------- /tests/subsurface_test_4.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_4.dump -------------------------------------------------------------------------------- /tests/subsurface_test_5.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_5.dump -------------------------------------------------------------------------------- /tests/subsurface_test_6.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_6.dump -------------------------------------------------------------------------------- /tests/subsurface_test_7.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_7.dump -------------------------------------------------------------------------------- /tests/subsurface_test_8.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_8.dump -------------------------------------------------------------------------------- /tests/subsurface_test_9.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_test_9.dump -------------------------------------------------------------------------------- /tests/single_pixel_buffer.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/single_pixel_buffer.dump -------------------------------------------------------------------------------- /tests/subsurface_1_complex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_1_complex.png -------------------------------------------------------------------------------- /tests/subsurface_1_damaged.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_1_damaged.png -------------------------------------------------------------------------------- /tests/transform_test_180_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/transform_test_180_1.dump -------------------------------------------------------------------------------- /tests/transform_test_180_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/transform_test_180_2.dump -------------------------------------------------------------------------------- /tests/transform_test_270_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/transform_test_270_1.dump -------------------------------------------------------------------------------- /tests/transform_test_270_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/transform_test_270_2.dump -------------------------------------------------------------------------------- /tests/transform_test_90_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/transform_test_90_1.dump -------------------------------------------------------------------------------- /tests/transform_test_90_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/transform_test_90_2.dump -------------------------------------------------------------------------------- /tests/subsurface_transparency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_transparency.png -------------------------------------------------------------------------------- /tests/viewport_dest_200_150_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/viewport_dest_200_150_1.dump -------------------------------------------------------------------------------- /tests/viewport_dest_200_150_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/viewport_dest_200_150_2.dump -------------------------------------------------------------------------------- /tests/transform_test_flipped_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/transform_test_flipped_1.dump -------------------------------------------------------------------------------- /tests/transform_test_flipped_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/transform_test_flipped_2.dump -------------------------------------------------------------------------------- /tests/single_pixel_buffer_viewport.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/single_pixel_buffer_viewport.dump -------------------------------------------------------------------------------- /tests/transform_test_flipped_180_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/transform_test_flipped_180_1.dump -------------------------------------------------------------------------------- /tests/transform_test_flipped_180_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/transform_test_flipped_180_2.dump -------------------------------------------------------------------------------- /tests/transform_test_flipped_270_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/transform_test_flipped_270_1.dump -------------------------------------------------------------------------------- /tests/transform_test_flipped_270_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/transform_test_flipped_270_2.dump -------------------------------------------------------------------------------- /tests/transform_test_flipped_90_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/transform_test_flipped_90_1.dump -------------------------------------------------------------------------------- /tests/transform_test_flipped_90_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/transform_test_flipped_90_2.dump -------------------------------------------------------------------------------- /tests/viewport_src_50_50_200_200_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/viewport_src_50_50_200_200_1.dump -------------------------------------------------------------------------------- /tests/viewport_src_50_50_200_200_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/viewport_src_50_50_200_200_2.dump -------------------------------------------------------------------------------- /tests/subsurface_transparency_damage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/subsurface_transparency_damage.png -------------------------------------------------------------------------------- /tests/viewport_src_50_50_200_200_dest_500_500_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/viewport_src_50_50_200_200_dest_500_500_1.dump -------------------------------------------------------------------------------- /tests/viewport_src_50_50_200_200_dest_500_500_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/viewport_src_50_50_200_200_dest_500_500_2.dump -------------------------------------------------------------------------------- /tests/viewport_src_50_50_200_200_dest_50_75_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/viewport_src_50_50_200_200_dest_50_75_1.dump -------------------------------------------------------------------------------- /tests/viewport_src_50_50_200_200_dest_50_75_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/viewport_src_50_50_200_200_dest_50_75_2.dump -------------------------------------------------------------------------------- /tests/viewport_src_250_50_200_200_dest_50_75_90cw_1.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/viewport_src_250_50_200_200_dest_50_75_90cw_1.dump -------------------------------------------------------------------------------- /tests/viewport_src_250_50_200_200_dest_50_75_90cw_2.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/12to11/master/tests/viewport_src_250_50_200_200_dest_50_75_90cw_2.dump -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *-*.c 2 | *-*.h 3 | viewporter.c 4 | viewporter.h 5 | *._man 6 | short_types.txt 7 | shaders.h 8 | transfer_atoms.h 9 | Makefile 10 | *.bak 11 | 12to11 12 | *.o 13 | vgcore* 14 | massif* 15 | callgrind* 16 | drm_modifiers.h 17 | -------------------------------------------------------------------------------- /svnignore.txt: -------------------------------------------------------------------------------- 1 | *-*.c 2 | *-*.h 3 | viewporter.c 4 | viewporter.h 5 | *._man 6 | short_types.txt 7 | shaders.h 8 | transfer_atoms.h 9 | Makefile 10 | *.bak 11 | 12to11 12 | *.o 13 | vgcore* 14 | massif* 15 | callgrind* 16 | drm_modifiers.h 17 | -------------------------------------------------------------------------------- /tests/svnignore.txt: -------------------------------------------------------------------------------- 1 | *-*.h 2 | *-*.c 3 | vgcore* 4 | simple_test 5 | damage_test 6 | transform_test 7 | viewporter_test 8 | subsurface_test 9 | scale_test 10 | seat_test 11 | dmabuf_test 12 | select_test 13 | select_helper 14 | select_helper_multiple 15 | xdg_activation_test 16 | single_pixel_buffer_test 17 | buffer_test 18 | tearing_control_test 19 | imgview 20 | reject.dump 21 | Makefile 22 | Makefile.bak 23 | viewporter.h 24 | viewporter.c 25 | -------------------------------------------------------------------------------- /12to11.conf: -------------------------------------------------------------------------------- 1 | /* Edit this file if any of these libraries and tools are named differently 2 | on your system. */ 3 | 4 | XCB = -lxcb 5 | XCB_SHM = -lxcb-shm 6 | XCB_DRI3 = -lxcb-dri3 7 | XCB_SHAPE = -lxcb-shape 8 | XCB_RANDR = -lxcb-randr 9 | WAYLAND_SERVER = -lwayland-server 10 | XCBLIB = -lX11-xcb 11 | PIXMAN = -lpixman-1 12 | DRM = -ldrm 13 | DRMFOURCCH = $(INCROOT)/libdrm/drm_fourcc.h 14 | DRMINCLUDES = -I$(INCROOT)/libdrm 15 | PIXMANINCLUDES = -I$(INCROOT)/pixman-1 16 | XPRESENTLIB = -lXpresent 17 | WAYLAND_SCANNER = wayland-scanner 18 | XSHMFENCELIB = -lxshmfence 19 | 20 | /* The following libraries are used for tests. */ 21 | 22 | WAYLAND_CLIENT = -lwayland-client 23 | PNG = -lpng 24 | GBM = -lgbm 25 | 26 | XCOMM #define BuildTests 27 | 28 | /* Comment the following code if building without EGL support. */ 29 | 30 | #define HaveEglSupport 31 | EGL = -lEGL 32 | GLES = -lGLESv2 33 | 34 | XCOMM Local Variables: 35 | XCOMM mode: makefile-imake 36 | XCOMM End: 37 | -------------------------------------------------------------------------------- /mime2.awk: -------------------------------------------------------------------------------- 1 | # Wayland compositor running on top of an X server. 2 | 3 | # Copyright (C) 2022 to various contributors. 4 | 5 | # This file is part of 12to11. 6 | 7 | # 12to11 is free software: you can redistribute it and/or modify it 8 | # under the terms of the GNU General Public License as published by the 9 | # Free Software Foundation, either version 3 of the License, or (at your 10 | # option) any later version. 11 | 12 | # 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | # for more details. 16 | 17 | # You should have received a copy of the GNU General Public License 18 | # along with 12to11. If not, see . 19 | 20 | BEGIN { 21 | print "#define DirectTransferAtomNames \\" 22 | } 23 | 24 | / ([a-z]+\/[-+.[:alnum:]]+) / { # Leave 2 spaces before and 1 space after 25 | match ($0, / ([a-z]+\/[-+.[:alnum:]]+) /, array) 26 | printf " \"%s\",\\\n", array[1] 27 | } 28 | 29 | END { 30 | printf "\n" 31 | } 32 | -------------------------------------------------------------------------------- /mime0.awk: -------------------------------------------------------------------------------- 1 | # Wayland compositor running on top of an X server. 2 | 3 | # Copyright (C) 2022 to various contributors. 4 | 5 | # This file is part of 12to11. 6 | 7 | # 12to11 is free software: you can redistribute it and/or modify it 8 | # under the terms of the GNU General Public License as published by the 9 | # Free Software Foundation, either version 3 of the License, or (at your 10 | # option) any later version. 11 | 12 | # 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | # for more details. 16 | 17 | # You should have received a copy of the GNU General Public License 18 | # along with 12to11. If not, see . 19 | 20 | BEGIN { 21 | print "/* Automatically generated file. Do not edit! */" 22 | print "#define DirectTransferMappings \\" 23 | } 24 | 25 | / ([a-z]+\/[-+.[:alnum:]]+) / { # Leave 2 spaces before and 1 space after 26 | match ($0, / ([a-z]+\/[-+.[:alnum:]]+) /, array) 27 | printf " { 0, \"%s\"},\\\n", array[1] 28 | } 29 | 30 | END { 31 | printf "\n" 32 | } 33 | -------------------------------------------------------------------------------- /mime4.awk: -------------------------------------------------------------------------------- 1 | # Wayland compositor running on top of an X server. 2 | 3 | # Copyright (C) 2022 to various contributors. 4 | 5 | # This file is part of 12to11. 6 | 7 | # 12to11 is free software: you can redistribute it and/or modify it 8 | # under the terms of the GNU General Public License as published by the 9 | # Free Software Foundation, either version 3 of the License, or (at your 10 | # option) any later version. 11 | 12 | # 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | # for more details. 16 | 17 | # You should have received a copy of the GNU General Public License 18 | # along with 12to11. If not, see . 19 | 20 | BEGIN { 21 | print "#define DirectTransferAtoms \\" 22 | } 23 | 24 | / ([a-z]+\/[-+.[:alnum:]]+) / { # Leave 2 spaces before and 1 space after 25 | match ($0, / ([a-z]+\/[-+.[:alnum:]]+) /, array) 26 | name = array[1] 27 | gsub (/[[:punct:]]/, "_", name) # Convert to a valid atom name 28 | printf " %s, \\\n", name 29 | } 30 | 31 | END { 32 | print " dummy_atom" 33 | } 34 | -------------------------------------------------------------------------------- /mime3.awk: -------------------------------------------------------------------------------- 1 | # Wayland compositor running on top of an X server. 2 | 3 | # Copyright (C) 2022 to various contributors. 4 | 5 | # This file is part of 12to11. 6 | 7 | # 12to11 is free software: you can redistribute it and/or modify it 8 | # under the terms of the GNU General Public License as published by the 9 | # Free Software Foundation, either version 3 of the License, or (at your 10 | # option) any later version. 11 | 12 | # 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | # for more details. 16 | 17 | # You should have received a copy of the GNU General Public License 18 | # along with 12to11. If not, see . 19 | 20 | BEGIN { 21 | print "#define DirectTransferAtomInit(list, base) \\" 22 | i = 0 23 | } 24 | 25 | / ([a-z]+\/[-+.[:alnum:]]+) / { # Leave 2 spaces before and 1 space after 26 | match ($0, / ([a-z]+\/[-+.[:alnum:]]+) /, array) 27 | name = array[1] 28 | gsub (/[[:punct:]]/, "_", name) # Convert to a valid atom name 29 | printf " %s = list[base + %d];\\\n", name, i++ 30 | } 31 | 32 | END { 33 | printf "\n" 34 | } 35 | -------------------------------------------------------------------------------- /mime1.awk: -------------------------------------------------------------------------------- 1 | # Wayland compositor running on top of an X server. 2 | 3 | # Copyright (C) 2022 to various contributors. 4 | 5 | # This file is part of 12to11. 6 | 7 | # 12to11 is free software: you can redistribute it and/or modify it 8 | # under the terms of the GNU General Public License as published by the 9 | # Free Software Foundation, either version 3 of the License, or (at your 10 | # option) any later version. 11 | 12 | # 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | # for more details. 16 | 17 | # You should have received a copy of the GNU General Public License 18 | # along with 12to11. If not, see . 19 | 20 | BEGIN { 21 | print "#define DirectTransferInitializer(table, start) \\" 22 | i = 0 23 | } 24 | 25 | / ([a-z]+\/[-+.[:alnum:]]+) / { # Leave 2 spaces before and 1 space after 26 | match ($0, / ([a-z]+\/[-+.[:alnum:]]+) /, array) 27 | name = array[1] 28 | gsub (/[[:punct:]]/, "_", name) # Convert to a valid atom name 29 | printf " table[%d + start].atom_flag = %s;\\\n", i++, name 30 | } 31 | 32 | END { 33 | printf "\n" 34 | } 35 | -------------------------------------------------------------------------------- /modifiers.awk: -------------------------------------------------------------------------------- 1 | # Wayland compositor running on top of an X serer. 2 | 3 | # Copyright (C) 2022 to various contributors. 4 | 5 | # This file is part of 12to11. 6 | 7 | # 12to11 is free software: you can redistribute it and/or modify it 8 | # under the terms of the GNU General Public License as published by the 9 | # Free Software Foundation, either version 3 of the License, or (at your 10 | # option) any later version. 11 | 12 | # 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | # for more details. 16 | 17 | # You should have received a copy of the GNU General Public License 18 | # along with 12to11. If not, see . 19 | 20 | BEGIN { 21 | print "#define DrmModifiersList \\" 22 | }; 23 | 24 | /^#define[[:space:]]+(I915|DRM)_FORMAT_MOD_[[:alnum:]_]+[[:space:]]+fourcc_mod_code(.*)$/ { 25 | printf (" { \"%s\", %s }, \\\n", $2, $2); 26 | } 27 | 28 | /^#define[[:space:]]+AMD_FMT_MOD_[[:alnum:]_]+[[:space:]]+(0x[[:xdigit:]]+|[:digit:]+)$/ { 29 | printf (" { \"%s\", %s | AMD_FMT_MOD }, \\\n", $2, $2); 30 | } 31 | 32 | END { 33 | printf (" { NULL, 0 },\n"); 34 | } 35 | 36 | # Broadcom, ARM, etc modifiers not supported! Patches welcome. 37 | -------------------------------------------------------------------------------- /tests/README: -------------------------------------------------------------------------------- 1 | This directory holds some work-in-progress code for testing the 2 | protocol translator. The current test suite is nowhere near 3 | comprehensive. 4 | 5 | Each test must be individually run on a system with an a8r8g8b8 6 | visual, GLOBAL_SCALE and OUTPUT_SCALE set to 1. They also rely on 7 | reference data; if some legitimate changes are made that affect test 8 | results, then the tests should be run with TEST_WRITE_REFERENCE=1, 9 | which will make the test binaries write out reference data to disk. 10 | 11 | When tests are being run, the tester must be very careful to not 12 | interfere with the test operation by moving or resizing the test 13 | window. A compositing manager should be running along with the test. 14 | 15 | These tests are supposed to test the functionality of the protocol 16 | translator by connecting to a running instance and validating the 17 | results of various high-level requests. In modern parlance, they 18 | would be ``integration tests''. 19 | 20 | Most likely, you do not want to run these tests manually, as the 21 | `run_tests.sh' script does all the setup for you. 22 | 23 | Please note that the EGL renderer currently does not pass some 24 | graphics tests, which is expected behavior, and that `select_test' 25 | must be run with no clipboard manager (or any other clients, for that 26 | matter) running. 27 | -------------------------------------------------------------------------------- /shaders.awk: -------------------------------------------------------------------------------- 1 | # Wayland compositor running on top of an X serer. 2 | 3 | # Copyright (C) 2022 to various contributors. 4 | 5 | # This file is part of 12to11. 6 | 7 | # 12to11 is free software: you can redistribute it and/or modify it 8 | # under the terms of the GNU General Public License as published by the 9 | # Free Software Foundation, either version 3 of the License, or (at your 10 | # option) any later version. 11 | 12 | # 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | # for more details. 16 | 17 | # You should have received a copy of the GNU General Public License 18 | # along with 12to11. If not, see . 19 | 20 | /^\/\/==/ { 21 | if (in_program) 22 | { 23 | in_program = 0; 24 | print ";" 25 | } 26 | else 27 | { 28 | match ($0, /^\/\/== ([[:alnum:] ]+)/, array) 29 | in_program = ignore_line = 1; 30 | 31 | # Start a new shader; first, escape the name by replacing white 32 | # space with underscores. 33 | gsub (/[[:space:]]/, "_", array[1]) 34 | 35 | # Next, make everything lowercase. 36 | array[1] = tolower (array[1]); 37 | 38 | printf "static const char *%s =\n", array[1] 39 | } 40 | } 41 | 42 | { 43 | if (ignore_line) 44 | ignore_line = 0; 45 | else if (in_program) 46 | { 47 | # Escape characters that can occur in regular GLSL programs but 48 | # must be escaped in C strings. 49 | string = $0 50 | gsub (/[\\"]/, "\\\\&", string) 51 | printf " \"%s\\n\"\n", string 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /compositor.c: -------------------------------------------------------------------------------- 1 | /* Wayland compositor running on top of an X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include "compositor.h" 21 | 22 | /* The compositor global. */ 23 | static struct wl_global *global_compositor; 24 | 25 | static void 26 | CreateSurface (struct wl_client *client, 27 | struct wl_resource *resource, 28 | uint32_t id) 29 | { 30 | XLCreateSurface (client, resource, id); 31 | } 32 | 33 | static void 34 | CreateRegion (struct wl_client *client, 35 | struct wl_resource *resource, 36 | uint32_t id) 37 | { 38 | XLCreateRegion (client, resource, id); 39 | } 40 | 41 | static const struct wl_compositor_interface wl_compositor_impl = 42 | { 43 | .create_surface = CreateSurface, 44 | .create_region = CreateRegion, 45 | }; 46 | 47 | static void 48 | HandleBind (struct wl_client *client, void *data, 49 | uint32_t version, uint32_t id) 50 | { 51 | struct wl_resource *resource; 52 | 53 | resource = wl_resource_create (client, &wl_compositor_interface, 54 | version, id); 55 | 56 | if (!resource) 57 | { 58 | wl_client_post_no_memory (client); 59 | return; 60 | } 61 | 62 | wl_resource_set_implementation (resource, &wl_compositor_impl, 63 | NULL, NULL); 64 | } 65 | 66 | void 67 | XLInitCompositor (void) 68 | { 69 | global_compositor 70 | = wl_global_create (compositor.wl_display, 71 | &wl_compositor_interface, 72 | 5, NULL, HandleBind); 73 | } 74 | -------------------------------------------------------------------------------- /decoration.c: -------------------------------------------------------------------------------- 1 | /* Wayland compositor running on top of an X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include "compositor.h" 21 | #include "xdg-decoration-unstable-v1.h" 22 | 23 | /* The xdg_decoration_manager_v1 global. */ 24 | static struct wl_global *decoration_manager_global; 25 | 26 | static void 27 | Destroy (struct wl_client *client, struct wl_resource *resource) 28 | { 29 | wl_resource_destroy (resource); 30 | } 31 | 32 | static void 33 | GetToplevelDecoration (struct wl_client *client, struct wl_resource *resource, 34 | uint32_t id, struct wl_resource *toplevel_resource) 35 | { 36 | XdgRoleImplementation *impl; 37 | 38 | impl = wl_resource_get_user_data (toplevel_resource); 39 | XLXdgToplevelGetDecoration (impl, resource, id); 40 | } 41 | 42 | static const struct zxdg_decoration_manager_v1_interface manager_impl = 43 | { 44 | .destroy = Destroy, 45 | .get_toplevel_decoration = GetToplevelDecoration, 46 | }; 47 | 48 | static void 49 | HandleBind (struct wl_client *client, void *data, uint32_t version, 50 | uint32_t id) 51 | { 52 | struct wl_resource *resource; 53 | 54 | resource 55 | = wl_resource_create (client, 56 | &zxdg_decoration_manager_v1_interface, 57 | version, id); 58 | 59 | if (!resource) 60 | { 61 | wl_client_post_no_memory (client); 62 | return; 63 | } 64 | 65 | wl_resource_set_implementation (resource, &manager_impl, NULL, NULL); 66 | } 67 | 68 | void 69 | XLInitDecoration (void) 70 | { 71 | decoration_manager_global 72 | = wl_global_create (compositor.wl_display, 73 | &zxdg_decoration_manager_v1_interface, 74 | 1, NULL, HandleBind); 75 | } 76 | -------------------------------------------------------------------------------- /tests/run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Tests for the Wayland compositor running on top of an X serer. 3 | 4 | # Copyright (C) 2022 to various contributors. 5 | 6 | # This file is part of 12to11. 7 | 8 | # 12to11 is free software: you can redistribute it and/or modify it 9 | # under the terms of the GNU General Public License as published by the 10 | # Free Software Foundation, either version 3 of the License, or (at your 11 | # option) any later version. 12 | 13 | # 12to11 is distributed in the hope that it will be useful, but WITHOUT 14 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 | # for more details. 17 | 18 | # You should have received a copy of the GNU General Public License 19 | # along with 12to11. If not, see . 20 | 21 | pushd "$(dirname $0)" 22 | declare -a standard_tests=( 23 | simple_test damage_test transform_test viewporter_test 24 | subsurface_test scale_test seat_test dmabuf_test 25 | xdg_activation_test single_pixel_buffer_test buffer_test 26 | tearing_control_test 27 | ) 28 | 29 | make -C . "${standard_tests[@]}" 30 | 31 | export GLOBAL_SCALE=1 32 | export OUTPUT_SCALE=1 33 | exec 3< <(stdbuf -oL ../12to11 -printsocket) 34 | read -u 3 WAYLAND_DISPLAY 35 | export WAYLAND_DISPLAY 36 | 37 | echo "Compositor started at ${WAYLAND_DISPLAY}" 38 | 39 | for test_executable in "${standard_tests[@]}" 40 | do 41 | echo "Running test ${test_executable}" 42 | 43 | if ./${test_executable}; then 44 | echo "${test_executable} completed successfully" 45 | else 46 | echo "${test_executable} failed; see its output for more details" 47 | fi 48 | done 49 | 50 | echo "Starting Xvfb at :27" 51 | 52 | Xvfb :27 & 53 | sleep 1 54 | exec 4< <(DISPLAY=:27 stdbuf -oL ../12to11 -printsocket) 55 | read -u 4 WAYLAND_DISPLAY 56 | export WAYLAND_DISPLAY 57 | 58 | declare -a vfb_tests=( 59 | select_test 60 | ) 61 | 62 | make -C . "${vfb_tests[@]}" select_helper select_helper_multiple 63 | 64 | echo "Compositor for vfb tests started at ${WAYLAND_DISPLAY}" 65 | 66 | for test_executable in "${vfb_tests[@]}" 67 | do 68 | echo "Running test ${test_executable}" 69 | 70 | if ./${test_executable}; then 71 | echo "${test_executable} completed successfully" 72 | else 73 | echo "${test_executable} failed; see its output for more details" 74 | fi 75 | done 76 | 77 | popd 78 | 79 | trap 'jobs -p | xargs kill' EXIT 80 | -------------------------------------------------------------------------------- /alloc.c: -------------------------------------------------------------------------------- 1 | /* Wayland compositor running on top of an X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "compositor.h" 26 | 27 | void * 28 | XLMalloc (size_t size) 29 | { 30 | void *ptr; 31 | 32 | ptr = malloc (size); 33 | 34 | if (!ptr && size) 35 | { 36 | fprintf (stderr, "Allocation of %zu bytes failed\n", 37 | size); 38 | abort (); 39 | } 40 | 41 | return ptr; 42 | } 43 | 44 | void * 45 | XLSafeMalloc (size_t size) 46 | { 47 | return malloc (size); 48 | } 49 | 50 | void * 51 | XLCalloc (size_t nmemb, size_t size) 52 | { 53 | void *ptr; 54 | 55 | ptr = calloc (nmemb, size); 56 | 57 | if (!ptr && nmemb && size) 58 | { 59 | fprintf (stderr, "Allocation of %zu * %zu failed\n", 60 | nmemb, size); 61 | abort (); 62 | } 63 | 64 | return ptr; 65 | } 66 | 67 | void 68 | XLFree (void *ptr) 69 | { 70 | if (ptr) 71 | free (ptr); 72 | } 73 | 74 | char * 75 | XLStrdup (const char *data) 76 | { 77 | char *string; 78 | 79 | string = strdup (data); 80 | 81 | if (!string) 82 | { 83 | fprintf (stderr, "Allocation of %zu bytes failed\n", 84 | strlen (data)); 85 | abort (); 86 | } 87 | 88 | return string; 89 | } 90 | 91 | void * 92 | XLRealloc (void *ptr, size_t size) 93 | { 94 | if (!ptr) 95 | return XLMalloc (size); 96 | 97 | ptr = realloc (ptr, size); 98 | 99 | if (size && !ptr) 100 | { 101 | fprintf (stderr, "Reallocation of %zu bytes failed\n", size); 102 | abort (); 103 | } 104 | 105 | /* Allow realloc to return NULL if size is also NULL. */ 106 | 107 | return ptr; 108 | } 109 | -------------------------------------------------------------------------------- /region.c: -------------------------------------------------------------------------------- 1 | /* Wayland compositor running on top of an X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include 21 | 22 | #include 23 | 24 | #include "compositor.h" 25 | 26 | static void 27 | DestroyRegion (struct wl_client *client, struct wl_resource *resource) 28 | { 29 | wl_resource_destroy (resource); 30 | } 31 | 32 | static void 33 | SubtractRegion (struct wl_client *client, struct wl_resource *resource, 34 | int32_t x, int32_t y, int32_t width, int32_t height) 35 | { 36 | pixman_region32_t *region, operand; 37 | 38 | region = wl_resource_get_user_data (resource); 39 | pixman_region32_init_rect (&operand, x, y, width, height); 40 | pixman_region32_subtract (region, region, &operand); 41 | } 42 | 43 | static void 44 | AddRegion (struct wl_client *client, struct wl_resource *resource, 45 | int32_t x, int32_t y, int32_t width, int32_t height) 46 | { 47 | pixman_region32_t *region, operand; 48 | 49 | region = wl_resource_get_user_data (resource); 50 | pixman_region32_init_rect (&operand, x, y, width, height); 51 | pixman_region32_union (region, region, &operand); 52 | } 53 | 54 | static const struct wl_region_interface wl_region_impl = 55 | { 56 | .destroy = DestroyRegion, 57 | .subtract = SubtractRegion, 58 | .add = AddRegion 59 | }; 60 | 61 | static void 62 | HandleResourceDestroy (struct wl_resource *resource) 63 | { 64 | pixman_region32_t *region; 65 | 66 | region = wl_resource_get_user_data (resource); 67 | pixman_region32_fini (region); 68 | XLFree (region); 69 | } 70 | 71 | void 72 | XLCreateRegion (struct wl_client *client, 73 | struct wl_resource *resource, 74 | uint32_t id) 75 | { 76 | pixman_region32_t *region; 77 | struct wl_resource *region_resource; 78 | 79 | region = XLSafeMalloc (sizeof *region); 80 | 81 | if (!region) 82 | { 83 | wl_resource_post_no_memory (resource); 84 | return; 85 | } 86 | 87 | region_resource 88 | = wl_resource_create (client, &wl_region_interface, 89 | wl_resource_get_version (resource), 90 | id); 91 | 92 | if (!resource) 93 | { 94 | wl_resource_post_no_memory (resource); 95 | XLFree (region); 96 | 97 | return; 98 | } 99 | 100 | pixman_region32_init (region); 101 | wl_resource_set_implementation (region_resource, 102 | &wl_region_impl, 103 | region, 104 | HandleResourceDestroy); 105 | } 106 | -------------------------------------------------------------------------------- /fence_ring.c: -------------------------------------------------------------------------------- 1 | /* Wayland compositor running on top of an X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include 21 | 22 | #include 23 | 24 | #include "compositor.h" 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | struct _Fence 32 | { 33 | /* The xshmfence. */ 34 | struct xshmfence *fence; 35 | 36 | /* The sync fence. */ 37 | XSyncFence fence_id; 38 | 39 | /* The number of references to this fence. Incremented by 40 | FenceRetain, decremented by FenceRelease. */ 41 | int refcount; 42 | }; 43 | 44 | Fence * 45 | GetFence (void) 46 | { 47 | Fence *fence; 48 | int fd; 49 | Window drawable; 50 | 51 | drawable = DefaultRootWindow (compositor.display); 52 | 53 | /* Allocate a new fence. */ 54 | fence = XLCalloc (1, sizeof *fence); 55 | fd = xshmfence_alloc_shm (); 56 | 57 | if (fd < 0) 58 | { 59 | perror ("xshmfence_alloc_shm"); 60 | abort (); 61 | } 62 | 63 | /* Map it. */ 64 | fence->fence = xshmfence_map_shm (fd); 65 | 66 | if (!fence->fence) 67 | { 68 | perror ("xshmfence_map_shm"); 69 | abort (); 70 | } 71 | 72 | /* Upload the fence to the X server. XCB will close the file 73 | descriptor. */ 74 | fence->fence_id = xcb_generate_id (compositor.conn); 75 | 76 | /* Make the file descriptor CLOEXEC, since it isn't closed 77 | immediately. */ 78 | XLAddFdFlag (fd, FD_CLOEXEC, False); 79 | xcb_dri3_fence_from_fd (compositor.conn, drawable, 80 | fence->fence_id, 0, fd); 81 | 82 | /* Retain the fence. */ 83 | FenceRetain (fence); 84 | 85 | /* Return the fence. */ 86 | return fence; 87 | } 88 | 89 | void 90 | FenceAwait (Fence *fence) 91 | { 92 | /* Wait for the fence to be triggered. */ 93 | xshmfence_await (fence->fence); 94 | 95 | /* Reset the fence. */ 96 | xshmfence_reset (fence->fence); 97 | } 98 | 99 | void 100 | FenceRelease (Fence *fence) 101 | { 102 | if (--fence->refcount) 103 | return; 104 | 105 | /* Unmap the fence. */ 106 | xshmfence_unmap_shm (fence->fence); 107 | 108 | /* Destroy the fence. */ 109 | XSyncDestroyFence (compositor.display, fence->fence_id); 110 | 111 | /* Free the fence. */ 112 | XLFree (fence); 113 | } 114 | 115 | void 116 | FenceRetain (Fence *fence) 117 | { 118 | fence->refcount++; 119 | } 120 | 121 | XSyncFence 122 | FenceToXFence (Fence *fence) 123 | { 124 | return fence->fence_id; 125 | } 126 | -------------------------------------------------------------------------------- /shaders.txt: -------------------------------------------------------------------------------- 1 | // -*- glsl -*- 2 | 3 | // File containing GLSL shaders used to generate shaders.h. 4 | 5 | // At the start of each shader, write // followed by two equals signs, 6 | // followed by a space, the name of the shader and a newline. 7 | // Following that, write the shader code. 8 | 9 | // To terminate a shader, write // followed by another two equals 10 | // signs, this time without a trailing name or whitespace. 11 | 12 | //== Clear Rectangle Vertex Shader 13 | attribute vec2 pos; 14 | 15 | void 16 | main (void) 17 | { 18 | gl_Position = vec4 (pos.x, pos.y, 1.0, 1.0); 19 | } 20 | //== 21 | 22 | //== Clear Rectangle Fragment Shader 23 | void 24 | main (void) 25 | { 26 | gl_FragColor = vec4 (0.0, 0.0, 0.0, 0.0); 27 | } 28 | //== 29 | 30 | //== Composite Rectangle Vertex Shader 31 | precision mediump float; 32 | attribute vec2 pos; 33 | attribute vec2 texcoord; 34 | varying vec2 v_texcoord; 35 | uniform mat3 source; 36 | 37 | void 38 | main (void) 39 | { 40 | gl_Position = vec4 (pos.x, pos.y, 1.0, 1.0); 41 | v_texcoord = (source * vec3 (texcoord, 1.0)).xy; 42 | } 43 | //== 44 | 45 | //== Composite Rectangle Fragment Shader RGBA 46 | precision mediump float; 47 | uniform sampler2D texture; 48 | uniform bool invert_y; 49 | varying vec2 v_texcoord; 50 | 51 | void 52 | main (void) 53 | { 54 | vec2 texcoord; 55 | 56 | texcoord = v_texcoord; 57 | 58 | if (invert_y) 59 | texcoord = vec2 (texcoord.x, 1.0 - texcoord.y); 60 | 61 | gl_FragColor = texture2D (texture, texcoord); 62 | } 63 | //== 64 | 65 | //== Composite Rectangle Fragment Shader RGBX 66 | precision mediump float; 67 | uniform sampler2D texture; 68 | uniform mat3 source; 69 | uniform bool invert_y; 70 | varying vec2 v_texcoord; 71 | 72 | void 73 | main (void) 74 | { 75 | vec2 texcoord; 76 | 77 | texcoord = v_texcoord; 78 | 79 | if (invert_y) 80 | texcoord = vec2 (texcoord.x, 1.0 - texcoord.y); 81 | 82 | gl_FragColor = vec4 (texture2D (texture, texcoord).rgb, 1.0); 83 | } 84 | //== 85 | 86 | //== Composite Rectangle Fragment Shader External 87 | #extension GL_OES_EGL_image_external : require 88 | 89 | precision mediump float; 90 | uniform samplerExternalOES texture; 91 | uniform mat3 source; 92 | uniform bool invert_y; 93 | varying vec2 v_texcoord; 94 | 95 | void 96 | main (void) 97 | { 98 | vec2 texcoord; 99 | 100 | texcoord = v_texcoord; 101 | 102 | if (invert_y) 103 | texcoord = vec2 (texcoord.x, 1.0 - texcoord.y); 104 | 105 | gl_FragColor = texture2D (texture, texcoord); 106 | } 107 | //== 108 | 109 | //== Composite Rectangle Fragment Shader Single Pixel 110 | #extension GL_OES_EGL_image_external : require 111 | 112 | precision mediump float; 113 | uniform vec4 source_color; 114 | uniform mat3 source; 115 | uniform bool invert_y; 116 | varying vec2 v_texcoord; 117 | 118 | void 119 | main (void) 120 | { 121 | vec2 texcoord; 122 | 123 | texcoord = v_texcoord; 124 | 125 | if (invert_y) 126 | texcoord = vec2 (texcoord.x, 1.0 - texcoord.y); 127 | 128 | if (texcoord.x < 0.0 || texcoord.y < 0.0 129 | || texcoord.x > 1.0 || texcoord.y > 1.0) 130 | gl_FragColor = vec4 (0.0, 0.0, 0.0, 0.0); 131 | else 132 | gl_FragColor = source_color; 133 | } 134 | //== 135 | -------------------------------------------------------------------------------- /buffer.c: -------------------------------------------------------------------------------- 1 | /* Wayland compositor running on top of an X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include 21 | 22 | #include "compositor.h" 23 | 24 | typedef struct _DestroyListener DestroyListener; 25 | 26 | struct _DestroyListener 27 | { 28 | /* Function to call. */ 29 | ExtBufferFunc func; 30 | 31 | /* User data. */ 32 | void *data; 33 | }; 34 | 35 | void 36 | XLRetainBuffer (ExtBuffer *buffer) 37 | { 38 | buffer->funcs.retain (buffer); 39 | } 40 | 41 | void 42 | XLDereferenceBuffer (ExtBuffer *buffer) 43 | { 44 | buffer->funcs.dereference (buffer); 45 | } 46 | 47 | RenderBuffer 48 | XLRenderBufferFromBuffer (ExtBuffer *buffer) 49 | { 50 | return buffer->funcs.get_buffer (buffer); 51 | } 52 | 53 | unsigned int 54 | XLBufferWidth (ExtBuffer *buffer) 55 | { 56 | return buffer->funcs.width (buffer); 57 | } 58 | 59 | unsigned int 60 | XLBufferHeight (ExtBuffer *buffer) 61 | { 62 | return buffer->funcs.height (buffer); 63 | } 64 | 65 | void 66 | XLReleaseBuffer (ExtBuffer *buffer) 67 | { 68 | buffer->funcs.release (buffer); 69 | } 70 | 71 | void * 72 | XLBufferRunOnFree (ExtBuffer *buffer, ExtBufferFunc func, 73 | void *data) 74 | { 75 | DestroyListener *listener; 76 | 77 | listener = XLMalloc (sizeof *listener); 78 | 79 | listener->func = func; 80 | listener->data = data; 81 | 82 | buffer->destroy_listeners 83 | = XLListPrepend (buffer->destroy_listeners, 84 | listener); 85 | 86 | return listener; 87 | } 88 | 89 | void 90 | XLBufferCancelRunOnFree (ExtBuffer *buffer, void *key) 91 | { 92 | buffer->destroy_listeners 93 | = XLListRemove (buffer->destroy_listeners, key); 94 | XLFree (key); 95 | } 96 | 97 | void 98 | XLPrintBuffer (ExtBuffer *buffer) 99 | { 100 | if (buffer->funcs.print_buffer) 101 | buffer->funcs.print_buffer (buffer); 102 | } 103 | 104 | void 105 | ExtBufferDestroy (ExtBuffer *buffer) 106 | { 107 | XLList *listener; 108 | DestroyListener *item; 109 | 110 | /* Now run every destroy listener connected to this buffer. */ 111 | for (listener = buffer->destroy_listeners; 112 | listener; listener = listener->next) 113 | { 114 | item = listener->data; 115 | 116 | item->func (buffer, item->data); 117 | } 118 | 119 | /* Free the label if present. */ 120 | XLFree (buffer->label); 121 | 122 | /* Not very efficient, since the list is followed through twice, but 123 | destroy listener lists should always be small. */ 124 | XLListFree (buffer->destroy_listeners, XLFree); 125 | } 126 | -------------------------------------------------------------------------------- /single-pixel-buffer-v1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Copyright © 2022 Simon Ser 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a 7 | copy of this software and associated documentation files (the "Software"), 8 | to deal in the Software without restriction, including without limitation 9 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | and/or sell copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice (including the next 14 | paragraph) shall be included in all copies or substantial portions of the 15 | Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | 25 | 26 | 27 | This protocol extension allows clients to create single-pixel buffers. 28 | 29 | Compositors supporting this protocol extension should also support the 30 | viewporter protocol extension. Clients may use viewporter to scale a 31 | single-pixel buffer to a desired size. 32 | 33 | Warning! The protocol described in this file is currently in the testing 34 | phase. Backward compatible changes may be added together with the 35 | corresponding interface version bump. Backward incompatible changes can 36 | only be done by creating a new major version of the extension. 37 | 38 | 39 | 40 | 41 | The wp_single_pixel_buffer_manager_v1 interface is a factory for 42 | single-pixel buffers. 43 | 44 | 45 | 46 | 47 | Destroy the wp_single_pixel_buffer_manager_v1 object. 48 | 49 | The child objects created via this interface are unaffected. 50 | 51 | 52 | 53 | 54 | 55 | Create a single-pixel buffer from four 32-bit RGBA values. 56 | 57 | Unless specified in another protocol extension, the RGBA values use 58 | pre-multiplied alpha. 59 | 60 | The width and height of the buffer are 1. 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /ewmh.c: -------------------------------------------------------------------------------- 1 | /* Wayland compositor running on top of an X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include "compositor.h" 21 | 22 | /* Array of supported atoms. Free this with XFree. */ 23 | static Atom *net_supported_atoms; 24 | 25 | /* Number of elements in that array. */ 26 | int n_supported_atoms; 27 | 28 | static Window 29 | GetWmCheckWindow (void) 30 | { 31 | Window result; 32 | unsigned char *tmp_data; 33 | int rc, actual_format; 34 | unsigned long actual_size, bytes_remaining; 35 | Atom actual_type; 36 | 37 | tmp_data = NULL; 38 | rc = XGetWindowProperty (compositor.display, 39 | DefaultRootWindow (compositor.display), 40 | _NET_SUPPORTING_WM_CHECK, 41 | 0, 1, False, XA_WINDOW, &actual_type, 42 | &actual_format, &actual_size, 43 | &bytes_remaining, &tmp_data); 44 | 45 | if (rc != Success || actual_type != XA_WINDOW 46 | || actual_format != 32 || actual_size != 1 47 | || !tmp_data) 48 | { 49 | if (tmp_data) 50 | XFree (tmp_data); 51 | 52 | return None; 53 | } 54 | 55 | result = *(Window *) tmp_data; 56 | XFree (tmp_data); 57 | 58 | return result; 59 | } 60 | 61 | static Bool 62 | IsValidWmCheckWindow (Window window) 63 | { 64 | CatchXErrors (); 65 | XSelectInput (compositor.display, window, 66 | SubstructureNotifyMask); 67 | return !UncatchXErrors (NULL); 68 | } 69 | 70 | Bool 71 | XLWmSupportsHint (Atom hint) 72 | { 73 | Window wm_check_window; 74 | Bool errors; 75 | unsigned char *tmp_data; 76 | int rc, actual_format, i; 77 | unsigned long actual_size, bytes_remaining; 78 | Atom actual_type; 79 | 80 | /* Window manager restarts are not handled here, since the rest of 81 | the code cannot cope with that. */ 82 | 83 | start_check: 84 | if (net_supported_atoms) 85 | { 86 | for (i = 0; i < n_supported_atoms; ++i) 87 | { 88 | if (net_supported_atoms[i] == hint) 89 | return True; 90 | } 91 | 92 | return False; 93 | } 94 | 95 | wm_check_window = GetWmCheckWindow (); 96 | 97 | if (!IsValidWmCheckWindow (wm_check_window)) 98 | return False; 99 | 100 | tmp_data = NULL; 101 | 102 | CatchXErrors (); 103 | rc = XGetWindowProperty (compositor.display, 104 | DefaultRootWindow (compositor.display), 105 | _NET_SUPPORTED, 0, 4096, False, XA_ATOM, 106 | &actual_type, &actual_format, &actual_size, 107 | &bytes_remaining, &tmp_data); 108 | errors = UncatchXErrors (NULL); 109 | 110 | if (rc != Success || actual_type != XA_ATOM || errors) 111 | { 112 | if (tmp_data) 113 | XFree (tmp_data); 114 | 115 | return False; 116 | } 117 | else 118 | { 119 | net_supported_atoms = (Atom *) tmp_data; 120 | n_supported_atoms = actual_size; 121 | 122 | goto start_check; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /relative_pointer.c: -------------------------------------------------------------------------------- 1 | /* Wayland compositor running on top of an X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include "compositor.h" 21 | #include "relative-pointer-unstable-v1.h" 22 | 23 | /* The zwp_relative_pointer_manager_v1 global. */ 24 | static struct wl_global *relative_pointer_manager_global; 25 | 26 | static void 27 | DestroyRelativePointer (struct wl_client *client, 28 | struct wl_resource *resource) 29 | { 30 | wl_resource_destroy (resource); 31 | } 32 | 33 | static struct zwp_relative_pointer_v1_interface relative_pointer_impl = 34 | { 35 | .destroy = DestroyRelativePointer, 36 | }; 37 | 38 | static void 39 | HandleRelativePointerResourceDestroy (struct wl_resource *resource) 40 | { 41 | RelativePointer *relative_pointer; 42 | 43 | relative_pointer = wl_resource_get_user_data (resource); 44 | XLSeatDestroyRelativePointer (relative_pointer); 45 | } 46 | 47 | 48 | 49 | static void 50 | Destroy (struct wl_client *client, struct wl_resource *resource) 51 | { 52 | wl_resource_destroy (resource); 53 | } 54 | 55 | static void 56 | GetRelativePointer (struct wl_client *client, struct wl_resource *resource, 57 | uint32_t id, struct wl_resource *pointer_resource) 58 | { 59 | struct wl_resource *relative_pointer_resource; 60 | Pointer *pointer; 61 | RelativePointer *relative_pointer; 62 | Seat *seat; 63 | 64 | pointer = wl_resource_get_user_data (pointer_resource); 65 | seat = XLPointerGetSeat (pointer); 66 | relative_pointer_resource 67 | = wl_resource_create (client, &zwp_relative_pointer_v1_interface, 68 | wl_resource_get_version (pointer_resource), 69 | id); 70 | 71 | if (!relative_pointer_resource) 72 | { 73 | wl_resource_post_no_memory (pointer_resource); 74 | return; 75 | } 76 | 77 | relative_pointer = XLSeatGetRelativePointer (seat, 78 | relative_pointer_resource); 79 | wl_resource_set_implementation (relative_pointer_resource, 80 | &relative_pointer_impl, relative_pointer, 81 | HandleRelativePointerResourceDestroy); 82 | } 83 | 84 | static const struct zwp_relative_pointer_manager_v1_interface manager_impl = 85 | { 86 | .destroy = Destroy, 87 | .get_relative_pointer = GetRelativePointer, 88 | }; 89 | 90 | static void 91 | HandleBind (struct wl_client *client, void *data, 92 | uint32_t version, uint32_t id) 93 | { 94 | struct wl_resource *resource; 95 | 96 | resource = wl_resource_create (client, 97 | &zwp_relative_pointer_manager_v1_interface, 98 | version, id); 99 | 100 | if (!resource) 101 | { 102 | wl_client_post_no_memory (client); 103 | return; 104 | } 105 | 106 | wl_resource_set_implementation (resource, &manager_impl, NULL, NULL); 107 | } 108 | 109 | void 110 | XLInitRelativePointer (void) 111 | { 112 | relative_pointer_manager_global 113 | = wl_global_create (compositor.wl_display, 114 | &zwp_relative_pointer_manager_v1_interface, 115 | 1, NULL, HandleBind); 116 | } 117 | 118 | void 119 | XLRelativePointerSendRelativeMotion (struct wl_resource *resource, 120 | uint64_t microsecond_time, double dx, 121 | double dy) 122 | { 123 | uint32_t time_hi, time_lo; 124 | 125 | time_hi = microsecond_time >> 32; 126 | time_lo = microsecond_time & 0xffffffff; 127 | 128 | zwp_relative_pointer_v1_send_relative_motion (resource, time_hi, time_lo, 129 | wl_fixed_from_double (dx), 130 | wl_fixed_from_double (dy), 131 | wl_fixed_from_double (dx), 132 | wl_fixed_from_double (dy)); 133 | } 134 | -------------------------------------------------------------------------------- /idle-inhibit-unstable-v1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright © 2015 Samsung Electronics Co., Ltd 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a 8 | copy of this software and associated documentation files (the "Software"), 9 | to deal in the Software without restriction, including without limitation 10 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | and/or sell copies of the Software, and to permit persons to whom the 12 | Software is furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice (including the next 15 | paragraph) shall be included in all copies or substantial portions of the 16 | Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 | DEALINGS IN THE SOFTWARE. 25 | 26 | 27 | 28 | 29 | This interface permits inhibiting the idle behavior such as screen 30 | blanking, locking, and screensaving. The client binds the idle manager 31 | globally, then creates idle-inhibitor objects for each surface. 32 | 33 | Warning! The protocol described in this file is experimental and 34 | backward incompatible changes may be made. Backward compatible changes 35 | may be added together with the corresponding interface version bump. 36 | Backward incompatible changes are done by bumping the version number in 37 | the protocol and interface names and resetting the interface version. 38 | Once the protocol is to be declared stable, the 'z' prefix and the 39 | version number in the protocol and interface names are removed and the 40 | interface version number is reset. 41 | 42 | 43 | 44 | 45 | Destroy the inhibit manager. 46 | 47 | 48 | 49 | 50 | 51 | Create a new inhibitor object associated with the given surface. 52 | 53 | 54 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | An idle inhibitor prevents the output that the associated surface is 63 | visible on from being set to a state where it is not visually usable due 64 | to lack of user interaction (e.g. blanked, dimmed, locked, set to power 65 | save, etc.) Any screensaver processes are also blocked from displaying. 66 | 67 | If the surface is destroyed, unmapped, becomes occluded, loses 68 | visibility, or otherwise becomes not visually relevant for the user, the 69 | idle inhibitor will not be honored by the compositor; if the surface 70 | subsequently regains visibility the inhibitor takes effect once again. 71 | Likewise, the inhibitor isn't honored if the system was already idled at 72 | the time the inhibitor was established, although if the system later 73 | de-idles and re-idles the inhibitor will take effect. 74 | 75 | 76 | 77 | 78 | Remove the inhibitor effect from the associated wl_surface. 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /buffer_release.c: -------------------------------------------------------------------------------- 1 | /* Wayland compositor running on top of an X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include "compositor.h" 21 | 22 | /* Simple helper code for managing buffer release in surfaces. */ 23 | 24 | typedef struct _ReleaseLaterRecord ReleaseLaterRecord; 25 | 26 | struct _ReleaseLaterRecord 27 | { 28 | /* A monotonically (overflow aside) increasing identifier. */ 29 | uint64_t id; 30 | 31 | /* The buffer that should be released upon receiving this 32 | message. */ 33 | ExtBuffer *buffer; 34 | 35 | /* The idle callback, if any. */ 36 | IdleCallbackKey key; 37 | 38 | /* The buffer release helper. */ 39 | BufferReleaseHelper *helper; 40 | 41 | /* The next and last records. */ 42 | ReleaseLaterRecord *next, *last; 43 | }; 44 | 45 | struct _BufferReleaseHelper 46 | { 47 | /* Queue of buffers pending release. */ 48 | ReleaseLaterRecord records; 49 | 50 | /* Callback run upon all buffers being released. */ 51 | AllReleasedCallback callback; 52 | 53 | /* Data for that callback. */ 54 | void *callback_data; 55 | }; 56 | 57 | BufferReleaseHelper * 58 | MakeBufferReleaseHelper (AllReleasedCallback callback, 59 | void *callback_data) 60 | { 61 | BufferReleaseHelper *helper; 62 | 63 | helper = XLCalloc (1, sizeof *helper); 64 | helper->records.next = &helper->records; 65 | helper->records.last = &helper->records; 66 | helper->callback = callback; 67 | helper->callback_data = callback_data; 68 | 69 | return helper; 70 | } 71 | 72 | void 73 | FreeBufferReleaseHelper (BufferReleaseHelper *helper) 74 | { 75 | ReleaseLaterRecord *next, *last; 76 | 77 | /* Do an XSync, and then release all the records. */ 78 | XSync (compositor.display, False); 79 | 80 | next = helper->records.next; 81 | while (next != &helper->records) 82 | { 83 | last = next; 84 | next = next->next; 85 | 86 | /* Cancel the idle callback if it already exists. */ 87 | if (last->key) 88 | RenderCancelIdleCallback (last->key); 89 | 90 | /* Release the buffer now. */ 91 | XLReleaseBuffer (last->buffer); 92 | 93 | /* Before freeing the record itself. */ 94 | XLFree (last); 95 | } 96 | 97 | /* Free the helper. */ 98 | XLFree (helper); 99 | } 100 | 101 | static void 102 | BufferIdleCallback (RenderBuffer buffer, void *data) 103 | { 104 | ReleaseLaterRecord *record; 105 | BufferReleaseHelper *helper; 106 | 107 | record = data; 108 | helper = record->helper; 109 | 110 | /* Release the buffer. */ 111 | XLReleaseBuffer (record->buffer); 112 | 113 | /* Unlink and free the record. */ 114 | record->next->last = record->last; 115 | record->last->next = record->next; 116 | XLFree (record); 117 | 118 | /* If there are no more records in the helper, run its 119 | all-released-callback. */ 120 | if (helper->records.next == &helper->records) 121 | helper->callback (helper->callback_data); 122 | } 123 | 124 | void 125 | ReleaseBufferWithHelper (BufferReleaseHelper *helper, ExtBuffer *buffer, 126 | RenderTarget target) 127 | { 128 | ReleaseLaterRecord *record; 129 | RenderBuffer render_buffer; 130 | 131 | render_buffer = XLRenderBufferFromBuffer (buffer); 132 | 133 | record = XLCalloc (1, sizeof *record); 134 | record->next = helper->records.next; 135 | record->last = &helper->records; 136 | helper->records.next->last = record; 137 | helper->records.next = record; 138 | 139 | /* Now, the record is linked into the list. Record the buffer and 140 | add an idle callback. */ 141 | record->buffer = buffer; 142 | record->key = RenderAddIdleCallback (render_buffer, target, 143 | BufferIdleCallback, 144 | record); 145 | record->helper = helper; 146 | } 147 | -------------------------------------------------------------------------------- /xdg_wm.c: -------------------------------------------------------------------------------- 1 | /* Wayland compositor running on top of an X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include 21 | 22 | #include "compositor.h" 23 | #include "xdg-shell.h" 24 | 25 | /* The xdg_wm_base global. */ 26 | static struct wl_global *global_xdg_wm_base; 27 | 28 | static void 29 | CreatePositioner (struct wl_client *client, struct wl_resource *resource, 30 | uint32_t id) 31 | { 32 | XLCreateXdgPositioner (client, resource, id); 33 | } 34 | 35 | static void 36 | GetXdgSurface (struct wl_client *client, struct wl_resource *resource, 37 | uint32_t id, struct wl_resource *surface_resource) 38 | { 39 | XLGetXdgSurface (client, resource, id, surface_resource); 40 | } 41 | 42 | static void 43 | Pong (struct wl_client *client, struct wl_resource *resource, 44 | uint32_t serial) 45 | { 46 | XdgWmBase *wm_base; 47 | XdgRoleList *role; 48 | 49 | /* Ping-pong implementation. Every time a ping request is received 50 | from the window manager, it is linked onto the list of all such 51 | requests on the toplevel. Then, ping is sent with a serial. 52 | Once the pong with the latest serial arrives from the client, 53 | pending requests are sent back to the window manager on all 54 | windows. */ 55 | wm_base = wl_resource_get_user_data (resource); 56 | 57 | if (serial == wm_base->last_ping) 58 | { 59 | /* Reply to the ping events sent to each surface created with 60 | this wm_base. */ 61 | role = wm_base->list.next; 62 | while (role != &wm_base->list) 63 | { 64 | XLXdgRoleReplyPing (role->role); 65 | role = role->next; 66 | } 67 | } 68 | } 69 | 70 | static void 71 | Destroy (struct wl_client *client, struct wl_resource *resource) 72 | { 73 | XdgWmBase *wm_base; 74 | 75 | /* If there are still xdg_surfaces created by this xdg_wm_base 76 | resource, post an error. */ 77 | wm_base = wl_resource_get_user_data (resource); 78 | 79 | if (wm_base->list.next != &wm_base->list) 80 | wl_resource_post_error (resource, XDG_WM_BASE_ERROR_DEFUNCT_SURFACES, 81 | "surfaces created by this xdg_wm_base still" 82 | " exist, yet it is being destroyed"); 83 | 84 | wl_resource_destroy (resource); 85 | } 86 | 87 | static const struct xdg_wm_base_interface xdg_wm_base_impl = 88 | { 89 | .destroy = Destroy, 90 | .create_positioner = CreatePositioner, 91 | .get_xdg_surface = GetXdgSurface, 92 | .pong = Pong, 93 | }; 94 | 95 | static void 96 | HandleResourceDestroy (struct wl_resource *resource) 97 | { 98 | XdgWmBase *wm_base; 99 | XdgRoleList *role, *last; 100 | 101 | wm_base = wl_resource_get_user_data (resource); 102 | 103 | /* Detach each surface. */ 104 | role = wm_base->list.next; 105 | while (role != &wm_base->list) 106 | { 107 | last = role; 108 | role = role->next; 109 | 110 | /* Complete all ping events. */ 111 | XLXdgRoleReplyPing (last->role); 112 | 113 | /* Tell the surface to not bother unlinking itself. */ 114 | last->next = NULL; 115 | last->last = NULL; 116 | last->role = NULL; 117 | } 118 | 119 | XLFree (wm_base); 120 | } 121 | 122 | static void 123 | HandleBind (struct wl_client *client, void *data, 124 | uint32_t version, uint32_t id) 125 | { 126 | XdgWmBase *wm_base; 127 | 128 | wm_base = XLSafeMalloc (sizeof *wm_base); 129 | 130 | if (!wm_base) 131 | { 132 | wl_client_post_no_memory (client); 133 | return; 134 | } 135 | 136 | memset (wm_base, 0, sizeof *wm_base); 137 | wm_base->resource 138 | = wl_resource_create (client, &xdg_wm_base_interface, 139 | version, id); 140 | 141 | if (!wm_base->resource) 142 | { 143 | XLFree (wm_base); 144 | wl_client_post_no_memory (client); 145 | return; 146 | } 147 | 148 | wl_resource_set_implementation (wm_base->resource, &xdg_wm_base_impl, 149 | wm_base, HandleResourceDestroy); 150 | wm_base->list.next = &wm_base->list; 151 | wm_base->list.last = &wm_base->list; 152 | } 153 | 154 | void 155 | XLInitXdgWM (void) 156 | { 157 | global_xdg_wm_base 158 | = wl_global_create (compositor.wl_display, 159 | &xdg_wm_base_interface, 160 | 5, NULL, HandleBind); 161 | } 162 | 163 | void 164 | XLXdgWmBaseSendPing (XdgWmBase *wm_base) 165 | { 166 | xdg_wm_base_send_ping (wm_base->resource, 167 | ++wm_base->last_ping); 168 | } 169 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This is a tool for running Wayland applications on an X server, 2 | preferably with a compositing manager running. 3 | 4 | It is not yet complete. What is not yet implemented includes support 5 | for touchscreens, and device switching in dmabuf feedback. 6 | 7 | It is not portable to systems other than recent versions of GNU/Linux 8 | running the X.Org server 1.20 or later, and has not been tested on 9 | window (and compositing) managers other than GNOME Shell. 10 | 11 | It will not work very well unless the compositing manager supports the 12 | EWMH frame synchronization protocol. 13 | 14 | Building and running this tool requires the following X protocol 15 | extensions: 16 | 17 | Nonrectangular Window Shape Extension, version 1.1 or later 18 | MIT Shared Memory Extension, version 1.2 or later 19 | X Resize, Rotate and Reflect Extension, version 1.4 or later 20 | X Synchronization Extension, version 1.0 or later 21 | X Rendering Extension, version 1.2 or later 22 | X Input Extension, version 2.3 or later 23 | Direct Rendering Interface 3, version 1.2 or later 24 | X Fixes Extension, version 1.5 or later 25 | X Presentation Extension, version 1.0 or later 26 | 27 | In addition, it requires Xlib to be built with the XCB transport, and 28 | the XCB bindings for MIT-SHM and DRI3 to be available. 29 | 30 | Sometimes, it might be desirable to build with EGL, and use OpenGL ES 31 | 2.0 for i.e. YUV video format support. To do so, uncomment the block 32 | of code for EGL support in 12to11.conf before running `xmkmf'. This 33 | will additionally require the EGL and GLESv2 development files, and 34 | for the following EGL and GLES extensions to be present at runtime: 35 | 36 | EGL_EXT_platform_base 37 | EGL_EXT_device_query 38 | EGL_KHR_image_base 39 | EGL_EXT_image_dma_buf_import_modifiers 40 | EGL_EXT_image_dma_buf_import 41 | EGL_EXT_buffer_age 42 | 43 | GL_OES_EGL_image 44 | GL_OES_EGL_image_external 45 | GL_EXT_read_format_bgra 46 | GL_EXT_unpack_subimage 47 | 48 | After building with EGL support, the renderer must be enabled by 49 | setting the environment variable "RENDERER" to "egl", or by setting 50 | the "renderer" resource (class "Renderer") to "egl". 51 | 52 | The following Wayland protocols are implemented to a more-or-less 53 | complete degree: 54 | 55 | 'wl_output', version: 4 56 | 'wl_compositor', version: 5 57 | 'wl_shm', version: 1 58 | 'xdg_wm_base', version: 5 59 | 'wl_subcompositor', version: 1 60 | 'wl_seat', version: 8 61 | 'wl_data_device_manager', version: 3 62 | 'zwp_linux_dmabuf_v1', version: 4 63 | 'zwp_primary_selection_device_manager_v1', version: 1 64 | 'wp_viewporter', version: 1 65 | 'zxdg_decoration_manager_v1', version: 1 66 | 'zwp_text_input_manager_v3', version: 1 67 | 'wp_single_pixel_buffer_manager_v1', version: 1 68 | 'zwp_pointer_constraints_v1', version: 1 69 | 'zwp_relative_pointer_manager_v1', version: 1 70 | 'zwp_idle_inhibit_manager_v1', version: 1 71 | 'xdg_activation_v1', version: 1 72 | 'wp_tearing_control_manager_v1', version: 1 73 | 74 | When built with EGL, the following Wayland protocol is also supported: 75 | 76 | 'zwp_linux_explicit_synchronization_v1', version: 2 77 | 78 | When the X server supports version 1.6 or later of the X Resize, 79 | Rotate and Reflect Extension, the following Wayland protocol is also 80 | supported: 81 | 82 | 'wp_drm_lease_device_v1', version: 1 83 | 84 | When the X server supports version 2.4 or later of the X Input 85 | Extension, the following Wayland protocol is also supported: 86 | 87 | 'zwp_pointer_gestures_v1', version: 3 88 | 89 | This directory is organized as follows: 90 | 91 | Imakefile - the top level Makefile template 92 | 12to11.conf - configuration 93 | *.xml - Wayland protocol definition source 94 | *.c, *.h - C source code 95 | *.awk - scripts used to generate headers 96 | *.txt - text data used to generate some headers, i.e. 97 | those containing MIME types or shaders 98 | 99 | Building the source code is simple, provided that you have the 100 | necessary libwayland-server library, pixman, XCB, DRM, xshmfence, and 101 | X extension libraries installed: 102 | 103 | xmkmf # to generate the Makefile 104 | make # to build the binary 105 | 106 | wayland-scanner is also required when building from the repository. 107 | 108 | Running the binary should be simple as well: 109 | 110 | ./12to11 111 | 112 | Wayland programs will then run as regular X windows. 113 | 114 | Be sure to configure your system so that idle inhibition is reported 115 | correctly. For more details, see the description of the 116 | idleInhibitCommand resource in the manual page. 117 | -------------------------------------------------------------------------------- /tests/imgview.c: -------------------------------------------------------------------------------- 1 | /* Tests for the Wayland compositor running on the X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include 21 | 22 | #include "test_harness.h" 23 | 24 | /* imgview -- simple viewer for .dump files. It opens each file as an 25 | argument and displays it in a window. */ 26 | 27 | /* The display imgview is connected to. */ 28 | static Display *display; 29 | 30 | /* The visual being used. */ 31 | static Visual *visual; 32 | 33 | /* Various image parameters. */ 34 | static int width, height, depth; 35 | 36 | static int 37 | get_depth_for_format (struct image_data_header *header) 38 | { 39 | switch (header->format) 40 | { 41 | case IMAGE_DATA_ARGB8888_LE: 42 | return 32; 43 | 44 | case IMAGE_DATA_XRGB8888_LE: 45 | return 24; 46 | } 47 | 48 | return 0; 49 | } 50 | 51 | static Visual * 52 | get_visual_for_format (struct image_data_header *header) 53 | { 54 | XVisualInfo template, *visuals; 55 | Visual *visual; 56 | unsigned long mask; 57 | int n_visuals; 58 | 59 | /* This isn't right if the pixel layout differs, but the program 60 | assumes that all 24-depth visuals are XRGB8888 and all 32-bit 61 | ones are ARGB8888. */ 62 | 63 | template.screen = DefaultScreen (display); 64 | template.class = TrueColor; 65 | 66 | switch (header->format) 67 | { 68 | case IMAGE_DATA_ARGB8888_LE: 69 | template.depth = 32; 70 | break; 71 | 72 | case IMAGE_DATA_XRGB8888_LE: 73 | template.depth = 24; 74 | break; 75 | } 76 | 77 | mask = VisualScreenMask | VisualDepthMask | VisualClassMask; 78 | visuals = XGetVisualInfo (display, mask, &template, &n_visuals); 79 | 80 | if (!n_visuals) 81 | { 82 | if (visuals) 83 | XFree (visuals); 84 | 85 | return NULL; 86 | } 87 | 88 | visual = visuals[0].visual; 89 | XFree (visuals); 90 | return visual; 91 | } 92 | 93 | static Pixmap 94 | get_image (const char *filename) 95 | { 96 | unsigned char *data; 97 | struct image_data_header header; 98 | XImage *image; 99 | Pixmap pixmap; 100 | GC gc; 101 | 102 | data = load_image_data (filename, &header); 103 | 104 | if (!data) 105 | return None; 106 | 107 | visual = get_visual_for_format (&header); 108 | depth = get_depth_for_format (&header); 109 | 110 | if (!depth || !visual) 111 | { 112 | free (data); 113 | return None; 114 | } 115 | 116 | image = XCreateImage (display, visual, depth, ZPixmap, 0, 117 | (char *) data, header.width, 118 | header.height, 8, header.stride); 119 | image->data = (char *) data; 120 | 121 | pixmap = XCreatePixmap (display, DefaultRootWindow (display), 122 | header.width, header.height, depth); 123 | gc = XCreateGC (display, pixmap, 0, NULL); 124 | 125 | /* Upload the image to the pixmap and free the GC. */ 126 | XPutImage (display, pixmap, gc, image, 0, 0, 127 | 0, 0, header.width, header.height); 128 | XFreeGC (display, gc); 129 | 130 | /* Destroy the XImage data. */ 131 | free (image->data); 132 | image->data = NULL; 133 | 134 | /* Destroy the XImage. */ 135 | XDestroyImage (image); 136 | 137 | /* Set image params. */ 138 | width = header.width; 139 | height = header.height; 140 | depth = depth; 141 | 142 | return pixmap; 143 | } 144 | 145 | static void 146 | loop_for_events (void) 147 | { 148 | XEvent event; 149 | 150 | while (true) 151 | XNextEvent (display, &event); 152 | } 153 | 154 | static void 155 | open_window (Pixmap image) 156 | { 157 | Window window; 158 | XSetWindowAttributes attrs; 159 | unsigned long flags; 160 | 161 | attrs.colormap = XCreateColormap (display, 162 | DefaultRootWindow (display), 163 | visual, AllocNone); 164 | /* This should be valid on any TrueColor visual. */ 165 | attrs.border_pixel = 0; 166 | attrs.background_pixmap = image; 167 | attrs.cursor = None; 168 | flags = (CWColormap | CWBorderPixel | CWBackPixmap | CWCursor); 169 | 170 | window = XCreateWindow (display, 171 | DefaultRootWindow (display), 172 | 0, 0, width, height, 0, depth, 173 | InputOutput, visual, flags, 174 | &attrs); 175 | XMapRaised (display, window); 176 | } 177 | 178 | int 179 | main (int argc, char **argv) 180 | { 181 | Pixmap image; 182 | int i; 183 | 184 | if (argc < 2) 185 | return 1; 186 | 187 | display = XOpenDisplay (NULL); 188 | 189 | if (!display) 190 | return 1; 191 | 192 | for (i = 1; i < argc; ++i) 193 | { 194 | image = get_image (argv[i]); 195 | 196 | if (!image) 197 | continue; 198 | 199 | open_window (image); 200 | } 201 | 202 | loop_for_events (); 203 | } 204 | -------------------------------------------------------------------------------- /tests/Imakefile: -------------------------------------------------------------------------------- 1 | #include "../12to11.conf" 2 | 3 | 12TO11ROOT = .. 4 | DEPLIBS = $(DEPXLIB) 5 | SYS_LIBRARIES = MathLibrary 6 | LOCAL_LIBRARIES = $(WAYLAND_CLIENT) $(XLIB) $(PNG) 7 | COMMONOBJS = test_harness.o 8 | COMMONSRCS = test_harness.c 9 | HEADER = test_harness.h 10 | GENFILES = 11 | EXTRA_DEFINES := -D_GNU_SOURCE -U_BSD_SOURCE -U_SVID_SOURCE 12 | INCLUDES := $(DRMINCLUDES) $(PIXMANINCLUDES) 13 | 14 | #define ScannerTarget(name) @@\ 15 | name.h: $(12TO11ROOT)/name.xml @@\ 16 | $(WAYLAND_SCANNER) client-header $< $@ @@\ 17 | @@\ 18 | name.c: $(12TO11ROOT)/name.xml name.h @@\ 19 | $(WAYLAND_SCANNER) private-code $< $@ @@\ 20 | @@\ 21 | COMMONOBJS := $(COMMONOBJS) name.o @@\ 22 | COMMONSRCS := $(COMMONSRCS) name.c @@\ 23 | GENFILES := $(GENFILES) name.c name.h @@\ 24 | HEADER := $(HEADER) name.h @@\ 25 | 26 | ScannerTarget(12to11-test) 27 | ScannerTarget(viewporter) 28 | ScannerTarget(linux-dmabuf-unstable-v1) 29 | ScannerTarget(xdg-activation-v1) 30 | ScannerTarget(single-pixel-buffer-v1) 31 | ScannerTarget(tearing-control-v1) 32 | 33 | /* Not actually a test. */ 34 | SRCS1 = $(COMMONSRCS) imgview.c 35 | OBJS1 = $(COMMONSRCS) imgview.o 36 | SRCS2 = $(COMMONSRCS) simple_test.c 37 | OBJS2 = $(COMMONOBJS) simple_test.o 38 | SRCS3 = $(COMMONSRCS) damage_test.c 39 | OBJS3 = $(COMMONOBJS) damage_test.o 40 | SRCS4 = $(COMMONSRCS) transform_test.c 41 | OBJS4 = $(COMMONSRCS) transform_test.o 42 | SRCS5 = $(COMMONSRCS) viewporter_test.c 43 | OBJS5 = $(COMMONSRCS) viewporter_test.o 44 | SRCS6 = $(COMMONSRCS) subsurface_test.c 45 | OBJS6 = $(COMMONSRCS) subsurface_test.o 46 | SRCS7 = $(COMMONSRCS) scale_test.c 47 | OBJS7 = $(COMMONSRCS) scale_test.o 48 | SRCS8 = $(COMMONSRCS) seat_test.c 49 | OBJS8 = $(COMMONSRCS) seat_test.o 50 | SRCS9 = $(COMMONSRCS) dmabuf_test.c 51 | OBJS9 = $(COMMONSRCS) dmabuf_test.o 52 | SRCS10 = $(COMMONSRCS) select_test.c 53 | OBJS10 = $(COMMONSRCS) select_test.o 54 | SRCS11 = select_helper.c 55 | OBJS11 = select_helper.o 56 | SRCS12 = select_helper_multiple.c 57 | OBJS12 = select_helper_multiple.o 58 | SRCS13 = $(COMMONSRCS) xdg_activation_test.c 59 | OBJS13 = $(COMMONSRCS) xdg_activation_test.o 60 | SRCS14 = $(COMMONSRCS) single_pixel_buffer_test.c 61 | OBJS14 = $(COMMONSRCS) single_pixel_buffer_test.o 62 | SRCS15 = $(COMMONSRCS) buffer_test.c 63 | OBJS15 = $(COMMONSRCS) buffer_test.o 64 | SRCS16 = $(COMMONSRCS) tearing_control_test.c 65 | OBJS16 = $(COMMONSRCS) tearing_control_test.o 66 | PROGRAMS = imgview simple_test damage_test transform_test viewporter_test subsurface_test scale_test seat_test dmabuf_test select_test select_helper select_helper_multiple xdg_activation_test single_pixel_buffer_test buffer_test tearing_control_test 67 | 68 | /* Make all objects depend on HEADER. */ 69 | $(OBJS1): $(HEADER) 70 | $(OBJS2): $(HEADER) 71 | $(OBJS3): $(HEADER) 72 | $(OBJS4): $(HEADER) 73 | $(OBJS5): $(HEADER) 74 | $(OBJS6): $(HEADER) 75 | $(OBJS7): $(HEADER) 76 | $(OBJS8): $(HEADER) 77 | $(OBJS9): $(HEADER) 78 | $(OBJS10): $(HEADER) 79 | $(OBJS13): $(HEADER) 80 | $(OBJS14): $(HEADER) 81 | $(OBJS15): $(HEADER) 82 | $(OBJS16): $(HEADER) 83 | 84 | /* And depend on all sources and headers. */ 85 | depend:: $(HEADER) $(COMMONSRCS) 86 | 87 | NormalProgramTarget(imgview,$(OBJS1),NullParameter,$(LOCAL_LIBRARIES),NullParameter) 88 | NormalProgramTarget(simple_test,$(OBJS2),NullParameter,$(LOCAL_LIBRARIES),NullParameter) 89 | NormalProgramTarget(damage_test,$(OBJS3),NullParameter,$(LOCAL_LIBRARIES),NullParameter) 90 | NormalProgramTarget(transform_test,$(OBJS4),NullParameter,$(LOCAL_LIBRARIES),NullParameter) 91 | NormalProgramTarget(viewporter_test,$(OBJS5),NullParameter,$(LOCAL_LIBRARIES),NullParameter) 92 | NormalProgramTarget(subsurface_test,$(OBJS6),NullParameter,$(LOCAL_LIBRARIES),NullParameter) 93 | NormalProgramTarget(scale_test,$(OBJS7),NullParameter,$(LOCAL_LIBRARIES),NullParameter) 94 | NormalProgramTarget(seat_test,$(OBJS8),NullParameter,$(LOCAL_LIBRARIES),NullParameter) 95 | NormalProgramTarget(dmabuf_test,$(OBJS9),NullParameter,$(LOCAL_LIBRARIES) $(GBM) $(DRM),NullParameter) 96 | NormalProgramTarget(select_test,$(OBJS10),NullParameter,$(LOCAL_LIBRARIES) ThreadsLibraries,NullParameter) 97 | NormalProgramTarget(select_helper,$(OBJS11),NullParameter,$(XLIB),NullParameter) 98 | NormalProgramTarget(select_helper_multiple,$(OBJS12),NullParameter,$(XLIB),NullParameter) 99 | NormalProgramTarget(xdg_activation_test,$(OBJS13),NullParameter,$(LOCAL_LIBRARIES),NullParameter) 100 | NormalProgramTarget(single_pixel_buffer_test,$(OBJS14),NullParameter,$(LOCAL_LIBRARIES),NullParameter) 101 | NormalProgramTarget(buffer_test,$(OBJS15),NullParameter,$(LOCAL_LIBRARIES),NullParameter) 102 | NormalProgramTarget(tearing_control_test,$(OBJS16),NullParameter,$(LOCAL_LIBRARIES),NullParameter) 103 | DependTarget3($(SRCS1),$(SRCS2),$(SRCS3)) 104 | DependTarget3($(SRCS4),$(SRCS5),$(SRCS6)) 105 | DependTarget3($(SRCS7),$(SRCS8),$(SRCS9)) 106 | DependTarget3($(SRCS10),$(SRCS11),$(SRCS12)) 107 | DependTarget3($(SRCS13),$(SRCS14),$(SRCS15)) 108 | DependTarget3($(SRCS16),NullParameter,NullParameter) 109 | 110 | all:: $(PROGRAMS) 111 | 112 | clean:: 113 | $(RM) $(GENFILES) 114 | -------------------------------------------------------------------------------- /tests/test_harness.h: -------------------------------------------------------------------------------- 1 | /* Tests for the Wayland compositor running on the X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | #include 32 | 33 | #include 34 | #include 35 | 36 | #include "12to11-test.h" 37 | 38 | struct test_seat 39 | { 40 | /* The test seat, if any. */ 41 | struct test_seat_controller *controller; 42 | 43 | /* The device manager, if any. */ 44 | struct test_device_controller *device_controller; 45 | 46 | /* The seat resource itself. */ 47 | struct wl_seat *seat; 48 | 49 | /* The wl_pointer resource. */ 50 | struct wl_pointer *pointer; 51 | 52 | /* The keyboard resource. */ 53 | struct wl_keyboard *keyboard; 54 | 55 | /* The device ID of the seat. */ 56 | uint32_t device_id; 57 | 58 | /* The buttons currently held down. */ 59 | unsigned char buttons; 60 | }; 61 | 62 | struct test_display 63 | { 64 | /* The wayland display. */ 65 | struct wl_display *display; 66 | 67 | /* The X display. */ 68 | Display *x_display; 69 | 70 | /* List of pixmap formats. */ 71 | XPixmapFormatValues *pixmap_formats; 72 | 73 | /* Number of pixmap formats. */ 74 | int num_pixmap_formats; 75 | 76 | /* The registry and various Wayland interfaces. */ 77 | struct wl_registry *registry; 78 | struct wl_compositor *compositor; 79 | struct wl_shm *shm; 80 | struct test_manager *test_manager; 81 | 82 | /* The test scale lock. */ 83 | struct test_scale_lock *scale_lock; 84 | 85 | /* Test interfaces. */ 86 | struct test_interface *interfaces; 87 | 88 | /* The test seat. */ 89 | struct test_seat *seat; 90 | 91 | /* The number of such interfaces. */ 92 | int num_test_interfaces; 93 | 94 | /* Internal field used by test_get_serial. */ 95 | uint32_t serial; 96 | }; 97 | 98 | struct test_interface 99 | { 100 | /* The name of the interface. */ 101 | const char *interface; 102 | 103 | /* Pointer to the interface data. */ 104 | void *data; 105 | 106 | /* Pointer to the interface. */ 107 | const struct wl_interface *c_interface; 108 | 109 | /* The wanted version. */ 110 | uint32_t version; 111 | }; 112 | 113 | struct test_buffer 114 | { 115 | /* The associated struct wl_buffer. */ 116 | struct wl_buffer *buffer; 117 | 118 | /* Whether or not the buffer is busy. */ 119 | int is_busy; 120 | }; 121 | 122 | struct image_data_header 123 | { 124 | /* Currently 1. High bit is byte order. */ 125 | unsigned char version; 126 | 127 | /* The data format. Currently always 0. */ 128 | unsigned char format; 129 | 130 | /* The width and height. */ 131 | unsigned short width, height; 132 | 133 | /* Padding. */ 134 | unsigned short pad1; 135 | 136 | /* The stride. */ 137 | unsigned int stride; 138 | }; 139 | 140 | enum image_data_format 141 | { 142 | /* Little-endian ARGB8888. */ 143 | IMAGE_DATA_ARGB8888_LE, 144 | /* Little-endian XRGB8888. */ 145 | IMAGE_DATA_XRGB8888_LE, 146 | }; 147 | 148 | extern void die (const char *) __attribute__ ((noreturn)); 149 | extern struct test_display *open_test_display (struct test_interface *, int); 150 | extern int get_shm_file_descriptor (void); 151 | extern size_t get_image_stride (struct test_display *, int, int); 152 | extern struct wl_buffer *upload_image_data (struct test_display *, 153 | const char *, int, int, 154 | int); 155 | extern void report_test_failure (const char *, ...) 156 | __attribute__ ((noreturn, format (gnu_printf, 1, 2))); 157 | extern void test_log (const char *, ...) 158 | __attribute__ ((format (gnu_printf, 1, 2))); 159 | 160 | extern bool make_test_surface (struct test_display *, struct wl_surface **, 161 | struct test_surface **); 162 | extern struct wl_buffer *load_png_image (struct test_display *, const char *); 163 | extern unsigned char *load_image_data (const char *, 164 | struct image_data_header *); 165 | extern void verify_image_data (struct test_display *, Window, const char *); 166 | extern void test_init (void); 167 | extern void test_complete (void) __attribute__ ((noreturn)); 168 | extern void test_set_scale (struct test_display *, int); 169 | extern void test_init_seat (struct test_display *); 170 | extern uint32_t test_get_serial (struct test_display *); 171 | extern void verify_window_size (struct test_display *, Window, int, int); 172 | extern struct test_buffer *get_test_buffer (struct test_display *, 173 | struct wl_buffer *); 174 | extern void test_buffer_committed (struct test_buffer *); 175 | extern void verify_buffer_released (struct test_buffer *); 176 | 177 | #define ARRAYELTS(arr) (sizeof (arr) / sizeof (arr)[0]) 178 | 179 | #if __GNUC__ >= 7 180 | #define FALLTHROUGH __attribute__ ((fallthrough)) 181 | #else 182 | #define FALLTHROUGH ((void) 0) 183 | #endif 184 | -------------------------------------------------------------------------------- /tests/select_helper.c: -------------------------------------------------------------------------------- 1 | /* Tests for the Wayland compositor running on the X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | /* select_helper.c -- Read the data of the clipboard selection and 29 | print them to stdout. 30 | 31 | There must be three arguments: the name of the display, the 32 | timestamp at which the selection was acquired, and the target. */ 33 | 34 | /* The display connected to. */ 35 | static Display *display; 36 | 37 | /* The selection transfer window. */ 38 | static Window selection_transfer_window; 39 | 40 | /* Various atoms. */ 41 | static Atom CLIPBOARD, target_atom, INCR; 42 | 43 | static void 44 | wait_for_selection_notify (XEvent *event) 45 | { 46 | while (true) 47 | { 48 | XNextEvent (display, event); 49 | 50 | if (event->type == SelectionNotify 51 | && (event->xselection.requestor 52 | == selection_transfer_window) 53 | && (event->xselection.selection 54 | == CLIPBOARD) 55 | && (event->xselection.property 56 | == target_atom) 57 | && (event->xselection.target 58 | == target_atom)) 59 | return; 60 | } 61 | } 62 | 63 | static void 64 | wait_for_new_value (XEvent *event, Atom property) 65 | { 66 | while (true) 67 | { 68 | XNextEvent (display, event); 69 | 70 | if (event->type == PropertyNotify 71 | && event->xproperty.atom == property 72 | && event->xproperty.state == PropertyNewValue) 73 | return; 74 | } 75 | } 76 | 77 | static size_t 78 | get_size_for_format (int format) 79 | { 80 | switch (format) 81 | { 82 | case 32: 83 | return sizeof (long); 84 | 85 | case 16: 86 | return sizeof (short int); 87 | 88 | case 8: 89 | return sizeof (char); 90 | } 91 | 92 | /* Should not actually happen. */ 93 | return 0; 94 | } 95 | 96 | int 97 | main (int argc, char **argv) 98 | { 99 | XSetWindowAttributes attrs; 100 | unsigned long flags, timestamp; 101 | char *atom_names[3]; 102 | Atom atoms[3], actual_type, property; 103 | XEvent event; 104 | int actual_format; 105 | unsigned long nitems, bytes_after; 106 | unsigned char *data; 107 | 108 | if (argc < 4) 109 | /* Not enough arguments were specified. */ 110 | return 1; 111 | 112 | display = XOpenDisplay (argv[1]); 113 | 114 | if (!display) 115 | return 1; 116 | 117 | /* Make the window used to transfer selection data. */ 118 | attrs.override_redirect = True; 119 | attrs.event_mask = PropertyChangeMask; 120 | flags = CWEventMask | CWOverrideRedirect; 121 | 122 | selection_transfer_window 123 | = XCreateWindow (display, DefaultRootWindow (display), 124 | -1, -1, 1, 1, 0, CopyFromParent, InputOnly, 125 | CopyFromParent, flags, &attrs); 126 | 127 | /* Get the time. */ 128 | timestamp = strtoul (argv[2], NULL, 10); 129 | 130 | atom_names[0] = argv[3]; 131 | atom_names[1] = (char *) "CLIPBOARD"; 132 | atom_names[2] = (char *) "INCR"; 133 | XInternAtoms (display, atom_names, 3, False, atoms); 134 | target_atom = atoms[0]; 135 | CLIPBOARD = atoms[1]; 136 | INCR = atoms[2]; 137 | 138 | /* Now ask for CLIPBOARD. */ 139 | XConvertSelection (display, CLIPBOARD, target_atom, 140 | target_atom, selection_transfer_window, 141 | timestamp); 142 | 143 | /* And wait for the SelectionNotify event. */ 144 | wait_for_selection_notify (&event); 145 | 146 | /* Selection conversion failed. */ 147 | if (event.xselection.property == None) 148 | return 1; 149 | 150 | property = event.xselection.property; 151 | 152 | XGetWindowProperty (display, selection_transfer_window, 153 | property, 0, 0xffffffff, True, AnyPropertyType, 154 | &actual_type, &actual_format, &nitems, &bytes_after, 155 | &data); 156 | 157 | if (!data || bytes_after) 158 | return 1; 159 | 160 | if (actual_type == INCR) 161 | { 162 | while (true) 163 | { 164 | XFree (data); 165 | 166 | wait_for_new_value (&event, property); 167 | XGetWindowProperty (display, selection_transfer_window, property, 0, 168 | 0xffffffff, True, AnyPropertyType, &actual_type, 169 | &actual_format, &nitems, &bytes_after, &data); 170 | 171 | if (!data) 172 | return 0; 173 | 174 | if (nitems) 175 | { 176 | /* Write the selection data to stdout. */ 177 | if (fwrite (data, get_size_for_format (actual_format), 178 | nitems, stdout) != nitems) 179 | return 1; 180 | 181 | continue; 182 | } 183 | 184 | /* Selection transfer is complete. */ 185 | fflush (stdout); 186 | return 0; 187 | } 188 | } 189 | else 190 | { 191 | /* Write the selection data to stdout. */ 192 | if (fwrite (data, get_size_for_format (actual_format), 193 | nitems, stdout) != nitems) 194 | return 1; 195 | 196 | /* Return success. */ 197 | fflush (stdout); 198 | return 0; 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /tearing-control-v1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Copyright © 2021 Xaver Hugl 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a 7 | copy of this software and associated documentation files (the "Software"), 8 | to deal in the Software without restriction, including without limitation 9 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | and/or sell copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice (including the next 14 | paragraph) shall be included in all copies or substantial portions of the 15 | Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | 25 | 26 | 27 | 28 | For some use cases like games or drawing tablets it can make sense to 29 | reduce latency by accepting tearing with the use of asynchronous page 30 | flips. This global is a factory interface, allowing clients to inform 31 | which type of presentation the content of their surfaces is suitable for. 32 | 33 | Graphics APIs like EGL or Vulkan, that manage the buffer queue and commits 34 | of a wl_surface themselves, are likely to be using this extension 35 | internally. If a client is using such an API for a wl_surface, it should 36 | not directly use this extension on that surface, to avoid raising a 37 | tearing_control_exists protocol error. 38 | 39 | Warning! The protocol described in this file is currently in the testing 40 | phase. Backward compatible changes may be added together with the 41 | corresponding interface version bump. Backward incompatible changes can 42 | only be done by creating a new major version of the extension. 43 | 44 | 45 | 46 | 47 | Destroy this tearing control factory object. Other objects, including 48 | wp_tearing_control_v1 objects created by this factory, are not affected 49 | by this request. 50 | 51 | 52 | 53 | 54 | 56 | 57 | 58 | 59 | 60 | Instantiate an interface extension for the given wl_surface to request 61 | asynchronous page flips for presentation. 62 | 63 | If the given wl_surface already has a wp_tearing_control_v1 object 64 | associated, the tearing_control_exists protocol error is raised. 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | An additional interface to a wl_surface object, which allows the client 74 | to hint to the compositor if the content on the surface is suitable for 75 | presentation with tearing. 76 | The default presentation hint is vsync. See presentation_hint for more 77 | details. 78 | 79 | 80 | 81 | 82 | This enum provides information for if submitted frames from the client 83 | may be presented with tearing. 84 | 85 | 86 | 87 | The content of this surface is meant to be synchronized to the 88 | vertical blanking period. This should not result in visible tearing 89 | and may result in a delay before a surface commit is presented. 90 | 91 | 92 | 93 | 94 | The content of this surface is meant to be presented with minimal 95 | latency and tearing is acceptable. 96 | 97 | 98 | 99 | 100 | 101 | 102 | Set the presentation hint for the associated wl_surface. This state is 103 | double-buffered and is applied on the next wl_surface.commit. 104 | 105 | The compositor is free to dynamically respect or ignore this hint based 106 | on various conditions like hardware capabilities, surface state and 107 | user preferences. 108 | 109 | 110 | 111 | 112 | 113 | 114 | Destroy this surface tearing object and revert the presentation hint to 115 | vsync. The change will be applied on the next wl_surface.commit. 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /tearing_control.c: -------------------------------------------------------------------------------- 1 | /* Wayland compositor running on top of an X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include 21 | 22 | #include "compositor.h" 23 | #include "tearing-control-v1.h" 24 | 25 | typedef struct _TearingControl TearingControl; 26 | 27 | struct _TearingControl 28 | { 29 | /* The associated surface. NULL when detached. */ 30 | Surface *surface; 31 | 32 | /* The associated resource. */ 33 | struct wl_resource *resource; 34 | }; 35 | 36 | /* The tearing control manager. */ 37 | static struct wl_global *tearing_control_manager_global; 38 | 39 | 40 | 41 | static void 42 | DestroyTearingControl (struct wl_client *client, struct wl_resource *resource) 43 | { 44 | TearingControl *control; 45 | 46 | control = wl_resource_get_user_data (resource); 47 | 48 | if (control->surface) 49 | { 50 | /* Reset the presentation hint. */ 51 | control->surface->pending_state.presentation_hint 52 | = PresentationHintVsync; 53 | control->surface->pending_state.pending 54 | |= PendingPresentationHint; 55 | } 56 | 57 | wl_resource_destroy (resource); 58 | } 59 | 60 | static void 61 | SetPresentationHint (struct wl_client *client, struct wl_resource *resource, 62 | uint32_t hint) 63 | { 64 | TearingControl *control; 65 | 66 | control = wl_resource_get_user_data (resource); 67 | 68 | if (control->surface) 69 | { 70 | switch (hint) 71 | { 72 | case WP_TEARING_CONTROL_V1_PRESENTATION_HINT_ASYNC: 73 | control->surface->pending_state.presentation_hint 74 | = PresentationHintAsync; 75 | break; 76 | 77 | default: 78 | control->surface->pending_state.presentation_hint 79 | = PresentationHintVsync; 80 | break; 81 | } 82 | 83 | control->surface->pending_state.pending |= PendingPresentationHint; 84 | } 85 | } 86 | 87 | static const struct wp_tearing_control_v1_interface control_impl = 88 | { 89 | .destroy = DestroyTearingControl, 90 | .set_presentation_hint = SetPresentationHint, 91 | }; 92 | 93 | static void 94 | HandleResourceDestroy (struct wl_resource *resource) 95 | { 96 | TearingControl *control, **reference; 97 | 98 | control = wl_resource_get_user_data (resource); 99 | 100 | /* If the surface is still attached to the tearing control, remove 101 | it from the surface. */ 102 | 103 | if (control->surface) 104 | { 105 | reference 106 | = XLSurfaceFindClientData (control->surface, 107 | TearingControlData); 108 | XLAssert (reference != NULL); 109 | 110 | *reference = NULL; 111 | } 112 | 113 | XLFree (control); 114 | } 115 | 116 | 117 | 118 | static void 119 | FreeTearingControlData (void *data) 120 | { 121 | TearingControl **control; 122 | 123 | control = data; 124 | 125 | if (!*control) 126 | return; 127 | 128 | /* Detach the surface from the tearing control. */ 129 | (*control)->surface = NULL; 130 | } 131 | 132 | static void 133 | Destroy (struct wl_client *client, struct wl_resource *resource) 134 | { 135 | wl_resource_destroy (resource); 136 | } 137 | 138 | static void 139 | GetTearingControl (struct wl_client *client, struct wl_resource *resource, 140 | uint32_t id, struct wl_resource *surface_resource) 141 | { 142 | Surface *surface; 143 | TearingControl **control; 144 | 145 | surface = wl_resource_get_user_data (surface_resource); 146 | control = XLSurfaceGetClientData (surface, TearingControlData, 147 | sizeof *control, 148 | FreeTearingControlData); 149 | 150 | #define ControlExists \ 151 | WP_TEARING_CONTROL_MANAGER_V1_ERROR_TEARING_CONTROL_EXISTS 152 | 153 | if (*control) 154 | { 155 | /* A tearing control resource already exists for this 156 | surface. */ 157 | wl_resource_post_error (resource, ControlExists, 158 | "a wp_tearing_control_v1 resource already exists" 159 | " for the specified surface"); 160 | return; 161 | } 162 | 163 | #undef ControlExists 164 | 165 | (*control) = XLCalloc (1, sizeof **control); 166 | (*control)->resource 167 | = wl_resource_create (client, 168 | &wp_tearing_control_v1_interface, 169 | wl_resource_get_version (resource), id); 170 | 171 | if (!(*control)->resource) 172 | { 173 | XLFree (*control); 174 | (*control) = NULL; 175 | 176 | wl_resource_post_no_memory (resource); 177 | return; 178 | } 179 | 180 | (*control)->surface = surface; 181 | wl_resource_set_implementation ((*control)->resource, &control_impl, 182 | (*control), HandleResourceDestroy); 183 | } 184 | 185 | static const struct wp_tearing_control_manager_v1_interface manager_impl = 186 | { 187 | .destroy = Destroy, 188 | .get_tearing_control = GetTearingControl, 189 | }; 190 | 191 | 192 | 193 | static void 194 | HandleBind (struct wl_client *client, void *data, 195 | uint32_t version, uint32_t id) 196 | { 197 | struct wl_resource *resource; 198 | 199 | resource = wl_resource_create (client, 200 | &wp_tearing_control_manager_v1_interface, 201 | version, id); 202 | 203 | if (!resource) 204 | { 205 | wl_client_post_no_memory (client); 206 | return; 207 | } 208 | 209 | wl_resource_set_implementation (resource, &manager_impl, 210 | NULL, NULL); 211 | } 212 | 213 | void 214 | XLInitTearingControl (void) 215 | { 216 | tearing_control_manager_global 217 | = wl_global_create (compositor.wl_display, 218 | &wp_tearing_control_manager_v1_interface, 219 | 1, NULL, HandleBind); 220 | } 221 | -------------------------------------------------------------------------------- /single_pixel_buffer.c: -------------------------------------------------------------------------------- 1 | /* Wayland compositor running on top of an X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include "compositor.h" 21 | #include "single-pixel-buffer-v1.h" 22 | #include "string.h" 23 | 24 | typedef struct _Buffer Buffer; 25 | 26 | struct _Buffer 27 | { 28 | /* The ExtBuffer associated with this buffer. */ 29 | ExtBuffer buffer; 30 | 31 | /* The rendering buffer associated with this buffer. */ 32 | RenderBuffer render_buffer; 33 | 34 | /* The wl_resource corresponding to this buffer. */ 35 | struct wl_resource *resource; 36 | 37 | /* The number of references to this buffer. */ 38 | int refcount; 39 | }; 40 | 41 | /* The global wp_single_pixel_buffer_manager_v1 resource. */ 42 | static struct wl_global *single_pixel_buffer_global; 43 | 44 | static void 45 | DestroyBuffer (struct wl_client *client, struct wl_resource *resource) 46 | { 47 | wl_resource_destroy (resource); 48 | } 49 | 50 | static const struct wl_buffer_interface single_pixel_buffer_impl = 51 | { 52 | .destroy = DestroyBuffer, 53 | }; 54 | 55 | static void 56 | RetainBuffer (Buffer *buffer) 57 | { 58 | buffer->refcount++; 59 | } 60 | 61 | static void 62 | DereferenceBuffer (Buffer *buffer) 63 | { 64 | if (--buffer->refcount) 65 | return; 66 | 67 | RenderFreeSinglePixelBuffer (buffer->render_buffer); 68 | ExtBufferDestroy (&buffer->buffer); 69 | XLFree (buffer); 70 | } 71 | 72 | static void 73 | ReleaseBufferFunc (ExtBuffer *buffer) 74 | { 75 | if (((Buffer *) buffer)->resource) 76 | wl_buffer_send_release (((Buffer *) buffer)->resource); 77 | } 78 | 79 | static void 80 | RetainBufferFunc (ExtBuffer *buffer) 81 | { 82 | RetainBuffer ((Buffer *) buffer); 83 | } 84 | 85 | static void 86 | DereferenceBufferFunc (ExtBuffer *buffer) 87 | { 88 | DereferenceBuffer ((Buffer *) buffer); 89 | } 90 | 91 | static RenderBuffer 92 | GetBufferFunc (ExtBuffer *buffer) 93 | { 94 | return ((Buffer *) buffer)->render_buffer; 95 | } 96 | 97 | static unsigned int 98 | WidthFunc (ExtBuffer *buffer) 99 | { 100 | /* Single pixel buffers are always 1x1. */ 101 | return 1; 102 | } 103 | 104 | static unsigned int 105 | HeightFunc (ExtBuffer *buffer) 106 | { 107 | /* Single pixel buffers are always 1x1. */ 108 | return 1; 109 | } 110 | 111 | static void 112 | PrintBuffer (Buffer *buffer) 113 | { 114 | /* Not implemented. */ 115 | } 116 | 117 | static void 118 | PrintBufferFunc (ExtBuffer *buffer) 119 | { 120 | PrintBuffer ((Buffer *) buffer); 121 | } 122 | 123 | static void 124 | HandleResourceDestroy (struct wl_resource *resource) 125 | { 126 | Buffer *buffer; 127 | 128 | buffer = wl_resource_get_user_data (resource); 129 | buffer->resource = NULL; 130 | 131 | DereferenceBuffer (buffer); 132 | } 133 | 134 | 135 | 136 | static void 137 | Destroy (struct wl_client *client, struct wl_resource *resource) 138 | { 139 | wl_resource_destroy (resource); 140 | } 141 | 142 | static void 143 | CreateU32RgbaBuffer (struct wl_client *client, struct wl_resource *resource, 144 | uint32_t id, uint32_t r, uint32_t g, uint32_t b, 145 | uint32_t a) 146 | { 147 | Buffer *buffer; 148 | Bool error; 149 | 150 | buffer = XLSafeMalloc (sizeof *buffer); 151 | 152 | if (!buffer) 153 | { 154 | wl_resource_post_no_memory (resource); 155 | return; 156 | } 157 | 158 | memset (buffer, 0, sizeof *buffer); 159 | buffer->resource = wl_resource_create (client, &wl_buffer_interface, 160 | wl_resource_get_version (resource), 161 | id); 162 | 163 | if (!buffer->resource) 164 | { 165 | out_of_memory: 166 | wl_resource_post_no_memory (resource); 167 | XLFree (buffer); 168 | return; 169 | } 170 | 171 | /* Now, create the render target. */ 172 | error = False; 173 | buffer->render_buffer = RenderBufferFromSinglePixel (r, g, b, a, 174 | &error); 175 | 176 | if (error) 177 | /* We probably ran out of memory. */ 178 | goto out_of_memory; 179 | 180 | buffer->refcount = 1; 181 | 182 | /* Initialize function pointers. */ 183 | buffer->buffer.funcs.retain = RetainBufferFunc; 184 | buffer->buffer.funcs.dereference = DereferenceBufferFunc; 185 | buffer->buffer.funcs.get_buffer = GetBufferFunc; 186 | buffer->buffer.funcs.width = WidthFunc; 187 | buffer->buffer.funcs.height = HeightFunc; 188 | buffer->buffer.funcs.release = ReleaseBufferFunc; 189 | buffer->buffer.funcs.print_buffer = PrintBufferFunc; 190 | 191 | wl_resource_set_implementation (buffer->resource, &single_pixel_buffer_impl, 192 | buffer, HandleResourceDestroy); 193 | } 194 | 195 | static const struct wp_single_pixel_buffer_manager_v1_interface manager_impl = 196 | { 197 | .destroy = Destroy, 198 | .create_u32_rgba_buffer = CreateU32RgbaBuffer, 199 | }; 200 | 201 | static void 202 | HandleBind (struct wl_client *client, void *data, uint32_t version, 203 | uint32_t id) 204 | { 205 | struct wl_resource *resource; 206 | 207 | resource = wl_resource_create (client, 208 | &wp_single_pixel_buffer_manager_v1_interface, 209 | version, id); 210 | 211 | if (!resource) 212 | { 213 | wl_client_post_no_memory (client); 214 | return; 215 | } 216 | 217 | wl_resource_set_implementation (resource, &manager_impl, 218 | NULL, NULL); 219 | } 220 | 221 | void 222 | XLInitSinglePixelBuffer (void) 223 | { 224 | single_pixel_buffer_global 225 | = wl_global_create (compositor.wl_display, 226 | &wp_single_pixel_buffer_manager_v1_interface, 227 | 1, NULL, HandleBind); 228 | } 229 | -------------------------------------------------------------------------------- /pointer_gestures.c: -------------------------------------------------------------------------------- 1 | /* Wayland compositor running on top of an X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include "compositor.h" 21 | #include "pointer-gestures-unstable-v1.h" 22 | 23 | /* The struct zwp_pointer_gestures_v1 global. */ 24 | static struct wl_global *pointer_gestures_global; 25 | 26 | static void 27 | DestroySwipeGesture (struct wl_client *client, struct wl_resource *resource) 28 | { 29 | wl_resource_destroy (resource); 30 | } 31 | 32 | static struct zwp_pointer_gesture_swipe_v1_interface gesture_swipe_impl = 33 | { 34 | .destroy = DestroySwipeGesture, 35 | }; 36 | 37 | static void 38 | HandleSwipeGestureResourceDestroy (struct wl_resource *resource) 39 | { 40 | SwipeGesture *gesture; 41 | 42 | gesture = wl_resource_get_user_data (resource); 43 | XLSeatDestroySwipeGesture (gesture); 44 | } 45 | 46 | 47 | 48 | static void 49 | DestroyPinchGesture (struct wl_client *client, struct wl_resource *resource) 50 | { 51 | wl_resource_destroy (resource); 52 | } 53 | 54 | static struct zwp_pointer_gesture_pinch_v1_interface gesture_pinch_impl = 55 | { 56 | .destroy = DestroyPinchGesture, 57 | }; 58 | 59 | static void 60 | HandlePinchGestureResourceDestroy (struct wl_resource *resource) 61 | { 62 | PinchGesture *gesture; 63 | 64 | gesture = wl_resource_get_user_data (resource); 65 | XLSeatDestroyPinchGesture (gesture); 66 | } 67 | 68 | 69 | 70 | static void 71 | DestroyHoldGesture (struct wl_client *client, struct wl_resource *resource) 72 | { 73 | wl_resource_destroy (resource); 74 | } 75 | 76 | static struct zwp_pointer_gesture_hold_v1_interface gesture_hold_impl = 77 | { 78 | .destroy = DestroyHoldGesture, 79 | }; 80 | 81 | 82 | 83 | static void 84 | GetSwipeGesture (struct wl_client *client, struct wl_resource *resource, 85 | uint32_t id, struct wl_resource *pointer_resource) 86 | { 87 | struct wl_resource *gesture_resource; 88 | Pointer *pointer; 89 | Seat *seat; 90 | SwipeGesture *gesture_swipe; 91 | 92 | pointer = wl_resource_get_user_data (pointer_resource); 93 | seat = XLPointerGetSeat (pointer); 94 | gesture_resource 95 | = wl_resource_create (client, 96 | &zwp_pointer_gesture_swipe_v1_interface, 97 | wl_resource_get_version (resource), id); 98 | 99 | if (!gesture_resource) 100 | { 101 | wl_resource_post_no_memory (resource); 102 | return; 103 | } 104 | 105 | gesture_swipe = XLSeatGetSwipeGesture (seat, gesture_resource); 106 | wl_resource_set_implementation (gesture_resource, &gesture_swipe_impl, 107 | gesture_swipe, 108 | HandleSwipeGestureResourceDestroy); 109 | } 110 | 111 | static void 112 | GetPinchGesture (struct wl_client *client, struct wl_resource *resource, 113 | uint32_t id, struct wl_resource *pointer_resource) 114 | { 115 | struct wl_resource *gesture_resource; 116 | Pointer *pointer; 117 | Seat *seat; 118 | PinchGesture *gesture_pinch; 119 | 120 | pointer = wl_resource_get_user_data (pointer_resource); 121 | seat = XLPointerGetSeat (pointer); 122 | gesture_resource 123 | = wl_resource_create (client, 124 | &zwp_pointer_gesture_pinch_v1_interface, 125 | wl_resource_get_version (resource), id); 126 | 127 | if (!gesture_resource) 128 | { 129 | wl_resource_post_no_memory (resource); 130 | return; 131 | } 132 | 133 | gesture_pinch = XLSeatGetPinchGesture (seat, gesture_resource); 134 | wl_resource_set_implementation (gesture_resource, &gesture_pinch_impl, 135 | gesture_pinch, 136 | HandlePinchGestureResourceDestroy); 137 | } 138 | 139 | static void 140 | Release (struct wl_client *client, struct wl_resource *resource) 141 | { 142 | wl_resource_destroy (resource); 143 | } 144 | 145 | static void 146 | GetHoldGesture (struct wl_client *client, struct wl_resource *resource, 147 | uint32_t id, struct wl_resource *pointer_resource) 148 | { 149 | struct wl_resource *gesture_resource; 150 | 151 | /* Hold gestures are not supported by the X Input extension, so a 152 | dummy resource is created that just does nothing. */ 153 | gesture_resource 154 | = wl_resource_create (client, &zwp_pointer_gesture_hold_v1_interface, 155 | wl_resource_get_version (resource), id); 156 | 157 | if (!gesture_resource) 158 | { 159 | wl_resource_post_no_memory (resource); 160 | return; 161 | } 162 | 163 | wl_resource_set_implementation (gesture_resource, &gesture_hold_impl, 164 | NULL, NULL); 165 | } 166 | 167 | static struct zwp_pointer_gestures_v1_interface pointer_gestures_impl = 168 | { 169 | .get_swipe_gesture = GetSwipeGesture, 170 | .get_pinch_gesture = GetPinchGesture, 171 | .release = Release, 172 | .get_hold_gesture = GetHoldGesture, 173 | }; 174 | 175 | static void 176 | HandleBind (struct wl_client *client, void *data, uint32_t version, 177 | uint32_t id) 178 | { 179 | struct wl_resource *resource; 180 | 181 | resource = wl_resource_create (client, &zwp_pointer_gestures_v1_interface, 182 | version, id); 183 | 184 | if (!resource) 185 | { 186 | wl_client_post_no_memory (client); 187 | return; 188 | } 189 | 190 | wl_resource_set_implementation (resource, &pointer_gestures_impl, 191 | NULL, NULL); 192 | } 193 | 194 | void 195 | XLInitPointerGestures (void) 196 | { 197 | if (xi2_major > 2 || xi2_minor >= 4) 198 | /* Create the pointer gestures global. */ 199 | pointer_gestures_global 200 | = wl_global_create (compositor.wl_display, 201 | &zwp_pointer_gestures_v1_interface, 202 | 3, NULL, HandleBind); 203 | 204 | /* Pointer gestures are not supported without XI 2.4 or later. */ 205 | } 206 | -------------------------------------------------------------------------------- /tests/simple_test.c: -------------------------------------------------------------------------------- 1 | /* Tests for the Wayland compositor running on the X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include "test_harness.h" 21 | 22 | enum test_kind 23 | { 24 | MAP_WINDOW_KIND, 25 | BASIC_TEST_CARD_IMAGE_KIND, 26 | }; 27 | 28 | static const char *test_names[] = 29 | { 30 | "map_window", 31 | "basic_test_card_image", 32 | }; 33 | 34 | #define LAST_TEST BASIC_TEST_CARD_IMAGE_KIND 35 | 36 | /* The display. */ 37 | static struct test_display *display; 38 | 39 | /* Test interfaces. */ 40 | static struct test_interface test_interfaces[] = 41 | { 42 | /* No interfaces yet. */ 43 | }; 44 | 45 | /* The test surface window. */ 46 | static Window test_surface_window; 47 | 48 | /* The test surface and Wayland surface. */ 49 | static struct test_surface *test_surface; 50 | static struct wl_surface *wayland_surface; 51 | 52 | 53 | 54 | /* Forward declarations. */ 55 | static void submit_frame_callback (struct wl_surface *, enum test_kind); 56 | static void submit_surface_damage (struct wl_surface *, int, int, int, int); 57 | 58 | 59 | 60 | static void 61 | verify_single_step (enum test_kind kind) 62 | { 63 | switch (kind) 64 | { 65 | case BASIC_TEST_CARD_IMAGE_KIND: 66 | verify_image_data (display, test_surface_window, 67 | "simple_test.dump"); 68 | break; 69 | 70 | default: 71 | break; 72 | } 73 | 74 | if (kind == LAST_TEST) 75 | test_complete (); 76 | } 77 | 78 | static void 79 | test_single_step (enum test_kind kind) 80 | { 81 | struct wl_buffer *buffer; 82 | 83 | test_log ("running test step: %s", test_names[kind]); 84 | 85 | switch (kind) 86 | { 87 | case MAP_WINDOW_KIND: 88 | buffer = load_png_image (display, "blue.png"); 89 | 90 | if (!buffer) 91 | report_test_failure ("failed to load blue.png"); 92 | 93 | wl_surface_attach (wayland_surface, buffer, 0, 0); 94 | submit_surface_damage (wayland_surface, 0, 0, 95 | INT_MAX, INT_MAX); 96 | wl_surface_commit (wayland_surface); 97 | wl_buffer_destroy (buffer); 98 | break; 99 | 100 | case BASIC_TEST_CARD_IMAGE_KIND: 101 | buffer = load_png_image (display, "basic_test_card.png"); 102 | 103 | if (!buffer) 104 | report_test_failure ("failed to load basic_test_card.png"); 105 | 106 | wl_surface_attach (wayland_surface, buffer, 0, 0); 107 | submit_frame_callback (wayland_surface, kind); 108 | submit_surface_damage (wayland_surface, 0, 0, 109 | INT_MAX, INT_MAX); 110 | wl_surface_commit (wayland_surface); 111 | wl_buffer_destroy (buffer); 112 | break; 113 | } 114 | } 115 | 116 | static void 117 | test_next_step (enum test_kind kind) 118 | { 119 | switch (kind) 120 | { 121 | default: 122 | break; 123 | } 124 | } 125 | 126 | 127 | 128 | static void 129 | handle_test_surface_mapped (void *data, struct test_surface *surface, 130 | uint32_t xid, const char *display_string) 131 | { 132 | /* Sleep for 1 second to ensure that the window is exposed and 133 | redirected. */ 134 | sleep (1); 135 | 136 | /* Start the test. */ 137 | test_surface_window = xid; 138 | 139 | /* Run the test again. */ 140 | test_single_step (BASIC_TEST_CARD_IMAGE_KIND); 141 | } 142 | 143 | static void 144 | handle_test_surface_committed (void *data, struct test_surface *surface, 145 | uint32_t presentation_hint) 146 | { 147 | 148 | } 149 | 150 | static const struct test_surface_listener test_surface_listener = 151 | { 152 | handle_test_surface_mapped, 153 | NULL, 154 | handle_test_surface_committed, 155 | }; 156 | 157 | 158 | 159 | static void 160 | handle_wl_callback_done (void *data, struct wl_callback *callback, 161 | uint32_t callback_data) 162 | { 163 | enum test_kind kind; 164 | 165 | /* kind is not a pointer. It is an enum test_kind stuffed into a 166 | pointer. */ 167 | kind = (intptr_t) data; 168 | 169 | wl_callback_destroy (callback); 170 | verify_single_step (kind); 171 | 172 | /* Now run the next test in this sequence. */ 173 | test_next_step (kind); 174 | } 175 | 176 | static const struct wl_callback_listener wl_callback_listener = 177 | { 178 | handle_wl_callback_done, 179 | }; 180 | 181 | 182 | 183 | static void 184 | submit_frame_callback (struct wl_surface *surface, enum test_kind kind) 185 | { 186 | struct wl_callback *callback; 187 | 188 | callback = wl_surface_frame (surface); 189 | wl_callback_add_listener (callback, &wl_callback_listener, 190 | (void *) (intptr_t) kind); 191 | } 192 | 193 | static void 194 | submit_surface_damage (struct wl_surface *surface, int x, int y, int width, 195 | int height) 196 | { 197 | test_log ("damaging surface by %d, %d, %d, %d", x, y, width, 198 | height); 199 | 200 | wl_surface_damage (surface, x, y, width, height); 201 | } 202 | 203 | static void 204 | run_test (void) 205 | { 206 | if (!make_test_surface (display, &wayland_surface, 207 | &test_surface)) 208 | report_test_failure ("failed to create test surface"); 209 | 210 | test_surface_add_listener (test_surface, &test_surface_listener, 211 | NULL); 212 | test_single_step (MAP_WINDOW_KIND); 213 | 214 | while (true) 215 | { 216 | if (wl_display_dispatch (display->display) == -1) 217 | die ("wl_display_dispatch"); 218 | } 219 | } 220 | 221 | int 222 | main (void) 223 | { 224 | test_init (); 225 | display = open_test_display (test_interfaces, 226 | ARRAYELTS (test_interfaces)); 227 | 228 | if (!display) 229 | report_test_failure ("failed to open display"); 230 | 231 | run_test (); 232 | } 233 | -------------------------------------------------------------------------------- /tests/buffer_test.c: -------------------------------------------------------------------------------- 1 | /* Tests for the Wayland compositor running on the X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include "test_harness.h" 21 | 22 | /* Tests for buffer release. */ 23 | 24 | enum test_kind 25 | { 26 | BUFFER_RELEASE_KIND, 27 | BUFFER_DESTROY_KIND, 28 | }; 29 | 30 | static const char *test_names[] = 31 | { 32 | "buffer_release", 33 | "buffer_destroy", 34 | }; 35 | 36 | #define LAST_TEST BUFFER_DESTROY_KIND 37 | 38 | /* The display. */ 39 | static struct test_display *display; 40 | 41 | /* Test interfaces. */ 42 | static struct test_interface test_interfaces[] = 43 | { 44 | /* No interfaces yet... */ 45 | }; 46 | 47 | /* The test surface and Wayland surface. */ 48 | static struct test_surface *test_surface; 49 | static struct wl_surface *wayland_surface; 50 | 51 | 52 | 53 | /* Forward declarations. */ 54 | static void wait_frame_callback (struct wl_surface *); 55 | 56 | 57 | 58 | static struct test_buffer * 59 | make_test_buffer (void) 60 | { 61 | struct wl_buffer *buffer; 62 | struct test_buffer *test_buffer; 63 | char *empty_data; 64 | size_t stride; 65 | 66 | stride = get_image_stride (display, 24, 1); 67 | 68 | if (!stride) 69 | report_test_failure ("unknown stride"); 70 | 71 | empty_data = calloc (1, stride); 72 | 73 | if (!empty_data) 74 | report_test_failure ("failed to allocate buffer data"); 75 | 76 | buffer = upload_image_data (display, empty_data, 1, 1, 24); 77 | free (empty_data); 78 | 79 | if (!buffer) 80 | report_test_failure ("failed to create single pixel buffer"); 81 | 82 | test_buffer = get_test_buffer (display, buffer); 83 | 84 | if (!test_buffer) 85 | report_test_failure ("failed to create test buffer"); 86 | 87 | return test_buffer; 88 | } 89 | 90 | static void 91 | test_single_step (enum test_kind kind) 92 | { 93 | struct test_buffer *buffers[1000]; 94 | int i; 95 | 96 | again: 97 | 98 | test_log ("running test step: %s", test_names[kind]); 99 | 100 | switch (kind) 101 | { 102 | case BUFFER_RELEASE_KIND: 103 | /* Abuse the buffer release machinery. Repeatedly commit 1000 104 | buffers. Then, wait for a frame callback on the 1000th 105 | commit. 106 | 107 | Verify that the first 999 have been released. */ 108 | 109 | for (i = 0; i < ARRAYELTS (buffers) - 1; ++i) 110 | { 111 | buffers[i] = make_test_buffer (); 112 | wl_surface_attach (wayland_surface, buffers[i]->buffer, 113 | 0, 0); 114 | test_buffer_committed (buffers[i]); 115 | wl_surface_commit (wayland_surface); 116 | } 117 | 118 | buffers[i] = make_test_buffer (); 119 | wl_surface_attach (wayland_surface, buffers[i]->buffer, 120 | 0, 0); 121 | test_buffer_committed (buffers[i]); 122 | wait_frame_callback (wayland_surface); 123 | 124 | for (i = 0; i < ARRAYELTS (buffers) - 1; ++i) 125 | verify_buffer_released (buffers[i]); 126 | 127 | kind = BUFFER_DESTROY_KIND; 128 | goto again; 129 | 130 | case BUFFER_DESTROY_KIND: 131 | /* Now do the same thing, but destroy every other wl_buffer. */ 132 | 133 | for (i = 0; i < ARRAYELTS (buffers) - 1; ++i) 134 | { 135 | wl_surface_attach (wayland_surface, buffers[i]->buffer, 136 | 0, 0); 137 | test_buffer_committed (buffers[i]); 138 | wl_surface_commit (wayland_surface); 139 | 140 | if (i % 2) 141 | wl_buffer_destroy (buffers[i]->buffer); 142 | 143 | /* buffers[i] is intentionally "leaked". */ 144 | buffers[i] = NULL; 145 | } 146 | 147 | wl_surface_attach (wayland_surface, buffers[i]->buffer, 148 | 0, 0); 149 | test_buffer_committed (buffers[i]); 150 | wait_frame_callback (wayland_surface); 151 | 152 | for (i = 0; i < ARRAYELTS (buffers) - 1; ++i) 153 | { 154 | if (buffers[i]) 155 | verify_buffer_released (buffers[i]); 156 | } 157 | } 158 | 159 | if (kind == LAST_TEST) 160 | test_complete (); 161 | } 162 | 163 | 164 | 165 | static void 166 | handle_wl_callback_done (void *data, struct wl_callback *callback, 167 | uint32_t callback_data) 168 | { 169 | bool *flag; 170 | 171 | wl_callback_destroy (callback); 172 | 173 | /* Now tell wait_frame_callback to break out of the loop. */ 174 | flag = data; 175 | *flag = true; 176 | } 177 | 178 | static const struct wl_callback_listener wl_callback_listener = 179 | { 180 | handle_wl_callback_done, 181 | }; 182 | 183 | 184 | 185 | static void 186 | wait_frame_callback (struct wl_surface *surface) 187 | { 188 | struct wl_callback *callback; 189 | bool flag; 190 | 191 | /* Commit surface and wait for a frame callback. */ 192 | 193 | callback = wl_surface_frame (surface); 194 | flag = false; 195 | 196 | wl_callback_add_listener (callback, &wl_callback_listener, 197 | &flag); 198 | wl_surface_commit (surface); 199 | 200 | while (!flag) 201 | { 202 | if (wl_display_dispatch (display->display) == -1) 203 | die ("wl_display_dispatch"); 204 | } 205 | } 206 | 207 | static void 208 | run_test (void) 209 | { 210 | if (!make_test_surface (display, &wayland_surface, 211 | &test_surface)) 212 | report_test_failure ("failed to create test surface"); 213 | 214 | test_single_step (BUFFER_RELEASE_KIND); 215 | 216 | while (true) 217 | { 218 | if (wl_display_dispatch (display->display) == -1) 219 | die ("wl_display_dispatch"); 220 | } 221 | } 222 | 223 | int 224 | main (void) 225 | { 226 | test_init (); 227 | display = open_test_display (test_interfaces, 228 | ARRAYELTS (test_interfaces)); 229 | 230 | if (!display) 231 | report_test_failure ("failed to open display"); 232 | 233 | run_test (); 234 | } 235 | -------------------------------------------------------------------------------- /timer.c: -------------------------------------------------------------------------------- 1 | /* Wayland compositor running on top of an X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | /* Some of this file was taken from timespec-add.c and timespec-sub.c, 21 | part of gnulib, written by Paul Eggert . */ 22 | 23 | #include "compositor.h" 24 | 25 | /* Linked list of all timers. */ 26 | static Timer all_timers; 27 | 28 | struct _Timer 29 | { 30 | /* The next and last timers in this list. */ 31 | Timer *next, *last; 32 | 33 | /* The repeat of this timer. */ 34 | struct timespec repeat; 35 | 36 | /* The next time this timer should be run. */ 37 | struct timespec next_time; 38 | 39 | /* The function that should be called when the timer is run. */ 40 | void (*function) (Timer *, void *, struct timespec); 41 | 42 | /* User data associated with the timer. */ 43 | void *timer_data; 44 | }; 45 | 46 | struct timespec 47 | CurrentTimespec (void) 48 | { 49 | struct timespec timespec; 50 | 51 | clock_gettime (CLOCK_MONOTONIC, ×pec); 52 | return timespec; 53 | } 54 | 55 | struct timespec 56 | MakeTimespec (time_t s, long int ns) 57 | { 58 | struct timespec r; 59 | 60 | r.tv_sec = s; 61 | r.tv_nsec = ns; 62 | 63 | return r; 64 | } 65 | 66 | int 67 | TimespecCmp (struct timespec a, struct timespec b) 68 | { 69 | return (2 * SafeCmp (a.tv_sec, b.tv_sec) 70 | + SafeCmp (a.tv_nsec, b.tv_nsec)); 71 | } 72 | 73 | struct timespec 74 | TimespecAdd (struct timespec a, struct timespec b) 75 | { 76 | time_t rs, bs, bs1; 77 | int ns, nsd, rns; 78 | 79 | rs = a.tv_sec; 80 | bs = b.tv_sec; 81 | ns = a.tv_nsec + b.tv_nsec; 82 | nsd = ns - 1000000000; 83 | rns = ns; 84 | 85 | if (0 < nsd) 86 | { 87 | rns = nsd; 88 | 89 | if (!IntAddWrapv (bs, 1, &bs1)) 90 | bs = bs1; 91 | else if (rs < 0) 92 | rs++; 93 | else 94 | goto high_overflow; 95 | } 96 | 97 | if (IntAddWrapv (rs, bs, &rs)) 98 | { 99 | if (bs < 0) 100 | { 101 | rs = TypeMinimum (time_t); 102 | rns = 0; 103 | } 104 | else 105 | { 106 | high_overflow: 107 | rs = TypeMaximum (time_t); 108 | rns = 1000000000 - 1; 109 | } 110 | } 111 | 112 | return MakeTimespec (rs, rns); 113 | } 114 | 115 | struct timespec 116 | TimespecSub (struct timespec a, struct timespec b) 117 | { 118 | time_t rs, bs, bs1; 119 | int ns, rns; 120 | 121 | rs = a.tv_sec; 122 | bs = b.tv_sec; 123 | ns = a.tv_nsec - b.tv_nsec; 124 | rns = ns; 125 | 126 | if (ns < 0) 127 | { 128 | rns = ns + 1000000000; 129 | if (!IntAddWrapv (bs, 1, &bs1)) 130 | bs = bs1; 131 | else if (- TypeIsSigned (time_t) < rs) 132 | rs--; 133 | else 134 | goto low_overflow; 135 | } 136 | 137 | if (IntSubtractWrapv (rs, bs, &rs)) 138 | { 139 | if (0 < bs) 140 | { 141 | low_overflow: 142 | rs = TypeMinimum (time_t); 143 | rns = 0; 144 | } 145 | else 146 | { 147 | rs = TypeMaximum (time_t); 148 | rns = 1000000000 - 1; 149 | } 150 | } 151 | 152 | return MakeTimespec (rs, rns); 153 | } 154 | 155 | Timer * 156 | AddTimer (void (*function) (Timer *, void *, struct timespec), 157 | void *data, struct timespec delay) 158 | { 159 | Timer *timer; 160 | 161 | timer = XLMalloc (sizeof *timer); 162 | timer->function = function; 163 | timer->timer_data = data; 164 | timer->repeat = delay; 165 | timer->next_time = TimespecAdd (CurrentTimespec (), 166 | delay); 167 | 168 | /* Chain the timer onto our list of timers. */ 169 | timer->next = all_timers.next; 170 | timer->last = &all_timers; 171 | 172 | all_timers.next->last = timer; 173 | all_timers.next = timer; 174 | 175 | return timer; 176 | } 177 | 178 | Timer * 179 | AddTimerWithBaseTime (void (*function) (Timer *, void *, struct timespec), 180 | void *data, struct timespec delay, struct timespec base) 181 | { 182 | Timer *timer; 183 | 184 | timer = XLMalloc (sizeof *timer); 185 | timer->function = function; 186 | timer->timer_data = data; 187 | timer->repeat = delay; 188 | timer->next_time = TimespecAdd (base, delay); 189 | 190 | /* Chain the timer onto our list of timers. */ 191 | timer->next = all_timers.next; 192 | timer->last = &all_timers; 193 | 194 | all_timers.next->last = timer; 195 | all_timers.next = timer; 196 | 197 | return timer; 198 | } 199 | 200 | void 201 | RemoveTimer (Timer *timer) 202 | { 203 | /* Start by removing the timer from the list of timers. This is 204 | only safe inside a timer callback our outside TimerCheck. */ 205 | timer->next->last = timer->last; 206 | timer->last->next = timer->next; 207 | 208 | /* Then, free the timer. */ 209 | XLFree (timer); 210 | } 211 | 212 | void 213 | RetimeTimer (Timer *timer) 214 | { 215 | timer->next_time = TimespecAdd (CurrentTimespec (), 216 | timer->repeat); 217 | } 218 | 219 | struct timespec 220 | TimerCheck (void) 221 | { 222 | struct timespec now, wait, temp; 223 | Timer *timer, *next; 224 | Bool flag; 225 | 226 | now = CurrentTimespec (); 227 | wait = MakeTimespec (TypeMaximum (time_t), 228 | 1000000000 - 1); 229 | timer = all_timers.next; 230 | 231 | while (timer != &all_timers) 232 | { 233 | /* Move the list forward first, so the timer callback can 234 | safely remove itself from the list. */ 235 | next = timer->next; 236 | flag = False; 237 | 238 | if (TimespecCmp (timer->next_time, now) <= 0) 239 | { 240 | timer->next_time = TimespecAdd (timer->next_time, 241 | timer->repeat); 242 | flag = True; 243 | } 244 | 245 | temp = TimespecSub (timer->next_time, now); 246 | 247 | if (TimespecCmp (temp, wait) < 0) 248 | /* Wait is the time to wait until the next timer might 249 | fire. */ 250 | wait = temp; 251 | 252 | if (flag) 253 | /* Run this function here instead, since it might remove the 254 | timer from the list. */ 255 | timer->function (timer, timer->timer_data, now); 256 | 257 | timer = next; 258 | } 259 | 260 | return wait; 261 | } 262 | 263 | void 264 | XLInitTimers (void) 265 | { 266 | all_timers.next = &all_timers; 267 | all_timers.last = &all_timers; 268 | } 269 | -------------------------------------------------------------------------------- /tests/single_pixel_buffer_test.c: -------------------------------------------------------------------------------- 1 | /* Tests for the Wayland compositor running on the X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include "test_harness.h" 21 | #include "single-pixel-buffer-v1.h" 22 | #include "viewporter.h" 23 | 24 | /* Tests for single pixel buffers. */ 25 | 26 | enum test_kind 27 | { 28 | MAP_WINDOW_KIND, 29 | SINGLE_PIXEL_BUFFER_KIND, 30 | SINGLE_PIXEL_BUFFER_VIEWPORT_KIND, 31 | }; 32 | 33 | static const char *test_names[] = 34 | { 35 | "map_window", 36 | "single_pixel_buffer", 37 | "single_pixel_buffer_viewport", 38 | }; 39 | 40 | #define LAST_TEST SINGLE_PIXEL_BUFFER_VIEWPORT_KIND 41 | 42 | /* The display. */ 43 | static struct test_display *display; 44 | 45 | /* The buffer manager. */ 46 | static struct wp_single_pixel_buffer_manager_v1 *manager; 47 | 48 | /* The viewporter. */ 49 | static struct wp_viewporter *viewporter; 50 | 51 | /* Test interfaces. */ 52 | static struct test_interface test_interfaces[] = 53 | { 54 | { "wp_single_pixel_buffer_manager_v1", &manager, 55 | &wp_single_pixel_buffer_manager_v1_interface, 1, }, 56 | { "wp_viewporter", &viewporter, &wp_viewporter_interface, 57 | 1, }, 58 | }; 59 | 60 | /* The test surface window. */ 61 | static Window test_surface_window; 62 | 63 | /* The test surface and Wayland surface. */ 64 | static struct test_surface *test_surface; 65 | static struct wl_surface *wayland_surface; 66 | 67 | /* The single pixel buffer. */ 68 | static struct wl_buffer *single_pixel_buffer; 69 | 70 | /* The viewport. */ 71 | static struct wp_viewport *viewport; 72 | 73 | 74 | 75 | /* Forward declarations. */ 76 | static void wait_frame_callback (struct wl_surface *); 77 | 78 | 79 | 80 | static void 81 | test_single_step (enum test_kind kind) 82 | { 83 | test_log ("running test step: %s", test_names[kind]); 84 | 85 | switch (kind) 86 | { 87 | case MAP_WINDOW_KIND: 88 | wl_surface_attach (wayland_surface, single_pixel_buffer, 0, 0); 89 | wl_surface_damage (wayland_surface, 0, 0, 1, 1); 90 | wl_surface_commit (wayland_surface); 91 | break; 92 | 93 | case SINGLE_PIXEL_BUFFER_KIND: 94 | wait_frame_callback (wayland_surface); 95 | verify_image_data (display, test_surface_window, 96 | "single_pixel_buffer.dump"); 97 | test_single_step (SINGLE_PIXEL_BUFFER_VIEWPORT_KIND); 98 | break; 99 | 100 | case SINGLE_PIXEL_BUFFER_VIEWPORT_KIND: 101 | wp_viewport_set_source (viewport, 102 | wl_fixed_from_double (0.0), 103 | wl_fixed_from_double (0.0), 104 | wl_fixed_from_double (1.0), 105 | wl_fixed_from_double (1.0)); 106 | wp_viewport_set_destination (viewport, 275, 275); 107 | wait_frame_callback (wayland_surface); 108 | 109 | verify_image_data (display, test_surface_window, 110 | "single_pixel_buffer_viewport.dump"); 111 | break; 112 | } 113 | 114 | if (kind == LAST_TEST) 115 | test_complete (); 116 | } 117 | 118 | 119 | 120 | static void 121 | handle_test_surface_mapped (void *data, struct test_surface *surface, 122 | uint32_t xid, const char *display_string) 123 | { 124 | /* Sleep for 1 second to ensure that the window is exposed and 125 | redirected. */ 126 | sleep (1); 127 | 128 | /* Start the test. */ 129 | test_surface_window = xid; 130 | 131 | /* Run the test again. */ 132 | test_single_step (SINGLE_PIXEL_BUFFER_KIND); 133 | } 134 | 135 | static void 136 | handle_test_surface_committed (void *data, struct test_surface *surface, 137 | uint32_t presentation_hint) 138 | { 139 | 140 | } 141 | 142 | static const struct test_surface_listener test_surface_listener = 143 | { 144 | handle_test_surface_mapped, 145 | NULL, 146 | handle_test_surface_committed, 147 | }; 148 | 149 | 150 | 151 | static void 152 | handle_wl_callback_done (void *data, struct wl_callback *callback, 153 | uint32_t callback_data) 154 | { 155 | bool *flag; 156 | 157 | wl_callback_destroy (callback); 158 | 159 | /* Now tell wait_frame_callback to break out of the loop. */ 160 | flag = data; 161 | *flag = true; 162 | } 163 | 164 | static const struct wl_callback_listener wl_callback_listener = 165 | { 166 | handle_wl_callback_done, 167 | }; 168 | 169 | 170 | 171 | static void 172 | wait_frame_callback (struct wl_surface *surface) 173 | { 174 | struct wl_callback *callback; 175 | bool flag; 176 | 177 | /* Commit surface and wait for a frame callback. */ 178 | 179 | callback = wl_surface_frame (surface); 180 | flag = false; 181 | 182 | wl_callback_add_listener (callback, &wl_callback_listener, 183 | &flag); 184 | wl_surface_commit (surface); 185 | 186 | while (!flag) 187 | { 188 | if (wl_display_dispatch (display->display) == -1) 189 | die ("wl_display_dispatch"); 190 | } 191 | } 192 | 193 | static void 194 | run_test (void) 195 | { 196 | if (!make_test_surface (display, &wayland_surface, 197 | &test_surface)) 198 | report_test_failure ("failed to create test surface"); 199 | 200 | test_surface_add_listener (test_surface, &test_surface_listener, 201 | NULL); 202 | 203 | /* Create the single pixel buffer. */ 204 | single_pixel_buffer 205 | = wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer (manager, 206 | 0xffffffff, 207 | 0xffffffff, 208 | 0x00000000, 209 | 0xffffffff); 210 | if (!single_pixel_buffer) 211 | report_test_failure ("failed to create single pixel buffer"); 212 | 213 | /* And the viewport. */ 214 | viewport = wp_viewporter_get_viewport (viewporter, wayland_surface); 215 | 216 | if (!viewport) 217 | report_test_failure ("failed to get viewport"); 218 | 219 | test_single_step (MAP_WINDOW_KIND); 220 | 221 | while (true) 222 | { 223 | if (wl_display_dispatch (display->display) == -1) 224 | die ("wl_display_dispatch"); 225 | } 226 | } 227 | 228 | int 229 | main (void) 230 | { 231 | test_init (); 232 | display = open_test_display (test_interfaces, 233 | ARRAYELTS (test_interfaces)); 234 | 235 | if (!display) 236 | report_test_failure ("failed to open display"); 237 | 238 | run_test (); 239 | } 240 | -------------------------------------------------------------------------------- /tests/tearing_control_test.c: -------------------------------------------------------------------------------- 1 | /* Tests for the Wayland compositor running on the X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include "test_harness.h" 21 | #include "tearing-control-v1.h" 22 | 23 | /* Tests for buffer release. */ 24 | 25 | enum test_kind 26 | { 27 | TEARING_CONTROL_KIND, 28 | TEARING_DESTROY_KIND, 29 | }; 30 | 31 | static const char *test_names[] = 32 | { 33 | "tearing_control", 34 | "tearing_destroy", 35 | }; 36 | 37 | #define LAST_TEST TEARING_DESTROY_KIND 38 | 39 | /* The display. */ 40 | static struct test_display *display; 41 | 42 | /* The tearing control manager. */ 43 | static struct wp_tearing_control_manager_v1 *manager; 44 | 45 | /* Test interfaces. */ 46 | static struct test_interface test_interfaces[] = 47 | { 48 | { "wp_tearing_control_manager_v1", &manager, 49 | &wp_tearing_control_manager_v1_interface, 1, }, 50 | }; 51 | 52 | /* The test surface and Wayland surface. */ 53 | static struct test_surface *test_surface; 54 | static struct wl_surface *wayland_surface; 55 | 56 | /* The tearing control. */ 57 | static struct wp_tearing_control_v1 *tearing_control; 58 | 59 | /* The presentation hint used. 1 means async, and 0 means vsync. */ 60 | static int used_presentation_mode; 61 | 62 | 63 | 64 | /* Forward declarations. */ 65 | static void verify_async_used (void); 66 | static void verify_vsync_used (void); 67 | 68 | 69 | 70 | static struct test_buffer * 71 | make_test_buffer (void) 72 | { 73 | struct wl_buffer *buffer; 74 | struct test_buffer *test_buffer; 75 | char *empty_data; 76 | size_t stride; 77 | 78 | stride = get_image_stride (display, 24, 1); 79 | 80 | if (!stride) 81 | report_test_failure ("unknown stride"); 82 | 83 | empty_data = calloc (1, stride); 84 | 85 | if (!empty_data) 86 | report_test_failure ("failed to allocate buffer data"); 87 | 88 | buffer = upload_image_data (display, empty_data, 1, 1, 24); 89 | free (empty_data); 90 | 91 | if (!buffer) 92 | report_test_failure ("failed to create single pixel buffer"); 93 | 94 | test_buffer = get_test_buffer (display, buffer); 95 | 96 | if (!test_buffer) 97 | report_test_failure ("failed to create test buffer"); 98 | 99 | return test_buffer; 100 | } 101 | 102 | static void 103 | test_single_step (enum test_kind kind) 104 | { 105 | struct test_buffer *buffer; 106 | 107 | again: 108 | 109 | test_log ("running test step: %s", test_names[kind]); 110 | 111 | switch (kind) 112 | { 113 | case TEARING_CONTROL_KIND: 114 | #define VSYNC WP_TEARING_CONTROL_V1_PRESENTATION_HINT_VSYNC 115 | wp_tearing_control_v1_set_presentation_hint (tearing_control, 116 | VSYNC); 117 | #undef VSYNC 118 | buffer = make_test_buffer (); 119 | 120 | /* Attach the buffer. */ 121 | wl_surface_attach (wayland_surface, buffer->buffer, 0, 0); 122 | wl_surface_commit (wayland_surface); 123 | 124 | /* Now see what kind of presentation was used. */ 125 | verify_vsync_used (); 126 | 127 | #define ASYNC WP_TEARING_CONTROL_V1_PRESENTATION_HINT_ASYNC 128 | wp_tearing_control_v1_set_presentation_hint (tearing_control, 129 | ASYNC); 130 | #undef ASYNC 131 | wl_surface_commit (wayland_surface); 132 | 133 | /* Now verify that async presentation was used. */ 134 | verify_async_used (); 135 | 136 | kind = TEARING_DESTROY_KIND; 137 | goto again; 138 | 139 | case TEARING_DESTROY_KIND: 140 | /* Destroy the tearing control resource. */ 141 | wp_tearing_control_v1_destroy (tearing_control); 142 | wl_surface_commit (wayland_surface); 143 | 144 | /* Verify that the tearing hint reverted to vsync. */ 145 | verify_vsync_used (); 146 | break; 147 | } 148 | 149 | if (kind == LAST_TEST) 150 | test_complete (); 151 | } 152 | 153 | 154 | 155 | static void 156 | handle_test_surface_mapped (void *data, struct test_surface *test_surface, 157 | uint32_t xid, const char *display_string) 158 | { 159 | 160 | } 161 | 162 | static void 163 | handle_test_surface_activated (void *data, struct test_surface *test_surface, 164 | uint32_t months, uint32_t milliseconds, 165 | struct wl_surface *activator_surface) 166 | { 167 | 168 | } 169 | 170 | static void 171 | handle_test_surface_committed (void *data, struct test_surface *test_surface, 172 | uint32_t presentation_hint) 173 | { 174 | used_presentation_mode = presentation_hint; 175 | } 176 | 177 | static const struct test_surface_listener test_surface_listener = 178 | { 179 | handle_test_surface_mapped, 180 | handle_test_surface_activated, 181 | handle_test_surface_committed, 182 | }; 183 | 184 | static void 185 | verify_async_used (void) 186 | { 187 | wl_display_roundtrip (display->display); 188 | 189 | if (used_presentation_mode != 1) 190 | report_test_failure ("async presentation not used where expected!"); 191 | } 192 | 193 | static void 194 | verify_vsync_used (void) 195 | { 196 | wl_display_roundtrip (display->display); 197 | 198 | if (used_presentation_mode == 1) 199 | report_test_failure ("vsync presentation not used where expected!"); 200 | } 201 | 202 | 203 | 204 | static void 205 | run_test (void) 206 | { 207 | if (!make_test_surface (display, &wayland_surface, 208 | &test_surface)) 209 | report_test_failure ("failed to create test surface"); 210 | 211 | test_surface_add_listener (test_surface, &test_surface_listener, 212 | NULL); 213 | 214 | tearing_control 215 | = wp_tearing_control_manager_v1_get_tearing_control (manager, 216 | wayland_surface); 217 | 218 | if (!tearing_control) 219 | report_test_failure ("failed to create tearing control"); 220 | 221 | test_single_step (TEARING_CONTROL_KIND); 222 | 223 | while (true) 224 | { 225 | if (wl_display_dispatch (display->display) == -1) 226 | die ("wl_display_dispatch"); 227 | } 228 | } 229 | 230 | int 231 | main (void) 232 | { 233 | test_init (); 234 | display = open_test_display (test_interfaces, 235 | ARRAYELTS (test_interfaces)); 236 | 237 | if (!display) 238 | report_test_failure ("failed to open display"); 239 | 240 | run_test (); 241 | } 242 | -------------------------------------------------------------------------------- /relative-pointer-unstable-v1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright © 2014 Jonas Ådahl 6 | Copyright © 2015 Red Hat Inc. 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a 9 | copy of this software and associated documentation files (the "Software"), 10 | to deal in the Software without restriction, including without limitation 11 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 | and/or sell copies of the Software, and to permit persons to whom the 13 | Software is furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice (including the next 16 | paragraph) shall be included in all copies or substantial portions of the 17 | Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | 27 | 28 | 29 | This protocol specifies a set of interfaces used for making clients able to 30 | receive relative pointer events not obstructed by barriers (such as the 31 | monitor edge or other pointer barriers). 32 | 33 | To start receiving relative pointer events, a client must first bind the 34 | global interface "wp_relative_pointer_manager" which, if a compositor 35 | supports relative pointer motion events, is exposed by the registry. After 36 | having created the relative pointer manager proxy object, the client uses 37 | it to create the actual relative pointer object using the 38 | "get_relative_pointer" request given a wl_pointer. The relative pointer 39 | motion events will then, when applicable, be transmitted via the proxy of 40 | the newly created relative pointer object. See the documentation of the 41 | relative pointer interface for more details. 42 | 43 | Warning! The protocol described in this file is experimental and backward 44 | incompatible changes may be made. Backward compatible changes may be added 45 | together with the corresponding interface version bump. Backward 46 | incompatible changes are done by bumping the version number in the protocol 47 | and interface names and resetting the interface version. Once the protocol 48 | is to be declared stable, the 'z' prefix and the version number in the 49 | protocol and interface names are removed and the interface version number is 50 | reset. 51 | 52 | 53 | 54 | 55 | A global interface used for getting the relative pointer object for a 56 | given pointer. 57 | 58 | 59 | 60 | 61 | Used by the client to notify the server that it will no longer use this 62 | relative pointer manager object. 63 | 64 | 65 | 66 | 67 | 68 | Create a relative pointer interface given a wl_pointer object. See the 69 | wp_relative_pointer interface for more details. 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | A wp_relative_pointer object is an extension to the wl_pointer interface 79 | used for emitting relative pointer events. It shares the same focus as 80 | wl_pointer objects of the same seat and will only emit events when it has 81 | focus. 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | Relative x/y pointer motion from the pointer of the seat associated with 91 | this object. 92 | 93 | A relative motion is in the same dimension as regular wl_pointer motion 94 | events, except they do not represent an absolute position. For example, 95 | moving a pointer from (x, y) to (x', y') would have the equivalent 96 | relative motion (x' - x, y' - y). If a pointer motion caused the 97 | absolute pointer position to be clipped by for example the edge of the 98 | monitor, the relative motion is unaffected by the clipping and will 99 | represent the unclipped motion. 100 | 101 | This event also contains non-accelerated motion deltas. The 102 | non-accelerated delta is, when applicable, the regular pointer motion 103 | delta as it was before having applied motion acceleration and other 104 | transformations such as normalization. 105 | 106 | Note that the non-accelerated delta does not represent 'raw' events as 107 | they were read from some device. Pointer motion acceleration is device- 108 | and configuration-specific and non-accelerated deltas and accelerated 109 | deltas may have the same value on some devices. 110 | 111 | Relative motions are not coupled to wl_pointer.motion events, and can be 112 | sent in combination with such events, but also independently. There may 113 | also be scenarios where wl_pointer.motion is sent, but there is no 114 | relative motion. The order of an absolute and relative motion event 115 | originating from the same physical motion is not guaranteed. 116 | 117 | If the client needs button events or focus state, it can receive them 118 | from a wl_pointer object of the same seat that the wp_relative_pointer 119 | object is associated with. 120 | 121 | 123 | 125 | 127 | 129 | 131 | 133 | 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /tests/damage_test.c: -------------------------------------------------------------------------------- 1 | /* Tests for the Wayland compositor running on the X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include "test_harness.h" 21 | 22 | enum test_kind 23 | { 24 | MAP_WINDOW_KIND, 25 | BASIC_TEST_CARD_IMAGE_KIND, 26 | BASIC_DAMAGE_KIND, 27 | }; 28 | 29 | static const char *test_names[] = 30 | { 31 | "map_window", 32 | "basic_test_card_image", 33 | "basic_damage", 34 | }; 35 | 36 | #define LAST_TEST BASIC_DAMAGE_KIND 37 | 38 | /* The display. */ 39 | static struct test_display *display; 40 | 41 | /* Test interfaces. */ 42 | static struct test_interface test_interfaces[] = 43 | { 44 | /* No interfaces yet. */ 45 | }; 46 | 47 | /* The test surface window. */ 48 | static Window test_surface_window; 49 | 50 | /* The test surface and Wayland surface. */ 51 | static struct test_surface *test_surface; 52 | static struct wl_surface *wayland_surface; 53 | 54 | 55 | 56 | /* Forward declarations. */ 57 | static void submit_frame_callback (struct wl_surface *, enum test_kind); 58 | static void submit_surface_damage (struct wl_surface *, int, int, int, int); 59 | 60 | 61 | 62 | static void 63 | verify_single_step (enum test_kind kind) 64 | { 65 | switch (kind) 66 | { 67 | case BASIC_TEST_CARD_IMAGE_KIND: 68 | verify_image_data (display, test_surface_window, 69 | "damage_test_1.dump"); 70 | break; 71 | 72 | case BASIC_DAMAGE_KIND: 73 | verify_image_data (display, test_surface_window, 74 | "damage_test_2.dump"); 75 | break; 76 | 77 | default: 78 | break; 79 | } 80 | 81 | if (kind == LAST_TEST) 82 | test_complete (); 83 | } 84 | 85 | static void 86 | test_single_step (enum test_kind kind) 87 | { 88 | struct wl_buffer *buffer; 89 | 90 | test_log ("running test step: %s", test_names[kind]); 91 | 92 | switch (kind) 93 | { 94 | case MAP_WINDOW_KIND: 95 | buffer = load_png_image (display, "blue.png"); 96 | 97 | if (!buffer) 98 | report_test_failure ("failed to load blue.png"); 99 | 100 | wl_surface_attach (wayland_surface, buffer, 0, 0); 101 | submit_surface_damage (wayland_surface, 0, 0, 102 | INT_MAX, INT_MAX); 103 | wl_surface_commit (wayland_surface); 104 | wl_buffer_destroy (buffer); 105 | break; 106 | 107 | case BASIC_TEST_CARD_IMAGE_KIND: 108 | buffer = load_png_image (display, "basic_test_card.png"); 109 | 110 | if (!buffer) 111 | report_test_failure ("failed to load basic_test_card.png"); 112 | 113 | wl_surface_attach (wayland_surface, buffer, 0, 0); 114 | submit_frame_callback (wayland_surface, kind); 115 | submit_surface_damage (wayland_surface, 0, 0, 116 | INT_MAX, INT_MAX); 117 | wl_surface_commit (wayland_surface); 118 | wl_buffer_destroy (buffer); 119 | break; 120 | 121 | case BASIC_DAMAGE_KIND: 122 | buffer = load_png_image (display, "basic_damage.png"); 123 | 124 | if (!buffer) 125 | report_test_failure ("failed to load basic_damage.png"); 126 | 127 | wl_surface_attach (wayland_surface, buffer, 0, 0); 128 | submit_frame_callback (wayland_surface, kind); 129 | submit_surface_damage (wayland_surface, 49, 26, 57, 48); 130 | wl_surface_commit (wayland_surface); 131 | wl_buffer_destroy (buffer); 132 | break; 133 | } 134 | } 135 | 136 | static void 137 | test_next_step (enum test_kind kind) 138 | { 139 | switch (kind) 140 | { 141 | case BASIC_TEST_CARD_IMAGE_KIND: 142 | test_single_step (BASIC_DAMAGE_KIND); 143 | break; 144 | 145 | default: 146 | break; 147 | } 148 | } 149 | 150 | 151 | 152 | static void 153 | handle_test_surface_mapped (void *data, struct test_surface *surface, 154 | uint32_t xid, const char *display_string) 155 | { 156 | /* Sleep for 1 second to ensure that the window is exposed and 157 | redirected. */ 158 | sleep (1); 159 | 160 | /* Start the test. */ 161 | test_surface_window = xid; 162 | 163 | /* Run the test again. */ 164 | test_single_step (BASIC_TEST_CARD_IMAGE_KIND); 165 | } 166 | 167 | static void 168 | handle_test_surface_committed (void *data, struct test_surface *surface, 169 | uint32_t presentation_hint) 170 | { 171 | 172 | } 173 | 174 | static const struct test_surface_listener test_surface_listener = 175 | { 176 | handle_test_surface_mapped, 177 | NULL, 178 | handle_test_surface_committed, 179 | }; 180 | 181 | 182 | 183 | static void 184 | handle_wl_callback_done (void *data, struct wl_callback *callback, 185 | uint32_t callback_data) 186 | { 187 | enum test_kind kind; 188 | 189 | /* kind is not a pointer. It is an enum test_kind stuffed into a 190 | pointer. */ 191 | kind = (intptr_t) data; 192 | 193 | wl_callback_destroy (callback); 194 | verify_single_step (kind); 195 | 196 | /* Now run the next test in this sequence. */ 197 | test_next_step (kind); 198 | } 199 | 200 | static const struct wl_callback_listener wl_callback_listener = 201 | { 202 | handle_wl_callback_done, 203 | }; 204 | 205 | 206 | 207 | static void 208 | submit_frame_callback (struct wl_surface *surface, enum test_kind kind) 209 | { 210 | struct wl_callback *callback; 211 | 212 | callback = wl_surface_frame (surface); 213 | wl_callback_add_listener (callback, &wl_callback_listener, 214 | (void *) (intptr_t) kind); 215 | } 216 | 217 | static void 218 | submit_surface_damage (struct wl_surface *surface, int x, int y, int width, 219 | int height) 220 | { 221 | test_log ("damaging surface by %d, %d, %d, %d", x, y, width, 222 | height); 223 | 224 | wl_surface_damage (surface, x, y, width, height); 225 | } 226 | 227 | static void 228 | run_test (void) 229 | { 230 | if (!make_test_surface (display, &wayland_surface, 231 | &test_surface)) 232 | report_test_failure ("failed to create test surface"); 233 | 234 | test_surface_add_listener (test_surface, &test_surface_listener, 235 | NULL); 236 | test_single_step (MAP_WINDOW_KIND); 237 | 238 | while (true) 239 | { 240 | if (wl_display_dispatch (display->display) == -1) 241 | die ("wl_display_dispatch"); 242 | } 243 | } 244 | 245 | int 246 | main (void) 247 | { 248 | test_init (); 249 | display = open_test_display (test_interfaces, 250 | ARRAYELTS (test_interfaces)); 251 | 252 | if (!display) 253 | report_test_failure ("failed to open display"); 254 | 255 | run_test (); 256 | } 257 | -------------------------------------------------------------------------------- /keyboard-shortcuts-inhibit-unstable-v1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright © 2017 Red Hat Inc. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a 8 | copy of this software and associated documentation files (the "Software"), 9 | to deal in the Software without restriction, including without limitation 10 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | and/or sell copies of the Software, and to permit persons to whom the 12 | Software is furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice (including the next 15 | paragraph) shall be included in all copies or substantial portions of the 16 | Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 | DEALINGS IN THE SOFTWARE. 25 | 26 | 27 | 28 | This protocol specifies a way for a client to request the compositor 29 | to ignore its own keyboard shortcuts for a given seat, so that all 30 | key events from that seat get forwarded to a surface. 31 | 32 | Warning! The protocol described in this file is experimental and 33 | backward incompatible changes may be made. Backward compatible 34 | changes may be added together with the corresponding interface 35 | version bump. 36 | Backward incompatible changes are done by bumping the version 37 | number in the protocol and interface names and resetting the 38 | interface version. Once the protocol is to be declared stable, 39 | the 'z' prefix and the version number in the protocol and 40 | interface names are removed and the interface version number is 41 | reset. 42 | 43 | 44 | 45 | 46 | A global interface used for inhibiting the compositor keyboard shortcuts. 47 | 48 | 49 | 50 | 51 | Destroy the keyboard shortcuts inhibitor manager. 52 | 53 | 54 | 55 | 56 | 57 | Create a new keyboard shortcuts inhibitor object associated with 58 | the given surface for the given seat. 59 | 60 | If shortcuts are already inhibited for the specified seat and surface, 61 | a protocol error "already_inhibited" is raised by the compositor. 62 | 63 | 64 | 66 | 68 | 69 | 70 | 71 | 74 | 75 | 76 | 77 | 78 | 79 | A keyboard shortcuts inhibitor instructs the compositor to ignore 80 | its own keyboard shortcuts when the associated surface has keyboard 81 | focus. As a result, when the surface has keyboard focus on the given 82 | seat, it will receive all key events originating from the specified 83 | seat, even those which would normally be caught by the compositor for 84 | its own shortcuts. 85 | 86 | The Wayland compositor is however under no obligation to disable 87 | all of its shortcuts, and may keep some special key combo for its own 88 | use, including but not limited to one allowing the user to forcibly 89 | restore normal keyboard events routing in the case of an unwilling 90 | client. The compositor may also use the same key combo to reactivate 91 | an existing shortcut inhibitor that was previously deactivated on 92 | user request. 93 | 94 | When the compositor restores its own keyboard shortcuts, an 95 | "inactive" event is emitted to notify the client that the keyboard 96 | shortcuts inhibitor is not effectively active for the surface and 97 | seat any more, and the client should not expect to receive all 98 | keyboard events. 99 | 100 | When the keyboard shortcuts inhibitor is inactive, the client has 101 | no way to forcibly reactivate the keyboard shortcuts inhibitor. 102 | 103 | The user can chose to re-enable a previously deactivated keyboard 104 | shortcuts inhibitor using any mechanism the compositor may offer, 105 | in which case the compositor will send an "active" event to notify 106 | the client. 107 | 108 | If the surface is destroyed, unmapped, or loses the seat's keyboard 109 | focus, the keyboard shortcuts inhibitor becomes irrelevant and the 110 | compositor will restore its own keyboard shortcuts but no "inactive" 111 | event is emitted in this case. 112 | 113 | 114 | 115 | 116 | Remove the keyboard shortcuts inhibitor from the associated wl_surface. 117 | 118 | 119 | 120 | 121 | 122 | This event indicates that the shortcut inhibitor is active. 123 | 124 | The compositor sends this event every time compositor shortcuts 125 | are inhibited on behalf of the surface. When active, the client 126 | may receive input events normally reserved by the compositor 127 | (see zwp_keyboard_shortcuts_inhibitor_v1). 128 | 129 | This occurs typically when the initial request "inhibit_shortcuts" 130 | first becomes active or when the user instructs the compositor to 131 | re-enable and existing shortcuts inhibitor using any mechanism 132 | offered by the compositor. 133 | 134 | 135 | 136 | 137 | 138 | This event indicates that the shortcuts inhibitor is inactive, 139 | normal shortcuts processing is restored by the compositor. 140 | 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /tests/select_helper_multiple.c: -------------------------------------------------------------------------------- 1 | /* Tests for the Wayland compositor running on the X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | /* select_helper_multiple.c -- Perform a request for multiple 29 | selections. 30 | 31 | There must be at least three arguments: the name of the display, 32 | the timestamp at which the selection was acquired, and the 33 | target(s). */ 34 | 35 | /* The display connected to. */ 36 | static Display *display; 37 | 38 | /* The selection transfer window. */ 39 | static Window selection_transfer_window; 40 | 41 | /* Various atoms. */ 42 | static Atom CLIPBOARD, INCR, MULTIPLE, ATOM_PAIR, *target_atoms; 43 | 44 | static void 45 | wait_for_selection_notify (XEvent *event) 46 | { 47 | while (true) 48 | { 49 | XNextEvent (display, event); 50 | 51 | if (event->type == SelectionNotify 52 | && (event->xselection.requestor 53 | == selection_transfer_window) 54 | && (event->xselection.selection 55 | == CLIPBOARD) 56 | && (event->xselection.property 57 | == MULTIPLE) 58 | && (event->xselection.target 59 | == MULTIPLE)) 60 | return; 61 | } 62 | } 63 | 64 | static void 65 | wait_for_new_value (XEvent *event, Atom property) 66 | { 67 | while (true) 68 | { 69 | XNextEvent (display, event); 70 | 71 | if (event->type == PropertyNotify 72 | && event->xproperty.atom == property 73 | && event->xproperty.state == PropertyNewValue) 74 | return; 75 | } 76 | } 77 | 78 | static size_t 79 | get_size_for_format (int format) 80 | { 81 | switch (format) 82 | { 83 | case 32: 84 | return sizeof (long); 85 | 86 | case 16: 87 | return sizeof (short int); 88 | 89 | case 8: 90 | return sizeof (char); 91 | } 92 | 93 | /* Should not actually happen. */ 94 | return 0; 95 | } 96 | 97 | int 98 | main (int argc, char **argv) 99 | { 100 | XSetWindowAttributes attrs; 101 | unsigned long flags, timestamp; 102 | char *atom_names[4]; 103 | Atom atoms[4], actual_type, property, *parameters; 104 | XEvent event; 105 | int actual_format, i; 106 | unsigned long nitems, bytes_after; 107 | unsigned char *data; 108 | 109 | if (argc < 4) 110 | /* Not enough arguments were specified. */ 111 | return 1; 112 | 113 | display = XOpenDisplay (argv[1]); 114 | 115 | if (!display) 116 | return 1; 117 | 118 | /* Make the window used to transfer selection data. */ 119 | attrs.override_redirect = True; 120 | attrs.event_mask = PropertyChangeMask; 121 | flags = CWEventMask | CWOverrideRedirect; 122 | 123 | selection_transfer_window 124 | = XCreateWindow (display, DefaultRootWindow (display), 125 | -1, -1, 1, 1, 0, CopyFromParent, InputOnly, 126 | CopyFromParent, flags, &attrs); 127 | 128 | /* Get the time. */ 129 | timestamp = strtoul (argv[2], NULL, 10); 130 | 131 | atom_names[0] = (char *) "CLIPBOARD"; 132 | atom_names[1] = (char *) "INCR"; 133 | atom_names[2] = (char *) "MULTIPLE"; 134 | atom_names[3] = (char *) "ATOM_PAIR"; 135 | XInternAtoms (display, atom_names, 4, False, atoms); 136 | CLIPBOARD = atoms[0]; 137 | INCR = atoms[1]; 138 | MULTIPLE = atoms[2]; 139 | ATOM_PAIR = atoms[3]; 140 | 141 | /* Intern the target atoms. */ 142 | target_atoms = malloc (sizeof *target_atoms * argc - 3); 143 | XInternAtoms (display, &argv[3], argc - 3, False, target_atoms); 144 | 145 | /* Write each of the atoms as parameters before making the selection 146 | request. */ 147 | atoms[0] = target_atoms[0]; 148 | atoms[1] = target_atoms[0]; 149 | XChangeProperty (display, selection_transfer_window, MULTIPLE, 150 | ATOM_PAIR, 32, PropModeReplace, 151 | (unsigned char *) atoms, 2); 152 | 153 | for (i = 1; i < argc - 3; ++i) 154 | { 155 | atoms[0] = target_atoms[i]; 156 | atoms[1] = target_atoms[i]; 157 | XChangeProperty (display, selection_transfer_window, MULTIPLE, 158 | ATOM_PAIR, 32, PropModeAppend, 159 | (unsigned char *) atoms, 2); 160 | } 161 | 162 | /* Now, request the selection. */ 163 | XConvertSelection (display, CLIPBOARD, MULTIPLE, 164 | MULTIPLE, selection_transfer_window, 165 | timestamp); 166 | 167 | /* And wait for the SelectionNotify event. */ 168 | wait_for_selection_notify (&event); 169 | 170 | /* Selection conversion failed. */ 171 | if (event.xselection.property == None) 172 | return 1; 173 | 174 | /* Now, read the MULTIPLE property again. See which conversions 175 | were completed. */ 176 | XGetWindowProperty (display, selection_transfer_window, 177 | event.xselection.property, 0, (argc - 3) * 2, 178 | True, ATOM_PAIR, 179 | &actual_type, &actual_format, &nitems, 180 | &bytes_after, &data); 181 | 182 | if (actual_format != 32 || actual_type != ATOM_PAIR 183 | || nitems != (argc - 3) * 2) 184 | return 1; 185 | 186 | parameters = (Atom *) data; 187 | 188 | for (i = 0; i < argc - 3; ++i) 189 | { 190 | if (!parameters[i * 2 + 1]) 191 | continue; 192 | 193 | property = parameters[i * 2]; 194 | 195 | XGetWindowProperty (display, selection_transfer_window, 196 | property, 0, 0xffffffff, True, AnyPropertyType, 197 | &actual_type, &actual_format, &nitems, &bytes_after, 198 | &data); 199 | 200 | if (!data || bytes_after) 201 | return 1; 202 | 203 | if (actual_type == INCR) 204 | { 205 | while (true) 206 | { 207 | XFree (data); 208 | 209 | wait_for_new_value (&event, property); 210 | XGetWindowProperty (display, selection_transfer_window, property, 0, 211 | 0xffffffff, True, AnyPropertyType, &actual_type, 212 | &actual_format, &nitems, &bytes_after, &data); 213 | 214 | if (!data) 215 | return 0; 216 | 217 | if (nitems) 218 | { 219 | /* Write the selection data to stdout. */ 220 | if (fwrite (data, get_size_for_format (actual_format), 221 | nitems, stdout) != nitems) 222 | return 1; 223 | 224 | continue; 225 | } 226 | 227 | /* Selection transfer is complete. */ 228 | fflush (stdout); 229 | break; 230 | } 231 | } 232 | else 233 | { 234 | /* Write the selection data to stdout. */ 235 | if (fwrite (data, get_size_for_format (actual_format), 236 | nitems, stdout) != nitems) 237 | return 1; 238 | 239 | /* Return success. */ 240 | fflush (stdout); 241 | } 242 | } 243 | 244 | return 0; 245 | } 246 | -------------------------------------------------------------------------------- /Imakefile: -------------------------------------------------------------------------------- 1 | #include "12to11.conf" 2 | 3 | #ifndef HasPosixThreads 4 | #error "Posix threads are required" 5 | #endif 6 | 7 | SYS_LIBRARIES = MathLibrary ThreadsLibraries 8 | DEPLIBS = $(DEPXLIB) $(DEPEXTENSIONLIB) $(DEPXRANDRLIB) $(DEPXRENDERLIB) $(DEPXFIXESLIB) $(DEPXILIB) $(DEPXKBFILELIB) 9 | LOCAL_LIBRARIES = $(XLIB) $(EXTENSIONLIB) $(XCBLIB) $(XCB) $(XCB_SHM) $(XRANDRLIB) $(PIXMAN) $(XRENDERLIB) $(XILIB) $(XKBFILELIB) $(XFIXESLIB) $(XCB_DRI3) $(XCB_SHAPE) $(WAYLAND_SERVER) $(XCB_RANDR) $(DRM) $(XPRESENTLIB) $(XSHMFENCELIB) 10 | INCLUDES := $(DRMINCLUDES) $(PIXMANINCLUDES) 11 | 12 | #ifdef BuildTests 13 | # define IHaveSubdirs 14 | # define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)' 15 | SUBDIRS = tests 16 | 17 | MakeSubdirs($(SUBDIRS)) 18 | DependSubdirs($(SUBDIRS)) 19 | #endif 20 | 21 | SRCS = 12to11.c run.c alloc.c fns.c output.c compositor.c surface.c region.c shm.c atoms.c subcompositor.c positioner.c xdg_wm.c xdg_surface.c xdg_toplevel.c frame_clock.c xerror.c ewmh.c timer.c subsurface.c seat.c data_device.c xdg_popup.c dmabuf.c buffer.c select.c xdata.c xsettings.c dnd.c icon_surface.c primary_selection.c renderer.c picture_renderer.c explicit_synchronization.c transform.c wp_viewporter.c decoration.c text_input.c single_pixel_buffer.c drm_lease.c pointer_constraints.c time.c relative_pointer.c keyboard_shortcuts_inhibit.c idle_inhibit.c process.c fence_ring.c pointer_gestures.c test.c buffer_release.c xdg_activation.c tearing_control.c sync_source.c 22 | OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o surface.o region.o shm.o atoms.o subcompositor.o positioner.o xdg_wm.o xdg_surface.o xdg_toplevel.o frame_clock.o xerror.o ewmh.o timer.o subsurface.o seat.o data_device.o xdg_popup.o dmabuf.o buffer.o select.o xdata.o xsettings.o dnd.o icon_surface.o primary_selection.o renderer.o picture_renderer.o explicit_synchronization.o transform.o wp_viewporter.o decoration.o text_input.o single_pixel_buffer.o drm_lease.o pointer_constraints.o time.o relative_pointer.o keyboard_shortcuts_inhibit.o idle_inhibit.o process.o fence_ring.o pointer_gestures.o test.o buffer_release.o xdg_activation.o tearing_control.o sync_source.o 23 | GENHEADERS = transfer_atoms.h drm_modifiers.h 24 | HEADER = $(GENHEADERS) compositor.h 25 | 26 | #if defined LinuxArchitecture || defined GNUArchitecture 27 | EXTRA_DEFINES := -DPortFile=\"port_gnu.h\" -D_GNU_SOURCE -U_BSD_SOURCE -U_SVID_SOURCE 28 | DEPEND_DEFINES := -DPortFile=\"port_gnu.h\" 29 | #else 30 | # error "The protocol translator was not ported to your system" 31 | #endif 32 | 33 | #ifdef HaveEglSupport 34 | 35 | EGL_SRCS = egl.c 36 | EGL_OBJS = egl.o 37 | LOCAL_LIBRARIES ::= $(LOCAL_LIBRARIES) $(EGL) $(GLES) 38 | SRCS ::= $(SRCS) $(EGL_SRCS) 39 | OBJS ::= $(OBJS) $(EGL_OBJS) 40 | DEFINES ::= $(DEFINES) -DHaveEglSupport 41 | 42 | shaders.h: shaders.txt shaders.awk 43 | awk -f shaders.awk shaders.txt > $@ 44 | 45 | depend:: shaders.h 46 | 47 | $(EGL_OBJS): shaders.h 48 | 49 | cleandir:: 50 | $(RM) shaders.h 51 | 52 | #endif 53 | 54 | OPTIMIZE = -O0 55 | #if GccMajorVersion >= 10 56 | ANALYZE = -fanalyzer 57 | #endif 58 | #if GccMajorVersion >= 7 59 | CDEBUGFLAGS := -fno-common -Wall -Warith-conversion -Wdate-time -Wdisabled-optimization -Wdouble-promotion -Wduplicated-cond -Wextra -Wformat-signedness -Winit-self -Winvalid-pch -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wmissing-prototypes -Wnested-externs -Wnull-dereference -Wold-style-definition -Wopenmp-simd -Wpacked -Wpointer-arith -Wstrict-prototypes -Wsuggest-attribute=format -Wsuggest-attribute=noreturn -Wsuggest-final-methods -Wsuggest-final-types -Wuninitialized -Wunknown-pragmas -Wunused-macros -Wvariadic-macros -Wvector-operation-performance -Wwrite-strings -Warray-bounds=2 -Wattribute-alias=2 -Wformat=2 -Wformat-truncation=2 -Wimplicit-fallthrough=5 -Wshift-overflow=2 -Wuse-after-free=3 -Wvla-larger-than=4031 -Wredundant-decls -Wno-missing-field-initializers -Wno-override-init -Wno-sign-compare -Wno-type-limits -Wno-unused-parameter -Wno-format-nonliteral -g3 $(OPTIMIZE) $(ANALYZE) 60 | #endif 61 | 62 | short_types.txt: media_types.txt 63 | XCOMM Remove all data types starting with application/vnd. 64 | XCOMM no program really uses them in clipboard data, and they 65 | XCOMM waste a lot of space on disk. 66 | sed '/application\/vnd/d' media_types.txt > $@ 67 | 68 | transfer_atoms.h: short_types.txt mime0.awk mime1.awk mime2.awk mime3.awk \ 69 | mime4.awk 70 | awk -f mime0.awk short_types.txt > $@ 71 | awk -f mime1.awk short_types.txt >> $@ 72 | awk -f mime2.awk short_types.txt >> $@ 73 | awk -f mime3.awk short_types.txt >> $@ 74 | awk -f mime4.awk short_types.txt >> $@ 75 | 76 | drm_modifiers.h: modifiers.awk $(DRMFOURCCH) 77 | awk -f modifiers.awk $(DRMFOURCCH) > $@ 78 | 79 | /* Now, define generated files. */ 80 | 81 | #define ScannerTarget(name) @@\ 82 | name.h: name.xml @@\ 83 | $(WAYLAND_SCANNER) server-header $< $@ @@\ 84 | @@\ 85 | name.c: name.xml name.h @@\ 86 | $(WAYLAND_SCANNER) private-code $< $@ @@\ 87 | @@\ 88 | GENHEADERS := $(GENHEADERS) name.h @@\ 89 | OBJS := $(OBJS) name.o @@\ 90 | SRCS := $(SRCS) name.c @@\ 91 | GENSRCS := $(GENSRCS) name.c @@\ 92 | 93 | ScannerTarget(linux-dmabuf-unstable-v1) 94 | ScannerTarget(xdg-shell) 95 | ScannerTarget(primary-selection-unstable-v1) 96 | ScannerTarget(linux-explicit-synchronization-unstable-v1) 97 | ScannerTarget(viewporter) 98 | ScannerTarget(xdg-decoration-unstable-v1) 99 | ScannerTarget(text-input-unstable-v3) 100 | ScannerTarget(single-pixel-buffer-v1) 101 | ScannerTarget(drm-lease-v1) 102 | ScannerTarget(pointer-constraints-unstable-v1) 103 | ScannerTarget(relative-pointer-unstable-v1) 104 | ScannerTarget(keyboard-shortcuts-inhibit-unstable-v1) 105 | ScannerTarget(idle-inhibit-unstable-v1) 106 | ScannerTarget(pointer-gestures-unstable-v1) 107 | ScannerTarget(12to11-test) 108 | ScannerTarget(xdg-activation-v1) 109 | ScannerTarget(tearing-control-v1) 110 | 111 | /* Make seat.o depend on test_seat.c, as it includes that. Both files 112 | are rather special. */ 113 | seat.o: test_seat.c 114 | 115 | /* Make OBJS depend on scanner headers, and depend on both them and 116 | SRCS. */ 117 | $(OBJS): $(GENHEADERS) 118 | 119 | /* depend somehow does not depend on SRCS, even though some of OBJS 120 | are generated. */ 121 | depend:: $(GENHEADERS) $(SRCS) 122 | 123 | cleandir:: 124 | $(RM) $(GENHEADERS) $(GENSRCS) short_types.txt 12to11.tar.gz 125 | 126 | ComplexProgramTarget(12to11) 127 | 128 | .PHONY: dist 129 | dist: 12to11.tar.gz 130 | 131 | DIST_FILES = Imakefile $(SRCS) media_types.txt shaders.txt *.awk *.xml 12to11.man README libraries.def *.h 132 | 133 | /* Include files generated by wayland-scanner, so the target does not 134 | need to have it installed. */ 135 | 136 | 12to11.tar.gz: $(DIST_FILES) 137 | rm -rf 12to11.tar.gz 138 | tar -cvf 12to11.tar $(DIST_FILES) 139 | gzip 12to11.tar 140 | $(RM) 12to11.tar 141 | -------------------------------------------------------------------------------- /xdg-decoration-unstable-v1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Copyright © 2018 Simon Ser 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a 7 | copy of this software and associated documentation files (the "Software"), 8 | to deal in the Software without restriction, including without limitation 9 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | and/or sell copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice (including the next 14 | paragraph) shall be included in all copies or substantial portions of the 15 | Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | 25 | 26 | 27 | 28 | This interface allows a compositor to announce support for server-side 29 | decorations. 30 | 31 | A window decoration is a set of window controls as deemed appropriate by 32 | the party managing them, such as user interface components used to move, 33 | resize and change a window's state. 34 | 35 | A client can use this protocol to request being decorated by a supporting 36 | compositor. 37 | 38 | If compositor and client do not negotiate the use of a server-side 39 | decoration using this protocol, clients continue to self-decorate as they 40 | see fit. 41 | 42 | Warning! The protocol described in this file is experimental and 43 | backward incompatible changes may be made. Backward compatible changes 44 | may be added together with the corresponding interface version bump. 45 | Backward incompatible changes are done by bumping the version number in 46 | the protocol and interface names and resetting the interface version. 47 | Once the protocol is to be declared stable, the 'z' prefix and the 48 | version number in the protocol and interface names are removed and the 49 | interface version number is reset. 50 | 51 | 52 | 53 | 54 | Destroy the decoration manager. This doesn't destroy objects created 55 | with the manager. 56 | 57 | 58 | 59 | 60 | 61 | Create a new decoration object associated with the given toplevel. 62 | 63 | Creating an xdg_toplevel_decoration from an xdg_toplevel which has a 64 | buffer attached or committed is a client error, and any attempts by a 65 | client to attach or manipulate a buffer prior to the first 66 | xdg_toplevel_decoration.configure event must also be treated as 67 | errors. 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | The decoration object allows the compositor to toggle server-side window 77 | decorations for a toplevel surface. The client can request to switch to 78 | another mode. 79 | 80 | The xdg_toplevel_decoration object must be destroyed before its 81 | xdg_toplevel. 82 | 83 | 84 | 85 | 87 | 89 | 91 | 92 | 93 | 94 | 95 | Switch back to a mode without any server-side decorations at the next 96 | commit. 97 | 98 | 99 | 100 | 101 | 102 | These values describe window decoration modes. 103 | 104 | 106 | 108 | 109 | 110 | 111 | 112 | Set the toplevel surface decoration mode. This informs the compositor 113 | that the client prefers the provided decoration mode. 114 | 115 | After requesting a decoration mode, the compositor will respond by 116 | emitting an xdg_surface.configure event. The client should then update 117 | its content, drawing it without decorations if the received mode is 118 | server-side decorations. The client must also acknowledge the configure 119 | when committing the new content (see xdg_surface.ack_configure). 120 | 121 | The compositor can decide not to use the client's mode and enforce a 122 | different mode instead. 123 | 124 | Clients whose decoration mode depend on the xdg_toplevel state may send 125 | a set_mode request in response to an xdg_surface.configure event and wait 126 | for the next xdg_surface.configure event to prevent unwanted state. 127 | Such clients are responsible for preventing configure loops and must 128 | make sure not to send multiple successive set_mode requests with the 129 | same decoration mode. 130 | 131 | 132 | 133 | 134 | 135 | 136 | Unset the toplevel surface decoration mode. This informs the compositor 137 | that the client doesn't prefer a particular decoration mode. 138 | 139 | This request has the same semantics as set_mode. 140 | 141 | 142 | 143 | 144 | 145 | The configure event asks the client to change its decoration mode. The 146 | configured state should not be applied immediately. Clients must send an 147 | ack_configure in response to this event. See xdg_surface.configure and 148 | xdg_surface.ack_configure for details. 149 | 150 | A configure event can be sent at any time. The specified mode must be 151 | obeyed by the client. 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /port_gnu.h: -------------------------------------------------------------------------------- 1 | /* Wayland compositor running on top of an X server. 2 | 3 | Copyright (C) 2022 to various contributors. 4 | 5 | This file is part of 12to11. 6 | 7 | 12to11 is free software: you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation, either version 3 of the License, or (at your 10 | option) any later version. 11 | 12 | 12to11 is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with 12to11. If not, see . */ 19 | 20 | /* Copyright (C) 2001-2022 Free Software Foundation, Inc. 21 | 22 | This program is free software: you can redistribute it and/or modify 23 | it under the terms of the GNU Lesser General Public License as 24 | published by the Free Software Foundation; either version 2.1 of the 25 | License, or (at your option) any later version. 26 | 27 | This program is distributed in the hope that it will be useful, but 28 | WITHOUT ANY WARRANTY; without even the implied warranty of 29 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 30 | Lesser General Public License for more details. 31 | 32 | You should have received a copy of the GNU Lesser General Public 33 | License along with this program. 34 | 35 | If not, see . */ 36 | 37 | #ifndef IntAddWrapv 38 | 39 | #define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v)) 40 | #define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v)) 41 | #define _GL_TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) 42 | #define _GL_EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0) 43 | #define _GL_TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT) 44 | 45 | #define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t) \ 46 | ((t) ((ut) (a) op (ut) (b))) 47 | 48 | #define _GL_INT_NEGATE_RANGE_OVERFLOW(a, min, max) \ 49 | ((min) < 0 ? (a) < - (max) : 0 < (a)) 50 | 51 | #define _GL_INT_MINIMUM(e) \ 52 | (_GL_EXPR_SIGNED (e) \ 53 | ? ~ _GL_SIGNED_INT_MAXIMUM (e) \ 54 | : _GL_INT_CONVERT (e, 0)) 55 | 56 | #define _GL_INT_MAXIMUM(e) \ 57 | (_GL_EXPR_SIGNED (e) \ 58 | ? _GL_SIGNED_INT_MAXIMUM (e) \ 59 | : _GL_INT_NEGATE_CONVERT (e, 1)) 60 | 61 | #define _GL_SIGNED_INT_MAXIMUM(e) \ 62 | (((_GL_INT_CONVERT (e, 1) << (_GL_TYPE_WIDTH (+ (e)) - 2)) - 1) * 2 + 1) 63 | 64 | #define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \ 65 | (overflow (a, b, tmin, tmax) \ 66 | ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 1) \ 67 | : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 0)) 68 | 69 | # define _GL_INT_NEGATE_OVERFLOW(a) \ 70 | _GL_INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) 71 | 72 | #define _GL_INT_ADD_RANGE_OVERFLOW(a, b, tmin, tmax) \ 73 | ((b) < 0 \ 74 | ? (((tmin) \ 75 | ? ((_GL_EXPR_SIGNED (_GL_INT_CONVERT (a, (tmin) - (b))) || (b) < (tmin)) \ 76 | && (a) < (tmin) - (b)) \ 77 | : (a) <= -1 - (b)) \ 78 | || ((_GL_EXPR_SIGNED (a) ? 0 <= (a) : (tmax) < (a)) && (tmax) < (a) + (b))) \ 79 | : (a) < 0 \ 80 | ? (((tmin) \ 81 | ? ((_GL_EXPR_SIGNED (_GL_INT_CONVERT (b, (tmin) - (a))) || (a) < (tmin)) \ 82 | && (b) < (tmin) - (a)) \ 83 | : (b) <= -1 - (a)) \ 84 | || ((_GL_EXPR_SIGNED (_GL_INT_CONVERT (a, b)) || (tmax) < (b)) \ 85 | && (tmax) < (a) + (b))) \ 86 | : (tmax) < (b) || (tmax) - (b) < (a)) 87 | #define _GL_INT_SUBTRACT_RANGE_OVERFLOW(a, b, tmin, tmax) \ 88 | (((a) < 0) == ((b) < 0) \ 89 | ? ((a) < (b) \ 90 | ? !(tmin) || -1 - (tmin) < (b) - (a) - 1 \ 91 | : (tmax) < (a) - (b)) \ 92 | : (a) < 0 \ 93 | ? ((!_GL_EXPR_SIGNED (_GL_INT_CONVERT ((a) - (tmin), b)) && (a) - (tmin) < 0) \ 94 | || (a) - (tmin) < (b)) \ 95 | : ((! (_GL_EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \ 96 | && _GL_EXPR_SIGNED (_GL_INT_CONVERT ((tmax) + (b), a))) \ 97 | && (tmax) <= -1 - (b)) \ 98 | || (tmax) + (b) < (a))) 99 | #define _GL_INT_MULTIPLY_RANGE_OVERFLOW(a, b, tmin, tmax) \ 100 | ((b) < 0 \ 101 | ? ((a) < 0 \ 102 | ? (_GL_EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \ 103 | ? (a) < (tmax) / (b) \ 104 | : ((_GL_INT_NEGATE_OVERFLOW (b) \ 105 | ? _GL_INT_CONVERT (b, tmax) >> (_GL_TYPE_WIDTH (+ (b)) - 1) \ 106 | : (tmax) / -(b)) \ 107 | <= -1 - (a))) \ 108 | : _GL_INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (b, tmin)) && (b) == -1 \ 109 | ? (_GL_EXPR_SIGNED (a) \ 110 | ? 0 < (a) + (tmin) \ 111 | : 0 < (a) && -1 - (tmin) < (a) - 1) \ 112 | : (tmin) / (b) < (a)) \ 113 | : (b) == 0 \ 114 | ? 0 \ 115 | : ((a) < 0 \ 116 | ? (_GL_INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (a, tmin)) && (a) == -1 \ 117 | ? (_GL_EXPR_SIGNED (b) ? 0 < (b) + (tmin) : -1 - (tmin) < (b) - 1) \ 118 | : (tmin) / (a) < (b)) \ 119 | : (tmax) / (b) < (a))) 120 | 121 | #define _GL_INT_OP_WRAPV(a, b, r, op, overflow) \ 122 | (_Generic \ 123 | (*(r), \ 124 | signed char: \ 125 | _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ 126 | signed char, SCHAR_MIN, SCHAR_MAX), \ 127 | unsigned char: \ 128 | _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ 129 | unsigned char, 0, UCHAR_MAX), \ 130 | short int: \ 131 | _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ 132 | short int, SHRT_MIN, SHRT_MAX), \ 133 | unsigned short int: \ 134 | _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ 135 | unsigned short int, 0, USHRT_MAX), \ 136 | int: \ 137 | _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ 138 | int, INT_MIN, INT_MAX), \ 139 | unsigned int: \ 140 | _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ 141 | unsigned int, 0, UINT_MAX), \ 142 | long int: \ 143 | _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ 144 | long int, LONG_MIN, LONG_MAX), \ 145 | unsigned long int: \ 146 | _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ 147 | unsigned long int, 0, ULONG_MAX), \ 148 | long long int: \ 149 | _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \ 150 | long long int, LLONG_MIN, LLONG_MAX), \ 151 | unsigned long long int: \ 152 | _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \ 153 | unsigned long long int, 0, ULLONG_MAX))) 154 | 155 | #define _GL_INT_ADD_WRAPV(a, b, r) \ 156 | _GL_INT_OP_WRAPV (a, b, r, +, _GL_INT_ADD_RANGE_OVERFLOW) 157 | #define _GL_INT_SUBTRACT_WRAPV(a, b, r) \ 158 | _GL_INT_OP_WRAPV (a, b, r, -, _GL_INT_SUBTRACT_RANGE_OVERFLOW) 159 | #define _GL_INT_MULTIPLY_WRAPV(a, b, r) \ 160 | _GL_INT_OP_WRAPV (a, b, r, *, _GL_INT_MULTIPLY_RANGE_OVERFLOW) 161 | 162 | #define IntAddWrapv(a, b, r) _GL_INT_ADD_WRAPV (a, b, r) 163 | #define IntSubtractWrapv(a, b, r) _GL_INT_SUBTRACT_WRAPV (a, b, r) 164 | #define IntMultiplyWrapv(a, b, r) _GL_INT_MULTIPLY_WRAPV (a, b, r) 165 | 166 | #endif 167 | 168 | #ifndef Popcount 169 | #define NeedPortPopcount 170 | 171 | extern int PortPopcount (unsigned long long int); 172 | 173 | #define Popcount(number) (PortPopcount (number)) 174 | 175 | #endif 176 | --------------------------------------------------------------------------------